summaryrefslogtreecommitdiff
path: root/chromium/mojo
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-01-04 14:17:57 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-01-05 10:05:06 +0000
commit39d357e3248f80abea0159765ff39554affb40db (patch)
treeaba0e6bfb76de0244bba0f5fdbd64b830dd6e621 /chromium/mojo
parent87778abf5a1f89266f37d1321b92a21851d8244d (diff)
downloadqtwebengine-chromium-39d357e3248f80abea0159765ff39554affb40db.tar.gz
BASELINE: Update Chromium to 55.0.2883.105
And updates ninja to 1.7.2 Change-Id: I20d43c737f82764d857ada9a55586901b18b9243 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/mojo')
-rw-r--r--chromium/mojo/BUILD.gn4
-rw-r--r--chromium/mojo/OWNERS2
-rw-r--r--chromium/mojo/android/BUILD.gn14
-rw-r--r--chromium/mojo/android/javatests/init_library.cc8
-rw-r--r--chromium/mojo/android/javatests/mojo_test_case.cc5
-rw-r--r--chromium/mojo/android/javatests/validation_test_util.cc9
-rw-r--r--chromium/mojo/android/system/base_run_loop.cc29
-rw-r--r--chromium/mojo/android/system/core_impl.cc87
-rw-r--r--chromium/mojo/android/system/watcher_impl.cc78
-rw-r--r--chromium/mojo/android/system/watcher_impl.h20
-rw-r--r--chromium/mojo/common/BUILD.gn18
-rw-r--r--chromium/mojo/common/OWNERS4
-rw-r--r--chromium/mojo/common/common_custom_types.mojom23
-rw-r--r--chromium/mojo/common/common_custom_types.typemap20
-rw-r--r--chromium/mojo/common/common_custom_types_struct_traits.cc66
-rw-r--r--chromium/mojo/common/common_custom_types_struct_traits.h71
-rw-r--r--chromium/mojo/common/common_custom_types_unittest.cc108
-rw-r--r--chromium/mojo/common/common_type_converters.h1
-rw-r--r--chromium/mojo/common/struct_traits_unittest.cc57
-rw-r--r--chromium/mojo/common/test_common_custom_types.mojom11
-rw-r--r--chromium/mojo/common/traits_test_service.mojom14
-rw-r--r--chromium/mojo/converters/blink/BUILD.gn44
-rw-r--r--chromium/mojo/converters/blink/DEPS5
-rw-r--r--chromium/mojo/converters/blink/blink_input_events_type_converters.cc248
-rw-r--r--chromium/mojo/converters/blink/blink_input_events_type_converters.h31
-rw-r--r--chromium/mojo/converters/blink/blink_input_events_type_converters_unittest.cc140
-rw-r--r--chromium/mojo/converters/blink/mojo_blink_export.h32
-rw-r--r--chromium/mojo/edk/embedder/BUILD.gn8
-rw-r--r--chromium/mojo/edk/embedder/embedder.cc13
-rw-r--r--chromium/mojo/edk/embedder/embedder.h21
-rw-r--r--chromium/mojo/edk/embedder/named_platform_channel_pair.h8
-rw-r--r--chromium/mojo/edk/embedder/named_platform_channel_pair_win.cc76
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle.h51
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_utils.h31
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc147
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_utils_win.cc82
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc4
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_utils_posix.cc84
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_utils_posix.h9
-rw-r--r--chromium/mojo/edk/embedder/platform_handle.h3
-rw-r--r--chromium/mojo/edk/embedder/platform_handle_utils_posix.cc4
-rw-r--r--chromium/mojo/edk/embedder/platform_shared_buffer.cc21
-rw-r--r--chromium/mojo/edk/js/core.cc95
-rw-r--r--chromium/mojo/edk/system/BUILD.gn7
-rw-r--r--chromium/mojo/edk/system/async_waiter.cc23
-rw-r--r--chromium/mojo/edk/system/async_waiter.h38
-rw-r--r--chromium/mojo/edk/system/broker_host.cc (renamed from chromium/mojo/edk/system/broker_host_posix.cc)92
-rw-r--r--chromium/mojo/edk/system/broker_host.h22
-rw-r--r--chromium/mojo/edk/system/broker_messages.h23
-rw-r--r--chromium/mojo/edk/system/broker_posix.cc2
-rw-r--r--chromium/mojo/edk/system/broker_win.cc144
-rw-r--r--chromium/mojo/edk/system/channel.cc4
-rw-r--r--chromium/mojo/edk/system/channel_posix.cc38
-rw-r--r--chromium/mojo/edk/system/channel_win.cc5
-rw-r--r--chromium/mojo/edk/system/core.cc33
-rw-r--r--chromium/mojo/edk/system/core.h21
-rw-r--r--chromium/mojo/edk/system/core_unittest.cc24
-rw-r--r--chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc1
-rw-r--r--chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc6
-rw-r--r--chromium/mojo/edk/system/data_pipe_unittest.cc93
-rw-r--r--chromium/mojo/edk/system/mach_port_relay.cc2
-rw-r--r--chromium/mojo/edk/system/message_pipe_dispatcher.cc8
-rw-r--r--chromium/mojo/edk/system/message_pipe_unittest.cc11
-rw-r--r--chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc118
-rw-r--r--chromium/mojo/edk/system/node_channel.cc36
-rw-r--r--chromium/mojo/edk/system/node_channel.h11
-rw-r--r--chromium/mojo/edk/system/node_controller.cc233
-rw-r--r--chromium/mojo/edk/system/node_controller.h43
-rw-r--r--chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc4
-rw-r--r--chromium/mojo/edk/system/ports/message_queue.cc2
-rw-r--r--chromium/mojo/edk/system/ports/node.cc12
-rw-r--r--chromium/mojo/edk/system/waiter.h2
-rw-r--r--chromium/mojo/edk/system/watch_unittest.cc31
-rw-r--r--chromium/mojo/edk/test/BUILD.gn4
-rw-r--r--chromium/mojo/message_pump/BUILD.gn24
-rw-r--r--chromium/mojo/message_pump/handle_watcher.cc480
-rw-r--r--chromium/mojo/message_pump/handle_watcher.h65
-rw-r--r--chromium/mojo/message_pump/handle_watcher_perftest.cc207
-rw-r--r--chromium/mojo/message_pump/handle_watcher_unittest.cc493
-rw-r--r--chromium/mojo/message_pump/message_pump_mojo.cc448
-rw-r--r--chromium/mojo/message_pump/message_pump_mojo.h178
-rw-r--r--chromium/mojo/message_pump/message_pump_mojo_handler.h29
-rw-r--r--chromium/mojo/message_pump/message_pump_mojo_unittest.cc193
-rw-r--r--chromium/mojo/message_pump/mojo_message_pump_export.h32
-rw-r--r--chromium/mojo/message_pump/time_helper.cc33
-rw-r--r--chromium/mojo/message_pump/time_helper.h34
-rw-r--r--chromium/mojo/mojo.gyp18
-rw-r--r--chromium/mojo/mojo_base.gyp192
-rw-r--r--chromium/mojo/mojo_common_unittests.isolate23
-rw-r--r--chromium/mojo/mojo_edk.gyp233
-rw-r--r--chromium/mojo/mojo_edk.gypi123
-rw-r--r--chromium/mojo/mojo_edk_nacl.gyp85
-rw-r--r--chromium/mojo/mojo_edk_tests.gyp397
-rw-r--r--chromium/mojo/mojo_js_integration_tests.isolate49
-rw-r--r--chromium/mojo/mojo_js_unittests.isolate46
-rw-r--r--chromium/mojo/mojo_public.gyp308
-rw-r--r--chromium/mojo/mojo_public.gypi152
-rw-r--r--chromium/mojo/mojo_public_bindings_unittests.isolate24
-rw-r--r--chromium/mojo/mojo_public_nacl.gyp87
-rw-r--r--chromium/mojo/mojo_public_system_unittests.isolate23
-rw-r--r--chromium/mojo/mojo_public_tests.gyp162
-rw-r--r--chromium/mojo/mojo_system_unittests.isolate23
-rw-r--r--chromium/mojo/mojo_test_apk.isolate11
-rw-r--r--chromium/mojo/mojom_bindings_generator.gypi166
-rw-r--r--chromium/mojo/mojom_bindings_generator_explicit.gypi183
-rw-r--r--chromium/mojo/mojom_bindings_generator_variables.gypi29
-rw-r--r--chromium/mojo/public/c/system/BUILD.gn2
-rw-r--r--chromium/mojo/public/c/system/core.h1
-rw-r--r--chromium/mojo/public/c/system/main.h35
-rw-r--r--chromium/mojo/public/c/test_support/BUILD.gn1
-rw-r--r--chromium/mojo/public/cpp/bindings/BUILD.gn45
-rw-r--r--chromium/mojo/public/cpp/bindings/array.h30
-rw-r--r--chromium/mojo/public/cpp/bindings/array_data_view.h244
-rw-r--r--chromium/mojo/public/cpp/bindings/array_traits.h4
-rw-r--r--chromium/mojo/public/cpp/bindings/array_traits_carray.h23
-rw-r--r--chromium/mojo/public/cpp/bindings/array_traits_stl.h41
-rw-r--r--chromium/mojo/public/cpp/bindings/associated_binding.h48
-rw-r--r--chromium/mojo/public/cpp/bindings/associated_binding_set.h27
-rw-r--r--chromium/mojo/public/cpp/bindings/associated_group.h3
-rw-r--r--chromium/mojo/public/cpp/bindings/associated_group_controller.h14
-rw-r--r--chromium/mojo/public/cpp/bindings/associated_interface_ptr.h35
-rw-r--r--chromium/mojo/public/cpp/bindings/associated_interface_request.h28
-rw-r--r--chromium/mojo/public/cpp/bindings/binding.h31
-rw-r--r--chromium/mojo/public/cpp/bindings/binding_set.h239
-rw-r--r--chromium/mojo/public/cpp/bindings/bindings_export.h34
-rw-r--r--chromium/mojo/public/cpp/bindings/connection_error_callback.h21
-rw-r--r--chromium/mojo/public/cpp/bindings/connector.h30
-rw-r--r--chromium/mojo/public/cpp/bindings/filter_chain.h (renamed from chromium/mojo/public/cpp/bindings/lib/filter_chain.h)35
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_data_view.h25
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_endpoint_client.h47
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_ptr.h42
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_request.h17
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/array_internal.h105
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/array_serialization.h75
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/associated_group_controller.cc5
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h38
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/binding_state.cc166
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/binding_state.h258
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/bindings_internal.h136
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/buffer.h54
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/clone_equals_util.h161
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/connector.cc89
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc121
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/control_message_handler.h18
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc188
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h29
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/filter_chain.cc22
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc43
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h55
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/handle_interface_serialization.h27
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/hash_util.h73
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc86
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h105
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/map_data_internal.h53
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/map_serialization.h43
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/may_auto_lock.h54
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message.cc130
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_buffer.cc37
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_buffer.h15
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_builder.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_filter.cc23
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_header_validator.cc11
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_internal.h30
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc211
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/multiplex_router.h59
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/native_struct.cc6
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/native_struct_data.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.cc10
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc4
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc8
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/router.cc66
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/router.h39
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/serialization.h20
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/serialization_context.h5
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/serialization_forward.h73
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/serialization_util.cc53
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/serialization_util.h83
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/string_serialization.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc5
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc9
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h67
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/template_util.h48
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/validation_context.cc52
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/validation_context.h73
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/validation_errors.cc13
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/validation_errors.h28
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/validation_util.cc52
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/validation_util.h151
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h76
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h132
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h1
-rw-r--r--chromium/mojo/public/cpp/bindings/map.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/map_data_view.h63
-rw-r--r--chromium/mojo/public/cpp/bindings/map_traits.h12
-rw-r--r--chromium/mojo/public/cpp/bindings/map_traits_stl.h48
-rw-r--r--chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h64
-rw-r--r--chromium/mojo/public/cpp/bindings/message.h97
-rw-r--r--chromium/mojo/public/cpp/bindings/message_filter.h38
-rw-r--r--chromium/mojo/public/cpp/bindings/message_header_validator.h11
-rw-r--r--chromium/mojo/public/cpp/bindings/native_enum.h11
-rw-r--r--chromium/mojo/public/cpp/bindings/native_struct.h4
-rw-r--r--chromium/mojo/public/cpp/bindings/native_struct_data_view.h36
-rw-r--r--chromium/mojo/public/cpp/bindings/no_interface.h1
-rw-r--r--chromium/mojo/public/cpp/bindings/pipe_control_message_handler.h5
-rw-r--r--chromium/mojo/public/cpp/bindings/pipe_control_message_proxy.h3
-rw-r--r--chromium/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h3
-rw-r--r--chromium/mojo/public/cpp/bindings/string.h13
-rw-r--r--chromium/mojo/public/cpp/bindings/string_data_view.h34
-rw-r--r--chromium/mojo/public/cpp/bindings/string_traits.h19
-rw-r--r--chromium/mojo/public/cpp/bindings/string_traits_string16.h3
-rw-r--r--chromium/mojo/public/cpp/bindings/strong_binding.h141
-rw-r--r--chromium/mojo/public/cpp/bindings/struct_ptr.h156
-rw-r--r--chromium/mojo/public/cpp/bindings/struct_traits.h46
-rw-r--r--chromium/mojo/public/cpp/bindings/sync_call_restrictions.h7
-rw-r--r--chromium/mojo/public/cpp/bindings/sync_handle_registry.h4
-rw-r--r--chromium/mojo/public/cpp/bindings/sync_handle_watcher.h3
-rw-r--r--chromium/mojo/public/cpp/bindings/tests/BUILD.gn10
-rw-r--r--chromium/mojo/public/cpp/bindings/tests/rect_blink.typemap15
-rw-r--r--chromium/mojo/public/cpp/bindings/tests/rect_chromium.typemap15
-rw-r--r--chromium/mojo/public/cpp/bindings/tests/struct_with_traits.typemap6
-rw-r--r--chromium/mojo/public/cpp/bindings/union_traits.h39
-rw-r--r--chromium/mojo/public/cpp/bindings/wtf_array.h13
-rw-r--r--chromium/mojo/public/cpp/bindings/wtf_map.h20
-rw-r--r--chromium/mojo/public/cpp/system/BUILD.gn27
-rw-r--r--chromium/mojo/public/cpp/system/buffer.h4
-rw-r--r--chromium/mojo/public/cpp/system/platform_handle.h12
-rw-r--r--chromium/mojo/public/cpp/system/system_export.h34
-rw-r--r--chromium/mojo/public/cpp/system/watcher.h3
-rw-r--r--chromium/mojo/public/cpp/test_support/BUILD.gn3
-rw-r--r--chromium/mojo/public/interfaces/bindings/BUILD.gn4
-rw-r--r--chromium/mojo/public/interfaces/bindings/OWNERS2
-rw-r--r--chromium/mojo/public/interfaces/bindings/interface_control_messages.mojom71
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/BUILD.gn23
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/rect.mojom13
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom41
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom6
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/test_bad_messages.mojom13
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/test_data_view.mojom41
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/test_export.mojom18
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/test_native_types.mojom1
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/test_structs.mojom22
-rw-r--r--chromium/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom13
-rw-r--r--chromium/mojo/public/java/BUILD.gn2
-rw-r--r--chromium/mojo/public/js/codec.js15
-rw-r--r--chromium/mojo/public/js/codec_unittests.js18
-rw-r--r--chromium/mojo/public/js/connection.js20
-rw-r--r--chromium/mojo/public/js/core.js75
-rw-r--r--chromium/mojo/public/js/core_unittests.js48
-rw-r--r--chromium/mojo/public/js/union_unittests.js10
-rw-r--r--chromium/mojo/public/js/validation_unittests.js7
-rw-r--r--chromium/mojo/public/js/validator.js14
-rw-r--r--chromium/mojo/public/mojo_application.gni270
-rw-r--r--chromium/mojo/public/mojo_application_manifest.gni139
-rw-r--r--chromium/mojo/public/mojo_application_manifest.gypi56
-rw-r--r--chromium/mojo/public/mojo_constants.gni8
-rw-r--r--chromium/mojo/public/tools/bindings/BUILD.gn12
-rw-r--r--chromium/mojo/public/tools/bindings/bindings.gyp83
-rw-r--r--chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni5
-rw-r--r--chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni17
-rwxr-xr-xchromium/mojo/public/tools/bindings/generate_type_mappings.py11
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl81
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_serialization_declaration.tmpl3
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl13
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl119
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl16
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl6
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl4
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl4
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl3
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl126
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl95
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl64
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl212
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl65
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl112
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl111
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl64
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl20
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl46
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl25
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl34
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_declaration.tmpl32
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_definition.tmpl (renamed from chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl)4
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl92
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_definition.tmpl12
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl24
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl56
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl146
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl166
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_declaration.tmpl24
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_definition.tmpl47
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl15
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl27
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl13
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl21
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl34
-rw-r--r--chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl15
-rw-r--r--chromium/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl4
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl32
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl6
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl8
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl6
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py405
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py21
-rw-r--r--chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py29
-rw-r--r--chromium/mojo/public/tools/bindings/mojom.gni175
-rwxr-xr-xchromium/mojo/public/tools/bindings/mojom_bindings_generator.py121
-rwxr-xr-xchromium/mojo/public/tools/bindings/mojom_list_outputs.py44
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py8
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py76
-rwxr-xr-xchromium/mojo/public/tools/gn/zip.py13
-rwxr-xr-xchromium/mojo/public/tools/manifest/manifest_collator.py104
-rwxr-xr-xchromium/mojo/public/tools/prepend.py37
314 files changed, 8102 insertions, 9214 deletions
diff --git a/chromium/mojo/BUILD.gn b/chromium/mojo/BUILD.gn
index 2dac654cdf6..def24ea224d 100644
--- a/chromium/mojo/BUILD.gn
+++ b/chromium/mojo/BUILD.gn
@@ -13,9 +13,6 @@ group("mojo") {
]
if (!(is_linux && current_cpu == "x86")) {
- # TODO(GYP): Figure out if this needs to be supported. Right now
- # it won't work on x86 official builds because it needs stuff in the
- # sysroot that doesn't exist.
deps += [ "//mojo/public" ]
}
@@ -31,7 +28,6 @@ group("tests") {
deps = [
"//ipc:ipc_tests",
"//mojo/common:mojo_common_unittests",
- "//mojo/converters/blink:blink_converters_unittests",
"//mojo/edk/js/test:js_integration_tests",
"//mojo/edk/js/test:js_unittests",
"//mojo/edk/system:mojo_message_pipe_perftests",
diff --git a/chromium/mojo/OWNERS b/chromium/mojo/OWNERS
index 7252d2bba11..b03794cd178 100644
--- a/chromium/mojo/OWNERS
+++ b/chromium/mojo/OWNERS
@@ -1,5 +1,5 @@
-amistry@chromium.org
ben@chromium.org
+jam@chromium.org
rockot@chromium.org
sky@chromium.org
yzshen@chromium.org
diff --git a/chromium/mojo/android/BUILD.gn b/chromium/mojo/android/BUILD.gn
index 813701c85d0..f9bdb0a49ec 100644
--- a/chromium/mojo/android/BUILD.gn
+++ b/chromium/mojo/android/BUILD.gn
@@ -29,6 +29,7 @@ generate_jni("system_java_jni_headers") {
sources = [
"system/src/org/chromium/mojo/system/impl/BaseRunLoop.java",
"system/src/org/chromium/mojo/system/impl/CoreImpl.java",
+ "system/src/org/chromium/mojo/system/impl/WatcherImpl.java",
]
jni_package = "mojo"
@@ -40,12 +41,15 @@ source_set("libsystem_java") {
"system/base_run_loop.h",
"system/core_impl.cc",
"system/core_impl.h",
+ "system/watcher_impl.cc",
+ "system/watcher_impl.h",
]
deps = [
":system_java_jni_headers",
"//base",
- "//mojo/message_pump",
+ "//mojo/public/c/system",
+ "//mojo/public/cpp/system",
]
}
@@ -59,6 +63,7 @@ android_library("system_java") {
"system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java",
"system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java",
"system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java",
+ "system/src/org/chromium/mojo/system/impl/WatcherImpl.java",
]
deps = [
@@ -90,6 +95,7 @@ android_library("mojo_javatests") {
"javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java",
"javatests/src/org/chromium/mojo/bindings/ValidationTestUtilTest.java",
"javatests/src/org/chromium/mojo/system/impl/CoreImplTest.java",
+ "javatests/src/org/chromium/mojo/system/impl/WatcherImplTest.java",
]
deps = [
@@ -102,6 +108,10 @@ android_library("mojo_javatests") {
"//mojo/public/java:bindings",
"//mojo/public/java:system",
]
+
+ data = [
+ "//mojo/public/interfaces/bindings/tests/data/validation/",
+ ]
}
shared_library("mojo_java_unittests") {
@@ -123,7 +133,6 @@ shared_library("mojo_java_unittests") {
"//base/test/:test_support",
"//build/config/sanitizers:deps",
"//mojo/edk/system",
- "//mojo/message_pump",
"//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils",
"//mojo/public/cpp/test_support:test_utils",
]
@@ -141,5 +150,4 @@ instrumentation_test_apk("mojo_test_apk") {
shared_libraries = [ ":mojo_java_unittests" ]
apk_name = "MojoTest"
android_manifest = "javatests/AndroidManifest.xml"
- isolate_file = "../mojo_test_apk.isolate"
}
diff --git a/chromium/mojo/android/javatests/init_library.cc b/chromium/mojo/android/javatests/init_library.cc
index d2d9423b5e7..967524017c8 100644
--- a/chromium/mojo/android/javatests/init_library.cc
+++ b/chromium/mojo/android/javatests/init_library.cc
@@ -10,14 +10,16 @@
#include "mojo/android/javatests/mojo_test_case.h"
#include "mojo/android/javatests/validation_test_util.h"
#include "mojo/android/system/core_impl.h"
+#include "mojo/android/system/watcher_impl.h"
#include "mojo/edk/embedder/embedder.h"
namespace {
base::android::RegistrationMethod kMojoRegisteredMethods[] = {
- { "CoreImpl", mojo::android::RegisterCoreImpl },
- { "MojoTestCase", mojo::android::RegisterMojoTestCase },
- { "ValidationTestUtil", mojo::android::RegisterValidationTestUtil },
+ {"CoreImpl", mojo::android::RegisterCoreImpl},
+ {"MojoTestCase", mojo::android::RegisterMojoTestCase},
+ {"ValidationTestUtil", mojo::android::RegisterValidationTestUtil},
+ {"WatcherImpl", mojo::android::RegisterWatcherImpl},
};
bool RegisterJNI(JNIEnv* env) {
diff --git a/chromium/mojo/android/javatests/mojo_test_case.cc b/chromium/mojo/android/javatests/mojo_test_case.cc
index 6d88985df8b..fc59009bd40 100644
--- a/chromium/mojo/android/javatests/mojo_test_case.cc
+++ b/chromium/mojo/android/javatests/mojo_test_case.cc
@@ -16,12 +16,13 @@
#include "base/test/test_support_android.h"
#include "base/threading/thread_task_runner_handle.h"
#include "jni/MojoTestCase_jni.h"
-#include "mojo/message_pump/message_pump_mojo.h"
+
+using base::android::JavaParamRef;
namespace {
struct TestEnvironment {
- TestEnvironment() : message_loop(mojo::common::MessagePumpMojo::Create()) {}
+ TestEnvironment() {}
base::ShadowingAtExitManager at_exit;
base::MessageLoop message_loop;
diff --git a/chromium/mojo/android/javatests/validation_test_util.cc b/chromium/mojo/android/javatests/validation_test_util.cc
index fb4d140f7d5..75f79b370ed 100644
--- a/chromium/mojo/android/javatests/validation_test_util.cc
+++ b/chromium/mojo/android/javatests/validation_test_util.cc
@@ -14,6 +14,9 @@
#include "jni/ValidationTestUtil_jni.h"
#include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h"
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+
namespace mojo {
namespace android {
@@ -34,8 +37,7 @@ ScopedJavaLocalRef<jobject> ParseData(
input, &data, &num_handles, &error_message)) {
ScopedJavaLocalRef<jstring> j_error_message =
base::android::ConvertUTF8ToJavaString(env, error_message);
- return Java_ValidationTestUtil_buildData(env, NULL, 0,
- j_error_message.obj());
+ return Java_ValidationTestUtil_buildData(env, nullptr, 0, j_error_message);
}
void* data_ptr = &data[0];
if (!data_ptr) {
@@ -44,7 +46,8 @@ ScopedJavaLocalRef<jobject> ParseData(
}
jobject byte_buffer =
env->NewDirectByteBuffer(data_ptr, data.size());
- return Java_ValidationTestUtil_buildData(env, byte_buffer, num_handles, NULL);
+ return Java_ValidationTestUtil_buildData(env, byte_buffer, num_handles,
+ nullptr);
}
} // namespace android
diff --git a/chromium/mojo/android/system/base_run_loop.cc b/chromium/mojo/android/system/base_run_loop.cc
index e48d2f0e019..22511f370cf 100644
--- a/chromium/mojo/android/system/base_run_loop.cc
+++ b/chromium/mojo/android/system/base_run_loop.cc
@@ -10,30 +10,31 @@
#include "base/android/jni_android.h"
#include "base/android/jni_registrar.h"
#include "base/bind.h"
+#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "jni/BaseRunLoop_jni.h"
-#include "mojo/message_pump/message_pump_mojo.h"
+
+using base::android::JavaParamRef;
namespace mojo {
namespace android {
static jlong CreateBaseRunLoop(JNIEnv* env,
const JavaParamRef<jobject>& jcaller) {
- base::MessageLoop* message_loop =
- new base::MessageLoop(common::MessagePumpMojo::Create());
+ base::MessageLoop* message_loop = new base::MessageLoop;
return reinterpret_cast<uintptr_t>(message_loop);
}
static void Run(JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jlong runLoopID) {
- reinterpret_cast<base::MessageLoop*>(runLoopID)->Run();
+ const JavaParamRef<jobject>& jcaller) {
+ base::RunLoop().Run();
}
static void RunUntilIdle(JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jlong runLoopID) {
- reinterpret_cast<base::MessageLoop*>(runLoopID)->RunUntilIdle();
+ const JavaParamRef<jobject>& jcaller) {
+ base::RunLoop().RunUntilIdle();
}
static void Quit(JNIEnv* env,
@@ -45,7 +46,7 @@ static void Quit(JNIEnv* env,
static void RunJavaRunnable(
const base::android::ScopedJavaGlobalRef<jobject>& runnable_ref) {
Java_BaseRunLoop_runRunnable(base::android::AttachCurrentThread(),
- runnable_ref.obj());
+ runnable_ref);
}
static void PostDelayedTask(JNIEnv* env,
@@ -58,9 +59,10 @@ static void PostDelayedTask(JNIEnv* env,
// use it across threads. |RunJavaRunnable| will acquire a new JNIEnv before
// running the Runnable.
runnable_ref.Reset(env, runnable);
- reinterpret_cast<base::MessageLoop*>(runLoopID)->PostDelayedTask(
- FROM_HERE, base::Bind(&RunJavaRunnable, runnable_ref),
- base::TimeDelta::FromMicroseconds(delay));
+ reinterpret_cast<base::MessageLoop*>(runLoopID)
+ ->task_runner()
+ ->PostDelayedTask(FROM_HERE, base::Bind(&RunJavaRunnable, runnable_ref),
+ base::TimeDelta::FromMicroseconds(delay));
}
static void DeleteMessageLoop(JNIEnv* env,
@@ -78,4 +80,3 @@ bool RegisterBaseRunLoop(JNIEnv* env) {
} // namespace android
} // namespace mojo
-
diff --git a/chromium/mojo/android/system/core_impl.cc b/chromium/mojo/android/system/core_impl.cc
index 526c05032a8..5cbd754fe90 100644
--- a/chromium/mojo/android/system/core_impl.cc
+++ b/chromium/mojo/android/system/core_impl.cc
@@ -7,56 +7,20 @@
#include <stddef.h>
#include <stdint.h>
-#include <memory>
-
#include "base/android/base_jni_registrar.h"
#include "base/android/jni_android.h"
#include "base/android/jni_registrar.h"
#include "base/android/library_loader/library_loader_hooks.h"
#include "base/android/scoped_java_ref.h"
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "jni/CoreImpl_jni.h"
-#include "mojo/message_pump/handle_watcher.h"
#include "mojo/public/c/system/core.h"
-namespace {
-
-using MojoAsyncWaitID = uintptr_t;
-const MojoAsyncWaitID kInvalidHandleCancelID = 0;
-
-struct AsyncWaitCallbackData {
- base::android::ScopedJavaGlobalRef<jobject> core_impl;
- base::android::ScopedJavaGlobalRef<jobject> callback;
- base::android::ScopedJavaGlobalRef<jobject> cancellable;
-
- AsyncWaitCallbackData(JNIEnv* env, jobject core_impl, jobject callback) {
- this->core_impl.Reset(env, core_impl);
- this->callback.Reset(env, callback);
- }
-};
-
-void AsyncWaitCallback(mojo::common::HandleWatcher* watcher,
- void* data,
- MojoResult result) {
- delete watcher;
- std::unique_ptr<AsyncWaitCallbackData> callback_data(
- static_cast<AsyncWaitCallbackData*>(data));
- mojo::android::Java_CoreImpl_onAsyncWaitResult(
- base::android::AttachCurrentThread(),
- callback_data->core_impl.obj(),
- result,
- callback_data->callback.obj(),
- callback_data->cancellable.obj());
-}
-
-} // namespace
-
namespace mojo {
namespace android {
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+
static jlong GetTimeTicksNow(JNIEnv* env,
const JavaParamRef<jobject>& jcaller) {
return MojoGetTimeTicksNow();
@@ -365,51 +329,6 @@ static int Unmap(JNIEnv* env,
return MojoUnmapBuffer(buffer_start);
}
-static ScopedJavaLocalRef<jobject> AsyncWait(
- JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jint mojo_handle,
- jint signals,
- jlong deadline,
- const JavaParamRef<jobject>& callback) {
- AsyncWaitCallbackData* callback_data =
- new AsyncWaitCallbackData(env, jcaller, callback);
- MojoAsyncWaitID cancel_id;
- if (static_cast<MojoHandle>(mojo_handle) != MOJO_HANDLE_INVALID) {
- common::HandleWatcher* watcher = new common::HandleWatcher();
- cancel_id = reinterpret_cast<MojoAsyncWaitID>(watcher);
- watcher->Start(Handle(static_cast<MojoHandle>(mojo_handle)), signals,
- deadline,
- base::Bind(&AsyncWaitCallback, watcher, callback_data));
- } else {
- cancel_id = kInvalidHandleCancelID;
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AsyncWaitCallback, nullptr, callback_data,
- MOJO_RESULT_INVALID_ARGUMENT));
- }
- base::android::ScopedJavaLocalRef<jobject> cancellable =
- Java_CoreImpl_newAsyncWaiterCancellableImpl(
- env, jcaller, cancel_id, reinterpret_cast<intptr_t>(callback_data));
- callback_data->cancellable.Reset(env, cancellable.obj());
- return cancellable;
-}
-
-static void CancelAsyncWait(JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jlong id,
- jlong data_ptr) {
- if (id == 0) {
- // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
- // invalid handle, so the AsyncWaitCallback will be called and will clear
- // the data_ptr.
- return;
- }
- std::unique_ptr<AsyncWaitCallbackData> deleter(
- reinterpret_cast<AsyncWaitCallbackData*>(data_ptr));
- delete reinterpret_cast<common::HandleWatcher*>(
- static_cast<MojoAsyncWaitID>(id));
-}
-
static jint GetNativeBufferOffset(JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
const JavaParamRef<jobject>& buffer,
diff --git a/chromium/mojo/android/system/watcher_impl.cc b/chromium/mojo/android/system/watcher_impl.cc
new file mode 100644
index 00000000000..a363a595bed
--- /dev/null
+++ b/chromium/mojo/android/system/watcher_impl.cc
@@ -0,0 +1,78 @@
+// Copyright 2016 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/android/system/watcher_impl.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/android/base_jni_registrar.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_registrar.h"
+#include "base/android/library_loader/library_loader_hooks.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "jni/WatcherImpl_jni.h"
+#include "mojo/public/cpp/system/handle.h"
+#include "mojo/public/cpp/system/watcher.h"
+
+namespace mojo {
+namespace android {
+
+using base::android::JavaParamRef;
+
+namespace {
+
+class JavaWatcherCallback {
+ public:
+ JavaWatcherCallback(JNIEnv* env, const JavaParamRef<jobject>& java_watcher) {
+ java_watcher_.Reset(env, java_watcher);
+ }
+
+ void OnHandleReady(MojoResult result) {
+ Java_WatcherImpl_onHandleReady(base::android::AttachCurrentThread(),
+ java_watcher_, result);
+ }
+
+ private:
+ base::android::ScopedJavaGlobalRef<jobject> java_watcher_;
+};
+
+} // namespace
+
+static jlong CreateWatcher(JNIEnv* env, const JavaParamRef<jobject>& jcaller) {
+ return reinterpret_cast<jlong>(new Watcher);
+}
+
+static jint Start(JNIEnv* env,
+ const JavaParamRef<jobject>& jcaller,
+ jlong watcher_ptr,
+ jint mojo_handle,
+ jint signals) {
+ Watcher* watcher = reinterpret_cast<Watcher*>(watcher_ptr);
+ return watcher->Start(
+ mojo::Handle(static_cast<MojoHandle>(mojo_handle)),
+ static_cast<MojoHandleSignals>(signals),
+ base::Bind(&JavaWatcherCallback::OnHandleReady,
+ base::Owned(new JavaWatcherCallback(env, jcaller))));
+}
+
+static void Cancel(JNIEnv* env,
+ const JavaParamRef<jobject>& jcaller,
+ jlong watcher_ptr) {
+ reinterpret_cast<Watcher*>(watcher_ptr)->Cancel();
+}
+
+static void Delete(JNIEnv* env,
+ const JavaParamRef<jobject>& jcaller,
+ jlong watcher_ptr) {
+ delete reinterpret_cast<Watcher*>(watcher_ptr);
+}
+
+bool RegisterWatcherImpl(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace android
+} // namespace mojo
diff --git a/chromium/mojo/android/system/watcher_impl.h b/chromium/mojo/android/system/watcher_impl.h
new file mode 100644
index 00000000000..784f007e25f
--- /dev/null
+++ b/chromium/mojo/android/system/watcher_impl.h
@@ -0,0 +1,20 @@
+// Copyright 2016 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_ANDROID_SYSTEM_WATCHER_IMPL_H_
+#define MOJO_ANDROID_SYSTEM_WATCHER_IMPL_H_
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+
+namespace mojo {
+namespace android {
+
+JNI_EXPORT bool RegisterWatcherImpl(JNIEnv* env);
+
+} // namespace android
+} // namespace mojo
+
+#endif // MOJO_ANDROID_SYSTEM_WATCHER_IMPL_H_
diff --git a/chromium/mojo/common/BUILD.gn b/chromium/mojo/common/BUILD.gn
index 2edfb6d5c83..278d9ee2fb2 100644
--- a/chromium/mojo/common/BUILD.gn
+++ b/chromium/mojo/common/BUILD.gn
@@ -12,14 +12,12 @@ group("common") {
]
}
-# GYP version: mojo/mojo_base.gyp:mojo_common_custom_types
mojom("common_custom_types") {
sources = [
"common_custom_types.mojom",
]
}
-# GYP version: mojo/mojo_base.gyp:mojo_common_lib
component("common_base") {
output_name = "mojo_common_lib"
@@ -44,21 +42,21 @@ component("common_base") {
]
}
-# GYP version: mojo/mojo_base.gyp:mojo_test_common_custom_types
mojom("test_common_custom_types") {
sources = [
"test_common_custom_types.mojom",
+ "traits_test_service.mojom",
]
public_deps = [
":common_custom_types",
]
}
-# GYP version: mojo/mojo_base.gyp:mojo_common_unittests
test("mojo_common_unittests") {
deps = [
":common",
":common_custom_types",
+ ":struct_traits",
":test_common_custom_types",
"//base",
"//base:message_loop_tests",
@@ -74,6 +72,7 @@ test("mojo_common_unittests") {
sources = [
"common_custom_types_unittest.cc",
"common_type_converters_unittest.cc",
+ "struct_traits_unittest.cc",
]
}
@@ -86,3 +85,14 @@ test("mojo_common_perftests") {
"//testing/gtest",
]
}
+
+source_set("struct_traits") {
+ sources = [
+ "common_custom_types_struct_traits.cc",
+ "common_custom_types_struct_traits.h",
+ ]
+ deps = [
+ ":common_custom_types_shared_cpp_sources",
+ "//base:base",
+ ]
+}
diff --git a/chromium/mojo/common/OWNERS b/chromium/mojo/common/OWNERS
index a1660982293..b567079e0a9 100644
--- a/chromium/mojo/common/OWNERS
+++ b/chromium/mojo/common/OWNERS
@@ -1,2 +1,6 @@
per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=set noparent
+per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/mojo/common/common_custom_types.mojom b/chromium/mojo/common/common_custom_types.mojom
index aa871064c42..203fa3c844d 100644
--- a/chromium/mojo/common/common_custom_types.mojom
+++ b/chromium/mojo/common/common_custom_types.mojom
@@ -16,8 +16,27 @@ struct DictionaryValue;
[Native]
struct Time;
-[Native]
-struct TimeDelta;
+struct TimeDelta {
+ int64 microseconds;
+};
[Native]
struct TimeTicks;
+
+// Corresponds to |base::string16| in base/strings/string16.h
+// Corresponds to |WTF::String| in
+// third_party/WebKit/Source/wtf/text/WTFString.h.
+struct String16 {
+ array<uint16> data;
+};
+
+// Corresponds to |base::UnguessableToken| in base/unguessable_token.h
+struct UnguessableToken {
+ uint64 high;
+ uint64 low;
+};
+
+// Corresponds to |base::Version| in base/version.h
+struct Version {
+ array<uint32> components;
+};
diff --git a/chromium/mojo/common/common_custom_types.typemap b/chromium/mojo/common/common_custom_types.typemap
index 8d88109d8c1..ecd09e87be1 100644
--- a/chromium/mojo/common/common_custom_types.typemap
+++ b/chromium/mojo/common/common_custom_types.typemap
@@ -5,19 +5,29 @@
mojom = "//mojo/common/common_custom_types.mojom"
public_headers = [
"//base/files/file_path.h",
- "//base/values.h",
+ "//base/strings/string16.h",
"//base/time/time.h",
+ "//base/unguessable_token.h",
+ "//base/values.h",
+ "//base/version.h",
+]
+traits_headers = [
+ "//ipc/ipc_message_utils.h",
+ "//mojo/common/common_custom_types_struct_traits.h",
]
-traits_headers = [ "//ipc/ipc_message_utils.h" ]
public_deps = [
"//ipc",
+ "//mojo/common:struct_traits",
]
type_mappings = [
"mojo.common.mojom.FilePath=base::FilePath",
"mojo.common.mojom.DictionaryValue=base::DictionaryValue",
"mojo.common.mojom.ListValue=base::ListValue",
- "mojo.common.mojom.Time=base::Time",
- "mojo.common.mojom.TimeDelta=base::TimeDelta",
- "mojo.common.mojom.TimeTicks=base::TimeTicks",
+ "mojo.common.mojom.UnguessableToken=base::UnguessableToken",
+ "mojo.common.mojom.String16=base::string16",
+ "mojo.common.mojom.Time=base::Time[copyable_pass_by_value]",
+ "mojo.common.mojom.TimeDelta=base::TimeDelta[copyable_pass_by_value]",
+ "mojo.common.mojom.TimeTicks=base::TimeTicks[copyable_pass_by_value]",
+ "mojo.common.mojom.Version=base::Version",
]
diff --git a/chromium/mojo/common/common_custom_types_struct_traits.cc b/chromium/mojo/common/common_custom_types_struct_traits.cc
new file mode 100644
index 00000000000..c18f793b793
--- /dev/null
+++ b/chromium/mojo/common/common_custom_types_struct_traits.cc
@@ -0,0 +1,66 @@
+// Copyright 2016 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/common/common_custom_types_struct_traits.h"
+
+#include <iterator>
+
+namespace mojo {
+
+// static
+mojo::ConstCArray<uint16_t>
+StructTraits<mojo::common::mojom::String16DataView, base::string16>::data(
+ const base::string16& str) {
+ return mojo::ConstCArray<uint16_t>(
+ str.size(), reinterpret_cast<const uint16_t*>(str.data()));
+}
+
+// static
+bool StructTraits<mojo::common::mojom::String16DataView, base::string16>::Read(
+ mojo::common::mojom::String16DataView data,
+ base::string16* out) {
+ mojo::ArrayDataView<uint16_t> view;
+ data.GetDataDataView(&view);
+ if (view.is_null())
+ return false;
+ out->assign(reinterpret_cast<const base::char16*>(view.data()), view.size());
+ return true;
+}
+
+// static
+const std::vector<uint32_t>&
+StructTraits<mojo::common::mojom::VersionDataView, base::Version>::components(
+ const base::Version& version) {
+ return version.components();
+}
+
+// static
+bool StructTraits<mojo::common::mojom::VersionDataView, base::Version>::Read(
+ mojo::common::mojom::VersionDataView data,
+ base::Version* out) {
+ std::vector<uint32_t> components;
+ if (!data.ReadComponents(&components))
+ return false;
+
+ *out = base::Version(base::Version(std::move(components)));
+ return out->IsValid();
+}
+
+// static
+bool StructTraits<mojo::common::mojom::UnguessableTokenDataView,
+ base::UnguessableToken>::
+ Read(mojo::common::mojom::UnguessableTokenDataView data,
+ base::UnguessableToken* out) {
+ uint64_t high = data.high();
+ uint64_t low = data.low();
+
+ // Receiving a zeroed UnguessableToken is a security issue.
+ if (high == 0 && low == 0)
+ return false;
+
+ *out = base::UnguessableToken::Deserialize(high, low);
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/common/common_custom_types_struct_traits.h b/chromium/mojo/common/common_custom_types_struct_traits.h
new file mode 100644
index 00000000000..37be5409074
--- /dev/null
+++ b/chromium/mojo/common/common_custom_types_struct_traits.h
@@ -0,0 +1,71 @@
+// Copyright 2016 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_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_
+#define MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/unguessable_token.h"
+#include "base/version.h"
+#include "mojo/common/common_custom_types.mojom-shared.h"
+#include "mojo/common/mojo_common_export.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<mojo::common::mojom::String16DataView, base::string16> {
+ static mojo::ConstCArray<uint16_t> data(const base::string16& str);
+ static bool Read(mojo::common::mojom::String16DataView data,
+ base::string16* out);
+};
+
+template <>
+struct StructTraits<mojo::common::mojom::VersionDataView, base::Version> {
+ static bool IsNull(const base::Version& version) {
+ return !version.IsValid();
+ }
+ static void SetToNull(base::Version* out) {
+ *out = base::Version(std::string());
+ }
+ static const std::vector<uint32_t>& components(const base::Version& version);
+ static bool Read(mojo::common::mojom::VersionDataView data,
+ base::Version* out);
+};
+
+// If base::UnguessableToken is no longer 128 bits, the logic below and the
+// mojom::UnguessableToken type should be updated.
+static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t),
+ "base::UnguessableToken should be of size 2 * sizeof(uint64_t).");
+
+template <>
+struct StructTraits<mojo::common::mojom::UnguessableTokenDataView,
+ base::UnguessableToken> {
+ static uint64_t high(const base::UnguessableToken& token) {
+ return token.GetHighForSerialization();
+ }
+
+ static uint64_t low(const base::UnguessableToken& token) {
+ return token.GetLowForSerialization();
+ }
+
+ static bool Read(mojo::common::mojom::UnguessableTokenDataView data,
+ base::UnguessableToken* out);
+};
+
+template <>
+struct StructTraits<mojo::common::mojom::TimeDeltaDataView, base::TimeDelta> {
+ static int64_t microseconds(const base::TimeDelta& delta) {
+ return delta.InMicroseconds();
+ }
+
+ static bool Read(mojo::common::mojom::TimeDeltaDataView data,
+ base::TimeDelta* delta) {
+ *delta = base::TimeDelta::FromMicroseconds(data.microseconds());
+ return true;
+ }
+};
+
+} // namespace mojo
+
+#endif // MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_
diff --git a/chromium/mojo/common/common_custom_types_unittest.cc b/chromium/mojo/common/common_custom_types_unittest.cc
index fe6bb5da73a..520f82a9a00 100644
--- a/chromium/mojo/common/common_custom_types_unittest.cc
+++ b/chromium/mojo/common/common_custom_types_unittest.cc
@@ -5,6 +5,7 @@
#include "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "mojo/common/common_custom_types.mojom.h"
#include "mojo/common/test_common_custom_types.mojom.h"
@@ -40,16 +41,37 @@ struct BounceTestTraits<base::ListValue> {
};
template <typename T>
+struct PassTraits {
+ using Type = const T&;
+};
+
+template <>
+struct PassTraits<base::Time> {
+ using Type = base::Time;
+};
+
+template <>
+struct PassTraits<base::TimeDelta> {
+ using Type = base::TimeDelta;
+};
+
+template <>
+struct PassTraits<base::TimeTicks> {
+ using Type = base::TimeTicks;
+};
+
+template <typename T>
void DoExpectResponse(T* expected_value,
const base::Closure& closure,
- const T& value) {
+ typename PassTraits<T>::Type value) {
BounceTestTraits<T>::ExpectEquality(*expected_value, value);
closure.Run();
}
template <typename T>
-base::Callback<void(const T&)> ExpectResponse(T* expected_value,
- const base::Closure& closure) {
+base::Callback<void(typename PassTraits<T>::Type)> ExpectResponse(
+ T* expected_value,
+ const base::Closure& closure) {
return base::Bind(&DoExpectResponse<T>, expected_value, closure);
}
@@ -68,24 +90,38 @@ class TestFilePathImpl : public TestFilePath {
mojo::Binding<TestFilePath> binding_;
};
+class TestUnguessableTokenImpl : public TestUnguessableToken {
+ public:
+ explicit TestUnguessableTokenImpl(TestUnguessableTokenRequest request)
+ : binding_(this, std::move(request)) {}
+
+ // TestUnguessableToken implementation:
+ void BounceNonce(const base::UnguessableToken& in,
+ const BounceNonceCallback& callback) override {
+ callback.Run(in);
+ }
+
+ private:
+ mojo::Binding<TestUnguessableToken> binding_;
+};
+
class TestTimeImpl : public TestTime {
public:
explicit TestTimeImpl(TestTimeRequest request)
: binding_(this, std::move(request)) {}
// TestTime implementation:
- void BounceTime(const base::Time& in,
- const BounceTimeCallback& callback) override {
+ void BounceTime(base::Time in, const BounceTimeCallback& callback) override {
callback.Run(in);
}
- void BounceTimeDelta(const base::TimeDelta& in,
- const BounceTimeDeltaCallback& callback) override {
+ void BounceTimeDelta(base::TimeDelta in,
+ const BounceTimeDeltaCallback& callback) override {
callback.Run(in);
}
- void BounceTimeTicks(const base::TimeTicks& in,
- const BounceTimeTicksCallback& callback) override {
+ void BounceTimeTicks(base::TimeTicks in,
+ const BounceTimeTicksCallback& callback) override {
callback.Run(in);
}
@@ -113,6 +149,21 @@ class TestValueImpl : public TestValue {
mojo::Binding<TestValue> binding_;
};
+class TestString16Impl : public TestString16 {
+ public:
+ explicit TestString16Impl(TestString16Request request)
+ : binding_(this, std::move(request)) {}
+
+ // TestString16 implementation:
+ void BounceString16(const base::string16& in,
+ const BounceString16Callback& callback) override {
+ callback.Run(in);
+ }
+
+ private:
+ mojo::Binding<TestString16> binding_;
+};
+
class CommonCustomTypesTest : public testing::Test {
protected:
CommonCustomTypesTest() {}
@@ -140,6 +191,19 @@ TEST_F(CommonCustomTypesTest, FilePath) {
run_loop.Run();
}
+TEST_F(CommonCustomTypesTest, UnguessableToken) {
+ base::RunLoop run_loop;
+
+ TestUnguessableTokenPtr ptr;
+ TestUnguessableTokenImpl impl(GetProxy(&ptr));
+
+ base::UnguessableToken token = base::UnguessableToken::Create();
+
+ ptr->BounceNonce(token, ExpectResponse(&token, run_loop.QuitClosure()));
+
+ run_loop.Run();
+}
+
TEST_F(CommonCustomTypesTest, Time) {
base::RunLoop run_loop;
@@ -221,6 +285,32 @@ TEST_F(CommonCustomTypesTest, Value) {
}
}
+TEST_F(CommonCustomTypesTest, String16) {
+ base::RunLoop run_loop;
+
+ TestString16Ptr ptr;
+ TestString16Impl impl(GetProxy(&ptr));
+
+ base::string16 str16 = base::ASCIIToUTF16("hello world");
+
+ ptr->BounceString16(str16, ExpectResponse(&str16, run_loop.QuitClosure()));
+
+ run_loop.Run();
+}
+
+TEST_F(CommonCustomTypesTest, EmptyString16) {
+ base::RunLoop run_loop;
+
+ TestString16Ptr ptr;
+ TestString16Impl impl(GetProxy(&ptr));
+
+ base::string16 str16;
+
+ ptr->BounceString16(str16, ExpectResponse(&str16, run_loop.QuitClosure()));
+
+ run_loop.Run();
+}
+
} // namespace test
} // namespace common
} // namespace mojo
diff --git a/chromium/mojo/common/common_type_converters.h b/chromium/mojo/common/common_type_converters.h
index a065f050791..bf1e723b84d 100644
--- a/chromium/mojo/common/common_type_converters.h
+++ b/chromium/mojo/common/common_type_converters.h
@@ -6,6 +6,7 @@
#define MOJO_COMMON_COMMON_TYPE_CONVERTERS_H_
#include <stdint.h>
+#include <vector>
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/mojo/common/struct_traits_unittest.cc b/chromium/mojo/common/struct_traits_unittest.cc
new file mode 100644
index 00000000000..5ac4bc9c800
--- /dev/null
+++ b/chromium/mojo/common/struct_traits_unittest.cc
@@ -0,0 +1,57 @@
+// Copyright 2016 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/message_loop/message_loop.h"
+#include "mojo/common/traits_test_service.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace common {
+namespace {
+
+class StructTraitsTest : public testing::Test, public mojom::TraitsTestService {
+ public:
+ StructTraitsTest() {}
+
+ protected:
+ mojom::TraitsTestServicePtr GetTraitsTestProxy() {
+ return traits_test_bindings_.CreateInterfacePtrAndBind(this);
+ }
+
+ private:
+ // TraitsTestService:
+ void EchoVersion(const base::Optional<base::Version>& m,
+ const EchoVersionCallback& callback) override {
+ callback.Run(m);
+ }
+
+ base::MessageLoop loop_;
+ mojo::BindingSet<TraitsTestService> traits_test_bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(StructTraitsTest);
+};
+
+TEST_F(StructTraitsTest, Version) {
+ const std::string& version_str = "1.2.3.4";
+ base::Version input(version_str);
+ mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
+ base::Optional<base::Version> output;
+ proxy->EchoVersion(input, &output);
+ EXPECT_TRUE(output.has_value());
+ EXPECT_EQ(version_str, output->GetString());
+}
+
+TEST_F(StructTraitsTest, InvalidVersion) {
+ const std::string invalid_version_str;
+ base::Version input(invalid_version_str);
+ mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
+ base::Optional<base::Version> output;
+ proxy->EchoVersion(input, &output);
+ EXPECT_FALSE(output.has_value());
+}
+
+} // namespace
+} // namespace common
+} // namespace mojo
diff --git a/chromium/mojo/common/test_common_custom_types.mojom b/chromium/mojo/common/test_common_custom_types.mojom
index db91a4f53f4..ab49cce1339 100644
--- a/chromium/mojo/common/test_common_custom_types.mojom
+++ b/chromium/mojo/common/test_common_custom_types.mojom
@@ -11,6 +11,11 @@ interface TestFilePath {
=> (mojo.common.mojom.FilePath out);
};
+interface TestUnguessableToken {
+ BounceNonce(mojo.common.mojom.UnguessableToken in)
+ => (mojo.common.mojom.UnguessableToken out);
+};
+
interface TestTime {
BounceTime(mojo.common.mojom.Time time) => (mojo.common.mojom.Time time);
BounceTimeDelta(mojo.common.mojom.TimeDelta time_delta)
@@ -25,3 +30,9 @@ interface TestValue {
BounceListValue(mojo.common.mojom.ListValue in)
=> (mojo.common.mojom.ListValue out);
};
+
+interface TestString16 {
+ [Sync]
+ BounceString16(mojo.common.mojom.String16 in)
+ => (mojo.common.mojom.String16 out);
+};
diff --git a/chromium/mojo/common/traits_test_service.mojom b/chromium/mojo/common/traits_test_service.mojom
new file mode 100644
index 00000000000..bf508cd661a
--- /dev/null
+++ b/chromium/mojo/common/traits_test_service.mojom
@@ -0,0 +1,14 @@
+// Copyright 2016 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.common.mojom;
+
+import "mojo/common/common_custom_types.mojom";
+
+// All functions on this interface echo their arguments to test StructTraits
+// serialization and deserialization.
+interface TraitsTestService {
+ [Sync]
+ EchoVersion(Version? v) => (Version? pass);
+};
diff --git a/chromium/mojo/converters/blink/BUILD.gn b/chromium/mojo/converters/blink/BUILD.gn
deleted file mode 100644
index 0bb92950940..00000000000
--- a/chromium/mojo/converters/blink/BUILD.gn
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2015 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("//testing/test.gni")
-
-component("blink") {
- output_name = "mojo_blink_lib"
-
- sources = [
- "blink_input_events_type_converters.cc",
- "blink_input_events_type_converters.h",
- "mojo_blink_export.h",
- ]
-
- defines = [ "MOJO_CONVERTERS_BLINK_IMPLEMENTATION" ]
-
- public_deps = [
- "//mojo/public/cpp/bindings",
- ]
-
- deps = [
- "//base",
- "//third_party/WebKit/public:blink",
- "//ui/events",
- "//ui/events:dom_keycode_converter",
- ]
-}
-
-test("blink_converters_unittests") {
- sources = [
- "blink_input_events_type_converters_unittest.cc",
- ]
- deps = [
- ":blink",
- "//base:message_loop_tests",
- "//base/test:run_all_unittests",
- "//base/test:test_support",
- "//mojo/public/cpp/bindings:bindings",
- "//testing/gtest",
- "//third_party/WebKit/public:blink",
- "//ui/events",
- ]
-}
diff --git a/chromium/mojo/converters/blink/DEPS b/chromium/mojo/converters/blink/DEPS
deleted file mode 100644
index 6678b7cae28..00000000000
--- a/chromium/mojo/converters/blink/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-include_rules = [
- "+base",
- "+third_party/WebKit/public",
- "+ui/events"
-]
diff --git a/chromium/mojo/converters/blink/blink_input_events_type_converters.cc b/chromium/mojo/converters/blink/blink_input_events_type_converters.cc
deleted file mode 100644
index b8764d09ca7..00000000000
--- a/chromium/mojo/converters/blink/blink_input_events_type_converters.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-// 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/converters/blink/blink_input_events_type_converters.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "base/time/time.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/events/base_event_utils.h"
-#include "ui/events/event.h"
-#include "ui/events/keycodes/dom/keycode_converter.h"
-
-namespace mojo {
-namespace {
-
-// TODO(majidvp): remove this and directly use ui::EventFlagsToWebEventModifiers
-int EventFlagsToWebEventModifiers(int flags) {
- int modifiers = 0;
-
- if (flags & ui::EF_SHIFT_DOWN)
- modifiers |= blink::WebInputEvent::ShiftKey;
- if (flags & ui::EF_CONTROL_DOWN)
- modifiers |= blink::WebInputEvent::ControlKey;
- if (flags & ui::EF_ALT_DOWN)
- modifiers |= blink::WebInputEvent::AltKey;
- // TODO(beng): MetaKey/META_MASK
- if (flags & ui::EF_LEFT_MOUSE_BUTTON)
- modifiers |= blink::WebInputEvent::LeftButtonDown;
- if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
- modifiers |= blink::WebInputEvent::MiddleButtonDown;
- if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
- modifiers |= blink::WebInputEvent::RightButtonDown;
- if (flags & ui::EF_CAPS_LOCK_ON)
- modifiers |= blink::WebInputEvent::CapsLockOn;
- return modifiers;
-}
-
-// TODO(majidvp): remove this and directly use ui::EventFlagsToWebEventModifiers
-int EventFlagsToWebInputEventModifiers(int flags) {
- return (flags & ui::EF_SHIFT_DOWN ? blink::WebInputEvent::ShiftKey : 0) |
- (flags & ui::EF_CONTROL_DOWN ? blink::WebInputEvent::ControlKey : 0) |
- (flags & ui::EF_CAPS_LOCK_ON ? blink::WebInputEvent::CapsLockOn : 0) |
- (flags & ui::EF_ALT_DOWN ? blink::WebInputEvent::AltKey : 0);
-}
-
-int GetClickCount(int flags) {
- if (flags & ui::EF_IS_TRIPLE_CLICK)
- return 3;
- else if (flags & ui::EF_IS_DOUBLE_CLICK)
- return 2;
-
- return 1;
-}
-
-void SetWebMouseEventLocation(const ui::LocatedEvent& located_event,
- blink::WebMouseEvent* web_event) {
- web_event->x = static_cast<int>(located_event.x());
- web_event->y = static_cast<int>(located_event.y());
- web_event->globalX = static_cast<int>(located_event.root_location_f().x());
- web_event->globalY = static_cast<int>(located_event.root_location_f().y());
-}
-
-std::unique_ptr<blink::WebInputEvent> BuildWebMouseEventFrom(
- const ui::PointerEvent& event) {
- std::unique_ptr<blink::WebMouseEvent> web_event(new blink::WebMouseEvent);
-
- web_event->pointerType = blink::WebPointerProperties::PointerType::Mouse;
- SetWebMouseEventLocation(event, web_event.get());
-
- web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
- web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
-
- web_event->button = blink::WebMouseEvent::ButtonNone;
- if (event.flags() & ui::EF_LEFT_MOUSE_BUTTON)
- web_event->button = blink::WebMouseEvent::ButtonLeft;
- if (event.flags() & ui::EF_MIDDLE_MOUSE_BUTTON)
- web_event->button = blink::WebMouseEvent::ButtonMiddle;
- if (event.flags() & ui::EF_RIGHT_MOUSE_BUTTON)
- web_event->button = blink::WebMouseEvent::ButtonRight;
-
- switch (event.type()) {
- case ui::ET_POINTER_DOWN:
- web_event->type = blink::WebInputEvent::MouseDown;
- break;
- case ui::ET_POINTER_UP:
- web_event->type = blink::WebInputEvent::MouseUp;
- break;
- case ui::ET_POINTER_MOVED:
- web_event->type = blink::WebInputEvent::MouseMove;
- break;
- case ui::ET_MOUSE_EXITED:
- web_event->type = blink::WebInputEvent::MouseLeave;
- break;
- default:
- NOTIMPLEMENTED() << "Received unexpected event: " << event.type();
- break;
- }
-
- web_event->clickCount = GetClickCount(event.flags());
-
- return std::move(web_event);
-}
-
-std::unique_ptr<blink::WebInputEvent> BuildWebKeyboardEvent(
- const ui::KeyEvent& event) {
- std::unique_ptr<blink::WebKeyboardEvent> web_event(
- new blink::WebKeyboardEvent);
-
- web_event->modifiers = EventFlagsToWebInputEventModifiers(event.flags());
- web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
-
- switch (event.type()) {
- case ui::ET_KEY_PRESSED:
- web_event->type = event.is_char() ? blink::WebInputEvent::Char
- : blink::WebInputEvent::RawKeyDown;
- break;
- case ui::ET_KEY_RELEASED:
- web_event->type = blink::WebInputEvent::KeyUp;
- break;
- default:
- NOTREACHED();
- }
-
- if (web_event->modifiers & blink::WebInputEvent::AltKey)
- web_event->isSystemKey = true;
-
- web_event->windowsKeyCode = event.GetLocatedWindowsKeyboardCode();
- web_event->nativeKeyCode =
- ui::KeycodeConverter::DomCodeToNativeKeycode(event.code());
- web_event->text[0] = event.GetText();
- web_event->unmodifiedText[0] = event.GetUnmodifiedText();
-
- web_event->setKeyIdentifierFromWindowsKeyCode();
- return std::move(web_event);
-}
-
-std::unique_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom(
- const ui::MouseWheelEvent& event) {
- std::unique_ptr<blink::WebMouseWheelEvent> web_event(
- new blink::WebMouseWheelEvent);
- web_event->type = blink::WebInputEvent::MouseWheel;
- web_event->button = blink::WebMouseEvent::ButtonNone;
- web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
- web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
-
- SetWebMouseEventLocation(event, web_event.get());
-
- // TODO(rjkroege): Update the following code once Blink supports
- // DOM Level 3 wheel events
- // (http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents)
- web_event->deltaX = event.x_offset();
- web_event->deltaY = event.y_offset();
-
- web_event->wheelTicksX = web_event->deltaX / ui::MouseWheelEvent::kWheelDelta;
- web_event->wheelTicksY = web_event->deltaY / ui::MouseWheelEvent::kWheelDelta;
-
- // TODO(moshayedi): ui::WheelEvent currently only supports WHEEL_MODE_LINE.
- // Add support for other wheel modes once ui::WheelEvent has support for them.
- web_event->hasPreciseScrollingDeltas = false;
- web_event->scrollByPage = false;
-
- return std::move(web_event);
-}
-
-void SetWebTouchEventLocation(const ui::PointerEvent& event,
- blink::WebTouchPoint* touch) {
- touch->position.x = event.x();
- touch->position.y = event.y();
- touch->screenPosition.x = event.root_location_f().x();
- touch->screenPosition.y = event.root_location_f().y();
-}
-
-std::unique_ptr<blink::WebInputEvent> BuildWebTouchEvent(
- const ui::PointerEvent& event) {
- std::unique_ptr<blink::WebTouchEvent> web_event(new blink::WebTouchEvent);
- blink::WebTouchPoint* touch = &web_event->touches[event.pointer_id()];
-
- // TODO(jonross): we will need to buffer input events, as blink expects all
- // active touch points to be in each WebInputEvent (crbug.com/578160)
- SetWebTouchEventLocation(event, touch);
- touch->pointerType = blink::WebPointerProperties::PointerType::Touch;
- touch->radiusX = event.pointer_details().radius_x;
- touch->radiusY = event.pointer_details().radius_y;
-
- web_event->modifiers = EventFlagsToWebEventModifiers(event.flags());
- web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp());
- web_event->uniqueTouchEventId = ui::GetNextTouchEventId();
-
- switch (event.type()) {
- case ui::ET_POINTER_DOWN:
- web_event->type = blink::WebInputEvent::TouchStart;
- touch->state = blink::WebTouchPoint::StatePressed;
- break;
- case ui::ET_POINTER_UP:
- web_event->type = blink::WebInputEvent::TouchEnd;
- touch->state = blink::WebTouchPoint::StateReleased;
- break;
- case ui::ET_POINTER_MOVED:
- web_event->type = blink::WebInputEvent::TouchMove;
- touch->state = blink::WebTouchPoint::StateMoved;
- break;
- case ui::ET_POINTER_CANCELLED:
- web_event->type = blink::WebInputEvent::TouchCancel;
- touch->state = blink::WebTouchPoint::StateCancelled;
- break;
- default:
- NOTIMPLEMENTED() << "Received non touch pointer event action: "
- << event.type();
- break;
- }
-
- return std::move(web_event);
-}
-
-} // namespace
-
-// static
-std::unique_ptr<blink::WebInputEvent>
-TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event>::Convert(
- const ui::Event& event) {
- DCHECK(event.IsKeyEvent() || event.IsPointerEvent() ||
- event.IsMouseWheelEvent());
- switch (event.type()) {
- case ui::ET_POINTER_DOWN:
- case ui::ET_POINTER_UP:
- case ui::ET_POINTER_CANCELLED:
- case ui::ET_POINTER_MOVED:
- case ui::ET_POINTER_EXITED:
- if (event.IsMousePointerEvent())
- return BuildWebMouseEventFrom(*event.AsPointerEvent());
- else if (event.IsTouchPointerEvent())
- return BuildWebTouchEvent(*event.AsPointerEvent());
- else
- return nullptr;
- case ui::ET_MOUSEWHEEL:
- return BuildWebMouseWheelEventFrom(*event.AsMouseWheelEvent());
- case ui::ET_KEY_PRESSED:
- case ui::ET_KEY_RELEASED:
- return BuildWebKeyboardEvent(*event.AsKeyEvent());
- default:
- return nullptr;
- }
-}
-
-} // namespace mojo
diff --git a/chromium/mojo/converters/blink/blink_input_events_type_converters.h b/chromium/mojo/converters/blink/blink_input_events_type_converters.h
deleted file mode 100644
index 3231eab0ed4..00000000000
--- a/chromium/mojo/converters/blink/blink_input_events_type_converters.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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_CONVERTERS_BLINK_BLINK_INPUT_EVENTS_TYPE_CONVERTERS_H_
-#define MOJO_CONVERTERS_BLINK_BLINK_INPUT_EVENTS_TYPE_CONVERTERS_H_
-
-#include <memory>
-
-#include "mojo/converters/blink/mojo_blink_export.h"
-#include "mojo/public/cpp/bindings/type_converter.h"
-
-namespace blink {
-class WebInputEvent;
-}
-
-namespace ui {
-class Event;
-}
-
-namespace mojo {
-
-template <>
-struct MOJO_BLINK_EXPORT
- TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event> {
- static std::unique_ptr<blink::WebInputEvent> Convert(const ui::Event& input);
-};
-
-} // namespace mojo
-
-#endif // MOJO_CONVERTERS_BLINK_BLINK_INPUT_EVENTS_TYPE_CONVERTERS_H_
diff --git a/chromium/mojo/converters/blink/blink_input_events_type_converters_unittest.cc b/chromium/mojo/converters/blink/blink_input_events_type_converters_unittest.cc
deleted file mode 100644
index 40d9c021309..00000000000
--- a/chromium/mojo/converters/blink/blink_input_events_type_converters_unittest.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2016 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/converters/blink/blink_input_events_type_converters.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/events/event.h"
-
-namespace mojo {
-
-TEST(BlinkInputEventsConvertersTest, KeyEvent) {
- struct {
- ui::KeyEvent event;
- blink::WebInputEvent::Type web_type;
- int web_modifiers;
- } tests[] = {
- {ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE),
- blink::WebInputEvent::RawKeyDown, 0x0},
- {ui::KeyEvent(L'B', ui::VKEY_B, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN),
- blink::WebInputEvent::Char,
- blink::WebInputEvent::ShiftKey | blink::WebInputEvent::ControlKey},
- {ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_C, ui::EF_ALT_DOWN),
- blink::WebInputEvent::KeyUp, blink::WebInputEvent::AltKey}};
-
- for (size_t i = 0; i < arraysize(tests); i++) {
- const std::unique_ptr<blink::WebInputEvent> web_event(
- TypeConverter<std::unique_ptr<blink::WebInputEvent>,
- ui::Event>::Convert(tests[i].event));
- ASSERT_TRUE(web_event);
- ASSERT_TRUE(blink::WebInputEvent::isKeyboardEventType(web_event->type));
- ASSERT_EQ(tests[i].web_type, web_event->type);
- ASSERT_EQ(tests[i].web_modifiers, web_event->modifiers);
-
- const blink::WebKeyboardEvent* web_key_event =
- static_cast<const blink::WebKeyboardEvent*>(web_event.get());
- ASSERT_EQ(static_cast<int>(tests[i].event.GetLocatedWindowsKeyboardCode()),
- web_key_event->windowsKeyCode);
- }
-}
-
-TEST(BlinkInputEventsConvertersTest, WheelEvent) {
- const int kDeltaX = 14;
- const int kDeltaY = -3;
- ui::MouseWheelEvent ui_event(
- ui::MouseEvent(ui::ET_MOUSEWHEEL, gfx::Point(), gfx::Point(),
- base::TimeTicks(), 0, 0),
- kDeltaX, kDeltaY);
- const std::unique_ptr<blink::WebInputEvent> web_event(
- TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event>::Convert(
- ui_event));
- ASSERT_TRUE(web_event);
- ASSERT_EQ(blink::WebInputEvent::MouseWheel, web_event->type);
- ASSERT_EQ(0, web_event->modifiers);
-
- const blink::WebMouseWheelEvent* web_wheel_event =
- static_cast<const blink::WebMouseWheelEvent*>(web_event.get());
- ASSERT_EQ(kDeltaX, web_wheel_event->deltaX);
- ASSERT_EQ(kDeltaY, web_wheel_event->deltaY);
-}
-
-TEST(BlinkInputEventsConvertersTest, MousePointerEvent) {
- struct {
- ui::EventType ui_type;
- blink::WebInputEvent::Type web_type;
- int ui_modifiers;
- int web_modifiers;
- gfx::Point location;
- gfx::Point screen_location;
- } tests[] = {
- {ui::ET_MOUSE_PRESSED, blink::WebInputEvent::MouseDown, 0x0, 0x0,
- gfx::Point(3, 5), gfx::Point(113, 125)},
- {ui::ET_MOUSE_RELEASED, blink::WebInputEvent::MouseUp,
- ui::EF_LEFT_MOUSE_BUTTON, blink::WebInputEvent::LeftButtonDown,
- gfx::Point(100, 1), gfx::Point(50, 1)},
- {ui::ET_MOUSE_MOVED, blink::WebInputEvent::MouseMove,
- ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
- blink::WebInputEvent::MiddleButtonDown |
- blink::WebInputEvent::RightButtonDown,
- gfx::Point(13, 3), gfx::Point(53, 3)},
- };
-
- for (size_t i = 0; i < arraysize(tests); i++) {
- ui::PointerEvent ui_event(ui::MouseEvent(
- tests[i].ui_type, tests[i].location, tests[i].screen_location,
- base::TimeTicks(), tests[i].ui_modifiers, 0));
- const std::unique_ptr<blink::WebInputEvent> web_event(
- TypeConverter<std::unique_ptr<blink::WebInputEvent>,
- ui::Event>::Convert(ui_event));
- ASSERT_TRUE(web_event);
- ASSERT_TRUE(blink::WebInputEvent::isMouseEventType(web_event->type));
- ASSERT_EQ(tests[i].web_type, web_event->type);
- ASSERT_EQ(tests[i].web_modifiers, web_event->modifiers);
-
- const blink::WebMouseEvent* web_mouse_event =
- static_cast<const blink::WebMouseEvent*>(web_event.get());
- ASSERT_EQ(tests[i].location.x(), web_mouse_event->x);
- ASSERT_EQ(tests[i].location.y(), web_mouse_event->y);
- ASSERT_EQ(tests[i].screen_location.x(), web_mouse_event->globalX);
- ASSERT_EQ(tests[i].screen_location.y(), web_mouse_event->globalY);
- }
-}
-
-TEST(BlinkInputEventsConvertersTest, TouchPointerEvent) {
- struct {
- ui::EventType ui_type;
- blink::WebInputEvent::Type web_type;
- gfx::Point location;
- int touch_id;
- float radius_x;
- float radius_y;
- } tests[] = {
- {ui::ET_TOUCH_PRESSED, blink::WebInputEvent::TouchStart, gfx::Point(3, 5),
- 1, 4.5, 5.5},
- {ui::ET_TOUCH_RELEASED, blink::WebInputEvent::TouchEnd,
- gfx::Point(100, 1), 2, 3.0, 3.0},
- };
-
- for (size_t i = 0; i < arraysize(tests); i++) {
- ui::PointerEvent ui_event(ui::TouchEvent(
- tests[i].ui_type, tests[i].location, 0, tests[i].touch_id,
- base::TimeTicks(), tests[i].radius_x, tests[i].radius_y, 0.0, 0.0));
- const std::unique_ptr<blink::WebInputEvent> web_event(
- TypeConverter<std::unique_ptr<blink::WebInputEvent>,
- ui::Event>::Convert(ui_event));
- ASSERT_TRUE(web_event);
- ASSERT_TRUE(blink::WebInputEvent::isTouchEventType(web_event->type));
- ASSERT_EQ(tests[i].web_type, web_event->type);
- ASSERT_EQ(0, web_event->modifiers);
-
- const blink::WebTouchEvent* web_touch_event =
- static_cast<const blink::WebTouchEvent*>(web_event.get());
- const blink::WebTouchPoint* web_touch_point =
- &web_touch_event->touches[tests[i].touch_id];
- ASSERT_EQ(tests[i].radius_x, web_touch_point->radiusX);
- ASSERT_EQ(tests[i].radius_y, web_touch_point->radiusY);
- }
-}
-} // namespace mojo
diff --git a/chromium/mojo/converters/blink/mojo_blink_export.h b/chromium/mojo/converters/blink/mojo_blink_export.h
deleted file mode 100644
index 1a771842048..00000000000
--- a/chromium/mojo/converters/blink/mojo_blink_export.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 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_CONVERTERS_BLINK_MOJO_BLINK_EXPORT_H_
-#define MOJO_CONVERTERS_BLINK_MOJO_BLINK_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-
-#if defined(WIN32)
-
-#if defined(MOJO_CONVERTERS_BLINK_IMPLEMENTATION)
-#define MOJO_BLINK_EXPORT __declspec(dllexport)
-#else
-#define MOJO_BLINK_EXPORT __declspec(dllimport)
-#endif
-
-#else // !defined(WIN32)
-
-#if defined(MOJO_CONVERTERS_BLINK_IMPLEMENTATION)
-#define MOJO_BLINK_EXPORT __attribute__((visibility("default")))
-#else
-#define MOJO_BLINK_EXPORT
-#endif
-
-#endif // defined(WIN32)
-
-#else // !defined(COMPONENT_BUILD)
-#define MOJO_BLINK_EXPORT
-#endif
-
-#endif // MOJO_CONVERTERS_BLINK_MOJO_BLINK_EXPORT_H_
diff --git a/chromium/mojo/edk/embedder/BUILD.gn b/chromium/mojo/edk/embedder/BUILD.gn
index f20fd40230d..67a7376eb45 100644
--- a/chromium/mojo/edk/embedder/BUILD.gn
+++ b/chromium/mojo/edk/embedder/BUILD.gn
@@ -10,6 +10,8 @@ source_set("headers") {
"embedder.h",
"embedder_internal.h",
"named_platform_channel_pair.h",
+ "named_platform_handle.h",
+ "named_platform_handle_utils.h",
"platform_channel_pair.h",
"platform_handle.h",
"platform_handle_utils.h",
@@ -77,6 +79,9 @@ source_set("platform") {
sources = [
"named_platform_channel_pair.h",
"named_platform_channel_pair_win.cc",
+ "named_platform_handle.h",
+ "named_platform_handle_utils.h",
+ "named_platform_handle_utils_win.cc",
"platform_channel_pair.cc",
"platform_channel_pair.h",
"platform_channel_pair_posix.cc",
@@ -93,6 +98,9 @@ source_set("platform") {
"platform_shared_buffer.h",
"scoped_platform_handle.h",
]
+ if (!is_nacl) {
+ sources += [ "named_platform_handle_utils_posix.cc" ]
+ }
defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
diff --git a/chromium/mojo/edk/embedder/embedder.cc b/chromium/mojo/edk/embedder/embedder.cc
index bc4c03ef7a5..3508ba3fc47 100644
--- a/chromium/mojo/edk/embedder/embedder.cc
+++ b/chromium/mojo/edk/embedder/embedder.cc
@@ -76,6 +76,12 @@ void SetParentPipeHandleFromCommandLine() {
SetParentPipeHandle(std::move(platform_channel));
}
+ScopedMessagePipeHandle ConnectToPeerProcess(ScopedPlatformHandle pipe) {
+ CHECK(internal::g_process_delegate);
+ DCHECK(pipe.is_valid());
+ return internal::g_core->ConnectToPeerProcess(std::move(pipe));
+}
+
void Init() {
MojoSystemThunks thunks = MakeSystemThunks();
size_t expected_size = MojoEmbedderSetSystemThunks(&thunks);
@@ -84,11 +90,8 @@ void Init() {
internal::g_core = new Core();
}
-MojoResult AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- const base::Callback<void(MojoResult)>& callback) {
- CHECK(internal::g_core);
- return internal::g_core->AsyncWait(handle, signals, callback);
+void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback) {
+ internal::g_core->SetDefaultProcessErrorCallback(callback);
}
MojoResult CreatePlatformHandleWrapper(
diff --git a/chromium/mojo/edk/embedder/embedder.h b/chromium/mojo/edk/embedder/embedder.h
index 21637eb68d0..8cb44a119cb 100644
--- a/chromium/mojo/edk/embedder/embedder.h
+++ b/chromium/mojo/edk/embedder/embedder.h
@@ -70,23 +70,26 @@ MOJO_SYSTEM_IMPL_EXPORT void SetParentPipeHandle(ScopedPlatformHandle pipe);
// PlatformChannelPair for details.
MOJO_SYSTEM_IMPL_EXPORT void SetParentPipeHandleFromCommandLine();
+// Called to connect to a peer process. This should be called only if there
+// is no common ancestor for the processes involved within this mojo system.
+// Both processes must call this function, each passing one end of a platform
+// channel. This returns one end of a message pipe to each process.
+MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle
+ConnectToPeerProcess(ScopedPlatformHandle pipe);
+
// Must be called first, or just after setting configuration parameters, to
// initialize the (global, singleton) system.
MOJO_SYSTEM_IMPL_EXPORT void Init();
+// Sets a default callback to invoke when an internal error is reported but
+// cannot be associated with a specific child process.
+MOJO_SYSTEM_IMPL_EXPORT void SetDefaultProcessErrorCallback(
+ const ProcessErrorCallback& callback);
+
// Basic functions -------------------------------------------------------------
// The functions in this section are available once |Init()| has been called.
-// Start waiting on the handle asynchronously. On success, |callback| will be
-// called exactly once, when |handle| satisfies a signal in |signals| or it
-// becomes known that it will never do so. |callback| will be executed on an
-// arbitrary thread, so it must not call any Mojo system or embedder functions.
-MOJO_SYSTEM_IMPL_EXPORT MojoResult
-AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- const base::Callback<void(MojoResult)>& callback);
-
// Creates a |MojoHandle| that wraps the given |PlatformHandle| (taking
// ownership of it). This |MojoHandle| can then, e.g., be passed through message
// pipes. Note: This takes ownership (and thus closes) |platform_handle| even on
diff --git a/chromium/mojo/edk/embedder/named_platform_channel_pair.h b/chromium/mojo/edk/embedder/named_platform_channel_pair.h
index 0dcbde52616..a238a4564d4 100644
--- a/chromium/mojo/edk/embedder/named_platform_channel_pair.h
+++ b/chromium/mojo/edk/embedder/named_platform_channel_pair.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
+#include "mojo/edk/embedder/named_platform_handle.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/system_impl_export.h"
@@ -48,13 +49,12 @@ class MOJO_SYSTEM_IMPL_EXPORT NamedPlatformChannelPair {
void PrepareToPassClientHandleToChildProcess(
base::CommandLine* command_line) const;
+ const NamedPlatformHandle& handle() const { return pipe_handle_; }
+
private:
+ NamedPlatformHandle pipe_handle_;
ScopedPlatformHandle server_handle_;
-#if defined(OS_WIN)
- base::string16 pipe_name_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(NamedPlatformChannelPair);
};
diff --git a/chromium/mojo/edk/embedder/named_platform_channel_pair_win.cc b/chromium/mojo/edk/embedder/named_platform_channel_pair_win.cc
index f7f16ae1ac2..39c16b9b1dc 100644
--- a/chromium/mojo/edk/embedder/named_platform_channel_pair_win.cc
+++ b/chromium/mojo/edk/embedder/named_platform_channel_pair_win.cc
@@ -4,7 +4,6 @@
#include "mojo/edk/embedder/named_platform_channel_pair.h"
-#include <sddl.h>
#include <windows.h>
#include <memory>
@@ -16,7 +15,9 @@
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
+#include "mojo/edk/embedder/named_platform_handle_utils.h"
#include "mojo/edk/embedder/platform_handle.h"
namespace mojo {
@@ -28,45 +29,15 @@ const char kMojoNamedPlatformChannelPipeSwitch[] =
"mojo-named-platform-channel-pipe";
std::wstring GeneratePipeName() {
- return base::StringPrintf(L"\\\\.\\pipe\\mojo.%u.%u.%I64u",
- GetCurrentProcessId(), GetCurrentThreadId(),
- base::RandUint64());
-
+ return base::StringPrintf(L"%u.%u.%I64u", GetCurrentProcessId(),
+ GetCurrentThreadId(), base::RandUint64());
}
} // namespace
-NamedPlatformChannelPair::NamedPlatformChannelPair() {
- pipe_name_ = GeneratePipeName();
-
- PSECURITY_DESCRIPTOR security_desc = nullptr;
- ULONG security_desc_len = 0;
- // Create a DACL to grant:
- // GA = Generic All
- // access to:
- // SY = LOCAL_SYSTEM
- // BA = BUILTIN_ADMINISTRATORS
- // OW = OWNER_RIGHTS
- PCHECK(ConvertStringSecurityDescriptorToSecurityDescriptor(
- L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;OW)",
- SDDL_REVISION_1, &security_desc, &security_desc_len));
- std::unique_ptr<void, decltype(::LocalFree)*> p(security_desc, ::LocalFree);
- SECURITY_ATTRIBUTES security_attributes = {
- sizeof(SECURITY_ATTRIBUTES), security_desc, FALSE };
-
- const DWORD kOpenMode =
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE;
- const DWORD kPipeMode =
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS;
- PlatformHandle handle(
- CreateNamedPipeW(pipe_name_.c_str(), kOpenMode, kPipeMode,
- 1, // Max instances.
- 4096, // Out buffer size.
- 4096, // In buffer size.
- 5000, // Timeout in milliseconds.
- &security_attributes));
- handle.needs_connection = true;
- server_handle_.reset(handle);
+NamedPlatformChannelPair::NamedPlatformChannelPair()
+ : pipe_handle_(GeneratePipeName()) {
+ server_handle_ = CreateServerHandle(pipe_handle_, true);
PCHECK(server_handle_.is_valid());
}
@@ -80,32 +51,15 @@ ScopedPlatformHandle NamedPlatformChannelPair::PassServerHandle() {
ScopedPlatformHandle
NamedPlatformChannelPair::PassClientHandleFromParentProcess(
const base::CommandLine& command_line) {
- std::wstring client_handle_string =
- command_line.GetSwitchValueNative(kMojoNamedPlatformChannelPipeSwitch);
-
- if (client_handle_string.empty())
- return ScopedPlatformHandle();
+ // In order to support passing the pipe name on the command line, the pipe
+ // handle is lazily created from the pipe name when requested.
+ NamedPlatformHandle handle(
+ command_line.GetSwitchValueNative(kMojoNamedPlatformChannelPipeSwitch));
- // Note: This may block.
- BOOL ok = WaitNamedPipeW(client_handle_string.c_str(),
- NMPWAIT_USE_DEFAULT_WAIT);
- if (!ok)
+ if (!handle.is_valid())
return ScopedPlatformHandle();
- // In order to support passing the pipe name on the command line, the pipe
- // handle is lazily created from the pipe name when requested.
- const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE;
- // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate
- // the client.
- const DWORD kFlags =
- SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED;
- ScopedPlatformHandle handle(
- PlatformHandle(CreateFileW(client_handle_string.c_str(), kDesiredAccess,
- 0, // No sharing.
- nullptr, OPEN_EXISTING, kFlags,
- nullptr))); // No template file.
- PCHECK(handle.is_valid());
- return handle;
+ return CreateClientHandle(handle);
}
void NamedPlatformChannelPair::PrepareToPassClientHandleToChildProcess(
@@ -123,8 +77,8 @@ void NamedPlatformChannelPair::PrepareToPassClientHandleToChildProcess(
kMojoNamedPlatformChannelPipeSwitch);
// (Any existing switch won't actually be removed from the command line, but
// the last one appended takes precedence.)
- command_line->AppendSwitchNative(
- kMojoNamedPlatformChannelPipeSwitch, pipe_name_);
+ command_line->AppendSwitchNative(kMojoNamedPlatformChannelPipeSwitch,
+ pipe_handle_.name);
}
} // namespace edk
diff --git a/chromium/mojo/edk/embedder/named_platform_handle.h b/chromium/mojo/edk/embedder/named_platform_handle.h
new file mode 100644
index 00000000000..15ca6565d51
--- /dev/null
+++ b/chromium/mojo/edk/embedder/named_platform_handle.h
@@ -0,0 +1,51 @@
+// Copyright 2016 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_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_
+#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_
+
+#include <string>
+
+#include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "mojo/edk/system/system_impl_export.h"
+
+namespace mojo {
+namespace edk {
+
+#if defined(OS_POSIX)
+struct MOJO_SYSTEM_IMPL_EXPORT NamedPlatformHandle {
+ NamedPlatformHandle() {}
+ explicit NamedPlatformHandle(const base::StringPiece& name)
+ : name(name.as_string()) {}
+
+ bool is_valid() const { return !name.empty(); }
+
+ std::string name;
+};
+#elif defined(OS_WIN)
+struct MOJO_SYSTEM_IMPL_EXPORT NamedPlatformHandle {
+ NamedPlatformHandle() {}
+ explicit NamedPlatformHandle(const base::StringPiece& name)
+ : name(base::UTF8ToUTF16(name)) {}
+
+ explicit NamedPlatformHandle(const base::StringPiece16& name)
+ : name(name.as_string()) {}
+
+ bool is_valid() const { return !name.empty(); }
+
+ base::string16 pipe_name() const { return L"\\\\.\\pipe\\mojo." + name; }
+
+ base::string16 name;
+};
+#else
+#error "Platform not yet supported."
+#endif
+
+} // namespace edk
+} // namespace mojo
+
+#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_
diff --git a/chromium/mojo/edk/embedder/named_platform_handle_utils.h b/chromium/mojo/edk/embedder/named_platform_handle_utils.h
new file mode 100644
index 00000000000..6b856bb52f0
--- /dev/null
+++ b/chromium/mojo/edk/embedder/named_platform_handle_utils.h
@@ -0,0 +1,31 @@
+// Copyright 2016 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_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_UTILS_H_
+#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_UTILS_H_
+
+#include "build/build_config.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/edk/system/system_impl_export.h"
+
+namespace mojo {
+namespace edk {
+
+struct NamedPlatformHandle;
+
+// Creates a client platform handle from |handle|. This may block until |handle|
+// is ready to receive connections.
+MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle
+CreateClientHandle(const NamedPlatformHandle& handle);
+
+// Creates a server platform handle from |handle|. On Windows, if
+// |enforce_uniqueness| is true, this will fail if another pipe with the same
+// name exists. On other platforms, |enforce_uniqueness| must be false.
+MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle
+CreateServerHandle(const NamedPlatformHandle& handle, bool enforce_uniqueness);
+
+} // namespace edk
+} // namespace mojo
+
+#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_UTILS_H_
diff --git a/chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc b/chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc
new file mode 100644
index 00000000000..97572c05903
--- /dev/null
+++ b/chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc
@@ -0,0 +1,147 @@
+// Copyright 2016 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/edk/embedder/named_platform_handle_utils.h"
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "mojo/edk/embedder/named_platform_handle.h"
+
+namespace mojo {
+namespace edk {
+namespace {
+
+// The maximum length of the name of a socket for MODE_NAMED_SERVER or
+// MODE_NAMED_CLIENT if you want to pass in your own socket.
+// The standard size on linux is 108, mac is 104. To maintain consistency
+// across platforms we standardize on the smaller value.
+const size_t kMaxSocketNameLength = 104;
+
+// This function fills in |unix_addr| with the appropriate data for the socket,
+// and sets |unix_addr_len| to the length of the data therein.
+// Returns true on success, or false on failure (typically because |handle.name|
+// violated the naming rules).
+bool MakeUnixAddr(const NamedPlatformHandle& handle,
+ struct sockaddr_un* unix_addr,
+ size_t* unix_addr_len) {
+ DCHECK(unix_addr);
+ DCHECK(unix_addr_len);
+ DCHECK(handle.is_valid());
+
+ // We reject handle.name.length() == kMaxSocketNameLength to make room for the
+ // NUL terminator at the end of the string.
+ if (handle.name.length() >= kMaxSocketNameLength) {
+ LOG(ERROR) << "Socket name too long: " << handle.name;
+ return false;
+ }
+
+ // Create unix_addr structure.
+ memset(unix_addr, 0, sizeof(struct sockaddr_un));
+ unix_addr->sun_family = AF_UNIX;
+ strncpy(unix_addr->sun_path, handle.name.c_str(), kMaxSocketNameLength);
+ *unix_addr_len =
+ offsetof(struct sockaddr_un, sun_path) + handle.name.length();
+ return true;
+}
+
+// This function creates a unix domain socket, and set it as non-blocking.
+// If successful, this returns a ScopedPlatformHandle containing the socket.
+// Otherwise, this returns an invalid ScopedPlatformHandle.
+ScopedPlatformHandle CreateUnixDomainSocket(bool needs_connection) {
+ // Create the unix domain socket.
+ PlatformHandle socket_handle(socket(AF_UNIX, SOCK_STREAM, 0));
+ socket_handle.needs_connection = needs_connection;
+ ScopedPlatformHandle handle(socket_handle);
+ if (!handle.is_valid()) {
+ PLOG(ERROR) << "Failed to create AF_UNIX socket.";
+ return ScopedPlatformHandle();
+ }
+
+ // Now set it as non-blocking.
+ if (!base::SetNonBlocking(handle.get().handle)) {
+ PLOG(ERROR) << "base::SetNonBlocking() failed " << handle.get().handle;
+ return ScopedPlatformHandle();
+ }
+ return handle;
+}
+
+} // namespace
+
+ScopedPlatformHandle CreateClientHandle(
+ const NamedPlatformHandle& named_handle) {
+ if (!named_handle.is_valid())
+ return ScopedPlatformHandle();
+
+ struct sockaddr_un unix_addr;
+ size_t unix_addr_len;
+ if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len))
+ return ScopedPlatformHandle();
+
+ ScopedPlatformHandle handle = CreateUnixDomainSocket(false);
+ if (!handle.is_valid())
+ return ScopedPlatformHandle();
+
+ if (HANDLE_EINTR(connect(handle.get().handle,
+ reinterpret_cast<sockaddr*>(&unix_addr),
+ unix_addr_len)) < 0) {
+ PLOG(ERROR) << "connect " << named_handle.name;
+ return ScopedPlatformHandle();
+ }
+
+ return handle;
+}
+
+ScopedPlatformHandle CreateServerHandle(const NamedPlatformHandle& named_handle,
+ bool enforce_uniqueness) {
+ CHECK(!enforce_uniqueness);
+ if (!named_handle.is_valid())
+ return ScopedPlatformHandle();
+
+ // Make sure the path we need exists.
+ base::FilePath socket_dir = base::FilePath(named_handle.name).DirName();
+ if (!base::CreateDirectory(socket_dir)) {
+ LOG(ERROR) << "Couldn't create directory: " << socket_dir.value();
+ return ScopedPlatformHandle();
+ }
+
+ // Delete any old FS instances.
+ if (unlink(named_handle.name.c_str()) < 0 && errno != ENOENT) {
+ PLOG(ERROR) << "unlink " << named_handle.name;
+ return ScopedPlatformHandle();
+ }
+
+ struct sockaddr_un unix_addr;
+ size_t unix_addr_len;
+ if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len))
+ return ScopedPlatformHandle();
+
+ ScopedPlatformHandle handle = CreateUnixDomainSocket(true);
+ if (!handle.is_valid())
+ return ScopedPlatformHandle();
+
+ // Bind the socket.
+ if (bind(handle.get().handle, reinterpret_cast<const sockaddr*>(&unix_addr),
+ unix_addr_len) < 0) {
+ PLOG(ERROR) << "bind " << named_handle.name;
+ return ScopedPlatformHandle();
+ }
+
+ // Start listening on the socket.
+ if (listen(handle.get().handle, SOMAXCONN) < 0) {
+ PLOG(ERROR) << "listen " << named_handle.name;
+ unlink(named_handle.name.c_str());
+ return ScopedPlatformHandle();
+ }
+ return handle;
+}
+
+} // namespace edk
+} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/named_platform_handle_utils_win.cc b/chromium/mojo/edk/embedder/named_platform_handle_utils_win.cc
new file mode 100644
index 00000000000..ccf506217ae
--- /dev/null
+++ b/chromium/mojo/edk/embedder/named_platform_handle_utils_win.cc
@@ -0,0 +1,82 @@
+// Copyright 2016 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/edk/embedder/named_platform_handle_utils.h"
+
+#include <sddl.h>
+#include <windows.h>
+
+#include <memory>
+
+#include "base/logging.h"
+#include "base/win/windows_version.h"
+#include "mojo/edk/embedder/named_platform_handle.h"
+
+namespace mojo {
+namespace edk {
+
+ScopedPlatformHandle CreateClientHandle(
+ const NamedPlatformHandle& named_handle) {
+ if (!named_handle.is_valid())
+ return ScopedPlatformHandle();
+
+ base::string16 pipe_name = named_handle.pipe_name();
+
+ // Note: This may block.
+ if (!WaitNamedPipeW(pipe_name.c_str(), NMPWAIT_USE_DEFAULT_WAIT))
+ return ScopedPlatformHandle();
+
+ const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate
+ // the client.
+ const DWORD kFlags =
+ SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED;
+ ScopedPlatformHandle handle(
+ PlatformHandle(CreateFileW(pipe_name.c_str(), kDesiredAccess,
+ 0, // No sharing.
+ nullptr, OPEN_EXISTING, kFlags,
+ nullptr))); // No template file.
+ PCHECK(handle.is_valid());
+ return handle;
+}
+
+ScopedPlatformHandle CreateServerHandle(const NamedPlatformHandle& named_handle,
+ bool enforce_uniqueness) {
+ if (!named_handle.is_valid())
+ return ScopedPlatformHandle();
+
+ PSECURITY_DESCRIPTOR security_desc = nullptr;
+ ULONG security_desc_len = 0;
+ // Create a DACL to grant:
+ // GA = Generic All
+ // access to:
+ // SY = LOCAL_SYSTEM
+ // BA = BUILTIN_ADMINISTRATORS
+ // OW = OWNER_RIGHTS
+ PCHECK(ConvertStringSecurityDescriptorToSecurityDescriptor(
+ L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;OW)", SDDL_REVISION_1,
+ &security_desc, &security_desc_len));
+ std::unique_ptr<void, decltype(::LocalFree)*> p(security_desc, ::LocalFree);
+ SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES),
+ security_desc, FALSE};
+
+ const DWORD kOpenMode = enforce_uniqueness
+ ? PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
+ FILE_FLAG_FIRST_PIPE_INSTANCE
+ : PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED;
+ const DWORD kPipeMode =
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS;
+ PlatformHandle handle(
+ CreateNamedPipeW(named_handle.pipe_name().c_str(), kOpenMode, kPipeMode,
+ enforce_uniqueness ? 1 : 255, // Max instances.
+ 4096, // Out buffer size.
+ 4096, // In buffer size.
+ 5000, // Timeout in milliseconds.
+ &security_attributes));
+ handle.needs_connection = true;
+ return ScopedPlatformHandle(handle);
+}
+
+} // namespace edk
+} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc b/chromium/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc
index e05cd799826..a3fd275b9ff 100644
--- a/chromium/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc
+++ b/chromium/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc
@@ -153,7 +153,7 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) {
for (size_t j = 1; j <= i; j++) {
base::FilePath unused;
base::ScopedFILE fp(
- base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
+ base::CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused));
ASSERT_TRUE(fp);
ASSERT_EQ(j, fwrite(std::string(j, c).data(), 1, j, fp.get()));
platform_handles->push_back(
@@ -209,7 +209,7 @@ TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) {
{
base::FilePath unused;
base::ScopedFILE fp(
- base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
+ base::CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused));
ASSERT_TRUE(fp);
ASSERT_EQ(file_contents.size(),
fwrite(file_contents.data(), 1, file_contents.size(), fp.get()));
diff --git a/chromium/mojo/edk/embedder/platform_channel_utils_posix.cc b/chromium/mojo/edk/embedder/platform_channel_utils_posix.cc
index 3171844f67c..9fda89ebb65 100644
--- a/chromium/mojo/edk/embedder/platform_channel_utils_posix.cc
+++ b/chromium/mojo/edk/embedder/platform_channel_utils_posix.cc
@@ -8,9 +8,13 @@
#include <sys/socket.h>
#include <unistd.h>
+#include <utility>
+
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "build/build_config.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
#if !defined(OS_NACL)
#include <sys/uio.h>
@@ -22,6 +26,55 @@
namespace mojo {
namespace edk {
+namespace {
+
+#if !defined(OS_NACL)
+bool IsRecoverableError() {
+ return errno == ECONNABORTED || errno == EMFILE || errno == ENFILE ||
+ errno == ENOMEM || errno == ENOBUFS;
+}
+
+bool GetPeerEuid(PlatformHandle handle, uid_t* peer_euid) {
+ DCHECK(peer_euid);
+#if defined(OS_MACOSX) || defined(OS_OPENBSD) || defined(OS_FREEBSD)
+ uid_t socket_euid;
+ gid_t socket_gid;
+ if (getpeereid(handle.handle, &socket_euid, &socket_gid) < 0) {
+ PLOG(ERROR) << "getpeereid " << handle.handle;
+ return false;
+ }
+ *peer_euid = socket_euid;
+ return true;
+#else
+ struct ucred cred;
+ socklen_t cred_len = sizeof(cred);
+ if (getsockopt(handle.handle, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) <
+ 0) {
+ PLOG(ERROR) << "getsockopt " << handle.handle;
+ return false;
+ }
+ if (static_cast<unsigned>(cred_len) < sizeof(cred)) {
+ NOTREACHED() << "Truncated ucred from SO_PEERCRED?";
+ return false;
+ }
+ *peer_euid = cred.uid;
+ return true;
+#endif
+}
+
+bool IsPeerAuthorized(PlatformHandle peer_handle) {
+ uid_t peer_euid;
+ if (!GetPeerEuid(peer_handle, &peer_euid))
+ return false;
+ if (peer_euid != geteuid()) {
+ DLOG(ERROR) << "Client euid is not authorised";
+ return false;
+ }
+ return true;
+}
+#endif // !defined(OS_NACL)
+
+} // namespace
// On Linux, |SIGPIPE| is suppressed by passing |MSG_NOSIGNAL| to
// |send()|/|sendmsg()|. (There is no way of suppressing |SIGPIPE| on
@@ -193,5 +246,36 @@ ssize_t PlatformChannelRecvmsg(PlatformHandle h,
return result;
}
+bool ServerAcceptConnection(PlatformHandle server_handle,
+ ScopedPlatformHandle* connection_handle) {
+ DCHECK(server_handle.is_valid());
+ connection_handle->reset();
+#if defined(OS_NACL)
+ NOTREACHED();
+ return false;
+#else
+ ScopedPlatformHandle accept_handle(
+ PlatformHandle(HANDLE_EINTR(accept(server_handle.handle, NULL, 0))));
+ if (!accept_handle.is_valid())
+ return IsRecoverableError();
+
+ // Verify that the IPC channel peer is running as the same user.
+ if (!IsPeerAuthorized(accept_handle.get())) {
+ return true;
+ }
+
+ if (!base::SetNonBlocking(accept_handle.get().handle)) {
+ PLOG(ERROR) << "base::SetNonBlocking() failed "
+ << accept_handle.get().handle;
+ // It's safe to keep listening on |server_handle| even if the attempt to set
+ // O_NONBLOCK failed on the client fd.
+ return true;
+ }
+
+ *connection_handle = std::move(accept_handle);
+ return true;
+#endif // defined(OS_NACL)
+}
+
} // namespace edk
} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_channel_utils_posix.h b/chromium/mojo/edk/embedder/platform_channel_utils_posix.h
index 8b24bd028f8..8bf2632e0ba 100644
--- a/chromium/mojo/edk/embedder/platform_channel_utils_posix.h
+++ b/chromium/mojo/edk/embedder/platform_channel_utils_posix.h
@@ -18,6 +18,7 @@ struct iovec; // Declared in <sys/uio.h>.
namespace mojo {
namespace edk {
+class ScopedPlatformHandle;
// The maximum number of handles that can be sent "at once" using
// |PlatformChannelSendmsgWithHandles()|. This must be less than the Linux
@@ -70,6 +71,14 @@ PlatformChannelRecvmsg(PlatformHandle h,
std::deque<PlatformHandle>* platform_handles,
bool block = false);
+// Returns false if |server_handle| encounters an unrecoverable error.
+// Returns true if it's valid to keep listening on |server_handle|. In this
+// case, it's possible that a connection wasn't successfully established; then,
+// |connection_handle| will be invalid.
+MOJO_SYSTEM_IMPL_EXPORT bool ServerAcceptConnection(
+ PlatformHandle server_handle,
+ ScopedPlatformHandle* connection_handle);
+
} // namespace edk
} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_handle.h b/chromium/mojo/edk/embedder/platform_handle.h
index 4f76009524a..4866e754fd1 100644
--- a/chromium/mojo/edk/embedder/platform_handle.h
+++ b/chromium/mojo/edk/embedder/platform_handle.h
@@ -53,6 +53,9 @@ struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle {
int handle = -1;
+ // A POSIX handle may be a listen handle that can accept a connection.
+ bool needs_connection = false;
+
#if defined(OS_MACOSX) && !defined(OS_IOS)
mach_port_t port = MACH_PORT_NULL;
#endif
diff --git a/chromium/mojo/edk/embedder/platform_handle_utils_posix.cc b/chromium/mojo/edk/embedder/platform_handle_utils_posix.cc
index fc2a0dbe09a..5604f96bf14 100644
--- a/chromium/mojo/edk/embedder/platform_handle_utils_posix.cc
+++ b/chromium/mojo/edk/embedder/platform_handle_utils_posix.cc
@@ -15,7 +15,9 @@ ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) {
DCHECK(platform_handle.is_valid());
// Note that |dup()| returns -1 on error (which is exactly the value we use
// for invalid |PlatformHandle| FDs).
- return ScopedPlatformHandle(PlatformHandle(dup(platform_handle.handle)));
+ PlatformHandle duped(dup(platform_handle.handle));
+ duped.needs_connection = platform_handle.needs_connection;
+ return ScopedPlatformHandle(duped);
}
} // namespace edk
diff --git a/chromium/mojo/edk/embedder/platform_shared_buffer.cc b/chromium/mojo/edk/embedder/platform_shared_buffer.cc
index 53d8edc0f62..58af44df8f8 100644
--- a/chromium/mojo/edk/embedder/platform_shared_buffer.cc
+++ b/chromium/mojo/edk/embedder/platform_shared_buffer.cc
@@ -253,21 +253,28 @@ bool PlatformSharedBuffer::InitFromPlatformHandle(
bool PlatformSharedBuffer::InitFromPlatformHandlePair(
ScopedPlatformHandle rw_platform_handle,
ScopedPlatformHandle ro_platform_handle) {
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_MACOSX)
NOTREACHED();
return false;
-#else
- DCHECK(!shared_memory_);
+#else // defined(OS_MACOSX)
+#if defined(OS_WIN)
+ base::SharedMemoryHandle handle(rw_platform_handle.release().handle,
+ base::GetCurrentProcId());
+ base::SharedMemoryHandle ro_handle(ro_platform_handle.release().handle,
+ base::GetCurrentProcId());
+#else // defined(OS_WIN)
base::SharedMemoryHandle handle(rw_platform_handle.release().handle, false);
- shared_memory_.reset(new base::SharedMemory(handle, false));
-
base::SharedMemoryHandle ro_handle(ro_platform_handle.release().handle,
false);
- ro_shared_memory_.reset(new base::SharedMemory(ro_handle, true));
+#endif // defined(OS_WIN)
+ DCHECK(!shared_memory_);
+ shared_memory_.reset(new base::SharedMemory(handle, false));
+ ro_shared_memory_.reset(new base::SharedMemory(ro_handle, true));
return true;
-#endif
+
+#endif // defined(OS_MACOSX)
}
void PlatformSharedBuffer::InitFromSharedMemoryHandle(
diff --git a/chromium/mojo/edk/js/core.cc b/chromium/mojo/edk/js/core.cc
index c8ccc37c536..f3eec8cc842 100644
--- a/chromium/mojo/edk/js/core.cc
+++ b/chromium/mojo/edk/js/core.cc
@@ -289,6 +289,87 @@ bool IsHandle(gin::Arguments* args, v8::Handle<v8::Value> val) {
args->isolate(), val, &ignore_handle);
}
+gin::Dictionary CreateSharedBuffer(const gin::Arguments& args,
+ uint64_t num_bytes,
+ MojoCreateSharedBufferOptionsFlags flags) {
+ gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
+ MojoHandle handle = MOJO_HANDLE_INVALID;
+ MojoCreateSharedBufferOptions options;
+ // The |flags| is mandatory parameter for CreateSharedBuffer, and it will
+ // be always initialized in MojoCreateSharedBufferOptions struct. For
+ // forward compatibility, set struct_size to be 8 bytes (struct_size + flags),
+ // so that validator will only check the field that is set.
+ options.struct_size = 8;
+ options.flags = flags;
+ MojoResult result = MojoCreateSharedBuffer(&options, num_bytes, &handle);
+ if (result != MOJO_RESULT_OK) {
+ dictionary.Set("result", result);
+ return dictionary;
+ }
+
+ dictionary.Set("result", result);
+ dictionary.Set("handle", mojo::Handle(handle));
+
+ return dictionary;
+}
+
+gin::Dictionary DuplicateBufferHandle(
+ const gin::Arguments& args,
+ mojo::Handle handle,
+ MojoDuplicateBufferHandleOptionsFlags flags) {
+ gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
+ MojoHandle duped = MOJO_HANDLE_INVALID;
+ MojoDuplicateBufferHandleOptions options;
+ // The |flags| is mandatory parameter for DuplicateBufferHandle, and it will
+ // be always initialized in MojoDuplicateBufferHandleOptions struct. For
+ // forward compatibility, set struct_size to be 8 bytes (struct_size + flags),
+ // so that validator will only check the field that is set.
+ options.struct_size = 8;
+ options.flags = flags;
+ MojoResult result =
+ MojoDuplicateBufferHandle(handle.value(), &options, &duped);
+ if (result != MOJO_RESULT_OK) {
+ dictionary.Set("result", result);
+ return dictionary;
+ }
+
+ dictionary.Set("result", result);
+ dictionary.Set("handle", mojo::Handle(duped));
+
+ return dictionary;
+}
+
+gin::Dictionary MapBuffer(const gin::Arguments& args,
+ mojo::Handle handle,
+ uint64_t offset,
+ uint64_t num_bytes,
+ MojoMapBufferFlags flags) {
+ gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate());
+ void* data = nullptr;
+ MojoResult result =
+ MojoMapBuffer(handle.value(), offset, num_bytes, &data, flags);
+ if (result != MOJO_RESULT_OK) {
+ dictionary.Set("result", result);
+ return dictionary;
+ }
+
+ v8::Handle<v8::ArrayBuffer> array_buffer =
+ v8::ArrayBuffer::New(args.isolate(), data, num_bytes);
+
+ dictionary.Set("result", result);
+ dictionary.Set("buffer", array_buffer);
+
+ return dictionary;
+}
+
+MojoResult UnmapBuffer(const gin::Arguments& args,
+ const v8::Handle<v8::ArrayBuffer>& buffer) {
+ // Buffer must be external, created by MapBuffer
+ if (!buffer->IsExternal())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ return MojoUnmapBuffer(buffer->GetContents().Data());
+}
gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin };
@@ -317,6 +398,10 @@ v8::Local<v8::Value> Core::GetModule(v8::Isolate* isolate) {
.SetMethod("readData", ReadData)
.SetMethod("drainData", DoDrainData)
.SetMethod("isHandle", IsHandle)
+ .SetMethod("createSharedBuffer", CreateSharedBuffer)
+ .SetMethod("duplicateBufferHandle", DuplicateBufferHandle)
+ .SetMethod("mapBuffer", MapBuffer)
+ .SetMethod("unmapBuffer", UnmapBuffer)
.SetValue("RESULT_OK", MOJO_RESULT_OK)
.SetValue("RESULT_CANCELLED", MOJO_RESULT_CANCELLED)
@@ -369,6 +454,16 @@ v8::Local<v8::Value> Core::GetModule(v8::Isolate* isolate) {
.SetValue("READ_DATA_FLAG_DISCARD", MOJO_READ_DATA_FLAG_DISCARD)
.SetValue("READ_DATA_FLAG_QUERY", MOJO_READ_DATA_FLAG_QUERY)
.SetValue("READ_DATA_FLAG_PEEK", MOJO_READ_DATA_FLAG_PEEK)
+ .SetValue("CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE",
+ MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE)
+
+ .SetValue("DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE",
+ MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE)
+
+ .SetValue("DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY",
+ MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY)
+
+ .SetValue("MAP_BUFFER_FLAG_NONE", MOJO_MAP_BUFFER_FLAG_NONE)
.Build();
data->SetObjectTemplate(&g_wrapper_info, templ);
diff --git a/chromium/mojo/edk/system/BUILD.gn b/chromium/mojo/edk/system/BUILD.gn
index b1d2d6dbc32..9023fbd35c0 100644
--- a/chromium/mojo/edk/system/BUILD.gn
+++ b/chromium/mojo/edk/system/BUILD.gn
@@ -15,16 +15,15 @@ component("system") {
output_name = "mojo_system_impl"
sources = [
- "async_waiter.cc",
- "async_waiter.h",
"atomic_flag.h",
"awakable.h",
"awakable_list.cc",
"awakable_list.h",
"broker.h",
+ "broker_host.cc",
"broker_host.h",
- "broker_host_posix.cc",
"broker_posix.cc",
+ "broker_win.cc",
"channel.cc",
"channel.h",
"channel_posix.cc",
@@ -108,7 +107,7 @@ component("system") {
if (is_nacl && !is_nacl_nonsfi) {
sources -= [
- "broker_host_posix.cc",
+ "broker_host.cc",
"broker_posix.cc",
"channel_posix.cc",
"remote_message_pipe_bootstrap.cc",
diff --git a/chromium/mojo/edk/system/async_waiter.cc b/chromium/mojo/edk/system/async_waiter.cc
deleted file mode 100644
index d2e7000fb38..00000000000
--- a/chromium/mojo/edk/system/async_waiter.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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/edk/system/async_waiter.h"
-
-namespace mojo {
-namespace edk {
-
-AsyncWaiter::AsyncWaiter(const AwakeCallback& callback) : callback_(callback) {
-}
-
-AsyncWaiter::~AsyncWaiter() {
-}
-
-bool AsyncWaiter::Awake(MojoResult result, uintptr_t context) {
- callback_.Run(result);
- delete this;
- return false;
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/system/async_waiter.h b/chromium/mojo/edk/system/async_waiter.h
deleted file mode 100644
index 8a1ed1c5db4..00000000000
--- a/chromium/mojo/edk/system/async_waiter.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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_EDK_SYSTEM_ASYNC_WAITER_H_
-#define MOJO_EDK_SYSTEM_ASYNC_WAITER_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "mojo/edk/system/awakable.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-namespace edk {
-
-// An |Awakable| implementation that just calls a given callback object.
-class MOJO_SYSTEM_IMPL_EXPORT AsyncWaiter final : public Awakable {
- public:
- using AwakeCallback = base::Callback<void(MojoResult)>;
-
- // |callback| must satisfy the same contract as |Awakable::Awake()|.
- explicit AsyncWaiter(const AwakeCallback& callback);
- virtual ~AsyncWaiter();
-
- private:
- // |Awakable| implementation:
- bool Awake(MojoResult result, uintptr_t context) override;
-
- AwakeCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(AsyncWaiter);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_ASYNC_WAITER_H_
diff --git a/chromium/mojo/edk/system/broker_host_posix.cc b/chromium/mojo/edk/system/broker_host.cc
index ed8e213c1c0..a5a5f9cf04b 100644
--- a/chromium/mojo/edk/system/broker_host_posix.cc
+++ b/chromium/mojo/edk/system/broker_host.cc
@@ -4,17 +4,14 @@
#include "mojo/edk/system/broker_host.h"
-#include <fcntl.h>
-#include <unistd.h>
-
#include <utility>
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "mojo/edk/embedder/embedder_internal.h"
-#include "mojo/edk/embedder/platform_channel_utils_posix.h"
+#include "mojo/edk/embedder/named_platform_channel_pair.h"
+#include "mojo/edk/embedder/named_platform_handle.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/system/broker_messages.h"
@@ -23,18 +20,25 @@ namespace mojo {
namespace edk {
namespace {
+
// To prevent abuse, limit the maximum size of shared memory buffers.
-// TODO(amistry): Re-consider this limit, or do something smarter.
-const size_t kMaxSharedBufferSize = 16 * 1024 * 1024;
-}
+// TODO(rockot): Re-consider this limit, or do something smarter.
+const uint32_t kMaxSharedBufferSize = 16 * 1024 * 1024;
-BrokerHost::BrokerHost(ScopedPlatformHandle platform_handle) {
+} // namespace
+
+BrokerHost::BrokerHost(base::ProcessHandle client_process,
+ ScopedPlatformHandle platform_handle)
+#if defined(OS_WIN)
+ : client_process_(client_process)
+#endif
+{
CHECK(platform_handle.is_valid());
base::MessageLoop::current()->AddDestructionObserver(this);
- channel_ = Channel::Create(this, std::move(platform_handle),
- base::ThreadTaskRunnerHandle::Get());
+ channel_ = Channel::Create(
+ this, std::move(platform_handle), base::ThreadTaskRunnerHandle::Get());
channel_->Start();
}
@@ -46,21 +50,63 @@ BrokerHost::~BrokerHost() {
channel_->ShutDown();
}
-void BrokerHost::SendChannel(ScopedPlatformHandle handle) {
+bool BrokerHost::PrepareHandlesForClient(PlatformHandleVector* handles) {
+#if defined(OS_WIN)
+ if (!Channel::Message::RewriteHandles(
+ base::GetCurrentProcessHandle(), client_process_, handles)) {
+ // NOTE: We only log an error here. We do not signal a logical error or
+ // prevent any message from being sent. The client should handle unexpected
+ // invalid handles appropriately.
+ DLOG(ERROR) << "Failed to rewrite one or more handles to broker client.";
+ return false;
+ }
+#endif
+ return true;
+}
+
+bool BrokerHost::SendChannel(ScopedPlatformHandle handle) {
CHECK(handle.is_valid());
CHECK(channel_);
+#if defined(OS_WIN)
+ InitData* data;
+ Channel::MessagePtr message =
+ CreateBrokerMessage(BrokerMessageType::INIT, 1, 0, &data);
+ data->pipe_name_length = 0;
+#else
Channel::MessagePtr message =
CreateBrokerMessage(BrokerMessageType::INIT, 1, nullptr);
+#endif
ScopedPlatformHandleVectorPtr handles;
handles.reset(new PlatformHandleVector(1));
handles->at(0) = handle.release();
- message->SetHandles(std::move(handles));
+ // This may legitimately fail on Windows if the client process is in another
+ // session, e.g., is an elevated process.
+ if (!PrepareHandlesForClient(handles.get()))
+ return false;
+
+ message->SetHandles(std::move(handles));
channel_->Write(std::move(message));
+ return true;
}
-void BrokerHost::OnBufferRequest(size_t num_bytes) {
+#if defined(OS_WIN)
+
+void BrokerHost::SendNamedChannel(const base::StringPiece16& pipe_name) {
+ InitData* data;
+ base::char16* name_data;
+ Channel::MessagePtr message = CreateBrokerMessage(
+ BrokerMessageType::INIT, 0, sizeof(*name_data) * pipe_name.length(),
+ &data, reinterpret_cast<void**>(&name_data));
+ data->pipe_name_length = static_cast<uint32_t>(pipe_name.length());
+ std::copy(pipe_name.begin(), pipe_name.end(), name_data);
+ channel_->Write(std::move(message));
+}
+
+#endif // defined(OS_WIN)
+
+void BrokerHost::OnBufferRequest(uint32_t num_bytes) {
scoped_refptr<PlatformSharedBuffer> buffer;
scoped_refptr<PlatformSharedBuffer> read_only_buffer;
if (num_bytes <= kMaxSharedBufferSize) {
@@ -80,6 +126,7 @@ void BrokerHost::OnBufferRequest(size_t num_bytes) {
handles.reset(new PlatformHandleVector(2));
handles->at(0) = buffer->PassPlatformHandle().release();
handles->at(1) = read_only_buffer->PassPlatformHandle().release();
+ PrepareHandlesForClient(handles.get());
message->SetHandles(std::move(handles));
}
@@ -101,29 +148,18 @@ void BrokerHost::OnChannelMessage(const void* payload,
const BufferRequestData* request =
reinterpret_cast<const BufferRequestData*>(header + 1);
OnBufferRequest(request->size);
- return;
}
break;
default:
+ LOG(ERROR) << "Unexpected broker message type: " << header->type;
break;
}
-
- LOG(ERROR) << "Unexpected broker message type: " << header->type;
}
-void BrokerHost::OnChannelError() {
- if (channel_) {
- channel_->ShutDown();
- channel_ = nullptr;
- }
+void BrokerHost::OnChannelError() { delete this; }
- delete this;
-}
-
-void BrokerHost::WillDestroyCurrentMessageLoop() {
- delete this;
-}
+void BrokerHost::WillDestroyCurrentMessageLoop() { delete this; }
} // namespace edk
} // namespace mojo
diff --git a/chromium/mojo/edk/system/broker_host.h b/chromium/mojo/edk/system/broker_host.h
index b8f68c4ddeb..a7995d2b0fc 100644
--- a/chromium/mojo/edk/system/broker_host.h
+++ b/chromium/mojo/edk/system/broker_host.h
@@ -5,8 +5,13 @@
#ifndef MOJO_EDK_SYSTEM_BROKER_HOST_H_
#define MOJO_EDK_SYSTEM_BROKER_HOST_H_
+#include <stdint.h>
+
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/process/process_handle.h"
+#include "base/strings/string_piece.h"
+#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel.h"
@@ -18,14 +23,21 @@ namespace edk {
class BrokerHost : public Channel::Delegate,
public base::MessageLoop::DestructionObserver {
public:
- explicit BrokerHost(ScopedPlatformHandle platform_handle);
+ BrokerHost(base::ProcessHandle client_process, ScopedPlatformHandle handle);
// Send |handle| to the child, to be used to establish a NodeChannel to us.
- void SendChannel(ScopedPlatformHandle handle);
+ bool SendChannel(ScopedPlatformHandle handle);
+
+#if defined(OS_WIN)
+ // Sends a named channel to the child. Like above, but for named pipes.
+ void SendNamedChannel(const base::StringPiece16& pipe_name);
+#endif
private:
~BrokerHost() override;
+ bool PrepareHandlesForClient(PlatformHandleVector* handles);
+
// Channel::Delegate:
void OnChannelMessage(const void* payload,
size_t payload_size,
@@ -35,7 +47,11 @@ class BrokerHost : public Channel::Delegate,
// base::MessageLoop::DestructionObserver:
void WillDestroyCurrentMessageLoop() override;
- void OnBufferRequest(size_t num_bytes);
+ void OnBufferRequest(uint32_t num_bytes);
+
+#if defined(OS_WIN)
+ base::ProcessHandle client_process_;
+#endif
scoped_refptr<Channel> channel_;
diff --git a/chromium/mojo/edk/system/broker_messages.h b/chromium/mojo/edk/system/broker_messages.h
index a67be15d8a1..19b757eec49 100644
--- a/chromium/mojo/edk/system/broker_messages.h
+++ b/chromium/mojo/edk/system/broker_messages.h
@@ -30,19 +30,34 @@ struct BufferRequestData {
uint32_t size;
};
+#if defined(OS_WIN)
+struct InitData {
+ // NOTE: InitData in the payload is followed by string16 data with exactly
+ // |pipe_name_length| wide characters (i.e., |pipe_name_length|*2 bytes.)
+ // This applies to Windows only.
+ uint32_t pipe_name_length;
+};
+#endif
+
#pragma pack(pop)
template <typename T>
-inline Channel::MessagePtr CreateBrokerMessage(BrokerMessageType type,
- size_t num_handles,
- T** out_message_data) {
- const size_t message_size = sizeof(BrokerMessageHeader) + sizeof(T);
+inline Channel::MessagePtr CreateBrokerMessage(
+ BrokerMessageType type,
+ size_t num_handles,
+ size_t extra_data_size,
+ T** out_message_data,
+ void** out_extra_data = nullptr) {
+ const size_t message_size = sizeof(BrokerMessageHeader) +
+ sizeof(**out_message_data) + extra_data_size;
Channel::MessagePtr message(new Channel::Message(message_size, num_handles));
BrokerMessageHeader* header =
reinterpret_cast<BrokerMessageHeader*>(message->mutable_payload());
header->type = type;
header->padding = 0;
*out_message_data = reinterpret_cast<T*>(header + 1);
+ if (out_extra_data)
+ *out_extra_data = *out_message_data + 1;
return message;
}
diff --git a/chromium/mojo/edk/system/broker_posix.cc b/chromium/mojo/edk/system/broker_posix.cc
index 5400ed2a287..8742f709a7b 100644
--- a/chromium/mojo/edk/system/broker_posix.cc
+++ b/chromium/mojo/edk/system/broker_posix.cc
@@ -94,7 +94,7 @@ scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
BufferRequestData* buffer_request;
Channel::MessagePtr out_message = CreateBrokerMessage(
- BrokerMessageType::BUFFER_REQUEST, 0, &buffer_request);
+ BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request);
buffer_request->size = num_bytes;
ssize_t write_result = PlatformChannelWrite(
sync_channel_.get(), out_message->data(), out_message->data_num_bytes());
diff --git a/chromium/mojo/edk/system/broker_win.cc b/chromium/mojo/edk/system/broker_win.cc
new file mode 100644
index 00000000000..e6d72e6716e
--- /dev/null
+++ b/chromium/mojo/edk/system/broker_win.cc
@@ -0,0 +1,144 @@
+// Copyright 2016 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 <windows.h>
+
+#include <limits>
+#include <utility>
+
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_piece.h"
+#include "mojo/edk/embedder/named_platform_handle.h"
+#include "mojo/edk/embedder/named_platform_handle_utils.h"
+#include "mojo/edk/embedder/platform_handle.h"
+#include "mojo/edk/embedder/platform_handle_vector.h"
+#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "mojo/edk/system/broker.h"
+#include "mojo/edk/system/broker_messages.h"
+#include "mojo/edk/system/channel.h"
+
+namespace mojo {
+namespace edk {
+
+namespace {
+
+// 256 bytes should be enough for anyone!
+const size_t kMaxBrokerMessageSize = 256;
+
+bool TakeHandlesFromBrokerMessage(Channel::Message* message,
+ size_t num_handles,
+ ScopedPlatformHandle* out_handles) {
+ if (message->num_handles() != num_handles) {
+ DLOG(ERROR) << "Received unexpected number of handles in broker message";
+ return false;
+ }
+
+ ScopedPlatformHandleVectorPtr handles = message->TakeHandles();
+ DCHECK(handles);
+ DCHECK_EQ(handles->size(), num_handles);
+ DCHECK(out_handles);
+
+ for (size_t i = 0; i < num_handles; ++i)
+ out_handles[i] = ScopedPlatformHandle((*handles)[i]);
+ handles->clear();
+ return true;
+}
+
+Channel::MessagePtr WaitForBrokerMessage(PlatformHandle platform_handle,
+ BrokerMessageType expected_type) {
+ char buffer[kMaxBrokerMessageSize];
+ DWORD bytes_read = 0;
+ BOOL result = ::ReadFile(platform_handle.handle, buffer,
+ kMaxBrokerMessageSize, &bytes_read, nullptr);
+ if (!result) {
+ // The pipe may be broken if the browser side has been closed, e.g. during
+ // browser shutdown. In that case the ReadFile call will fail and we
+ // shouldn't continue waiting.
+ PLOG(ERROR) << "Error reading broker pipe";
+ return nullptr;
+ }
+
+ Channel::MessagePtr message =
+ Channel::Message::Deserialize(buffer, static_cast<size_t>(bytes_read));
+ if (!message || message->payload_size() < sizeof(BrokerMessageHeader)) {
+ LOG(ERROR) << "Invalid broker message";
+ return nullptr;
+ }
+
+ const BrokerMessageHeader* header =
+ reinterpret_cast<const BrokerMessageHeader*>(message->payload());
+ if (header->type != expected_type) {
+ LOG(ERROR) << "Unexpected broker message type";
+ return nullptr;
+ }
+
+ return message;
+}
+
+} // namespace
+
+Broker::Broker(ScopedPlatformHandle handle) : sync_channel_(std::move(handle)) {
+ CHECK(sync_channel_.is_valid());
+ Channel::MessagePtr message =
+ WaitForBrokerMessage(sync_channel_.get(), BrokerMessageType::INIT);
+
+ // If we fail to read a message (broken pipe), just return early. The parent
+ // handle will be null and callers must handle this gracefully.
+ if (!message)
+ return;
+
+ if (!TakeHandlesFromBrokerMessage(message.get(), 1, &parent_channel_)) {
+ // If the message has no handles, we expect it to carry pipe name instead.
+ const BrokerMessageHeader* header =
+ static_cast<const BrokerMessageHeader*>(message->payload());
+ CHECK_GE(message->payload_size(),
+ sizeof(BrokerMessageHeader) + sizeof(InitData));
+ const InitData* data = reinterpret_cast<const InitData*>(header + 1);
+ CHECK_EQ(message->payload_size(),
+ sizeof(BrokerMessageHeader) + sizeof(InitData) +
+ data->pipe_name_length * sizeof(base::char16));
+ const base::char16* name_data =
+ reinterpret_cast<const base::char16*>(data + 1);
+ CHECK(data->pipe_name_length);
+ parent_channel_ = CreateClientHandle(NamedPlatformHandle(
+ base::StringPiece16(name_data, data->pipe_name_length)));
+ }
+}
+
+Broker::~Broker() {}
+
+ScopedPlatformHandle Broker::GetParentPlatformHandle() {
+ return std::move(parent_channel_);
+}
+
+scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
+ base::AutoLock lock(lock_);
+ BufferRequestData* buffer_request;
+ Channel::MessagePtr out_message = CreateBrokerMessage(
+ BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request);
+ buffer_request->size = base::checked_cast<uint32_t>(num_bytes);
+ DWORD bytes_written = 0;
+ BOOL result = ::WriteFile(sync_channel_.get().handle, out_message->data(),
+ static_cast<DWORD>(out_message->data_num_bytes()),
+ &bytes_written, nullptr);
+ if (!result ||
+ static_cast<size_t>(bytes_written) != out_message->data_num_bytes()) {
+ LOG(ERROR) << "Error sending sync broker message";
+ return nullptr;
+ }
+
+ ScopedPlatformHandle handles[2];
+ Channel::MessagePtr response = WaitForBrokerMessage(
+ sync_channel_.get(), BrokerMessageType::BUFFER_RESPONSE);
+ if (response &&
+ TakeHandlesFromBrokerMessage(response.get(), 2, &handles[0])) {
+ return PlatformSharedBuffer::CreateFromPlatformHandlePair(
+ num_bytes, std::move(handles[0]), std::move(handles[1]));
+ }
+
+ return nullptr;
+}
+
+} // namespace edk
+} // namespace mojo
diff --git a/chromium/mojo/edk/system/channel.cc b/chromium/mojo/edk/system/channel.cc
index 56509b5b609..a020ee6b482 100644
--- a/chromium/mojo/edk/system/channel.cc
+++ b/chromium/mojo/edk/system/channel.cc
@@ -192,8 +192,8 @@ Channel::MessagePtr Channel::Message::Deserialize(const void* data,
ScopedPlatformHandleVectorPtr handles(
new PlatformHandleVector(header->num_handles));
for (size_t i = 0; i < header->num_handles; i++) {
- (*handles)[i].handle = reinterpret_cast<HANDLE>(
- static_cast<uintptr_t>(message->handles_[i].handle));
+ (*handles)[i].handle =
+ base::win::Uint32ToHandle(message->handles_[i].handle);
}
message->SetHandles(std::move(handles));
#endif
diff --git a/chromium/mojo/edk/system/channel_posix.cc b/chromium/mojo/edk/system/channel_posix.cc
index 16a9304462f..77a5832de47 100644
--- a/chromium/mojo/edk/system/channel_posix.cc
+++ b/chromium/mojo/edk/system/channel_posix.cc
@@ -211,11 +211,19 @@ class ChannelPosix : public Channel,
DCHECK(!read_watcher_);
DCHECK(!write_watcher_);
read_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher);
- write_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher);
- base::MessageLoopForIO::current()->WatchFileDescriptor(
- handle_.get().handle, true /* persistent */,
- base::MessageLoopForIO::WATCH_READ, read_watcher_.get(), this);
base::MessageLoop::current()->AddDestructionObserver(this);
+ if (handle_.get().needs_connection) {
+ base::MessageLoopForIO::current()->WatchFileDescriptor(
+ handle_.get().handle, false /* persistent */,
+ base::MessageLoopForIO::WATCH_READ, read_watcher_.get(), this);
+ } else {
+ write_watcher_.reset(new base::MessageLoopForIO::FileDescriptorWatcher);
+ base::MessageLoopForIO::current()->WatchFileDescriptor(
+ handle_.get().handle, true /* persistent */,
+ base::MessageLoopForIO::WATCH_READ, read_watcher_.get(), this);
+ base::AutoLock lock(write_lock_);
+ FlushOutgoingMessagesNoLock();
+ }
}
void WaitForWriteOnIOThread() {
@@ -265,6 +273,24 @@ class ChannelPosix : public Channel,
// base::MessageLoopForIO::Watcher:
void OnFileCanReadWithoutBlocking(int fd) override {
CHECK_EQ(fd, handle_.get().handle);
+ if (handle_.get().needs_connection) {
+#if !defined(OS_NACL)
+ read_watcher_.reset();
+ base::MessageLoop::current()->RemoveDestructionObserver(this);
+
+ ScopedPlatformHandle accept_fd;
+ ServerAcceptConnection(handle_.get(), &accept_fd);
+ if (!accept_fd.is_valid()) {
+ OnError();
+ return;
+ }
+ handle_ = std::move(accept_fd);
+ StartOnIOThread();
+#else
+ NOTREACHED();
+#endif
+ return;
+ }
bool read_error = false;
size_t next_read_size = 0;
@@ -321,6 +347,10 @@ class ChannelPosix : public Channel,
// cannot be written, it's queued and a wait is initiated to write the message
// ASAP on the I/O thread.
bool WriteNoLock(MessageView message_view) {
+ if (handle_.get().needs_connection) {
+ outgoing_messages_.emplace_front(std::move(message_view));
+ return true;
+ }
size_t bytes_written = 0;
do {
message_view.advance_data_offset(bytes_written);
diff --git a/chromium/mojo/edk/system/channel_win.cc b/chromium/mojo/edk/system/channel_win.cc
index c989344f62b..232577ffece 100644
--- a/chromium/mojo/edk/system/channel_win.cc
+++ b/chromium/mojo/edk/system/channel_win.cc
@@ -19,6 +19,7 @@
#include "base/message_loop/message_loop.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
+#include "base/win/win_util.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
namespace mojo {
@@ -137,8 +138,8 @@ class ChannelWin : public Channel,
const HandleEntry* extra_header_handles =
reinterpret_cast<const HandleEntry*>(extra_header);
for (size_t i = 0; i < num_handles; i++) {
- (*handles)->at(i).handle = reinterpret_cast<HANDLE>(
- static_cast<uintptr_t>(extra_header_handles[i].handle));
+ (*handles)->at(i).handle =
+ base::win::Uint32ToHandle(extra_header_handles[i].handle);
}
return true;
}
diff --git a/chromium/mojo/edk/system/core.cc b/chromium/mojo/edk/system/core.cc
index aca5b259673..d2a421ebeee 100644
--- a/chromium/mojo/edk/system/core.cc
+++ b/chromium/mojo/edk/system/core.cc
@@ -21,7 +21,6 @@
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/embedder_internal.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/system/async_waiter.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
@@ -168,6 +167,11 @@ scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
return handles_.GetDispatcher(handle);
}
+void Core::SetDefaultProcessErrorCallback(
+ const ProcessErrorCallback& callback) {
+ default_process_error_callback_ = callback;
+}
+
void Core::AddChild(base::ProcessHandle process_handle,
ScopedPlatformHandle platform_handle,
const std::string& child_token,
@@ -183,6 +187,17 @@ void Core::ChildLaunchFailed(const std::string& child_token) {
GetNodeController()->CloseChildPorts(child_token);
}
+ScopedMessagePipeHandle Core::ConnectToPeerProcess(
+ ScopedPlatformHandle pipe_handle) {
+ RequestContext request_context;
+ ports::PortRef port0, port1;
+ GetNodeController()->node()->CreatePortPair(&port0, &port1);
+ MojoHandle handle = AddDispatcher(new MessagePipeDispatcher(
+ GetNodeController(), port0, kUnknownPipeIdForDebug, 0));
+ GetNodeController()->ConnectToPeer(std::move(pipe_handle), port1);
+ return ScopedMessagePipeHandle(MessagePipeHandle(handle));
+}
+
void Core::InitChild(ScopedPlatformHandle platform_handle) {
GetNodeController()->ConnectToParent(std::move(platform_handle));
}
@@ -363,20 +378,6 @@ ScopedMessagePipeHandle Core::CreateChildMessagePipe(const std::string& token) {
return ScopedMessagePipeHandle(MessagePipeHandle(handle));
}
-MojoResult Core::AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- const base::Callback<void(MojoResult)>& callback) {
- scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
- DCHECK(dispatcher);
-
- std::unique_ptr<AsyncWaiter> waiter =
- base::WrapUnique(new AsyncWaiter(callback));
- MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr);
- if (rv == MOJO_RESULT_OK)
- ignore_result(waiter.release());
- return rv;
-}
-
MojoResult Core::SetProperty(MojoPropertyType type, const void* value) {
base::AutoLock locker(property_lock_);
switch (type) {
@@ -787,6 +788,8 @@ MojoResult Core::NotifyBadMessage(MojoMessageHandle message,
reinterpret_cast<MessageForTransit*>(message)->ports_message();
if (ports_message.source_node() == ports::kInvalidNodeName) {
DVLOG(1) << "Received invalid message from unknown node.";
+ if (!default_process_error_callback_.is_null())
+ default_process_error_callback_.Run(std::string(error, error_num_bytes));
return MOJO_RESULT_OK;
}
diff --git a/chromium/mojo/edk/system/core.h b/chromium/mojo/edk/system/core.h
index b273a69e962..dc635a05608 100644
--- a/chromium/mojo/edk/system/core.h
+++ b/chromium/mojo/edk/system/core.h
@@ -51,6 +51,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle);
+ void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback);
+
// Called in the parent process any time a new child is launched.
void AddChild(base::ProcessHandle process_handle,
ScopedPlatformHandle platform_handle,
@@ -60,6 +62,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// Called in the parent process when a child process fails to launch.
void ChildLaunchFailed(const std::string& child_token);
+ // Called to connect to a peer process. This should be called only if there
+ // is no common ancestor for the processes involved within this mojo system.
+ // Both processes must call this function, each passing one end of a platform
+ // channel. This returns one end of a message pipe to each process.
+ ScopedMessagePipeHandle ConnectToPeerProcess(
+ ScopedPlatformHandle pipe_handle);
+
// Called in a child process exactly once during early initialization.
void InitChild(ScopedPlatformHandle platform_handle);
@@ -116,14 +125,6 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// may be called from any thread. Beware!
void RequestShutdown(const base::Closure& callback);
- // Watches on the given handle for the given signals, calling |callback| when
- // a signal is satisfied or when all signals become unsatisfiable. |callback|
- // must satisfy stringent requirements -- see |Awakable::Awake()| in
- // awakable.h. In particular, it must not call any Mojo system functions.
- MojoResult AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- const base::Callback<void(MojoResult)>& callback);
-
MojoResult SetProperty(MojoPropertyType type, const void* value);
// ---------------------------------------------------------------------------
@@ -298,6 +299,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// to access it.
std::unique_ptr<NodeController> node_controller_;
+ // The default callback to invoke, if any, when a process error is reported
+ // but cannot be associated with a specific process.
+ ProcessErrorCallback default_process_error_callback_;
+
base::Lock handles_lock_;
HandleTable handles_;
diff --git a/chromium/mojo/edk/system/core_unittest.cc b/chromium/mojo/edk/system/core_unittest.cc
index a25c7af3d08..33a7068f0d5 100644
--- a/chromium/mojo/edk/system/core_unittest.cc
+++ b/chromium/mojo/edk/system/core_unittest.cc
@@ -1243,30 +1243,6 @@ struct TestAsyncWaiter {
MojoResult result;
};
-TEST_F(CoreTest, AsyncWait) {
- TestAsyncWaiter waiter;
- MockHandleInfo info;
- MojoHandle h = CreateMockHandle(&info);
-
- ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->AsyncWait(h, MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&TestAsyncWaiter::Awake,
- base::Unretained(&waiter))));
- ASSERT_EQ(0u, info.GetAddedAwakableSize());
-
- info.AllowAddAwakable(true);
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->AsyncWait(h, MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&TestAsyncWaiter::Awake,
- base::Unretained(&waiter))));
- ASSERT_EQ(1u, info.GetAddedAwakableSize());
-
- ASSERT_FALSE(info.GetAddedAwakableAt(0)->Awake(MOJO_RESULT_BUSY, 0));
- ASSERT_EQ(MOJO_RESULT_BUSY, waiter.result);
-
- ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h));
-}
-
// TODO(vtl): Test |DuplicateBufferHandle()| and |MapBuffer()|.
} // namespace
diff --git a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc
index 23cb2e0368d..d5460cb4642 100644
--- a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc
+++ b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc
@@ -421,6 +421,7 @@ DataPipeConsumerDispatcher::Deserialize(const void* data,
dispatcher->bytes_available_ = state->bytes_available;
dispatcher->peer_closed_ = state->flags & kFlagPeerClosed;
dispatcher->InitializeNoLock();
+ dispatcher->UpdateSignalsStateNoLock();
}
return dispatcher;
diff --git a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc
index d056e7dbc83..8273c14d18f 100644
--- a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc
+++ b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc
@@ -137,9 +137,8 @@ MojoResult DataPipeProducerDispatcher::WriteData(const void* elements,
if (*num_bytes == 0)
return MOJO_RESULT_OK; // Nothing to do.
- bool all_or_none = flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE;
- uint32_t min_num_bytes_to_write = all_or_none ? *num_bytes : 0;
- if (min_num_bytes_to_write > options_.capacity_num_bytes) {
+ if ((flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) &&
+ (*num_bytes > available_capacity_)) {
// Don't return "should wait" since you can't wait for a specified amount of
// data.
return MOJO_RESULT_OUT_OF_RANGE;
@@ -403,6 +402,7 @@ DataPipeProducerDispatcher::Deserialize(const void* data,
dispatcher->available_capacity_ = state->available_capacity;
dispatcher->peer_closed_ = state->flags & kFlagPeerClosed;
dispatcher->InitializeNoLock();
+ dispatcher->UpdateSignalsStateNoLock();
}
return dispatcher;
diff --git a/chromium/mojo/edk/system/data_pipe_unittest.cc b/chromium/mojo/edk/system/data_pipe_unittest.cc
index 526444c6d58..32e661e7f52 100644
--- a/chromium/mojo/edk/system/data_pipe_unittest.cc
+++ b/chromium/mojo/edk/system/data_pipe_unittest.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/system/test_utils.h"
@@ -20,6 +21,7 @@
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/c/system/message_pipe.h"
+#include "mojo/public/cpp/system/watcher.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
@@ -797,7 +799,7 @@ TEST_F(DataPipeTest, AllOrNone) {
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
- // Try writing way too much.
+ // Try writing more than the total capacity of the pipe.
uint32_t num_bytes = 20u * sizeof(int32_t);
int32_t buffer[100];
Seq(0, arraysize(buffer), buffer);
@@ -832,12 +834,11 @@ TEST_F(DataPipeTest, AllOrNone) {
ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes));
ASSERT_EQ(5u * sizeof(int32_t), num_bytes);
- /* TODO(jam): enable if we end up observing max capacity
- // Too much.
+ // Try writing more than the available capacity of the pipe, but less than the
+ // total capacity.
num_bytes = 6u * sizeof(int32_t);
Seq(200, arraysize(buffer), buffer);
ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, WriteData(buffer, &num_bytes, true));
- */
// Try reading too much.
num_bytes = 11u * sizeof(int32_t);
@@ -1898,6 +1899,90 @@ TEST_F(DataPipeTest, CreateInChild) {
END_CHILD()
}
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(DataPipeStatusChangeInTransitClient,
+ DataPipeTest, parent) {
+ // This test verifies that peer closure is detectable through various
+ // mechanisms when it races with handle transfer.
+
+ MojoHandle handles[6];
+ EXPECT_EQ("o_O", ReadMessageWithHandles(parent, handles, 6));
+ MojoHandle* producers = &handles[0];
+ MojoHandle* consumers = &handles[3];
+
+ // Wait on producer 0 using MojoWait.
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoWait(producers[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_DEADLINE_INDEFINITE, nullptr));
+
+ // Wait on consumer 0 using MojoWait.
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoWait(consumers[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_DEADLINE_INDEFINITE, nullptr));
+
+ base::MessageLoop message_loop;
+
+ // Wait on producer 1 and consumer 1 using Watchers.
+ {
+ base::RunLoop run_loop;
+ int count = 0;
+ auto callback = base::Bind(
+ [] (base::RunLoop* loop, int* count, MojoResult result) {
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ if (++*count == 2)
+ loop->Quit();
+ },
+ &run_loop, &count);
+ Watcher producer_watcher, consumer_watcher;
+ producer_watcher.Start(
+ Handle(producers[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, callback);
+ consumer_watcher.Start(
+ Handle(consumers[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, callback);
+ run_loop.Run();
+ }
+
+ // Wait on producer 2 by polling with MojoWriteData.
+ MojoResult result;
+ do {
+ uint32_t num_bytes = 0;
+ result = MojoWriteData(
+ producers[2], nullptr, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ } while (result == MOJO_RESULT_OK);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+
+ // Wait on consumer 2 by polling with MojoReadData.
+ do {
+ char byte;
+ uint32_t num_bytes = 1;
+ result = MojoReadData(
+ consumers[2], &byte, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+ } while (result == MOJO_RESULT_SHOULD_WAIT);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+
+ for (size_t i = 0; i < 6; ++i)
+ CloseHandle(handles[i]);
+}
+
+TEST_F(DataPipeTest, StatusChangeInTransit) {
+ MojoHandle producers[6];
+ MojoHandle consumers[6];
+ for (size_t i = 0; i < 6; ++i)
+ CreateDataPipe(&producers[i], &consumers[i], 1);
+
+ RUN_CHILD_ON_PIPE(DataPipeStatusChangeInTransitClient, child)
+ MojoHandle handles[] = { producers[0], producers[1], producers[2],
+ consumers[3], consumers[4], consumers[5] };
+
+ // Send 3 producers and 3 consumers, and let their transfer race with their
+ // peers' closure.
+ WriteMessageWithHandles(child, "o_O", handles, 6);
+
+ for (size_t i = 0; i < 3; ++i)
+ CloseHandle(consumers[i]);
+ for (size_t i = 3; i < 6; ++i)
+ CloseHandle(producers[i]);
+ END_CHILD()
+}
+
#endif // !defined(OS_IOS)
} // namespace
diff --git a/chromium/mojo/edk/system/mach_port_relay.cc b/chromium/mojo/edk/system/mach_port_relay.cc
index ddd633c8a45..f05cf22a9a5 100644
--- a/chromium/mojo/edk/system/mach_port_relay.cc
+++ b/chromium/mojo/edk/system/mach_port_relay.cc
@@ -240,7 +240,7 @@ void MachPortRelay::RemoveObserver(Observer* observer) {
void MachPortRelay::OnReceivedTaskPort(base::ProcessHandle process) {
base::AutoLock locker(observers_lock_);
- for (const auto observer : observers_)
+ for (auto* observer : observers_)
observer->OnProcessReady(process);
}
diff --git a/chromium/mojo/edk/system/message_pipe_dispatcher.cc b/chromium/mojo/edk/system/message_pipe_dispatcher.cc
index 23e5a3fb47d..999869a172e 100644
--- a/chromium/mojo/edk/system/message_pipe_dispatcher.cc
+++ b/chromium/mojo/edk/system/message_pipe_dispatcher.cc
@@ -106,7 +106,7 @@ Dispatcher::Type MessagePipeDispatcher::GetType() const {
MojoResult MessagePipeDispatcher::Close() {
base::AutoLock lock(signal_lock_);
- DVLOG(1) << "Closing message pipe " << pipe_id_ << " endpoint " << endpoint_
+ DVLOG(2) << "Closing message pipe " << pipe_id_ << " endpoint " << endpoint_
<< " [port=" << port_.name() << "]";
return CloseNoLock();
}
@@ -141,7 +141,7 @@ MojoResult MessagePipeDispatcher::WriteMessage(
size_t num_bytes = message->num_bytes();
int rv = node_controller_->SendMessage(port_, message->TakePortsMessage());
- DVLOG(1) << "Sent message on pipe " << pipe_id_ << " endpoint " << endpoint_
+ DVLOG(4) << "Sent message on pipe " << pipe_id_ << " endpoint " << endpoint_
<< " [port=" << port_.name() << "; rv=" << rv
<< "; num_bytes=" << num_bytes << "]";
@@ -536,12 +536,12 @@ void MessagePipeDispatcher::OnPortStatusChanged() {
message_size = message.num_payload_bytes();
return false;
}, &unused);
- DVLOG(1) << "New message detected on message pipe " << pipe_id_
+ DVLOG(4) << "New message detected on message pipe " << pipe_id_
<< " endpoint " << endpoint_ << " [port=" << port_.name()
<< "; size=" << message_size << "]";
}
if (port_status.peer_closed) {
- DVLOG(1) << "Peer closure detected on message pipe " << pipe_id_
+ DVLOG(2) << "Peer closure detected on message pipe " << pipe_id_
<< " endpoint " << endpoint_ << " [port=" << port_.name() << "]";
}
}
diff --git a/chromium/mojo/edk/system/message_pipe_unittest.cc b/chromium/mojo/edk/system/message_pipe_unittest.cc
index fcfaeca1790..8f489508e92 100644
--- a/chromium/mojo/edk/system/message_pipe_unittest.cc
+++ b/chromium/mojo/edk/system/message_pipe_unittest.cc
@@ -706,6 +706,17 @@ TEST_F(FuseMessagePipeTest, FuseAfterPeerWriteAndClosure) {
EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
}
+TEST_F(MessagePipeTest, ClosePipesStressTest) {
+ // Stress test to exercise https://crbug.com/665869.
+ const size_t kNumPipes = 100000;
+ for (size_t i = 0; i < kNumPipes; ++i) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+ MojoClose(a);
+ MojoClose(b);
+ }
+}
+
} // namespace
} // namespace edk
} // namespace mojo
diff --git a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc
index 6e2c6f1866f..011d8249095 100644
--- a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc
+++ b/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc
@@ -18,6 +18,8 @@
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "build/build_config.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
@@ -29,6 +31,7 @@
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/c/system/types.h"
+#include "mojo/public/cpp/system/watcher.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -68,6 +71,16 @@ class MultiprocessMessagePipeTest : public test::MojoTestBase {
};
};
+class MultiprocessMessagePipeTestWithPeerSupport
+ : public MultiprocessMessagePipeTest,
+ public testing::WithParamInterface<test::MojoTestBase::LaunchType> {
+ protected:
+ void SetUp() override {
+ test::MojoTestBase::SetUp();
+ set_launch_type(GetParam());
+ }
+};
+
// For each message received, sends a reply message with the same contents
// repeated twice, until the other end is closed or it receives "quitquitquit"
// (which it doesn't reply to). It'll return the number of messages received,
@@ -116,7 +129,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(EchoEcho, MultiprocessMessagePipeTest, h) {
return rv;
}
-TEST_F(MultiprocessMessagePipeTest, Basic) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, Basic) {
RUN_CHILD_ON_PIPE(EchoEcho, h)
std::string hello("hello");
ASSERT_EQ(MOJO_RESULT_OK,
@@ -152,7 +165,7 @@ TEST_F(MultiprocessMessagePipeTest, Basic) {
END_CHILD_AND_EXPECT_EXIT_CODE(1 % 100);
}
-TEST_F(MultiprocessMessagePipeTest, QueueMessages) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, QueueMessages) {
static const size_t kNumMessages = 1001;
RUN_CHILD_ON_PIPE(EchoEcho, h)
for (size_t i = 0; i < kNumMessages; i++) {
@@ -415,7 +428,7 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
for (size_t i = 0; i < pipe_count; ++i) {
base::FilePath unused;
base::ScopedFILE fp(
- CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
+ CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused));
const std::string world("world");
CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size());
fflush(fp.get());
@@ -509,7 +522,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe, MultiprocessMessagePipeTest, h) {
return 0;
}
-TEST_F(MultiprocessMessagePipeTest, MessagePipePassing) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MessagePipePassing) {
RUN_CHILD_ON_PIPE(CheckMessagePipe, h)
MojoCreateSharedBufferOptions options;
options.struct_size = sizeof(options);
@@ -551,7 +564,7 @@ TEST_F(MultiprocessMessagePipeTest, MessagePipePassing) {
END_CHILD()
}
-TEST_F(MultiprocessMessagePipeTest, MessagePipeTwoPassing) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MessagePipeTwoPassing) {
RUN_CHILD_ON_PIPE(CheckMessagePipe, h)
MojoHandle mp1, mp2;
ASSERT_EQ(MOJO_RESULT_OK,
@@ -681,7 +694,7 @@ TEST_F(MultiprocessMessagePipeTest, DataPipeConsumer) {
END_CHILD();
}
-TEST_F(MultiprocessMessagePipeTest, CreateMessagePipe) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, CreateMessagePipe) {
MojoHandle p0, p1;
CreateMessagePipe(&p0, &p1);
VerifyTransmission(p0, p1, "hey man");
@@ -693,7 +706,7 @@ TEST_F(MultiprocessMessagePipeTest, CreateMessagePipe) {
CloseHandle(p1);
}
-TEST_F(MultiprocessMessagePipeTest, PassMessagePipeLocal) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, PassMessagePipeLocal) {
MojoHandle p0, p1;
CreateMessagePipe(&p0, &p1);
VerifyTransmission(p0, p1, "testing testing");
@@ -733,7 +746,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(ChannelEchoClient, MultiprocessMessagePipeTest,
return 0;
}
-TEST_F(MultiprocessMessagePipeTest, MultiprocessChannelPipe) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MultiprocessChannelPipe) {
RUN_CHILD_ON_PIPE(ChannelEchoClient, h)
VerifyEcho(h, "in an interstellar burst");
VerifyEcho(h, "i am back to save the universe");
@@ -758,7 +771,8 @@ DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceClient, MultiprocessMessagePipeTest,
return 0;
}
-TEST_F(MultiprocessMessagePipeTest, PassMessagePipeCrossProcess) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport,
+ PassMessagePipeCrossProcess) {
MojoHandle p0, p1;
CreateMessagePipe(&p0, &p1);
RUN_CHILD_ON_PIPE(EchoServiceClient, h)
@@ -815,7 +829,8 @@ DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceFactoryClient,
return 0;
}
-TEST_F(MultiprocessMessagePipeTest, PassMoarMessagePipesCrossProcess) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport,
+ PassMoarMessagePipesCrossProcess) {
MojoHandle echo_factory_proxy, echo_factory_request;
CreateMessagePipe(&echo_factory_proxy, &echo_factory_request);
@@ -860,7 +875,8 @@ TEST_F(MultiprocessMessagePipeTest, PassMoarMessagePipesCrossProcess) {
CloseHandle(echo_proxy_c);
}
-TEST_F(MultiprocessMessagePipeTest, ChannelPipesWithMultipleChildren) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport,
+ ChannelPipesWithMultipleChildren) {
RUN_CHILD_ON_PIPE(ChannelEchoClient, a)
RUN_CHILD_ON_PIPE(ChannelEchoClient, b)
VerifyEcho(a, "hello child 0");
@@ -890,7 +906,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingPongPipeClient,
EXPECT_EQ("quit", ReadMessage(h));
}
-TEST_F(MultiprocessMessagePipeTest, PingPongPipe) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, PingPongPipe) {
MojoHandle p0, p1;
CreateMessagePipe(&p0, &p1);
@@ -1096,11 +1112,12 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeer,
MojoHandle p;
EXPECT_EQ("foo", ReadMessageWithHandles(h, &p, 1));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- MOJO_DEADLINE_INDEFINITE, nullptr));
+ auto result = MojoWait(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_DEADLINE_INDEFINITE, nullptr);
+ EXPECT_EQ(MOJO_RESULT_OK, result);
}
-TEST_F(MultiprocessMessagePipeTest, SendPipeThenClosePeer) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, SendPipeThenClosePeer) {
RUN_CHILD_ON_PIPE(ReceivePipeWithClosedPeer, h)
MojoHandle a, b;
CreateMessagePipe(&a, &b);
@@ -1176,8 +1193,7 @@ TEST_F(MultiprocessMessagePipeTest,
END_CHILD()
}
-
-TEST_F(MultiprocessMessagePipeTest, SendClosePeerSend) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, SendClosePeerSend) {
MojoHandle a, b;
CreateMessagePipe(&a, &b);
@@ -1220,7 +1236,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteCloseSendPeerClient,
EXPECT_EQ("quit", ReadMessage(h));
}
-TEST_F(MultiprocessMessagePipeTest, WriteCloseSendPeer) {
+TEST_P(MultiprocessMessagePipeTestWithPeerSupport, WriteCloseSendPeer) {
MojoHandle pipe[2];
CreateMessagePipe(&pipe[0], &pipe[1]);
@@ -1281,6 +1297,64 @@ TEST_F(MultiprocessMessagePipeTest, BootstrapMessagePipeAsync) {
END_CHILD()
}
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MessagePipeStatusChangeInTransitClient,
+ MultiprocessMessagePipeTest, parent) {
+ // This test verifies that peer closure is detectable through various
+ // mechanisms when it races with handle transfer.
+ MojoHandle handles[4];
+ EXPECT_EQ("o_O", ReadMessageWithHandles(parent, handles, 4));
+
+ // Wait on handle 0 using MojoWait.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWait(handles[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_DEADLINE_INDEFINITE, nullptr));
+
+ base::MessageLoop message_loop;
+
+ // Wait on handle 1 using a Watcher.
+ {
+ base::RunLoop run_loop;
+ Watcher watcher;
+ watcher.Start(Handle(handles[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ base::Bind([] (base::RunLoop* loop, MojoResult result) {
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ loop->Quit();
+ }, &run_loop));
+ run_loop.Run();
+ }
+
+ // Wait on handle 2 by polling with MojoReadMessage.
+ MojoResult result;
+ do {
+ result = MojoReadMessage(handles[2], nullptr, nullptr, nullptr, nullptr,
+ MOJO_READ_MESSAGE_FLAG_NONE);
+ } while (result == MOJO_RESULT_SHOULD_WAIT);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+
+ // Wait on handle 3 by polling with MojoWriteMessage.
+ do {
+ result = MojoWriteMessage(handles[3], nullptr, 0, nullptr, 0,
+ MOJO_WRITE_MESSAGE_FLAG_NONE);
+ } while (result == MOJO_RESULT_OK);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+
+ for (size_t i = 0; i < 4; ++i)
+ CloseHandle(handles[i]);
+}
+
+TEST_F(MultiprocessMessagePipeTest, MessagePipeStatusChangeInTransit) {
+ MojoHandle local_handles[4];
+ MojoHandle sent_handles[4];
+ for (size_t i = 0; i < 4; ++i)
+ CreateMessagePipe(&local_handles[i], &sent_handles[i]);
+
+ RUN_CHILD_ON_PIPE(MessagePipeStatusChangeInTransitClient, child)
+ // Send 4 handles and let their transfer race with their peers' closure.
+ WriteMessageWithHandles(child, "o_O", sent_handles, 4);
+ for (size_t i = 0; i < 4; ++i)
+ CloseHandle(local_handles[i]);
+ END_CHILD()
+}
+
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(BadMessageClient, MultiprocessMessagePipeTest,
parent) {
MojoHandle pipe;
@@ -1345,7 +1419,13 @@ TEST_F(MultiprocessMessagePipeTest, NotifyBadMessage) {
EXPECT_NE(std::string::npos, first_process_error.find(kFirstErrorMessage));
EXPECT_NE(std::string::npos, second_process_error.find(kSecondErrorMessage));
}
-
+INSTANTIATE_TEST_CASE_P(
+ ,
+ MultiprocessMessagePipeTestWithPeerSupport,
+ testing::Values(test::MojoTestBase::LaunchType::CHILD,
+ test::MojoTestBase::LaunchType::PEER,
+ test::MojoTestBase::LaunchType::NAMED_CHILD,
+ test::MojoTestBase::LaunchType::NAMED_PEER));
} // namespace
} // namespace edk
} // namespace mojo
diff --git a/chromium/mojo/edk/system/node_channel.cc b/chromium/mojo/edk/system/node_channel.cc
index eb83f2e22e1..da9e0dbf25c 100644
--- a/chromium/mojo/edk/system/node_channel.cc
+++ b/chromium/mojo/edk/system/node_channel.cc
@@ -47,6 +47,7 @@ enum class MessageType : uint32_t {
#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
PORTS_MESSAGE_FROM_RELAY,
#endif
+ ACCEPT_PEER,
};
struct Header {
@@ -67,6 +68,12 @@ struct AcceptParentData {
ports::NodeName child_name;
};
+struct AcceptPeerData {
+ ports::NodeName token;
+ ports::NodeName peer_name;
+ ports::PortName port_name;
+};
+
// This message may include a process handle on plaforms that require it.
struct AddBrokerClientData {
ports::NodeName client_name;
@@ -282,6 +289,18 @@ void NodeChannel::AcceptParent(const ports::NodeName& token,
WriteChannelMessage(std::move(message));
}
+void NodeChannel::AcceptPeer(const ports::NodeName& sender_name,
+ const ports::NodeName& token,
+ const ports::PortName& port_name) {
+ AcceptPeerData* data;
+ Channel::MessagePtr message =
+ CreateMessage(MessageType::ACCEPT_PEER, sizeof(AcceptPeerData), 0, &data);
+ data->token = token;
+ data->peer_name = sender_name;
+ data->port_name = port_name;
+ WriteChannelMessage(std::move(message));
+}
+
void NodeChannel::AddBrokerClient(const ports::NodeName& client_name,
base::ProcessHandle process_handle) {
AddBrokerClientData* data;
@@ -503,7 +522,7 @@ void NodeChannel::OnChannelMessage(const void* payload,
if (payload_size <= sizeof(Header)) {
- delegate_->OnChannelError(remote_node_name_);
+ delegate_->OnChannelError(remote_node_name_, this);
return;
}
@@ -728,12 +747,22 @@ void NodeChannel::OnChannelMessage(const void* payload,
#endif // defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
+ case MessageType::ACCEPT_PEER: {
+ const AcceptPeerData* data;
+ if (GetMessagePayload(payload, payload_size, &data)) {
+ delegate_->OnAcceptPeer(remote_node_name_, data->token, data->peer_name,
+ data->port_name);
+ return;
+ }
+ break;
+ }
+
default:
break;
}
DLOG(ERROR) << "Received invalid message. Closing channel.";
- delegate_->OnChannelError(remote_node_name_);
+ delegate_->OnChannelError(remote_node_name_, this);
}
void NodeChannel::OnChannelError() {
@@ -746,7 +775,7 @@ void NodeChannel::OnChannelError() {
// to the name name after that destruction. So may a copy of
// |remote_node_name_| so it can be used if |this| becomes destroyed.
ports::NodeName node_name = remote_node_name_;
- delegate_->OnChannelError(node_name);
+ delegate_->OnChannelError(node_name, this);
}
#if defined(OS_MACOSX) && !defined(OS_IOS)
@@ -771,7 +800,6 @@ void NodeChannel::ProcessPendingMessagesWithMachPorts() {
pending_writes.swap(pending_write_messages_);
pending_relays.swap(pending_relay_messages_);
}
- DCHECK(pending_writes.empty() && pending_relays.empty());
while (!pending_writes.empty()) {
Channel::MessagePtr message = std::move(pending_writes.front());
diff --git a/chromium/mojo/edk/system/node_channel.h b/chromium/mojo/edk/system/node_channel.h
index 658553c6002..bbac6422a0c 100644
--- a/chromium/mojo/edk/system/node_channel.h
+++ b/chromium/mojo/edk/system/node_channel.h
@@ -76,8 +76,12 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
const ports::NodeName& source_node,
Channel::MessagePtr message) = 0;
#endif
-
- virtual void OnChannelError(const ports::NodeName& node) = 0;
+ virtual void OnAcceptPeer(const ports::NodeName& from_node,
+ const ports::NodeName& token,
+ const ports::NodeName& peer_name,
+ const ports::PortName& port_name) = 0;
+ virtual void OnChannelError(const ports::NodeName& node,
+ NodeChannel* channel) = 0;
#if defined(OS_MACOSX) && !defined(OS_IOS)
virtual MachPortRelay* GetMachPortRelay() = 0;
@@ -123,6 +127,9 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
const ports::NodeName& token);
void AcceptParent(const ports::NodeName& token,
const ports::NodeName& child_name);
+ void AcceptPeer(const ports::NodeName& sender_name,
+ const ports::NodeName& token,
+ const ports::PortName& port_name);
void AddBrokerClient(const ports::NodeName& client_name,
base::ProcessHandle process_handle);
void BrokerClientAdded(const ports::NodeName& client_name,
diff --git a/chromium/mojo/edk/system/node_controller.cc b/chromium/mojo/edk/system/node_controller.cc
index f40a0cf37d6..faab32b75c6 100644
--- a/chromium/mojo/edk/system/node_controller.cc
+++ b/chromium/mojo/edk/system/node_controller.cc
@@ -18,11 +18,14 @@
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "mojo/edk/embedder/embedder_internal.h"
+#include "mojo/edk/embedder/named_platform_channel_pair.h"
+#include "mojo/edk/embedder/named_platform_handle.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/system/broker.h"
#include "mojo/edk/system/broker_host.h"
#include "mojo/edk/system/core.h"
#include "mojo/edk/system/ports_message.h"
+#include "mojo/edk/system/request_context.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include "mojo/edk/system/mach_port_relay.h"
@@ -57,7 +60,7 @@ void RecordPeerCount(size_t count) {
// 8k is the maximum number of file descriptors allowed in Chrome.
UMA_HISTOGRAM_CUSTOM_COUNTS("Mojo.System.Node.ConnectedPeers",
static_cast<int32_t>(count),
- 0 /* min */,
+ 1 /* min */,
8000 /* max */,
50 /* bucket count */);
}
@@ -68,7 +71,7 @@ void RecordPendingChildCount(size_t count) {
// 8k is the maximum number of file descriptors allowed in Chrome.
UMA_HISTOGRAM_CUSTOM_COUNTS("Mojo.System.Node.PendingChildren",
static_cast<int32_t>(count),
- 0 /* min */,
+ 1 /* min */,
8000 /* max */,
50 /* bucket count */);
}
@@ -227,10 +230,9 @@ void NodeController::CloseChildPorts(const std::string& child_token) {
}
void NodeController::ConnectToParent(ScopedPlatformHandle platform_handle) {
-// TODO(amistry): Consider the need for a broker on Windows.
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL_SFI)
- // On posix, use the bootstrap channel for the broker and receive the node's
- // channel synchronously as the first message from the broker.
+#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI)
+ // Use the bootstrap channel for the broker and receive the node's channel
+ // synchronously as the first message from the broker.
base::ElapsedTimer timer;
broker_.reset(new Broker(std::move(platform_handle)));
platform_handle = broker_->GetParentPlatformHandle();
@@ -242,6 +244,7 @@ void NodeController::ConnectToParent(ScopedPlatformHandle platform_handle) {
// the broker was unable to negotiate a NodeChannel pipe. In this case we
// can cancel parent connection.
DVLOG(1) << "Cannot connect to invalid parent channel.";
+ CancelPendingPortMerges();
return;
}
#endif
@@ -253,6 +256,16 @@ void NodeController::ConnectToParent(ScopedPlatformHandle platform_handle) {
base::Passed(&platform_handle)));
}
+void NodeController::ConnectToPeer(ScopedPlatformHandle handle,
+ const ports::PortRef& port) {
+ ports::NodeName node_name;
+ GenerateRandomName(&node_name);
+ io_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&NodeController::ConnectToPeerOnIOThread,
+ base::Unretained(this), base::Passed(&handle),
+ node_name, port));
+}
+
void NodeController::SetPortObserver(
const ports::PortRef& port,
const scoped_refptr<PortObserver>& observer) {
@@ -309,6 +322,7 @@ void NodeController::MergePortIntoParent(const std::string& token,
}
scoped_refptr<NodeChannel> parent;
+ bool reject_merge = false;
{
// Hold |pending_port_merges_lock_| while getting |parent|. Otherwise,
// there is a race where the parent can be set, and |pending_port_merges_|
@@ -316,11 +330,21 @@ void NodeController::MergePortIntoParent(const std::string& token,
// |pending_port_merges_|.
base::AutoLock lock(pending_port_merges_lock_);
parent = GetParentChannel();
- if (!parent) {
+ if (reject_pending_merges_) {
+ reject_merge = true;
+ } else if (!parent) {
pending_port_merges_.push_back(std::make_pair(token, port));
return;
}
}
+ if (reject_merge) {
+ node_->ClosePort(port);
+ DVLOG(2) << "Rejecting port merge for token " << token
+ << " due to closed parent channel.";
+ AcceptIncomingMessages();
+ return;
+ }
+
parent->RequestPortMerge(port.name(), token);
}
@@ -333,7 +357,7 @@ int NodeController::MergeLocalPorts(const ports::PortRef& port0,
scoped_refptr<PlatformSharedBuffer> NodeController::CreateSharedBuffer(
size_t num_bytes) {
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL_SFI)
+#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI)
// Shared buffer creation failure is fatal, so always use the broker when we
// have one. This does mean that a non-root process that has children will use
// the broker for shared buffer creation even though that process is
@@ -369,19 +393,34 @@ void NodeController::ConnectToChildOnIOThread(
const ProcessErrorCallback& process_error_callback) {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL)
+#if !defined(OS_MACOSX) && !defined(OS_NACL)
PlatformChannelPair node_channel;
+ ScopedPlatformHandle server_handle = node_channel.PassServerHandle();
// BrokerHost owns itself.
- BrokerHost* broker_host = new BrokerHost(std::move(platform_handle));
- broker_host->SendChannel(node_channel.PassClientHandle());
- scoped_refptr<NodeChannel> channel = NodeChannel::Create(
- this, node_channel.PassServerHandle(), io_task_runner_,
- process_error_callback);
+ BrokerHost* broker_host =
+ new BrokerHost(process_handle, std::move(platform_handle));
+ bool channel_ok = broker_host->SendChannel(node_channel.PassClientHandle());
+
+#if defined(OS_WIN)
+ if (!channel_ok) {
+ // On Windows the above operation may fail if the channel is crossing a
+ // session boundary. In that case we fall back to a named pipe.
+ NamedPlatformChannelPair named_channel;
+ server_handle = named_channel.PassServerHandle();
+ broker_host->SendNamedChannel(named_channel.handle().name);
+ }
#else
+ CHECK(channel_ok);
+#endif // defined(OS_WIN)
+
+ scoped_refptr<NodeChannel> channel = NodeChannel::Create(
+ this, std::move(server_handle), io_task_runner_, process_error_callback);
+
+#else // !defined(OS_MACOSX) && !defined(OS_NACL)
scoped_refptr<NodeChannel> channel =
NodeChannel::Create(this, std::move(platform_handle), io_task_runner_,
process_error_callback);
-#endif
+#endif // !defined(OS_MACOSX) && !defined(OS_NACL)
// We set up the child channel with a temporary name so it can be identified
// as a pending child if it writes any messages to the channel. We may start
@@ -422,6 +461,21 @@ void NodeController::ConnectToParentOnIOThread(
bootstrap_parent_channel_->Start();
}
+void NodeController::ConnectToPeerOnIOThread(ScopedPlatformHandle handle,
+ ports::NodeName token,
+ ports::PortRef port) {
+ DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
+
+ scoped_refptr<NodeChannel> channel =
+ NodeChannel::Create(this, std::move(handle), io_task_runner_, {});
+ pending_peers_.insert({token, {channel, port}});
+
+ channel->SetRemoteNodeName(token);
+ channel->Start();
+
+ channel->AcceptPeer(name_, token, port.name());
+}
+
scoped_refptr<NodeChannel> NodeController::GetPeerChannel(
const ports::NodeName& name) {
base::AutoLock lock(peers_lock_);
@@ -494,7 +548,8 @@ void NodeController::AddPeer(const ports::NodeName& name,
}
}
-void NodeController::DropPeer(const ports::NodeName& name) {
+void NodeController::DropPeer(const ports::NodeName& name,
+ NodeChannel* channel) {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
{
@@ -541,10 +596,24 @@ void NodeController::DropPeer(const ports::NodeName& name) {
}
}
+ bool is_parent;
+ {
+ base::AutoLock lock(parent_lock_);
+ is_parent = (name == parent_name_ || channel == bootstrap_parent_channel_);
+ }
+
+ // If the error comes from the parent channel, we also need to cancel any
+ // port merge requests, so that errors can be propagated to the message
+ // pipes.
+ if (is_parent)
+ CancelPendingPortMerges();
+
for (const auto& port : ports_to_close)
node_->ClosePort(port);
node_->LostConnectionToNode(name);
+
+ AcceptIncomingMessages();
}
void NodeController::SendPeerMessage(const ports::NodeName& name,
@@ -631,6 +700,7 @@ void NodeController::AcceptIncomingMessages() {
messages_lock_.Release();
break;
}
+
// libstdc++'s deque creates an internal buffer on construction, even when
// the size is 0. So avoid creating it until it is necessary.
std::queue<ports::ScopedMessage> messages;
@@ -643,9 +713,25 @@ void NodeController::AcceptIncomingMessages() {
messages.pop();
}
}
+
AttemptShutdownIfRequested();
}
+void NodeController::ProcessIncomingMessages() {
+ RequestContext request_context(RequestContext::Source::SYSTEM);
+
+ {
+ base::AutoLock lock(messages_lock_);
+ // Allow a new incoming messages processing task to be posted. This can't be
+ // done after AcceptIncomingMessages() otherwise a message might be missed.
+ // Doing it here may result in at most two tasks existing at the same time;
+ // this running one, and one pending in the task runner.
+ incoming_messages_task_posted_ = false;
+ }
+
+ AcceptIncomingMessages();
+}
+
void NodeController::DropAllPeers() {
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
@@ -672,6 +758,7 @@ void NodeController::DropAllPeers() {
peers_.clear();
pending_children_.clear();
pending_peer_messages_.clear();
+ pending_peers_.clear();
}
for (const auto& peer : all_peers)
@@ -693,17 +780,41 @@ void NodeController::AllocMessage(size_t num_header_bytes,
void NodeController::ForwardMessage(const ports::NodeName& node,
ports::ScopedMessage message) {
DCHECK(message);
+ bool schedule_pump_task = false;
if (node == name_) {
// NOTE: We need to avoid re-entering the Node instance within
// ForwardMessage. Because ForwardMessage is only ever called
// (synchronously) in response to Node's ClosePort, SendMessage, or
// AcceptMessage, we flush the queue after calling any of those methods.
base::AutoLock lock(messages_lock_);
+ // |io_task_runner_| may be null in tests or processes that don't require
+ // multi-process Mojo.
+ schedule_pump_task = incoming_messages_.empty() && io_task_runner_ &&
+ !incoming_messages_task_posted_;
+ incoming_messages_task_posted_ |= schedule_pump_task;
incoming_messages_.emplace(std::move(message));
incoming_messages_flag_.Set(true);
} else {
SendPeerMessage(node, std::move(message));
}
+
+ if (schedule_pump_task) {
+ // Normally, the queue is processed after the action that added the local
+ // message is done (i.e. SendMessage, ClosePort, etc). However, it's also
+ // possible for a local message to be added as a result of a remote message,
+ // and OnChannelMessage() doesn't process this queue (although
+ // OnPortsMessage() does). There may also be other code paths, now or added
+ // in the future, which cause local messages to be added but don't process
+ // this message queue.
+ //
+ // Instead of adding a call to AcceptIncomingMessages() on every possible
+ // code path, post a task to the IO thread to process the queue. If the
+ // current call stack processes the queue, this may end up doing nothing.
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&NodeController::ProcessIncomingMessages,
+ base::Unretained(this)));
+ }
}
void NodeController::BroadcastMessage(ports::ScopedMessage message) {
@@ -740,14 +851,16 @@ void NodeController::OnAcceptChild(const ports::NodeName& from_node,
scoped_refptr<NodeChannel> parent;
{
base::AutoLock lock(parent_lock_);
- if (!bootstrap_parent_channel_ || parent_name_ != ports::kInvalidNodeName) {
- DLOG(ERROR) << "Unexpected AcceptChild message from " << from_node;
- DropPeer(from_node);
- return;
+ if (bootstrap_parent_channel_ && parent_name_ == ports::kInvalidNodeName) {
+ parent_name_ = parent_name;
+ parent = bootstrap_parent_channel_;
}
+ }
- parent_name_ = parent_name;
- parent = bootstrap_parent_channel_;
+ if (!parent) {
+ DLOG(ERROR) << "Unexpected AcceptChild message from " << from_node;
+ DropPeer(from_node, nullptr);
+ return;
}
parent->SetRemoteNodeName(parent_name);
@@ -769,7 +882,7 @@ void NodeController::OnAcceptParent(const ports::NodeName& from_node,
if (it == pending_children_.end() || token != from_node) {
DLOG(ERROR) << "Received unexpected AcceptParent message from "
<< from_node;
- DropPeer(from_node);
+ DropPeer(from_node, nullptr);
return;
}
@@ -826,7 +939,7 @@ void NodeController::OnAddBrokerClient(const ports::NodeName& from_node,
if (GetPeerChannel(client_name)) {
DLOG(ERROR) << "Ignoring AddBrokerClient for known client.";
- DropPeer(from_node);
+ DropPeer(from_node, nullptr);
return;
}
@@ -957,7 +1070,7 @@ void NodeController::OnPortsMessage(const ports::NodeName& from_node,
if (!ParsePortsMessage(channel_message.get(), &data, &num_data_bytes,
&num_header_bytes, &num_payload_bytes,
&num_ports_bytes)) {
- DropPeer(from_node);
+ DropPeer(from_node, nullptr);
return;
}
@@ -996,6 +1109,8 @@ void NodeController::OnRequestPortMerge(
int rv = node_->MergePorts(local_port, from_node, connector_port_name);
if (rv != ports::OK)
DLOG(ERROR) << "MergePorts failed: " << rv;
+
+ AcceptIncomingMessages();
}
void NodeController::OnRequestIntroduction(const ports::NodeName& from_node,
@@ -1006,7 +1121,7 @@ void NodeController::OnRequestIntroduction(const ports::NodeName& from_node,
if (from_node == name || name == ports::kInvalidNodeName || !requestor) {
DLOG(ERROR) << "Rejecting invalid OnRequestIntroduction message from "
<< from_node;
- DropPeer(from_node);
+ DropPeer(from_node, nullptr);
return;
}
@@ -1029,7 +1144,7 @@ void NodeController::OnIntroduce(const ports::NodeName& from_node,
if (!channel_handle.is_valid()) {
node_->LostConnectionToNode(name);
- DLOG(ERROR) << "Could not be introduced to peer " << name;
+ DVLOG(1) << "Could not be introduced to peer " << name;
base::AutoLock lock(peers_lock_);
pending_peer_messages_.erase(name);
return;
@@ -1052,13 +1167,13 @@ void NodeController::OnBroadcast(const ports::NodeName& from_node,
if (!ParsePortsMessage(message.get(), &data, &num_data_bytes,
&num_header_bytes, &num_payload_bytes,
&num_ports_bytes)) {
- DropPeer(from_node);
+ DropPeer(from_node, nullptr);
return;
}
// Broadcast messages must not contain ports.
if (num_ports_bytes > 0) {
- DropPeer(from_node);
+ DropPeer(from_node, nullptr);
return;
}
@@ -1083,7 +1198,7 @@ void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node,
if (GetBrokerChannel()) {
// Only the broker should be asked to relay a message.
LOG(ERROR) << "Non-broker refusing to relay message.";
- DropPeer(from_node);
+ DropPeer(from_node, nullptr);
return;
}
@@ -1144,7 +1259,7 @@ void NodeController::OnPortsMessageFromRelay(const ports::NodeName& from_node,
Channel::MessagePtr message) {
if (GetPeerChannel(from_node) != GetBrokerChannel()) {
LOG(ERROR) << "Refusing relayed message from non-broker node.";
- DropPeer(from_node);
+ DropPeer(from_node, nullptr);
return;
}
@@ -1152,9 +1267,44 @@ void NodeController::OnPortsMessageFromRelay(const ports::NodeName& from_node,
}
#endif
-void NodeController::OnChannelError(const ports::NodeName& from_node) {
+void NodeController::OnAcceptPeer(const ports::NodeName& from_node,
+ const ports::NodeName& token,
+ const ports::NodeName& peer_name,
+ const ports::PortName& port_name) {
+ DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
+
+ auto it = pending_peers_.find(from_node);
+ if (it == pending_peers_.end()) {
+ DLOG(ERROR) << "Received unexpected AcceptPeer message from " << from_node;
+ DropPeer(from_node, nullptr);
+ return;
+ }
+
+ scoped_refptr<NodeChannel> channel = it->second.first;
+ ports::PortRef local_port = it->second.second;
+ pending_peers_.erase(it);
+ DCHECK(channel);
+
+ // If the peer connection is a self connection (which is used in tests),
+ // drop the channel to it and skip straight to merging the ports.
+ if (name_ != peer_name) {
+ DVLOG(1) << "Node " << name_ << " accepted peer " << peer_name;
+
+ AddPeer(peer_name, channel, false /* start_channel */);
+ }
+
+ // We need to choose one side to initiate the port merge. It doesn't matter
+ // who does it as long as they don't both try. Simple solution: pick the one
+ // with the "smaller" port name.
+ if (local_port.name() < port_name) {
+ node()->MergePorts(local_port, peer_name, port_name);
+ }
+}
+
+void NodeController::OnChannelError(const ports::NodeName& from_node,
+ NodeChannel* channel) {
if (io_task_runner_->RunsTasksOnCurrentThread()) {
- DropPeer(from_node);
+ DropPeer(from_node, channel);
// DropPeer may have caused local port closures, so be sure to process any
// pending local messages.
AcceptIncomingMessages();
@@ -1162,7 +1312,7 @@ void NodeController::OnChannelError(const ports::NodeName& from_node) {
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&NodeController::OnChannelError, base::Unretained(this),
- from_node));
+ from_node, channel));
}
}
@@ -1180,6 +1330,21 @@ MachPortRelay* NodeController::GetMachPortRelay() {
}
#endif
+void NodeController::CancelPendingPortMerges() {
+ std::vector<ports::PortRef> ports_to_close;
+
+ {
+ base::AutoLock lock(pending_port_merges_lock_);
+ reject_pending_merges_ = true;
+ for (const auto& port : pending_port_merges_)
+ ports_to_close.push_back(port.second);
+ pending_port_merges_.clear();
+ }
+
+ for (const auto& port : ports_to_close)
+ node_->ClosePort(port);
+}
+
void NodeController::DestroyOnIOThreadShutdown() {
destroy_on_io_thread_shutdown_ = true;
}
diff --git a/chromium/mojo/edk/system/node_controller.h b/chromium/mojo/edk/system/node_controller.h
index d0f3d6a7763..8692bd78787 100644
--- a/chromium/mojo/edk/system/node_controller.h
+++ b/chromium/mojo/edk/system/node_controller.h
@@ -85,6 +85,10 @@ class NodeController : public ports::NodeDelegate,
// handshake.
void ConnectToParent(ScopedPlatformHandle platform_handle);
+ // Connects this node to a peer node. On success, |port| will be merged with
+ // the corresponding port in the peer node.
+ void ConnectToPeer(ScopedPlatformHandle handle, const ports::PortRef& port);
+
// Sets a port's observer. If |observer| is null the port's current observer
// is removed.
void SetPortObserver(const ports::PortRef& port,
@@ -146,6 +150,10 @@ class NodeController : public ports::NodeDelegate,
const ProcessErrorCallback& process_error_callback);
void ConnectToParentOnIOThread(ScopedPlatformHandle platform_handle);
+ void ConnectToPeerOnIOThread(ScopedPlatformHandle handle,
+ ports::NodeName token,
+ ports::PortRef port);
+
scoped_refptr<NodeChannel> GetPeerChannel(const ports::NodeName& name);
scoped_refptr<NodeChannel> GetParentChannel();
scoped_refptr<NodeChannel> GetBrokerChannel();
@@ -153,10 +161,11 @@ class NodeController : public ports::NodeDelegate,
void AddPeer(const ports::NodeName& name,
scoped_refptr<NodeChannel> channel,
bool start_channel);
- void DropPeer(const ports::NodeName& name);
+ void DropPeer(const ports::NodeName& name, NodeChannel* channel);
void SendPeerMessage(const ports::NodeName& name,
ports::ScopedMessage message);
void AcceptIncomingMessages();
+ void ProcessIncomingMessages();
void DropAllPeers();
// ports::NodeDelegate:
@@ -205,11 +214,21 @@ class NodeController : public ports::NodeDelegate,
const ports::NodeName& source_node,
Channel::MessagePtr message) override;
#endif
- void OnChannelError(const ports::NodeName& from_node) override;
+ void OnAcceptPeer(const ports::NodeName& from_node,
+ const ports::NodeName& token,
+ const ports::NodeName& peer_name,
+ const ports::PortName& port_name) override;
+ void OnChannelError(const ports::NodeName& from_node,
+ NodeChannel* channel) override;
#if defined(OS_MACOSX) && !defined(OS_IOS)
MachPortRelay* GetMachPortRelay() override;
#endif
+ // Cancels all pending port merges. These are merges which are supposed to
+ // be requested from the parent ASAP, and they may be cancelled if the
+ // connection to the parent is broken or never established.
+ void CancelPendingPortMerges();
+
// Marks this NodeController for destruction when the IO thread shuts down.
// This is used in case Core is torn down before the IO thread. Must only be
// called on the IO thread.
@@ -245,12 +264,16 @@ class NodeController : public ports::NodeDelegate,
// have one yet :(
std::unordered_map<ports::NodeName, std::string> pending_child_tokens_;
- // Guards |pending_port_merges_|.
+ // Guards |pending_port_merges_| and |reject_pending_merges_|.
base::Lock pending_port_merges_lock_;
// A set of port merge requests awaiting parent connection.
std::vector<std::pair<std::string, ports::PortRef>> pending_port_merges_;
+ // Indicates that new merge requests should be rejected because the parent has
+ // disconnected.
+ bool reject_pending_merges_ = false;
+
// Guards |parent_name_| and |bootstrap_parent_channel_|.
base::Lock parent_lock_;
@@ -274,9 +297,12 @@ class NodeController : public ports::NodeDelegate,
std::unordered_map<ports::NodeName, OutgoingMessageQueue>
pending_relay_messages_;
- // Guards |incoming_messages_|.
+ // Guards |incoming_messages_| and |incoming_messages_task_posted_|.
base::Lock messages_lock_;
std::queue<ports::ScopedMessage> incoming_messages_;
+ // Ensures that there is only one incoming messages task posted to the IO
+ // thread.
+ bool incoming_messages_task_posted_ = false;
// Flag to fast-path checking |incoming_messages_|.
AtomicFlag incoming_messages_flag_;
@@ -296,12 +322,17 @@ class NodeController : public ports::NodeDelegate,
// Channels to children during handshake.
NodeMap pending_children_;
+ using PeerNodeMap =
+ std::unordered_map<ports::NodeName,
+ std::pair<scoped_refptr<NodeChannel>, ports::PortRef>>;
+ PeerNodeMap pending_peers_;
+
// Indicates whether this object should delete itself on IO thread shutdown.
// Must only be accessed from the IO thread.
bool destroy_on_io_thread_shutdown_ = false;
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL_SFI)
- // Broker for sync shared buffer creation (non-Mac posix-only) in children.
+#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI)
+ // Broker for sync shared buffer creation in children.
std::unique_ptr<Broker> broker_;
#endif
diff --git a/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc
index ad6dc381659..7a942622b0b 100644
--- a/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc
+++ b/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc
@@ -28,7 +28,7 @@ TEST(PlatformHandleDispatcherTest, Basic) {
base::FilePath unused;
base::ScopedFILE fp(
- CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
+ CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused));
ASSERT_TRUE(fp);
EXPECT_EQ(sizeof(kHelloWorld),
fwrite(kHelloWorld, 1, sizeof(kHelloWorld), fp.get()));
@@ -70,7 +70,7 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
base::FilePath unused;
base::ScopedFILE fp(
- CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
+ CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused));
EXPECT_EQ(sizeof(kFooBar), fwrite(kFooBar, 1, sizeof(kFooBar), fp.get()));
scoped_refptr<PlatformHandleDispatcher> dispatcher =
diff --git a/chromium/mojo/edk/system/ports/message_queue.cc b/chromium/mojo/edk/system/ports/message_queue.cc
index 0a012f581df..ef2e9400989 100644
--- a/chromium/mojo/edk/system/ports/message_queue.cc
+++ b/chromium/mojo/edk/system/ports/message_queue.cc
@@ -35,7 +35,7 @@ MessageQueue::~MessageQueue() {
size_t num_leaked_ports = 0;
for (const auto& message : heap_)
num_leaked_ports += message->num_ports();
- DLOG_IF(WARNING, num_leaked_ports > 0)
+ DVLOG_IF(1, num_leaked_ports > 0)
<< "Leaking " << num_leaked_ports << " ports in unreceived messages";
#endif
}
diff --git a/chromium/mojo/edk/system/ports/node.cc b/chromium/mojo/edk/system/ports/node.cc
index c7f42f6f8b3..d6e2767988c 100644
--- a/chromium/mojo/edk/system/ports/node.cc
+++ b/chromium/mojo/edk/system/ports/node.cc
@@ -8,6 +8,7 @@
#include <utility>
+#include "base/atomicops.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
@@ -272,7 +273,7 @@ int Node::GetMessageIf(const PortRef& port_ref,
ScopedMessage* message) {
*message = nullptr;
- DVLOG(2) << "GetMessageIf for " << port_ref.name() << "@" << name_;
+ DVLOG(4) << "GetMessageIf for " << port_ref.name() << "@" << name_;
Port* port = port_ref.port();
{
@@ -428,7 +429,7 @@ int Node::OnUserMessage(ScopedMessage message) {
ports_buf << message->ports()[i];
}
- DVLOG(2) << "AcceptMessage " << event->sequence_num
+ DVLOG(4) << "AcceptMessage " << event->sequence_num
<< " [ports=" << ports_buf.str() << "] at "
<< port_name << "@" << name_;
#endif
@@ -808,6 +809,11 @@ scoped_refptr<Port> Node::GetPort_Locked(const PortName& port_name) {
if (iter == ports_.end())
return nullptr;
+#if defined(OS_ANDROID) && defined(ARCH_CPU_ARM64)
+ // Workaround for https://crbug.com/665869.
+ base::subtle::MemoryBarrier();
+#endif
+
return iter->second;
}
@@ -1078,7 +1084,7 @@ int Node::WillSendMessage_Locked(const LockedPort& port,
}
#if DCHECK_IS_ON()
- DVLOG(2) << "Sending message "
+ DVLOG(4) << "Sending message "
<< GetEventData<UserEventData>(*message)->sequence_num
<< " [ports=" << ports_buf.str() << "]"
<< " from " << port_name << "@" << name_
diff --git a/chromium/mojo/edk/system/waiter.h b/chromium/mojo/edk/system/waiter.h
index 9e286d36d8b..897ecbe45a9 100644
--- a/chromium/mojo/edk/system/waiter.h
+++ b/chromium/mojo/edk/system/waiter.h
@@ -62,8 +62,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Waiter final : public Awakable {
bool Awake(MojoResult result, uintptr_t context) override;
private:
- base::ConditionVariable cv_; // Associated to |lock_|.
base::Lock lock_; // Protects the following members.
+ base::ConditionVariable cv_; // Associated to |lock_|.
#if DCHECK_IS_ON()
bool initialized_;
#endif
diff --git a/chromium/mojo/edk/system/watch_unittest.cc b/chromium/mojo/edk/system/watch_unittest.cc
index 7b3137f97c4..ec28d94f805 100644
--- a/chromium/mojo/edk/system/watch_unittest.cc
+++ b/chromium/mojo/edk/system/watch_unittest.cc
@@ -5,8 +5,11 @@
#include <functional>
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "mojo/edk/system/request_context.h"
#include "mojo/edk/test/mojo_test_base.h"
#include "mojo/public/c/system/functions.h"
@@ -29,7 +32,7 @@ class WatchHelper {
using Callback =
std::function<void(MojoResult result, MojoHandleSignalsState state)>;
- WatchHelper() {}
+ WatchHelper() : task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
~WatchHelper() {
CHECK(!watching_);
}
@@ -55,27 +58,32 @@ class WatchHelper {
watching_ = false;
}
- void ExpectSystemNotifications() { expect_system_notifications_ = true; }
-
private:
static void OnNotify(uintptr_t context,
MojoResult result,
MojoHandleSignalsState state,
MojoWatchNotificationFlags flags) {
WatchHelper* watcher = reinterpret_cast<WatchHelper*>(context);
+ watcher->task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&NotifyOnMainThread, context, result, state, flags));
+ }
+
+ static void NotifyOnMainThread(uintptr_t context,
+ MojoResult result,
+ MojoHandleSignalsState state,
+ MojoWatchNotificationFlags flags) {
+ WatchHelper* watcher = reinterpret_cast<WatchHelper*>(context);
CHECK(watcher->watching_);
if (result == MOJO_RESULT_CANCELLED)
watcher->watching_ = false;
- CHECK_EQ(flags, watcher->expect_system_notifications_?
- MOJO_WATCH_NOTIFICATION_FLAG_FROM_SYSTEM :
- MOJO_WATCH_NOTIFICATION_FLAG_NONE);
watcher->callback_(result, state);
}
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
bool watching_ = false;
MojoHandle handle_;
Callback callback_;
- bool expect_system_notifications_ = false;
DISALLOW_COPY_AND_ASSIGN(WatchHelper);
};
@@ -249,6 +257,7 @@ TEST_F(WatchTest, WatchWhileSatisfied) {
WriteMessage(a, "hey");
bool signaled = false;
WatchHelper b_watcher;
+ base::RunLoop loop;
b_watcher.Watch(
b, MOJO_HANDLE_SIGNAL_READABLE,
[&] (MojoResult result, MojoHandleSignalsState state) {
@@ -256,7 +265,9 @@ TEST_F(WatchTest, WatchWhileSatisfied) {
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE,
state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
signaled = true;
+ loop.Quit();
});
+ loop.Run();
EXPECT_TRUE(signaled);
b_watcher.Cancel();
@@ -419,6 +430,7 @@ TEST_F(WatchTest, NestedCancellation) {
CreateMessagePipe(&a, &b);
CreateMessagePipe(&c, &d);
+ base::RunLoop loop;
bool a_watcher_run = false;
WatchHelper a_watcher;
a_watcher.Watch(
@@ -438,8 +450,9 @@ TEST_F(WatchTest, NestedCancellation) {
// ...but this should prevent that notification from dispatching because
// |a_watcher| is now cancelled.
a_watcher.Cancel();
+
+ loop.Quit();
});
- c_watcher.ExpectSystemNotifications();
{
// Force "system" notifications for the synchronous behavior required to
@@ -451,6 +464,8 @@ TEST_F(WatchTest, NestedCancellation) {
CloseHandle(d);
}
+ loop.Run();
+
EXPECT_FALSE(a_watcher.is_watching());
EXPECT_FALSE(a_watcher_run);
diff --git a/chromium/mojo/edk/test/BUILD.gn b/chromium/mojo/edk/test/BUILD.gn
index cd56fb8e398..ebacc646c23 100644
--- a/chromium/mojo/edk/test/BUILD.gn
+++ b/chromium/mojo/edk/test/BUILD.gn
@@ -4,7 +4,7 @@
import("//testing/test.gni")
-source_set("test_support") {
+static_library("test_support") {
testonly = true
sources = [
"mojo_test_base.cc",
@@ -73,7 +73,7 @@ source_set("run_all_perftests") {
}
}
-source_set("test_support_impl") {
+static_library("test_support_impl") {
testonly = true
deps = [
"//base",
diff --git a/chromium/mojo/message_pump/BUILD.gn b/chromium/mojo/message_pump/BUILD.gn
deleted file mode 100644
index e1ae4af28e3..00000000000
--- a/chromium/mojo/message_pump/BUILD.gn
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2015 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("//testing/test.gni")
-
-component("message_pump") {
- sources = [
- "handle_watcher.cc",
- "handle_watcher.h",
- "message_pump_mojo.cc",
- "message_pump_mojo.h",
- "message_pump_mojo_handler.h",
- "time_helper.cc",
- "time_helper.h",
- ]
-
- defines = [ "MOJO_MESSAGE_PUMP_IMPLEMENTATION" ]
-
- public_deps = [
- "//base",
- "//mojo/public/cpp/system",
- ]
-}
diff --git a/chromium/mojo/message_pump/handle_watcher.cc b/chromium/mojo/message_pump/handle_watcher.cc
deleted file mode 100644
index 7f6f56165da..00000000000
--- a/chromium/mojo/message_pump/handle_watcher.cc
+++ /dev/null
@@ -1,480 +0,0 @@
-// 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/message_pump/handle_watcher.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <map>
-
-#include "base/atomic_sequence_num.h"
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "mojo/message_pump/message_pump_mojo.h"
-#include "mojo/message_pump/message_pump_mojo_handler.h"
-#include "mojo/message_pump/time_helper.h"
-#include "mojo/public/c/system/message_pipe.h"
-
-namespace mojo {
-namespace common {
-
-typedef int WatcherID;
-
-namespace {
-
-const char kWatcherThreadName[] = "handle-watcher-thread";
-
-base::TimeTicks MojoDeadlineToTimeTicks(MojoDeadline deadline) {
- return deadline == MOJO_DEADLINE_INDEFINITE ? base::TimeTicks() :
- internal::NowTicks() + base::TimeDelta::FromMicroseconds(deadline);
-}
-
-// Tracks the data for a single call to Start().
-struct WatchData {
- WatchData()
- : id(0), handle_signals(MOJO_HANDLE_SIGNAL_NONE), task_runner(NULL) {}
-
- WatcherID id;
- Handle handle;
- MojoHandleSignals handle_signals;
- base::TimeTicks deadline;
- base::Callback<void(MojoResult)> callback;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner;
-};
-
-// WatcherBackend --------------------------------------------------------------
-
-// WatcherBackend is responsible for managing the requests and interacting with
-// MessagePumpMojo. All access (outside of creation/destruction) is done on the
-// thread WatcherThreadManager creates.
-class WatcherBackend : public MessagePumpMojoHandler {
- public:
- WatcherBackend();
- ~WatcherBackend() override;
-
- void StartWatching(const WatchData& data);
- void StopWatching(WatcherID watcher_id);
-
- private:
- typedef std::map<Handle, WatchData> HandleToWatchDataMap;
-
- // Invoked when a handle needs to be removed and notified.
- void RemoveAndNotify(const Handle& handle, MojoResult result);
-
- // Searches through |handle_to_data_| for |watcher_id|. Returns true if found
- // and sets |handle| to the Handle. Returns false if not a known id.
- bool GetMojoHandleByWatcherID(WatcherID watcher_id, Handle* handle) const;
-
- // MessagePumpMojoHandler overrides:
- void OnHandleReady(const Handle& handle) override;
- void OnHandleError(const Handle& handle, MojoResult result) override;
-
- // Maps from assigned id to WatchData.
- HandleToWatchDataMap handle_to_data_;
-
- DISALLOW_COPY_AND_ASSIGN(WatcherBackend);
-};
-
-WatcherBackend::WatcherBackend() {
-}
-
-WatcherBackend::~WatcherBackend() {
-}
-
-void WatcherBackend::StartWatching(const WatchData& data) {
- RemoveAndNotify(data.handle, MOJO_RESULT_CANCELLED);
-
- DCHECK_EQ(0u, handle_to_data_.count(data.handle));
-
- handle_to_data_[data.handle] = data;
- MessagePumpMojo::current()->AddHandler(this, data.handle,
- data.handle_signals,
- data.deadline);
-}
-
-void WatcherBackend::StopWatching(WatcherID watcher_id) {
- // Because of the thread hop it is entirely possible to get here and not
- // have a valid handle registered for |watcher_id|.
- Handle handle;
- if (!GetMojoHandleByWatcherID(watcher_id, &handle))
- return;
-
- handle_to_data_.erase(handle);
- MessagePumpMojo::current()->RemoveHandler(handle);
-}
-
-void WatcherBackend::RemoveAndNotify(const Handle& handle,
- MojoResult result) {
- if (handle_to_data_.count(handle) == 0)
- return;
-
- const WatchData data(handle_to_data_[handle]);
- handle_to_data_.erase(handle);
- MessagePumpMojo::current()->RemoveHandler(handle);
-
- data.task_runner->PostTask(FROM_HERE, base::Bind(data.callback, result));
-}
-
-bool WatcherBackend::GetMojoHandleByWatcherID(WatcherID watcher_id,
- Handle* handle) const {
- for (HandleToWatchDataMap::const_iterator i = handle_to_data_.begin();
- i != handle_to_data_.end(); ++i) {
- if (i->second.id == watcher_id) {
- *handle = i->second.handle;
- return true;
- }
- }
- return false;
-}
-
-void WatcherBackend::OnHandleReady(const Handle& handle) {
- RemoveAndNotify(handle, MOJO_RESULT_OK);
-}
-
-void WatcherBackend::OnHandleError(const Handle& handle, MojoResult result) {
- RemoveAndNotify(handle, result);
-}
-
-// WatcherThreadManager --------------------------------------------------------
-
-// WatcherThreadManager manages the background thread that listens for handles
-// to be ready. All requests are handled by WatcherBackend.
-class WatcherThreadManager {
- public:
- ~WatcherThreadManager();
-
- // Returns the shared instance.
- static WatcherThreadManager* GetInstance();
-
- // Starts watching the requested handle. Returns a unique ID that is used to
- // stop watching the handle. When the handle is ready |callback| is notified
- // on the thread StartWatching() was invoked on.
- // This may be invoked on any thread.
- WatcherID StartWatching(const Handle& handle,
- MojoHandleSignals handle_signals,
- base::TimeTicks deadline,
- const base::Callback<void(MojoResult)>& callback);
-
- // Stops watching a handle.
- // This may be invoked on any thread.
- void StopWatching(WatcherID watcher_id);
-
- private:
- enum RequestType {
- REQUEST_START,
- REQUEST_STOP,
- };
-
- // See description of |requests_| for details.
- struct RequestData {
- RequestData() : type(REQUEST_START), stop_id(0) {}
-
- RequestType type;
- WatchData start_data;
- WatcherID stop_id;
- };
-
- typedef std::vector<RequestData> Requests;
-
- friend struct base::DefaultSingletonTraits<WatcherThreadManager>;
-
- WatcherThreadManager();
-
- // Schedules a request on the background thread. See |requests_| for details.
- void AddRequest(const RequestData& data);
-
- // Processes requests added to |requests_|. This is invoked on the backend
- // thread.
- void ProcessRequestsOnBackendThread();
-
- base::Thread thread_;
-
- base::AtomicSequenceNumber watcher_id_generator_;
-
- WatcherBackend backend_;
-
- // Protects |requests_|.
- base::Lock lock_;
-
- // Start/Stop result in adding a RequestData to |requests_| (protected by
- // |lock_|). When the background thread wakes up it processes the requests.
- Requests requests_;
-
- DISALLOW_COPY_AND_ASSIGN(WatcherThreadManager);
-};
-
-WatcherThreadManager::~WatcherThreadManager() {
- thread_.Stop();
-}
-
-WatcherThreadManager* WatcherThreadManager::GetInstance() {
- return base::Singleton<WatcherThreadManager>::get();
-}
-
-WatcherID WatcherThreadManager::StartWatching(
- const Handle& handle,
- MojoHandleSignals handle_signals,
- base::TimeTicks deadline,
- const base::Callback<void(MojoResult)>& callback) {
- RequestData request_data;
- request_data.type = REQUEST_START;
- request_data.start_data.id = watcher_id_generator_.GetNext();
- request_data.start_data.handle = handle;
- request_data.start_data.callback = callback;
- request_data.start_data.handle_signals = handle_signals;
- request_data.start_data.deadline = deadline;
- request_data.start_data.task_runner = base::ThreadTaskRunnerHandle::Get();
- AddRequest(request_data);
- return request_data.start_data.id;
-}
-
-void WatcherThreadManager::StopWatching(WatcherID watcher_id) {
- // Handle the case of StartWatching() followed by StopWatching() before
- // |thread_| woke up.
- {
- base::AutoLock auto_lock(lock_);
- for (Requests::iterator i = requests_.begin(); i != requests_.end(); ++i) {
- if (i->type == REQUEST_START && i->start_data.id == watcher_id) {
- // Watcher ids are not reused, so if we find it we can stop.
- requests_.erase(i);
- return;
- }
- }
- }
-
- RequestData request_data;
- request_data.type = REQUEST_STOP;
- request_data.stop_id = watcher_id;
- AddRequest(request_data);
-}
-
-void WatcherThreadManager::AddRequest(const RequestData& data) {
- {
- base::AutoLock auto_lock(lock_);
- const bool was_empty = requests_.empty();
- requests_.push_back(data);
- if (!was_empty)
- return;
- }
-
- // We outlive |thread_|, so it's safe to use Unretained() here.
- thread_.task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&WatcherThreadManager::ProcessRequestsOnBackendThread,
- base::Unretained(this)));
-}
-
-void WatcherThreadManager::ProcessRequestsOnBackendThread() {
- DCHECK(thread_.task_runner()->BelongsToCurrentThread());
-
- Requests requests;
- {
- base::AutoLock auto_lock(lock_);
- requests_.swap(requests);
- }
- for (size_t i = 0; i < requests.size(); ++i) {
- if (requests[i].type == REQUEST_START) {
- backend_.StartWatching(requests[i].start_data);
- } else {
- backend_.StopWatching(requests[i].stop_id);
- }
- }
-}
-
-WatcherThreadManager::WatcherThreadManager()
- : thread_(kWatcherThreadName) {
- base::Thread::Options thread_options;
- thread_options.message_pump_factory = base::Bind(&MessagePumpMojo::Create);
- thread_.StartWithOptions(thread_options);
-}
-
-} // namespace
-
-// HandleWatcher::StateBase and subclasses -------------------------------------
-
-// The base class of HandleWatcher's state. Owns the user's callback and
-// monitors the current thread's MessageLoop to know when to force the callback
-// to run (with an error) even though the pipe hasn't been signaled yet.
-class HandleWatcher::StateBase : public base::MessageLoop::DestructionObserver {
- public:
- StateBase(HandleWatcher* watcher,
- const base::Callback<void(MojoResult)>& callback)
- : watcher_(watcher),
- callback_(callback),
- got_ready_(false) {
- base::MessageLoop::current()->AddDestructionObserver(this);
- }
-
- ~StateBase() override {
- base::MessageLoop::current()->RemoveDestructionObserver(this);
- }
-
- protected:
- void NotifyHandleReady(MojoResult result) {
- got_ready_ = true;
- NotifyAndDestroy(result);
- }
-
- bool got_ready() const { return got_ready_; }
-
- private:
- void WillDestroyCurrentMessageLoop() override {
- // The current thread is exiting. Simulate a watch error.
- NotifyAndDestroy(MOJO_RESULT_ABORTED);
- }
-
- void NotifyAndDestroy(MojoResult result) {
- base::Callback<void(MojoResult)> callback = callback_;
- watcher_->Stop(); // Destroys |this|.
-
- callback.Run(result);
- }
-
- HandleWatcher* watcher_;
- base::Callback<void(MojoResult)> callback_;
-
- // Have we been notified that the handle is ready?
- bool got_ready_;
-
- DISALLOW_COPY_AND_ASSIGN(StateBase);
-};
-
-// If the thread on which HandleWatcher is used runs MessagePumpMojo,
-// SameThreadWatchingState is used to directly watch the handle on the same
-// thread.
-class HandleWatcher::SameThreadWatchingState : public StateBase,
- public MessagePumpMojoHandler {
- public:
- SameThreadWatchingState(HandleWatcher* watcher,
- const Handle& handle,
- MojoHandleSignals handle_signals,
- MojoDeadline deadline,
- const base::Callback<void(MojoResult)>& callback)
- : StateBase(watcher, callback),
- handle_(handle) {
- DCHECK(MessagePumpMojo::IsCurrent());
-
- MessagePumpMojo::current()->AddHandler(
- this, handle, handle_signals, MojoDeadlineToTimeTicks(deadline));
- }
-
- ~SameThreadWatchingState() override {
- if (!got_ready())
- MessagePumpMojo::current()->RemoveHandler(handle_);
- }
-
- private:
- // MessagePumpMojoHandler overrides:
- void OnHandleReady(const Handle& handle) override {
- StopWatchingAndNotifyReady(handle, MOJO_RESULT_OK);
- }
-
- void OnHandleError(const Handle& handle, MojoResult result) override {
- StopWatchingAndNotifyReady(handle, result);
- }
-
- void StopWatchingAndNotifyReady(const Handle& handle, MojoResult result) {
- DCHECK_EQ(handle.value(), handle_.value());
- MessagePumpMojo::current()->RemoveHandler(handle_);
- NotifyHandleReady(result);
- }
-
- Handle handle_;
-
- DISALLOW_COPY_AND_ASSIGN(SameThreadWatchingState);
-};
-
-// If the thread on which HandleWatcher is used runs a message pump different
-// from MessagePumpMojo, SecondaryThreadWatchingState is used to watch the
-// handle on the handle watcher thread.
-class HandleWatcher::SecondaryThreadWatchingState : public StateBase {
- public:
- SecondaryThreadWatchingState(HandleWatcher* watcher,
- const Handle& handle,
- MojoHandleSignals handle_signals,
- MojoDeadline deadline,
- const base::Callback<void(MojoResult)>& callback)
- : StateBase(watcher, callback),
- weak_factory_(this) {
- watcher_id_ = WatcherThreadManager::GetInstance()->StartWatching(
- handle,
- handle_signals,
- MojoDeadlineToTimeTicks(deadline),
- base::Bind(&SecondaryThreadWatchingState::NotifyHandleReady,
- weak_factory_.GetWeakPtr()));
- }
-
- ~SecondaryThreadWatchingState() override {
- // If we've been notified the handle is ready (|got_ready()| is true) then
- // the watch has been implicitly removed by
- // WatcherThreadManager/MessagePumpMojo and we don't have to call
- // StopWatching(). To do so would needlessly entail posting a task and
- // blocking until the background thread services it.
- if (!got_ready())
- WatcherThreadManager::GetInstance()->StopWatching(watcher_id_);
- }
-
- private:
- WatcherID watcher_id_;
-
- // Used to weakly bind |this| to the WatcherThreadManager.
- base::WeakPtrFactory<SecondaryThreadWatchingState> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(SecondaryThreadWatchingState);
-};
-
-// HandleWatcher ---------------------------------------------------------------
-
-HandleWatcher::HandleWatcher() {
-}
-
-HandleWatcher::~HandleWatcher() {
-}
-
-void HandleWatcher::Start(const Handle& handle,
- MojoHandleSignals handle_signals,
- MojoDeadline deadline,
- const base::Callback<void(MojoResult)>& callback) {
- DCHECK(handle.is_valid());
- DCHECK_NE(MOJO_HANDLE_SIGNAL_NONE, handle_signals);
-
- // Need to clear the state before creating a new one.
- state_.reset();
- if (MessagePumpMojo::IsCurrent()) {
- state_.reset(new SameThreadWatchingState(
- this, handle, handle_signals, deadline, callback));
- } else {
-#if !defined(OFFICIAL_BUILD)
- // Just for making debugging non-transferable message pipes easier. Since
- // they can't be sent after they're read/written/listened to,
- // MessagePipeDispatcher saves the callstack of when it's "bound" to a
- // pipe id. Triggering a read here, instead of later in the PostTask, means
- // we have a callstack that is useful to check if the pipe is erronously
- // attempted to be sent.
- uint32_t temp = 0;
- MojoReadMessage(handle.value(), nullptr, &temp, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE);
-#endif
- state_.reset(new SecondaryThreadWatchingState(
- this, handle, handle_signals, deadline, callback));
- }
-}
-
-void HandleWatcher::Stop() {
- state_.reset();
-}
-
-} // namespace common
-} // namespace mojo
diff --git a/chromium/mojo/message_pump/handle_watcher.h b/chromium/mojo/message_pump/handle_watcher.h
deleted file mode 100644
index 10056b143cb..00000000000
--- a/chromium/mojo/message_pump/handle_watcher.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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_MESSAGE_PUMP_HANDLE_WATCHER_H_
-#define MOJO_MESSAGE_PUMP_HANDLE_WATCHER_H_
-
-#include <memory>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "mojo/message_pump/mojo_message_pump_export.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace base {
-class Thread;
-}
-
-namespace mojo {
-namespace common {
-namespace test {
-class HandleWatcherTest;
-}
-
-// HandleWatcher is used to asynchronously wait on a handle and notify a Closure
-// when the handle is ready, or the deadline has expired.
-class MOJO_MESSAGE_PUMP_EXPORT HandleWatcher {
- public:
- HandleWatcher();
-
- ~HandleWatcher();
-
- // Starts listening for |handle|. This implicitly invokes Stop(). In other
- // words, Start() performs one asynchronous watch at a time. It is ok to call
- // Start() multiple times, but it cancels any existing watches. |callback| is
- // notified when the handle is ready, invalid or deadline has passed and is
- // notified on the thread Start() was invoked on. If the current thread exits
- // before the handle is ready, then |callback| is invoked with a result of
- // MOJO_RESULT_ABORTED.
- void Start(const Handle& handle,
- MojoHandleSignals handle_signals,
- MojoDeadline deadline,
- const base::Callback<void(MojoResult)>& callback);
-
- // Stops listening. Does nothing if not in the process of listening.
- void Stop();
-
- bool is_watching() const { return !!state_; }
-
- private:
- class StateBase;
- class SameThreadWatchingState;
- class SecondaryThreadWatchingState;
-
- // If non-NULL Start() has been invoked.
- std::unique_ptr<StateBase> state_;
-
- DISALLOW_COPY_AND_ASSIGN(HandleWatcher);
-};
-
-} // namespace common
-} // namespace mojo
-
-#endif // MOJO_MESSAGE_PUMP_HANDLE_WATCHER_H_
diff --git a/chromium/mojo/message_pump/handle_watcher_perftest.cc b/chromium/mojo/message_pump/handle_watcher_perftest.cc
deleted file mode 100644
index 96c8495c020..00000000000
--- a/chromium/mojo/message_pump/handle_watcher_perftest.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright 2015 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 <stdint.h>
-
-#include <string>
-#include <utility>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/memory/scoped_vector.h"
-#include "base/run_loop.h"
-#include "base/time/time.h"
-#include "mojo/message_pump/handle_watcher.h"
-#include "mojo/message_pump/message_pump_mojo.h"
-#include "mojo/public/cpp/test_support/test_support.h"
-#include "mojo/public/cpp/test_support/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace common {
-namespace test {
-
-enum MessageLoopConfig {
- MESSAGE_LOOP_CONFIG_DEFAULT = 0,
- MESSAGE_LOOP_CONFIG_MOJO = 1
-};
-
-std::unique_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) {
- std::unique_ptr<base::MessageLoop> loop;
- if (config == MESSAGE_LOOP_CONFIG_DEFAULT)
- loop.reset(new base::MessageLoop());
- else
- loop.reset(new base::MessageLoop(MessagePumpMojo::Create()));
- return loop;
-}
-
-void OnWatcherSignaled(const base::Closure& callback, MojoResult /* result */) {
- callback.Run();
-}
-
-class ScopedPerfTimer {
- public:
- ScopedPerfTimer(const std::string& test_name,
- const std::string& sub_test_name,
- uint64_t iterations)
- : test_name_(test_name),
- sub_test_name_(sub_test_name),
- iterations_(iterations),
- start_time_(base::TimeTicks::Now()) {}
- ~ScopedPerfTimer() {
- base::TimeTicks end_time = base::TimeTicks::Now();
- mojo::test::LogPerfResult(
- test_name_.c_str(), sub_test_name_.c_str(),
- iterations_ / (end_time - start_time_).InSecondsF(),
- "iterations/second");
- }
-
- private:
- const std::string test_name_;
- const std::string sub_test_name_;
- const uint64_t iterations_;
- base::TimeTicks start_time_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedPerfTimer);
-};
-
-class HandleWatcherPerftest : public testing::TestWithParam<MessageLoopConfig> {
- public:
- HandleWatcherPerftest() : message_loop_(CreateMessageLoop(GetParam())) {}
-
- protected:
- std::string GetMessageLoopName() const {
- return (GetParam() == MESSAGE_LOOP_CONFIG_DEFAULT) ? "DefaultMessageLoop"
- : "MojoMessageLoop";
- }
-
- private:
- std::unique_ptr<base::MessageLoop> message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(HandleWatcherPerftest);
-};
-
-INSTANTIATE_TEST_CASE_P(MultipleMessageLoopConfigs,
- HandleWatcherPerftest,
- testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT,
- MESSAGE_LOOP_CONFIG_MOJO));
-
-void NeverReached(MojoResult result) {
- FAIL() << "Callback should never be invoked " << result;
-}
-
-TEST_P(HandleWatcherPerftest, StartStop) {
- const uint64_t kIterations = 100000;
- MessagePipe pipe;
- HandleWatcher watcher;
-
- ScopedPerfTimer timer("StartStop", GetMessageLoopName(), kIterations);
- for (uint64_t i = 0; i < kIterations; i++) {
- watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached));
- watcher.Stop();
- }
-}
-
-TEST_P(HandleWatcherPerftest, StartAllThenStop_1000Handles) {
- const uint64_t kIterations = 100;
- const uint64_t kHandles = 1000;
-
- struct TestData {
- MessagePipe pipe;
- HandleWatcher watcher;
- };
- ScopedVector<TestData> data_vector;
- // Create separately from the start/stop loops to avoid affecting the
- // benchmark.
- for (uint64_t i = 0; i < kHandles; i++) {
- std::unique_ptr<TestData> test_data(new TestData);
- ASSERT_TRUE(test_data->pipe.handle0.is_valid());
- data_vector.push_back(std::move(test_data));
- }
-
- ScopedPerfTimer timer("StartAllThenStop_1000Handles", GetMessageLoopName(),
- kIterations * kHandles);
- for (uint64_t iter = 0; iter < kIterations; iter++) {
- for (uint64_t i = 0; i < kHandles; i++) {
- TestData* test_data = data_vector[i];
- test_data->watcher.Start(
- test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached));
- }
- for (uint64_t i = 0; i < kHandles; i++) {
- TestData* test_data = data_vector[i];
- test_data->watcher.Stop();
- }
- }
-}
-
-TEST_P(HandleWatcherPerftest, StartAndSignal) {
- const uint64_t kIterations = 10000;
- const std::string kMessage = "hello";
- MessagePipe pipe;
- HandleWatcher watcher;
- std::string received_message;
-
- ScopedPerfTimer timer("StartAndSignal", GetMessageLoopName(), kIterations);
- for (uint64_t i = 0; i < kIterations; i++) {
- base::RunLoop run_loop;
- watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE,
- base::Bind(&OnWatcherSignaled, run_loop.QuitClosure()));
- ASSERT_TRUE(mojo::test::WriteTextMessage(pipe.handle1.get(), kMessage));
- run_loop.Run();
- watcher.Stop();
-
- ASSERT_TRUE(
- mojo::test::ReadTextMessage(pipe.handle0.get(), &received_message));
- EXPECT_EQ(kMessage, received_message);
- received_message.clear();
- }
-}
-
-TEST_P(HandleWatcherPerftest, StartAndSignal_1000Waiting) {
- const uint64_t kIterations = 10000;
- const uint64_t kWaitingHandles = 1000;
- const std::string kMessage = "hello";
- MessagePipe pipe;
- HandleWatcher watcher;
- std::string received_message;
-
- struct TestData {
- MessagePipe pipe;
- HandleWatcher watcher;
- };
- ScopedVector<TestData> data_vector;
- for (uint64_t i = 0; i < kWaitingHandles; i++) {
- std::unique_ptr<TestData> test_data(new TestData);
- ASSERT_TRUE(test_data->pipe.handle0.is_valid());
- test_data->watcher.Start(
- test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached));
- data_vector.push_back(std::move(test_data));
- }
-
- ScopedPerfTimer timer("StartAndSignal_1000Waiting", GetMessageLoopName(),
- kIterations);
- for (uint64_t i = 0; i < kIterations; i++) {
- base::RunLoop run_loop;
- watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE,
- base::Bind(&OnWatcherSignaled, run_loop.QuitClosure()));
- ASSERT_TRUE(mojo::test::WriteTextMessage(pipe.handle1.get(), kMessage));
- run_loop.Run();
- watcher.Stop();
-
- ASSERT_TRUE(
- mojo::test::ReadTextMessage(pipe.handle0.get(), &received_message));
- EXPECT_EQ(kMessage, received_message);
- received_message.clear();
- }
-}
-
-} // namespace test
-} // namespace common
-} // namespace mojo
diff --git a/chromium/mojo/message_pump/handle_watcher_unittest.cc b/chromium/mojo/message_pump/handle_watcher_unittest.cc
deleted file mode 100644
index fd1f49b3f9f..00000000000
--- a/chromium/mojo/message_pump/handle_watcher_unittest.cc
+++ /dev/null
@@ -1,493 +0,0 @@
-// 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/message_pump/handle_watcher.h"
-
-#include <memory>
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/memory/scoped_vector.h"
-#include "base/run_loop.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/threading/thread.h"
-#include "mojo/message_pump/message_pump_mojo.h"
-#include "mojo/message_pump/time_helper.h"
-#include "mojo/public/cpp/system/core.h"
-#include "mojo/public/cpp/test_support/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace common {
-namespace test {
-
-enum MessageLoopConfig {
- MESSAGE_LOOP_CONFIG_DEFAULT = 0,
- MESSAGE_LOOP_CONFIG_MOJO = 1
-};
-
-void ObserveCallback(bool* was_signaled,
- MojoResult* result_observed,
- MojoResult result) {
- *was_signaled = true;
- *result_observed = result;
-}
-
-void RunUntilIdle() {
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
-}
-
-void DeleteWatcherAndForwardResult(
- HandleWatcher* watcher,
- base::Callback<void(MojoResult)> next_callback,
- MojoResult result) {
- delete watcher;
- next_callback.Run(result);
-}
-
-std::unique_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) {
- std::unique_ptr<base::MessageLoop> loop;
- if (config == MESSAGE_LOOP_CONFIG_DEFAULT)
- loop.reset(new base::MessageLoop());
- else
- loop.reset(new base::MessageLoop(MessagePumpMojo::Create()));
- return loop;
-}
-
-// Helper class to manage the callback and running the message loop waiting for
-// message to be received. Typical usage is something like:
-// Schedule callback returned from GetCallback().
-// RunUntilGotCallback();
-// EXPECT_TRUE(got_callback());
-// clear_callback();
-class CallbackHelper {
- public:
- CallbackHelper()
- : got_callback_(false),
- run_loop_(NULL),
- weak_factory_(this) {}
- ~CallbackHelper() {}
-
- // See description above |got_callback_|.
- bool got_callback() const { return got_callback_; }
- void clear_callback() { got_callback_ = false; }
-
- // Runs the current MessageLoop until the callback returned from GetCallback()
- // is notified.
- void RunUntilGotCallback() {
- ASSERT_TRUE(run_loop_ == NULL);
- base::RunLoop run_loop;
- base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop);
- run_loop.Run();
- }
-
- base::Callback<void(MojoResult)> GetCallback() {
- return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr());
- }
-
- void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) {
- StartWithCallback(watcher, handle, GetCallback());
- }
-
- void StartWithCallback(HandleWatcher* watcher,
- const MessagePipeHandle& handle,
- const base::Callback<void(MojoResult)>& callback) {
- watcher->Start(handle, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, callback);
- }
-
- private:
- void OnCallback(MojoResult result) {
- got_callback_ = true;
- if (run_loop_)
- run_loop_->Quit();
- }
-
- // Set to true when the callback is called.
- bool got_callback_;
-
- // If non-NULL we're in RunUntilGotCallback().
- base::RunLoop* run_loop_;
-
- base::WeakPtrFactory<CallbackHelper> weak_factory_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
-};
-
-class HandleWatcherTest : public testing::TestWithParam<MessageLoopConfig> {
- public:
- HandleWatcherTest()
- : at_exit_(new base::ShadowingAtExitManager),
- message_loop_(CreateMessageLoop(GetParam())) {}
- virtual ~HandleWatcherTest() {
- // By explicitly destroying |at_exit_| before resetting the tick clock, it
- // ensures that the handle watcher thread (if there is one) is shut down,
- // preventing a race with users of the tick clock in MessagePumpMojo.
- at_exit_.reset();
- test::SetTickClockForTest(NULL);
- }
-
- protected:
- void TearDownMessageLoop() {
- message_loop_.reset();
- }
-
- // This should be called at the beginning of any test that needs it, so that
- // it is installed before the handle watcher thread starts.
- void InstallTickClock() {
- test::SetTickClockForTest(&tick_clock_);
- }
-
- base::SimpleTestTickClock tick_clock_;
-
- private:
- std::unique_ptr<base::ShadowingAtExitManager> at_exit_;
- std::unique_ptr<base::MessageLoop> message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest);
-};
-
-INSTANTIATE_TEST_CASE_P(
- MultipleMessageLoopConfigs, HandleWatcherTest,
- testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT, MESSAGE_LOOP_CONFIG_MOJO));
-
-// Trivial test case with a single handle to watch.
-TEST_P(HandleWatcherTest, SingleHandler) {
- MessagePipe test_pipe;
- ASSERT_TRUE(test_pipe.handle0.is_valid());
- CallbackHelper callback_helper;
- HandleWatcher watcher;
- callback_helper.Start(&watcher, test_pipe.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper.got_callback());
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(),
- std::string()));
- callback_helper.RunUntilGotCallback();
- EXPECT_TRUE(callback_helper.got_callback());
-}
-
-// Creates three handles and notfies them in reverse order ensuring each one is
-// notified appropriately.
-TEST_P(HandleWatcherTest, ThreeHandles) {
- MessagePipe test_pipe1;
- MessagePipe test_pipe2;
- MessagePipe test_pipe3;
- CallbackHelper callback_helper1;
- CallbackHelper callback_helper2;
- CallbackHelper callback_helper3;
- ASSERT_TRUE(test_pipe1.handle0.is_valid());
- ASSERT_TRUE(test_pipe2.handle0.is_valid());
- ASSERT_TRUE(test_pipe3.handle0.is_valid());
-
- HandleWatcher watcher1;
- callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
- EXPECT_FALSE(callback_helper3.got_callback());
-
- HandleWatcher watcher2;
- callback_helper2.Start(&watcher2, test_pipe2.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
- EXPECT_FALSE(callback_helper3.got_callback());
-
- HandleWatcher watcher3;
- callback_helper3.Start(&watcher3, test_pipe3.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
- EXPECT_FALSE(callback_helper3.got_callback());
-
- // Write to 3 and make sure it's notified.
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(),
- std::string()));
- callback_helper3.RunUntilGotCallback();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
- EXPECT_TRUE(callback_helper3.got_callback());
- callback_helper3.clear_callback();
-
- // Write to 1 and 3. Only 1 should be notified since 3 was is no longer
- // running.
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
- std::string()));
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(),
- std::string()));
- callback_helper1.RunUntilGotCallback();
- EXPECT_TRUE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
- EXPECT_FALSE(callback_helper3.got_callback());
- callback_helper1.clear_callback();
-
- // Write to 1 and 2. Only 2 should be notified (since 1 was already notified).
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
- std::string()));
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(),
- std::string()));
- callback_helper2.RunUntilGotCallback();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_TRUE(callback_helper2.got_callback());
- EXPECT_FALSE(callback_helper3.got_callback());
-}
-
-// Verifies Start() invoked a second time works.
-TEST_P(HandleWatcherTest, Restart) {
- MessagePipe test_pipe1;
- MessagePipe test_pipe2;
- CallbackHelper callback_helper1;
- CallbackHelper callback_helper2;
- ASSERT_TRUE(test_pipe1.handle0.is_valid());
- ASSERT_TRUE(test_pipe2.handle0.is_valid());
-
- HandleWatcher watcher1;
- callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
-
- HandleWatcher watcher2;
- callback_helper2.Start(&watcher2, test_pipe2.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
-
- // Write to 1 and make sure it's notified.
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
- std::string()));
- callback_helper1.RunUntilGotCallback();
- EXPECT_TRUE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
- callback_helper1.clear_callback();
- EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1.handle0.get()));
-
- // Write to 2 and make sure it's notified.
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(),
- std::string()));
- callback_helper2.RunUntilGotCallback();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_TRUE(callback_helper2.got_callback());
- callback_helper2.clear_callback();
-
- // Listen on 1 again.
- callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
-
- // Write to 1 and make sure it's notified.
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(),
- std::string()));
- callback_helper1.RunUntilGotCallback();
- EXPECT_TRUE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
-}
-
-// Verifies Start() invoked a second time on the same handle works.
-TEST_P(HandleWatcherTest, RestartOnSameHandle) {
- MessagePipe test_pipe;
- CallbackHelper callback_helper;
- ASSERT_TRUE(test_pipe.handle0.is_valid());
-
- HandleWatcher watcher;
- callback_helper.Start(&watcher, test_pipe.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper.got_callback());
-
- callback_helper.Start(&watcher, test_pipe.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper.got_callback());
-}
-
-// Verifies deadline is honored.
-TEST_P(HandleWatcherTest, Deadline) {
- InstallTickClock();
-
- MessagePipe test_pipe1;
- MessagePipe test_pipe2;
- MessagePipe test_pipe3;
- CallbackHelper callback_helper1;
- CallbackHelper callback_helper2;
- CallbackHelper callback_helper3;
- ASSERT_TRUE(test_pipe1.handle0.is_valid());
- ASSERT_TRUE(test_pipe2.handle0.is_valid());
- ASSERT_TRUE(test_pipe3.handle0.is_valid());
-
- // Add a watcher with an infinite timeout.
- HandleWatcher watcher1;
- callback_helper1.Start(&watcher1, test_pipe1.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
- EXPECT_FALSE(callback_helper3.got_callback());
-
- // Add another watcher wth a timeout of 500 microseconds.
- HandleWatcher watcher2;
- watcher2.Start(test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 500,
- callback_helper2.GetCallback());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_FALSE(callback_helper2.got_callback());
- EXPECT_FALSE(callback_helper3.got_callback());
-
- // Advance the clock passed the deadline. We also have to start another
- // watcher to wake up the background thread.
- tick_clock_.Advance(base::TimeDelta::FromMicroseconds(501));
-
- HandleWatcher watcher3;
- callback_helper3.Start(&watcher3, test_pipe3.handle0.get());
-
- callback_helper2.RunUntilGotCallback();
- EXPECT_FALSE(callback_helper1.got_callback());
- EXPECT_TRUE(callback_helper2.got_callback());
- EXPECT_FALSE(callback_helper3.got_callback());
-}
-
-TEST_P(HandleWatcherTest, DeleteInCallback) {
- MessagePipe test_pipe;
- CallbackHelper callback_helper;
-
- HandleWatcher* watcher = new HandleWatcher();
- callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(),
- base::Bind(&DeleteWatcherAndForwardResult,
- watcher,
- callback_helper.GetCallback()));
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(),
- std::string()));
- callback_helper.RunUntilGotCallback();
- EXPECT_TRUE(callback_helper.got_callback());
-}
-
-TEST_P(HandleWatcherTest, AbortedOnMessageLoopDestruction) {
- bool was_signaled = false;
- MojoResult result = MOJO_RESULT_OK;
-
- MessagePipe pipe;
- HandleWatcher watcher;
- watcher.Start(pipe.handle0.get(),
- MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE,
- base::Bind(&ObserveCallback, &was_signaled, &result));
-
- // Now, let the MessageLoop get torn down. We expect our callback to run.
- TearDownMessageLoop();
-
- EXPECT_TRUE(was_signaled);
- EXPECT_EQ(MOJO_RESULT_ABORTED, result);
-}
-
-void NeverReached(MojoResult result) {
- FAIL() << "Callback should never be invoked " << result;
-}
-
-// Called on the main thread when a thread is done. Decrements |active_count|
-// and if |active_count| is zero quits |run_loop|.
-void StressThreadDone(base::RunLoop* run_loop, int* active_count) {
- (*active_count)--;
- EXPECT_GE(*active_count, 0);
- if (*active_count == 0)
- run_loop->Quit();
-}
-
-// See description of StressTest. This is called on the background thread.
-// |count| is the number of HandleWatchers to create. |active_count| is the
-// number of outstanding threads, |task_runner| the task runner for the main
-// thread and |run_loop| the run loop that should be quit when there are no more
-// threads running. When done StressThreadDone() is invoked on the main thread.
-// |active_count| and |run_loop| should only be used on the main thread.
-void RunStressTest(int count,
- scoped_refptr<base::TaskRunner> task_runner,
- base::RunLoop* run_loop,
- int* active_count) {
- struct TestData {
- MessagePipe pipe;
- HandleWatcher watcher;
- };
- ScopedVector<TestData> data_vector;
- for (int i = 0; i < count; ++i) {
- if (i % 20 == 0) {
- // Every so often we wait. This results in some level of thread balancing
- // as well as making sure HandleWatcher has time to actually start some
- // watches.
- MessagePipe test_pipe;
- ASSERT_TRUE(test_pipe.handle0.is_valid());
- CallbackHelper callback_helper;
- HandleWatcher watcher;
- callback_helper.Start(&watcher, test_pipe.handle0.get());
- RunUntilIdle();
- EXPECT_FALSE(callback_helper.got_callback());
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(),
- std::string()));
- base::MessageLoop::ScopedNestableTaskAllower scoper(
- base::MessageLoop::current());
- callback_helper.RunUntilGotCallback();
- EXPECT_TRUE(callback_helper.got_callback());
- } else {
- std::unique_ptr<TestData> test_data(new TestData);
- ASSERT_TRUE(test_data->pipe.handle0.is_valid());
- test_data->watcher.Start(test_data->pipe.handle0.get(),
- MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE,
- base::Bind(&NeverReached));
- data_vector.push_back(test_data.release());
- }
- if (i % 15 == 0)
- data_vector.clear();
- }
- task_runner->PostTask(FROM_HERE,
- base::Bind(&StressThreadDone, run_loop,
- active_count));
-}
-
-// This test is meant to stress HandleWatcher. It uses from various threads
-// repeatedly starting and stopping watches. It spins up kThreadCount
-// threads. Each thread creates kWatchCount watches. Every so often each thread
-// writes to a pipe and waits for the response.
-TEST(HandleWatcherCleanEnvironmentTest, StressTest) {
-#if defined(NDEBUG)
- const int kThreadCount = 15;
- const int kWatchCount = 400;
-#else
- const int kThreadCount = 10;
- const int kWatchCount = 250;
-#endif
-
- base::ShadowingAtExitManager at_exit;
- base::MessageLoop message_loop;
- base::RunLoop run_loop;
- ScopedVector<base::Thread> threads;
- int threads_active_counter = kThreadCount;
- // Starts the threads first and then post the task in hopes of having more
- // threads running at once.
- for (int i = 0; i < kThreadCount; ++i) {
- std::unique_ptr<base::Thread> thread(new base::Thread("test thread"));
- if (i % 2) {
- base::Thread::Options thread_options;
- thread_options.message_pump_factory =
- base::Bind(&MessagePumpMojo::Create);
- thread->StartWithOptions(thread_options);
- } else {
- thread->Start();
- }
- threads.push_back(thread.release());
- }
- for (int i = 0; i < kThreadCount; ++i) {
- threads[i]->task_runner()->PostTask(
- FROM_HERE, base::Bind(&RunStressTest, kWatchCount,
- message_loop.task_runner(),
- &run_loop, &threads_active_counter));
- }
- run_loop.Run();
- ASSERT_EQ(0, threads_active_counter);
-}
-
-} // namespace test
-} // namespace common
-} // namespace mojo
diff --git a/chromium/mojo/message_pump/message_pump_mojo.cc b/chromium/mojo/message_pump/message_pump_mojo.cc
deleted file mode 100644
index b907ba3e2c0..00000000000
--- a/chromium/mojo/message_pump/message_pump_mojo.cc
+++ /dev/null
@@ -1,448 +0,0 @@
-// 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/message_pump/message_pump_mojo.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <map>
-#include <vector>
-
-#include "base/containers/small_map.h"
-#include "base/debug/alias.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/threading/thread_local.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/time/time.h"
-#include "mojo/message_pump/message_pump_mojo_handler.h"
-#include "mojo/message_pump/time_helper.h"
-#include "mojo/public/c/system/wait_set.h"
-
-namespace mojo {
-namespace common {
-namespace {
-
-base::LazyInstance<base::ThreadLocalPointer<MessagePumpMojo> >::Leaky
- g_tls_current_pump = LAZY_INSTANCE_INITIALIZER;
-
-MojoDeadline TimeTicksToMojoDeadline(base::TimeTicks time_ticks,
- base::TimeTicks now) {
- // The is_null() check matches that of HandleWatcher as well as how
- // |delayed_work_time| is used.
- if (time_ticks.is_null())
- return MOJO_DEADLINE_INDEFINITE;
- const int64_t delta = (time_ticks - now).InMicroseconds();
- return delta < 0 ? static_cast<MojoDeadline>(0) :
- static_cast<MojoDeadline>(delta);
-}
-
-} // namespace
-
-struct MessagePumpMojo::RunState {
- RunState() : should_quit(false) {}
-
- base::TimeTicks delayed_work_time;
-
- bool should_quit;
-};
-
-MessagePumpMojo::MessagePumpMojo()
- : run_state_(NULL),
- next_handler_id_(0),
- event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {
- DCHECK(!current())
- << "There is already a MessagePumpMojo instance on this thread.";
- g_tls_current_pump.Pointer()->Set(this);
-
- MojoResult result = CreateMessagePipe(nullptr, &read_handle_, &write_handle_);
- CHECK_EQ(result, MOJO_RESULT_OK);
- CHECK(read_handle_.is_valid());
- CHECK(write_handle_.is_valid());
-
- MojoHandle handle;
- result = MojoCreateWaitSet(&handle);
- CHECK_EQ(result, MOJO_RESULT_OK);
- wait_set_handle_.reset(Handle(handle));
- CHECK(wait_set_handle_.is_valid());
-
- result =
- MojoAddHandle(wait_set_handle_.get().value(), read_handle_.get().value(),
- MOJO_HANDLE_SIGNAL_READABLE);
- CHECK_EQ(result, MOJO_RESULT_OK);
-}
-
-MessagePumpMojo::~MessagePumpMojo() {
- DCHECK_EQ(this, current());
- g_tls_current_pump.Pointer()->Set(NULL);
-}
-
-// static
-std::unique_ptr<base::MessagePump> MessagePumpMojo::Create() {
- return std::unique_ptr<MessagePump>(new MessagePumpMojo());
-}
-
-// static
-MessagePumpMojo* MessagePumpMojo::current() {
- return g_tls_current_pump.Pointer()->Get();
-}
-
-void MessagePumpMojo::AddHandler(MessagePumpMojoHandler* handler,
- const Handle& handle,
- MojoHandleSignals wait_signals,
- base::TimeTicks deadline) {
- CHECK(handler);
- DCHECK(handle.is_valid());
- // Assume it's an error if someone tries to reregister an existing handle.
- CHECK_EQ(0u, handlers_.count(handle));
- Handler handler_data;
- handler_data.handler = handler;
- handler_data.wait_signals = wait_signals;
- handler_data.deadline = deadline;
- handler_data.id = next_handler_id_++;
- handlers_[handle] = handler_data;
- if (!deadline.is_null()) {
- bool inserted = deadline_handles_.insert(handle).second;
- DCHECK(inserted);
- }
-
- MojoResult result = MojoAddHandle(wait_set_handle_.get().value(),
- handle.value(), wait_signals);
- // Because stopping a HandleWatcher is now asynchronous, it's possible for the
- // handle to no longer be open at this point.
- CHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_INVALID_ARGUMENT);
-}
-
-void MessagePumpMojo::RemoveHandler(const Handle& handle) {
- MojoResult result =
- MojoRemoveHandle(wait_set_handle_.get().value(), handle.value());
- // At this point, it's possible that the handle has been closed, which would
- // cause MojoRemoveHandle() to return MOJO_RESULT_INVALID_ARGUMENT. It's also
- // possible for the handle to have already been removed, so all of the
- // possible error codes are valid here.
- CHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_NOT_FOUND ||
- result == MOJO_RESULT_INVALID_ARGUMENT);
-
- handlers_.erase(handle);
- deadline_handles_.erase(handle);
-}
-
-void MessagePumpMojo::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void MessagePumpMojo::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void MessagePumpMojo::Run(Delegate* delegate) {
- RunState run_state;
- RunState* old_state = NULL;
- {
- base::AutoLock auto_lock(run_state_lock_);
- old_state = run_state_;
- run_state_ = &run_state;
- }
- DoRunLoop(&run_state, delegate);
- {
- base::AutoLock auto_lock(run_state_lock_);
- run_state_ = old_state;
- }
-}
-
-void MessagePumpMojo::Quit() {
- base::AutoLock auto_lock(run_state_lock_);
- if (run_state_)
- run_state_->should_quit = true;
-}
-
-void MessagePumpMojo::ScheduleWork() {
- SignalControlPipe();
-}
-
-void MessagePumpMojo::ScheduleDelayedWork(
- const base::TimeTicks& delayed_work_time) {
- base::AutoLock auto_lock(run_state_lock_);
- if (!run_state_)
- return;
- run_state_->delayed_work_time = delayed_work_time;
-}
-
-void MessagePumpMojo::DoRunLoop(RunState* run_state, Delegate* delegate) {
- bool more_work_is_plausible = true;
- for (;;) {
- const bool block = !more_work_is_plausible;
- if (read_handle_.is_valid()) {
- more_work_is_plausible = DoInternalWork(*run_state, block);
- } else {
- more_work_is_plausible = DoNonMojoWork(*run_state, block);
- }
-
- if (run_state->should_quit)
- break;
-
- more_work_is_plausible |= delegate->DoWork();
- if (run_state->should_quit)
- break;
-
- more_work_is_plausible |= delegate->DoDelayedWork(
- &run_state->delayed_work_time);
- if (run_state->should_quit)
- break;
-
- if (more_work_is_plausible)
- continue;
-
- more_work_is_plausible = delegate->DoIdleWork();
- if (run_state->should_quit)
- break;
- }
-}
-
-bool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) {
- bool did_work = block;
- if (block) {
- // If the wait isn't blocking (deadline == 0), there's no point in waiting.
- // Wait sets do not require a wait operation to be performed in order to
- // retreive any ready handles. Performing a wait with deadline == 0 is
- // unnecessary work.
- did_work = WaitForReadyHandles(run_state);
- }
-
- did_work |= ProcessReadyHandles();
- did_work |= RemoveExpiredHandles();
-
- return did_work;
-}
-
-bool MessagePumpMojo::DoNonMojoWork(const RunState& run_state, bool block) {
- bool did_work = block;
- if (block) {
- const MojoDeadline deadline = GetDeadlineForWait(run_state);
- // Stolen from base/message_loop/message_pump_default.cc
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- if (deadline == MOJO_DEADLINE_INDEFINITE) {
- event_.Wait();
- } else {
- if (deadline > 0) {
- event_.TimedWait(base::TimeDelta::FromMicroseconds(deadline));
- } else {
- did_work = false;
- }
- }
- // Since event_ is auto-reset, we don't need to do anything special here
- // other than service each delegate method.
- }
-
- did_work |= RemoveExpiredHandles();
-
- return did_work;
-}
-
-bool MessagePumpMojo::WaitForReadyHandles(const RunState& run_state) const {
- const MojoDeadline deadline = GetDeadlineForWait(run_state);
- const MojoResult wait_result = Wait(
- wait_set_handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, deadline, nullptr);
- if (wait_result == MOJO_RESULT_OK) {
- // Handles may be ready. Or not since wake-ups can be spurious in certain
- // circumstances.
- return true;
- } else if (wait_result == MOJO_RESULT_DEADLINE_EXCEEDED) {
- return false;
- }
-
- base::debug::Alias(&wait_result);
- // Unexpected result is likely fatal, crash so we can determine cause.
- CHECK(false);
- return false;
-}
-
-bool MessagePumpMojo::ProcessReadyHandles() {
- // Maximum number of handles to retrieve and process. Experimentally, the 95th
- // percentile is 1 handle, and the long-term average is 1.1. However, this has
- // been seen to reach >10 under heavy load. 8 is a hand-wavy compromise.
- const uint32_t kMaxServiced = 8;
- uint32_t num_ready_handles = kMaxServiced;
- MojoHandle handles[kMaxServiced];
- MojoResult handle_results[kMaxServiced];
-
- const MojoResult get_result =
- MojoGetReadyHandles(wait_set_handle_.get().value(), &num_ready_handles,
- handles, handle_results, nullptr);
- CHECK(get_result == MOJO_RESULT_OK || get_result == MOJO_RESULT_SHOULD_WAIT);
- if (get_result != MOJO_RESULT_OK)
- return false;
-
- DCHECK(num_ready_handles);
- DCHECK_LE(num_ready_handles, kMaxServiced);
- // Do this in two steps, because notifying a handler may remove/add other
- // handles that may have also been woken up.
- // First, enumerate the IDs of the ready handles. Then, iterate over the
- // handles and only take action if the ID hasn't changed.
- // Since the size of this map is bounded by |kMaxServiced|, use a SmallMap to
- // avoid the per-element allocation.
- base::SmallMap<std::map<Handle, int>, kMaxServiced> ready_handles;
- for (uint32_t i = 0; i < num_ready_handles; i++) {
- const Handle handle = Handle(handles[i]);
- // Skip the control handle. It's special.
- if (handle.value() == read_handle_.get().value())
- continue;
- DCHECK(handle.is_valid());
- const auto it = handlers_.find(handle);
- // Skip handles that have been removed. This is possible because
- // RemoveHandler() can be called with a handle that has been closed. Because
- // the handle is closed, the MojoRemoveHandle() call in RemoveHandler()
- // would have failed, but the handle is still in the wait set. Once the
- // handle is retrieved using MojoGetReadyHandles(), it is implicitly removed
- // from the set. The result is either the pending result that existed when
- // the handle was closed, or |MOJO_RESULT_CANCELLED| to indicate that the
- // handle was closed.
- if (it == handlers_.end())
- continue;
- ready_handles[handle] = it->second.id;
- }
-
- for (uint32_t i = 0; i < num_ready_handles; i++) {
- const Handle handle = Handle(handles[i]);
-
- // If the handle has been removed, or it's ID has changed, skip over it.
- // If the handle's ID has changed, and it still satisfies its signals,
- // then it'll be caught in the next message pump iteration.
- const auto it = handlers_.find(handle);
- if ((handle.value() != read_handle_.get().value()) &&
- (it == handlers_.end() || it->second.id != ready_handles[handle])) {
- continue;
- }
-
- switch (handle_results[i]) {
- case MOJO_RESULT_CANCELLED:
- case MOJO_RESULT_FAILED_PRECONDITION:
- DVLOG(1) << "Error: " << handle_results[i]
- << " handle: " << handle.value();
- if (handle.value() == read_handle_.get().value()) {
- // The Mojo EDK is shutting down. We can't just quit the message pump
- // because that may cause the thread to quit, which causes the
- // thread's MessageLoop to be destroyed, which races with any use of
- // |Thread::task_runner()|. So instead, we enter a "dumb" mode which
- // bypasses Mojo and just acts like a trivial message pump. That way,
- // we can wait for the usual thread exiting mechanism to happen.
- // The dumb mode is indicated by releasing the control pipe's read
- // handle.
- read_handle_.reset();
- } else {
- SignalHandleError(handle, handle_results[i]);
- }
- break;
- case MOJO_RESULT_OK:
- if (handle.value() == read_handle_.get().value()) {
- DVLOG(1) << "Signaled control pipe";
- // Control pipe was written to.
- ReadMessageRaw(read_handle_.get(), nullptr, nullptr, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
- } else {
- DVLOG(1) << "Handle ready: " << handle.value();
- SignalHandleReady(handle);
- }
- break;
- default:
- base::debug::Alias(&i);
- base::debug::Alias(&handle_results[i]);
- // Unexpected result is likely fatal, crash so we can determine cause.
- CHECK(false);
- }
- }
- return true;
-}
-
-bool MessagePumpMojo::RemoveExpiredHandles() {
- bool removed = false;
- // Notify and remove any handlers whose time has expired. First, iterate over
- // the set of handles that have a deadline, and add the expired handles to a
- // map of <Handle, id>. Then, iterate over those expired handles and remove
- // them. The two-step process is because a handler can add/remove new
- // handlers.
- std::map<Handle, int> expired_handles;
- const base::TimeTicks now(internal::NowTicks());
- for (const Handle handle : deadline_handles_) {
- const auto it = handlers_.find(handle);
- // Expect any handle in |deadline_handles_| to also be in |handlers_| since
- // the two are modified in lock-step.
- DCHECK(it != handlers_.end());
- if (!it->second.deadline.is_null() && it->second.deadline < now)
- expired_handles[handle] = it->second.id;
- }
- for (const auto& pair : expired_handles) {
- auto it = handlers_.find(pair.first);
- // Don't need to check deadline again since it can't change if id hasn't
- // changed.
- if (it != handlers_.end() && it->second.id == pair.second) {
- SignalHandleError(pair.first, MOJO_RESULT_DEADLINE_EXCEEDED);
- removed = true;
- }
- }
- return removed;
-}
-
-void MessagePumpMojo::SignalControlPipe() {
- const MojoResult result =
- WriteMessageRaw(write_handle_.get(), NULL, 0, NULL, 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE);
- if (result == MOJO_RESULT_FAILED_PRECONDITION) {
- // Mojo EDK is shutting down.
- event_.Signal();
- return;
- }
-
- // If we can't write we likely won't wake up the thread and there is a strong
- // chance we'll deadlock.
- CHECK_EQ(MOJO_RESULT_OK, result);
-}
-
-MojoDeadline MessagePumpMojo::GetDeadlineForWait(
- const RunState& run_state) const {
- const base::TimeTicks now(internal::NowTicks());
- MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time,
- now);
- for (const Handle handle : deadline_handles_) {
- auto it = handlers_.find(handle);
- DCHECK(it != handlers_.end());
- deadline = std::min(
- TimeTicksToMojoDeadline(it->second.deadline, now), deadline);
- }
- return deadline;
-}
-
-void MessagePumpMojo::SignalHandleReady(Handle handle) {
- auto it = handlers_.find(handle);
- DCHECK(it != handlers_.end());
- MessagePumpMojoHandler* handler = it->second.handler;
-
- WillSignalHandler();
- handler->OnHandleReady(handle);
- DidSignalHandler();
-}
-
-void MessagePumpMojo::SignalHandleError(Handle handle, MojoResult result) {
- auto it = handlers_.find(handle);
- DCHECK(it != handlers_.end());
- MessagePumpMojoHandler* handler = it->second.handler;
-
- RemoveHandler(handle);
- WillSignalHandler();
- handler->OnHandleError(handle, result);
- DidSignalHandler();
-}
-
-void MessagePumpMojo::WillSignalHandler() {
- FOR_EACH_OBSERVER(Observer, observers_, WillSignalHandler());
-}
-
-void MessagePumpMojo::DidSignalHandler() {
- FOR_EACH_OBSERVER(Observer, observers_, DidSignalHandler());
-}
-
-} // namespace common
-} // namespace mojo
diff --git a/chromium/mojo/message_pump/message_pump_mojo.h b/chromium/mojo/message_pump/message_pump_mojo.h
deleted file mode 100644
index ef2f55a7f72..00000000000
--- a/chromium/mojo/message_pump/message_pump_mojo.h
+++ /dev/null
@@ -1,178 +0,0 @@
-// 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_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_H_
-#define MOJO_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_H_
-
-#include <stdint.h>
-
-#include <functional>
-#include <memory>
-#include <set>
-#include <unordered_map>
-
-#include "base/macros.h"
-#include "base/message_loop/message_pump.h"
-#include "base/observer_list.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/time/time.h"
-#include "mojo/message_pump/mojo_message_pump_export.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace mojo {
-namespace common {
-
-class MessagePumpMojoHandler;
-
-// Mojo implementation of MessagePump.
-class MOJO_MESSAGE_PUMP_EXPORT MessagePumpMojo : public base::MessagePump {
- public:
- class MOJO_MESSAGE_PUMP_EXPORT Observer {
- public:
- Observer() {}
-
- virtual void WillSignalHandler() = 0;
- virtual void DidSignalHandler() = 0;
-
- protected:
- virtual ~Observer() {}
- };
-
- MessagePumpMojo();
- ~MessagePumpMojo() override;
-
- // Static factory function (for using with |base::Thread::Options|, wrapped
- // using |base::Bind()|).
- static std::unique_ptr<base::MessagePump> Create();
-
- // Returns the MessagePumpMojo instance of the current thread, if it exists.
- static MessagePumpMojo* current();
-
- static bool IsCurrent() { return !!current(); }
-
- // Registers a MessagePumpMojoHandler for the specified handle. Only one
- // handler can be registered for a specified handle.
- // NOTE: a value of 0 for |deadline| indicates an indefinite timeout.
- void AddHandler(MessagePumpMojoHandler* handler,
- const Handle& handle,
- MojoHandleSignals wait_signals,
- base::TimeTicks deadline);
-
- void RemoveHandler(const Handle& handle);
-
- void AddObserver(Observer*);
- void RemoveObserver(Observer*);
-
- // MessagePump:
- void Run(Delegate* delegate) override;
- void Quit() override;
- void ScheduleWork() override;
- void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) override;
-
- private:
- struct RunState;
-
- // Contains the data needed to track a request to AddHandler().
- struct Handler {
- Handler() : handler(NULL), wait_signals(MOJO_HANDLE_SIGNAL_NONE), id(0) {}
-
- MessagePumpMojoHandler* handler;
- MojoHandleSignals wait_signals;
- base::TimeTicks deadline;
- // See description of |MessagePumpMojo::next_handler_id_| for details.
- int id;
- };
-
- struct HandleHasher {
- size_t operator()(const Handle& handle) const {
- return std::hash<uint32_t>()(static_cast<uint32_t>(handle.value()));
- }
- };
-
- using HandleToHandler = std::unordered_map<Handle, Handler, HandleHasher>;
-
- // Implementation of Run().
- void DoRunLoop(RunState* run_state, Delegate* delegate);
-
- // Services the set of handles ready. If |block| is true this waits for a
- // handle to become ready, otherwise this does not block. Returns |true| if a
- // handle has become ready, |false| otherwise.
- bool DoInternalWork(const RunState& run_state, bool block);
-
- bool DoNonMojoWork(const RunState& run_state, bool block);
-
- // Waits for handles in the wait set to become ready. Returns |true| if ready
- // handles may be available, or |false| if the wait's deadline was exceeded.
- // Note, ready handles may be unavailable, even though |true| was returned.
- bool WaitForReadyHandles(const RunState& run_state) const;
-
- // Retrieves any 'ready' handles from the wait set, and runs the handler's
- // OnHandleReady() or OnHandleError() functions as necessary. Returns |true|
- // if any handles were ready and processed.
- bool ProcessReadyHandles();
-
- // Removes any handles that have expired their deadline. Runs the handler's
- // OnHandleError() function with |MOJO_RESULT_DEADLINE_EXCEEDED| as the
- // result. Returns |true| if any handles were removed.
- bool RemoveExpiredHandles();
-
- void SignalControlPipe();
-
- // Returns the deadline for the call to MojoWait().
- MojoDeadline GetDeadlineForWait(const RunState& run_state) const;
-
- // Run |OnHandleReady()| for the handler registered with |handle|. |handle|
- // must be registered.
- void SignalHandleReady(Handle handle);
-
- // Run |OnHandleError()| for the handler registered with |handle| and the
- // error code |result|. |handle| must be registered, and will be removed
- // before calling |OnHandleError()|.
- void SignalHandleError(Handle handle, MojoResult result);
-
- void WillSignalHandler();
- void DidSignalHandler();
-
- // If non-NULL we're running (inside Run()). Member is reference to value on
- // stack.
- RunState* run_state_;
-
- // Lock for accessing |run_state_|. In general the only method that we have to
- // worry about is ScheduleWork(). All other methods are invoked on the same
- // thread.
- base::Lock run_state_lock_;
-
- HandleToHandler handlers_;
- // Set of handles that have a deadline set. Avoids iterating over all elements
- // in |handles_| in the common case (no deadline set).
- // TODO(amistry): Make this better and avoid special-casing deadlines.
- std::set<Handle> deadline_handles_;
-
- // An ever increasing value assigned to each Handler::id. Used to detect
- // uniqueness while notifying. That is, while notifying expired timers we copy
- // |handlers_| 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_;
-
- base::ObserverList<Observer> observers_;
-
- // Mojo handle for the wait set.
- ScopedHandle wait_set_handle_;
- // Used to wake up run loop from |SignalControlPipe()|.
- ScopedMessagePipeHandle read_handle_;
- ScopedMessagePipeHandle write_handle_;
-
- // Used to sleep until there is more work to do, when the Mojo EDK is shutting
- // down.
- base::WaitableEvent event_;
-
- DISALLOW_COPY_AND_ASSIGN(MessagePumpMojo);
-};
-
-} // namespace common
-} // namespace mojo
-
-#endif // MOJO_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_H_
diff --git a/chromium/mojo/message_pump/message_pump_mojo_handler.h b/chromium/mojo/message_pump/message_pump_mojo_handler.h
deleted file mode 100644
index 8beb9baa340..00000000000
--- a/chromium/mojo/message_pump/message_pump_mojo_handler.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_HANDLER_H_
-#define MOJO_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_HANDLER_H_
-
-#include "mojo/message_pump/mojo_message_pump_export.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace mojo {
-namespace common {
-
-// Used by MessagePumpMojo to notify when a handle is either ready or has become
-// invalid. In case of error, the handler will be removed.
-class MOJO_MESSAGE_PUMP_EXPORT MessagePumpMojoHandler {
- public:
- virtual void OnHandleReady(const Handle& handle) = 0;
-
- virtual void OnHandleError(const Handle& handle, MojoResult result) = 0;
-
- protected:
- virtual ~MessagePumpMojoHandler() {}
-};
-
-} // namespace common
-} // namespace mojo
-
-#endif // MOJO_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_HANDLER_H_
diff --git a/chromium/mojo/message_pump/message_pump_mojo_unittest.cc b/chromium/mojo/message_pump/message_pump_mojo_unittest.cc
deleted file mode 100644
index 1abb27cfe96..00000000000
--- a/chromium/mojo/message_pump/message_pump_mojo_unittest.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-// 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/message_pump/message_pump_mojo.h"
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop_test.h"
-#include "base/run_loop.h"
-#include "mojo/message_pump/message_pump_mojo_handler.h"
-#include "mojo/public/cpp/system/core.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace common {
-namespace test {
-
-std::unique_ptr<base::MessagePump> CreateMojoMessagePump() {
- return std::unique_ptr<base::MessagePump>(new MessagePumpMojo());
-}
-
-RUN_MESSAGE_LOOP_TESTS(Mojo, &CreateMojoMessagePump);
-
-class CountingMojoHandler : public MessagePumpMojoHandler {
- public:
- CountingMojoHandler() : success_count_(0), error_count_(0) {}
-
- void OnHandleReady(const Handle& handle) override {
- ReadMessageRaw(static_cast<const MessagePipeHandle&>(handle),
- NULL,
- NULL,
- NULL,
- NULL,
- MOJO_READ_MESSAGE_FLAG_NONE);
- ++success_count_;
- if (success_count_ == success_callback_count_ &&
- !success_callback_.is_null()) {
- success_callback_.Run();
- success_callback_.Reset();
- }
- }
-
- void set_success_callback(const base::Closure& callback,
- int success_count) {
- success_callback_ = callback;
- success_callback_count_ = success_count;
- }
-
- void OnHandleError(const Handle& handle, MojoResult result) override {
- ++error_count_;
- if (!error_callback_.is_null()) {
- error_callback_.Run();
- error_callback_.Reset();
- }
- }
-
- void set_error_callback(const base::Closure& callback) {
- error_callback_ = callback;
- }
-
- int success_count() { return success_count_; }
- int error_count() { return error_count_; }
-
- private:
- int success_count_;
- int error_count_;
-
- base::Closure error_callback_;
- int success_callback_count_;
-
- base::Closure success_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(CountingMojoHandler);
-};
-
-class CountingObserver : public MessagePumpMojo::Observer {
- public:
- void WillSignalHandler() override { will_signal_handler_count++; }
- void DidSignalHandler() override { did_signal_handler_count++; }
-
- int will_signal_handler_count = 0;
- int did_signal_handler_count = 0;
-};
-
-TEST(MessagePumpMojo, RunUntilIdle) {
- base::MessageLoop message_loop(MessagePumpMojo::Create());
- CountingMojoHandler handler;
- base::RunLoop run_loop;
- handler.set_success_callback(run_loop.QuitClosure(), 2);
- MessagePipe handles;
- MessagePumpMojo::current()->AddHandler(&handler,
- handles.handle0.get(),
- MOJO_HANDLE_SIGNAL_READABLE,
- base::TimeTicks());
- WriteMessageRaw(
- handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
- WriteMessageRaw(
- handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
- MojoHandleSignalsState hss;
- ASSERT_EQ(MOJO_RESULT_OK,
- MojoWait(handles.handle0.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &hss));
- run_loop.Run();
- EXPECT_EQ(2, handler.success_count());
-}
-
-TEST(MessagePumpMojo, Observer) {
- base::MessageLoop message_loop(MessagePumpMojo::Create());
-
- CountingObserver observer;
- MessagePumpMojo::current()->AddObserver(&observer);
-
- CountingMojoHandler handler;
- base::RunLoop run_loop;
- handler.set_success_callback(run_loop.QuitClosure(), 1);
- MessagePipe handles;
- MessagePumpMojo::current()->AddHandler(&handler,
- handles.handle0.get(),
- MOJO_HANDLE_SIGNAL_READABLE,
- base::TimeTicks());
- WriteMessageRaw(
- handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
-
- MojoHandleSignalsState hss;
- ASSERT_EQ(MOJO_RESULT_OK,
- MojoWait(handles.handle0.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &hss));
- run_loop.Run();
- EXPECT_EQ(1, handler.success_count());
- EXPECT_EQ(1, observer.will_signal_handler_count);
- EXPECT_EQ(1, observer.did_signal_handler_count);
- MessagePumpMojo::current()->RemoveObserver(&observer);
-
- base::RunLoop run_loop2;
- handler.set_success_callback(run_loop2.QuitClosure(), 2);
- WriteMessageRaw(
- handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
- ASSERT_EQ(MOJO_RESULT_OK,
- MojoWait(handles.handle0.get().value(), MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &hss));
- run_loop2.Run();
- EXPECT_EQ(2, handler.success_count());
- EXPECT_EQ(1, observer.will_signal_handler_count);
- EXPECT_EQ(1, observer.did_signal_handler_count);
-}
-
-TEST(MessagePumpMojo, UnregisterAfterDeadline) {
- base::MessageLoop message_loop(MessagePumpMojo::Create());
- CountingMojoHandler handler;
- base::RunLoop run_loop;
- handler.set_error_callback(run_loop.QuitClosure());
- MessagePipe handles;
- MessagePumpMojo::current()->AddHandler(
- &handler,
- handles.handle0.get(),
- MOJO_HANDLE_SIGNAL_READABLE,
- base::TimeTicks::Now() - base::TimeDelta::FromSeconds(1));
- run_loop.Run();
- EXPECT_EQ(1, handler.error_count());
-}
-
-TEST(MessagePumpMojo, AddClosedHandle) {
- base::MessageLoop message_loop(MessagePumpMojo::Create());
- CountingMojoHandler handler;
- MessagePipe handles;
- Handle closed_handle = handles.handle0.get();
- handles.handle0.reset();
- MessagePumpMojo::current()->AddHandler(
- &handler, closed_handle, MOJO_HANDLE_SIGNAL_READABLE, base::TimeTicks());
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
- MessagePumpMojo::current()->RemoveHandler(closed_handle);
- EXPECT_EQ(0, handler.error_count());
- EXPECT_EQ(0, handler.success_count());
-}
-
-TEST(MessagePumpMojo, CloseAfterAdding) {
- base::MessageLoop message_loop(MessagePumpMojo::Create());
- CountingMojoHandler handler;
- MessagePipe handles;
- MessagePumpMojo::current()->AddHandler(&handler, handles.handle0.get(),
- MOJO_HANDLE_SIGNAL_READABLE,
- base::TimeTicks());
- handles.handle0.reset();
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
- EXPECT_EQ(1, handler.error_count());
- EXPECT_EQ(0, handler.success_count());
-}
-
-} // namespace test
-} // namespace common
-} // namespace mojo
diff --git a/chromium/mojo/message_pump/mojo_message_pump_export.h b/chromium/mojo/message_pump/mojo_message_pump_export.h
deleted file mode 100644
index f8c1864b018..00000000000
--- a/chromium/mojo/message_pump/mojo_message_pump_export.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 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_MESSAGE_PUMP_MOJO_MESSAGE_PUMP_EXPORT_H_
-#define MOJO_MESSAGE_PUMP_MOJO_MESSAGE_PUMP_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-
-#if defined(WIN32)
-
-#if defined(MOJO_MESSAGE_PUMP_IMPLEMENTATION)
-#define MOJO_MESSAGE_PUMP_EXPORT __declspec(dllexport)
-#else
-#define MOJO_MESSAGE_PUMP_EXPORT __declspec(dllimport)
-#endif
-
-#else // !defined(WIN32)
-
-#if defined(MOJO_MESSAGE_PUMP_IMPLEMENTATION)
-#define MOJO_MESSAGE_PUMP_EXPORT __attribute__((visibility("default")))
-#else
-#define MOJO_MESSAGE_PUMP_EXPORT
-#endif
-
-#endif // defined(WIN32)
-
-#else // !defined(COMPONENT_BUILD)
-#define MOJO_MESSAGE_PUMP_EXPORT
-#endif
-
-#endif // MOJO_MESSAGE_PUMP_MOJO_MESSAGE_PUMP_EXPORT_H_
diff --git a/chromium/mojo/message_pump/time_helper.cc b/chromium/mojo/message_pump/time_helper.cc
deleted file mode 100644
index ffd667e47d7..00000000000
--- a/chromium/mojo/message_pump/time_helper.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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/message_pump/time_helper.h"
-
-#include "base/time/tick_clock.h"
-
-namespace mojo {
-namespace common {
-
-namespace {
-
-base::TickClock* tick_clock = NULL;
-
-} // namespace
-
-namespace test {
-
-void SetTickClockForTest(base::TickClock* clock) {
- tick_clock = clock;
-}
-} // namespace test
-
-namespace internal {
-
-base::TimeTicks NowTicks() {
- return tick_clock ? tick_clock->NowTicks() : base::TimeTicks::Now();
-}
-
-} // namespace internal
-} // namespace common
-} // namespace mojo
diff --git a/chromium/mojo/message_pump/time_helper.h b/chromium/mojo/message_pump/time_helper.h
deleted file mode 100644
index 60790004393..00000000000
--- a/chromium/mojo/message_pump/time_helper.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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_MESSAGE_PUMP_TIME_HELPER_H_
-#define MOJO_MESSAGE_PUMP_TIME_HELPER_H_
-
-#include "base/time/time.h"
-#include "mojo/message_pump/mojo_message_pump_export.h"
-
-namespace base {
-class TickClock;
-}
-
-namespace mojo {
-namespace common {
-namespace test {
-
-// Sets the TickClock used for getting TimeTicks::Now(). This is currently used
-// by both HandleWatcher and MessagePumpMojo.
-MOJO_MESSAGE_PUMP_EXPORT void SetTickClockForTest(base::TickClock* clock);
-
-} // namespace test
-
-namespace internal {
-
-// Returns now. Used internally; generally not useful.
-MOJO_MESSAGE_PUMP_EXPORT base::TimeTicks NowTicks();
-
-} // namespace internal
-} // namespace common
-} // namespace mojo
-
-#endif // MOJO_MESSAGE_PUMP_TIME_HELPER_H_
diff --git a/chromium/mojo/mojo.gyp b/chromium/mojo/mojo.gyp
deleted file mode 100644
index 1ef0c4d520d..00000000000
--- a/chromium/mojo/mojo.gyp
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-{
- 'targets': [
- {
- # GN version: //mojo
- 'target_name': 'mojo',
- 'type': 'none',
- 'dependencies': [
- 'mojo_base.gyp:mojo_base',
- 'mojo_edk_tests.gyp:mojo_edk_tests',
- 'mojo_public.gyp:mojo_public',
- ],
- },
- ]
-}
diff --git a/chromium/mojo/mojo_base.gyp b/chromium/mojo/mojo_base.gyp
deleted file mode 100644
index a067353fa3a..00000000000
--- a/chromium/mojo/mojo_base.gyp
+++ /dev/null
@@ -1,192 +0,0 @@
-# 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.
-
-# Essential components (and their tests) that are needed to build
-# Chrome should be here. Other components that are useful only in
-# Mojo land like mojo_shell should be in mojo.gyp.
-{
- 'variables': {
- 'chromium_code': 1,
- },
- 'targets': [
- {
- 'target_name': 'mojo_base',
- 'type': 'none',
- 'dependencies': [
- # NOTE: If adding a new dependency here, please consider whether it
- # should also be added to the list of Mojo-related dependencies of
- # build/all.gyp:All on iOS, as All cannot depend on the mojo_base
- # target on iOS due to the presence of the js targets, which cause v8
- # to be built.
- 'mojo_common_lib',
- 'mojo_common_unittests',
- ],
- 'conditions': [
- ['OS == "android"', {
- 'dependencies': [
- 'mojo_public.gyp:mojo_bindings_java',
- 'mojo_public.gyp:mojo_public_java',
- ],
- }],
- ]
- },
- {
- 'target_name': 'mojo_none',
- 'type': 'none',
- },
- {
- # GN version: //mojo/common
- 'target_name': 'mojo_common_lib',
- 'type': '<(component)',
- 'defines': [
- 'MOJO_COMMON_IMPLEMENTATION',
- ],
- 'dependencies': [
- '../base/base.gyp:base',
- '../mojo/mojo_public.gyp:mojo_public_system',
- ],
- 'sources': [
- 'common/common_type_converters.cc',
- 'common/common_type_converters.h',
- 'common/data_pipe_file_utils.cc',
- 'common/data_pipe_utils.cc',
- 'common/data_pipe_utils.h',
- ],
- },
- {
- # GN version: //mojo/common:common_custom_types
- 'target_name': 'mojo_common_custom_types_mojom',
- 'type': 'none',
- 'variables': {
- 'mojom_files': [
- 'common/common_custom_types.mojom',
- ],
- 'mojom_typemaps': [
- 'common/common_custom_types.typemap',
- ],
- },
- 'dependencies': [
- '../ipc/ipc.gyp:ipc',
- ],
- 'includes': [ 'mojom_bindings_generator_explicit.gypi' ],
- },
- {
- # GN version: //mojo/common:test_common_custom_types
- 'target_name': 'mojo_test_common_custom_types',
- 'type': 'static_library',
- 'variables': {
- 'mojom_typemaps': [
- 'common/common_custom_types.typemap',
- ],
- },
- 'sources': [
- 'common/test_common_custom_types.mojom',
- ],
- 'dependencies': [
- 'mojo_common_custom_types_mojom',
- ],
- 'includes': [ 'mojom_bindings_generator.gypi' ],
- },
- {
- # GN version: //mojo/common:mojo_common_unittests
- 'target_name': 'mojo_common_unittests',
- 'type': 'executable',
- 'dependencies': [
- '../base/base.gyp:base',
- '../base/base.gyp:test_support_base',
- '../base/base.gyp:base_message_loop_tests',
- '../testing/gtest.gyp:gtest',
- '../url/url.gyp:url_lib',
- 'mojo_common_custom_types_mojom',
- 'mojo_common_lib',
- 'mojo_test_common_custom_types',
- 'mojo_edk.gyp:mojo_system_impl',
- 'mojo_edk.gyp:mojo_common_test_support',
- 'mojo_edk.gyp:mojo_run_all_unittests',
- 'mojo_public.gyp:mojo_cpp_bindings',
- 'mojo_public.gyp:mojo_public_test_utils',
- ],
- 'sources': [
- 'common/common_custom_types_unittest.cc',
- 'common/common_type_converters_unittest.cc',
- ],
- },
- ],
- 'conditions': [
- ['OS=="android"', {
- 'targets': [
- {
- 'target_name': 'mojo_jni_headers',
- 'type': 'none',
- 'dependencies': [
- 'mojo_java_set_jni_headers',
- ],
- 'sources': [
- 'android/javatests/src/org/chromium/mojo/MojoTestCase.java',
- 'android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java',
- 'android/system/src/org/chromium/mojo/system/impl/CoreImpl.java',
- ],
- 'variables': {
- 'jni_gen_package': 'mojo',
- },
- 'includes': [ '../build/jni_generator.gypi' ],
- },
- {
- 'target_name': 'libmojo_system_java',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- 'mojo_common_lib',
- 'mojo_edk.gyp:mojo_system_impl',
- 'mojo_jni_headers',
- 'mojo_public.gyp:mojo_message_pump_lib',
- ],
- 'sources': [
- 'android/system/core_impl.cc',
- 'android/system/core_impl.h',
- ],
- },
- {
- 'target_name': 'mojo_java_set_jni_headers',
- 'type': 'none',
- 'variables': {
- 'jni_gen_package': 'mojo',
- 'input_java_class': 'java/util/HashSet.class',
- },
- 'includes': [ '../build/jar_file_jni_generator.gypi' ],
- },
- {
- 'target_name': 'mojo_system_java',
- 'type': 'none',
- 'dependencies': [
- '../base/base.gyp:base_java',
- 'libmojo_system_java',
- 'mojo_public.gyp:mojo_public_java',
- ],
- 'variables': {
- 'java_in_dir': '<(DEPTH)/mojo/android/system',
- },
- 'includes': [ '../build/java.gypi' ],
- },
- ],
- }],
- ['test_isolation_mode != "noop"', {
- 'targets': [
- {
- 'target_name': 'mojo_common_unittests_run',
- 'type': 'none',
- 'dependencies': [
- 'mojo_common_unittests',
- ],
- 'includes': [
- '../build/isolate.gypi',
- ],
- 'sources': [
- 'mojo_common_unittests.isolate',
- ],
- },
- ],
- }],
- ]
-}
diff --git a/chromium/mojo/mojo_common_unittests.isolate b/chromium/mojo/mojo_common_unittests.isolate
deleted file mode 100644
index a72311cd59e..00000000000
--- a/chromium/mojo/mojo_common_unittests.isolate
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2015 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.
-{
- 'includes': [
- '../base/base.isolate',
- ],
- 'conditions': [
- ['OS=="win" or OS=="mac" or OS=="linux"', {
- 'variables': {
- 'command': [
- '../testing/test_env.py',
- '<(PRODUCT_DIR)/mojo_common_unittests<(EXECUTABLE_SUFFIX)',
- '--brave-new-test-launcher',
- '--test-launcher-bot-mode',
- ],
- 'files': [
- '../testing/test_env.py',
- ],
- },
- }],
- ],
-}
diff --git a/chromium/mojo/mojo_edk.gyp b/chromium/mojo/mojo_edk.gyp
deleted file mode 100644
index 5541839b01f..00000000000
--- a/chromium/mojo/mojo_edk.gyp
+++ /dev/null
@@ -1,233 +0,0 @@
-# Copyright 2015 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': {
- 'chromium_code': 1,
- },
- 'includes': [
- 'mojo_edk.gypi',
- ],
- 'target_defaults' : {
- 'include_dirs': [
- '..',
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '..',
- ],
- },
- },
- 'targets': [
- {
- # GN version: //mojo/edk/system/ports
- 'target_name': 'mojo_system_ports',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- '../crypto/crypto.gyp:crypto',
- ],
- 'sources': [
- '<@(mojo_edk_ports_sources)',
- ],
- },
- {
- # GN version: //mojo/edk/system
- 'target_name': 'mojo_system_impl',
- 'type': '<(component)',
- 'dependencies': [
- '../base/base.gyp:base',
- '../crypto/crypto.gyp:crypto',
- 'mojo_public.gyp:mojo_public_system',
- 'mojo_system_ports',
- ],
- 'defines': [
- 'MOJO_SYSTEM_IMPL_IMPLEMENTATION',
- ],
- 'sources': [
- '<@(mojo_edk_system_impl_sources)',
- '<@(mojo_edk_system_impl_non_nacl_sources)',
- ],
- 'conditions': [
- ['OS=="android"', {
- 'dependencies': [
- '../third_party/ashmem/ashmem.gyp:ashmem',
- ],
- }],
- ['OS=="android" or chromeos==1', {
- 'defines': [
- 'MOJO_EDK_LEGACY_PROTOCOL',
- ],
- }],
- ['OS=="win"', {
- # Structure was padded due to __declspec(align()), which is
- # uninteresting.
- 'msvs_disabled_warnings': [ 4324 ],
- }],
- ['OS=="mac" and OS!="ios"', {
- 'sources': [
- 'edk/system/mach_port_relay.cc',
- 'edk/system/mach_port_relay.h',
- ],
- }],
- ],
- },
- {
- # GN version: //mojo/edk/js
- 'target_name': 'mojo_js_lib',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- '../gin/gin.gyp:gin',
- '../v8/src/v8.gyp:v8',
- ],
- 'export_dependent_settings': [
- '../base/base.gyp:base',
- '../gin/gin.gyp:gin',
- ],
- 'sources': [
- # Sources list duplicated in GN build.
- 'edk/js/core.cc',
- 'edk/js/core.h',
- 'edk/js/drain_data.cc',
- 'edk/js/drain_data.h',
- 'edk/js/handle.cc',
- 'edk/js/handle.h',
- 'edk/js/handle_close_observer.h',
- 'edk/js/mojo_runner_delegate.cc',
- 'edk/js/mojo_runner_delegate.h',
- 'edk/js/support.cc',
- 'edk/js/support.h',
- 'edk/js/threading.cc',
- 'edk/js/threading.h',
- 'edk/js/waiting_callback.cc',
- 'edk/js/waiting_callback.h',
- ],
- },
- {
- # GN version: //mojo/edk/test:test_support_impl
- 'target_name': 'mojo_test_support_impl',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- ],
- 'sources': [
- 'edk/test/test_support_impl.cc',
- 'edk/test/test_support_impl.h',
- ],
- },
- {
- # GN version: //mojo/edk/test:test_support
- 'target_name': 'mojo_common_test_support',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- '../base/base.gyp:test_support_base',
- '../testing/gtest.gyp:gtest',
- 'mojo_system_impl',
- ],
- 'sources': [
- 'edk/test/mojo_test_base.cc',
- 'edk/test/mojo_test_base.h',
- 'edk/test/multiprocess_test_helper.cc',
- 'edk/test/multiprocess_test_helper.h',
- 'edk/test/scoped_ipc_support.cc',
- 'edk/test/scoped_ipc_support.h',
- 'edk/test/test_utils.h',
- 'edk/test/test_utils_posix.cc',
- 'edk/test/test_utils_win.cc',
- ],
- 'conditions': [
- ['OS=="ios"', {
- 'sources!': [
- 'edk/test/multiprocess_test_helper.cc',
- ],
- }],
- ],
- },
- {
- # GN version: //mojo/edk/test:run_all_unittests
- 'target_name': 'mojo_run_all_unittests',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- '../base/base.gyp:test_support_base',
- '../testing/gtest.gyp:gtest',
- 'mojo_common_test_support',
- 'mojo_public.gyp:mojo_public_test_support',
- 'mojo_system_impl',
- 'mojo_test_support_impl',
- ],
- 'sources': [
- 'edk/test/run_all_unittests.cc',
- ],
- },
- {
- # GN version: //mojo/edk/test:run_all_perftests
- 'target_name': 'mojo_run_all_perftests',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- '../base/base.gyp:test_support_base',
- '../testing/gtest.gyp:gtest',
- 'mojo_common_test_support',
- 'mojo_public.gyp:mojo_public_test_support',
- 'mojo_system_impl',
- 'mojo_test_support_impl',
- ],
- 'sources': [
- 'edk/test/run_all_perftests.cc',
- ],
- },
- ],
- 'conditions': [
- ['OS == "win" and target_arch=="ia32"', {
- 'targets': [
- {
- # GN version: //mojo/edk/system/ports
- 'target_name': 'mojo_system_ports_win64',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base_win64',
- '../crypto/crypto.gyp:crypto_nacl_win64',
- ],
- 'sources': [
- '<@(mojo_edk_ports_sources)',
- ],
- 'configurations': {
- 'Common_Base': {
- 'msvs_target_platform': 'x64',
- },
- },
- },
- {
- # GN version: //mojo/edk/system
- 'target_name': 'mojo_system_impl_win64',
- 'type': '<(component)',
- 'dependencies': [
- '../base/base.gyp:base_win64',
- '../crypto/crypto.gyp:crypto_nacl_win64',
- 'mojo_public.gyp:mojo_public_system_win64',
- 'mojo_system_ports_win64',
- ],
- 'defines': [
- 'MOJO_SYSTEM_IMPL_IMPLEMENTATION',
- ],
- 'sources': [
- '<@(mojo_edk_system_impl_sources)',
- '<@(mojo_edk_system_impl_non_nacl_sources)',
- ],
- # Structure was padded due to __declspec(align()), which is
- # uninteresting.
- 'msvs_disabled_warnings': [ 4324 ],
- 'configurations': {
- 'Common_Base': {
- 'msvs_target_platform': 'x64',
- },
- },
- },
- ],
- }],
- ]
-}
diff --git a/chromium/mojo/mojo_edk.gypi b/chromium/mojo/mojo_edk.gypi
deleted file mode 100644
index 7039c7bace9..00000000000
--- a/chromium/mojo/mojo_edk.gypi
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright 2016 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': {
- 'mojo_edk_ports_sources': [
- 'edk/system/ports/event.cc',
- 'edk/system/ports/event.h',
- 'edk/system/ports/message.cc',
- 'edk/system/ports/message.h',
- 'edk/system/ports/message_queue.cc',
- 'edk/system/ports/message_queue.h',
- 'edk/system/ports/name.cc',
- 'edk/system/ports/name.h',
- 'edk/system/ports/node.cc',
- 'edk/system/ports/node.h',
- 'edk/system/ports/node_delegate.h',
- 'edk/system/ports/port.cc',
- 'edk/system/ports/port.h',
- 'edk/system/ports/port_ref.cc',
- 'edk/system/ports/user_data.h',
- 'edk/system/ports_message.cc',
- 'edk/system/ports_message.h',
- ],
- 'mojo_edk_system_impl_sources': [
- 'edk/embedder/configuration.h',
- 'edk/embedder/embedder.cc',
- 'edk/embedder/embedder.h',
- 'edk/embedder/embedder_internal.h',
- 'edk/embedder/entrypoints.cc',
- 'edk/embedder/named_platform_channel_pair_win.cc',
- 'edk/embedder/named_platform_channel_pair.h',
- 'edk/embedder/platform_channel_pair.cc',
- 'edk/embedder/platform_channel_pair.h',
- 'edk/embedder/platform_channel_pair_posix.cc',
- 'edk/embedder/platform_channel_pair_win.cc',
- 'edk/embedder/platform_handle.cc',
- 'edk/embedder/platform_handle.h',
- 'edk/embedder/platform_handle_utils.h',
- 'edk/embedder/platform_handle_utils_posix.cc',
- 'edk/embedder/platform_handle_utils_win.cc',
- 'edk/embedder/platform_handle_vector.h',
- 'edk/embedder/platform_shared_buffer.cc',
- 'edk/embedder/platform_shared_buffer.h',
- 'edk/embedder/scoped_ipc_support.cc',
- 'edk/embedder/scoped_ipc_support.h',
- 'edk/embedder/scoped_platform_handle.h',
- 'edk/system/awakable.h',
- 'edk/system/awakable_list.cc',
- 'edk/system/awakable_list.h',
- 'edk/system/async_waiter.cc',
- 'edk/system/async_waiter.h',
- 'edk/system/atomic_flag.h',
- 'edk/system/broker.h',
- 'edk/system/broker_host.h',
- 'edk/system/channel.cc',
- 'edk/system/channel.h',
- 'edk/system/channel_win.cc',
- 'edk/system/configuration.cc',
- 'edk/system/configuration.h',
- 'edk/system/core.cc',
- 'edk/system/core.h',
- 'edk/system/data_pipe_consumer_dispatcher.cc',
- 'edk/system/data_pipe_consumer_dispatcher.h',
- 'edk/system/data_pipe_control_message.cc',
- 'edk/system/data_pipe_control_message.h',
- 'edk/system/data_pipe_producer_dispatcher.cc',
- 'edk/system/data_pipe_producer_dispatcher.h',
- 'edk/system/dispatcher.cc',
- 'edk/system/dispatcher.h',
- 'edk/system/handle_signals_state.h',
- 'edk/system/handle_table.cc',
- 'edk/system/handle_table.h',
- 'edk/system/mapping_table.cc',
- 'edk/system/mapping_table.h',
- 'edk/system/message_for_transit.cc',
- 'edk/system/message_for_transit.h',
- 'edk/system/message_pipe_dispatcher.cc',
- 'edk/system/message_pipe_dispatcher.h',
- 'edk/system/node_channel.cc',
- 'edk/system/node_channel.h',
- 'edk/system/node_controller.cc',
- 'edk/system/node_controller.h',
- 'edk/system/options_validation.h',
- 'edk/system/platform_handle_dispatcher.cc',
- 'edk/system/platform_handle_dispatcher.h',
- 'edk/system/remote_message_pipe_bootstrap.h',
- 'edk/system/request_context.cc',
- 'edk/system/request_context.h',
- 'edk/system/shared_buffer_dispatcher.cc',
- 'edk/system/shared_buffer_dispatcher.h',
- 'edk/system/wait_set_dispatcher.cc',
- 'edk/system/wait_set_dispatcher.h',
- 'edk/system/waiter.cc',
- 'edk/system/waiter.h',
- 'edk/system/watcher.cc',
- 'edk/system/watcher.h',
- 'edk/system/watcher_set.cc',
- 'edk/system/watcher_set.h',
- # Test-only code:
- # TODO(vtl): It's a little unfortunate that these end up in the same
- # component as non-test-only code. In the static build, this code
- # should hopefully be dead-stripped.
- 'edk/embedder/test_embedder.cc',
- 'edk/embedder/test_embedder.h',
- ],
- 'mojo_edk_system_impl_non_nacl_sources': [
- 'edk/embedder/platform_channel_utils_posix.cc',
- 'edk/embedder/platform_channel_utils_posix.h',
- 'edk/system/broker_host_posix.cc',
- 'edk/system/broker_posix.cc',
- 'edk/system/channel_posix.cc',
- 'edk/system/remote_message_pipe_bootstrap.cc',
- ],
- 'mojo_edk_system_impl_nacl_nonsfi_sources': [
- 'edk/embedder/platform_channel_utils_posix.cc',
- 'edk/embedder/platform_channel_utils_posix.h',
- 'edk/system/broker_posix.cc',
- 'edk/system/channel_posix.cc',
- ],
- },
-}
diff --git a/chromium/mojo/mojo_edk_nacl.gyp b/chromium/mojo/mojo_edk_nacl.gyp
deleted file mode 100644
index b4df059ac76..00000000000
--- a/chromium/mojo/mojo_edk_nacl.gyp
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright 2015 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': {
- 'chromium_code': 1,
- },
- 'includes': [
- '../build/common_untrusted.gypi',
- 'mojo_edk.gypi',
- ],
- 'target_defaults' : {
- 'include_dirs': [
- '..',
- ],
- },
- 'targets': [
- {
- # GN version: //mojo/edk/system
- 'target_name': 'mojo_system_impl_nacl',
- 'type': 'none',
- 'variables': {
- 'nacl_untrusted_build': 1,
- 'nlib_target': 'libmojo_system_impl_nacl.a',
- 'build_glibc': 0,
- 'build_newlib': 0,
- 'build_irt': 1,
- 'build_pnacl_newlib': 0,
- 'build_nonsfi_helper': 0,
- },
- 'dependencies': [
- '../base/base_nacl.gyp:base_nacl',
- '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- 'mojo_public.gyp:mojo_public_system',
- ],
- 'defines': [
- 'MOJO_SYSTEM_IMPL_IMPLEMENTATION',
- ],
- 'sources': [
- '<@(mojo_edk_ports_sources)',
- '<@(mojo_edk_system_impl_sources)',
- ],
- 'conditions': [
- ['OS=="android" or chromeos==1', {
- 'defines': [
- 'MOJO_EDK_LEGACY_PROTOCOL',
- ],
- }],
- ],
- },
- {
- 'target_name': 'mojo_system_impl_nacl_nonsfi',
- 'type': 'none',
- 'variables': {
- 'nacl_untrusted_build': 1,
- 'nlib_target': 'libmojo_system_impl_nacl_nonsfi.a',
- 'build_glibc': 0,
- 'build_newlib': 0,
- 'build_irt': 0,
- 'build_pnacl_newlib': 0,
- 'build_nonsfi_helper': 1,
- },
- 'dependencies': [
- '../base/base_nacl.gyp:base_nacl_nonsfi',
- 'mojo_public.gyp:mojo_public_system',
- ],
- 'defines': [
- 'MOJO_SYSTEM_IMPL_IMPLEMENTATION',
- ],
- 'sources': [
- '<@(mojo_edk_ports_sources)',
- '<@(mojo_edk_system_impl_sources)',
- '<@(mojo_edk_system_impl_nacl_nonsfi_sources)',
- ],
- 'conditions': [
- ['OS=="android" or chromeos==1', {
- 'defines': [
- 'MOJO_EDK_LEGACY_PROTOCOL',
- ],
- }],
- ],
- },
- ],
-}
diff --git a/chromium/mojo/mojo_edk_tests.gyp b/chromium/mojo/mojo_edk_tests.gyp
deleted file mode 100644
index e1924621337..00000000000
--- a/chromium/mojo/mojo_edk_tests.gyp
+++ /dev/null
@@ -1,397 +0,0 @@
-# Copyright 2015 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': {
- 'chromium_code': 1,
- },
- 'targets': [
- {
- 'target_name': 'mojo_edk_tests',
- 'type': 'none',
- 'dependencies': [
- # NOTE: If adding a new dependency here, please consider whether it
- # should also be added to the list of Mojo-related dependencies of
- # build/all.gyp:All on iOS, as All cannot depend on the mojo_base
- # target on iOS due to the presence of the js targets, which cause v8
- # to be built.
- 'mojo_message_pipe_perftests',
- 'mojo_public_bindings_perftests',
- 'mojo_public_bindings_unittests',
- 'mojo_public_system_perftests',
- 'mojo_public_system_unittests',
- 'mojo_system_unittests',
- 'mojo_js_unittests',
- 'mojo_js_integration_tests',
- ],
- },
- {
- # GN version: //mojo/edk/test:mojo_public_bindings_unittests
- 'target_name': 'mojo_public_bindings_unittests',
- 'type': 'executable',
- 'dependencies': [
- '../testing/gtest.gyp:gtest',
- 'mojo_edk.gyp:mojo_run_all_unittests',
- 'mojo_public.gyp:mojo_cpp_bindings',
- 'mojo_public.gyp:mojo_public_bindings_test_utils',
- 'mojo_public.gyp:mojo_public_test_utils',
- 'mojo_public_tests.gyp:mojo_public_test_associated_interfaces',
- 'mojo_public_tests.gyp:mojo_public_test_interfaces',
- 'mojo_public_tests.gyp:mojo_public_test_interfaces_blink',
- 'mojo_public_tests.gyp:mojo_public_test_interfaces_struct_traits',
- ],
- 'variables': {
- 'clang_warning_flags_unset': [ '-Wglobal-constructors' ],
- },
- 'sources': [
- 'public/cpp/bindings/tests/array_common_test.h',
- 'public/cpp/bindings/tests/array_unittest.cc',
- 'public/cpp/bindings/tests/associated_interface_unittest.cc',
- 'public/cpp/bindings/tests/bind_task_runner_unittest.cc',
- 'public/cpp/bindings/tests/binding_callback_unittest.cc',
- 'public/cpp/bindings/tests/binding_unittest.cc',
- 'public/cpp/bindings/tests/buffer_unittest.cc',
- 'public/cpp/bindings/tests/connector_unittest.cc',
- 'public/cpp/bindings/tests/constant_unittest.cc',
- 'public/cpp/bindings/tests/container_test_util.cc',
- 'public/cpp/bindings/tests/container_test_util.h',
- 'public/cpp/bindings/tests/equals_unittest.cc',
- 'public/cpp/bindings/tests/handle_passing_unittest.cc',
- 'public/cpp/bindings/tests/interface_ptr_unittest.cc',
- 'public/cpp/bindings/tests/map_common_test.h',
- 'public/cpp/bindings/tests/map_unittest.cc',
- 'public/cpp/bindings/tests/message_queue.cc',
- 'public/cpp/bindings/tests/message_queue.h',
- 'public/cpp/bindings/tests/multiplex_router_unittest.cc',
- 'public/cpp/bindings/tests/pickle_unittest.cc',
- 'public/cpp/bindings/tests/pickled_types_blink.cc',
- 'public/cpp/bindings/tests/pickled_types_blink.h',
- 'public/cpp/bindings/tests/pickled_types_chromium.cc',
- 'public/cpp/bindings/tests/pickled_types_chromium.h',
- 'public/cpp/bindings/tests/rect_blink.h',
- 'public/cpp/bindings/tests/rect_blink_traits.h',
- 'public/cpp/bindings/tests/rect_chromium.h',
- 'public/cpp/bindings/tests/rect_chromium_traits.h',
- 'public/cpp/bindings/tests/request_response_unittest.cc',
- 'public/cpp/bindings/tests/router_test_util.cc',
- 'public/cpp/bindings/tests/router_test_util.h',
- 'public/cpp/bindings/tests/router_unittest.cc',
- 'public/cpp/bindings/tests/sample_service_unittest.cc',
- 'public/cpp/bindings/tests/serialization_warning_unittest.cc',
- 'public/cpp/bindings/tests/stl_converters_unittest.cc',
- 'public/cpp/bindings/tests/string_unittest.cc',
- 'public/cpp/bindings/tests/struct_traits_unittest.cc',
- 'public/cpp/bindings/tests/struct_unittest.cc',
- 'public/cpp/bindings/tests/struct_with_traits_impl.cc',
- 'public/cpp/bindings/tests/struct_with_traits_impl.h',
- 'public/cpp/bindings/tests/struct_with_traits_impl_traits.cc',
- 'public/cpp/bindings/tests/struct_with_traits_impl_traits.h',
- 'public/cpp/bindings/tests/sync_method_unittest.cc',
- 'public/cpp/bindings/tests/type_conversion_unittest.cc',
- 'public/cpp/bindings/tests/union_unittest.cc',
- 'public/cpp/bindings/tests/validation_context_unittest.cc',
- 'public/cpp/bindings/tests/validation_unittest.cc',
- 'public/cpp/bindings/tests/variant_test_util.h',
- ],
- 'conditions': [
- # TODO(yzshen): Blink-flavor bindings tests should be moved into
- # mojo_public_bindings_for_blink_tests (which should eventually be moved
- # into blink).
- ['OS=="ios"', {
- 'dependencies!': [
- 'mojo_public.gyp:mojo_public_test_interfaces_blink',
- ],
- 'sources!': [
- 'public/cpp/bindings/tests/pickle_unittest.cc',
- 'public/cpp/bindings/tests/pickled_types_blink.cc',
- 'public/cpp/bindings/tests/pickled_types_blink.h',
- 'public/cpp/bindings/tests/pickled_types_chromium.cc',
- 'public/cpp/bindings/tests/pickled_types_chromium.h',
- 'public/cpp/bindings/tests/rect_blink.h',
- 'public/cpp/bindings/tests/rect_blink_traits.h',
- 'public/cpp/bindings/tests/struct_traits_unittest.cc',
- ],
- }],
- ],
- },
- {
- # GN version: //mojo/public/cpp/bindings/tests:for_blink_tests
- 'target_name': 'mojo_public_bindings_for_blink_tests',
- 'type': 'static_library',
- 'dependencies': [
- '../testing/gtest.gyp:gtest',
- 'mojo_public.gyp:mojo_cpp_bindings',
- 'mojo_public_tests.gyp:mojo_public_test_interfaces',
- 'mojo_public_tests.gyp:mojo_public_test_wtf_types',
- 'mojo_public_tests.gyp:mojo_public_test_wtf_types_blink',
- ],
- 'variables': {
- 'clang_warning_flags_unset': [ '-Wglobal-constructors' ],
- },
- 'sources': [
- 'public/cpp/bindings/tests/array_common_test.h',
- 'public/cpp/bindings/tests/container_test_util.cc',
- 'public/cpp/bindings/tests/container_test_util.h',
- 'public/cpp/bindings/tests/map_common_test.h',
- 'public/cpp/bindings/tests/variant_test_util.h',
- 'public/cpp/bindings/tests/wtf_array_unittest.cc',
- 'public/cpp/bindings/tests/wtf_map_unittest.cc',
- 'public/cpp/bindings/tests/wtf_types_unittest.cc',
- ],
- },
- {
- # GN version: //mojo/edk/test:mojo_public_bindings_perftests
- 'target_name': 'mojo_public_bindings_perftests',
- 'type': 'executable',
- 'dependencies': [
- '../base/base.gyp:test_support_base',
- '../testing/gtest.gyp:gtest',
- 'mojo_base.gyp:mojo_common_lib',
- 'mojo_edk.gyp:mojo_run_all_perftests',
- 'mojo_public.gyp:mojo_cpp_bindings',
- 'mojo_public.gyp:mojo_public_bindings_test_utils',
- 'mojo_public.gyp:mojo_public_test_utils',
- 'mojo_public_tests.gyp:mojo_public_test_interfaces',
- ],
- 'sources': [
- 'public/cpp/bindings/tests/bindings_perftest.cc',
- 'public/cpp/bindings/tests/e2e_perftest.cc',
- ],
- },
- {
- # GN version: //mojo/public/cpp/system/tests:mojo_public_system_unittests
- # and //mojo/public/c/system/tests
- 'target_name': 'mojo_public_system_unittests',
- 'type': 'executable',
- 'dependencies': [
- '../testing/gtest.gyp:gtest',
- 'mojo_edk.gyp:mojo_run_all_unittests',
- 'mojo_public.gyp:mojo_cpp_system',
- 'mojo_public.gyp:mojo_public_test_utils',
- ],
- 'sources': [
- '<(DEPTH)/mojo/public/c/system/tests/core_unittest.cc',
- '<(DEPTH)/mojo/public/c/system/tests/core_unittest_pure_c.c',
- '<(DEPTH)/mojo/public/c/system/tests/macros_unittest.cc',
- '<(DEPTH)/mojo/public/cpp/system/tests/core_unittest.cc',
- '<(DEPTH)/mojo/public/cpp/system/tests/watcher_unittest.cc',
- ],
- },
- {
- # GN version: //mojo/edk/test:mojo_public_system_perftests
- 'target_name': 'mojo_public_system_perftests',
- 'type': 'executable',
- 'dependencies': [
- '../base/base.gyp:base',
- '../testing/gtest.gyp:gtest',
- 'mojo_edk.gyp:mojo_run_all_perftests',
- 'mojo_public.gyp:mojo_public_system',
- 'mojo_public.gyp:mojo_public_test_utils',
- ],
- 'sources': [
- 'public/c/system/tests/core_perftest.cc',
- ],
- },
- {
- # GN version: //mojo/edk/system:mojo_system_unittests
- 'target_name': 'mojo_system_unittests',
- 'type': '<(gtest_target_type)',
- 'dependencies': [
- '../base/base.gyp:base',
- '../testing/gtest.gyp:gtest',
- 'mojo_edk.gyp:mojo_common_test_support',
- 'mojo_edk.gyp:mojo_run_all_unittests',
- 'mojo_edk.gyp:mojo_system_impl',
- 'mojo_edk.gyp:mojo_system_ports',
- 'mojo_public.gyp:mojo_public_system',
- ],
- 'sources': [
- 'edk/embedder/embedder_unittest.cc',
- 'edk/embedder/platform_channel_pair_posix_unittest.cc',
- 'edk/embedder/platform_shared_buffer_unittest.cc',
- 'edk/system/awakable_list_unittest.cc',
- 'edk/system/core_test_base.cc',
- 'edk/system/core_test_base.h',
- 'edk/system/core_unittest.cc',
- 'edk/system/message_pipe_unittest.cc',
- 'edk/system/multiprocess_message_pipe_unittest.cc',
- 'edk/system/options_validation_unittest.cc',
- 'edk/system/platform_handle_dispatcher_unittest.cc',
- 'edk/system/platform_wrapper_unittest.cc',
- 'edk/system/ports/ports_unittest.cc',
- 'edk/system/shared_buffer_dispatcher_unittest.cc',
- 'edk/system/shared_buffer_unittest.cc',
- 'edk/system/test_utils.cc',
- 'edk/system/test_utils.h',
- 'edk/system/wait_set_dispatcher_unittest.cc',
- 'edk/system/waiter_test_utils.cc',
- 'edk/system/waiter_test_utils.h',
- 'edk/system/waiter_unittest.cc',
- 'edk/system/watch_unittest.cc',
- ],
- 'conditions': [
- ['OS=="ios"', {
- 'sources!': [
- 'edk/system/multiprocess_message_pipe_unittest.cc',
- ],
- }],
- ['OS == "android"', {
- 'dependencies': [
- '../testing/android/native_test.gyp:native_test_native_code',
- ],
- }],
- ],
- },
- {
- # GN version: //mojo/edk/system:mojo_message_pipe_perftests
- 'target_name': 'mojo_message_pipe_perftests',
- 'type': 'executable',
- 'dependencies': [
- '../base/base.gyp:base',
- '../base/base.gyp:test_support_base',
- '../testing/gtest.gyp:gtest',
- 'mojo_edk.gyp:mojo_common_test_support',
- 'mojo_edk.gyp:mojo_run_all_perftests',
- 'mojo_edk.gyp:mojo_system_impl',
- 'mojo_public.gyp:mojo_public_system',
- ],
- 'sources': [
- 'edk/system/message_pipe_perftest.cc',
- 'edk/system/test_utils.cc',
- 'edk/system/test_utils.h',
- ],
- },
- # TODO(yzshen): fix the following two targets.
- {
- # GN version: //mojo/edk/js/test:js_unittests
- 'target_name': 'mojo_js_unittests',
- 'type': 'executable',
- 'dependencies': [
- '../gin/gin.gyp:gin_test',
- 'mojo_edk.gyp:mojo_common_test_support',
- 'mojo_edk.gyp:mojo_run_all_unittests',
- 'mojo_edk.gyp:mojo_js_lib',
- 'mojo_public_tests.gyp:mojo_public_test_interfaces',
- ],
- 'sources': [
- 'edk/js/handle_unittest.cc',
- 'edk/js/test/run_js_tests.cc',
- ],
- },
- {
- # GN version: //mojo/edk/js/test:js_integration_tests
- 'target_name': 'mojo_js_integration_tests',
- 'type': 'executable',
- 'dependencies': [
- '../base/base.gyp:base',
- '../gin/gin.gyp:gin_test',
- 'mojo_base.gyp:mojo_common_lib',
- 'mojo_edk.gyp:mojo_js_lib',
- 'mojo_edk.gyp:mojo_run_all_unittests',
- 'mojo_js_to_cpp_bindings',
- 'mojo_public_tests.gyp:mojo_public_test_interfaces',
- ],
- 'sources': [
- 'edk/js/test/run_js_integration_tests.cc',
- 'edk/js/tests/js_to_cpp_tests.cc',
- ],
- },
- {
- 'target_name': 'mojo_js_to_cpp_bindings',
- 'type': 'none',
- 'variables': {
- 'mojom_files': [
- 'edk/js/tests/js_to_cpp.mojom',
- ],
- },
- 'includes': [ 'mojom_bindings_generator_explicit.gypi' ],
- },
- ],
- 'conditions': [
- ['test_isolation_mode != "noop"', {
- 'targets': [
- {
- 'target_name': 'mojo_public_bindings_unittests_run',
- 'type': 'none',
- 'dependencies': [
- 'mojo_public_bindings_unittests',
- ],
- 'includes': [
- '../build/isolate.gypi',
- ],
- 'sources': [
- 'mojo_public_bindings_unittests.isolate',
- ],
- },
- {
- 'target_name': 'mojo_public_system_unittests_run',
- 'type': 'none',
- 'dependencies': [
- 'mojo_public_system_unittests',
- ],
- 'includes': [
- '../build/isolate.gypi',
- ],
- 'sources': [
- 'mojo_public_system_unittests.isolate',
- ],
- },
- {
- 'target_name': 'mojo_js_unittests_run',
- 'type': 'none',
- 'dependencies': [
- 'mojo_js_unittests',
- ],
- 'includes': [
- '../build/isolate.gypi',
- ],
- 'sources': [
- 'mojo_js_unittests.isolate',
- ],
- },
- {
- 'target_name': 'mojo_js_integration_tests_run',
- 'type': 'none',
- 'dependencies': [
- 'mojo_js_integration_tests',
- ],
- 'includes': [
- '../build/isolate.gypi',
- ],
- 'sources': [
- 'mojo_js_integration_tests.isolate',
- ],
- },
- {
- 'target_name': 'mojo_system_unittests_run',
- 'type': 'none',
- 'dependencies': [
- 'mojo_system_unittests',
- ],
- 'includes': [
- '../build/isolate.gypi',
- ],
- 'sources': [
- 'mojo_system_unittests.isolate',
- ],
- },
- ],
- }],
- ['OS == "android"', {
- 'targets': [
- {
- 'target_name': 'mojo_system_unittests_apk',
- 'type': 'none',
- 'dependencies': [
- 'mojo_system_unittests',
- ],
- 'variables': {
- 'test_suite_name': 'mojo_system_unittests',
- },
- 'includes': [ '../build/apk_test.gypi' ],
- },
- ],
- }],
- ],
-}
diff --git a/chromium/mojo/mojo_js_integration_tests.isolate b/chromium/mojo/mojo_js_integration_tests.isolate
deleted file mode 100644
index 2ce03457d9e..00000000000
--- a/chromium/mojo/mojo_js_integration_tests.isolate
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2016 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.
-{
- 'includes': [
- '../base/base.isolate',
- '../gin/v8.isolate',
- '../third_party/icu/icu.isolate',
- ],
- 'conditions': [
- ['OS=="win" or OS=="mac" or OS=="linux"', {
- 'variables': {
- 'command': [
- '../testing/test_env.py',
- '<(PRODUCT_DIR)/mojo_js_integration_tests<(EXECUTABLE_SUFFIX)',
- '--brave-new-test-launcher',
- '--test-launcher-bot-mode',
- ],
- 'files': [
- '../gin/test/expect.js',
- '../mojo/edk/js/tests/',
- '../mojo/public/js/',
- '../testing/test_env.py',
- '<(PRODUCT_DIR)/mojo_js_integration_tests<(EXECUTABLE_SUFFIX)',
- '<(PRODUCT_DIR)/gen/mojo/common/common_custom_types.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/edk/js/tests/js_to_cpp.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/math_calculator.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/no_module.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/ping_service.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/rect.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/regression_tests.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_factory.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_import.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_import2.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/scoping.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_constants.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_native_types.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_structs.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_unions.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.js',
- ],
- },
- }],
- ],
-}
diff --git a/chromium/mojo/mojo_js_unittests.isolate b/chromium/mojo/mojo_js_unittests.isolate
deleted file mode 100644
index 81bae0b9a86..00000000000
--- a/chromium/mojo/mojo_js_unittests.isolate
+++ /dev/null
@@ -1,46 +0,0 @@
-# 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.
-{
- 'includes': [
- '../base/base.isolate',
- '../gin/v8.isolate',
- '../third_party/icu/icu.isolate',
- ],
- 'conditions': [
- ['OS=="win" or OS=="mac" or OS=="linux"', {
- 'variables': {
- 'command': [
- '../testing/test_env.py',
- '<(PRODUCT_DIR)/mojo_js_unittests<(EXECUTABLE_SUFFIX)',
- '--brave-new-test-launcher',
- '--test-launcher-bot-mode',
- ],
- 'files': [
- '../gin/test/expect.js',
- '../testing/test_env.py',
- 'public/interfaces/bindings/tests/data/validation/',
- 'public/js/',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/math_calculator.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/no_module.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/ping_service.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/rect.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/regression_tests.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_factory.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_import.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_import2.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/scoping.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_constants.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_native_types.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_structs.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/test_unions.mojom.js',
- '<(PRODUCT_DIR)/gen/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.js',
- ],
- },
- }],
- ],
-}
diff --git a/chromium/mojo/mojo_public.gyp b/chromium/mojo/mojo_public.gyp
deleted file mode 100644
index c52d21f2394..00000000000
--- a/chromium/mojo/mojo_public.gyp
+++ /dev/null
@@ -1,308 +0,0 @@
-# Copyright 2014 The Chroium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
- 'includes': [
- 'mojo_public.gypi',
- ],
- 'variables': {
- 'chromium_code': 1,
- },
- 'target_defaults' : {
- 'include_dirs': [
- '..',
- ],
- },
- 'targets': [
- {
- 'target_name': 'mojo_public',
- 'type': 'none',
- 'dependencies': [
- 'mojo_js_bindings',
- 'mojo_public_system',
- ],
- },
- {
- # GN version: //mojo/public/c/system
- 'target_name': 'mojo_public_system',
- 'type': '<(component)',
- 'sources': [
- '<@(mojo_public_system_sources)',
- ],
- 'defines': [
- 'MOJO_SYSTEM_IMPLEMENTATION',
- ],
- },
- {
- # GN version: //mojo/public/cpp/system
- 'target_name': 'mojo_cpp_system',
- 'type': 'static_library',
- 'sources': [
- '<@(mojo_cpp_system_sources)',
- ],
- 'dependencies': [
- '../base/base.gyp:base',
- 'mojo_public_system',
- ],
- },
- {
- # GN version: //mojo/public/cpp/bindings
- 'target_name': 'mojo_cpp_bindings',
- 'type': 'static_library',
- 'include_dirs': [
- '..'
- ],
- 'sources': [
- '<@(mojo_cpp_bindings_sources)',
-
- # This comes from the mojo_interface_bindings_cpp_sources dependency.
- '>@(mojom_generated_sources)',
- ],
- 'dependencies': [
- '../base/base.gyp:base',
- 'mojo_cpp_system',
- 'mojo_interface_bindings_cpp_sources',
- ],
- },
- {
- # GN version: //mojo/message_pump
- 'target_name': 'mojo_message_pump_lib',
- 'type': '<(component)',
- 'defines': [
- 'MOJO_MESSAGE_PUMP_IMPLEMENTATION',
- ],
- 'dependencies': [
- '../base/base.gyp:base',
- 'mojo_cpp_system',
- ],
- 'sources': [
- 'message_pump/handle_watcher.cc',
- 'message_pump/handle_watcher.h',
- 'message_pump/message_pump_mojo.cc',
- 'message_pump/message_pump_mojo.h',
- 'message_pump/message_pump_mojo_handler.h',
- 'message_pump/time_helper.cc',
- 'message_pump/time_helper.h',
- ],
- },
- {
- # GN version: //mojo/public/js
- 'target_name': 'mojo_js_bindings',
- 'type': 'static_library',
- 'include_dirs': [
- '..'
- ],
- 'sources': [
- 'public/js/constants.cc',
- 'public/js/constants.h',
- ],
- },
- {
- 'target_name': 'mojo_interface_bindings_mojom',
- 'type': 'none',
- 'variables': {
- 'require_interface_bindings': 0,
- 'mojom_files': [
- 'public/interfaces/bindings/interface_control_messages.mojom',
- 'public/interfaces/bindings/pipe_control_messages.mojom',
- ],
- },
- 'includes': [ 'mojom_bindings_generator_explicit.gypi' ],
- },
- {
- 'target_name': 'mojo_interface_bindings_cpp_sources',
- 'type': 'none',
- 'dependencies': [
- 'mojo_interface_bindings_mojom',
- ],
- },
- {
- # This target can be used to introduce a dependency on interface bindings
- # generation without introducing any side-effects in the dependent
- # target's configuration.
- 'target_name': 'mojo_interface_bindings_generation',
- 'type': 'none',
- 'dependencies': [
- 'mojo_interface_bindings_cpp_sources',
- ],
- },
- {
- # GN version: //mojo/public/c/test_support
- 'target_name': 'mojo_public_test_support',
- 'type': 'static_library',
- 'include_dirs': [
- '..',
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '..',
- ],
- },
- 'sources': [
- 'public/c/test_support/test_support.h',
- # TODO(vtl): Convert this to thunks http://crbug.com/386799
- 'public/tests/test_support_private.cc',
- 'public/tests/test_support_private.h',
- ],
- },
- {
- # GN version: //mojo/public/cpp/test_support:test_utils
- 'target_name': 'mojo_public_test_utils',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- '../testing/gtest.gyp:gtest',
- 'mojo_public_test_support',
- ],
- 'sources': [
- 'public/cpp/test_support/lib/test_support.cc',
- 'public/cpp/test_support/lib/test_utils.cc',
- 'public/cpp/test_support/test_utils.h',
- ],
- },
- {
- # GN version: //mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils
- 'target_name': 'mojo_public_bindings_test_utils',
- 'type': 'static_library',
- 'dependencies': [
- '../base/base.gyp:base',
- ],
- 'sources': [
- 'public/cpp/bindings/tests/validation_test_input_parser.cc',
- 'public/cpp/bindings/tests/validation_test_input_parser.h',
- ],
- },
- ],
- 'conditions': [
- ['OS == "android"', {
- 'targets': [
- {
- # GN version: //mojo/public/java:system
- 'target_name': 'mojo_public_java',
- 'type': 'none',
- 'variables': {
- 'chromium_code': 0,
- 'java_in_dir': 'public/java/system',
- },
- 'includes': [ '../build/java.gypi' ],
- },
- {
- 'target_name': 'mojo_interface_bindings_java_sources',
- 'type': 'none',
- 'dependencies': [
- 'mojo_interface_bindings_mojom',
- ],
- },
- {
- # GN version: //mojo/public/java:bindings
- 'target_name': 'mojo_bindings_java',
- 'type': 'none',
- 'variables': {
- 'chromium_code': 0,
- 'java_in_dir': 'public/java/bindings',
- },
- 'dependencies': [
- 'mojo_interface_bindings_java_sources',
- 'mojo_public_java',
- '<(DEPTH)/base/base.gyp:base_java',
- ],
- 'includes': [ '../build/java.gypi' ],
- },
- ],
- }],
- ['OS != "ios"', {
- 'targets': [
- {
- # TODO(yzshen): crbug.com/617718 Consider moving this into blink.
- # GN version: //mojo/public/cpp/bindings:wtf_support
- 'target_name': 'mojo_cpp_bindings_wtf_support',
- 'type': 'static_library',
- 'include_dirs': [
- '..'
- ],
- 'sources': [
- 'public/cpp/bindings/array_traits_wtf.h',
- 'public/cpp/bindings/array_traits_wtf_vector.h',
- 'public/cpp/bindings/lib/string_traits_wtf.cc',
- 'public/cpp/bindings/lib/wtf_serialization.h',
- 'public/cpp/bindings/map_traits_wtf.h',
- 'public/cpp/bindings/string_traits_wtf.h',
- 'public/cpp/bindings/wtf_array.h',
- 'public/cpp/bindings/wtf_map.h',
- ],
- 'dependencies': [
- 'mojo_cpp_bindings',
- '../third_party/WebKit/Source/config.gyp:config',
- '../third_party/WebKit/Source/wtf/wtf.gyp:wtf',
- ],
- 'export_dependent_settings': [
- 'mojo_cpp_bindings',
- '../third_party/WebKit/Source/config.gyp:config',
- ],
- },
- ],
- }],
- ['OS == "win" and target_arch=="ia32"', {
- 'targets': [
- {
- # GN version: //mojo/public/c/system
- 'target_name': 'mojo_public_system_win64',
- 'type': '<(component)',
- 'sources': [
- '<@(mojo_public_system_sources)',
- ],
- 'defines': [
- 'MOJO_SYSTEM_IMPLEMENTATION',
- ],
- 'configurations': {
- 'Common_Base': {
- 'msvs_target_platform': 'x64',
- },
- },
- },
- {
- # GN version: //mojo/public/cpp/system
- 'target_name': 'mojo_cpp_system_win64',
- 'type': 'static_library',
- 'sources': [
- '<@(mojo_cpp_system_sources)',
- ],
- 'dependencies': [
- '../base/base.gyp:base_win64',
- 'mojo_public_system_win64',
- ],
- 'configurations': {
- 'Common_Base': {
- 'msvs_target_platform': 'x64',
- },
- },
- },
- {
- # GN version: //mojo/public/cpp/bindings
- 'target_name': 'mojo_cpp_bindings_win64',
- 'type': 'static_library',
- 'include_dirs': [
- '..'
- ],
- 'sources': [
- '<@(mojo_cpp_bindings_sources)',
-
- # This comes from the mojo_interface_bindings_cpp_sources dependency.
- '>@(mojom_generated_sources)',
- ],
- 'dependencies': [
- '../base/base.gyp:base_win64',
- 'mojo_cpp_system_win64',
- 'mojo_interface_bindings_cpp_sources',
- ],
- 'configurations': {
- 'Common_Base': {
- 'msvs_target_platform': 'x64',
- },
- },
- },
- ],
- }],
- ],
-}
diff --git a/chromium/mojo/mojo_public.gypi b/chromium/mojo/mojo_public.gypi
deleted file mode 100644
index b2057537bf5..00000000000
--- a/chromium/mojo/mojo_public.gypi
+++ /dev/null
@@ -1,152 +0,0 @@
-# Copyright 2016 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': {
- 'mojo_cpp_bindings_sources': [
- 'public/cpp/bindings/array.h',
- 'public/cpp/bindings/array_traits.h',
- 'public/cpp/bindings/array_traits_carray.h',
- 'public/cpp/bindings/array_traits_standard.h',
- 'public/cpp/bindings/array_traits_stl.h',
- 'public/cpp/bindings/associated_binding.h',
- 'public/cpp/bindings/associated_group.h',
- 'public/cpp/bindings/associated_group_controller.h',
- 'public/cpp/bindings/associated_interface_ptr.h',
- 'public/cpp/bindings/associated_interface_ptr_info.h',
- 'public/cpp/bindings/associated_interface_request.h',
- 'public/cpp/bindings/binding.h',
- 'public/cpp/bindings/binding_set.h',
- 'public/cpp/bindings/connector.h',
- 'public/cpp/bindings/enum_traits.h',
- 'public/cpp/bindings/interface_endpoint_client.h',
- 'public/cpp/bindings/interface_endpoint_controller.h',
- 'public/cpp/bindings/interface_id.h',
- 'public/cpp/bindings/interface_ptr.h',
- 'public/cpp/bindings/interface_ptr_set.h',
- 'public/cpp/bindings/interface_request.h',
- 'public/cpp/bindings/lib/array_internal.cc',
- 'public/cpp/bindings/lib/array_internal.h',
- 'public/cpp/bindings/lib/array_serialization.h',
- 'public/cpp/bindings/lib/associated_group.cc',
- 'public/cpp/bindings/lib/associated_group_controller.cc',
- 'public/cpp/bindings/lib/associated_interface_ptr_state.h',
- 'public/cpp/bindings/lib/binding_state.h',
- 'public/cpp/bindings/lib/bindings_internal.h',
- 'public/cpp/bindings/lib/buffer.h',
- 'public/cpp/bindings/lib/connector.cc',
- 'public/cpp/bindings/lib/control_message_handler.cc',
- 'public/cpp/bindings/lib/control_message_handler.h',
- 'public/cpp/bindings/lib/control_message_proxy.cc',
- 'public/cpp/bindings/lib/control_message_proxy.h',
- 'public/cpp/bindings/lib/filter_chain.cc',
- 'public/cpp/bindings/lib/filter_chain.h',
- 'public/cpp/bindings/lib/fixed_buffer.cc',
- 'public/cpp/bindings/lib/fixed_buffer.h',
- 'public/cpp/bindings/lib/handle_interface_serialization.h',
- 'public/cpp/bindings/lib/interface_endpoint_client.cc',
- 'public/cpp/bindings/lib/interface_ptr_state.h',
- 'public/cpp/bindings/lib/map_data_internal.h',
- 'public/cpp/bindings/lib/map_serialization.h',
- 'public/cpp/bindings/lib/message.cc',
- 'public/cpp/bindings/lib/message_buffer.cc',
- 'public/cpp/bindings/lib/message_buffer.h',
- 'public/cpp/bindings/lib/message_builder.cc',
- 'public/cpp/bindings/lib/message_builder.h',
- 'public/cpp/bindings/lib/message_filter.cc',
- 'public/cpp/bindings/lib/message_header_validator.cc',
- 'public/cpp/bindings/lib/message_internal.h',
- 'public/cpp/bindings/lib/multiplex_router.cc',
- 'public/cpp/bindings/lib/multiplex_router.h',
- 'public/cpp/bindings/lib/native_enum_data.h',
- 'public/cpp/bindings/lib/native_enum_serialization.h',
- 'public/cpp/bindings/lib/native_struct.cc',
- 'public/cpp/bindings/lib/native_struct_data.cc',
- 'public/cpp/bindings/lib/native_struct_data.h',
- 'public/cpp/bindings/lib/native_struct_serialization.cc',
- 'public/cpp/bindings/lib/native_struct_serialization.h',
- 'public/cpp/bindings/lib/no_interface.cc',
- 'public/cpp/bindings/lib/pipe_control_message_handler.cc',
- 'public/cpp/bindings/lib/pipe_control_message_proxy.cc',
- 'public/cpp/bindings/lib/router.cc',
- 'public/cpp/bindings/lib/router.h',
- 'public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc',
- 'public/cpp/bindings/lib/serialization.h',
- 'public/cpp/bindings/lib/serialization_context.cc',
- 'public/cpp/bindings/lib/serialization_context.h',
- 'public/cpp/bindings/lib/serialization_forward.h',
- 'public/cpp/bindings/lib/serialization_forward.h',
- 'public/cpp/bindings/lib/serialization_util.cc',
- 'public/cpp/bindings/lib/serialization_util.h',
- 'public/cpp/bindings/lib/string_serialization.h',
- 'public/cpp/bindings/lib/string_traits_string16.cc',
- 'public/cpp/bindings/lib/sync_call_restrictions.cc',
- 'public/cpp/bindings/lib/sync_handle_registry.cc',
- 'public/cpp/bindings/lib/sync_handle_watcher.cc',
- 'public/cpp/bindings/lib/template_util.h',
- 'public/cpp/bindings/lib/validate_params.h',
- 'public/cpp/bindings/lib/validation_context.cc',
- 'public/cpp/bindings/lib/validation_context.h',
- 'public/cpp/bindings/lib/validation_errors.cc',
- 'public/cpp/bindings/lib/validation_errors.h',
- 'public/cpp/bindings/lib/validation_util.cc',
- 'public/cpp/bindings/lib/validation_util.h',
- 'public/cpp/bindings/map_traits.h',
- 'public/cpp/bindings/map_traits_standard.h',
- 'public/cpp/bindings/map_traits_stl.h',
- 'public/cpp/bindings/message.h',
- 'public/cpp/bindings/message_filter.h',
- 'public/cpp/bindings/message_header_validator.h',
- 'public/cpp/bindings/native_enum.h',
- 'public/cpp/bindings/native_struct.h',
- 'public/cpp/bindings/no_interface.h',
- 'public/cpp/bindings/pipe_control_message_handler.h',
- 'public/cpp/bindings/pipe_control_message_handler_delegate.h',
- 'public/cpp/bindings/pipe_control_message_proxy.h',
- 'public/cpp/bindings/scoped_interface_endpoint_handle.h',
- 'public/cpp/bindings/stl_converters.h',
- 'public/cpp/bindings/string.h',
- 'public/cpp/bindings/string_traits.h',
- 'public/cpp/bindings/string_traits_standard.h',
- 'public/cpp/bindings/string_traits_stl.h',
- 'public/cpp/bindings/string_traits_string16.h',
- 'public/cpp/bindings/string_traits_string_piece.h',
- 'public/cpp/bindings/strong_binding.h',
- 'public/cpp/bindings/struct_ptr.h',
- 'public/cpp/bindings/struct_traits.h',
- 'public/cpp/bindings/sync_call_restrictions.h',
- 'public/cpp/bindings/sync_handle_registry.h',
- 'public/cpp/bindings/sync_handle_watcher.h',
- 'public/cpp/bindings/type_converter.h',
- ],
- 'mojo_cpp_system_sources': [
- 'public/cpp/system/buffer.cc',
- 'public/cpp/system/buffer.h',
- 'public/cpp/system/core.h',
- 'public/cpp/system/data_pipe.h',
- 'public/cpp/system/functions.h',
- 'public/cpp/system/handle.h',
- 'public/cpp/system/message.h',
- 'public/cpp/system/message_pipe.h',
- 'public/cpp/system/platform_handle.cc',
- 'public/cpp/system/platform_handle.h',
- 'public/cpp/system/watcher.cc',
- 'public/cpp/system/watcher.h',
- ],
- 'mojo_public_system_sources': [
- 'public/c/system/buffer.h',
- 'public/c/system/core.h',
- 'public/c/system/data_pipe.h',
- 'public/c/system/functions.h',
- 'public/c/system/macros.h',
- 'public/c/system/message_pipe.h',
- 'public/c/system/platform_handle.h',
- 'public/c/system/system_export.h',
- 'public/c/system/thunks.cc',
- 'public/c/system/thunks.h',
- 'public/c/system/types.h',
- 'public/c/system/wait_set.h',
- ],
- },
-}
diff --git a/chromium/mojo/mojo_public_bindings_unittests.isolate b/chromium/mojo/mojo_public_bindings_unittests.isolate
deleted file mode 100644
index 846bf78b6d2..00000000000
--- a/chromium/mojo/mojo_public_bindings_unittests.isolate
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2015 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.
-{
- 'includes': [
- '../base/base.isolate',
- ],
- 'conditions': [
- ['OS=="win" or OS=="mac" or OS=="linux"', {
- 'variables': {
- 'command': [
- '../testing/test_env.py',
- '<(PRODUCT_DIR)/mojo_public_bindings_unittests<(EXECUTABLE_SUFFIX)',
- '--brave-new-test-launcher',
- '--test-launcher-bot-mode',
- ],
- 'files': [
- '../testing/test_env.py',
- 'public/interfaces/bindings/tests/data/validation/',
- ],
- },
- }],
- ],
-}
diff --git a/chromium/mojo/mojo_public_nacl.gyp b/chromium/mojo/mojo_public_nacl.gyp
deleted file mode 100644
index c235c053153..00000000000
--- a/chromium/mojo/mojo_public_nacl.gyp
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright 2016 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': {
- 'chromium_code': 1,
- },
- 'includes': [
- '../build/common_untrusted.gypi',
- 'mojo_public.gypi',
- ],
- 'target_defaults' : {
- 'include_dirs': [
- '..',
- ],
- },
- 'targets': [
- {
- # GN version: //mojo/public/c/system
- 'target_name': 'mojo_public_system_nacl',
- 'type': 'none',
- 'variables': {
- 'nacl_untrusted_build': 1,
- 'nlib_target': 'libmojo_public_system_nacl.a',
- 'build_glibc': 0,
- 'build_newlib': 0,
- 'build_irt': 1,
- 'build_pnacl_newlib': 0,
- 'build_nonsfi_helper': 1,
- },
- 'sources': [
- '<@(mojo_public_system_sources)',
- ],
- 'defines': [
- 'MOJO_SYSTEM_IMPLEMENTATION',
- ],
- },
- {
- # GN version: //mojo/public/cpp/bindings
- 'target_name': 'mojo_cpp_bindings_nacl',
- 'type': 'none',
- 'variables': {
- 'nacl_untrusted_build': 1,
- 'nlib_target': 'libmojo_cpp_bindings_nacl.a',
- 'build_glibc': 0,
- 'build_newlib': 0,
- 'build_irt': 1,
- 'build_pnacl_newlib': 0,
- 'build_nonsfi_helper': 1,
- },
- 'dependencies': [
- '../base/base_nacl.gyp:base_nacl',
- '../base/base_nacl.gyp:base_nacl_nonsfi',
- '../mojo/mojo_public.gyp:mojo_interface_bindings_cpp_sources',
- 'mojo_cpp_system_nacl',
- ],
- 'sources': [
- '<@(mojo_cpp_bindings_sources)',
-
- # This comes from the mojo_interface_bindings_cpp_sources dependency.
- '>@(mojom_generated_sources)',
- ],
- },
- {
- # GN version: //mojo/public/cpp/system
- 'target_name': 'mojo_cpp_system_nacl',
- 'type': 'none',
- 'variables': {
- 'nacl_untrusted_build': 1,
- 'nlib_target': 'libmojo_cpp_system_nacl.a',
- 'build_glibc': 0,
- 'build_newlib': 0,
- 'build_irt': 1,
- 'build_pnacl_newlib': 0,
- 'build_nonsfi_helper': 1,
- },
- 'sources': [
- '<@(mojo_cpp_system_sources)',
- ],
- 'dependencies': [
- '../base/base_nacl.gyp:base_nacl',
- 'mojo_public_system_nacl',
- ],
- },
- ],
-}
diff --git a/chromium/mojo/mojo_public_system_unittests.isolate b/chromium/mojo/mojo_public_system_unittests.isolate
deleted file mode 100644
index f761bf77cd8..00000000000
--- a/chromium/mojo/mojo_public_system_unittests.isolate
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2015 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.
-{
- 'includes': [
- '../base/base.isolate',
- ],
- 'conditions': [
- ['OS=="win" or OS=="mac" or OS=="linux"', {
- 'variables': {
- 'command': [
- '../testing/test_env.py',
- '<(PRODUCT_DIR)/mojo_public_system_unittests<(EXECUTABLE_SUFFIX)',
- '--brave-new-test-launcher',
- '--test-launcher-bot-mode',
- ],
- 'files': [
- '../testing/test_env.py',
- ],
- },
- }],
- ],
-}
diff --git a/chromium/mojo/mojo_public_tests.gyp b/chromium/mojo/mojo_public_tests.gyp
deleted file mode 100644
index ebe2b6c788f..00000000000
--- a/chromium/mojo/mojo_public_tests.gyp
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright 2016 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': {
- 'chromium_code': 1,
- 'mojo_public_test_interfaces_mojom_files': [
- 'public/interfaces/bindings/tests/math_calculator.mojom',
- 'public/interfaces/bindings/tests/no_module.mojom',
- 'public/interfaces/bindings/tests/ping_service.mojom',
- 'public/interfaces/bindings/tests/rect.mojom',
- 'public/interfaces/bindings/tests/regression_tests.mojom',
- 'public/interfaces/bindings/tests/sample_factory.mojom',
- 'public/interfaces/bindings/tests/sample_import.mojom',
- 'public/interfaces/bindings/tests/sample_import2.mojom',
- 'public/interfaces/bindings/tests/sample_interfaces.mojom',
- 'public/interfaces/bindings/tests/sample_service.mojom',
- 'public/interfaces/bindings/tests/scoping.mojom',
- 'public/interfaces/bindings/tests/serialization_test_structs.mojom',
- 'public/interfaces/bindings/tests/test_constants.mojom',
- 'public/interfaces/bindings/tests/test_native_types.mojom',
- 'public/interfaces/bindings/tests/test_sync_methods.mojom',
- ],
- },
- 'target_defaults' : {
- 'include_dirs': [
- '..',
- ],
- },
- 'targets': [
- {
- 'target_name': 'mojo_public_test_interfaces_mojom',
- 'type': 'none',
- 'variables': {
- 'mojom_files': [
- 'public/interfaces/bindings/tests/test_structs.mojom',
- 'public/interfaces/bindings/tests/test_unions.mojom',
- 'public/interfaces/bindings/tests/validation_test_interfaces.mojom',
- '<@(mojo_public_test_interfaces_mojom_files)',
- ],
- 'mojom_typemaps': [
- 'public/cpp/bindings/tests/rect_chromium.typemap',
- 'public/cpp/bindings/tests/test_native_types_chromium.typemap',
- ],
- },
- 'includes': [ 'mojom_bindings_generator_explicit.gypi' ],
- },
- {
- 'target_name': 'mojo_public_test_interfaces_struct_traits',
- 'type': 'static_library',
- 'variables': {
- 'mojom_typemaps': [
- 'public/cpp/bindings/tests/struct_with_traits.typemap',
- ],
- },
- 'sources': [
- 'public/interfaces/bindings/tests/struct_with_traits.mojom',
- 'public/cpp/bindings/tests/struct_with_traits_impl_traits.cc',
- ],
- 'includes': [ 'mojom_bindings_generator.gypi' ],
- },
- {
- # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces
- 'target_name': 'mojo_public_test_interfaces',
- 'type': 'static_library',
- 'export_dependent_settings': [
- 'mojo_public.gyp:mojo_cpp_bindings',
- ],
- 'sources': [
- 'public/cpp/bindings/tests/pickled_types_chromium.cc',
- ],
- 'dependencies': [
- '../ipc/ipc.gyp:ipc',
- 'mojo_public.gyp:mojo_cpp_bindings',
- 'mojo_public_test_interfaces_mojom',
- ],
- },
- {
- 'target_name': 'mojo_public_test_associated_interfaces_mojom',
- 'type': 'none',
- 'variables': {
- # These files are not included in the mojo_public_test_interfaces_mojom
- # target because associated interfaces are not supported by all bindings
- # languages yet.
- 'mojom_files': [
- 'public/interfaces/bindings/tests/test_associated_interfaces.mojom',
- 'public/interfaces/bindings/tests/validation_test_associated_interfaces.mojom',
- ],
- },
- 'includes': [ 'mojom_bindings_generator_explicit.gypi' ],
- },
- {
- # GN version: //mojo/public/interfaces/bindings/tests:test_associated_interfaces
- 'target_name': 'mojo_public_test_associated_interfaces',
- 'type': 'static_library',
- 'export_dependent_settings': [
- 'mojo_public.gyp:mojo_cpp_bindings',
- ],
- 'dependencies': [
- 'mojo_public.gyp:mojo_cpp_bindings',
- 'mojo_public_test_associated_interfaces_mojom',
- ],
- },
- {
- 'target_name': 'mojo_public_test_wtf_types',
- 'type': 'static_library',
- 'sources': [
- 'public/interfaces/bindings/tests/test_wtf_types.mojom',
- ],
- 'includes': [ 'mojom_bindings_generator.gypi' ],
- },
- ],
- 'conditions': [
- ['OS != "ios"', {
- 'targets': [
- {
- 'target_name': 'mojo_public_test_interfaces_mojom_blink',
- 'type': 'none',
- 'variables': {
- 'for_blink': 'true',
- 'mojom_typemaps': [
- 'public/cpp/bindings/tests/rect_blink.typemap',
- 'public/cpp/bindings/tests/test_native_types_blink.typemap',
- ],
- 'mojom_files': '<(mojo_public_test_interfaces_mojom_files)',
- },
- 'includes': [ 'mojom_bindings_generator_explicit.gypi' ],
- },
- {
- # GN version: //mojo/public/interfaces/bindings/tests:test_interfaces_blink
- 'target_name': 'mojo_public_test_interfaces_blink',
- 'type': 'static_library',
- 'export_dependent_settings': [
- 'mojo_public.gyp:mojo_cpp_bindings',
- 'mojo_public_test_interfaces_mojom_blink',
- ],
- 'sources': [
- 'public/cpp/bindings/tests/pickled_types_blink.cc',
- ],
- 'dependencies': [
- '../ipc/ipc.gyp:ipc',
- 'mojo_public.gyp:mojo_cpp_bindings',
- 'mojo_public_test_interfaces_mojom_blink',
- ],
- },
- {
- 'target_name': 'mojo_public_test_wtf_types_blink',
- 'type': 'static_library',
- 'variables': {
- 'for_blink': 'true',
- },
- 'sources': [
- 'public/interfaces/bindings/tests/test_wtf_types.mojom',
- ],
- 'includes': [ 'mojom_bindings_generator.gypi' ],
- },
- ],
- }],
- ],
-}
-
diff --git a/chromium/mojo/mojo_system_unittests.isolate b/chromium/mojo/mojo_system_unittests.isolate
deleted file mode 100644
index ef3cbb929a8..00000000000
--- a/chromium/mojo/mojo_system_unittests.isolate
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2015 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.
-{
- 'includes': [
- '../base/base.isolate',
- ],
- 'conditions': [
- ['OS=="win" or OS=="mac" or OS=="linux"', {
- 'variables': {
- 'command': [
- '../testing/test_env.py',
- '<(PRODUCT_DIR)/mojo_system_unittests<(EXECUTABLE_SUFFIX)',
- '--brave-new-test-launcher',
- '--test-launcher-bot-mode',
- ],
- 'files': [
- '../testing/test_env.py',
- ],
- },
- }],
- ],
-}
diff --git a/chromium/mojo/mojo_test_apk.isolate b/chromium/mojo/mojo_test_apk.isolate
deleted file mode 100644
index e08c1be9141..00000000000
--- a/chromium/mojo/mojo_test_apk.isolate
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2016 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': {
- 'files': [
- '<(DEPTH)/mojo/public/interfaces/bindings/tests/data/validation/',
- ],
- },
-}
diff --git a/chromium/mojo/mojom_bindings_generator.gypi b/chromium/mojo/mojom_bindings_generator.gypi
deleted file mode 100644
index dea11695dd1..00000000000
--- a/chromium/mojo/mojom_bindings_generator.gypi
+++ /dev/null
@@ -1,166 +0,0 @@
-# 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.
-
-{
- 'includes': [
- 'mojom_bindings_generator_variables.gypi',
- ],
- 'variables': {
- 'variables': {
- 'variables': {
- 'for_blink%': 'false',
- },
- 'for_blink%': '<(for_blink)',
- 'conditions': [
- ['for_blink=="true"', {
- 'mojom_output_languages%': 'c++',
- 'mojom_variant%': 'blink',
- 'mojom_generator_wtf_arg%': [
- '--for_blink',
- ],
- 'wtf_dependencies%': [
- '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings_wtf_support',
- '<(DEPTH)/third_party/WebKit/Source/wtf/wtf.gyp:wtf',
- ],
- }, {
- 'mojom_output_languages%': 'c++,javascript,java',
- 'mojom_variant%': 'none',
- 'mojom_generator_wtf_arg%': [],
- 'wtf_dependencies%': [],
- }],
- ],
- },
- 'for_blink%': '<(for_blink)',
- 'mojom_variant%': '<(mojom_variant)',
- 'mojom_generator_wtf_arg%': '<(mojom_generator_wtf_arg)',
- 'wtf_dependencies%': '<(wtf_dependencies)',
- 'mojom_output_languages%': '<(mojom_output_languages)',
- 'mojom_typemaps%': [],
- 'mojom_base_output_dir':
- '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))',
- 'mojom_generated_outputs': [
- '<!@(python <(DEPTH)/mojo/public/tools/bindings/mojom_list_outputs.py --basedir <(mojom_base_output_dir) --variant <(mojom_variant) <@(_sources))',
- ],
- 'generated_typemap_file': '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(_target_name)_type_mappings',
- },
- 'actions': [
- {
- 'variables': {
- 'java_out_dir': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
- 'stamp_filename': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/<(_target_name).stamp',
- },
- 'action_name': '<(_target_name)_mojom_bindings_stamp',
- # The java output directory is deleted to ensure that the java library
- # doesn't try to compile stale files.
- 'action': [
- 'python', '<(DEPTH)/build/rmdir_and_stamp.py',
- '<(java_out_dir)',
- '<(stamp_filename)',
- ],
- 'inputs': [ '<@(_sources)' ],
- 'outputs': [ '<(stamp_filename)' ],
- },
- {
- 'variables': {
- 'output': '<(generated_typemap_file)',
- },
- 'action_name': '<(_target_name)_type_mappings',
- 'action': [
- 'python', '<(DEPTH)/mojo/public/tools/bindings/generate_type_mappings.py',
- '--output',
- '<(output)',
- '<!@(python <(DEPTH)/mojo/public/tools/bindings/format_typemap_generator_args.py <@(mojom_typemaps))',
- ],
- 'inputs':[
- '<(DEPTH)/mojo/public/tools/bindings/generate_type_mappings.py',
- ],
- 'outputs': [ '<(output)' ],
- },
- ],
- 'rules': [
- {
- 'rule_name': '<(_target_name)_mojom_bindings_generator',
- 'extension': 'mojom',
- 'variables': {
- 'java_out_dir': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
- 'mojom_import_args%': [
- '-I<(DEPTH)',
- '-I<(DEPTH)/mojo/services',
- ],
- 'stamp_filename': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/<(_target_name).stamp',
- },
- 'inputs': [
- '<@(mojom_bindings_generator_sources)',
- '<(stamp_filename)',
- '<(generated_typemap_file)',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/cpp_templates.zip',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/java_templates.zip',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/js_templates.zip',
- ],
- 'conditions': [
- ['mojom_variant=="none"', {
- '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',
- ]
- }, {
- 'outputs': [
- '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom-<(mojom_variant).cc',
- '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom-<(mojom_variant).h',
- '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom-<(mojom_variant)-internal.h',
- ],
- }]
- ],
- 'action': [
- 'python', '<@(mojom_bindings_generator)',
- '--use_bundled_pylibs', 'generate',
- './<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom',
- '-d', '<(DEPTH)',
- '<@(mojom_import_args)',
- '-o', '<(SHARED_INTERMEDIATE_DIR)',
- '--java_output_directory=<(java_out_dir)',
- '--variant', '<(mojom_variant)',
- '-g', '<(mojom_output_languages)',
- '--typemap',
- '<(generated_typemap_file)',
- '<@(mojom_generator_wtf_arg)',
- '--bytecode_path',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings',
- ],
- 'message': 'Generating Mojo bindings from <(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom',
- 'process_outputs_as_sources': 1,
- }
- ],
- 'dependencies': [
- '<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/mojo/mojo_public.gyp:mojo_interface_bindings_generation',
- '<(DEPTH)/mojo/public/tools/bindings/bindings.gyp:precompile_mojom_bindings_generator_templates',
- '<@(wtf_dependencies)',
- ],
- 'export_dependent_settings': [
- '<@(wtf_dependencies)',
- ],
- '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',
- ],
- 'additional_input_paths': [
- '<@(mojom_bindings_generator_sources)',
- '<@(_sources)',
- ],
- },
- },
- 'hard_dependency': 1,
-}
diff --git a/chromium/mojo/mojom_bindings_generator_explicit.gypi b/chromium/mojo/mojom_bindings_generator_explicit.gypi
deleted file mode 100644
index 06e831040ae..00000000000
--- a/chromium/mojo/mojom_bindings_generator_explicit.gypi
+++ /dev/null
@@ -1,183 +0,0 @@
-# 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.
-
-{
- 'includes': [
- 'mojom_bindings_generator_variables.gypi',
- ],
- 'variables': {
- 'variables': {
- 'variables': {
- 'for_blink%': 'false',
- },
- 'for_blink%': 'false',
- 'conditions': [
- ['for_blink=="true"', {
- 'mojom_output_languages%': 'c++',
- 'mojom_variant%': 'blink',
- 'mojom_generator_wtf_arg%': [
- '--for_blink',
- ],
- 'wtf_dependencies%': [
- '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings_wtf_support',
- '<(DEPTH)/third_party/WebKit/Source/wtf/wtf.gyp:wtf',
- ],
- }, {
- 'mojom_output_languages%': 'c++,javascript,java',
- 'mojom_variant%': 'none',
- 'mojom_generator_wtf_arg%': [],
- 'wtf_dependencies%': [],
- }],
- ],
- },
- 'for_blink%': '<(for_blink)',
- 'mojom_variant%': '<(mojom_variant)',
- 'mojom_generator_wtf_arg%': '<(mojom_generator_wtf_arg)',
- 'wtf_dependencies%': '<(wtf_dependencies)',
- 'mojom_output_languages%': '<(mojom_output_languages)',
- 'mojom_typemaps%': [],
- 'mojom_base_output_dir':
- '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))',
- 'mojom_generated_outputs': [
- '<!@(python <(DEPTH)/mojo/public/tools/bindings/mojom_list_outputs.py --basedir <(mojom_base_output_dir) --variant <(mojom_variant) <@(mojom_files))',
- ],
- 'generated_typemap_file': '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(_target_name)_type_mappings',
- 'mojom_include_path%': '<(DEPTH)',
- 'require_interface_bindings%': 1,
- },
- # Given mojom files as inputs, generate sources. These sources will be
- # exported to another target (via dependent_settings) to be compiled. This
- # keeps code generation separate from compilation, allowing the same sources
- # to be compiled with multiple toolchains - target, NaCl, etc.
- 'actions': [
- {
- 'variables': {
- 'java_out_dir': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
- 'stamp_filename': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/<(_target_name).stamp',
- },
- 'action_name': '<(_target_name)_mojom_bindings_stamp',
- # The java output directory is deleted to ensure that the java library
- # doesn't try to compile stale files.
- 'action': [
- 'python', '<(DEPTH)/build/rmdir_and_stamp.py',
- '<(java_out_dir)',
- '<(stamp_filename)',
- ],
- 'inputs': [
- '<@(mojom_files)',
- ],
- 'outputs': [ '<(stamp_filename)' ],
- },
- {
- 'variables': {
- 'output': '<(generated_typemap_file)',
- },
- 'action_name': '<(_target_name)_type_mappings',
- 'action': [
- 'python', '<(DEPTH)/mojo/public/tools/bindings/generate_type_mappings.py',
- '--output',
- '<(output)',
- '<!@(python <(DEPTH)/mojo/public/tools/bindings/format_typemap_generator_args.py <@(mojom_typemaps))',
- ],
- 'inputs':[
- '<(DEPTH)/mojo/public/tools/bindings/generate_type_mappings.py',
- ],
- 'outputs': [ '<(output)' ],
- },
- {
- 'action_name': '<(_target_name)_mojom_bindings_generator',
- 'variables': {
- 'java_out_dir': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
- 'stamp_filename': '<(PRODUCT_DIR)/java_mojo/<(_target_name)/<(_target_name).stamp',
- 'mojom_import_args%': [
- '-I<(DEPTH)',
- '-I<(DEPTH)/mojo/services',
- '-I<(mojom_include_path)',
- ],
- },
- 'inputs': [
- '<@(mojom_bindings_generator_sources)',
- '<@(mojom_files)',
- '<(stamp_filename)',
- '<(generated_typemap_file)',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/cpp_templates.zip',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/java_templates.zip',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/js_templates.zip',
- ],
- 'outputs': [
- '<@(mojom_generated_outputs)',
- ],
- 'action': [
- 'python', '<@(mojom_bindings_generator)',
- '--use_bundled_pylibs', 'generate',
- '<@(mojom_files)',
- '-d', '<(DEPTH)',
- '<@(mojom_import_args)',
- '-o', '<(SHARED_INTERMEDIATE_DIR)',
- '--java_output_directory=<(java_out_dir)',
- '--variant', '<(mojom_variant)',
- '-g', '<(mojom_output_languages)',
- '--typemap',
- '<(generated_typemap_file)',
- '<@(mojom_generator_wtf_arg)',
- '--bytecode_path',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings',
- ],
- 'message': 'Generating Mojo bindings from <@(mojom_files)',
- }
- ],
- 'conditions': [
- ['require_interface_bindings==1', {
- 'dependencies': [
- '<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/mojo/mojo_public.gyp:mojo_interface_bindings_generation',
- ],
- }],
- ],
- 'dependencies': [
- '<(DEPTH)/mojo/public/tools/bindings/bindings.gyp:precompile_mojom_bindings_generator_templates',
- '<@(wtf_dependencies)',
- ],
- 'export_dependent_settings': [
- '<@(wtf_dependencies)',
- ],
- # Prevent the generated sources from being injected into the "all" target by
- # preventing the code generator from being directly depended on by the "all"
- # target.
- 'suppress_wildcard': '1',
- 'hard_dependency': '1',
- 'direct_dependent_settings': {
- # A target directly depending on this action will compile the generated
- # sources.
- 'sources': [
- '<@(mojom_generated_outputs)',
- ],
- # Include paths needed to compile the generated sources into a library.
- 'include_dirs': [
- '<(DEPTH)',
- '<(SHARED_INTERMEDIATE_DIR)',
- ],
- # Make sure the generated header files are available for any static library
- # that depends on a static library that depends on this generator.
- 'hard_dependency': 1,
- 'direct_dependent_settings': {
- # Include paths needed to find the generated header files and their
- # transitive dependancies when using the library.
- 'include_dirs': [
- '<(DEPTH)',
- '<(SHARED_INTERMEDIATE_DIR)',
- ],
- 'variables': {
- 'generated_src_dirs': [
- '<(PRODUCT_DIR)/java_mojo/<(_target_name)/src',
- ],
- 'additional_input_paths': [
- '<@(mojom_bindings_generator_sources)',
- '<@(mojom_files)',
- ],
- 'mojom_generated_sources': [ '<@(mojom_generated_outputs)' ],
- },
- }
- },
-}
diff --git a/chromium/mojo/mojom_bindings_generator_variables.gypi b/chromium/mojo/mojom_bindings_generator_variables.gypi
deleted file mode 100644
index 9e3c40003cb..00000000000
--- a/chromium/mojo/mojom_bindings_generator_variables.gypi
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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.
-
-{
- 'variables': {
- 'mojom_bindings_generator':
- '<(DEPTH)/mojo/public/tools/bindings/mojom_bindings_generator.py',
- 'mojom_bindings_generator_sources': [
- '<(mojom_bindings_generator)',
- '<(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',
- ]
- }
-}
diff --git a/chromium/mojo/public/c/system/BUILD.gn b/chromium/mojo/public/c/system/BUILD.gn
index 3ec12f6bc0e..cde32282f63 100644
--- a/chromium/mojo/public/c/system/BUILD.gn
+++ b/chromium/mojo/public/c/system/BUILD.gn
@@ -25,7 +25,7 @@ component("system") {
# This should ONLY be depended upon directly by shared_library targets which
# need to export the MojoSetSystemThunks symbol, like targets generated by the
-# mojo_native_application template in //mojo/public/mojo_application.gni.
+# mojo_native_application template in //services/shell/public/cpp/service.gni.
source_set("set_thunks_for_app") {
sources = [
"set_thunks_for_app.cc",
diff --git a/chromium/mojo/public/c/system/core.h b/chromium/mojo/public/c/system/core.h
index 3775e90d558..77d452b0dec 100644
--- a/chromium/mojo/public/c/system/core.h
+++ b/chromium/mojo/public/c/system/core.h
@@ -13,7 +13,6 @@
#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/main.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/c/system/platform_handle.h"
#include "mojo/public/c/system/system_export.h"
diff --git a/chromium/mojo/public/c/system/main.h b/chromium/mojo/public/c/system/main.h
deleted file mode 100644
index 65d0837c03e..00000000000
--- a/chromium/mojo/public/c/system/main.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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_MAIN_H_
-#define MOJO_PUBLIC_C_SYSTEM_MAIN_H_
-
-#include "mojo/public/c/system/types.h"
-
-// Implement MojoMain directly as the entry point for an application.
-//
-// MojoResult MojoMain(MojoHandle application_request) {
-// ...
-// }
-//
-// TODO(davemoore): Establish this as part of our SDK for third party mojo
-// application writers.
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if defined(WIN32)
-__declspec(dllexport) MojoResult
- __cdecl MojoMain(MojoHandle application_request);
-#else // !defined(WIN32)
-__attribute__((visibility("default"))) MojoResult
- MojoMain(MojoHandle service_provider_handle);
-#endif // defined(WIN32)
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // MOJO_PUBLIC_C_SYSTEM_MAIN_H_
diff --git a/chromium/mojo/public/c/test_support/BUILD.gn b/chromium/mojo/public/c/test_support/BUILD.gn
index 75d9c13d346..e2abd5807eb 100644
--- a/chromium/mojo/public/c/test_support/BUILD.gn
+++ b/chromium/mojo/public/c/test_support/BUILD.gn
@@ -2,7 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# GYP version: mojo/mojo_public.gyp:mojo_test_support
static_library("test_support") {
output_name = "mojo_public_test_support"
diff --git a/chromium/mojo/public/cpp/bindings/BUILD.gn b/chromium/mojo/public/cpp/bindings/BUILD.gn
index d34d77040c4..7b60b2c0a5a 100644
--- a/chromium/mojo/public/cpp/bindings/BUILD.gn
+++ b/chromium/mojo/public/cpp/bindings/BUILD.gn
@@ -2,14 +2,33 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-source_set("bindings") {
+interfaces_bindings_gen_dir = "$root_gen_dir/mojo/public/interfaces/bindings"
+
+component("bindings") {
sources = [
+ # Normally, targets should depend on the source_sets generated by mojom
+ # targets. However, the generated source_sets use portions of the bindings
+ # library. In order to avoid linker warnings about locally-defined imports
+ # in Windows components build, this target depends on the generated C++
+ # files directly so that the EXPORT macro defintions match.
+ "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared-internal.h",
+ "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared.cc",
+ "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared.h",
+ "$interfaces_bindings_gen_dir/interface_control_messages.mojom.cc",
+ "$interfaces_bindings_gen_dir/interface_control_messages.mojom.h",
+ "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared-internal.h",
+ "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared.cc",
+ "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared.h",
+ "$interfaces_bindings_gen_dir/pipe_control_messages.mojom.cc",
+ "$interfaces_bindings_gen_dir/pipe_control_messages.mojom.h",
"array.h",
+ "array_data_view.h",
"array_traits.h",
"array_traits_carray.h",
"array_traits_standard.h",
"array_traits_stl.h",
"associated_binding.h",
+ "associated_binding_set.h",
"associated_group.h",
"associated_group_controller.h",
"associated_interface_ptr.h",
@@ -17,8 +36,12 @@ source_set("bindings") {
"associated_interface_request.h",
"binding.h",
"binding_set.h",
+ "bindings_export.h",
+ "connection_error_callback.h",
"connector.h",
"enum_traits.h",
+ "filter_chain.h",
+ "interface_data_view.h",
"interface_endpoint_client.h",
"interface_endpoint_controller.h",
"interface_id.h",
@@ -32,29 +55,31 @@ source_set("bindings") {
"lib/associated_group.cc",
"lib/associated_group_controller.cc",
"lib/associated_interface_ptr_state.h",
+ "lib/binding_state.cc",
"lib/binding_state.h",
"lib/bindings_internal.h",
"lib/buffer.h",
+ "lib/clone_equals_util.h",
"lib/connector.cc",
"lib/control_message_handler.cc",
"lib/control_message_handler.h",
"lib/control_message_proxy.cc",
"lib/control_message_proxy.h",
"lib/filter_chain.cc",
- "lib/filter_chain.h",
"lib/fixed_buffer.cc",
"lib/fixed_buffer.h",
"lib/handle_interface_serialization.h",
+ "lib/hash_util.h",
"lib/interface_endpoint_client.cc",
"lib/interface_ptr_state.h",
"lib/map_data_internal.h",
"lib/map_serialization.h",
+ "lib/may_auto_lock.h",
"lib/message.cc",
"lib/message_buffer.cc",
"lib/message_buffer.h",
"lib/message_builder.cc",
"lib/message_builder.h",
- "lib/message_filter.cc",
"lib/message_header_validator.cc",
"lib/message_internal.h",
"lib/multiplex_router.cc",
@@ -76,7 +101,6 @@ source_set("bindings") {
"lib/serialization_context.cc",
"lib/serialization_context.h",
"lib/serialization_forward.h",
- "lib/serialization_util.cc",
"lib/serialization_util.h",
"lib/string_serialization.h",
"lib/string_traits_string16.cc",
@@ -93,14 +117,15 @@ source_set("bindings") {
"lib/validation_util.cc",
"lib/validation_util.h",
"map.h",
+ "map_data_view.h",
"map_traits.h",
"map_traits_standard.h",
"map_traits_stl.h",
"message.h",
- "message_filter.h",
"message_header_validator.h",
"native_enum.h",
"native_struct.h",
+ "native_struct_data_view.h",
"no_interface.h",
"pipe_control_message_handler.h",
"pipe_control_message_handler_delegate.h",
@@ -108,6 +133,7 @@ source_set("bindings") {
"scoped_interface_endpoint_handle.h",
"stl_converters.h",
"string.h",
+ "string_data_view.h",
"string_traits.h",
"string_traits_standard.h",
"string_traits_stl.h",
@@ -119,6 +145,7 @@ source_set("bindings") {
"sync_handle_registry.h",
"sync_handle_watcher.h",
"type_converter.h",
+ "union_traits.h",
]
public_deps = [
@@ -130,8 +157,11 @@ source_set("bindings") {
deps = [
"//base",
- "//mojo/public/interfaces/bindings:bindings_cpp_sources",
+ "//mojo/public/interfaces/bindings:bindings__generator",
+ "//mojo/public/interfaces/bindings:bindings_shared__generator",
]
+
+ defines = [ "MOJO_CPP_BINDINGS_IMPLEMENTATION" ]
}
source_set("struct_traits") {
@@ -147,8 +177,11 @@ if (!is_ios) {
"array_traits_wtf.h",
"array_traits_wtf_vector.h",
"lib/string_traits_wtf.cc",
+ "lib/wtf_clone_equals_util.h",
+ "lib/wtf_hash_util.h",
"lib/wtf_serialization.h",
"map_traits_wtf.h",
+ "map_traits_wtf_hash_map.h",
"string_traits_wtf.h",
"wtf_array.h",
"wtf_map.h",
diff --git a/chromium/mojo/public/cpp/bindings/array.h b/chromium/mojo/public/cpp/bindings/array.h
index ed8bdb595ae..faf7398fffd 100644
--- a/chromium/mojo/public/cpp/bindings/array.h
+++ b/chromium/mojo/public/cpp/bindings/array.h
@@ -16,6 +16,8 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/clone_equals_util.h"
+#include "mojo/public/cpp/bindings/lib/hash_util.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
#include "mojo/public/cpp/bindings/type_converter.h"
@@ -132,19 +134,23 @@ class Array {
// Sets the array to empty (even if previously it was null.)
void SetToEmpty() { resize(0); }
+ // Ensures the underlying storage can store up to |size| elements without
+ // performing reallocations. This works like the reserve method of
+ // |std::vector|.
+ void reserve(size_t size) { vec_.reserve(size); }
+
// Returns a const reference to the |std::vector| managed by this class. If
// the array is null, this will be an empty vector.
const std::vector<T>& storage() const { return vec_; }
// Passes the underlying storage and resets this array to null.
- //
- // TODO(yzshen): Consider changing this to a rvalue-ref-qualified conversion
- // to std::vector<T> after we move to MSVC 2015.
std::vector<T> PassStorage() {
is_null_ = true;
return std::move(vec_);
}
+ operator const std::vector<T>&() const { return vec_; }
+
void Swap(Array* other) {
std::swap(is_null_, other->is_null_);
vec_.swap(other->vec_);
@@ -169,10 +175,8 @@ class Array {
Array Clone() const {
Array result;
result.is_null_ = is_null_;
- result.vec_.reserve(vec_.size());
- for (const auto& element : vec_)
- result.vec_.push_back(internal::Clone(element));
- return std::move(result);
+ result.vec_ = internal::Clone(vec_);
+ return result;
}
// Indicates whether the contents of this array are equal to |other|. A null
@@ -181,13 +185,11 @@ class Array {
bool Equals(const Array& other) const {
if (is_null() != other.is_null())
return false;
- if (size() != other.size())
- return false;
- for (size_t i = 0; i < size(); ++i) {
- if (!internal::Equals(at(i), other.at(i)))
- return false;
- }
- return true;
+ return internal::Equals(vec_, other.vec_);
+ }
+
+ size_t Hash(size_t seed) const {
+ return is_null() ? seed : internal::Hash(seed, vec_);
}
private:
diff --git a/chromium/mojo/public/cpp/bindings/array_data_view.h b/chromium/mojo/public/cpp/bindings/array_data_view.h
new file mode 100644
index 00000000000..d02a8846ec7
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/array_data_view.h
@@ -0,0 +1,244 @@
+// Copyright 2016 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_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_
+
+#include <type_traits>
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename T, typename EnableType = void>
+class ArrayDataViewImpl;
+
+template <typename T>
+class ArrayDataViewImpl<
+ T,
+ typename std::enable_if<
+ BelongsTo<T, MojomTypeCategory::POD>::value>::type> {
+ public:
+ using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
+
+ ArrayDataViewImpl(Data_* data, SerializationContext* context)
+ : data_(data), context_(context) {}
+
+ T operator[](size_t index) const { return data_->at(index); }
+
+ const T* data() const { return data_->storage(); }
+
+ protected:
+ Data_* data_;
+ SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<
+ T,
+ typename std::enable_if<
+ BelongsTo<T, MojomTypeCategory::BOOLEAN>::value>::type> {
+ public:
+ using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
+
+ ArrayDataViewImpl(Data_* data, SerializationContext* context)
+ : data_(data), context_(context) {}
+
+ bool operator[](size_t index) const { return data_->at(index); }
+
+ protected:
+ Data_* data_;
+ SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<
+ T,
+ typename std::enable_if<
+ BelongsTo<T, MojomTypeCategory::ENUM>::value>::type> {
+ public:
+ static_assert(sizeof(T) == sizeof(int32_t), "Unexpected enum size");
+
+ using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
+
+ ArrayDataViewImpl(Data_* data, SerializationContext* context)
+ : data_(data), context_(context) {}
+
+ T operator[](size_t index) const { return static_cast<T>(data_->at(index)); }
+
+ const T* data() const { return reinterpret_cast<const T*>(data_->storage()); }
+
+ template <typename U>
+ bool Read(size_t index, U* output) {
+ return Deserialize<T>(data_->at(index), output);
+ }
+
+ protected:
+ Data_* data_;
+ SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<
+ T,
+ typename std::enable_if<
+ BelongsTo<T,
+ MojomTypeCategory::ASSOCIATED_INTERFACE |
+ MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST |
+ MojomTypeCategory::INTERFACE |
+ MojomTypeCategory::INTERFACE_REQUEST>::value>::type> {
+ public:
+ using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
+
+ ArrayDataViewImpl(Data_* data, SerializationContext* context)
+ : data_(data), context_(context) {}
+
+ template <typename U>
+ U Take(size_t index) {
+ U result;
+ bool ret = Deserialize<T>(&data_->at(index), &result, context_);
+ DCHECK(ret);
+ return result;
+ }
+
+ protected:
+ Data_* data_;
+ SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<
+ T,
+ typename std::enable_if<
+ BelongsTo<T, MojomTypeCategory::HANDLE>::value>::type> {
+ public:
+ using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
+
+ ArrayDataViewImpl(Data_* data, SerializationContext* context)
+ : data_(data), context_(context) {}
+
+ T Take(size_t index) {
+ T result;
+ bool ret = Deserialize<T>(&data_->at(index), &result, context_);
+ DCHECK(ret);
+ return result;
+ }
+
+ protected:
+ Data_* data_;
+ SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<T,
+ typename std::enable_if<BelongsTo<
+ T,
+ MojomTypeCategory::ARRAY | MojomTypeCategory::MAP |
+ MojomTypeCategory::STRING |
+ MojomTypeCategory::STRUCT>::value>::type> {
+ public:
+ using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
+
+ ArrayDataViewImpl(Data_* data, SerializationContext* context)
+ : data_(data), context_(context) {}
+
+ void GetDataView(size_t index, T* output) {
+ *output = T(data_->at(index).Get(), context_);
+ }
+
+ template <typename U>
+ bool Read(size_t index, U* output) {
+ return Deserialize<T>(data_->at(index).Get(), output, context_);
+ }
+
+ protected:
+ Data_* data_;
+ SerializationContext* context_;
+};
+
+template <typename T>
+class ArrayDataViewImpl<
+ T,
+ typename std::enable_if<
+ BelongsTo<T, MojomTypeCategory::UNION>::value>::type> {
+ public:
+ using Data_ = typename MojomTypeTraits<ArrayDataView<T>>::Data;
+
+ ArrayDataViewImpl(Data_* data, SerializationContext* context)
+ : data_(data), context_(context) {}
+
+ void GetDataView(size_t index, T* output) {
+ *output = T(&data_->at(index), context_);
+ }
+
+ template <typename U>
+ bool Read(size_t index, U* output) {
+ return Deserialize<T>(&data_->at(index), output, context_);
+ }
+
+ protected:
+ Data_* data_;
+ SerializationContext* context_;
+};
+
+} // namespace internal
+
+template <typename K, typename V>
+class MapDataView;
+
+template <typename T>
+class ArrayDataView : public internal::ArrayDataViewImpl<T> {
+ public:
+ using Element = T;
+ using Data_ = typename internal::ArrayDataViewImpl<T>::Data_;
+
+ ArrayDataView() : internal::ArrayDataViewImpl<T>(nullptr, nullptr) {}
+
+ ArrayDataView(Data_* data, internal::SerializationContext* context)
+ : internal::ArrayDataViewImpl<T>(data, context) {}
+
+ bool is_null() const { return !this->data_; }
+
+ size_t size() const { return this->data_->size(); }
+
+ // Methods to access elements are different for different element types. They
+ // are inherited from internal::ArrayDataViewImpl:
+
+ // POD types except boolean and enums:
+ // T operator[](size_t index) const;
+ // const T* data() const;
+
+ // Boolean:
+ // bool operator[](size_t index) const;
+
+ // Enums:
+ // T operator[](size_t index) const;
+ // const T* data() const;
+ // template <typename U>
+ // bool Read(size_t index, U* output);
+
+ // Handles:
+ // T Take(size_t index);
+
+ // Interfaces:
+ // template <typename U>
+ // U Take(size_t index);
+
+ // Object types:
+ // void GetDataView(size_t index, T* output);
+ // template <typename U>
+ // bool Read(size_t index, U* output);
+
+ private:
+ template <typename K, typename V>
+ friend class MapDataView;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_
diff --git a/chromium/mojo/public/cpp/bindings/array_traits.h b/chromium/mojo/public/cpp/bindings/array_traits.h
index 366573db280..594b2e0789d 100644
--- a/chromium/mojo/public/cpp/bindings/array_traits.h
+++ b/chromium/mojo/public/cpp/bindings/array_traits.h
@@ -47,7 +47,9 @@ namespace mojo {
// static void AdvanceIterator(Iterator& iterator);
//
// // Returns a reference to the value at the current position of
-// // |iterator|.
+// // |iterator|. Optionally, the ConstIterator version of GetValue can
+// // return by value instead of by reference if it makes sense for the
+// // type.
// static const T& GetValue(ConstIterator& iterator);
// static T& GetValue(Iterator& iterator);
//
diff --git a/chromium/mojo/public/cpp/bindings/array_traits_carray.h b/chromium/mojo/public/cpp/bindings/array_traits_carray.h
index ffcf9d58556..3ff694b8821 100644
--- a/chromium/mojo/public/cpp/bindings/array_traits_carray.h
+++ b/chromium/mojo/public/cpp/bindings/array_traits_carray.h
@@ -20,6 +20,14 @@ struct CArray {
};
template <typename T>
+struct ConstCArray {
+ ConstCArray() : size(0), data(nullptr) {}
+ ConstCArray(size_t size, const T* data) : size(size), data(data) {}
+ size_t size;
+ const T* data;
+};
+
+template <typename T>
struct ArrayTraits<CArray<T>> {
using Element = T;
@@ -48,6 +56,21 @@ struct ArrayTraits<CArray<T>> {
}
};
+template <typename T>
+struct ArrayTraits<ConstCArray<T>> {
+ using Element = T;
+
+ static bool IsNull(const ConstCArray<T>& input) { return !input.data; }
+
+ static size_t GetSize(const ConstCArray<T>& input) { return input.size; }
+
+ static const T* GetData(const ConstCArray<T>& input) { return input.data; }
+
+ static const T& GetAt(const ConstCArray<T>& input, size_t index) {
+ return input.data[index];
+ }
+};
+
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_
diff --git a/chromium/mojo/public/cpp/bindings/array_traits_stl.h b/chromium/mojo/public/cpp/bindings/array_traits_stl.h
index 51af5ad7a1b..c1aac00a7cd 100644
--- a/chromium/mojo/public/cpp/bindings/array_traits_stl.h
+++ b/chromium/mojo/public/cpp/bindings/array_traits_stl.h
@@ -42,12 +42,49 @@ struct ArrayTraits<std::vector<T>> {
return input[index];
}
- static bool Resize(std::vector<T>& input, size_t size) {
- input.resize(size);
+ static inline bool Resize(std::vector<T>& input, size_t size) {
+ // Instead of calling std::vector<T>::resize() directly, this is a hack to
+ // make compilers happy. Some compilers (e.g., Mac, Android, Linux MSan)
+ // currently don't allow resizing types like
+ // std::vector<std::vector<MoveOnlyType>>.
+ // Because the deserialization code doesn't care about the original contents
+ // of |input|, we discard them directly.
+ //
+ // The "inline" keyword of this method matters. Without it, we have observed
+ // significant perf regression with some tests on Mac. crbug.com/631415
+ if (input.size() != size) {
+ std::vector<T> temp(size);
+ input.swap(temp);
+ }
+
return true;
}
};
+// This ArrayTraits specialization is used only for serialization.
+template <typename T>
+struct ArrayTraits<std::set<T>> {
+ using Element = T;
+ using ConstIterator = typename std::set<T>::const_iterator;
+
+ static bool IsNull(const std::set<T>& input) {
+ // std::set<> is always converted to non-null mojom array.
+ return false;
+ }
+
+ static size_t GetSize(const std::set<T>& input) { return input.size(); }
+
+ static ConstIterator GetBegin(const std::set<T>& input) {
+ return input.begin();
+ }
+ static void AdvanceIterator(ConstIterator& iterator) {
+ ++iterator;
+ }
+ static const T& GetValue(ConstIterator& iterator) {
+ return *iterator;
+ }
+};
+
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_
diff --git a/chromium/mojo/public/cpp/bindings/associated_binding.h b/chromium/mojo/public/cpp/bindings/associated_binding.h
index 1da50090cc1..a7a7c822869 100644
--- a/chromium/mojo/public/cpp/bindings/associated_binding.h
+++ b/chromium/mojo/public/cpp/bindings/associated_binding.h
@@ -6,6 +6,7 @@
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
#include <memory>
+#include <string>
#include <utility>
#include "base/bind.h"
@@ -18,11 +19,15 @@
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/associated_group_controller.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
+#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
namespace mojo {
+class MessageReceiver;
+
// Represents the implementation side of an associated interface. It is similar
// to Binding, except that it doesn't own a message pipe handle.
//
@@ -101,21 +106,33 @@ class AssociatedBinding {
endpoint_client_.reset(new InterfaceEndpointClient(
std::move(handle), &stub_,
base::WrapUnique(new typename Interface::RequestValidator_()),
- Interface::HasSyncMethods_, std::move(runner)));
- endpoint_client_->set_connection_error_handler(
- base::Bind(&AssociatedBinding::RunConnectionErrorHandler,
- base::Unretained(this)));
+ Interface::HasSyncMethods_, std::move(runner), Interface::Version_));
stub_.serialization_context()->group_controller =
endpoint_client_->group_controller();
}
+ // Adds a message filter to be notified of each incoming message before
+ // dispatch. If a filter returns |false| from Accept(), the message is not
+ // dispatched and the pipe is closed. Filters cannot be removed.
+ void AddFilter(std::unique_ptr<MessageReceiver> filter) {
+ DCHECK(endpoint_client_);
+ endpoint_client_->AddFilter(std::move(filter));
+ }
+
// Closes the associated interface. Puts this object into a state where it can
// be rebound.
void Close() {
DCHECK(endpoint_client_);
endpoint_client_.reset();
- connection_error_handler_.Reset();
+ }
+
+ // Similar to the method above, but also specifies a disconnect reason.
+ void CloseWithReason(uint32_t custom_reason, const std::string& description) {
+ DCHECK(endpoint_client_);
+ endpoint_client_->control_message_proxy()->SendDisconnectReason(
+ custom_reason, description);
+ Close();
}
// Unbinds and returns the associated interface request so it can be
@@ -128,7 +145,6 @@ class AssociatedBinding {
request.Bind(endpoint_client_->PassHandle());
endpoint_client_.reset();
- connection_error_handler_.Reset();
return request;
}
@@ -140,7 +156,13 @@ class AssociatedBinding {
// AssociatedBinding is unbound or closed.
void set_connection_error_handler(const base::Closure& error_handler) {
DCHECK(is_bound());
- connection_error_handler_ = error_handler;
+ endpoint_client_->set_connection_error_handler(error_handler);
+ }
+
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ DCHECK(is_bound());
+ endpoint_client_->set_connection_error_with_reason_handler(error_handler);
}
// Returns the interface implementation that was previously specified.
@@ -155,17 +177,19 @@ class AssociatedBinding {
return endpoint_client_ ? endpoint_client_->associated_group() : nullptr;
}
- private:
- void RunConnectionErrorHandler() {
- if (!connection_error_handler_.is_null())
- connection_error_handler_.Run();
+ // Sends a message on the underlying message pipe and runs the current
+ // message loop until its response is received. This can be used in tests to
+ // verify that no message was sent on a message pipe in response to some
+ // stimulus.
+ void FlushForTesting() {
+ endpoint_client_->control_message_proxy()->FlushForTesting();
}
+ private:
std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
typename Interface::Stub_ stub_;
Interface* impl_;
- base::Closure connection_error_handler_;
DISALLOW_COPY_AND_ASSIGN(AssociatedBinding);
};
diff --git a/chromium/mojo/public/cpp/bindings/associated_binding_set.h b/chromium/mojo/public/cpp/bindings/associated_binding_set.h
new file mode 100644
index 00000000000..b15022358ee
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/associated_binding_set.h
@@ -0,0 +1,27 @@
+// Copyright 2016 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_ASSOCIATED_BINDING_SET_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_SET_H_
+
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+#include "mojo/public/cpp/bindings/associated_interface_request.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+
+namespace mojo {
+
+template <typename Interface>
+struct BindingSetTraits<AssociatedBinding<Interface>> {
+ using ProxyType = AssociatedInterfacePtr<Interface>;
+ using RequestType = AssociatedInterfaceRequest<Interface>;
+};
+
+template <typename Interface>
+using AssociatedBindingSet =
+ BindingSet<Interface, AssociatedBinding<Interface>>;
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_SET_H_
diff --git a/chromium/mojo/public/cpp/bindings/associated_group.h b/chromium/mojo/public/cpp/bindings/associated_group.h
index 836c0d61b57..b1c692acd23 100644
--- a/chromium/mojo/public/cpp/bindings/associated_group.h
+++ b/chromium/mojo/public/cpp/bindings/associated_group.h
@@ -10,6 +10,7 @@
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
namespace mojo {
@@ -20,7 +21,7 @@ class AssociatedGroupController;
// message pipe. It is used to create associated interfaces for that message
// pipe.
// It is thread safe and cheap to make copies.
-class AssociatedGroup {
+class MOJO_CPP_BINDINGS_EXPORT AssociatedGroup {
public:
// Configuration used by CreateAssociatedInterface(). Please see the comments
// of that method for more details.
diff --git a/chromium/mojo/public/cpp/bindings/associated_group_controller.h b/chromium/mojo/public/cpp/bindings/associated_group_controller.h
index 0ab8253ed45..42849df81e1 100644
--- a/chromium/mojo/public/cpp/bindings/associated_group_controller.h
+++ b/chromium/mojo/public/cpp/bindings/associated_group_controller.h
@@ -9,8 +9,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/ref_counted_delete_on_message_loop.h"
#include "base/single_thread_task_runner.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/interface_id.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
@@ -21,12 +21,9 @@ class InterfaceEndpointClient;
class InterfaceEndpointController;
// An internal interface used to manage endpoints within an associated group.
-class AssociatedGroupController :
- public base::RefCountedDeleteOnMessageLoop<AssociatedGroupController> {
+class MOJO_CPP_BINDINGS_EXPORT AssociatedGroupController
+ : public base::RefCountedThreadSafe<AssociatedGroupController> {
public:
- explicit AssociatedGroupController(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-
// Creates a pair of interface endpoint handles. The method generates a new
// interface ID and assigns it to the two handles. |local_endpoint| is used
// locally; while |remote_endpoint| is sent over the message pipe.
@@ -66,8 +63,7 @@ class AssociatedGroupController :
std::unique_ptr<AssociatedGroup> CreateAssociatedGroup();
protected:
- friend class base::RefCountedDeleteOnMessageLoop<AssociatedGroupController>;
- friend class base::DeleteHelper<AssociatedGroupController>;
+ friend class base::RefCountedThreadSafe<AssociatedGroupController>;
// Creates a new ScopedInterfaceEndpointHandle associated with this
// controller.
@@ -76,8 +72,6 @@ class AssociatedGroupController :
bool is_local);
virtual ~AssociatedGroupController();
-
- DISALLOW_COPY_AND_ASSIGN(AssociatedGroupController);
};
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h b/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h
index 10494cecb05..3bdb319548a 100644
--- a/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h
+++ b/chromium/mojo/public/cpp/bindings/associated_interface_ptr.h
@@ -6,6 +6,8 @@
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_
#include <stdint.h>
+
+#include <string>
#include <utility>
#include "base/callback.h"
@@ -17,7 +19,10 @@
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
#include "mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h"
+#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
+#include "mojo/public/cpp/system/message_pipe.h"
namespace mojo {
@@ -107,6 +112,12 @@ class AssociatedInterfacePtr {
internal_state_.RequireVersion(version);
}
+ // Sends a message on the underlying message pipe and runs the current
+ // message loop until its response is received. This can be used in tests to
+ // verify that no message was sent on a message pipe in response to some
+ // stimulus.
+ void FlushForTesting() { internal_state_.FlushForTesting(); }
+
// Closes the associated interface (if any) and returns the pointer to the
// unbound state.
void reset() {
@@ -114,6 +125,13 @@ class AssociatedInterfacePtr {
internal_state_.Swap(&doomed);
}
+ // Similar to the method above, but also specifies a disconnect reason.
+ void ResetWithReason(uint32_t custom_reason, const std::string& description) {
+ if (internal_state_.is_bound())
+ internal_state_.SendDisconnectReason(custom_reason, description);
+ reset();
+ }
+
// Indicates whether an error has been encountered. If true, method calls made
// on this interface will be dropped (and may already have been dropped).
bool encountered_error() const { return internal_state_.encountered_error(); }
@@ -126,6 +144,11 @@ class AssociatedInterfacePtr {
internal_state_.set_connection_error_handler(error_handler);
}
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ internal_state_.set_connection_error_with_reason_handler(error_handler);
+ }
+
// Unbinds and returns the associated interface pointer information which
// could be used to setup an AssociatedInterfacePtr again. This method may be
// used to move the proxy to a different thread.
@@ -203,6 +226,18 @@ AssociatedInterfaceRequest<Interface> GetProxy(
return request;
}
+// Creates an associated interface proxy which casts its messages into the void.
+template <typename Interface>
+void GetDummyProxyForTesting(AssociatedInterfacePtr<Interface>* proxy) {
+ MessagePipe pipe;
+ scoped_refptr<internal::MultiplexRouter> router =
+ new internal::MultiplexRouter(std::move(pipe.handle0),
+ internal::MultiplexRouter::MULTI_INTERFACE,
+ false, base::ThreadTaskRunnerHandle::Get());
+ std::unique_ptr<AssociatedGroup> group = router->CreateAssociatedGroup();
+ GetProxy(proxy, group.get());
+}
+
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_
diff --git a/chromium/mojo/public/cpp/bindings/associated_interface_request.h b/chromium/mojo/public/cpp/bindings/associated_interface_request.h
index 30fcd16ec14..361b301d389 100644
--- a/chromium/mojo/public/cpp/bindings/associated_interface_request.h
+++ b/chromium/mojo/public/cpp/bindings/associated_interface_request.h
@@ -5,9 +5,15 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_
+#include <string>
#include <utility>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
+#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
+#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
namespace mojo {
@@ -64,6 +70,28 @@ class AssociatedInterfaceRequest {
return !is_pending() && !other.is_pending();
}
+ void ResetWithReason(uint32_t custom_reason, const std::string& description) {
+ if (!handle_.is_valid())
+ return;
+
+ if (!handle_.is_local()) {
+ // This handle is supposed to be sent to the other end of the message
+ // pipe and used there.
+ NOTREACHED();
+ handle_.reset();
+ return;
+ }
+
+ InterfaceEndpointClient client(std::move(handle_), nullptr,
+ base::MakeUnique<PassThroughFilter>(), false,
+ base::ThreadTaskRunnerHandle::Get(), 0u);
+ Message message =
+ internal::ControlMessageProxy::ConstructDisconnectReasonMessage(
+ custom_reason, description);
+ bool result = client.Accept(&message);
+ DCHECK(result);
+ }
+
private:
ScopedInterfaceEndpointHandle handle_;
diff --git a/chromium/mojo/public/cpp/bindings/binding.h b/chromium/mojo/public/cpp/bindings/binding.h
index 8c9ee2f0c52..71257d2ac42 100644
--- a/chromium/mojo/public/cpp/bindings/binding.h
+++ b/chromium/mojo/public/cpp/bindings/binding.h
@@ -5,6 +5,7 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_
#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_
+#include <string>
#include <utility>
#include "base/callback_forward.h"
@@ -12,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/bindings/interface_ptr_info.h"
#include "mojo/public/cpp/bindings/interface_request.h"
@@ -21,6 +23,7 @@
namespace mojo {
class AssociatedGroup;
+class MessageReceiver;
// Represents the binding of an interface implementation to a message pipe.
// When the |Binding| object is destroyed, the binding between the message pipe
@@ -152,6 +155,14 @@ class Binding {
Bind(request.PassMessagePipe(), std::move(runner));
}
+ // Adds a message filter to be notified of each incoming message before
+ // dispatch. If a filter returns |false| from Accept(), the message is not
+ // dispatched and the pipe is closed. Filters cannot be removed.
+ void AddFilter(std::unique_ptr<MessageReceiver> filter) {
+ DCHECK(is_bound());
+ internal_state_.AddFilter(std::move(filter));
+ }
+
// Whether there are any associated interfaces running on the pipe currently.
bool HasAssociatedInterfaces() const {
return internal_state_.HasAssociatedInterfaces();
@@ -189,6 +200,11 @@ class Binding {
// state where it can be rebound to a new pipe.
void Close() { internal_state_.Close(); }
+ // Similar to the method above, but also specifies a disconnect reason.
+ void CloseWithReason(uint32_t custom_reason, const std::string& description) {
+ internal_state_.CloseWithReason(custom_reason, description);
+ }
+
// Unbinds the underlying pipe from this binding and returns it so it can be
// used in another context, such as on another thread or with a different
// implementation. Put this object into a state where it can be rebound to a
@@ -217,6 +233,12 @@ class Binding {
internal_state_.set_connection_error_handler(error_handler);
}
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ DCHECK(is_bound());
+ internal_state_.set_connection_error_with_reason_handler(error_handler);
+ }
+
// Returns the interface implementation that was previously specified. Caller
// does not take ownership.
Interface* impl() { return internal_state_.impl(); }
@@ -239,12 +261,17 @@ class Binding {
return internal_state_.associated_group();
}
+ // Sends a no-op message on the underlying message pipe and runs the current
+ // message loop until its response is received. This can be used in tests to
+ // verify that no message was sent on a message pipe in response to some
+ // stimulus.
+ void FlushForTesting() { internal_state_.FlushForTesting(); }
+
// Exposed for testing, should not generally be used.
void EnableTestingMode() { internal_state_.EnableTestingMode(); }
private:
- internal::BindingState<Interface, Interface::PassesAssociatedKinds_>
- internal_state_;
+ internal::BindingState<Interface, true> internal_state_;
DISALLOW_COPY_AND_ASSIGN(Binding);
};
diff --git a/chromium/mojo/public/cpp/bindings/binding_set.h b/chromium/mojo/public/cpp/bindings/binding_set.h
index b1baca6a808..d778f6c3478 100644
--- a/chromium/mojo/public/cpp/bindings/binding_set.h
+++ b/chromium/mojo/public/cpp/bindings/binding_set.h
@@ -5,107 +5,234 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_
-#include <algorithm>
+#include <string>
#include <utility>
-#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/message.h"
namespace mojo {
+template <typename BindingType>
+struct BindingSetTraits;
+
+template <typename Interface>
+struct BindingSetTraits<Binding<Interface>> {
+ using ProxyType = InterfacePtr<Interface>;
+ using RequestType = InterfaceRequest<Interface>;
+
+ static RequestType GetProxy(ProxyType* proxy) {
+ return mojo::GetProxy(proxy);
+ }
+};
+
+enum class BindingSetDispatchMode {
+ WITHOUT_CONTEXT,
+ WITH_CONTEXT,
+};
+
+using BindingId = size_t;
+
// Use this class to manage a set of bindings, which are automatically destroyed
// and removed from the set when the pipe they are bound to is disconnected.
-template <typename Interface>
+template <typename Interface, typename BindingType = Binding<Interface>>
class BindingSet {
public:
- BindingSet() {}
- ~BindingSet() { CloseAllBindings(); }
+ using PreDispatchCallback = base::Callback<void(void*)>;
+ using Traits = BindingSetTraits<BindingType>;
+ using ProxyType = typename Traits::ProxyType;
+ using RequestType = typename Traits::RequestType;
+
+ BindingSet() : BindingSet(BindingSetDispatchMode::WITHOUT_CONTEXT) {}
+
+ // Constructs a new BindingSet operating in |dispatch_mode|. If |WITH_CONTEXT|
+ // is used, AddBinding() supports a |context| argument, and dispatch_context()
+ // may be called during message or error dispatch to identify which specific
+ // binding received the message or error.
+ explicit BindingSet(BindingSetDispatchMode dispatch_mode)
+ : dispatch_mode_(dispatch_mode) {}
void set_connection_error_handler(const base::Closure& error_handler) {
error_handler_ = error_handler;
+ error_with_reason_handler_.Reset();
}
- void AddBinding(Interface* impl, InterfaceRequest<Interface> request) {
- auto binding = new Element(impl, std::move(request));
- binding->set_connection_error_handler(
- base::Bind(&BindingSet::OnConnectionError, base::Unretained(this)));
- bindings_.push_back(binding->GetWeakPtr());
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ error_with_reason_handler_ = error_handler;
+ error_handler_.Reset();
}
- // Returns an InterfacePtr bound to one end of a pipe whose other end is
- // bound to |this|.
- InterfacePtr<Interface> CreateInterfacePtrAndBind(Interface* impl) {
- InterfacePtr<Interface> interface_ptr;
- AddBinding(impl, GetProxy(&interface_ptr));
- return interface_ptr;
+ // Sets a callback to be invoked immediately before dispatching any message or
+ // error received by any of the bindings in the set. This may only be used
+ // if the set was constructed with |BindingSetDispatchMode::WITH_CONTEXT|.
+ // |handler| is passed the context associated with the binding which received
+ // the message or event about to be dispatched.
+ void set_pre_dispatch_handler(const PreDispatchCallback& handler) {
+ DCHECK(SupportsContext());
+ pre_dispatch_handler_ = handler;
}
- void CloseAllBindings() {
- for (const auto& it : bindings_) {
- if (it) {
- it->Close();
- delete it.get();
- }
- }
- bindings_.clear();
+ // Adds a new binding to the set which binds |request| to |impl|. If |context|
+ // is non-null, dispatch_context() will reflect this value during the extent
+ // of any message or error dispatch targeting this specific binding. Note that
+ // |context| may only be non-null if the BindingSet was constructed with
+ // |BindingSetDispatchMode::WITH_CONTEXT|.
+ BindingId AddBinding(Interface* impl,
+ RequestType request,
+ void* context = nullptr) {
+ DCHECK(!context || SupportsContext());
+ BindingId id = next_binding_id_++;
+ DCHECK_GE(next_binding_id_, 0u);
+ std::unique_ptr<Entry> entry =
+ base::MakeUnique<Entry>(impl, std::move(request), this, id, context);
+ bindings_.insert(std::make_pair(id, std::move(entry)));
+ return id;
+ }
+
+ // Removes a binding from the set. Note that this is safe to call even if the
+ // binding corresponding to |id| has already been removed.
+ //
+ // Returns |true| if the binding was removed and |false| if it didn't exist.
+ bool RemoveBinding(BindingId id) {
+ auto it = bindings_.find(id);
+ if (it == bindings_.end())
+ return false;
+ bindings_.erase(it);
+ return true;
+ }
+
+ // Returns a proxy bound to one end of a pipe whose other end is bound to
+ // |this|. If |id_storage| is not null, |*id_storage| will be set to the ID
+ // of the added binding.
+ ProxyType CreateInterfacePtrAndBind(Interface* impl,
+ BindingId* id_storage = nullptr) {
+ ProxyType proxy;
+ BindingId id = AddBinding(impl, Traits::GetProxy(&proxy));
+ if (id_storage)
+ *id_storage = id;
+ return proxy;
}
+ void CloseAllBindings() { bindings_.clear(); }
+
bool empty() const { return bindings_.empty(); }
+ // Implementations may call this when processing a dispatched message or
+ // error. During the extent of message or error dispatch, this will return the
+ // context associated with the specific binding which received the message or
+ // error. Use AddBinding() to associated a context with a specific binding.
+ //
+ // Note that this may ONLY be called if the BindingSet was constructed with
+ // |BindingSetDispatchMode::WITH_CONTEXT|.
+ void* dispatch_context() const {
+ DCHECK(SupportsContext());
+ return dispatch_context_;
+ }
+
+ void FlushForTesting() {
+ for (auto& binding : bindings_) {
+ binding.first->FlushForTesting();
+ }
+ }
+
private:
- class Element {
+ friend class Entry;
+
+ class Entry {
public:
- Element(Interface* impl, InterfaceRequest<Interface> request)
- : binding_(impl, std::move(request)), weak_ptr_factory_(this) {
- binding_.set_connection_error_handler(
- base::Bind(&Element::OnConnectionError, base::Unretained(this)));
+ Entry(Interface* impl,
+ RequestType request,
+ BindingSet* binding_set,
+ BindingId binding_id,
+ void* context)
+ : binding_(impl, std::move(request)),
+ binding_set_(binding_set),
+ binding_id_(binding_id),
+ context_(context) {
+ if (binding_set->SupportsContext())
+ binding_.AddFilter(base::MakeUnique<DispatchFilter>(this));
+ binding_.set_connection_error_with_reason_handler(
+ base::Bind(&Entry::OnConnectionError, base::Unretained(this)));
}
- ~Element() {}
+ void FlushForTesting() { binding_.FlushForTesting(); }
- void set_connection_error_handler(const base::Closure& error_handler) {
- error_handler_ = error_handler;
- }
+ private:
+ class DispatchFilter : public MessageReceiver {
+ public:
+ explicit DispatchFilter(Entry* entry) : entry_(entry) {}
+ ~DispatchFilter() override {}
+
+ private:
+ // MessageReceiver:
+ bool Accept(Message* message) override {
+ entry_->WillDispatch();
+ return true;
+ }
- base::WeakPtr<Element> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
+ Entry* entry_;
- void Close() { binding_.Close(); }
+ DISALLOW_COPY_AND_ASSIGN(DispatchFilter);
+ };
- void OnConnectionError() {
- base::Closure error_handler = error_handler_;
- delete this;
- if (!error_handler.is_null())
- error_handler.Run();
+ void WillDispatch() {
+ DCHECK(binding_set_->SupportsContext());
+ binding_set_->SetDispatchContext(context_);
}
- private:
- Binding<Interface> binding_;
- base::Closure error_handler_;
- base::WeakPtrFactory<Element> weak_ptr_factory_;
+ void OnConnectionError(uint32_t custom_reason,
+ const std::string& description) {
+ if (binding_set_->SupportsContext())
+ WillDispatch();
+ binding_set_->OnConnectionError(binding_id_, custom_reason, description);
+ }
+
+ BindingType binding_;
+ BindingSet* const binding_set_;
+ const BindingId binding_id_;
+ void* const context_;
- DISALLOW_COPY_AND_ASSIGN(Element);
+ DISALLOW_COPY_AND_ASSIGN(Entry);
};
- void OnConnectionError() {
- // Clear any deleted bindings.
- bindings_.erase(std::remove_if(bindings_.begin(), bindings_.end(),
- [](const base::WeakPtr<Element>& p) {
- return p.get() == nullptr;
- }),
- bindings_.end());
+ void SetDispatchContext(void* context) {
+ DCHECK(SupportsContext());
+ dispatch_context_ = context;
+ if (!pre_dispatch_handler_.is_null())
+ pre_dispatch_handler_.Run(context);
+ }
+
+ bool SupportsContext() const {
+ return dispatch_mode_ == BindingSetDispatchMode::WITH_CONTEXT;
+ }
+
+ void OnConnectionError(BindingId id,
+ uint32_t custom_reason,
+ const std::string& description) {
+ auto it = bindings_.find(id);
+ DCHECK(it != bindings_.end());
+ bindings_.erase(it);
if (!error_handler_.is_null())
error_handler_.Run();
+ else if (!error_with_reason_handler_.is_null())
+ error_with_reason_handler_.Run(custom_reason, description);
}
+ BindingSetDispatchMode dispatch_mode_;
base::Closure error_handler_;
- std::vector<base::WeakPtr<Element>> bindings_;
+ ConnectionErrorWithReasonCallback error_with_reason_handler_;
+ PreDispatchCallback pre_dispatch_handler_;
+ BindingId next_binding_id_ = 0;
+ std::map<BindingId, std::unique_ptr<Entry>> bindings_;
+ void* dispatch_context_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(BindingSet);
};
diff --git a/chromium/mojo/public/cpp/bindings/bindings_export.h b/chromium/mojo/public/cpp/bindings/bindings_export.h
new file mode 100644
index 00000000000..9fd7a2784eb
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/bindings_export.h
@@ -0,0 +1,34 @@
+// Copyright 2016 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_BINDINGS_EXPORT_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_BINDINGS_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+
+#if defined(WIN32)
+
+#if defined(MOJO_CPP_BINDINGS_IMPLEMENTATION)
+#define MOJO_CPP_BINDINGS_EXPORT __declspec(dllexport)
+#else
+#define MOJO_CPP_BINDINGS_EXPORT __declspec(dllimport)
+#endif
+
+#else // !defined(WIN32)
+
+#if defined(MOJO_CPP_BINDINGS_IMPLEMENTATION)
+#define MOJO_CPP_BINDINGS_EXPORT __attribute((visibility("default")))
+#else
+#define MOJO_CPP_BINDINGS_EXPORT
+#endif
+
+#endif // defined(WIN32)
+
+#else // !defined(COMPONENT_BUILD)
+
+#define MOJO_CPP_BINDINGS_EXPORT
+
+#endif // defined(COMPONENT_BUILD)
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDINGS_EXPORT_H_
diff --git a/chromium/mojo/public/cpp/bindings/connection_error_callback.h b/chromium/mojo/public/cpp/bindings/connection_error_callback.h
new file mode 100644
index 00000000000..306e99e45b3
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/connection_error_callback.h
@@ -0,0 +1,21 @@
+// Copyright 2016 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_CONNECTION_ERROR_CALLBACK_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_ERROR_CALLBACK_H_
+
+#include "base/callback.h"
+
+namespace mojo {
+
+// This callback type accepts user-defined disconnect reason and description. If
+// the other side specifies a reason on closing the connection, it will be
+// passed to the error handler.
+using ConnectionErrorWithReasonCallback =
+ base::Callback<void(uint32_t /* custom_reason */,
+ const std::string& /* description */)>;
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_ERROR_CALLBACK_H_
diff --git a/chromium/mojo/public/cpp/bindings/connector.h b/chromium/mojo/public/cpp/bindings/connector.h
index d14ad179baa..dcfe8cb9304 100644
--- a/chromium/mojo/public/cpp/bindings/connector.h
+++ b/chromium/mojo/public/cpp/bindings/connector.h
@@ -8,10 +8,12 @@
#include <memory>
#include "base/callback.h"
+#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
#include "mojo/public/cpp/system/core.h"
@@ -33,7 +35,8 @@ namespace mojo {
// - Sending messages can be configured to be thread safe (please see comments
// of the constructor). Other than that, the object should only be accessed
// on the creating thread.
-class Connector : public MessageReceiver {
+class MOJO_CPP_BINDINGS_EXPORT Connector
+ : NON_EXPORTED_BASE(public MessageReceiver) {
public:
enum ConnectorConfig {
// Connector::Accept() is only called from a single thread.
@@ -138,6 +141,7 @@ class Connector : public MessageReceiver {
// Whether currently the control flow is inside the sync handle watcher
// callback.
+ // It always returns false after CloseMessagePipe()/PassMessagePipe().
bool during_sync_handle_watcher_callback() const {
return sync_handle_watcher_callback_count_ > 0;
}
@@ -155,7 +159,8 @@ class Connector : public MessageReceiver {
void WaitToReadMore();
- // Returns false if |this| was destroyed during message dispatch.
+ // Returns false if it is impossible to receive more messages in the future.
+ // |this| may have been destroyed in that case.
WARN_UNUSED_RESULT bool ReadSingleMessage(MojoResult* read_result);
// |this| can be destroyed during message dispatch.
@@ -175,31 +180,36 @@ class Connector : public MessageReceiver {
base::Closure connection_error_handler_;
ScopedMessagePipeHandle message_pipe_;
- MessageReceiver* incoming_receiver_;
+ MessageReceiver* incoming_receiver_ = nullptr;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- Watcher handle_watcher_;
+ std::unique_ptr<Watcher> handle_watcher_;
- bool error_;
- bool drop_writes_;
- bool enforce_errors_from_incoming_receiver_;
+ bool error_ = false;
+ bool drop_writes_ = false;
+ bool enforce_errors_from_incoming_receiver_ = true;
- bool paused_;
+ bool paused_ = false;
// If sending messages is allowed from multiple threads, |lock_| is used to
// protect modifications to |message_pipe_| and |drop_writes_|.
std::unique_ptr<base::Lock> lock_;
std::unique_ptr<SyncHandleWatcher> sync_watcher_;
- bool allow_woken_up_by_others_;
+ bool allow_woken_up_by_others_ = false;
// If non-zero, currently the control flow is inside the sync handle watcher
// callback.
- size_t sync_handle_watcher_callback_count_;
+ size_t sync_handle_watcher_callback_count_ = 0;
base::ThreadChecker thread_checker_;
+ base::Lock connected_lock_;
+ bool connected_ = true;
+
// Create a single weak ptr and use it everywhere, to avoid the malloc/free
// cost of creating a new weak ptr whenever it is needed.
+ // NOTE: This weak pointer is invalidated when the message pipe is closed or
+ // transferred (i.e., when |connected_| is set to false).
base::WeakPtr<Connector> weak_self_;
base::WeakPtrFactory<Connector> weak_factory_;
diff --git a/chromium/mojo/public/cpp/bindings/lib/filter_chain.h b/chromium/mojo/public/cpp/bindings/filter_chain.h
index 447be3d1368..1262f39b803 100644
--- a/chromium/mojo/public/cpp/bindings/lib/filter_chain.h
+++ b/chromium/mojo/public/cpp/bindings/filter_chain.h
@@ -2,20 +2,22 @@
// 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_
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_
#include <utility>
#include <vector>
+#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/message.h"
-#include "mojo/public/cpp/bindings/message_filter.h"
namespace mojo {
-namespace internal {
-class FilterChain {
+class MOJO_CPP_BINDINGS_EXPORT FilterChain
+ : NON_EXPORTED_BASE(public MessageReceiver) {
public:
// Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while
// this object is alive.
@@ -23,25 +25,22 @@ class FilterChain {
FilterChain(FilterChain&& other);
FilterChain& operator=(FilterChain&& other);
- ~FilterChain();
+ ~FilterChain() override;
template <typename FilterType, typename... Args>
inline void Append(Args&&... args);
+ void Append(std::unique_ptr<MessageReceiver> filter);
+
// 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();
+ // MessageReceiver:
+ bool Accept(Message* message) override;
private:
- // Owned by this object.
- // TODO(dcheng): Use unique_ptr.
- std::vector<MessageFilter*> filters_;
+ std::vector<std::unique_ptr<MessageReceiver>> filters_;
MessageReceiver* sink_;
@@ -50,17 +49,13 @@ class FilterChain {
template <typename FilterType, typename... Args>
inline void FilterChain::Append(Args&&... args) {
- FilterType* filter = new FilterType(std::forward<Args>(args)..., sink_);
- if (!filters_.empty())
- filters_.back()->set_sink(filter);
- filters_.push_back(filter);
+ Append(base::MakeUnique<FilterType>(std::forward<Args>(args)...));
}
template <>
inline void FilterChain::Append<PassThroughFilter>() {
}
-} // namespace internal
} // namespace mojo
-#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_FILTER_CHAIN_H_
+#endif // MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_
diff --git a/chromium/mojo/public/cpp/bindings/interface_data_view.h b/chromium/mojo/public/cpp/bindings/interface_data_view.h
new file mode 100644
index 00000000000..ef1225431c9
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/interface_data_view.h
@@ -0,0 +1,25 @@
+// Copyright 2016 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_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_DATA_VIEW_H_
+
+namespace mojo {
+
+// They are used for type identification purpose only.
+template <typename Interface>
+class AssociatedInterfacePtrInfoDataView {};
+
+template <typename Interface>
+class AssociatedInterfaceRequestDataView {};
+
+template <typename Interface>
+class InterfacePtrDataView {};
+
+template <typename Interface>
+class InterfaceRequestDataView {};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_DATA_VIEW_H_
diff --git a/chromium/mojo/public/cpp/bindings/interface_endpoint_client.h b/chromium/mojo/public/cpp/bindings/interface_endpoint_client.h
index 9dc40a2ea3f..6129d75bbf7 100644
--- a/chromium/mojo/public/cpp/bindings/interface_endpoint_client.h
+++ b/chromium/mojo/public/cpp/bindings/interface_endpoint_client.h
@@ -11,14 +11,20 @@
#include <memory>
#include "base/callback.h"
+#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
+#include "mojo/public/cpp/bindings/filter_chain.h"
+#include "mojo/public/cpp/bindings/lib/control_message_handler.h"
+#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
#include "mojo/public/cpp/bindings/message.h"
-#include "mojo/public/cpp/bindings/message_filter.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
namespace mojo {
@@ -30,15 +36,18 @@ class InterfaceEndpointController;
// InterfaceEndpointClient handles message sending and receiving of an interface
// endpoint, either the implementation side or the client side.
// It should only be accessed and destructed on the creating thread.
-class InterfaceEndpointClient : public MessageReceiverWithResponder {
+class MOJO_CPP_BINDINGS_EXPORT InterfaceEndpointClient
+ : NON_EXPORTED_BASE(public MessageReceiverWithResponder),
+ public base::MessageLoop::DestructionObserver {
public:
// |receiver| is okay to be null. If it is not null, it must outlive this
// object.
InterfaceEndpointClient(ScopedInterfaceEndpointHandle handle,
MessageReceiverWithResponderStatus* receiver,
- std::unique_ptr<MessageFilter> payload_validator,
+ std::unique_ptr<MessageReceiver> payload_validator,
bool expect_sync_requests,
- scoped_refptr<base::SingleThreadTaskRunner> runner);
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
+ uint32_t interface_version);
~InterfaceEndpointClient() override;
// Sets the error handler to receive notifications when an error is
@@ -46,6 +55,14 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder {
void set_connection_error_handler(const base::Closure& error_handler) {
DCHECK(thread_checker_.CalledOnValidThread());
error_handler_ = error_handler;
+ error_with_reason_handler_.Reset();
+ }
+
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ error_with_reason_handler_ = error_handler;
+ error_handler_.Reset();
}
// Returns true if an error was encountered.
@@ -66,6 +83,10 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder {
AssociatedGroup* associated_group();
uint32_t interface_id() const;
+ // Adds a MessageReceiver which can filter a message after validation but
+ // before dispatch.
+ void AddFilter(std::unique_ptr<MessageReceiver> filter);
+
// After this call the object is in an invalid state and shouldn't be reused.
ScopedInterfaceEndpointHandle PassHandle();
@@ -85,6 +106,10 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder {
bool HandleIncomingMessage(Message* message);
void NotifyError();
+ internal::ControlMessageProxy* control_message_proxy() {
+ return &control_message_proxy_;
+ }
+
private:
// Maps from the id of a response to the MessageReceiver that handles the
// response.
@@ -96,7 +121,7 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder {
explicit SyncResponseInfo(bool* in_response_received);
~SyncResponseInfo();
- std::unique_ptr<Message> response;
+ Message response;
// Points to a stack-allocated variable.
bool* response_received;
@@ -124,14 +149,18 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder {
};
bool HandleValidatedMessage(Message* message);
+ void StopObservingIfNecessary();
+
+ // base::MessageLoop::DestructionObserver:
+ void WillDestroyCurrentMessageLoop() override;
ScopedInterfaceEndpointHandle handle_;
std::unique_ptr<AssociatedGroup> associated_group_;
InterfaceEndpointController* controller_;
MessageReceiverWithResponderStatus* const incoming_receiver_;
- std::unique_ptr<MessageFilter> payload_validator_;
HandleIncomingMessageThunk thunk_;
+ FilterChain filters_;
AsyncResponderMap async_responders_;
SyncResponseMap sync_responses_;
@@ -139,10 +168,16 @@ class InterfaceEndpointClient : public MessageReceiverWithResponder {
uint64_t next_request_id_;
base::Closure error_handler_;
+ ConnectionErrorWithReasonCallback error_with_reason_handler_;
bool encountered_error_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ internal::ControlMessageProxy control_message_proxy_;
+ internal::ControlMessageHandler control_message_handler_;
+
+ bool observing_message_loop_destruction_ = true;
+
base::ThreadChecker thread_checker_;
base::WeakPtrFactory<InterfaceEndpointClient> weak_ptr_factory_;
diff --git a/chromium/mojo/public/cpp/bindings/interface_ptr.h b/chromium/mojo/public/cpp/bindings/interface_ptr.h
index d894984993c..bd77ead0428 100644
--- a/chromium/mojo/public/cpp/bindings/interface_ptr.h
+++ b/chromium/mojo/public/cpp/bindings/interface_ptr.h
@@ -6,6 +6,8 @@
#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
#include <stdint.h>
+
+#include <string>
#include <utility>
#include "base/callback_forward.h"
@@ -14,6 +16,7 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
#include "mojo/public/cpp/bindings/interface_ptr_info.h"
#include "mojo/public/cpp/bindings/lib/interface_ptr_state.h"
@@ -114,6 +117,12 @@ class InterfacePtr {
internal_state_.RequireVersion(version);
}
+ // Sends a no-op message on the underlying message pipe and runs the current
+ // message loop until its response is received. This can be used in tests to
+ // verify that no message was sent on a message pipe in response to some
+ // stimulus.
+ void FlushForTesting() { internal_state_.FlushForTesting(); }
+
// Closes the bound message pipe (if any) and returns the pointer to the
// unbound state.
void reset() {
@@ -121,22 +130,18 @@ class InterfacePtr {
internal_state_.Swap(&doomed);
}
+ // Similar to the method above, but also specifies a disconnect reason.
+ void ResetWithReason(uint32_t custom_reason, const std::string& description) {
+ if (internal_state_.is_bound())
+ internal_state_.SendDisconnectReason(custom_reason, description);
+ reset();
+ }
+
// Whether there are any associated interfaces running on the pipe currently.
bool HasAssociatedInterfaces() const {
return internal_state_.HasAssociatedInterfaces();
}
- // Blocks the current thread until the next incoming response callback arrives
- // or an error occurs. Returns |true| if a response arrived, or |false| in
- // case of error.
- //
- // This method may only be called if the InterfacePtr has been bound to a
- // message pipe and there are no associated interfaces running.
- bool WaitForIncomingResponse() {
- CHECK(!HasAssociatedInterfaces());
- return internal_state_.WaitForIncomingResponse();
- }
-
// Indicates whether the message pipe has encountered an error. If true,
// method calls made on this interface will be dropped (and may already have
// been dropped).
@@ -151,6 +156,11 @@ class InterfacePtr {
internal_state_.set_connection_error_handler(error_handler);
}
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ internal_state_.set_connection_error_with_reason_handler(error_handler);
+ }
+
// Unbinds the InterfacePtr and returns the information which could be used
// to setup an InterfacePtr again. This method may be used to move the proxy
// to a different thread (see class comments for details).
@@ -191,8 +201,7 @@ class InterfacePtr {
}
// DO NOT USE. Exposed only for internal use and for testing.
- internal::InterfacePtrState<Interface, Interface::PassesAssociatedKinds_>*
- internal_state() {
+ internal::InterfacePtrState<Interface, true>* internal_state() {
return &internal_state_;
}
@@ -200,9 +209,7 @@ class InterfacePtr {
// implicitly convertible to a real bool (which is dangerous).
private:
// TODO(dcheng): Use an explicit conversion operator.
- typedef internal::InterfacePtrState<Interface,
- Interface::PassesAssociatedKinds_>
- InterfacePtr::*Testable;
+ typedef internal::InterfacePtrState<Interface, true> InterfacePtr::*Testable;
public:
operator Testable() const {
@@ -218,8 +225,7 @@ class InterfacePtr {
template <typename T>
bool operator!=(const InterfacePtr<T>& other) const = delete;
- typedef internal::InterfacePtrState<Interface,
- Interface::PassesAssociatedKinds_> State;
+ typedef internal::InterfacePtrState<Interface, true> State;
mutable State internal_state_;
DISALLOW_COPY_AND_ASSIGN(InterfacePtr);
diff --git a/chromium/mojo/public/cpp/bindings/interface_request.h b/chromium/mojo/public/cpp/bindings/interface_request.h
index fc23aec3ee7..5d75dd3e610 100644
--- a/chromium/mojo/public/cpp/bindings/interface_request.h
+++ b/chromium/mojo/public/cpp/bindings/interface_request.h
@@ -5,12 +5,15 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_
#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_
+#include <string>
#include <utility>
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
+#include "mojo/public/cpp/system/message_pipe.h"
namespace mojo {
@@ -64,6 +67,20 @@ class InterfaceRequest {
return !is_pending() && !other.is_pending();
}
+ void ResetWithReason(uint32_t custom_reason, const std::string& description) {
+ if (!handle_.is_valid())
+ return;
+
+ Message message =
+ internal::ControlMessageProxy::ConstructDisconnectReasonMessage(
+ custom_reason, description);
+ MojoResult result = WriteMessageNew(
+ handle_.get(), message.TakeMojoMessage(), MOJO_WRITE_MESSAGE_FLAG_NONE);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+
+ handle_.reset();
+ }
+
private:
ScopedMessagePipeHandle handle_;
diff --git a/chromium/mojo/public/cpp/bindings/lib/array_internal.h b/chromium/mojo/public/cpp/bindings/lib/array_internal.h
index adf5e32038f..9bb35218106 100644
--- a/chromium/mojo/public/cpp/bindings/lib/array_internal.h
+++ b/chromium/mojo/public/cpp/bindings/lib/array_internal.h
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "mojo/public/c/system/macros.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/buffer.h"
#include "mojo/public/cpp/bindings/lib/serialization_util.h"
@@ -28,13 +29,13 @@ namespace internal {
template <typename K, typename V>
class Map_Data;
-std::string MakeMessageWithArrayIndex(const char* message,
- size_t size,
- size_t index);
+MOJO_CPP_BINDINGS_EXPORT std::string
+MakeMessageWithArrayIndex(const char* message, size_t size, size_t index);
-std::string MakeMessageWithExpectedArraySize(const char* message,
- size_t size,
- size_t expected_size);
+MOJO_CPP_BINDINGS_EXPORT std::string MakeMessageWithExpectedArraySize(
+ const char* message,
+ size_t size,
+ size_t expected_size);
template <typename T>
struct ArrayDataTraits {
@@ -58,28 +59,6 @@ struct ArrayDataTraits {
}
};
-template <typename P>
-struct ArrayDataTraits<P*> {
- using StorageType = Pointer<P>;
- using Ref = P*&;
- using ConstRef = P* const&;
-
- static const uint32_t kMaxNumElements =
- (std::numeric_limits<uint32_t>::max() - sizeof(ArrayHeader)) /
- sizeof(StorageType);
-
- static uint32_t GetStorageSize(uint32_t num_elements) {
- DCHECK(num_elements <= kMaxNumElements);
- return sizeof(ArrayHeader) + 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.
@@ -89,7 +68,7 @@ template <>
struct ArrayDataTraits<bool> {
// Helper class to emulate a reference to a bool, used for direct element
// access.
- class BitRef {
+ class MOJO_CPP_BINDINGS_EXPORT BitRef {
public:
~BitRef();
BitRef& operator=(bool value);
@@ -131,7 +110,7 @@ struct ArrayDataTraits<bool> {
//
// TODO(yzshen): Validation code should be organzied in a way similar to
// Serializer<>, or merged into it. It should be templatized with the mojo
-// wrapper type instead of the data type, that way we can use MojomTypeTraits
+// data view type instead of the data type, that way we can use MojomTypeTraits
// to determine the categories.
template <typename T, bool is_union, bool is_handle_or_interface>
@@ -141,12 +120,6 @@ template <typename T>
struct ArraySerializationHelper<T, false, false> {
using ElementType = typename ArrayDataTraits<T>::StorageType;
- static void EncodePointers(const ArrayHeader* header,
- ElementType* elements) {}
-
- static void DecodePointers(const ArrayHeader* header,
- ElementType* elements) {}
-
static bool ValidateElements(const ArrayHeader* header,
const ElementType* elements,
ValidationContext* validation_context,
@@ -172,12 +145,6 @@ template <typename T>
struct ArraySerializationHelper<T, false, true> {
using ElementType = typename ArrayDataTraits<T>::StorageType;
- static void EncodePointers(const ArrayHeader* header,
- ElementType* elements) {}
-
- static void DecodePointers(const ArrayHeader* header,
- ElementType* elements) {}
-
static bool ValidateElements(const ArrayHeader* header,
const ElementType* elements,
ValidationContext* validation_context,
@@ -209,19 +176,9 @@ struct ArraySerializationHelper<T, false, true> {
}
};
-template <typename P>
-struct ArraySerializationHelper<P*, false, false> {
- using ElementType = typename ArrayDataTraits<P*>::StorageType;
-
- static void EncodePointers(const ArrayHeader* header, ElementType* elements) {
- for (uint32_t i = 0; i < header->num_elements; ++i)
- Encode(&elements[i]);
- }
-
- static void DecodePointers(const ArrayHeader* header, ElementType* elements) {
- for (uint32_t i = 0; i < header->num_elements; ++i)
- Decode(&elements[i]);
- }
+template <typename T>
+struct ArraySerializationHelper<Pointer<T>, false, false> {
+ using ElementType = typename ArrayDataTraits<Pointer<T>>::StorageType;
static bool ValidateElements(const ArrayHeader* header,
const ElementType* elements,
@@ -237,7 +194,7 @@ struct ArraySerializationHelper<P*, false, false> {
i).c_str());
return false;
}
- if (!ValidateCaller<P>::Run(elements[i], validation_context,
+ if (!ValidateCaller<T>::Run(elements[i], validation_context,
validate_params->element_validate_params)) {
return false;
}
@@ -246,9 +203,11 @@ struct ArraySerializationHelper<P*, false, false> {
}
private:
- template <typename T>
+ template <typename U,
+ bool is_array_or_map = IsSpecializationOf<Array_Data, U>::value ||
+ IsSpecializationOf<Map_Data, U>::value>
struct ValidateCaller {
- static bool Run(const Pointer<T>& data,
+ static bool Run(const Pointer<U>& data,
ValidationContext* validation_context,
const ContainerValidateParams* validate_params) {
DCHECK(!validate_params)
@@ -258,21 +217,12 @@ struct ArraySerializationHelper<P*, false, false> {
}
};
- template <typename Key, typename Value>
- struct ValidateCaller<Map_Data<Key, Value>> {
- static bool Run(const Pointer<Map_Data<Key, Value>>& data,
+ template <typename U>
+ struct ValidateCaller<U, true> {
+ static bool Run(const Pointer<U>& data,
ValidationContext* validation_context,
const ContainerValidateParams* validate_params) {
- return ValidateMap(data, validation_context, validate_params);
- }
- };
-
- template <typename T>
- struct ValidateCaller<Array_Data<T>> {
- static bool Run(const Pointer<Array_Data<T>>& data,
- ValidationContext* validation_context,
- const ContainerValidateParams* validate_params) {
- return ValidateArray(data, validation_context, validate_params);
+ return ValidateContainer(data, validation_context, validate_params);
}
};
};
@@ -281,16 +231,6 @@ template <typename U>
struct ArraySerializationHelper<U, true, false> {
using ElementType = typename ArrayDataTraits<U>::StorageType;
- static void EncodePointers(const ArrayHeader* header, ElementType* elements) {
- for (uint32_t i = 0; i < header->num_elements; ++i)
- elements[i].EncodePointers();
- }
-
- static void DecodePointers(const ArrayHeader* header, ElementType* elements) {
- for (uint32_t i = 0; i < header->num_elements; ++i)
- elements[i].DecodePointers();
- }
-
static bool ValidateElements(const ArrayHeader* header,
const ElementType* elements,
ValidationContext* validation_context,
@@ -406,9 +346,6 @@ class Array_Data {
reinterpret_cast<const char*>(this) + sizeof(*this));
}
- void EncodePointers() { Helper::EncodePointers(&header_, storage()); }
- void DecodePointers() { Helper::DecodePointers(&header_, storage()); }
-
private:
Array_Data(uint32_t num_bytes, uint32_t num_elements) {
header_.num_bytes = num_bytes;
diff --git a/chromium/mojo/public/cpp/bindings/lib/array_serialization.h b/chromium/mojo/public/cpp/bindings/lib/array_serialization.h
index c0e9318333b..9e68f452458 100644
--- a/chromium/mojo/public/cpp/bindings/lib/array_serialization.h
+++ b/chromium/mojo/public/cpp/bindings/lib/array_serialization.h
@@ -14,7 +14,7 @@
#include <vector>
#include "base/logging.h"
-#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/array_data_view.h"
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
@@ -46,7 +46,7 @@ class ArrayIterator<Traits, MaybeConstUserType, true> {
using GetNextResult =
decltype(Traits::GetValue(std::declval<IteratorType&>()));
GetNextResult GetNext() {
- auto& value = Traits::GetValue(iter_);
+ GetNextResult value = Traits::GetValue(iter_);
Traits::AdvanceIterator(iter_);
return value;
}
@@ -287,9 +287,6 @@ struct ArraySerializer<
using Element = typename MojomType::Element;
using Traits = ArrayTraits<UserType>;
- static_assert(std::is_same<Element, typename Traits::Element>::value,
- "Incorrect array serializer");
-
static size_t GetSerializedSize(UserTypeIterator* input,
SerializationContext* context) {
return sizeof(Data) +
@@ -306,7 +303,8 @@ struct ArraySerializer<
size_t size = input->GetSize();
for (size_t i = 0; i < size; ++i) {
- Serialize<Element>(input->GetNext(), &output->at(i), context);
+ typename UserTypeIterator::GetNextResult next = input->GetNext();
+ Serialize<Element>(next, &output->at(i), context);
static const ValidationError kError =
BelongsTo<Element,
@@ -353,19 +351,18 @@ struct ArraySerializer<MojomType,
MojomTypeCategory::STRUCT>::value>::type> {
using UserType = typename std::remove_const<MaybeConstUserType>::type;
using Data = typename MojomTypeTraits<MojomType>::Data;
- using DataElement = typename Data::Element;
using Element = typename MojomType::Element;
+ using DataElementPtr = typename MojomTypeTraits<Element>::Data*;
using Traits = ArrayTraits<UserType>;
static size_t GetSerializedSize(UserTypeIterator* input,
SerializationContext* context) {
size_t element_count = input->GetSize();
- size_t size =
- sizeof(Data) +
- element_count *
- sizeof(Pointer<typename std::remove_pointer<DataElement>::type>);
- for (size_t i = 0; i < element_count; ++i)
- size += PrepareToSerialize<Element>(input->GetNext(), context);
+ size_t size = sizeof(Data) + element_count * sizeof(typename Data::Element);
+ for (size_t i = 0; i < element_count; ++i) {
+ typename UserTypeIterator::GetNextResult next = input->GetNext();
+ size += PrepareToSerialize<Element>(next, context);
+ }
return size;
}
@@ -376,13 +373,14 @@ struct ArraySerializer<MojomType,
SerializationContext* context) {
size_t size = input->GetSize();
for (size_t i = 0; i < size; ++i) {
- DataElement element;
- SerializeCaller<Element>::Run(input->GetNext(), buf, &element,
+ DataElementPtr data_ptr;
+ typename UserTypeIterator::GetNextResult next = input->GetNext();
+ SerializeCaller<Element>::Run(next, buf, &data_ptr,
validate_params->element_validate_params,
context);
- output->at(i) = element;
+ output->at(i).Set(data_ptr);
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !validate_params->element_is_nullable && !element,
+ !validate_params->element_is_nullable && !data_ptr,
VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
MakeMessageWithArrayIndex("null in array expecting valid pointers",
size, i));
@@ -391,19 +389,15 @@ struct ArraySerializer<MojomType,
static bool DeserializeElements(Data* input,
UserType* output,
SerializationContext* context) {
- bool success = true;
if (!Traits::Resize(*output, input->size()))
return false;
ArrayIterator<Traits, UserType> iterator(*output);
for (size_t i = 0; i < input->size(); ++i) {
- // Note that we rely on complete deserialization taking place in order to
- // transfer ownership of all encoded handles. Therefore we don't
- // short-circuit on failure here.
- if (!Deserialize<Element>(input->at(i), &iterator.GetNext(), context)) {
- success = false;
- }
+ if (!Deserialize<Element>(input->at(i).Get(), &iterator.GetNext(),
+ context))
+ return false;
}
- return success;
+ return true;
}
private:
@@ -415,7 +409,7 @@ struct ArraySerializer<MojomType,
template <typename InputElementType>
static void Run(InputElementType&& input,
Buffer* buf,
- DataElement* output,
+ DataElementPtr* output,
const ContainerValidateParams* validate_params,
SerializationContext* context) {
Serialize<T>(std::forward<InputElementType>(input), buf, output, context);
@@ -427,7 +421,7 @@ struct ArraySerializer<MojomType,
template <typename InputElementType>
static void Run(InputElementType&& input,
Buffer* buf,
- DataElement* output,
+ DataElementPtr* output,
const ContainerValidateParams* validate_params,
SerializationContext* context) {
Serialize<T>(std::forward<InputElementType>(input), buf, output,
@@ -451,10 +445,6 @@ struct ArraySerializer<
using Element = typename MojomType::Element;
using Traits = ArrayTraits<UserType>;
- static_assert(std::is_same<typename MojomType::Element,
- typename Traits::Element>::value,
- "Incorrect array serializer");
-
static size_t GetSerializedSize(UserTypeIterator* input,
SerializationContext* context) {
size_t element_count = input->GetSize();
@@ -462,7 +452,8 @@ struct ArraySerializer<
for (size_t i = 0; i < element_count; ++i) {
// Call with |inlined| set to false, so that it will account for both the
// data in the union and the space in the array used to hold the union.
- size += PrepareToSerialize<Element>(input->GetNext(), false, context);
+ typename UserTypeIterator::GetNextResult next = input->GetNext();
+ size += PrepareToSerialize<Element>(next, false, context);
}
return size;
}
@@ -475,7 +466,8 @@ struct ArraySerializer<
size_t size = input->GetSize();
for (size_t i = 0; i < size; ++i) {
typename Data::Element* result = output->storage() + i;
- Serialize<Element>(input->GetNext(), buf, &result, true, context);
+ typename UserTypeIterator::GetNextResult next = input->GetNext();
+ Serialize<Element>(next, buf, &result, true, context);
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
!validate_params->element_is_nullable && output->at(i).is_null(),
VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
@@ -487,30 +479,25 @@ struct ArraySerializer<
static bool DeserializeElements(Data* input,
UserType* output,
SerializationContext* context) {
- bool success = true;
if (!Traits::Resize(*output, input->size()))
return false;
ArrayIterator<Traits, UserType> iterator(*output);
for (size_t i = 0; i < input->size(); ++i) {
- // Note that we rely on complete deserialization taking place in order to
- // transfer ownership of all encoded handles. Therefore we don't
- // short-circuit on failure here.
- if (!Deserialize<Element>(&input->at(i), &iterator.GetNext(), context)) {
- success = false;
- }
+ if (!Deserialize<Element>(&input->at(i), &iterator.GetNext(), context))
+ return false;
}
- return success;
+ return true;
}
};
template <typename Element, typename MaybeConstUserType>
-struct Serializer<Array<Element>, MaybeConstUserType> {
+struct Serializer<ArrayDataView<Element>, MaybeConstUserType> {
using UserType = typename std::remove_const<MaybeConstUserType>::type;
using Traits = ArrayTraits<UserType>;
- using Impl = ArraySerializer<Array<Element>,
+ using Impl = ArraySerializer<ArrayDataView<Element>,
MaybeConstUserType,
ArrayIterator<Traits, MaybeConstUserType>>;
- using Data = typename MojomTypeTraits<Array<Element>>::Data;
+ using Data = typename MojomTypeTraits<ArrayDataView<Element>>::Data;
static size_t PrepareToSerialize(MaybeConstUserType& input,
SerializationContext* context) {
diff --git a/chromium/mojo/public/cpp/bindings/lib/associated_group_controller.cc b/chromium/mojo/public/cpp/bindings/lib/associated_group_controller.cc
index 42db9b383d3..78af40a2a4e 100644
--- a/chromium/mojo/public/cpp/bindings/lib/associated_group_controller.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/associated_group_controller.cc
@@ -8,11 +8,6 @@
namespace mojo {
-AssociatedGroupController::AssociatedGroupController(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : base::RefCountedDeleteOnMessageLoop<AssociatedGroupController>(
- task_runner) {}
-
AssociatedGroupController::~AssociatedGroupController() {}
std::unique_ptr<AssociatedGroup>
diff --git a/chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h b/chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
index c7f74fbb9c3..839978dbbaa 100644
--- a/chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
+++ b/chromium/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
@@ -9,6 +9,7 @@
#include <algorithm> // For |std::swap()|.
#include <memory>
+#include <string>
#include <utility>
#include "base/bind.h"
@@ -20,8 +21,10 @@
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/associated_group_controller.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
#include "mojo/public/cpp/bindings/interface_id.h"
+#include "mojo/public/cpp/bindings/lib/control_message_handler.h"
#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -52,12 +55,11 @@ class AssociatedInterfacePtrState {
}
void QueryVersion(const base::Callback<void(uint32_t)>& callback) {
- // Do a static cast in case the interface contains methods with the same
- // name. It is safe to capture |this| because the callback won't be run
- // after this object goes away.
- static_cast<ControlMessageProxy*>(proxy_.get())
- ->QueryVersion(base::Bind(&AssociatedInterfacePtrState::OnQueryVersion,
- base::Unretained(this), callback));
+ // It is safe to capture |this| because the callback won't be run after this
+ // object goes away.
+ endpoint_client_->control_message_proxy()->QueryVersion(
+ base::Bind(&AssociatedInterfacePtrState::OnQueryVersion,
+ base::Unretained(this), callback));
}
void RequireVersion(uint32_t version) {
@@ -65,9 +67,17 @@ class AssociatedInterfacePtrState {
return;
version_ = version;
- // Do a static cast in case the interface contains methods with the same
- // name.
- static_cast<ControlMessageProxy*>(proxy_.get())->RequireVersion(version);
+ endpoint_client_->control_message_proxy()->RequireVersion(version);
+ }
+
+ void FlushForTesting() {
+ endpoint_client_->control_message_proxy()->FlushForTesting();
+ }
+
+ void SendDisconnectReason(uint32_t custom_reason,
+ const std::string& description) {
+ endpoint_client_->control_message_proxy()->SendDisconnectReason(
+ custom_reason, description);
}
void Swap(AssociatedInterfacePtrState* other) {
@@ -85,10 +95,12 @@ class AssociatedInterfacePtrState {
DCHECK(info.is_valid());
version_ = info.version();
+ // The version is only queried from the client so the value passed here
+ // will not be used.
endpoint_client_.reset(new InterfaceEndpointClient(
info.PassHandle(), nullptr,
base::WrapUnique(new typename Interface::ResponseValidator_()), false,
- std::move(runner)));
+ std::move(runner), 0u));
proxy_.reset(new Proxy(endpoint_client_.get()));
proxy_->serialization_context()->group_controller =
endpoint_client_->group_controller();
@@ -114,6 +126,12 @@ class AssociatedInterfacePtrState {
endpoint_client_->set_connection_error_handler(error_handler);
}
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ DCHECK(endpoint_client_);
+ endpoint_client_->set_connection_error_with_reason_handler(error_handler);
+ }
+
// Returns true if bound and awaiting a response to a message.
bool has_pending_callbacks() const {
return endpoint_client_ && endpoint_client_->has_pending_responders();
diff --git a/chromium/mojo/public/cpp/bindings/lib/binding_state.cc b/chromium/mojo/public/cpp/bindings/lib/binding_state.cc
new file mode 100644
index 00000000000..e41258f586c
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/binding_state.cc
@@ -0,0 +1,166 @@
+// Copyright 2016 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/binding_state.h"
+
+#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
+
+namespace mojo {
+namespace internal {
+
+SimpleBindingState::SimpleBindingState() = default;
+
+SimpleBindingState::~SimpleBindingState() = default;
+
+void SimpleBindingState::AddFilter(std::unique_ptr<MessageReceiver> filter) {
+ DCHECK(router_);
+ router_->AddFilter(std::move(filter));
+}
+
+void SimpleBindingState::PauseIncomingMethodCallProcessing() {
+ DCHECK(router_);
+ router_->PauseIncomingMethodCallProcessing();
+}
+void SimpleBindingState::ResumeIncomingMethodCallProcessing() {
+ DCHECK(router_);
+ router_->ResumeIncomingMethodCallProcessing();
+}
+
+bool SimpleBindingState::WaitForIncomingMethodCall(MojoDeadline deadline) {
+ DCHECK(router_);
+ return router_->WaitForIncomingMessage(deadline);
+}
+
+void SimpleBindingState::Close() {
+ if (!router_)
+ return;
+
+ router_->CloseMessagePipe();
+ DestroyRouter();
+}
+
+void SimpleBindingState::CloseWithReason(uint32_t custom_reason,
+ const std::string& description) {
+ if (router_)
+ router_->control_message_proxy()->SendDisconnectReason(custom_reason,
+ description);
+ Close();
+}
+
+void SimpleBindingState::FlushForTesting() {
+ router_->control_message_proxy()->FlushForTesting();
+}
+
+void SimpleBindingState::EnableTestingMode() {
+ DCHECK(is_bound());
+ router_->EnableTestingMode();
+}
+
+void SimpleBindingState::BindInternal(
+ ScopedMessagePipeHandle handle,
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
+ const char* interface_name,
+ std::unique_ptr<MessageReceiver> request_validator,
+ bool has_sync_methods,
+ MessageReceiverWithResponderStatus* stub,
+ uint32_t interface_version) {
+ FilterChain filters;
+ filters.Append<MessageHeaderValidator>(interface_name);
+ filters.Append(std::move(request_validator));
+
+ router_ = new internal::Router(std::move(handle), std::move(filters),
+ has_sync_methods, std::move(runner),
+ interface_version);
+ router_->set_incoming_receiver(stub);
+}
+
+void SimpleBindingState::DestroyRouter() {
+ delete router_;
+ router_ = nullptr;
+}
+
+// -----------------------------------------------------------------------------
+
+MultiplexedBindingState::MultiplexedBindingState() = default;
+
+MultiplexedBindingState::~MultiplexedBindingState() = default;
+
+void MultiplexedBindingState::AddFilter(
+ std::unique_ptr<MessageReceiver> filter) {
+ DCHECK(endpoint_client_);
+ endpoint_client_->AddFilter(std::move(filter));
+}
+
+bool MultiplexedBindingState::HasAssociatedInterfaces() const {
+ return router_ ? router_->HasAssociatedEndpoints() : false;
+}
+
+void MultiplexedBindingState::PauseIncomingMethodCallProcessing() {
+ DCHECK(router_);
+ router_->PauseIncomingMethodCallProcessing();
+}
+void MultiplexedBindingState::ResumeIncomingMethodCallProcessing() {
+ DCHECK(router_);
+ router_->ResumeIncomingMethodCallProcessing();
+}
+
+bool MultiplexedBindingState::WaitForIncomingMethodCall(MojoDeadline deadline) {
+ DCHECK(router_);
+ return router_->WaitForIncomingMessage(deadline);
+}
+
+void MultiplexedBindingState::Close() {
+ if (!router_)
+ return;
+
+ endpoint_client_.reset();
+ router_->CloseMessagePipe();
+ router_ = nullptr;
+}
+
+void MultiplexedBindingState::CloseWithReason(uint32_t custom_reason,
+ const std::string& description) {
+ if (endpoint_client_)
+ endpoint_client_->control_message_proxy()->SendDisconnectReason(
+ custom_reason, description);
+ Close();
+}
+
+void MultiplexedBindingState::FlushForTesting() {
+ endpoint_client_->control_message_proxy()->FlushForTesting();
+}
+
+void MultiplexedBindingState::EnableTestingMode() {
+ DCHECK(is_bound());
+ router_->EnableTestingMode();
+}
+
+void MultiplexedBindingState::BindInternal(
+ ScopedMessagePipeHandle handle,
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
+ const char* interface_name,
+ std::unique_ptr<MessageReceiver> request_validator,
+ bool passes_associated_kinds,
+ bool has_sync_methods,
+ MessageReceiverWithResponderStatus* stub,
+ uint32_t interface_version) {
+ DCHECK(!router_);
+
+ MultiplexRouter::Config config =
+ passes_associated_kinds
+ ? MultiplexRouter::MULTI_INTERFACE
+ : (has_sync_methods
+ ? MultiplexRouter::SINGLE_INTERFACE_WITH_SYNC_METHODS
+ : MultiplexRouter::SINGLE_INTERFACE);
+ router_ = new MultiplexRouter(std::move(handle), config, false, runner);
+ router_->SetMasterInterfaceName(interface_name);
+
+ endpoint_client_.reset(new InterfaceEndpointClient(
+ router_->CreateLocalEndpointHandle(kMasterInterfaceId), stub,
+ std::move(request_validator), has_sync_methods, std::move(runner),
+ interface_version));
+}
+
+} // namesapce internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/binding_state.h b/chromium/mojo/public/cpp/bindings/lib/binding_state.h
index c8d3e834a39..98eccb7186b 100644
--- a/chromium/mojo/public/cpp/bindings/lib/binding_state.h
+++ b/chromium/mojo/public/cpp/bindings/lib/binding_state.h
@@ -6,6 +6,7 @@
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_
#include <memory>
+#include <string>
#include <utility>
#include "base/bind.h"
@@ -16,12 +17,14 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/associated_group.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
+#include "mojo/public/cpp/bindings/filter_chain.h"
#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
#include "mojo/public/cpp/bindings/interface_id.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/bindings/interface_ptr_info.h"
#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/bindings/lib/filter_chain.h"
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
#include "mojo/public/cpp/bindings/lib/router.h"
#include "mojo/public/cpp/bindings/message_header_validator.h"
@@ -31,6 +34,64 @@
namespace mojo {
namespace internal {
+// Base class used for templated binding primitives which bind a pipe
+// exclusively to a single interface.
+class MOJO_CPP_BINDINGS_EXPORT SimpleBindingState {
+ public:
+ SimpleBindingState();
+ ~SimpleBindingState();
+
+ void AddFilter(std::unique_ptr<MessageReceiver> filter);
+
+ bool HasAssociatedInterfaces() const { return false; }
+
+ void PauseIncomingMethodCallProcessing();
+ void ResumeIncomingMethodCallProcessing();
+
+ bool WaitForIncomingMethodCall(
+ MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE);
+
+ void Close();
+ void CloseWithReason(uint32_t custom_reason, const std::string& description);
+
+ void set_connection_error_handler(const base::Closure& error_handler) {
+ DCHECK(is_bound());
+ router_->set_connection_error_handler(error_handler);
+ }
+
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ DCHECK(is_bound());
+ router_->set_connection_error_with_reason_handler(error_handler);
+ }
+
+ bool is_bound() const { return !!router_; }
+
+ MessagePipeHandle handle() const {
+ DCHECK(is_bound());
+ return router_->handle();
+ }
+
+ AssociatedGroup* associated_group() { return nullptr; }
+
+ void FlushForTesting();
+
+ void EnableTestingMode();
+
+ protected:
+ void BindInternal(ScopedMessagePipeHandle handle,
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
+ const char* interface_name,
+ std::unique_ptr<MessageReceiver> request_validator,
+ bool has_sync_methods,
+ MessageReceiverWithResponderStatus* stub,
+ uint32_t interface_version);
+
+ void DestroyRouter();
+
+ internal::Router* router_ = nullptr;
+};
+
template <typename Interface, bool use_multiplex_router>
class BindingState;
@@ -39,7 +100,7 @@ class BindingState;
// multiple interfaces running on the underlying message pipe. In that case, we
// can use this specialization to reduce cost.
template <typename Interface>
-class BindingState<Interface, false> {
+class BindingState<Interface, false> : public SimpleBindingState {
public:
explicit BindingState(Interface* impl) : impl_(impl) {
stub_.set_sink(impl_);
@@ -50,42 +111,10 @@ class BindingState<Interface, false> {
void Bind(ScopedMessagePipeHandle handle,
scoped_refptr<base::SingleThreadTaskRunner> runner) {
DCHECK(!router_);
- internal::FilterChain filters;
- filters.Append<MessageHeaderValidator>(Interface::Name_);
- filters.Append<typename Interface::RequestValidator_>();
-
- router_ =
- new internal::Router(std::move(handle), std::move(filters),
- Interface::HasSyncMethods_, std::move(runner));
- router_->set_incoming_receiver(&stub_);
- router_->set_connection_error_handler(
- base::Bind(&BindingState::RunConnectionErrorHandler,
- base::Unretained(this)));
- }
-
- bool HasAssociatedInterfaces() const { return false; }
-
- void PauseIncomingMethodCallProcessing() {
- DCHECK(router_);
- router_->PauseIncomingMethodCallProcessing();
- }
- void ResumeIncomingMethodCallProcessing() {
- DCHECK(router_);
- router_->ResumeIncomingMethodCallProcessing();
- }
-
- bool WaitForIncomingMethodCall(
- MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) {
- DCHECK(router_);
- return router_->WaitForIncomingMessage(deadline);
- }
-
- void Close() {
- if (!router_)
- return;
-
- router_->CloseMessagePipe();
- DestroyRouter();
+ SimpleBindingState::BindInternal(
+ std::move(handle), runner, Interface::Name_,
+ base::MakeUnique<typename Interface::RequestValidator_>(),
+ Interface::HasSyncMethods_, &stub_, Interface::Version_);
}
InterfaceRequest<Interface> Unbind() {
@@ -95,12 +124,45 @@ class BindingState<Interface, false> {
return std::move(request);
}
+ Interface* impl() { return impl_; }
+
+ private:
+ typename Interface::Stub_ stub_;
+ Interface* impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(BindingState);
+};
+
+// Base class used for templated binding primitives which may bind a pipe to
+// multiple interfaces.
+class MOJO_CPP_BINDINGS_EXPORT MultiplexedBindingState {
+ public:
+ MultiplexedBindingState();
+ ~MultiplexedBindingState();
+
+ void AddFilter(std::unique_ptr<MessageReceiver> filter);
+
+ bool HasAssociatedInterfaces() const;
+
+ void PauseIncomingMethodCallProcessing();
+ void ResumeIncomingMethodCallProcessing();
+
+ bool WaitForIncomingMethodCall(
+ MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE);
+
+ void Close();
+ void CloseWithReason(uint32_t custom_reason, const std::string& description);
+
void set_connection_error_handler(const base::Closure& error_handler) {
DCHECK(is_bound());
- connection_error_handler_ = error_handler;
+ endpoint_client_->set_connection_error_handler(error_handler);
}
- Interface* impl() { return impl_; }
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ DCHECK(is_bound());
+ endpoint_client_->set_connection_error_with_reason_handler(error_handler);
+ }
bool is_bound() const { return !!router_; }
@@ -109,38 +171,32 @@ class BindingState<Interface, false> {
return router_->handle();
}
- AssociatedGroup* associated_group() { return nullptr; }
-
- void EnableTestingMode() {
- DCHECK(is_bound());
- router_->EnableTestingMode();
+ AssociatedGroup* associated_group() {
+ return endpoint_client_ ? endpoint_client_->associated_group() : nullptr;
}
- private:
- void DestroyRouter() {
- router_->set_connection_error_handler(base::Closure());
- delete router_;
- router_ = nullptr;
- connection_error_handler_.Reset();
- }
+ void FlushForTesting();
- void RunConnectionErrorHandler() {
- if (!connection_error_handler_.is_null())
- connection_error_handler_.Run();
- }
+ void EnableTestingMode();
- internal::Router* router_ = nullptr;
- typename Interface::Stub_ stub_;
- Interface* impl_;
- base::Closure connection_error_handler_;
+ protected:
+ void BindInternal(ScopedMessagePipeHandle handle,
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
+ const char* interface_name,
+ std::unique_ptr<MessageReceiver> request_validator,
+ bool passes_associated_kinds,
+ bool has_sync_methods,
+ MessageReceiverWithResponderStatus* stub,
+ uint32_t interface_version);
- DISALLOW_COPY_AND_ASSIGN(BindingState);
+ scoped_refptr<internal::MultiplexRouter> router_;
+ std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
};
// Uses a multiplexing router. If |Interface| has methods to pass associated
// interface pointers or requests, this specialization should be used.
template <typename Interface>
-class BindingState<Interface, true> {
+class BindingState<Interface, true> : public MultiplexedBindingState {
public:
explicit BindingState(Interface* impl) : impl_(impl) {
stub_.set_sink(impl_);
@@ -150,49 +206,12 @@ class BindingState<Interface, true> {
void Bind(ScopedMessagePipeHandle handle,
scoped_refptr<base::SingleThreadTaskRunner> runner) {
- DCHECK(!router_);
-
- router_ = new internal::MultiplexRouter(false, std::move(handle), runner);
- router_->SetMasterInterfaceName(Interface::Name_);
+ MultiplexedBindingState::BindInternal(
+ std::move(handle), runner, Interface::Name_,
+ base::MakeUnique<typename Interface::RequestValidator_>(),
+ Interface::PassesAssociatedKinds_, Interface::HasSyncMethods_, &stub_,
+ Interface::Version_);
stub_.serialization_context()->group_controller = router_;
-
- endpoint_client_.reset(new InterfaceEndpointClient(
- router_->CreateLocalEndpointHandle(kMasterInterfaceId),
- &stub_, base::WrapUnique(new typename Interface::RequestValidator_()),
- Interface::HasSyncMethods_, std::move(runner)));
-
- endpoint_client_->set_connection_error_handler(
- base::Bind(&BindingState::RunConnectionErrorHandler,
- base::Unretained(this)));
- }
-
- bool HasAssociatedInterfaces() const {
- return router_ ? router_->HasAssociatedEndpoints() : false;
- }
-
- void PauseIncomingMethodCallProcessing() {
- DCHECK(router_);
- router_->PauseIncomingMethodCallProcessing();
- }
- void ResumeIncomingMethodCallProcessing() {
- DCHECK(router_);
- router_->ResumeIncomingMethodCallProcessing();
- }
-
- bool WaitForIncomingMethodCall(
- MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) {
- DCHECK(router_);
- return router_->WaitForIncomingMessage(deadline);
- }
-
- void Close() {
- if (!router_)
- return;
-
- endpoint_client_.reset();
- router_->CloseMessagePipe();
- router_ = nullptr;
- connection_error_handler_.Reset();
}
InterfaceRequest<Interface> Unbind() {
@@ -200,45 +219,14 @@ class BindingState<Interface, true> {
InterfaceRequest<Interface> request =
MakeRequest<Interface>(router_->PassMessagePipe());
router_ = nullptr;
- connection_error_handler_.Reset();
return request;
}
- void set_connection_error_handler(const base::Closure& error_handler) {
- DCHECK(is_bound());
- connection_error_handler_ = error_handler;
- }
-
Interface* impl() { return impl_; }
- bool is_bound() const { return !!router_; }
-
- MessagePipeHandle handle() const {
- DCHECK(is_bound());
- return router_->handle();
- }
-
- AssociatedGroup* associated_group() {
- return endpoint_client_ ? endpoint_client_->associated_group() : nullptr;
- }
-
- void EnableTestingMode() {
- DCHECK(is_bound());
- router_->EnableTestingMode();
- }
-
private:
- void RunConnectionErrorHandler() {
- if (!connection_error_handler_.is_null())
- connection_error_handler_.Run();
- }
-
- scoped_refptr<internal::MultiplexRouter> router_;
- std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
-
typename Interface::Stub_ stub_;
Interface* impl_;
- base::Closure connection_error_handler_;
DISALLOW_COPY_AND_ASSIGN(BindingState);
};
diff --git a/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h b/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h
index cd28cc7ad0b..494abe3f9e4 100644
--- a/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h
+++ b/chromium/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -7,6 +7,9 @@
#include <stdint.h>
+#include <functional>
+
+#include "base/template_util.h"
#include "mojo/public/cpp/bindings/interface_id.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
#include "mojo/public/cpp/system/core.h"
@@ -14,30 +17,26 @@
namespace mojo {
template <typename T>
-class Array;
+class ArrayDataView;
template <typename T>
-class AssociatedInterfacePtrInfo;
+class AssociatedInterfacePtrInfoDataView;
template <typename T>
-class AssociatedInterfaceRequest;
+class AssociatedInterfaceRequestDataView;
template <typename T>
-class InterfacePtr;
+class InterfacePtrDataView;
template <typename T>
-class InterfaceRequest;
+class InterfaceRequestDataView;
template <typename K, typename V>
-class Map;
-
-class String;
+class MapDataView;
-template <typename T>
-class StructPtr;
+class NativeStructDataView;
-template <typename T>
-class InlinedStructPtr;
+class StringDataView;
namespace internal {
@@ -55,8 +54,46 @@ class Array_Data;
template <typename K, typename V>
class Map_Data;
+class NativeStruct_Data;
+
using String_Data = Array_Data<char>;
+inline size_t Align(size_t size) {
+ return (size + 7) & ~0x7;
+}
+
+inline bool IsAligned(const void* ptr) {
+ return !(reinterpret_cast<uintptr_t>(ptr) & 0x7);
+}
+
+// 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.
+//
+inline 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);
+ DCHECK(p_obj > p_slot);
+
+ *offset = static_cast<uint64_t>(p_obj - p_slot);
+}
+
+// Note: This function doesn't validate the encoded pointer value.
+inline const void* DecodePointer(const uint64_t* offset) {
+ if (!*offset)
+ return nullptr;
+ return reinterpret_cast<const char*>(offset) + *offset;
+}
+
#pragma pack(push, 1)
struct StructHeader {
@@ -72,9 +109,18 @@ struct ArrayHeader {
static_assert(sizeof(ArrayHeader) == 8, "Bad_sizeof(ArrayHeader)");
template <typename T>
-union Pointer {
+struct Pointer {
+ using BaseType = T;
+
+ void Set(T* ptr) { EncodePointer(ptr, &offset); }
+ const T* Get() const { return static_cast<const T*>(DecodePointer(&offset)); }
+ T* Get() {
+ return static_cast<T*>(const_cast<void*>(DecodePointer(&offset)));
+ }
+
+ bool is_null() const { return offset == 0; }
+
uint64_t offset;
- T* ptr;
};
static_assert(sizeof(Pointer<char>) == 8, "Bad_sizeof(Pointer)");
@@ -170,15 +216,15 @@ struct MojomTypeTraits {
};
template <typename T>
-struct MojomTypeTraits<Array<T>, false> {
+struct MojomTypeTraits<ArrayDataView<T>, false> {
using Data = Array_Data<typename MojomTypeTraits<T>::DataAsArrayElement>;
- using DataAsArrayElement = Data*;
+ using DataAsArrayElement = Pointer<Data>;
static const MojomTypeCategory category = MojomTypeCategory::ARRAY;
};
template <typename T>
-struct MojomTypeTraits<AssociatedInterfacePtrInfo<T>, false> {
+struct MojomTypeTraits<AssociatedInterfacePtrInfoDataView<T>, false> {
using Data = AssociatedInterface_Data;
using DataAsArrayElement = Data;
@@ -187,7 +233,7 @@ struct MojomTypeTraits<AssociatedInterfacePtrInfo<T>, false> {
};
template <typename T>
-struct MojomTypeTraits<AssociatedInterfaceRequest<T>, false> {
+struct MojomTypeTraits<AssociatedInterfaceRequestDataView<T>, false> {
using Data = AssociatedInterfaceRequest_Data;
using DataAsArrayElement = Data;
@@ -220,7 +266,7 @@ struct MojomTypeTraits<ScopedHandleBase<T>, false> {
};
template <typename T>
-struct MojomTypeTraits<InterfacePtr<T>, false> {
+struct MojomTypeTraits<InterfacePtrDataView<T>, false> {
using Data = Interface_Data;
using DataAsArrayElement = Data;
@@ -228,7 +274,7 @@ struct MojomTypeTraits<InterfacePtr<T>, false> {
};
template <typename T>
-struct MojomTypeTraits<InterfaceRequest<T>, false> {
+struct MojomTypeTraits<InterfaceRequestDataView<T>, false> {
using Data = Handle_Data;
using DataAsArrayElement = Data;
@@ -237,46 +283,28 @@ struct MojomTypeTraits<InterfaceRequest<T>, false> {
};
template <typename K, typename V>
-struct MojomTypeTraits<Map<K, V>, false> {
+struct MojomTypeTraits<MapDataView<K, V>, false> {
using Data = Map_Data<typename MojomTypeTraits<K>::DataAsArrayElement,
typename MojomTypeTraits<V>::DataAsArrayElement>;
- using DataAsArrayElement = Data*;
+ using DataAsArrayElement = Pointer<Data>;
static const MojomTypeCategory category = MojomTypeCategory::MAP;
};
template <>
-struct MojomTypeTraits<String, false> {
- using Data = String_Data;
- using DataAsArrayElement = Data*;
+struct MojomTypeTraits<NativeStructDataView, false> {
+ using Data = internal::NativeStruct_Data;
+ using DataAsArrayElement = Pointer<Data>;
- static const MojomTypeCategory category = MojomTypeCategory::STRING;
+ static const MojomTypeCategory category = MojomTypeCategory::STRUCT;
};
-template <typename T>
-struct MojomTypeTraits<StructPtr<T>, false> {
- using Data = typename T::Data_;
- using DataAsArrayElement =
- typename std::conditional<IsUnionDataType<Data>::value,
- Data,
- Data*>::type;
-
- static const MojomTypeCategory category = IsUnionDataType<Data>::value
- ? MojomTypeCategory::UNION
- : MojomTypeCategory::STRUCT;
-};
+template <>
+struct MojomTypeTraits<StringDataView, false> {
+ using Data = String_Data;
+ using DataAsArrayElement = Pointer<Data>;
-template <typename T>
-struct MojomTypeTraits<InlinedStructPtr<T>, false> {
- using Data = typename T::Data_;
- using DataAsArrayElement =
- typename std::conditional<IsUnionDataType<Data>::value,
- Data,
- Data*>::type;
-
- static const MojomTypeCategory category = IsUnionDataType<Data>::value
- ? MojomTypeCategory::UNION
- : MojomTypeCategory::STRUCT;
+ static const MojomTypeCategory category = MojomTypeCategory::STRING;
};
template <typename T, MojomTypeCategory categories>
@@ -285,6 +313,16 @@ struct BelongsTo {
static_cast<uint32_t>(MojomTypeTraits<T>::category & categories) != 0;
};
+template <typename T>
+struct EnumHashImpl {
+ static_assert(std::is_enum<T>::value, "Incorrect hash function.");
+
+ size_t operator()(T input) const {
+ using UnderlyingType = typename base::underlying_type<T>::type;
+ return std::hash<UnderlyingType>()(static_cast<UnderlyingType>(input));
+ }
+};
+
} // namespace internal
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/buffer.h b/chromium/mojo/public/cpp/bindings/lib/buffer.h
index c3b570e7767..213a44590f6 100644
--- a/chromium/mojo/public/cpp/bindings/lib/buffer.h
+++ b/chromium/mojo/public/cpp/bindings/lib/buffer.h
@@ -7,15 +7,61 @@
#include <stddef.h>
+#include "base/logging.h"
+#include "base/macros.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.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.
+// Buffer provides an interface to allocate memory blocks which are 8-byte
+// aligned and zero-initialized. It doesn't own the underlying memory. Users
+// must ensure that the memory stays valid while using the allocated blocks from
+// Buffer.
class Buffer {
public:
- virtual ~Buffer() {}
- virtual void* Allocate(size_t num_bytes) = 0;
+ Buffer() {}
+
+ // The memory must have been zero-initialized. |data| must be 8-byte
+ // aligned.
+ void Initialize(void* data, size_t size) {
+ DCHECK(IsAligned(data));
+
+ data_ = data;
+ size_ = size;
+ cursor_ = reinterpret_cast<uintptr_t>(data);
+ data_end_ = cursor_ + size;
+ }
+
+ size_t size() const { return size_; }
+
+ void* data() const { return data_; }
+
+ // Allocates |num_bytes| from the buffer and returns a pointer to the start of
+ // the allocated block.
+ // The resulting address is 8-byte aligned, and the content of the memory is
+ // zero-filled.
+ void* Allocate(size_t num_bytes) {
+ num_bytes = Align(num_bytes);
+ uintptr_t result = cursor_;
+ cursor_ += num_bytes;
+ if (cursor_ > data_end_ || cursor_ < result) {
+ NOTREACHED();
+ cursor_ -= num_bytes;
+ return nullptr;
+ }
+
+ return reinterpret_cast<void*>(result);
+ }
+
+ private:
+ void* data_ = nullptr;
+ size_t size_ = 0;
+
+ uintptr_t cursor_ = 0;
+ uintptr_t data_end_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
};
} // namespace internal
diff --git a/chromium/mojo/public/cpp/bindings/lib/clone_equals_util.h b/chromium/mojo/public/cpp/bindings/lib/clone_equals_util.h
new file mode 100644
index 00000000000..f7bd898c300
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/clone_equals_util.h
@@ -0,0 +1,161 @@
+// Copyright 2016 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_CLONE_EQUALS_UTIL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CLONE_EQUALS_UTIL_H_
+
+#include <type_traits>
+#include <unordered_map>
+#include <vector>
+
+#include "base/optional.h"
+#include "mojo/public/cpp/bindings/lib/template_util.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename T>
+struct HasCloneMethod {
+ template <typename U>
+ static char Test(decltype(&U::Clone));
+ template <typename U>
+ static int Test(...);
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+
+ private:
+ EnsureTypeIsComplete<T> check_t_;
+};
+
+template <typename T, bool has_clone_method = HasCloneMethod<T>::value>
+struct CloneTraits;
+
+template <typename T>
+T Clone(const T& input);
+
+template <typename T>
+struct CloneTraits<T, true> {
+ static T Clone(const T& input) { return input.Clone(); }
+};
+
+template <typename T>
+struct CloneTraits<T, false> {
+ static T Clone(const T& input) { return input; }
+};
+
+template <typename T>
+struct CloneTraits<base::Optional<T>, false> {
+ static base::Optional<T> Clone(const base::Optional<T>& input) {
+ if (!input)
+ return base::nullopt;
+
+ return base::Optional<T>(internal::Clone(*input));
+ }
+};
+
+template <typename T>
+struct CloneTraits<std::vector<T>, false> {
+ static std::vector<T> Clone(const std::vector<T>& input) {
+ std::vector<T> result;
+ result.reserve(input.size());
+ for (const auto& element : input)
+ result.push_back(internal::Clone(element));
+
+ return result;
+ }
+};
+
+template <typename K, typename V>
+struct CloneTraits<std::unordered_map<K, V>, false> {
+ static std::unordered_map<K, V> Clone(const std::unordered_map<K, V>& input) {
+ std::unordered_map<K, V> result;
+ for (const auto& element : input) {
+ result.insert(std::make_pair(internal::Clone(element.first),
+ internal::Clone(element.second)));
+ }
+ return result;
+ }
+};
+
+template <typename T>
+T Clone(const T& input) {
+ return CloneTraits<T>::Clone(input);
+};
+
+template <typename T>
+struct HasEqualsMethod {
+ template <typename U>
+ static char Test(decltype(&U::Equals));
+ template <typename U>
+ static int Test(...);
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+
+ private:
+ EnsureTypeIsComplete<T> check_t_;
+};
+
+template <typename T, bool has_equals_method = HasEqualsMethod<T>::value>
+struct EqualsTraits;
+
+template <typename T>
+bool Equals(const T& a, const T& b);
+
+template <typename T>
+struct EqualsTraits<T, true> {
+ static bool Equals(const T& a, const T& b) { return a.Equals(b); }
+};
+
+template <typename T>
+struct EqualsTraits<T, false> {
+ static bool Equals(const T& a, const T& b) { return a == b; }
+};
+
+template <typename T>
+struct EqualsTraits<base::Optional<T>, false> {
+ static bool Equals(const base::Optional<T>& a, const base::Optional<T>& b) {
+ if (!a && !b)
+ return true;
+ if (!a || !b)
+ return false;
+
+ return internal::Equals(*a, *b);
+ }
+};
+
+template <typename T>
+struct EqualsTraits<std::vector<T>, false> {
+ static bool Equals(const std::vector<T>& a, const std::vector<T>& b) {
+ if (a.size() != b.size())
+ return false;
+ for (size_t i = 0; i < a.size(); ++i) {
+ if (!internal::Equals(a[i], b[i]))
+ return false;
+ }
+ return true;
+ }
+};
+
+template <typename K, typename V>
+struct EqualsTraits<std::unordered_map<K, V>, false> {
+ static bool Equals(const std::unordered_map<K, V>& a,
+ const std::unordered_map<K, V>& b) {
+ if (a.size() != b.size())
+ return false;
+ for (const auto& element : a) {
+ auto iter = b.find(element.first);
+ if (iter == b.end() || !internal::Equals(element.second, iter->second))
+ return false;
+ }
+ return true;
+ }
+};
+
+template <typename T>
+bool Equals(const T& a, const T& b) {
+ return EqualsTraits<T>::Equals(a, b);
+}
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CLONE_EQUALS_UTIL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.cc b/chromium/mojo/public/cpp/bindings/lib/connector.cc
index 1bb38f0fd9c..64524111eb2 100644
--- a/chromium/mojo/public/cpp/bindings/lib/connector.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/connector.cc
@@ -12,51 +12,17 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
+#include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
namespace mojo {
-namespace {
-
-// Similar to base::AutoLock, except that it does nothing if |lock| passed into
-// the constructor is null.
-class MayAutoLock {
- public:
- explicit MayAutoLock(base::Lock* lock) : lock_(lock) {
- if (lock_)
- lock_->Acquire();
- }
-
- ~MayAutoLock() {
- if (lock_) {
- lock_->AssertAcquired();
- lock_->Release();
- }
- }
-
- private:
- base::Lock* lock_;
- DISALLOW_COPY_AND_ASSIGN(MayAutoLock);
-};
-
-} // namespace
-
-// ----------------------------------------------------------------------------
-
Connector::Connector(ScopedMessagePipeHandle message_pipe,
ConnectorConfig config,
scoped_refptr<base::SingleThreadTaskRunner> runner)
: message_pipe_(std::move(message_pipe)),
- incoming_receiver_(nullptr),
task_runner_(std::move(runner)),
- handle_watcher_(task_runner_),
- error_(false),
- drop_writes_(false),
- enforce_errors_from_incoming_receiver_(true),
- paused_(false),
lock_(config == MULTI_THREADED_SEND ? new base::Lock : nullptr),
- allow_woken_up_by_others_(false),
- sync_handle_watcher_callback_count_(0),
weak_factory_(this) {
weak_self_ = weak_factory_.GetWeakPtr();
// Even though we don't have an incoming receiver, we still want to monitor
@@ -65,25 +31,34 @@ Connector::Connector(ScopedMessagePipeHandle message_pipe,
}
Connector::~Connector() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ {
+ // Allow for quick destruction on any thread if the pipe is already closed.
+ base::AutoLock lock(connected_lock_);
+ if (!connected_)
+ return;
+ }
+ DCHECK(thread_checker_.CalledOnValidThread());
CancelWait();
}
void Connector::CloseMessagePipe() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- CancelWait();
- MayAutoLock locker(lock_.get());
- message_pipe_.reset();
+ // Throw away the returned message pipe.
+ PassMessagePipe();
}
ScopedMessagePipeHandle Connector::PassMessagePipe() {
DCHECK(thread_checker_.CalledOnValidThread());
CancelWait();
- MayAutoLock locker(lock_.get());
- return std::move(message_pipe_);
+ internal::MayAutoLock locker(lock_.get());
+ ScopedMessagePipeHandle message_pipe = std::move(message_pipe_);
+ weak_factory_.InvalidateWeakPtrs();
+ sync_handle_watcher_callback_count_ = 0;
+
+ base::AutoLock lock(connected_lock_);
+ connected_ = false;
+ return message_pipe;
}
void Connector::RaiseError() {
@@ -143,7 +118,7 @@ bool Connector::Accept(Message* message) {
if (error_)
return false;
- MayAutoLock locker(lock_.get());
+ internal::MayAutoLock locker(lock_.get());
if (!message_pipe_.is_valid() || drop_writes_)
return true;
@@ -214,8 +189,10 @@ void Connector::OnSyncHandleWatcherHandleReady(MojoResult result) {
sync_handle_watcher_callback_count_++;
OnHandleReadyInternal(result);
// At this point, this object might have been deleted.
- if (weak_self)
+ if (weak_self) {
+ DCHECK_LT(0u, sync_handle_watcher_callback_count_);
sync_handle_watcher_callback_count_--;
+ }
}
void Connector::OnHandleReadyInternal(MojoResult result) {
@@ -231,12 +208,12 @@ void Connector::OnHandleReadyInternal(MojoResult result) {
void Connector::WaitToReadMore() {
CHECK(!paused_);
- DCHECK(!handle_watcher_.IsWatching());
+ DCHECK(!handle_watcher_);
- MojoResult rv = handle_watcher_.Start(
+ handle_watcher_.reset(new Watcher(task_runner_));
+ MojoResult rv = handle_watcher_->Start(
message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE,
- base::Bind(&Connector::OnWatcherHandleReady,
- base::Unretained(this)));
+ base::Bind(&Connector::OnWatcherHandleReady, base::Unretained(this)));
if (rv != MOJO_RESULT_OK) {
// If the watch failed because the handle is invalid or its conditions can
@@ -257,8 +234,8 @@ bool Connector::ReadSingleMessage(MojoResult* read_result) {
bool receiver_result = false;
- // Detect if |this| was destroyed during message dispatch. Allow for the
- // possibility of re-entering ReadMore() through message dispatch.
+ // Detect if |this| was destroyed or the message pipe was closed/transferred
+ // during message dispatch.
base::WeakPtr<Connector> weak_self = weak_self_;
Message message;
@@ -292,9 +269,11 @@ void Connector::ReadAllAvailableMessages() {
while (!error_) {
MojoResult rv;
- // Return immediately if |this| was destroyed. Do not touch any members!
- if (!ReadSingleMessage(&rv))
+ if (!ReadSingleMessage(&rv)) {
+ // Return immediately without touching any members. |this| may have been
+ // destroyed.
return;
+ }
if (paused_)
return;
@@ -305,7 +284,7 @@ void Connector::ReadAllAvailableMessages() {
}
void Connector::CancelWait() {
- handle_watcher_.Cancel();
+ handle_watcher_.reset();
sync_watcher_.reset();
}
@@ -325,7 +304,7 @@ void Connector::HandleError(bool force_pipe_reset, bool force_async_handler) {
if (force_pipe_reset) {
CancelWait();
- MayAutoLock locker(lock_.get());
+ internal::MayAutoLock locker(lock_.get());
message_pipe_.reset();
MessagePipe dummy_pipe;
message_pipe_ = std::move(dummy_pipe.handle0);
diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc b/chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc
index 1bcd87daf9e..bfd785df087 100644
--- a/chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/control_message_handler.cc
@@ -11,15 +11,53 @@
#include "base/logging.h"
#include "mojo/public/cpp/bindings/lib/message_builder.h"
#include "mojo/public/cpp/bindings/lib/serialization.h"
+#include "mojo/public/cpp/bindings/lib/validation_util.h"
#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
namespace mojo {
namespace internal {
+namespace {
+
+bool ValidateControlRequestWithResponse(Message* message) {
+ ValidationContext validation_context(
+ message->data(), message->data_num_bytes(), message->handles()->size(),
+ message, "ControlRequestValidator");
+ if (!ValidateMessageIsRequestExpectingResponse(message, &validation_context))
+ return false;
+
+ switch (message->header()->name) {
+ case interface_control::kRunMessageId:
+ return ValidateMessagePayload<
+ interface_control::internal::RunMessageParams_Data>(
+ message, &validation_context);
+ }
+ return false;
+}
+
+bool ValidateControlRequestWithoutResponse(Message* message) {
+ ValidationContext validation_context(
+ message->data(), message->data_num_bytes(), message->handles()->size(),
+ message, "ControlRequestValidator");
+ if (!ValidateMessageIsRequestWithoutResponse(message, &validation_context))
+ return false;
+
+ switch (message->header()->name) {
+ case interface_control::kRunOrClosePipeMessageId:
+ return ValidateMessageIsRequestWithoutResponse(message,
+ &validation_context) &&
+ ValidateMessagePayload<
+ interface_control::internal::RunOrClosePipeMessageParams_Data>(
+ message, &validation_context);
+ }
+ return false;
+}
+
+} // namespace
// static
bool ControlMessageHandler::IsControlMessage(const Message* message) {
- return message->header()->name == kRunMessageId ||
- message->header()->name == kRunOrClosePipeMessageId;
+ return message->header()->name == interface_control::kRunMessageId ||
+ message->header()->name == interface_control::kRunOrClosePipeMessageId;
}
ControlMessageHandler::ControlMessageHandler(uint32_t interface_version)
@@ -30,7 +68,10 @@ ControlMessageHandler::~ControlMessageHandler() {
}
bool ControlMessageHandler::Accept(Message* message) {
- if (message->header()->name == kRunOrClosePipeMessageId)
+ if (!ValidateControlRequestWithoutResponse(message))
+ return false;
+
+ if (message->header()->name == interface_control::kRunOrClosePipeMessageId)
return RunOrClosePipe(message);
NOTREACHED();
@@ -40,7 +81,10 @@ bool ControlMessageHandler::Accept(Message* message) {
bool ControlMessageHandler::AcceptWithResponder(
Message* message,
MessageReceiverWithStatus* responder) {
- if (message->header()->name == kRunMessageId)
+ if (!ValidateControlRequestWithResponse(message))
+ return false;
+
+ if (message->header()->name == interface_control::kRunMessageId)
return Run(message, responder);
NOTREACHED();
@@ -49,21 +93,36 @@ bool ControlMessageHandler::AcceptWithResponder(
bool ControlMessageHandler::Run(Message* message,
MessageReceiverWithStatus* responder) {
- RunResponseMessageParamsPtr response_params_ptr(
- RunResponseMessageParams::New());
- response_params_ptr->reserved0 = 16u;
- response_params_ptr->reserved1 = 0u;
- response_params_ptr->query_version_result = QueryVersionResult::New();
- response_params_ptr->query_version_result->version = interface_version_;
-
- size_t size = PrepareToSerialize<RunResponseMessageParamsPtr>(
- response_params_ptr, &context_);
- ResponseMessageBuilder builder(kRunMessageId, size, message->request_id());
-
- RunResponseMessageParams_Data* response_params = nullptr;
- Serialize<RunResponseMessageParamsPtr>(response_params_ptr, builder.buffer(),
- &response_params, &context_);
- response_params->EncodePointers();
+ interface_control::internal::RunMessageParams_Data* params =
+ reinterpret_cast<interface_control::internal::RunMessageParams_Data*>(
+ message->mutable_payload());
+ interface_control::RunMessageParamsPtr params_ptr;
+ Deserialize<interface_control::RunMessageParamsDataView>(params, &params_ptr,
+ &context_);
+ auto& input = *params_ptr->input;
+ interface_control::RunOutputPtr output = interface_control::RunOutput::New();
+ if (input.is_query_version()) {
+ output->set_query_version_result(
+ interface_control::QueryVersionResult::New());
+ output->get_query_version_result()->version = interface_version_;
+ } else if (input.is_flush_for_testing()) {
+ output.reset();
+ } else {
+ output.reset();
+ }
+
+ auto response_params_ptr = interface_control::RunResponseMessageParams::New();
+ response_params_ptr->output = std::move(output);
+ size_t size =
+ PrepareToSerialize<interface_control::RunResponseMessageParamsDataView>(
+ response_params_ptr, &context_);
+ ResponseMessageBuilder builder(interface_control::kRunMessageId, size,
+ message->request_id());
+
+ interface_control::internal::RunResponseMessageParams_Data* response_params =
+ nullptr;
+ Serialize<interface_control::RunResponseMessageParamsDataView>(
+ response_params_ptr, builder.buffer(), &response_params, &context_);
bool ok = responder->Accept(builder.message());
ALLOW_UNUSED_LOCAL(ok);
delete responder;
@@ -72,15 +131,25 @@ bool ControlMessageHandler::Run(Message* message,
}
bool ControlMessageHandler::RunOrClosePipe(Message* message) {
- RunOrClosePipeMessageParams_Data* params =
- reinterpret_cast<RunOrClosePipeMessageParams_Data*>(
+ interface_control::internal::RunOrClosePipeMessageParams_Data* params =
+ reinterpret_cast<
+ interface_control::internal::RunOrClosePipeMessageParams_Data*>(
message->mutable_payload());
- params->DecodePointers();
+ interface_control::RunOrClosePipeMessageParamsPtr params_ptr;
+ Deserialize<interface_control::RunOrClosePipeMessageParamsDataView>(
+ params, &params_ptr, &context_);
+ auto& input = *params_ptr->input;
+ if (input.is_require_version())
+ return interface_version_ >= input.get_require_version()->version;
+ else if (input.is_send_disconnect_reason()) {
+ disconnect_custom_reason_ =
+ input.get_send_disconnect_reason()->custom_reason;
+ disconnect_description_ =
+ std::move(input.get_send_disconnect_reason()->description);
+ return true;
+ }
- RunOrClosePipeMessageParamsPtr params_ptr;
- Deserialize<RunOrClosePipeMessageParamsPtr>(params, &params_ptr, &context_);
-
- return interface_version_ >= params_ptr->require_version->version;
+ return false;
}
} // namespace internal
diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_handler.h b/chromium/mojo/public/cpp/bindings/lib/control_message_handler.h
index 13b5aa6214e..d26bbce1b3c 100644
--- a/chromium/mojo/public/cpp/bindings/lib/control_message_handler.h
+++ b/chromium/mojo/public/cpp/bindings/lib/control_message_handler.h
@@ -7,7 +7,11 @@
#include <stdint.h>
+#include <string>
+
+#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/serialization_context.h"
#include "mojo/public/cpp/bindings/message.h"
@@ -15,7 +19,8 @@ namespace mojo {
namespace internal {
// Handlers for request messages defined in interface_control_messages.mojom.
-class ControlMessageHandler : public MessageReceiverWithResponderStatus {
+class MOJO_CPP_BINDINGS_EXPORT ControlMessageHandler
+ : NON_EXPORTED_BASE(public MessageReceiverWithResponderStatus) {
public:
static bool IsControlMessage(const Message* message);
@@ -28,6 +33,14 @@ class ControlMessageHandler : public MessageReceiverWithResponderStatus {
bool AcceptWithResponder(Message* message,
MessageReceiverWithStatus* responder) override;
+ uint32_t disconnect_custom_reason() const {
+ return disconnect_custom_reason_;
+ }
+
+ const std::string& disconnect_description() const {
+ return disconnect_description_;
+ }
+
private:
bool Run(Message* message, MessageReceiverWithStatus* responder);
bool RunOrClosePipe(Message* message);
@@ -35,6 +48,9 @@ class ControlMessageHandler : public MessageReceiverWithResponderStatus {
uint32_t interface_version_;
SerializationContext context_;
+ uint32_t disconnect_custom_reason_ = 0;
+ std::string disconnect_description_;
+
DISALLOW_COPY_AND_ASSIGN(ControlMessageHandler);
};
diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc
index a22601c15d5..1561dfb9a74 100644
--- a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc
@@ -9,10 +9,12 @@
#include <utility>
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "mojo/public/cpp/bindings/lib/message_builder.h"
#include "mojo/public/cpp/bindings/lib/serialization.h"
-#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/bindings/lib/validation_util.h"
#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
namespace mojo {
@@ -20,11 +22,28 @@ namespace internal {
namespace {
-using RunCallback = base::Callback<void(QueryVersionResultPtr)>;
+bool ValidateControlResponse(Message* message) {
+ ValidationContext validation_context(
+ message->data(), message->data_num_bytes(), message->handles()->size(),
+ message, "ControlResponseValidator");
+ if (!ValidateMessageIsResponse(message, &validation_context))
+ return false;
+
+ switch (message->header()->name) {
+ case interface_control::kRunMessageId:
+ return ValidateMessagePayload<
+ interface_control::internal::RunResponseMessageParams_Data>(
+ message, &validation_context);
+ }
+ return false;
+}
+
+using RunCallback =
+ base::Callback<void(interface_control::RunResponseMessageParamsPtr)>;
class RunResponseForwardToCallback : public MessageReceiver {
public:
- RunResponseForwardToCallback(const RunCallback& callback)
+ explicit RunResponseForwardToCallback(const RunCallback& callback)
: callback_(callback) {}
bool Accept(Message* message) override;
@@ -34,63 +53,81 @@ class RunResponseForwardToCallback : public MessageReceiver {
};
bool RunResponseForwardToCallback::Accept(Message* message) {
- RunResponseMessageParams_Data* params =
- reinterpret_cast<RunResponseMessageParams_Data*>(
- message->mutable_payload());
- params->DecodePointers();
+ if (!ValidateControlResponse(message))
+ return false;
- RunResponseMessageParamsPtr params_ptr;
+ interface_control::internal::RunResponseMessageParams_Data* params =
+ reinterpret_cast<
+ interface_control::internal::RunResponseMessageParams_Data*>(
+ message->mutable_payload());
+ interface_control::RunResponseMessageParamsPtr params_ptr;
SerializationContext context;
- Deserialize<RunResponseMessageParamsPtr>(params, &params_ptr, &context);
+ Deserialize<interface_control::RunResponseMessageParamsDataView>(
+ params, &params_ptr, &context);
- callback_.Run(std::move(params_ptr->query_version_result));
+ callback_.Run(std::move(params_ptr));
return true;
}
void SendRunMessage(MessageReceiverWithResponder* receiver,
- QueryVersionPtr query_version,
- const RunCallback& callback,
- SerializationContext* context) {
- RunMessageParamsPtr params_ptr(RunMessageParams::New());
- params_ptr->reserved0 = 16u;
- params_ptr->reserved1 = 0u;
- params_ptr->query_version = std::move(query_version);
-
- size_t size = PrepareToSerialize<RunMessageParamsPtr>(params_ptr, context);
- RequestMessageBuilder builder(kRunMessageId, size);
-
- RunMessageParams_Data* params = nullptr;
- Serialize<RunMessageParamsPtr>(params_ptr, builder.buffer(), &params,
- context);
- params->EncodePointers();
+ interface_control::RunInputPtr input_ptr,
+ const RunCallback& callback) {
+ SerializationContext context;
+
+ auto params_ptr = interface_control::RunMessageParams::New();
+ params_ptr->input = std::move(input_ptr);
+ size_t size = PrepareToSerialize<interface_control::RunMessageParamsDataView>(
+ params_ptr, &context);
+ RequestMessageBuilder builder(interface_control::kRunMessageId, size);
+
+ interface_control::internal::RunMessageParams_Data* params = nullptr;
+ Serialize<interface_control::RunMessageParamsDataView>(
+ params_ptr, builder.buffer(), &params, &context);
MessageReceiver* responder = new RunResponseForwardToCallback(callback);
if (!receiver->AcceptWithResponder(builder.message(), responder))
delete responder;
}
-void SendRunOrClosePipeMessage(MessageReceiverWithResponder* receiver,
- RequireVersionPtr require_version,
- SerializationContext* context) {
- RunOrClosePipeMessageParamsPtr params_ptr(RunOrClosePipeMessageParams::New());
- params_ptr->reserved0 = 16u;
- params_ptr->reserved1 = 0u;
- params_ptr->require_version = std::move(require_version);
-
- size_t size =
- PrepareToSerialize<RunOrClosePipeMessageParamsPtr>(params_ptr, context);
- MessageBuilder builder(kRunOrClosePipeMessageId, size);
-
- RunOrClosePipeMessageParams_Data* params = nullptr;
- Serialize<RunOrClosePipeMessageParamsPtr>(params_ptr, builder.buffer(),
- &params, context);
- params->EncodePointers();
- bool ok = receiver->Accept(builder.message());
+Message ConstructRunOrClosePipeMessage(
+ interface_control::RunOrClosePipeInputPtr input_ptr) {
+ SerializationContext context;
+
+ auto params_ptr = interface_control::RunOrClosePipeMessageParams::New();
+ params_ptr->input = std::move(input_ptr);
+
+ size_t size = PrepareToSerialize<
+ interface_control::RunOrClosePipeMessageParamsDataView>(params_ptr,
+ &context);
+ MessageBuilder builder(interface_control::kRunOrClosePipeMessageId, size);
+
+ interface_control::internal::RunOrClosePipeMessageParams_Data* params =
+ nullptr;
+ Serialize<interface_control::RunOrClosePipeMessageParamsDataView>(
+ params_ptr, builder.buffer(), &params, &context);
+ return std::move(*builder.message());
+}
+
+void SendRunOrClosePipeMessage(
+ MessageReceiverWithResponder* receiver,
+ interface_control::RunOrClosePipeInputPtr input_ptr) {
+ Message message(ConstructRunOrClosePipeMessage(std::move(input_ptr)));
+
+ bool ok = receiver->Accept(&message);
ALLOW_UNUSED_LOCAL(ok);
}
-void RunVersionCallback(const base::Callback<void(uint32_t)>& callback,
- QueryVersionResultPtr query_version_result) {
- callback.Run(query_version_result->version);
+void RunVersionCallback(
+ const base::Callback<void(uint32_t)>& callback,
+ interface_control::RunResponseMessageParamsPtr run_response) {
+ uint32_t version = 0u;
+ if (run_response->output && run_response->output->is_query_version_result())
+ version = run_response->output->get_query_version_result()->version;
+ callback.Run(version);
+}
+
+void RunClosure(const base::Closure& callback,
+ interface_control::RunResponseMessageParamsPtr run_response) {
+ callback.Run();
}
} // namespace
@@ -99,16 +136,69 @@ ControlMessageProxy::ControlMessageProxy(MessageReceiverWithResponder* receiver)
: receiver_(receiver) {
}
+ControlMessageProxy::~ControlMessageProxy() = default;
+
void ControlMessageProxy::QueryVersion(
const base::Callback<void(uint32_t)>& callback) {
- SendRunMessage(receiver_, QueryVersion::New(),
- base::Bind(&RunVersionCallback, callback), &context_);
+ auto input_ptr = interface_control::RunInput::New();
+ input_ptr->set_query_version(interface_control::QueryVersion::New());
+ SendRunMessage(receiver_, std::move(input_ptr),
+ base::Bind(&RunVersionCallback, callback));
}
void ControlMessageProxy::RequireVersion(uint32_t version) {
- RequireVersionPtr require_version(RequireVersion::New());
+ auto require_version = interface_control::RequireVersion::New();
require_version->version = version;
- SendRunOrClosePipeMessage(receiver_, std::move(require_version), &context_);
+ auto input_ptr = interface_control::RunOrClosePipeInput::New();
+ input_ptr->set_require_version(std::move(require_version));
+ SendRunOrClosePipeMessage(receiver_, std::move(input_ptr));
+}
+
+void ControlMessageProxy::FlushForTesting() {
+ if (encountered_error_)
+ return;
+
+ auto input_ptr = interface_control::RunInput::New();
+ input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New());
+ base::RunLoop run_loop;
+ run_loop_quit_closure_ = run_loop.QuitClosure();
+ SendRunMessage(
+ receiver_, std::move(input_ptr),
+ base::Bind(&RunClosure,
+ base::Bind(&ControlMessageProxy::RunFlushForTestingClosure,
+ base::Unretained(this))));
+ run_loop.Run();
+}
+
+void ControlMessageProxy::SendDisconnectReason(uint32_t custom_reason,
+ const std::string& description) {
+ Message message =
+ ConstructDisconnectReasonMessage(custom_reason, description);
+ bool ok = receiver_->Accept(&message);
+ ALLOW_UNUSED_LOCAL(ok);
+}
+
+void ControlMessageProxy::RunFlushForTestingClosure() {
+ DCHECK(!run_loop_quit_closure_.is_null());
+ base::ResetAndReturn(&run_loop_quit_closure_).Run();
+}
+
+void ControlMessageProxy::OnConnectionError() {
+ encountered_error_ = true;
+ if (!run_loop_quit_closure_.is_null())
+ RunFlushForTestingClosure();
+}
+
+// static
+Message ControlMessageProxy::ConstructDisconnectReasonMessage(
+ uint32_t custom_reason,
+ const std::string& description) {
+ auto send_disconnect_reason = interface_control::SendDisconnectReason::New();
+ send_disconnect_reason->custom_reason = custom_reason;
+ send_disconnect_reason->description = description;
+ auto input_ptr = interface_control::RunOrClosePipeInput::New();
+ input_ptr->set_send_disconnect_reason(std::move(send_disconnect_reason));
+ return ConstructRunOrClosePipeMessage(std::move(input_ptr));
}
} // namespace internal
diff --git a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h
index 5ec6ddca351..d2f154e77b5 100644
--- a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h
+++ b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h
@@ -7,29 +7,46 @@
#include <stdint.h>
-#include "base/callback_forward.h"
+#include <string>
+
+#include "base/callback.h"
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+#include "mojo/public/cpp/bindings/message.h"
namespace mojo {
-class MessageReceiverWithResponder;
-
namespace internal {
// Proxy for request messages defined in interface_control_messages.mojom.
-class ControlMessageProxy {
+class MOJO_CPP_BINDINGS_EXPORT ControlMessageProxy {
public:
// Doesn't take ownership of |receiver|. It must outlive this object.
explicit ControlMessageProxy(MessageReceiverWithResponder* receiver);
+ ~ControlMessageProxy();
void QueryVersion(const base::Callback<void(uint32_t)>& callback);
void RequireVersion(uint32_t version);
- protected:
+ void FlushForTesting();
+ void SendDisconnectReason(uint32_t custom_reason,
+ const std::string& description);
+
+ void OnConnectionError();
+
+ static Message ConstructDisconnectReasonMessage(
+ uint32_t custom_reason,
+ const std::string& description);
+
+ private:
+ void RunFlushForTestingClosure();
+
// Not owned.
MessageReceiverWithResponder* receiver_;
- SerializationContext context_;
+ bool encountered_error_ = false;
+
+ base::Closure run_loop_quit_closure_;
DISALLOW_COPY_AND_ASSIGN(ControlMessageProxy);
};
diff --git a/chromium/mojo/public/cpp/bindings/lib/filter_chain.cc b/chromium/mojo/public/cpp/bindings/lib/filter_chain.cc
index 899bac1624a..5d919fe1725 100644
--- a/chromium/mojo/public/cpp/bindings/lib/filter_chain.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/filter_chain.cc
@@ -2,14 +2,13 @@
// 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 "mojo/public/cpp/bindings/filter_chain.h"
#include <algorithm>
#include "base/logging.h"
namespace mojo {
-namespace internal {
FilterChain::FilterChain(MessageReceiver* sink) : sink_(sink) {
}
@@ -26,24 +25,23 @@ FilterChain& FilterChain::operator=(FilterChain&& other) {
}
FilterChain::~FilterChain() {
- for (std::vector<MessageFilter*>::iterator iter = filters_.begin();
- iter != filters_.end();
- ++iter) {
- delete *iter;
- }
}
void FilterChain::SetSink(MessageReceiver* sink) {
DCHECK(!sink_);
sink_ = sink;
- if (!filters_.empty())
- filters_.back()->set_sink(sink);
}
-MessageReceiver* FilterChain::GetHead() {
+bool FilterChain::Accept(Message* message) {
DCHECK(sink_);
- return filters_.empty() ? sink_ : filters_.front();
+ for (auto& filter : filters_)
+ if (!filter->Accept(message))
+ return false;
+ return sink_->Accept(message);
+}
+
+void FilterChain::Append(std::unique_ptr<MessageReceiver> filter) {
+ filters_.emplace_back(std::move(filter));
}
-} // namespace internal
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc
index 50b8a21c56b..725a193cd74 100644
--- a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc
@@ -4,56 +4,25 @@
#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
-#include <stddef.h>
#include <stdlib.h>
-#include <algorithm>
-
-#include "base/logging.h"
-#include "mojo/public/cpp/bindings/lib/serialization_util.h"
-
namespace mojo {
namespace internal {
-FixedBuffer::FixedBuffer() : ptr_(nullptr), cursor_(0), size_(0) {}
-
-void FixedBuffer::Initialize(void* memory, size_t size) {
- DCHECK(size == internal::Align(size));
-
- ptr_ = static_cast<char*>(memory);
- cursor_ = 0;
- size_ = size;
-}
-
-void* FixedBuffer::Allocate(size_t delta) {
- delta = internal::Align(delta);
-
- if (delta == 0 || delta > size_ - cursor_) {
- NOTREACHED();
- return nullptr;
- }
-
- char* result = ptr_ + cursor_;
- cursor_ += delta;
-
- return result;
-}
-
FixedBufferForTesting::FixedBufferForTesting(size_t size) {
- size_ = internal::Align(size);
+ size = internal::Align(size);
// Use calloc here to ensure all message memory is zero'd out.
- ptr_ = static_cast<char*>(calloc(size_, 1));
+ void* ptr = calloc(size, 1);
+ Initialize(ptr, size);
}
FixedBufferForTesting::~FixedBufferForTesting() {
- free(ptr_);
+ free(data());
}
void* FixedBufferForTesting::Leak() {
- char* ptr = ptr_;
- ptr_ = nullptr;
- cursor_ = 0;
- size_ = 0;
+ void* ptr = data();
+ Initialize(nullptr, 0);
return ptr;
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h
index 9a5704b4bfa..070b0c8cef4 100644
--- a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h
+++ b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.h
@@ -7,62 +7,21 @@
#include <stddef.h>
+#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/buffer.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:
- FixedBuffer();
-
- // |size| should be aligned using internal::Align.
- void Initialize(void* memory, size_t size);
-
- size_t size() const { return size_; }
-
- // 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.
- void* Allocate(size_t num_bytes) override;
-
- protected:
- char* ptr_;
- size_t cursor_;
- size_t size_;
-
- DISALLOW_COPY_AND_ASSIGN(FixedBuffer);
-};
-
-class FixedBufferForTesting : public FixedBuffer {
+// FixedBufferForTesting owns its buffer. The Leak method may be used to steal
+// the underlying memory.
+class MOJO_CPP_BINDINGS_EXPORT FixedBufferForTesting
+ : NON_EXPORTED_BASE(public Buffer) {
public:
explicit FixedBufferForTesting(size_t size);
- ~FixedBufferForTesting() override;
+ ~FixedBufferForTesting();
// Returns the internal memory owned by the Buffer to the caller. The Buffer
// relinquishes its pointer, effectively resetting the state of the Buffer
diff --git a/chromium/mojo/public/cpp/bindings/lib/handle_interface_serialization.h b/chromium/mojo/public/cpp/bindings/lib/handle_interface_serialization.h
index 344c2cae4e2..ecfb5bb5fed 100644
--- a/chromium/mojo/public/cpp/bindings/lib/handle_interface_serialization.h
+++ b/chromium/mojo/public/cpp/bindings/lib/handle_interface_serialization.h
@@ -5,9 +5,12 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_HANDLE_INTERFACE_SERIALIZATION_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_HANDLE_INTERFACE_SERIALIZATION_H_
+#include <type_traits>
+
#include "mojo/public/cpp/bindings/associated_group_controller.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
+#include "mojo/public/cpp/bindings/interface_data_view.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
@@ -18,9 +21,11 @@
namespace mojo {
namespace internal {
-template <typename T>
-struct Serializer<AssociatedInterfacePtrInfo<T>,
+template <typename Base, typename T>
+struct Serializer<AssociatedInterfacePtrInfoDataView<Base>,
AssociatedInterfacePtrInfo<T>> {
+ static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch.");
+
static void Serialize(AssociatedInterfacePtrInfo<T>& input,
AssociatedInterface_Data* output,
SerializationContext* context) {
@@ -41,9 +46,11 @@ struct Serializer<AssociatedInterfacePtrInfo<T>,
}
};
-template <typename T>
-struct Serializer<AssociatedInterfaceRequest<T>,
+template <typename Base, typename T>
+struct Serializer<AssociatedInterfaceRequestDataView<Base>,
AssociatedInterfaceRequest<T>> {
+ static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch.");
+
static void Serialize(AssociatedInterfaceRequest<T>& input,
AssociatedInterfaceRequest_Data* output,
SerializationContext* context) {
@@ -62,8 +69,10 @@ struct Serializer<AssociatedInterfaceRequest<T>,
}
};
-template <typename T>
-struct Serializer<InterfacePtr<T>, InterfacePtr<T>> {
+template <typename Base, typename T>
+struct Serializer<InterfacePtrDataView<Base>, InterfacePtr<T>> {
+ static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch.");
+
static void Serialize(InterfacePtr<T>& input,
Interface_Data* output,
SerializationContext* context) {
@@ -82,8 +91,10 @@ struct Serializer<InterfacePtr<T>, InterfacePtr<T>> {
}
};
-template <typename T>
-struct Serializer<InterfaceRequest<T>, InterfaceRequest<T>> {
+template <typename Base, typename T>
+struct Serializer<InterfaceRequestDataView<Base>, InterfaceRequest<T>> {
+ static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch.");
+
static void Serialize(InterfaceRequest<T>& input,
Handle_Data* output,
SerializationContext* context) {
diff --git a/chromium/mojo/public/cpp/bindings/lib/hash_util.h b/chromium/mojo/public/cpp/bindings/lib/hash_util.h
new file mode 100644
index 00000000000..c37599c4ce2
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/hash_util.h
@@ -0,0 +1,73 @@
+// Copyright 2016 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_HASH_UTIL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_
+
+#include <cstring>
+#include <functional>
+#include <type_traits>
+#include <vector>
+
+#include "mojo/public/cpp/bindings/lib/template_util.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename T>
+size_t HashCombine(size_t seed, const T& value) {
+ // Based on proposal in:
+ // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
+ return seed ^ (std::hash<T>()(value) + (seed << 6) + (seed >> 2));
+}
+
+template <typename T>
+struct HasHashMethod {
+ template <typename U>
+ static char Test(decltype(&U::Hash));
+ template <typename U>
+ static int Test(...);
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+
+ private:
+ EnsureTypeIsComplete<T> check_t_;
+};
+
+template <typename T, bool has_hash_method = HasHashMethod<T>::value>
+struct HashTraits;
+
+template <typename T>
+size_t Hash(size_t seed, const T& value);
+
+template <typename T>
+struct HashTraits<T, true> {
+ static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); }
+};
+
+template <typename T>
+struct HashTraits<T, false> {
+ static size_t Hash(size_t seed, const T& value) {
+ return HashCombine(seed, value);
+ }
+};
+
+template <typename T>
+struct HashTraits<std::vector<T>, false> {
+ static size_t Hash(size_t seed, const std::vector<T>& value) {
+ for (const auto& element : value) {
+ seed = HashCombine(seed, element);
+ }
+ return seed;
+ }
+};
+
+template <typename T>
+size_t Hash(size_t seed, const T& value) {
+ return HashTraits<T>::Hash(seed, value);
+}
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
index e1f388aa21a..df16ecfaeea 100644
--- a/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -17,6 +17,7 @@
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/associated_group_controller.h"
#include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
+#include "mojo/public/cpp/bindings/lib/validation_util.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
namespace mojo {
@@ -132,34 +133,43 @@ bool InterfaceEndpointClient::HandleIncomingMessageThunk::Accept(
InterfaceEndpointClient::InterfaceEndpointClient(
ScopedInterfaceEndpointHandle handle,
MessageReceiverWithResponderStatus* receiver,
- std::unique_ptr<MessageFilter> payload_validator,
+ std::unique_ptr<MessageReceiver> payload_validator,
bool expect_sync_requests,
- scoped_refptr<base::SingleThreadTaskRunner> runner)
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
+ uint32_t interface_version)
: handle_(std::move(handle)),
incoming_receiver_(receiver),
- payload_validator_(std::move(payload_validator)),
thunk_(this),
+ filters_(&thunk_),
next_request_id_(1),
encountered_error_(false),
task_runner_(std::move(runner)),
+ control_message_proxy_(this),
+ control_message_handler_(interface_version),
weak_ptr_factory_(this) {
DCHECK(handle_.is_valid());
DCHECK(handle_.is_local());
// TODO(yzshen): the way to use validator (or message filter in general)
// directly is a little awkward.
- payload_validator_->set_sink(&thunk_);
+ if (payload_validator)
+ filters_.Append(std::move(payload_validator));
controller_ = handle_.group_controller()->AttachEndpointClient(
handle_, this, task_runner_);
if (expect_sync_requests)
controller_->AllowWokenUpBySyncWatchOnSameThread();
+
+ base::MessageLoop::current()->AddDestructionObserver(this);
}
InterfaceEndpointClient::~InterfaceEndpointClient() {
DCHECK(thread_checker_.CalledOnValidThread());
- handle_.group_controller()->DetachEndpointClient(handle_);
+ StopObservingIfNecessary();
+
+ if (handle_.is_valid())
+ handle_.group_controller()->DetachEndpointClient(handle_);
}
AssociatedGroup* InterfaceEndpointClient::associated_group() {
@@ -186,6 +196,11 @@ ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() {
return std::move(handle_);
}
+void InterfaceEndpointClient::AddFilter(
+ std::unique_ptr<MessageReceiver> filter) {
+ filters_.Append(std::move(filter));
+}
+
void InterfaceEndpointClient::RaiseError() {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -234,20 +249,18 @@ bool InterfaceEndpointClient::AcceptWithResponder(Message* message,
bool response_received = false;
std::unique_ptr<MessageReceiver> sync_responder(responder);
sync_responses_.insert(std::make_pair(
- request_id, base::WrapUnique(new SyncResponseInfo(&response_received))));
+ request_id, base::MakeUnique<SyncResponseInfo>(&response_received)));
base::WeakPtr<InterfaceEndpointClient> weak_self =
weak_ptr_factory_.GetWeakPtr();
controller_->SyncWatch(&response_received);
// Make sure that this instance hasn't been destroyed.
if (weak_self) {
- DCHECK(ContainsKey(sync_responses_, request_id));
+ DCHECK(base::ContainsKey(sync_responses_, request_id));
auto iter = sync_responses_.find(request_id);
DCHECK_EQ(&response_received, iter->second->response_received);
- if (response_received) {
- std::unique_ptr<Message> response = std::move(iter->second->response);
- ignore_result(sync_responder->Accept(response.get()));
- }
+ if (response_received)
+ ignore_result(sync_responder->Accept(&iter->second->response));
sync_responses_.erase(iter);
}
@@ -257,8 +270,7 @@ bool InterfaceEndpointClient::AcceptWithResponder(Message* message,
bool InterfaceEndpointClient::HandleIncomingMessage(Message* message) {
DCHECK(thread_checker_.CalledOnValidThread());
-
- return payload_validator_->Accept(message);
+ return filters_.Accept(message);
}
void InterfaceEndpointClient::NotifyError() {
@@ -267,20 +279,38 @@ void InterfaceEndpointClient::NotifyError() {
if (encountered_error_)
return;
encountered_error_ = true;
- if (!error_handler_.is_null())
+
+ // The callbacks may hold on to resources. There is no need to keep them any
+ // longer.
+ async_responders_.clear();
+
+ control_message_proxy_.OnConnectionError();
+
+ if (!error_handler_.is_null()) {
error_handler_.Run();
+ } else if (!error_with_reason_handler_.is_null()) {
+ // Make a copy on the stack. If we directly pass a reference to a member of
+ // |control_message_handler_|, that reference will be invalidated as soon as
+ // the user destroys the interface endpoint.
+ std::string description = control_message_handler_.disconnect_description();
+ error_with_reason_handler_.Run(
+ control_message_handler_.disconnect_custom_reason(), description);
+ }
}
bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) {
DCHECK_EQ(handle_.id(), message->interface_id());
+ DCHECK(!encountered_error_);
if (message->has_flag(Message::kFlagExpectsResponse)) {
- if (!incoming_receiver_)
- return false;
-
MessageReceiverWithStatus* responder =
new ResponderThunk(weak_ptr_factory_.GetWeakPtr(), task_runner_);
- bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
+ bool ok = false;
+ if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) {
+ ok = control_message_handler_.AcceptWithResponder(message, responder);
+ } else {
+ ok = incoming_receiver_->AcceptWithResponder(message, responder);
+ }
if (!ok)
delete responder;
return ok;
@@ -291,8 +321,7 @@ bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) {
auto it = sync_responses_.find(request_id);
if (it == sync_responses_.end())
return false;
- it->second->response.reset(new Message());
- message->MoveTo(it->second->response.get());
+ it->second->response = std::move(*message);
*it->second->response_received = true;
return true;
}
@@ -304,11 +333,24 @@ bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) {
async_responders_.erase(it);
return responder->Accept(message);
} else {
- if (!incoming_receiver_)
- return false;
+ if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
+ return control_message_handler_.Accept(message);
return incoming_receiver_->Accept(message);
}
}
+void InterfaceEndpointClient::StopObservingIfNecessary() {
+ if (!observing_message_loop_destruction_)
+ return;
+
+ observing_message_loop_destruction_ = false;
+ base::MessageLoop::current()->RemoveDestructionObserver(this);
+}
+
+void InterfaceEndpointClient::WillDestroyCurrentMessageLoop() {
+ StopObservingIfNecessary();
+ NotifyError();
+}
+
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h
index c76fc9c1bca..78aa02e1763 100644
--- a/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h
+++ b/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h
@@ -9,6 +9,7 @@
#include <algorithm> // For |std::swap()|.
#include <memory>
+#include <string>
#include <utility>
#include "base/bind.h"
@@ -19,11 +20,13 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/associated_group.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
+#include "mojo/public/cpp/bindings/filter_chain.h"
#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
#include "mojo/public/cpp/bindings/interface_id.h"
#include "mojo/public/cpp/bindings/interface_ptr_info.h"
+#include "mojo/public/cpp/bindings/lib/control_message_handler.h"
#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
-#include "mojo/public/cpp/bindings/lib/filter_chain.h"
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
#include "mojo/public/cpp/bindings/lib/router.h"
#include "mojo/public/cpp/bindings/message_header_validator.h"
@@ -64,12 +67,10 @@ class InterfacePtrState<Interface, false> {
void QueryVersion(const base::Callback<void(uint32_t)>& callback) {
ConfigureProxyIfNecessary();
- // Do a static cast in case the interface contains methods with the same
- // name. It is safe to capture |this| because the callback won't be run
- // after this object goes away.
- static_cast<ControlMessageProxy*>(proxy_)->QueryVersion(
- base::Bind(&InterfacePtrState::OnQueryVersion, base::Unretained(this),
- callback));
+ // It is safe to capture |this| because the callback won't be run after this
+ // object goes away.
+ router_->control_message_proxy()->QueryVersion(base::Bind(
+ &InterfacePtrState::OnQueryVersion, base::Unretained(this), callback));
}
void RequireVersion(uint32_t version) {
@@ -79,9 +80,19 @@ class InterfacePtrState<Interface, false> {
return;
version_ = version;
- // Do a static cast in case the interface contains methods with the same
- // name.
- static_cast<ControlMessageProxy*>(proxy_)->RequireVersion(version);
+ router_->control_message_proxy()->RequireVersion(version);
+ }
+
+ void FlushForTesting() {
+ ConfigureProxyIfNecessary();
+ router_->control_message_proxy()->FlushForTesting();
+ }
+
+ void SendDisconnectReason(uint32_t custom_reason,
+ const std::string& description) {
+ ConfigureProxyIfNecessary();
+ router_->control_message_proxy()->SendDisconnectReason(custom_reason,
+ description);
}
void Swap(InterfacePtrState* other) {
@@ -108,13 +119,6 @@ class InterfacePtrState<Interface, false> {
bool HasAssociatedInterfaces() const { return false; }
- bool WaitForIncomingResponse() {
- ConfigureProxyIfNecessary();
-
- DCHECK(router_);
- return router_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
- }
-
// After this method is called, the object is in an invalid state and
// shouldn't be reused.
InterfacePtrInfo<Interface> PassInterface() {
@@ -135,6 +139,14 @@ class InterfacePtrState<Interface, false> {
router_->set_connection_error_handler(error_handler);
}
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ ConfigureProxyIfNecessary();
+
+ DCHECK(router_);
+ router_->set_connection_error_with_reason_handler(error_handler);
+ }
+
// Returns true if bound and awaiting a response to a message.
bool has_pending_callbacks() const {
return router_ && router_->has_pending_responders();
@@ -164,8 +176,10 @@ class InterfacePtrState<Interface, false> {
filters.Append<MessageHeaderValidator>(Interface::Name_);
filters.Append<typename Interface::ResponseValidator_>();
+ // The version is only queried from the client so the value passed here
+ // will not be used.
router_ = new Router(std::move(handle_), std::move(filters), false,
- std::move(runner_));
+ std::move(runner_), 0u);
proxy_ = new Proxy(router_);
}
@@ -216,13 +230,10 @@ class InterfacePtrState<Interface, true> {
void QueryVersion(const base::Callback<void(uint32_t)>& callback) {
ConfigureProxyIfNecessary();
-
- // Do a static cast in case the interface contains methods with the same
- // name. It is safe to capture |this| because the callback won't be run
- // after this object goes away.
- static_cast<ControlMessageProxy*>(proxy_.get())->QueryVersion(
- base::Bind(&InterfacePtrState::OnQueryVersion, base::Unretained(this),
- callback));
+ // It is safe to capture |this| because the callback won't be run after this
+ // object goes away.
+ endpoint_client_->control_message_proxy()->QueryVersion(base::Bind(
+ &InterfacePtrState::OnQueryVersion, base::Unretained(this), callback));
}
void RequireVersion(uint32_t version) {
@@ -232,9 +243,19 @@ class InterfacePtrState<Interface, true> {
return;
version_ = version;
- // Do a static cast in case the interface contains methods with the same
- // name.
- static_cast<ControlMessageProxy*>(proxy_.get())->RequireVersion(version);
+ endpoint_client_->control_message_proxy()->RequireVersion(version);
+ }
+
+ void FlushForTesting() {
+ ConfigureProxyIfNecessary();
+ endpoint_client_->control_message_proxy()->FlushForTesting();
+ }
+
+ void SendDisconnectReason(uint32_t custom_reason,
+ const std::string& description) {
+ ConfigureProxyIfNecessary();
+ endpoint_client_->control_message_proxy()->SendDisconnectReason(
+ custom_reason, description);
}
void Swap(InterfacePtrState* other) {
@@ -265,13 +286,6 @@ class InterfacePtrState<Interface, true> {
return router_ ? router_->HasAssociatedEndpoints() : false;
}
- bool WaitForIncomingResponse() {
- ConfigureProxyIfNecessary();
-
- DCHECK(router_);
- return router_->WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE);
- }
-
// After this method is called, the object is in an invalid state and
// shouldn't be reused.
InterfacePtrInfo<Interface> PassInterface() {
@@ -294,6 +308,14 @@ class InterfacePtrState<Interface, true> {
endpoint_client_->set_connection_error_handler(error_handler);
}
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ ConfigureProxyIfNecessary();
+
+ DCHECK(endpoint_client_);
+ endpoint_client_->set_connection_error_with_reason_handler(error_handler);
+ }
+
// Returns true if bound and awaiting a response to a message.
bool has_pending_callbacks() const {
return endpoint_client_ && endpoint_client_->has_pending_responders();
@@ -323,12 +345,21 @@ class InterfacePtrState<Interface, true> {
if (!handle_.is_valid())
return;
- router_ = new MultiplexRouter(true, std::move(handle_), runner_);
+ MultiplexRouter::Config config =
+ Interface::PassesAssociatedKinds_
+ ? MultiplexRouter::MULTI_INTERFACE
+ : (Interface::HasSyncMethods_
+ ? MultiplexRouter::SINGLE_INTERFACE_WITH_SYNC_METHODS
+ : MultiplexRouter::SINGLE_INTERFACE);
+ router_ = new MultiplexRouter(std::move(handle_), config, true, runner_);
router_->SetMasterInterfaceName(Interface::Name_);
endpoint_client_.reset(new InterfaceEndpointClient(
router_->CreateLocalEndpointHandle(kMasterInterfaceId), nullptr,
base::WrapUnique(new typename Interface::ResponseValidator_()), false,
- std::move(runner_)));
+ std::move(runner_),
+ // The version is only queried from the client so the value passed here
+ // will not be used.
+ 0u));
proxy_.reset(new Proxy(endpoint_client_.get()));
proxy_->serialization_context()->group_controller =
endpoint_client_->group_controller();
diff --git a/chromium/mojo/public/cpp/bindings/lib/map_data_internal.h b/chromium/mojo/public/cpp/bindings/lib/map_data_internal.h
index e2633331e02..f8e3d2918fc 100644
--- a/chromium/mojo/public/cpp/bindings/lib/map_data_internal.h
+++ b/chromium/mojo/public/cpp/bindings/lib/map_data_internal.h
@@ -41,45 +41,22 @@ class Map_Data {
return false;
}
- if (!ValidateEncodedPointer(&object->keys.offset)) {
- ReportValidationError(validation_context,
- VALIDATION_ERROR_ILLEGAL_POINTER);
- return false;
- }
- if (!object->keys.offset) {
- ReportValidationError(validation_context,
- VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
- "null key array in map struct");
- return false;
- }
- if (!Array_Data<Key>::Validate(DecodePointerRaw(&object->keys.offset),
- validation_context,
- validate_params->key_validate_params)) {
+ if (!ValidatePointerNonNullable(
+ object->keys, "null key array in map struct", validation_context) ||
+ !ValidateContainer(object->keys, validation_context,
+ validate_params->key_validate_params)) {
return false;
}
- if (!ValidateEncodedPointer(&object->values.offset)) {
- ReportValidationError(validation_context,
- VALIDATION_ERROR_ILLEGAL_POINTER);
- return false;
- }
- if (!object->values.offset) {
- ReportValidationError(validation_context,
- VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
- "null value array in map struct");
- return false;
- }
- if (!Array_Data<Value>::Validate(
- DecodePointerRaw(&object->values.offset),
- validation_context, validate_params->element_validate_params)) {
+ if (!ValidatePointerNonNullable(object->values,
+ "null value array in map struct",
+ validation_context) ||
+ !ValidateContainer(object->values, validation_context,
+ validate_params->element_validate_params)) {
return false;
}
- const ArrayHeader* key_header =
- static_cast<const ArrayHeader*>(DecodePointerRaw(&object->keys.offset));
- const ArrayHeader* value_header = static_cast<const ArrayHeader*>(
- DecodePointerRaw(&object->values.offset));
- if (key_header->num_elements != value_header->num_elements) {
+ if (object->keys.Get()->size() != object->values.Get()->size()) {
ReportValidationError(validation_context,
VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP);
return false;
@@ -93,16 +70,6 @@ class Map_Data {
Pointer<Array_Data<Key>> keys;
Pointer<Array_Data<Value>> values;
- void EncodePointers() {
- Encode(&keys);
- Encode(&values);
- }
-
- void DecodePointers() {
- Decode(&keys);
- Decode(&values);
- }
-
private:
Map_Data() {
header_.num_bytes = sizeof(*this);
diff --git a/chromium/mojo/public/cpp/bindings/lib/map_serialization.h b/chromium/mojo/public/cpp/bindings/lib/map_serialization.h
index 407c8b4f6c3..718a76307db 100644
--- a/chromium/mojo/public/cpp/bindings/lib/map_serialization.h
+++ b/chromium/mojo/public/cpp/bindings/lib/map_serialization.h
@@ -8,11 +8,11 @@
#include <type_traits>
#include <vector>
-#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/array_data_view.h"
#include "mojo/public/cpp/bindings/lib/array_serialization.h"
#include "mojo/public/cpp/bindings/lib/map_data_internal.h"
#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
-#include "mojo/public/cpp/bindings/map.h"
+#include "mojo/public/cpp/bindings/map_data_view.h"
namespace mojo {
namespace internal {
@@ -46,12 +46,15 @@ class MapKeyReader : public MapReaderBase<MaybeConstUserType> {
public:
using Base = MapReaderBase<MaybeConstUserType>;
using Traits = typename Base::Traits;
+ using MaybeConstIterator = typename Base::MaybeConstIterator;
explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {}
~MapKeyReader() {}
- const typename Traits::Key& GetNext() {
- const typename Traits::Key& key = Traits::GetKey(this->iter_);
+ using GetNextResult =
+ decltype(Traits::GetKey(std::declval<MaybeConstIterator&>()));
+ GetNextResult GetNext() {
+ GetNextResult key = Traits::GetKey(this->iter_);
Traits::AdvanceIterator(this->iter_);
return key;
}
@@ -78,17 +81,17 @@ class MapValueReader : public MapReaderBase<MaybeConstUserType> {
};
template <typename Key, typename Value, typename MaybeConstUserType>
-struct Serializer<Map<Key, Value>, MaybeConstUserType> {
+struct Serializer<MapDataView<Key, Value>, MaybeConstUserType> {
using UserType = typename std::remove_const<MaybeConstUserType>::type;
using Traits = MapTraits<UserType>;
using UserKey = typename Traits::Key;
using UserValue = typename Traits::Value;
- using Data = typename MojomTypeTraits<Map<Key, Value>>::Data;
- using KeyArraySerializer = ArraySerializer<Array<Key>,
+ using Data = typename MojomTypeTraits<MapDataView<Key, Value>>::Data;
+ using KeyArraySerializer = ArraySerializer<ArrayDataView<Key>,
std::vector<UserKey>,
MapKeyReader<MaybeConstUserType>>;
using ValueArraySerializer =
- ArraySerializer<Array<Value>,
+ ArraySerializer<ArrayDataView<Value>,
std::vector<UserValue>,
MapValueReader<MaybeConstUserType>>;
@@ -122,22 +125,24 @@ struct Serializer<Map<Key, Value>, MaybeConstUserType> {
auto result = Data::New(buf);
if (result) {
- result->keys.ptr =
- MojomTypeTraits<Array<Key>>::Data::New(Traits::GetSize(input), buf);
- if (result->keys.ptr) {
+ auto keys_ptr = MojomTypeTraits<ArrayDataView<Key>>::Data::New(
+ Traits::GetSize(input), buf);
+ if (keys_ptr) {
MapKeyReader<MaybeConstUserType> key_reader(input);
KeyArraySerializer::SerializeElements(
- &key_reader, buf, result->keys.ptr,
- validate_params->key_validate_params, context);
+ &key_reader, buf, keys_ptr, validate_params->key_validate_params,
+ context);
+ result->keys.Set(keys_ptr);
}
- result->values.ptr =
- MojomTypeTraits<Array<Value>>::Data::New(Traits::GetSize(input), buf);
- if (result->values.ptr) {
+ auto values_ptr = MojomTypeTraits<ArrayDataView<Value>>::Data::New(
+ Traits::GetSize(input), buf);
+ if (values_ptr) {
MapValueReader<MaybeConstUserType> value_reader(input);
ValueArraySerializer::SerializeElements(
- &value_reader, buf, result->values.ptr,
+ &value_reader, buf, values_ptr,
validate_params->element_validate_params, context);
+ result->values.Set(values_ptr);
}
}
*output = result;
@@ -152,9 +157,9 @@ struct Serializer<Map<Key, Value>, MaybeConstUserType> {
std::vector<UserKey> keys;
std::vector<UserValue> values;
- if (!KeyArraySerializer::DeserializeElements(input->keys.ptr, &keys,
+ if (!KeyArraySerializer::DeserializeElements(input->keys.Get(), &keys,
context) ||
- !ValueArraySerializer::DeserializeElements(input->values.ptr, &values,
+ !ValueArraySerializer::DeserializeElements(input->values.Get(), &values,
context)) {
return false;
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/may_auto_lock.h b/chromium/mojo/public/cpp/bindings/lib/may_auto_lock.h
new file mode 100644
index 00000000000..09ee705d79a
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/may_auto_lock.h
@@ -0,0 +1,54 @@
+// Copyright 2016 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/macros.h"
+#include "base/synchronization/lock.h"
+
+namespace mojo {
+namespace internal {
+
+// Similar to base::AutoLock, except that it does nothing if |lock| passed into
+// the constructor is null.
+class MayAutoLock {
+ public:
+ explicit MayAutoLock(base::Lock* lock) : lock_(lock) {
+ if (lock_)
+ lock_->Acquire();
+ }
+
+ ~MayAutoLock() {
+ if (lock_) {
+ lock_->AssertAcquired();
+ lock_->Release();
+ }
+ }
+
+ private:
+ base::Lock* lock_;
+ DISALLOW_COPY_AND_ASSIGN(MayAutoLock);
+};
+
+// Similar to base::AutoUnlock, except that it does nothing if |lock| passed
+// into the constructor is null.
+class MayAutoUnlock {
+ public:
+ explicit MayAutoUnlock(base::Lock* lock) : lock_(lock) {
+ if (lock_) {
+ lock_->AssertAcquired();
+ lock_->Release();
+ }
+ }
+
+ ~MayAutoUnlock() {
+ if (lock_)
+ lock_->Acquire();
+ }
+
+ private:
+ base::Lock* lock_;
+ DISALLOW_COPY_AND_ASSIGN(MayAutoUnlock);
+};
+
+} // namespace internal
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/message.cc b/chromium/mojo/public/cpp/bindings/lib/message.cc
index 939e064b5ce..0018a03bcd7 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/message.cc
@@ -11,18 +11,52 @@
#include <algorithm>
#include <utility>
+#include "base/bind.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
+#include "base/threading/thread_local.h"
namespace mojo {
+namespace {
+
+base::LazyInstance<base::ThreadLocalPointer<internal::MessageDispatchContext>>
+ g_tls_message_dispatch_context = LAZY_INSTANCE_INITIALIZER;
+
+base::LazyInstance<base::ThreadLocalPointer<SyncMessageResponseContext>>
+ g_tls_sync_response_context = LAZY_INSTANCE_INITIALIZER;
+
+void DoNotifyBadMessage(Message message, const std::string& error) {
+ message.NotifyBadMessage(error);
+}
+
+} // namespace
+
Message::Message() {
}
+Message::Message(Message&& other)
+ : buffer_(std::move(other.buffer_)), handles_(std::move(other.handles_)) {
+}
+
Message::~Message() {
CloseHandles();
}
+Message& Message::operator=(Message&& other) {
+ Reset();
+ std::swap(other.buffer_, buffer_);
+ std::swap(other.handles_, handles_);
+ return *this;
+}
+
+void Message::Reset() {
+ CloseHandles();
+ handles_.clear();
+ buffer_.reset();
+}
+
void Message::Initialize(size_t capacity, bool zero_initialized) {
DCHECK(!buffer_);
buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized));
@@ -36,18 +70,6 @@ void Message::InitializeFromMojoMessage(ScopedMessageHandle message,
handles_.swap(*handles);
}
-void Message::MoveTo(Message* destination) {
- DCHECK(this != destination);
-
- // No copy needed.
- std::swap(destination->buffer_, buffer_);
- std::swap(destination->handles_, handles_);
-
- CloseHandles();
- handles_.clear();
- buffer_.reset();
-}
-
ScopedMessageHandle Message::TakeMojoMessage() {
if (handles_.empty()) // Fast path for the common case: No handles.
return buffer_->TakeMessage();
@@ -80,6 +102,7 @@ ScopedMessageHandle Message::TakeMojoMessage() {
}
void Message::NotifyBadMessage(const std::string& error) {
+ DCHECK(buffer_);
buffer_->NotifyBadMessage(error);
}
@@ -91,6 +114,40 @@ void Message::CloseHandles() {
}
}
+PassThroughFilter::PassThroughFilter() {}
+
+PassThroughFilter::~PassThroughFilter() {}
+
+bool PassThroughFilter::Accept(Message* message) { return true; }
+
+SyncMessageResponseContext::SyncMessageResponseContext()
+ : outer_context_(current()) {
+ g_tls_sync_response_context.Get().Set(this);
+}
+
+SyncMessageResponseContext::~SyncMessageResponseContext() {
+ DCHECK_EQ(current(), this);
+ g_tls_sync_response_context.Get().Set(outer_context_);
+}
+
+// static
+SyncMessageResponseContext* SyncMessageResponseContext::current() {
+ return g_tls_sync_response_context.Get().Get();
+}
+
+void SyncMessageResponseContext::ReportBadMessage(const std::string& error) {
+ GetBadMessageCallback().Run(error);
+}
+
+const ReportBadMessageCallback&
+SyncMessageResponseContext::GetBadMessageCallback() {
+ if (bad_message_callback_.is_null()) {
+ bad_message_callback_ =
+ base::Bind(&DoNotifyBadMessage, base::Passed(&response_));
+ }
+ return bad_message_callback_;
+}
+
MojoResult ReadMessage(MessagePipeHandle handle, Message* message) {
MojoResult rv;
@@ -122,4 +179,53 @@ MojoResult ReadMessage(MessagePipeHandle handle, Message* message) {
return MOJO_RESULT_OK;
}
+void ReportBadMessage(const std::string& error) {
+ internal::MessageDispatchContext* context =
+ internal::MessageDispatchContext::current();
+ DCHECK(context);
+ context->GetBadMessageCallback().Run(error);
+}
+
+ReportBadMessageCallback GetBadMessageCallback() {
+ internal::MessageDispatchContext* context =
+ internal::MessageDispatchContext::current();
+ DCHECK(context);
+ return context->GetBadMessageCallback();
+}
+
+namespace internal {
+
+MessageDispatchContext::MessageDispatchContext(Message* message)
+ : outer_context_(current()), message_(message) {
+ g_tls_message_dispatch_context.Get().Set(this);
+}
+
+MessageDispatchContext::~MessageDispatchContext() {
+ DCHECK_EQ(current(), this);
+ g_tls_message_dispatch_context.Get().Set(outer_context_);
+}
+
+// static
+MessageDispatchContext* MessageDispatchContext::current() {
+ return g_tls_message_dispatch_context.Get().Get();
+}
+
+const ReportBadMessageCallback&
+MessageDispatchContext::GetBadMessageCallback() {
+ if (bad_message_callback_.is_null()) {
+ bad_message_callback_ =
+ base::Bind(&DoNotifyBadMessage, base::Passed(message_));
+ }
+ return bad_message_callback_;
+}
+
+// static
+void SyncMessageResponseSetup::SetCurrentSyncResponseMessage(Message* message) {
+ SyncMessageResponseContext* context = SyncMessageResponseContext::current();
+ if (context)
+ context->response_ = std::move(*message);
+}
+
+} // namespace internal
+
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_buffer.cc b/chromium/mojo/public/cpp/bindings/lib/message_buffer.cc
index af79cfd2513..cc12ef6e31c 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message_buffer.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/message_buffer.cc
@@ -13,54 +13,35 @@ namespace internal {
MessageBuffer::MessageBuffer(size_t capacity, bool zero_initialized) {
DCHECK_LE(capacity, std::numeric_limits<uint32_t>::max());
- data_num_bytes_ = static_cast<uint32_t>(capacity);
MojoResult rv = AllocMessage(capacity, nullptr, 0,
MOJO_ALLOC_MESSAGE_FLAG_NONE, &message_);
CHECK_EQ(rv, MOJO_RESULT_OK);
- if (capacity == 0) {
- buffer_ = nullptr;
- } else {
- rv = GetMessageBuffer(message_.get(), &buffer_);
+ void* buffer = nullptr;
+ if (capacity != 0) {
+ rv = GetMessageBuffer(message_.get(), &buffer);
CHECK_EQ(rv, MOJO_RESULT_OK);
if (zero_initialized)
- memset(buffer_, 0, capacity);
+ memset(buffer, 0, capacity);
}
+ Initialize(buffer, capacity);
}
MessageBuffer::MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes) {
message_ = std::move(message);
- data_num_bytes_ = num_bytes;
- if (num_bytes == 0) {
- buffer_ = nullptr;
- } else {
- MojoResult rv = GetMessageBuffer(message_.get(), &buffer_);
+ void* buffer = nullptr;
+ if (num_bytes != 0) {
+ MojoResult rv = GetMessageBuffer(message_.get(), &buffer);
CHECK_EQ(rv, MOJO_RESULT_OK);
}
+ Initialize(buffer, num_bytes);
}
MessageBuffer::~MessageBuffer() {}
-void* MessageBuffer::Allocate(size_t delta) {
- delta = internal::Align(delta);
-
- DCHECK_LE(delta, static_cast<size_t>(data_num_bytes_));
- DCHECK_GT(bytes_claimed_ + static_cast<uint32_t>(delta), bytes_claimed_);
-
- uint32_t new_bytes_claimed = bytes_claimed_ + static_cast<uint32_t>(delta);
- if (new_bytes_claimed > data_num_bytes_) {
- NOTREACHED();
- return nullptr;
- }
-
- char* start = static_cast<char*>(buffer_) + bytes_claimed_;
- bytes_claimed_ = new_bytes_claimed;
- return static_cast<void*>(start);
-}
-
void MessageBuffer::NotifyBadMessage(const std::string& error) {
DCHECK(message_.is_valid());
MojoResult result = mojo::NotifyBadMessage(message_.get(), error);
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_buffer.h b/chromium/mojo/public/cpp/bindings/lib/message_buffer.h
index 038213149f3..96d5140f774 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message_buffer.h
+++ b/chromium/mojo/public/cpp/bindings/lib/message_buffer.h
@@ -5,7 +5,6 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_
#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_
-#include <stddef.h>
#include <stdint.h>
#include <utility>
@@ -17,7 +16,7 @@
namespace mojo {
namespace internal {
-// A fixed-size Buffer implementation using a Mojo message object for storage.
+// A fixed-size Buffer using a Mojo message object for storage.
class MessageBuffer : public Buffer {
public:
// Initializes this buffer to carry a fixed byte capacity and no handles.
@@ -26,24 +25,14 @@ class MessageBuffer : public Buffer {
// Initializes this buffer from an existing Mojo MessageHandle.
MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes);
- ~MessageBuffer() override;
-
- void* data() const { return buffer_; }
- uint32_t data_num_bytes() const { return data_num_bytes_; }
-
- // Buffer:
- void* Allocate(size_t delta) override;
+ ~MessageBuffer();
ScopedMessageHandle TakeMessage() { return std::move(message_); }
void NotifyBadMessage(const std::string& error);
private:
- uint32_t data_num_bytes_ = 0;
ScopedMessageHandle message_;
- void* buffer_;
-
- uint32_t bytes_claimed_ = 0;
DISALLOW_COPY_AND_ASSIGN(MessageBuffer);
};
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_builder.h b/chromium/mojo/public/cpp/bindings/lib/message_builder.h
index a5a050f7ed7..2e3a4a1f14e 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message_builder.h
+++ b/chromium/mojo/public/cpp/bindings/lib/message_builder.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/message_internal.h"
#include "mojo/public/cpp/bindings/message.h"
@@ -16,7 +17,7 @@ class Message;
namespace internal {
-class MessageBuilder {
+class MOJO_CPP_BINDINGS_EXPORT MessageBuilder {
public:
MessageBuilder(uint32_t name, size_t payload_size);
~MessageBuilder();
@@ -33,7 +34,8 @@ class MessageBuilder {
DISALLOW_COPY_AND_ASSIGN(MessageBuilder);
};
-class MessageWithRequestIDBuilder : public MessageBuilder {
+class MOJO_CPP_BINDINGS_EXPORT MessageWithRequestIDBuilder
+ : public MessageBuilder {
public:
MessageWithRequestIDBuilder(uint32_t name,
size_t payload_size,
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_filter.cc b/chromium/mojo/public/cpp/bindings/lib/message_filter.cc
deleted file mode 100644
index b09f40d8c5e..00000000000
--- a/chromium/mojo/public/cpp/bindings/lib/message_filter.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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
index 10f77741301..ef01f0a0702 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message_header_validator.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/message_header_validator.cc
@@ -65,12 +65,11 @@ bool IsValidMessageHeader(const internal::MessageHeader* header,
} // namespace
-MessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink)
- : MessageHeaderValidator("MessageHeaderValidator", sink) {}
+MessageHeaderValidator::MessageHeaderValidator()
+ : MessageHeaderValidator("MessageHeaderValidator") {}
-MessageHeaderValidator::MessageHeaderValidator(const std::string& description,
- MessageReceiver* sink)
- : MessageFilter(sink), description_(description) {
+MessageHeaderValidator::MessageHeaderValidator(const std::string& description)
+ : description_(description) {
}
void MessageHeaderValidator::SetDescription(const std::string& description) {
@@ -90,7 +89,7 @@ bool MessageHeaderValidator::Accept(Message* message) {
if (!IsValidMessageHeader(message->header(), &validation_context))
return false;
- return sink_->Accept(message);
+ return true;
}
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_internal.h b/chromium/mojo/public/cpp/bindings/lib/message_internal.h
index 63edffd7cbd..ad3ef9913fa 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message_internal.h
+++ b/chromium/mojo/public/cpp/bindings/lib/message_internal.h
@@ -7,9 +7,17 @@
#include <stdint.h>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
namespace mojo {
+
+class Message;
+
namespace internal {
#pragma pack(push, 1)
@@ -37,6 +45,28 @@ static_assert(sizeof(MessageHeaderWithRequestID) == 32,
#pragma pack(pop)
+class MOJO_CPP_BINDINGS_EXPORT MessageDispatchContext {
+ public:
+ explicit MessageDispatchContext(Message* message);
+ ~MessageDispatchContext();
+
+ static MessageDispatchContext* current();
+
+ const base::Callback<void(const std::string&)>& GetBadMessageCallback();
+
+ private:
+ MessageDispatchContext* outer_context_;
+ Message* message_;
+ base::Callback<void(const std::string&)> bad_message_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageDispatchContext);
+};
+
+class MOJO_CPP_BINDINGS_EXPORT SyncMessageResponseSetup {
+ public:
+ static void SetCurrentSyncResponseMessage(Message* message);
+};
+
} // namespace internal
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc
index dcfbab1545b..ef0426fa976 100644
--- a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -18,6 +18,7 @@
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
#include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
+#include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
namespace mojo {
@@ -50,13 +51,13 @@ class MultiplexRouter::InterfaceEndpoint
bool closed() const { return closed_; }
void set_closed() {
- router_->lock_.AssertAcquired();
+ router_->AssertLockAcquired();
closed_ = true;
}
bool peer_closed() const { return peer_closed_; }
void set_peer_closed() {
- router_->lock_.AssertAcquired();
+ router_->AssertLockAcquired();
peer_closed_ = true;
}
@@ -68,7 +69,7 @@ class MultiplexRouter::InterfaceEndpoint
void AttachClient(InterfaceEndpointClient* client,
scoped_refptr<base::SingleThreadTaskRunner> runner) {
- router_->lock_.AssertAcquired();
+ router_->AssertLockAcquired();
DCHECK(!client_);
DCHECK(!closed_);
DCHECK(runner->BelongsToCurrentThread());
@@ -80,7 +81,7 @@ class MultiplexRouter::InterfaceEndpoint
// This method must be called on the same thread as the corresponding
// AttachClient() call.
void DetachClient() {
- router_->lock_.AssertAcquired();
+ router_->AssertLockAcquired();
DCHECK(client_);
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!closed_);
@@ -91,7 +92,7 @@ class MultiplexRouter::InterfaceEndpoint
}
void SignalSyncMessageEvent() {
- router_->lock_.AssertAcquired();
+ router_->AssertLockAcquired();
if (event_signalled_)
return;
@@ -103,6 +104,20 @@ class MultiplexRouter::InterfaceEndpoint
DCHECK_EQ(MOJO_RESULT_OK, result);
}
+ void ResetSyncMessageSignal() {
+ router_->AssertLockAcquired();
+
+ if (!event_signalled_)
+ return;
+
+ DCHECK(sync_message_event_receiver_.is_valid());
+ MojoResult result =
+ ReadMessageRaw(sync_message_event_receiver_.get(), nullptr, nullptr,
+ nullptr, nullptr, MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ event_signalled_ = false;
+ }
+
// ---------------------------------------------------------------------------
// The following public methods (i.e., InterfaceEndpointController
// implementation) are called by the client on the same thread as the
@@ -132,7 +147,7 @@ class MultiplexRouter::InterfaceEndpoint
friend class base::RefCounted<InterfaceEndpoint>;
~InterfaceEndpoint() override {
- router_->lock_.AssertAcquired();
+ router_->AssertLockAcquired();
DCHECK(!client_);
DCHECK(closed_);
@@ -150,7 +165,7 @@ class MultiplexRouter::InterfaceEndpoint
DCHECK_EQ(MOJO_RESULT_OK, result);
bool reset_sync_watcher = false;
{
- base::AutoLock locker(router_->lock_);
+ MayAutoLock locker(router_->lock_.get());
bool more_to_process = router_->ProcessFirstSyncMessageForEndpoint(id_);
@@ -175,7 +190,7 @@ class MultiplexRouter::InterfaceEndpoint
return;
{
- base::AutoLock locker(router_->lock_);
+ MayAutoLock locker(router_->lock_.get());
EnsureEventMessagePipeExists();
auto iter = router_->sync_message_tasks_.find(id_);
@@ -189,7 +204,7 @@ class MultiplexRouter::InterfaceEndpoint
}
void EnsureEventMessagePipeExists() {
- router_->lock_.AssertAcquired();
+ router_->AssertLockAcquired();
if (sync_message_event_receiver_.is_valid())
return;
@@ -199,20 +214,6 @@ class MultiplexRouter::InterfaceEndpoint
DCHECK_EQ(MOJO_RESULT_OK, result);
}
- void ResetSyncMessageSignal() {
- router_->lock_.AssertAcquired();
-
- if (!event_signalled_)
- return;
-
- DCHECK(sync_message_event_receiver_.is_valid());
- MojoResult result = ReadMessageRaw(sync_message_event_receiver_.get(),
- nullptr, nullptr, nullptr, nullptr,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
- DCHECK_EQ(MOJO_RESULT_OK, result);
- event_signalled_ = false;
- }
-
// ---------------------------------------------------------------------------
// The following members are safe to access from any threads.
@@ -255,8 +256,7 @@ struct MultiplexRouter::Task {
// Doesn't take ownership of |message| but takes its contents.
static std::unique_ptr<Task> CreateMessageTask(Message* message) {
Task* task = new Task(MESSAGE);
- task->message.reset(new Message);
- message->MoveTo(task->message.get());
+ task->message = std::move(*message);
return base::WrapUnique(task);
}
static std::unique_ptr<Task> CreateNotifyErrorTask(
@@ -271,7 +271,7 @@ struct MultiplexRouter::Task {
bool IsMessageTask() const { return type == MESSAGE; }
bool IsNotifyErrorTask() const { return type == NOTIFY_ERROR; }
- std::unique_ptr<Message> message;
+ Message message;
scoped_refptr<InterfaceEndpoint> endpoint_to_notify;
enum Type { MESSAGE, NOTIFY_ERROR };
@@ -282,33 +282,49 @@ struct MultiplexRouter::Task {
};
MultiplexRouter::MultiplexRouter(
- bool set_interface_id_namesapce_bit,
ScopedMessagePipeHandle message_pipe,
+ Config config,
+ bool set_interface_id_namesapce_bit,
scoped_refptr<base::SingleThreadTaskRunner> runner)
- : AssociatedGroupController(base::ThreadTaskRunnerHandle::Get()),
- set_interface_id_namespace_bit_(set_interface_id_namesapce_bit),
- header_validator_(this),
+ : set_interface_id_namespace_bit_(set_interface_id_namesapce_bit),
+ task_runner_(runner),
+ header_validator_(nullptr),
+ filters_(this),
connector_(std::move(message_pipe),
- Connector::MULTI_THREADED_SEND,
+ config == MULTI_INTERFACE ? Connector::MULTI_THREADED_SEND
+ : Connector::SINGLE_THREADED_SEND,
std::move(runner)),
+ lock_(config == MULTI_INTERFACE ? new base::Lock : nullptr),
control_message_handler_(this),
control_message_proxy_(&connector_),
next_interface_id_value_(1),
posted_to_process_tasks_(false),
encountered_error_(false),
+ paused_(false),
testing_mode_(false) {
- // Always participate in sync handle watching, because even if it doesn't
- // expect sync requests during sync handle watching, it may still need to
- // dispatch messages to associated endpoints on a different thread.
- connector_.AllowWokenUpBySyncWatchOnSameThread();
- connector_.set_incoming_receiver(&header_validator_);
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ if (config == SINGLE_INTERFACE_WITH_SYNC_METHODS ||
+ config == MULTI_INTERFACE) {
+ // Always participate in sync handle watching in multi-interface mode,
+ // because even if it doesn't expect sync requests during sync handle
+ // watching, it may still need to dispatch messages to associated endpoints
+ // on a different thread.
+ connector_.AllowWokenUpBySyncWatchOnSameThread();
+ }
+ connector_.set_incoming_receiver(&filters_);
connector_.set_connection_error_handler(
base::Bind(&MultiplexRouter::OnPipeConnectionError,
base::Unretained(this)));
+
+ std::unique_ptr<MessageHeaderValidator> header_validator =
+ base::MakeUnique<MessageHeaderValidator>();
+ header_validator_ = header_validator.get();
+ filters_.Append(std::move(header_validator));
}
MultiplexRouter::~MultiplexRouter() {
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
sync_message_tasks_.clear();
tasks_.clear();
@@ -328,7 +344,7 @@ MultiplexRouter::~MultiplexRouter() {
void MultiplexRouter::SetMasterInterfaceName(const std::string& name) {
DCHECK(thread_checker_.CalledOnValidThread());
- header_validator_.SetDescription(name + " [master] MessageHeaderValidator");
+ header_validator_->SetDescription(name + " [master] MessageHeaderValidator");
control_message_handler_.SetDescription(
name + " [master] PipeControlMessageHandler");
}
@@ -336,7 +352,7 @@ void MultiplexRouter::SetMasterInterfaceName(const std::string& name) {
void MultiplexRouter::CreateEndpointHandlePair(
ScopedInterfaceEndpointHandle* local_endpoint,
ScopedInterfaceEndpointHandle* remote_endpoint) {
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
uint32_t id = 0;
do {
if (next_interface_id_value_ >= kInterfaceIdNamespaceMask)
@@ -344,7 +360,7 @@ void MultiplexRouter::CreateEndpointHandlePair(
id = next_interface_id_value_++;
if (set_interface_id_namespace_bit_)
id |= kInterfaceIdNamespaceMask;
- } while (ContainsKey(endpoints_, id));
+ } while (base::ContainsKey(endpoints_, id));
InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id);
endpoints_[id] = endpoint;
@@ -360,7 +376,7 @@ ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle(
if (!IsValidInterfaceId(id))
return ScopedInterfaceEndpointHandle();
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
bool inserted = false;
InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
if (inserted) {
@@ -379,10 +395,10 @@ void MultiplexRouter::CloseEndpointHandle(InterfaceId id, bool is_local) {
if (!IsValidInterfaceId(id))
return;
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
if (!is_local) {
- DCHECK(ContainsKey(endpoints_, id));
+ DCHECK(base::ContainsKey(endpoints_, id));
DCHECK(!IsMasterInterfaceId(id));
// We will receive a NotifyPeerEndpointClosed message from the other side.
@@ -391,7 +407,7 @@ void MultiplexRouter::CloseEndpointHandle(InterfaceId id, bool is_local) {
return;
}
- DCHECK(ContainsKey(endpoints_, id));
+ DCHECK(base::ContainsKey(endpoints_, id));
InterfaceEndpoint* endpoint = endpoints_[id].get();
DCHECK(!endpoint->client());
DCHECK(!endpoint->closed());
@@ -412,8 +428,8 @@ InterfaceEndpointController* MultiplexRouter::AttachEndpointClient(
DCHECK(IsValidInterfaceId(id));
DCHECK(client);
- base::AutoLock locker(lock_);
- DCHECK(ContainsKey(endpoints_, id));
+ MayAutoLock locker(lock_.get());
+ DCHECK(base::ContainsKey(endpoints_, id));
InterfaceEndpoint* endpoint = endpoints_[id].get();
endpoint->AttachClient(client, std::move(runner));
@@ -431,8 +447,8 @@ void MultiplexRouter::DetachEndpointClient(
DCHECK(IsValidInterfaceId(id));
- base::AutoLock locker(lock_);
- DCHECK(ContainsKey(endpoints_, id));
+ MayAutoLock locker(lock_.get());
+ DCHECK(base::ContainsKey(endpoints_, id));
InterfaceEndpoint* endpoint = endpoints_[id].get();
endpoint->DetachClient();
@@ -456,21 +472,48 @@ void MultiplexRouter::CloseMessagePipe() {
OnPipeConnectionError();
}
+void MultiplexRouter::PauseIncomingMethodCallProcessing() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ connector_.PauseIncomingMethodCallProcessing();
+
+ MayAutoLock locker(lock_.get());
+ paused_ = true;
+
+ for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter)
+ iter->second->ResetSyncMessageSignal();
+}
+
+void MultiplexRouter::ResumeIncomingMethodCallProcessing() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ connector_.ResumeIncomingMethodCallProcessing();
+
+ MayAutoLock locker(lock_.get());
+ paused_ = false;
+
+ for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter) {
+ auto sync_iter = sync_message_tasks_.find(iter->first);
+ if (sync_iter != sync_message_tasks_.end() && !sync_iter->second.empty())
+ iter->second->SignalSyncMessageEvent();
+ }
+
+ ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr);
+}
+
bool MultiplexRouter::HasAssociatedEndpoints() const {
DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
if (endpoints_.size() > 1)
return true;
if (endpoints_.size() == 0)
return false;
- return !ContainsKey(endpoints_, kMasterInterfaceId);
+ return !base::ContainsKey(endpoints_, kMasterInterfaceId);
}
void MultiplexRouter::EnableTestingMode() {
DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
testing_mode_ = true;
connector_.set_enforce_errors_from_incoming_receiver(false);
@@ -480,7 +523,9 @@ bool MultiplexRouter::Accept(Message* message) {
DCHECK(thread_checker_.CalledOnValidThread());
scoped_refptr<MultiplexRouter> protector(this);
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
+
+ DCHECK(!paused_);
ClientCallBehavior client_call_behavior =
connector_.during_sync_handle_watcher_callback()
@@ -497,8 +542,8 @@ bool MultiplexRouter::Accept(Message* message) {
tasks_.push_back(Task::CreateMessageTask(message));
Task* task = tasks_.back().get();
- if (task->message->has_flag(Message::kFlagIsSync)) {
- InterfaceId id = task->message->interface_id();
+ if (task->message.has_flag(Message::kFlagIsSync)) {
+ InterfaceId id = task->message.interface_id();
sync_message_tasks_[id].push_back(task);
auto iter = endpoints_.find(id);
if (iter != endpoints_.end())
@@ -517,7 +562,7 @@ bool MultiplexRouter::Accept(Message* message) {
}
bool MultiplexRouter::OnPeerAssociatedEndpointClosed(InterfaceId id) {
- lock_.AssertAcquired();
+ AssertLockAcquired();
if (IsMasterInterfaceId(id))
return false;
@@ -542,7 +587,7 @@ bool MultiplexRouter::OnPeerAssociatedEndpointClosed(InterfaceId id) {
}
bool MultiplexRouter::OnAssociatedEndpointClosedBeforeSent(InterfaceId id) {
- lock_.AssertAcquired();
+ AssertLockAcquired();
if (IsMasterInterfaceId(id))
return false;
@@ -560,7 +605,7 @@ void MultiplexRouter::OnPipeConnectionError() {
DCHECK(thread_checker_.CalledOnValidThread());
scoped_refptr<MultiplexRouter> protector(this);
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
encountered_error_ = true;
@@ -585,20 +630,20 @@ void MultiplexRouter::OnPipeConnectionError() {
void MultiplexRouter::ProcessTasks(
ClientCallBehavior client_call_behavior,
base::SingleThreadTaskRunner* current_task_runner) {
- lock_.AssertAcquired();
+ AssertLockAcquired();
if (posted_to_process_tasks_)
return;
- while (!tasks_.empty()) {
+ while (!tasks_.empty() && !paused_) {
std::unique_ptr<Task> task(std::move(tasks_.front()));
tasks_.pop_front();
InterfaceId id = kInvalidInterfaceId;
- bool sync_message = task->IsMessageTask() && task->message &&
- task->message->has_flag(Message::kFlagIsSync);
+ bool sync_message = task->IsMessageTask() && !task->message.IsNull() &&
+ task->message.has_flag(Message::kFlagIsSync);
if (sync_message) {
- id = task->message->interface_id();
+ id = task->message.interface_id();
auto& sync_message_queue = sync_message_tasks_[id];
DCHECK_EQ(task.get(), sync_message_queue.front());
sync_message_queue.pop_front();
@@ -608,7 +653,7 @@ void MultiplexRouter::ProcessTasks(
task->IsNotifyErrorTask()
? ProcessNotifyErrorTask(task.get(), client_call_behavior,
current_task_runner)
- : ProcessIncomingMessage(task->message.get(), client_call_behavior,
+ : ProcessIncomingMessage(&task->message, client_call_behavior,
current_task_runner);
if (!processed) {
@@ -629,21 +674,24 @@ void MultiplexRouter::ProcessTasks(
}
bool MultiplexRouter::ProcessFirstSyncMessageForEndpoint(InterfaceId id) {
- lock_.AssertAcquired();
+ AssertLockAcquired();
auto iter = sync_message_tasks_.find(id);
if (iter == sync_message_tasks_.end())
return false;
+ if (paused_)
+ return true;
+
MultiplexRouter::Task* task = iter->second.front();
iter->second.pop_front();
DCHECK(task->IsMessageTask());
- std::unique_ptr<Message> message(std::move(task->message));
+ Message message = std::move(task->message);
- // Note: after this call, |task| and |iter| may be invalidated.
+ // Note: after this call, |task| and |iter| may be invalidated.
bool processed = ProcessIncomingMessage(
- message.get(), ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES, nullptr);
+ &message, ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES, nullptr);
DCHECK(processed);
iter = sync_message_tasks_.find(id);
@@ -663,7 +711,9 @@ bool MultiplexRouter::ProcessNotifyErrorTask(
ClientCallBehavior client_call_behavior,
base::SingleThreadTaskRunner* current_task_runner) {
DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread());
- lock_.AssertAcquired();
+ DCHECK(!paused_);
+
+ AssertLockAcquired();
InterfaceEndpoint* endpoint = task->endpoint_to_notify.get();
if (!endpoint->client())
return true;
@@ -683,7 +733,7 @@ bool MultiplexRouter::ProcessNotifyErrorTask(
//
// It is safe to call into |client| without the lock. Because |client| is
// always accessed on the same thread, including DetachEndpointClient().
- base::AutoUnlock unlocker(lock_);
+ MayAutoUnlock unlocker(lock_.get());
client->NotifyError();
}
return true;
@@ -694,9 +744,11 @@ bool MultiplexRouter::ProcessIncomingMessage(
ClientCallBehavior client_call_behavior,
base::SingleThreadTaskRunner* current_task_runner) {
DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread());
- lock_.AssertAcquired();
+ DCHECK(!paused_);
+ DCHECK(message);
+ AssertLockAcquired();
- if (!message) {
+ if (message->IsNull()) {
// This is a sync message and has been processed during sync handle
// watching.
return true;
@@ -768,7 +820,7 @@ bool MultiplexRouter::ProcessIncomingMessage(
//
// It is safe to call into |client| without the lock. Because |client| is
// always accessed on the same thread, including DetachEndpointClient().
- base::AutoUnlock unlocker(lock_);
+ MayAutoUnlock unlocker(lock_.get());
result = client->HandleIncomingMessage(message);
}
if (!result)
@@ -779,7 +831,7 @@ bool MultiplexRouter::ProcessIncomingMessage(
void MultiplexRouter::MaybePostToProcessTasks(
base::SingleThreadTaskRunner* task_runner) {
- lock_.AssertAcquired();
+ AssertLockAcquired();
if (posted_to_process_tasks_)
return;
@@ -792,7 +844,7 @@ void MultiplexRouter::MaybePostToProcessTasks(
void MultiplexRouter::LockAndCallProcessTasks() {
// There is no need to hold a ref to this class in this case because this is
// always called using base::Bind(), which holds a ref.
- base::AutoLock locker(lock_);
+ MayAutoLock locker(lock_.get());
posted_to_process_tasks_ = false;
scoped_refptr<base::SingleThreadTaskRunner> runner(
std::move(posted_to_task_runner_));
@@ -818,7 +870,7 @@ void MultiplexRouter::UpdateEndpointStateMayRemove(
}
void MultiplexRouter::RaiseErrorInNonTestingMode() {
- lock_.AssertAcquired();
+ AssertLockAcquired();
if (!testing_mode_)
RaiseError();
}
@@ -826,7 +878,7 @@ void MultiplexRouter::RaiseErrorInNonTestingMode() {
MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint(
InterfaceId id,
bool* inserted) {
- lock_.AssertAcquired();
+ AssertLockAcquired();
// Either |inserted| is nullptr or it points to a boolean initialized as
// false.
DCHECK(!inserted || !*inserted);
@@ -845,5 +897,12 @@ MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint(
return endpoint;
}
+void MultiplexRouter::AssertLockAcquired() {
+#if DCHECK_IS_ON()
+ if (lock_)
+ lock_->AssertAcquired();
+#endif
+}
+
} // namespace internal
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h
index dc66e8ee832..6ecae85b6ef 100644
--- a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h
+++ b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -12,6 +12,7 @@
#include <memory>
#include <string>
+#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -20,7 +21,9 @@
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "mojo/public/cpp/bindings/associated_group_controller.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/connector.h"
+#include "mojo/public/cpp/bindings/filter_chain.h"
#include "mojo/public/cpp/bindings/interface_id.h"
#include "mojo/public/cpp/bindings/message_header_validator.h"
#include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
@@ -47,15 +50,33 @@ namespace internal {
// Some public methods are only allowed to be called on the creating thread;
// while the others are safe to call from any threads. Please see the method
// comments for more details.
-class MultiplexRouter
- : public MessageReceiver,
+//
+// NOTE: CloseMessagePipe() or PassMessagePipe() MUST be called on |runner|'s
+// thread before this object is destroyed.
+class MOJO_CPP_BINDINGS_EXPORT MultiplexRouter
+ : NON_EXPORTED_BASE(public MessageReceiver),
public AssociatedGroupController,
- public PipeControlMessageHandlerDelegate {
+ NON_EXPORTED_BASE(public PipeControlMessageHandlerDelegate) {
public:
+ enum Config {
+ // There is only the master interface running on this router. Please note
+ // that because of interface versioning, the other side of the message pipe
+ // may use a newer master interface definition which passes associated
+ // interfaces. In that case, this router may still receive pipe control
+ // messages or messages targetting associated interfaces.
+ SINGLE_INTERFACE,
+ // Similar to the mode above, there is only the master interface running on
+ // this router. Besides, the master interface has sync methods.
+ SINGLE_INTERFACE_WITH_SYNC_METHODS,
+ // There may be associated interfaces running on this router.
+ MULTI_INTERFACE
+ };
+
// If |set_interface_id_namespace_bit| is true, the interface IDs generated by
// this router will have the highest bit set.
- MultiplexRouter(bool set_interface_id_namespace_bit,
- ScopedMessagePipeHandle message_pipe,
+ MultiplexRouter(ScopedMessagePipeHandle message_pipe,
+ Config config,
+ bool set_interface_id_namespace_bit,
scoped_refptr<base::SingleThreadTaskRunner> runner);
// Sets the master interface name for this router. Only used when reporting
@@ -102,14 +123,8 @@ class MultiplexRouter
}
// See Binding for details of pause/resume.
- void PauseIncomingMethodCallProcessing() {
- DCHECK(thread_checker_.CalledOnValidThread());
- connector_.PauseIncomingMethodCallProcessing();
- }
- void ResumeIncomingMethodCallProcessing() {
- DCHECK(thread_checker_.CalledOnValidThread());
- connector_.ResumeIncomingMethodCallProcessing();
- }
+ void PauseIncomingMethodCallProcessing();
+ void ResumeIncomingMethodCallProcessing();
// Whether there are any associated interfaces running currently.
bool HasAssociatedEndpoints() const;
@@ -131,6 +146,10 @@ class MultiplexRouter
return connector_.handle();
}
+ bool SimulateReceivingMessageForTesting(Message* message) {
+ return filters_.Accept(message);
+ }
+
private:
class InterfaceEndpoint;
struct Task;
@@ -203,17 +222,25 @@ class MultiplexRouter
InterfaceEndpoint* FindOrInsertEndpoint(InterfaceId id, bool* inserted);
+ void AssertLockAcquired();
+
// Whether to set the namespace bit when generating interface IDs. Please see
// comments of kInterfaceIdNamespaceMask.
const bool set_interface_id_namespace_bit_;
- MessageHeaderValidator header_validator_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ // Owned by |filters_| below.
+ MessageHeaderValidator* header_validator_;
+
+ FilterChain filters_;
Connector connector_;
base::ThreadChecker thread_checker_;
// Protects the following members.
- mutable base::Lock lock_;
+ // Sets to nullptr in Config::SINGLE_INTERFACE* mode.
+ std::unique_ptr<base::Lock> lock_;
PipeControlMessageHandler control_message_handler_;
PipeControlMessageProxy control_message_proxy_;
@@ -229,6 +256,8 @@ class MultiplexRouter
bool encountered_error_;
+ bool paused_;
+
bool testing_mode_;
DISALLOW_COPY_AND_ASSIGN(MultiplexRouter);
diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct.cc b/chromium/mojo/public/cpp/bindings/lib/native_struct.cc
index 837b75a60e3..2d60eb0d7e2 100644
--- a/chromium/mojo/public/cpp/bindings/lib/native_struct.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/native_struct.cc
@@ -4,6 +4,8 @@
#include "mojo/public/cpp/bindings/native_struct.h"
+#include "mojo/public/cpp/bindings/lib/hash_util.h"
+
namespace mojo {
// static
@@ -27,4 +29,8 @@ bool NativeStruct::Equals(const NativeStruct& other) const {
return data.Equals(other.data);
}
+size_t NativeStruct::Hash(size_t seed) const {
+ return internal::Hash(seed, data);
+}
+
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct_data.h b/chromium/mojo/public/cpp/bindings/lib/native_struct_data.h
index 984feec8b15..e4f3aaf028f 100644
--- a/chromium/mojo/public/cpp/bindings/lib/native_struct_data.h
+++ b/chromium/mojo/public/cpp/bindings/lib/native_struct_data.h
@@ -7,6 +7,7 @@
#include <vector>
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/system/handle.h"
@@ -16,13 +17,10 @@ namespace internal {
class Buffer;
class ValidationContext;
-class NativeStruct_Data {
+class MOJO_CPP_BINDINGS_EXPORT NativeStruct_Data {
public:
static bool Validate(const void* data, ValidationContext* validation_context);
- void EncodePointers() {}
- void DecodePointers() {}
-
// Unlike normal structs, the memory layout is exactly the same as an array
// of uint8_t.
Array_Data<uint8_t> data;
diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.cc b/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.cc
index ac06059e428..fa0dbf38034 100644
--- a/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.cc
@@ -15,7 +15,8 @@ size_t UnmappedNativeStructSerializerImpl::PrepareToSerialize(
SerializationContext* context) {
if (!input)
return 0;
- return internal::PrepareToSerialize<Array<uint8_t>>(input->data, context);
+ return internal::PrepareToSerialize<ArrayDataView<uint8_t>>(input->data,
+ context);
}
// static
@@ -31,8 +32,8 @@ void UnmappedNativeStructSerializerImpl::Serialize(
Array_Data<uint8_t>* data = nullptr;
const ContainerValidateParams params(0, false, nullptr);
- internal::Serialize<Array<uint8_t>>(input->data, buffer, &data, &params,
- context);
+ internal::Serialize<ArrayDataView<uint8_t>>(input->data, buffer, &data,
+ &params, context);
*output = reinterpret_cast<NativeStruct_Data*>(data);
}
@@ -44,7 +45,8 @@ bool UnmappedNativeStructSerializerImpl::Deserialize(
Array_Data<uint8_t>* data = reinterpret_cast<Array_Data<uint8_t>*>(input);
NativeStructPtr result(NativeStruct::New());
- if (!internal::Deserialize<Array<uint8_t>>(data, &result->data, context)) {
+ if (!internal::Deserialize<ArrayDataView<uint8_t>>(data, &result->data,
+ context)) {
output = nullptr;
return false;
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.h b/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.h
index e64b862b6c1..457435b9558 100644
--- a/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.h
+++ b/chromium/mojo/public/cpp/bindings/lib/native_struct_serialization.h
@@ -13,12 +13,14 @@
#include "base/logging.h"
#include "base/pickle.h"
#include "ipc/ipc_param_traits.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/native_struct_data.h"
#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
#include "mojo/public/cpp/bindings/lib/serialization_util.h"
#include "mojo/public/cpp/bindings/native_struct.h"
+#include "mojo/public/cpp/bindings/native_struct_data_view.h"
namespace mojo {
namespace internal {
@@ -102,7 +104,7 @@ struct NativeStructSerializerImpl {
}
};
-struct UnmappedNativeStructSerializerImpl {
+struct MOJO_CPP_BINDINGS_EXPORT UnmappedNativeStructSerializerImpl {
static size_t PrepareToSerialize(const NativeStructPtr& input,
SerializationContext* context);
static void Serialize(const NativeStructPtr& input,
@@ -123,7 +125,7 @@ struct NativeStructSerializerImpl<const NativeStructPtr>
: public UnmappedNativeStructSerializerImpl {};
template <typename MaybeConstUserType>
-struct Serializer<NativeStructPtr, MaybeConstUserType>
+struct Serializer<NativeStructDataView, MaybeConstUserType>
: public NativeStructSerializerImpl<MaybeConstUserType> {};
} // namespace internal
diff --git a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
index 616d0d783b8..39b31635a3d 100644
--- a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
@@ -62,10 +62,8 @@ bool PipeControlMessageHandler::RunOrClosePipe(Message* message) {
reinterpret_cast<
pipe_control::internal::RunOrClosePipeMessageParams_Data*>(
message->mutable_payload());
- params->DecodePointers();
-
pipe_control::RunOrClosePipeMessageParamsPtr params_ptr;
- internal::Deserialize<pipe_control::RunOrClosePipeMessageParamsPtr>(
+ internal::Deserialize<pipe_control::RunOrClosePipeMessageParamsDataView>(
params, &params_ptr, &context_);
if (params_ptr->input->is_peer_associated_endpoint_closed_event()) {
diff --git a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
index 7a160ff7183..c1508ae3374 100644
--- a/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
@@ -24,16 +24,14 @@ void SendRunOrClosePipeMessage(MessageReceiver* receiver,
pipe_control::RunOrClosePipeMessageParams::New());
params_ptr->input = std::move(input);
- size_t size =
- internal::PrepareToSerialize<
- pipe_control::RunOrClosePipeMessageParamsPtr>(params_ptr, context);
+ size_t size = internal::PrepareToSerialize<
+ pipe_control::RunOrClosePipeMessageParamsDataView>(params_ptr, context);
internal::MessageBuilder builder(pipe_control::kRunOrClosePipeMessageId,
size);
pipe_control::internal::RunOrClosePipeMessageParams_Data* params = nullptr;
- internal::Serialize<pipe_control::RunOrClosePipeMessageParamsPtr>(
+ internal::Serialize<pipe_control::RunOrClosePipeMessageParamsDataView>(
params_ptr, builder.buffer(), &params, context);
- params->EncodePointers();
builder.message()->set_interface_id(kInvalidInterfaceId);
bool ok = receiver->Accept(builder.message());
// This return value may be ignored as !ok implies the underlying message pipe
diff --git a/chromium/mojo/public/cpp/bindings/lib/router.cc b/chromium/mojo/public/cpp/bindings/lib/router.cc
index 8c1b77d5647..8db5c1bbe4c 100644
--- a/chromium/mojo/public/cpp/bindings/lib/router.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/router.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
+#include "mojo/public/cpp/bindings/lib/validation_util.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
namespace mojo {
@@ -118,7 +119,8 @@ bool Router::HandleIncomingMessageThunk::Accept(Message* message) {
Router::Router(ScopedMessagePipeHandle message_pipe,
FilterChain filters,
bool expects_sync_requests,
- scoped_refptr<base::SingleThreadTaskRunner> runner)
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
+ int interface_version)
: thunk_(this),
filters_(std::move(filters)),
connector_(std::move(message_pipe),
@@ -129,17 +131,23 @@ Router::Router(ScopedMessagePipeHandle message_pipe,
testing_mode_(false),
pending_task_for_messages_(false),
encountered_error_(false),
+ control_message_proxy_(this),
+ control_message_handler_(interface_version),
weak_factory_(this) {
filters_.SetSink(&thunk_);
if (expects_sync_requests)
connector_.AllowWokenUpBySyncWatchOnSameThread();
- connector_.set_incoming_receiver(filters_.GetHead());
+ connector_.set_incoming_receiver(&filters_);
connector_.set_connection_error_handler(
base::Bind(&Router::OnConnectionError, base::Unretained(this)));
}
Router::~Router() {}
+void Router::AddFilter(std::unique_ptr<MessageReceiver> filter) {
+ filters_.Append(std::move(filter));
+}
+
bool Router::Accept(Message* message) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!message->has_flag(Message::kFlagExpectsResponse));
@@ -171,19 +179,17 @@ bool Router::AcceptWithResponder(Message* message, MessageReceiver* responder) {
bool response_received = false;
std::unique_ptr<MessageReceiver> sync_responder(responder);
sync_responses_.insert(std::make_pair(
- request_id, base::WrapUnique(new SyncResponseInfo(&response_received))));
+ request_id, base::MakeUnique<SyncResponseInfo>(&response_received)));
base::WeakPtr<Router> weak_self = weak_factory_.GetWeakPtr();
connector_.SyncWatch(&response_received);
// Make sure that this instance hasn't been destroyed.
if (weak_self) {
- DCHECK(ContainsKey(sync_responses_, request_id));
+ DCHECK(base::ContainsKey(sync_responses_, request_id));
auto iter = sync_responses_.find(request_id);
DCHECK_EQ(&response_received, iter->second->response_received);
- if (response_received) {
- std::unique_ptr<Message> response = std::move(iter->second->response);
- ignore_result(sync_responder->Accept(response.get()));
- }
+ if (response_received)
+ ignore_result(sync_responder->Accept(&iter->second->response));
sync_responses_.erase(iter);
}
@@ -204,9 +210,7 @@ bool Router::HandleIncomingMessage(Message* message) {
connector_.during_sync_handle_watcher_callback();
if (!message->has_flag(Message::kFlagIsSync) &&
(during_sync_call || !pending_messages_.empty())) {
- std::unique_ptr<Message> pending_message(new Message);
- message->MoveTo(pending_message.get());
- pending_messages_.push(std::move(pending_message));
+ pending_messages_.emplace(std::move(*message));
if (!pending_task_for_messages_) {
pending_task_for_messages_ = true;
@@ -227,10 +231,10 @@ void Router::HandleQueuedMessages() {
base::WeakPtr<Router> weak_self = weak_factory_.GetWeakPtr();
while (!pending_messages_.empty()) {
- std::unique_ptr<Message> message(std::move(pending_messages_.front()));
+ Message message(std::move(pending_messages_.front()));
pending_messages_.pop();
- bool result = HandleMessageInternal(message.get());
+ bool result = HandleMessageInternal(&message);
if (!weak_self)
return;
@@ -250,13 +254,17 @@ void Router::HandleQueuedMessages() {
}
bool Router::HandleMessageInternal(Message* message) {
- if (message->has_flag(Message::kFlagExpectsResponse)) {
- if (!incoming_receiver_)
- return false;
+ DCHECK(!encountered_error_);
+ if (message->has_flag(Message::kFlagExpectsResponse)) {
MessageReceiverWithStatus* responder = new ResponderThunk(
weak_factory_.GetWeakPtr(), connector_.task_runner());
- bool ok = incoming_receiver_->AcceptWithResponder(message, responder);
+ bool ok = false;
+ if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) {
+ ok = control_message_handler_.AcceptWithResponder(message, responder);
+ } else {
+ ok = incoming_receiver_->AcceptWithResponder(message, responder);
+ }
if (!ok)
delete responder;
return ok;
@@ -270,8 +278,7 @@ bool Router::HandleMessageInternal(Message* message) {
DCHECK(testing_mode_);
return false;
}
- it->second->response.reset(new Message());
- message->MoveTo(it->second->response.get());
+ it->second->response = std::move(*message);
*it->second->response_received = true;
return true;
}
@@ -285,8 +292,8 @@ bool Router::HandleMessageInternal(Message* message) {
async_responders_.erase(it);
return responder->Accept(message);
} else {
- if (!incoming_receiver_)
- return false;
+ if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
+ return control_message_handler_.Accept(message);
return incoming_receiver_->Accept(message);
}
@@ -312,9 +319,24 @@ void Router::OnConnectionError() {
return;
}
+ control_message_proxy_.OnConnectionError();
+
encountered_error_ = true;
- if (!error_handler_.is_null())
+
+ // The callbacks may hold on to resources. There is no need to keep them any
+ // longer.
+ async_responders_.clear();
+
+ if (!error_handler_.is_null()) {
error_handler_.Run();
+ } else if (!error_with_reason_handler_.is_null()) {
+ // Make a copy on the stack. If we directly pass a reference to a member of
+ // |control_message_handler_|, that reference will be invalidated as soon as
+ // the user destroys the interface endpoint.
+ std::string description = control_message_handler_.disconnect_description();
+ error_with_reason_handler_.Run(
+ control_message_handler_.disconnect_custom_reason(), description);
+ }
}
// ----------------------------------------------------------------------------
diff --git a/chromium/mojo/public/cpp/bindings/lib/router.h b/chromium/mojo/public/cpp/bindings/lib/router.h
index 6dbe08d5b20..d07bfeedf02 100644
--- a/chromium/mojo/public/cpp/bindings/lib/router.h
+++ b/chromium/mojo/public/cpp/bindings/lib/router.h
@@ -12,25 +12,33 @@
#include <queue>
#include "base/callback.h"
+#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
#include "mojo/public/cpp/bindings/connector.h"
-#include "mojo/public/cpp/bindings/lib/filter_chain.h"
+#include "mojo/public/cpp/bindings/filter_chain.h"
+#include "mojo/public/cpp/bindings/lib/control_message_handler.h"
+#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
+#include "mojo/public/cpp/bindings/message.h"
namespace mojo {
namespace internal {
// TODO(yzshen): Consider removing this class and use MultiplexRouter in all
// cases. crbug.com/594244
-class Router : public MessageReceiverWithResponder {
+class MOJO_CPP_BINDINGS_EXPORT Router
+ : NON_EXPORTED_BASE(public MessageReceiverWithResponder) {
public:
Router(ScopedMessagePipeHandle message_pipe,
FilterChain filters,
bool expects_sync_requests,
- scoped_refptr<base::SingleThreadTaskRunner> runner);
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
+ int interface_version);
~Router() override;
// Sets the receiver to handle messages read from the message pipe that do
@@ -43,6 +51,12 @@ class Router : public MessageReceiverWithResponder {
// encountered while reading from the pipe or waiting to read from the pipe.
void set_connection_error_handler(const base::Closure& error_handler) {
error_handler_ = error_handler;
+ error_with_reason_handler_.Reset();
+ }
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ error_with_reason_handler_ = error_handler;
+ error_handler_.Reset();
}
// Returns true if an error was encountered while reading from the pipe or
@@ -58,6 +72,8 @@ class Router : public MessageReceiverWithResponder {
return connector_.is_valid();
}
+ void AddFilter(std::unique_ptr<MessageReceiver> filter);
+
// Please note that this method shouldn't be called unless it results from an
// explicit request of the user of bindings (e.g., the user sets an
// InterfacePtr to null or closes a Binding).
@@ -89,6 +105,8 @@ class Router : public MessageReceiverWithResponder {
}
// See Binding for details of pause/resume.
+ // Note: This doesn't strictly pause incoming calls. If there are
+ // queued messages, they may be dispatched during pause.
void PauseIncomingMethodCallProcessing() {
DCHECK(thread_checker_.CalledOnValidThread());
connector_.PauseIncomingMethodCallProcessing();
@@ -113,6 +131,14 @@ class Router : public MessageReceiverWithResponder {
return !async_responders_.empty() || !sync_responses_.empty();
}
+ ControlMessageProxy* control_message_proxy() {
+ return &control_message_proxy_;
+ }
+
+ bool SimulateReceivingMessageForTesting(Message* message) {
+ return filters_.Accept(message);
+ }
+
private:
// Maps from the id of a response to the MessageReceiver that handles the
// response.
@@ -124,7 +150,7 @@ class Router : public MessageReceiverWithResponder {
explicit SyncResponseInfo(bool* in_response_received);
~SyncResponseInfo();
- std::unique_ptr<Message> response;
+ Message response;
// Points to a stack-allocated variable.
bool* response_received;
@@ -161,12 +187,15 @@ class Router : public MessageReceiverWithResponder {
SyncResponseMap sync_responses_;
uint64_t next_request_id_;
bool testing_mode_;
- std::queue<std::unique_ptr<Message>> pending_messages_;
+ std::queue<Message> pending_messages_;
// Whether a task has been posted to trigger processing of
// |pending_messages_|.
bool pending_task_for_messages_;
bool encountered_error_;
base::Closure error_handler_;
+ ConnectionErrorWithReasonCallback error_with_reason_handler_;
+ ControlMessageProxy control_message_proxy_;
+ ControlMessageHandler control_message_handler_;
base::ThreadChecker thread_checker_;
base::WeakPtrFactory<Router> weak_factory_;
};
diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization.h b/chromium/mojo/public/cpp/bindings/lib/serialization.h
index fe2c16a9943..a570e2205bf 100644
--- a/chromium/mojo/public/cpp/bindings/lib/serialization.h
+++ b/chromium/mojo/public/cpp/bindings/lib/serialization.h
@@ -11,7 +11,7 @@
#include "mojo/public/cpp/bindings/array_traits_standard.h"
#include "mojo/public/cpp/bindings/array_traits_stl.h"
#include "mojo/public/cpp/bindings/lib/array_serialization.h"
-#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
+#include "mojo/public/cpp/bindings/lib/buffer.h"
#include "mojo/public/cpp/bindings/lib/handle_interface_serialization.h"
#include "mojo/public/cpp/bindings/lib/map_serialization.h"
#include "mojo/public/cpp/bindings/lib/native_enum_serialization.h"
@@ -53,13 +53,11 @@ DataArrayType StructSerializeImpl(UserType* input) {
DCHECK(IsAligned(result_buffer));
}
- FixedBuffer buffer;
+ Buffer buffer;
buffer.Initialize(result_buffer, size);
- typename MojomType::Struct::Data_* data = nullptr;
+ typename MojomTypeTraits<MojomType>::Data* data = nullptr;
Serialize<MojomType>(*input, &buffer, &data, &context);
- data->EncodePointers();
-
if (need_copy) {
memcpy(&result.front(), result_buffer, size);
free(result_buffer);
@@ -69,15 +67,18 @@ DataArrayType StructSerializeImpl(UserType* input) {
}
template <typename MojomType, typename DataArrayType, typename UserType>
-bool StructDeserializeImpl(DataArrayType input, UserType* output) {
+bool StructDeserializeImpl(const DataArrayType& input, UserType* output) {
static_assert(BelongsTo<MojomType, MojomTypeCategory::STRUCT>::value,
"Unexpected type.");
- using DataType = typename MojomType::Struct::Data_;
+ using DataType = typename MojomTypeTraits<MojomType>::Data;
if (input.is_null())
return false;
- void* input_buffer = input.empty() ? nullptr : &input.front();
+ void* input_buffer =
+ input.empty()
+ ? nullptr
+ : const_cast<void*>(reinterpret_cast<const void*>(&input.front()));
// Please see comments in StructSerializeImpl.
bool need_copy = !IsAligned(input_buffer);
@@ -92,9 +93,6 @@ bool StructDeserializeImpl(DataArrayType input, UserType* output) {
bool result = false;
if (DataType::Validate(input_buffer, &validation_context)) {
auto data = reinterpret_cast<DataType*>(input_buffer);
- if (data)
- data->DecodePointers();
-
SerializationContext context;
result = Deserialize<MojomType>(data, output, &context);
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_context.h b/chromium/mojo/public/cpp/bindings/lib/serialization_context.h
index 64d2a1a4e2c..4bded307ee8 100644
--- a/chromium/mojo/public/cpp/bindings/lib/serialization_context.h
+++ b/chromium/mojo/public/cpp/bindings/lib/serialization_context.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/system/handle.h"
@@ -23,7 +24,7 @@ class AssociatedGroupController;
namespace internal {
// A container for handles during serialization/deserialization.
-class SerializedHandleVector {
+class MOJO_CPP_BINDINGS_EXPORT SerializedHandleVector {
public:
SerializedHandleVector();
~SerializedHandleVector();
@@ -54,7 +55,7 @@ class SerializedHandleVector {
};
// Context information for serialization/deserialization routines.
-struct SerializationContext {
+struct MOJO_CPP_BINDINGS_EXPORT SerializationContext {
SerializationContext();
explicit SerializationContext(
scoped_refptr<AssociatedGroupController> in_group_controller);
diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_forward.h b/chromium/mojo/public/cpp/bindings/lib/serialization_forward.h
index 7f73932c85f..55c9982cccc 100644
--- a/chromium/mojo/public/cpp/bindings/lib/serialization_forward.h
+++ b/chromium/mojo/public/cpp/bindings/lib/serialization_forward.h
@@ -5,11 +5,14 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_
+#include "base/optional.h"
#include "mojo/public/cpp/bindings/array_traits.h"
#include "mojo/public/cpp/bindings/enum_traits.h"
+#include "mojo/public/cpp/bindings/lib/template_util.h"
#include "mojo/public/cpp/bindings/map_traits.h"
#include "mojo/public/cpp/bindings/string_traits.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "mojo/public/cpp/bindings/union_traits.h"
// This file is included by serialization implementation files to avoid circular
// includes.
@@ -22,11 +25,23 @@ namespace internal {
template <typename MojomType, typename MaybeConstUserType>
struct Serializer;
+template <typename T>
+struct IsOptionalWrapper {
+ static const bool value = IsSpecializationOf<
+ base::Optional,
+ typename std::remove_const<
+ typename std::remove_reference<T>::type>::type>::value;
+};
+
// PrepareToSerialize() must be matched by a Serialize() for the same input
// later. Moreover, within the same SerializationContext if PrepareToSerialize()
// is called for |input_1|, ..., |input_n|, Serialize() must be called for
// those objects in the exact same order.
-template <typename MojomType, typename InputUserType, typename... Args>
+template <typename MojomType,
+ typename InputUserType,
+ typename... Args,
+ typename std::enable_if<
+ !IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
size_t PrepareToSerialize(InputUserType&& input, Args&&... args) {
return Serializer<MojomType,
typename std::remove_reference<InputUserType>::type>::
@@ -34,7 +49,11 @@ size_t PrepareToSerialize(InputUserType&& input, Args&&... args) {
std::forward<Args>(args)...);
}
-template <typename MojomType, typename InputUserType, typename... Args>
+template <typename MojomType,
+ typename InputUserType,
+ typename... Args,
+ typename std::enable_if<
+ !IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
void Serialize(InputUserType&& input, Args&&... args) {
Serializer<MojomType, typename std::remove_reference<InputUserType>::type>::
Serialize(std::forward<InputUserType>(input),
@@ -44,12 +63,60 @@ void Serialize(InputUserType&& input, Args&&... args) {
template <typename MojomType,
typename DataType,
typename InputUserType,
- typename... Args>
+ typename... Args,
+ typename std::enable_if<
+ !IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) {
return Serializer<MojomType, InputUserType>::Deserialize(
std::forward<DataType>(input), output, std::forward<Args>(args)...);
}
+// Specialization that unwraps base::Optional<>.
+template <typename MojomType,
+ typename InputUserType,
+ typename... Args,
+ typename std::enable_if<
+ IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
+size_t PrepareToSerialize(InputUserType&& input, Args&&... args) {
+ if (!input)
+ return 0;
+ return PrepareToSerialize<MojomType>(*input, std::forward<Args>(args)...);
+}
+
+template <typename MojomType,
+ typename InputUserType,
+ typename DataType,
+ typename... Args,
+ typename std::enable_if<
+ IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
+void Serialize(InputUserType&& input,
+ Buffer* buffer,
+ DataType** output,
+ Args&&... args) {
+ if (!input) {
+ *output = nullptr;
+ return;
+ }
+ Serialize<MojomType>(*input, buffer, output, std::forward<Args>(args)...);
+}
+
+template <typename MojomType,
+ typename DataType,
+ typename InputUserType,
+ typename... Args,
+ typename std::enable_if<
+ IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
+bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) {
+ if (!input) {
+ *output = base::nullopt;
+ return true;
+ }
+ if (!*output)
+ output->emplace();
+ return Deserialize<MojomType>(std::forward<DataType>(input), &output->value(),
+ std::forward<Args>(args)...);
+}
+
} // namespace internal
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_util.cc b/chromium/mojo/public/cpp/bindings/lib/serialization_util.cc
deleted file mode 100644
index d672243b779..00000000000
--- a/chromium/mojo/public/cpp/bindings/lib/serialization_util.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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/serialization_util.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);
- DCHECK(p_obj > p_slot);
-
- *offset = static_cast<uint64_t>(p_obj - p_slot);
-}
-
-const void* DecodePointerRaw(const uint64_t* offset) {
- if (!*offset)
- return nullptr;
- return reinterpret_cast<const char*>(offset) + *offset;
-}
-
-} // namespace internal
-} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/serialization_util.h b/chromium/mojo/public/cpp/bindings/lib/serialization_util.h
index 523f4842c36..4820a014ec1 100644
--- a/chromium/mojo/public/cpp/bindings/lib/serialization_util.h
+++ b/chromium/mojo/public/cpp/bindings/lib/serialization_util.h
@@ -12,95 +12,12 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
-#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/serialization_context.h"
-#include "mojo/public/cpp/system/handle.h"
namespace mojo {
-
-class AssociatedGroupController;
-
namespace internal {
-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)));
-}
-
-// 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) {
- if (obj->ptr)
- obj->ptr->EncodePointers();
- 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) {
- DecodePointer(&obj->offset, &obj->ptr);
- if (obj->ptr)
- obj->ptr->DecodePointers();
-}
-
-template <typename T>
-inline void AssociatedInterfacePtrInfoToData(
- AssociatedInterfacePtrInfo<T> input,
- AssociatedInterface_Data* output) {
- output->version = input.version();
- output->interface_id = input.PassHandle().release();
-}
-
-template <typename T>
-inline void AssociatedInterfaceDataToPtrInfo(
- AssociatedInterface_Data* input,
- AssociatedInterfacePtrInfo<T>* output,
- AssociatedGroupController* group_controller) {
- output->set_handle(group_controller->CreateLocalEndpointHandle(
- FetchAndReset(&input->interface_id)));
- output->set_version(input->version);
-}
-
-template <typename T>
-inline void InterfacePointerToData(InterfacePtr<T> input,
- Interface_Data* output,
- SerializationContext* context) {
- InterfacePtrInfo<T> info = input.PassInterface();
- output->handle = context->handles.AddHandle(info.PassHandle().release());
- output->version = info.version();
-}
-
-template <typename T>
-inline void InterfaceDataToPointer(Interface_Data* input,
- InterfacePtr<T>* output,
- SerializationContext* context) {
- output->Bind(InterfacePtrInfo<T>(
- context->handles.TakeHandleAs<mojo::MessagePipeHandle>(input->handle),
- input->version));
-}
-
template <typename T>
struct HasIsNullMethod {
template <typename U>
diff --git a/chromium/mojo/public/cpp/bindings/lib/string_serialization.h b/chromium/mojo/public/cpp/bindings/lib/string_serialization.h
index 5e65891ef5e..6e0c7585769 100644
--- a/chromium/mojo/public/cpp/bindings/lib/string_serialization.h
+++ b/chromium/mojo/public/cpp/bindings/lib/string_serialization.h
@@ -11,14 +11,14 @@
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
#include "mojo/public/cpp/bindings/lib/serialization_util.h"
-#include "mojo/public/cpp/bindings/string.h"
+#include "mojo/public/cpp/bindings/string_data_view.h"
#include "mojo/public/cpp/bindings/string_traits.h"
namespace mojo {
namespace internal {
template <typename MaybeConstUserType>
-struct Serializer<String, MaybeConstUserType> {
+struct Serializer<StringDataView, MaybeConstUserType> {
using UserType = typename std::remove_const<MaybeConstUserType>::type;
using Traits = StringTraits<UserType>;
@@ -60,7 +60,7 @@ struct Serializer<String, MaybeConstUserType> {
SerializationContext* context) {
if (!input)
return CallSetToNullIfExists<Traits>(output);
- return Traits::Read(StringDataView(input), output);
+ return Traits::Read(StringDataView(input, context), output);
}
};
diff --git a/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc b/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc
index 19fa9074483..203f6f59032 100644
--- a/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/string_traits_wtf.cc
@@ -16,7 +16,7 @@ namespace {
struct UTF8AdaptorInfo {
explicit UTF8AdaptorInfo(const WTF::String& input) : utf8_adaptor(input) {
#if DCHECK_IS_ON()
- original_size_in_bytes = static_cast<size_t>(input.sizeInBytes());
+ original_size_in_bytes = input.charactersSizeInBytes();
#endif
}
@@ -34,8 +34,7 @@ UTF8AdaptorInfo* ToAdaptor(const WTF::String& input, void* context) {
UTF8AdaptorInfo* adaptor = static_cast<UTF8AdaptorInfo*>(context);
#if DCHECK_IS_ON()
- DCHECK_EQ(adaptor->original_size_in_bytes,
- static_cast<size_t>(input.sizeInBytes()));
+ DCHECK_EQ(adaptor->original_size_in_bytes, input.charactersSizeInBytes());
#endif
return adaptor;
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
index f6372d9eb51..cc831371757 100644
--- a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
@@ -34,7 +34,7 @@ bool SyncHandleRegistry::RegisterHandle(const Handle& handle,
const HandleCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (ContainsKey(handles_, handle))
+ if (base::ContainsKey(handles_, handle))
return false;
MojoResult result = MojoAddHandle(wait_set_handle_.get().value(),
@@ -48,7 +48,7 @@ bool SyncHandleRegistry::RegisterHandle(const Handle& handle,
void SyncHandleRegistry::UnregisterHandle(const Handle& handle) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (!ContainsKey(handles_, handle))
+ if (!base::ContainsKey(handles_, handle))
return;
MojoResult result =
@@ -107,6 +107,11 @@ SyncHandleRegistry::SyncHandleRegistry() {
SyncHandleRegistry::~SyncHandleRegistry() {
DCHECK(thread_checker_.CalledOnValidThread());
+
+ // If this breaks, it is likely that the global variable is bulit into and
+ // accessed from multiple modules.
+ CHECK_EQ(this, g_current_sync_handle_watcher.Pointer()->Get());
+
g_current_sync_handle_watcher.Pointer()->Set(nullptr);
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h b/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h
deleted file mode 100644
index d6b8c38e0ce..00000000000
--- a/chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2016 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_SYNC_HANDLE_REGISTRY_H_
-#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SYNC_HANDLE_REGISTRY_H_
-
-#include <unordered_map>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "mojo/public/cpp/system/core.h"
-
-namespace mojo {
-namespace internal {
-
-// SyncHandleRegistry is a thread-local storage to register handles that want to
-// be watched together.
-//
-// This class is not thread safe.
-class SyncHandleRegistry : public base::RefCounted<SyncHandleRegistry> {
- public:
- // Returns a thread-local object.
- static scoped_refptr<SyncHandleRegistry> current();
-
- using HandleCallback = base::Callback<void(MojoResult)>;
- bool RegisterHandle(const Handle& handle,
- MojoHandleSignals handle_signals,
- const HandleCallback& callback);
-
- void UnregisterHandle(const Handle& handle);
-
- // Waits on all the registered handles and runs callbacks synchronously for
- // those ready handles.
- // The method:
- // - returns true when any element of |should_stop| is set to true;
- // - returns false when any error occurs.
- bool WatchAllHandles(const bool* should_stop[], size_t count);
-
- private:
- friend class base::RefCounted<SyncHandleRegistry>;
-
- struct HandleHasher {
- size_t operator()(const Handle& handle) const {
- return std::hash<uint32_t>()(static_cast<uint32_t>(handle.value()));
- }
- };
- using HandleMap = std::unordered_map<Handle, HandleCallback, HandleHasher>;
-
- SyncHandleRegistry();
- ~SyncHandleRegistry();
-
- HandleMap handles_;
-
- ScopedHandle wait_set_handle_;
-
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(SyncHandleRegistry);
-};
-
-} // namespace internal
-} // namespace mojo
-
-#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SYNC_HANDLE_REGISTRY_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/template_util.h b/chromium/mojo/public/cpp/bindings/lib/template_util.h
index 4e4ce66b6f4..5151123ac0b 100644
--- a/chromium/mojo/public/cpp/bindings/lib/template_util.h
+++ b/chromium/mojo/public/cpp/bindings/lib/template_util.h
@@ -114,54 +114,6 @@ struct Conditional<false, T, F> {
typedef F type;
};
-template <typename T>
-struct HasCloneMethod {
- template <typename U>
- static char Test(decltype(&U::Clone));
- template <typename U>
- static int Test(...);
- static const bool value = sizeof(Test<T>(0)) == sizeof(char);
-
- private:
- EnsureTypeIsComplete<T> check_t_;
-};
-
-template <typename T,
- typename std::enable_if<HasCloneMethod<T>::value>::type* = nullptr>
-T Clone(const T& input) {
- return input.Clone();
-};
-
-template <typename T,
- typename std::enable_if<!HasCloneMethod<T>::value>::type* = nullptr>
-T Clone(const T& input) {
- return input;
-}
-
-template <typename T>
-struct HasEqualsMethod {
- template <typename U>
- static char Test(decltype(&U::Equals));
- template <typename U>
- static int Test(...);
- static const bool value = sizeof(Test<T>(0)) == sizeof(char);
-
- private:
- EnsureTypeIsComplete<T> check_t_;
-};
-
-template <typename T,
- typename std::enable_if<HasEqualsMethod<T>::value>::type* = nullptr>
-bool Equals(const T& a, const T& b) {
- return a.Equals(b);
-};
-
-template <typename T,
- typename std::enable_if<!HasEqualsMethod<T>::value>::type* = nullptr>
-bool Equals(const T& a, const T& b) {
- return a == b;
-}
-
} // namespace internal
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_context.cc b/chromium/mojo/public/cpp/bindings/lib/validation_context.cc
index e2688c43f54..435168658a2 100644
--- a/chromium/mojo/public/cpp/bindings/lib/validation_context.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/validation_context.cc
@@ -4,28 +4,24 @@
#include "mojo/public/cpp/bindings/lib/validation_context.h"
-#include <stddef.h>
-#include <stdint.h>
-
#include "base/logging.h"
-#include "mojo/public/cpp/bindings/lib/serialization_util.h"
-#include "mojo/public/cpp/bindings/message.h"
-#include "mojo/public/cpp/system/handle.h"
namespace mojo {
namespace internal {
ValidationContext::ValidationContext(const void* data,
- uint32_t data_num_bytes,
+ size_t data_num_bytes,
size_t num_handles,
Message* message,
- const base::StringPiece& description)
+ const base::StringPiece& description,
+ int stack_depth)
: message_(message),
description_(description),
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)) {
+ handle_end_(static_cast<uint32_t>(num_handles)),
+ stack_depth_(stack_depth) {
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
@@ -44,43 +40,5 @@ ValidationContext::ValidationContext(const void* data,
ValidationContext::~ValidationContext() {
}
-bool ValidationContext::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 ValidationContext::ClaimHandle(const Handle_Data& 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 ValidationContext::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 ValidationContext::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/validation_context.h b/chromium/mojo/public/cpp/bindings/lib/validation_context.h
index 5b02a59fdfc..f8fe58ea22f 100644
--- a/chromium/mojo/public/cpp/bindings/lib/validation_context.h
+++ b/chromium/mojo/public/cpp/bindings/lib/validation_context.h
@@ -8,20 +8,23 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+static const int kMaxRecursionDepth = 100;
+
namespace mojo {
-class Handle;
class Message;
namespace internal {
// ValidationContext is used when validating object sizes, pointers and handle
// indices in the payload of incoming messages.
-class ValidationContext {
+class MOJO_CPP_BINDINGS_EXPORT ValidationContext {
public:
// [data, data + data_num_bytes) specifies the initial valid memory range.
// [0, num_handles) specifies the initial valid range of handle indices.
@@ -31,10 +34,11 @@ class ValidationContext {
// provided, the MojoNotifyBadMessage API will be used to notify the system of
// such errors.
ValidationContext(const void* data,
- uint32_t data_num_bytes,
+ size_t data_num_bytes,
size_t num_handles,
Message* message = nullptr,
- const base::StringPiece& description = "");
+ const base::StringPiece& description = "",
+ int stack_depth = 0);
~ValidationContext();
@@ -43,24 +47,75 @@ class ValidationContext {
// 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);
+ bool 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;
+ }
// 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_Data& encoded_handle);
+ bool ClaimHandle(const Handle_Data& 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;
+ }
// 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;
+ bool 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);
+ }
+
+ // This object should be created on the stack once every time we recurse down
+ // into a subfield during validation to make sure we don't recurse too deep
+ // and blow the stack.
+ class ScopedDepthTracker {
+ public:
+ // |ctx| must outlive this object.
+ explicit ScopedDepthTracker(ValidationContext* ctx) : ctx_(ctx) {
+ ++ctx_->stack_depth_;
+ }
+
+ ~ScopedDepthTracker() { --ctx_->stack_depth_; }
+
+ private:
+ ValidationContext* ctx_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDepthTracker);
+ };
+
+ // Returns true if the recursion depth limit has been reached.
+ bool ExceedsMaxDepth() WARN_UNUSED_RESULT {
+ return stack_depth_ > kMaxRecursionDepth;
+ }
Message* message() const { return message_; }
const base::StringPiece& description() const { return description_; }
private:
- bool InternalIsValidRange(uintptr_t begin, uintptr_t end) const;
+ bool InternalIsValidRange(uintptr_t begin, uintptr_t end) const {
+ return end > begin && begin >= data_begin_ && end <= data_end_;
+ }
Message* const message_;
const base::StringPiece description_;
@@ -73,6 +128,8 @@ class ValidationContext {
uint32_t handle_begin_;
uint32_t handle_end_;
+ int stack_depth_;
+
DISALLOW_COPY_AND_ASSIGN(ValidationContext);
};
diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_errors.cc b/chromium/mojo/public/cpp/bindings/lib/validation_errors.cc
index 90652de05fa..67106a0fd50 100644
--- a/chromium/mojo/public/cpp/bindings/lib/validation_errors.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/validation_errors.cc
@@ -55,6 +55,8 @@ const char* ValidationErrorToString(ValidationError error) {
return "VALIDATION_ERROR_UNKNOWN_ENUM_VALUE";
case VALIDATION_ERROR_DESERIALIZATION_FAILED:
return "VALIDATION_ERROR_DESERIALIZATION_FAILED";
+ case VALIDATION_ERROR_MAX_RECURSION_DEPTH:
+ return "VALIDATION_ERROR_MAX_RECURSION_DEPTH";
}
return "Unknown error";
@@ -88,6 +90,17 @@ void ReportValidationError(ValidationContext* context,
}
}
+void ReportValidationErrorForMessage(
+ mojo::Message* message,
+ ValidationError error,
+ const char* description) {
+ ValidationContext validation_context(
+ message->data(), message->data_num_bytes(),
+ message->handles()->size(), message,
+ description);
+ ReportValidationError(&validation_context, error);
+}
+
ValidationErrorObserverForTesting::ValidationErrorObserverForTesting(
const base::Closure& callback)
: last_error_(VALIDATION_ERROR_NONE), callback_(callback) {
diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_errors.h b/chromium/mojo/public/cpp/bindings/lib/validation_errors.h
index ec0aa2798c2..7636e391dad 100644
--- a/chromium/mojo/public/cpp/bindings/lib/validation_errors.h
+++ b/chromium/mojo/public/cpp/bindings/lib/validation_errors.h
@@ -8,9 +8,13 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/validation_context.h"
namespace mojo {
+
+class Message;
+
namespace internal {
enum ValidationError {
@@ -67,17 +71,27 @@ enum ValidationError {
// Message deserialization failure, for example due to rejection by custom
// validation logic.
VALIDATION_ERROR_DESERIALIZATION_FAILED,
+ // The message contains a too deeply nested value, for example a recursively
+ // defined field which runtime value is too large.
+ VALIDATION_ERROR_MAX_RECURSION_DEPTH,
};
-const char* ValidationErrorToString(ValidationError error);
+MOJO_CPP_BINDINGS_EXPORT const char* ValidationErrorToString(
+ ValidationError error);
+
+MOJO_CPP_BINDINGS_EXPORT void ReportValidationError(
+ ValidationContext* context,
+ ValidationError error,
+ const char* description = nullptr);
-void ReportValidationError(ValidationContext* context,
- ValidationError error,
- const char* description = nullptr);
+MOJO_CPP_BINDINGS_EXPORT void ReportValidationErrorForMessage(
+ mojo::Message* message,
+ ValidationError error,
+ const char* description = nullptr);
// Only used by validation tests and when there is only one thread doing message
// validation.
-class ValidationErrorObserverForTesting {
+class MOJO_CPP_BINDINGS_EXPORT ValidationErrorObserverForTesting {
public:
explicit ValidationErrorObserverForTesting(const base::Closure& callback);
~ValidationErrorObserverForTesting();
@@ -99,11 +113,11 @@ class ValidationErrorObserverForTesting {
//
// The function returns true if the error is recorded (by a
// SerializationWarningObserverForTesting object), false otherwise.
-bool ReportSerializationWarning(ValidationError error);
+MOJO_CPP_BINDINGS_EXPORT bool ReportSerializationWarning(ValidationError error);
// Only used by serialization tests and when there is only one thread doing
// message serialization.
-class SerializationWarningObserverForTesting {
+class MOJO_CPP_BINDINGS_EXPORT SerializationWarningObserverForTesting {
public:
SerializationWarningObserverForTesting();
~SerializationWarningObserverForTesting();
diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_util.cc b/chromium/mojo/public/cpp/bindings/lib/validation_util.cc
index 9e635211651..9675afe8e0a 100644
--- a/chromium/mojo/public/cpp/bindings/lib/validation_util.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/validation_util.cc
@@ -16,16 +16,6 @@
namespace mojo {
namespace internal {
-bool ValidateEncodedPointer(const uint64_t* offset) {
- // - Make sure |*offset| is no more than 32-bits.
- // - Cast |offset| to uintptr_t so overflow behavior is well defined across
- // 32-bit and 64-bit systems.
- return *offset <= std::numeric_limits<uint32_t>::max() &&
- (reinterpret_cast<uintptr_t>(offset) +
- static_cast<uint32_t>(*offset) >=
- reinterpret_cast<uintptr_t>(offset));
-}
-
bool ValidateStructHeaderAndClaimMemory(const void* data,
ValidationContext* validation_context) {
if (!IsAligned(data)) {
@@ -56,20 +46,17 @@ bool ValidateStructHeaderAndClaimMemory(const void* data,
return true;
}
-bool ValidateUnionHeaderAndClaimMemory(const void* data,
- bool inlined,
- ValidationContext* validation_context) {
+bool ValidateNonInlinedUnionHeaderAndClaimMemory(
+ const void* data,
+ ValidationContext* validation_context) {
if (!IsAligned(data)) {
ReportValidationError(validation_context,
VALIDATION_ERROR_MISALIGNED_OBJECT);
return false;
}
- // If the union is inlined in another structure its memory was already
- // claimed.
- // This ONLY applies to the union itself, NOT anything which the union points
- // to.
- if (!inlined && !validation_context->ClaimMemory(data, kUnionDataSize)) {
+ if (!validation_context->ClaimMemory(data, kUnionDataSize) ||
+ *static_cast<const uint32_t*>(data) != kUnionDataSize) {
ReportValidationError(validation_context,
VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
return false;
@@ -113,35 +100,6 @@ bool ValidateMessageIsResponse(const Message* message,
return true;
}
-bool ValidateControlRequest(const Message* message,
- ValidationContext* validation_context) {
- switch (message->header()->name) {
- case kRunMessageId:
- return ValidateMessageIsRequestExpectingResponse(message,
- validation_context) &&
- ValidateMessagePayload<RunMessageParams_Data>(message,
- validation_context);
- case kRunOrClosePipeMessageId:
- return ValidateMessageIsRequestWithoutResponse(message,
- validation_context) &&
- ValidateMessagePayload<RunOrClosePipeMessageParams_Data>(
- message, validation_context);
- }
- return false;
-}
-
-bool ValidateControlResponse(const Message* message,
- ValidationContext* validation_context) {
- if (!ValidateMessageIsResponse(message, validation_context))
- return false;
- switch (message->header()->name) {
- case kRunMessageId:
- return ValidateMessagePayload<RunResponseMessageParams_Data>(
- message, validation_context);
- }
- return false;
-}
-
bool IsHandleOrInterfaceValid(const AssociatedInterface_Data& input) {
return IsValidInterfaceId(input.interface_id);
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/validation_util.h b/chromium/mojo/public/cpp/bindings/lib/validation_util.h
index 7f861018661..8de5569072c 100644
--- a/chromium/mojo/public/cpp/bindings/lib/validation_util.h
+++ b/chromium/mojo/public/cpp/bindings/lib/validation_util.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/serialization_util.h"
#include "mojo/public/cpp/bindings/lib/validate_params.h"
@@ -19,7 +20,25 @@ namespace internal {
// Checks whether decoding the pointer will overflow and produce a pointer
// smaller than |offset|.
-bool ValidateEncodedPointer(const uint64_t* offset);
+inline bool ValidateEncodedPointer(const uint64_t* offset) {
+ // - Make sure |*offset| is no more than 32-bits.
+ // - Cast |offset| to uintptr_t so overflow behavior is well defined across
+ // 32-bit and 64-bit systems.
+ return *offset <= std::numeric_limits<uint32_t>::max() &&
+ (reinterpret_cast<uintptr_t>(offset) +
+ static_cast<uint32_t>(*offset) >=
+ reinterpret_cast<uintptr_t>(offset));
+}
+
+template <typename T>
+bool ValidatePointer(const Pointer<T>& input,
+ ValidationContext* validation_context) {
+ bool result = ValidateEncodedPointer(&input.offset);
+ if (!result)
+ ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER);
+
+ return result;
+}
// Validates that |data| contains a valid struct header, in terms of alignment
// and size (i.e., the |num_bytes| field of the header is sufficient for storing
@@ -28,30 +47,32 @@ bool ValidateEncodedPointer(const uint64_t* offset);
// |validation_context|. On success, the memory range is marked as occupied.
// Note: Does not verify |version| or that |num_bytes| is correct for the
// claimed version.
-bool ValidateStructHeaderAndClaimMemory(const void* data,
- ValidationContext* validation_context);
+MOJO_CPP_BINDINGS_EXPORT bool ValidateStructHeaderAndClaimMemory(
+ const void* data,
+ ValidationContext* validation_context);
// Validates that |data| contains a valid union header, in terms of alignment
-// and size. If not inlined, it checks that the memory range
-// [data, data + num_bytes) is not marked as occupied by other objects in
-// |validation_context|. On success, the memory range is marked as occupied.
-bool ValidateUnionHeaderAndClaimMemory(const void* data,
- bool inlined,
- ValidationContext* validation_context);
+// and size. It checks that the memory range [data, data + kUnionDataSize) is
+// not marked as occupied by other objects in |validation_context|. On success,
+// the memory range is marked as occupied.
+MOJO_CPP_BINDINGS_EXPORT bool ValidateNonInlinedUnionHeaderAndClaimMemory(
+ const void* data,
+ ValidationContext* validation_context);
// Validates that the message is a request which doesn't expect a response.
-bool ValidateMessageIsRequestWithoutResponse(
+MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsRequestWithoutResponse(
const Message* message,
ValidationContext* validation_context);
// Validates that the message is a request expecting a response.
-bool ValidateMessageIsRequestExpectingResponse(
+MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsRequestExpectingResponse(
const Message* message,
ValidationContext* validation_context);
// Validates that the message is a response.
-bool ValidateMessageIsResponse(const Message* message,
- ValidationContext* validation_context);
+MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsResponse(
+ const Message* message,
+ ValidationContext* validation_context);
// Validates that the message payload is a valid struct of type ParamsType.
template <typename ParamsType>
@@ -60,13 +81,6 @@ bool ValidateMessagePayload(const Message* message,
return ParamsType::Validate(message->payload(), validation_context);
}
-// The following methods validate control messages defined in
-// interface_control_messages.mojom.
-bool ValidateControlRequest(const Message* message,
- ValidationContext* validation_context);
-bool ValidateControlResponse(const Message* message,
- ValidationContext* validation_context);
-
// The following Validate.*NonNullable() functions validate that the given
// |input| is not null/invalid.
template <typename T>
@@ -95,91 +109,96 @@ bool ValidateInlinedUnionNonNullable(const T& input,
return false;
}
-bool IsHandleOrInterfaceValid(const AssociatedInterface_Data& input);
-bool IsHandleOrInterfaceValid(const AssociatedInterfaceRequest_Data& input);
-bool IsHandleOrInterfaceValid(const Interface_Data& input);
-bool IsHandleOrInterfaceValid(const Handle_Data& input);
+MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid(
+ const AssociatedInterface_Data& input);
+MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid(
+ const AssociatedInterfaceRequest_Data& input);
+MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid(
+ const Interface_Data& input);
+MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid(
+ const Handle_Data& input);
-bool ValidateHandleOrInterfaceNonNullable(
+MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable(
const AssociatedInterface_Data& input,
const char* error_message,
ValidationContext* validation_context);
-bool ValidateHandleOrInterfaceNonNullable(
+MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable(
const AssociatedInterfaceRequest_Data& input,
const char* error_message,
ValidationContext* validation_context);
-bool ValidateHandleOrInterfaceNonNullable(
+MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable(
const Interface_Data& input,
const char* error_message,
ValidationContext* validation_context);
-bool ValidateHandleOrInterfaceNonNullable(
+MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable(
const Handle_Data& input,
const char* error_message,
ValidationContext* validation_context);
template <typename T>
-bool ValidateArray(const Pointer<Array_Data<T>>& input,
- ValidationContext* validation_context,
- const ContainerValidateParams* validate_params) {
- if (!ValidateEncodedPointer(&input.offset)) {
- ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER);
- return false;
- }
-
- return Array_Data<T>::Validate(DecodePointerRaw(&input.offset),
- validation_context, validate_params);
-}
-
-template <typename T>
-bool ValidateMap(const Pointer<T>& input,
- ValidationContext* validation_context,
- const ContainerValidateParams* validate_params) {
- if (!ValidateEncodedPointer(&input.offset)) {
- ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER);
+bool ValidateContainer(const Pointer<T>& input,
+ ValidationContext* validation_context,
+ const ContainerValidateParams* validate_params) {
+ ValidationContext::ScopedDepthTracker depth_tracker(validation_context);
+ if (validation_context->ExceedsMaxDepth()) {
+ ReportValidationError(validation_context,
+ VALIDATION_ERROR_MAX_RECURSION_DEPTH);
return false;
}
-
- return T::Validate(DecodePointerRaw(&input.offset), validation_context,
- validate_params);
+ return ValidatePointer(input, validation_context) &&
+ T::Validate(input.Get(), validation_context, validate_params);
}
template <typename T>
bool ValidateStruct(const Pointer<T>& input,
ValidationContext* validation_context) {
- if (!ValidateEncodedPointer(&input.offset)) {
- ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER);
+ ValidationContext::ScopedDepthTracker depth_tracker(validation_context);
+ if (validation_context->ExceedsMaxDepth()) {
+ ReportValidationError(validation_context,
+ VALIDATION_ERROR_MAX_RECURSION_DEPTH);
return false;
}
-
- return T::Validate(DecodePointerRaw(&input.offset), validation_context);
+ return ValidatePointer(input, validation_context) &&
+ T::Validate(input.Get(), validation_context);
}
template <typename T>
bool ValidateInlinedUnion(const T& input,
ValidationContext* validation_context) {
+ ValidationContext::ScopedDepthTracker depth_tracker(validation_context);
+ if (validation_context->ExceedsMaxDepth()) {
+ ReportValidationError(validation_context,
+ VALIDATION_ERROR_MAX_RECURSION_DEPTH);
+ return false;
+ }
return T::Validate(&input, validation_context, true);
}
template <typename T>
bool ValidateNonInlinedUnion(const Pointer<T>& input,
ValidationContext* validation_context) {
- if (!ValidateEncodedPointer(&input.offset)) {
- ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER);
+ ValidationContext::ScopedDepthTracker depth_tracker(validation_context);
+ if (validation_context->ExceedsMaxDepth()) {
+ ReportValidationError(validation_context,
+ VALIDATION_ERROR_MAX_RECURSION_DEPTH);
return false;
}
-
- return T::Validate(DecodePointerRaw(&input.offset), validation_context,
- false);
+ return ValidatePointer(input, validation_context) &&
+ T::Validate(input.Get(), validation_context, false);
}
-bool ValidateHandleOrInterface(const AssociatedInterface_Data& input,
- ValidationContext* validation_context);
-bool ValidateHandleOrInterface(const AssociatedInterfaceRequest_Data& input,
- ValidationContext* validation_context);
-bool ValidateHandleOrInterface(const Interface_Data& input,
- ValidationContext* validation_context);
-bool ValidateHandleOrInterface(const Handle_Data& input,
- ValidationContext* validation_context);
+MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface(
+ const AssociatedInterface_Data& input,
+ ValidationContext* validation_context);
+MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface(
+ const AssociatedInterfaceRequest_Data& input,
+ ValidationContext* validation_context);
+MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface(
+ const Interface_Data& input,
+ ValidationContext* validation_context);
+MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface(
+ const Handle_Data& input,
+ ValidationContext* validation_context);
} // namespace internal
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h b/chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h
new file mode 100644
index 00000000000..edbf27b7d30
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h
@@ -0,0 +1,76 @@
+// Copyright 2016 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_WTF_CLONE_EQUALS_UTIL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_
+
+#include <type_traits>
+
+#include "mojo/public/cpp/bindings/lib/clone_equals_util.h"
+#include "third_party/WebKit/Source/wtf/HashMap.h"
+#include "third_party/WebKit/Source/wtf/Optional.h"
+#include "third_party/WebKit/Source/wtf/Vector.h"
+#include "third_party/WebKit/Source/wtf/text/WTFString.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename T>
+struct CloneTraits<WTF::Vector<T>, false> {
+ static WTF::Vector<T> Clone(const WTF::Vector<T>& input) {
+ WTF::Vector<T> result;
+ result.reserveCapacity(input.size());
+ for (const auto& element : input)
+ result.append(internal::Clone(element));
+
+ return result;
+ }
+};
+
+template <typename K, typename V>
+struct CloneTraits<WTF::HashMap<K, V>, false> {
+ static WTF::HashMap<K, V> Clone(const WTF::HashMap<K, V>& input) {
+ WTF::HashMap<K, V> result;
+ auto input_end = input.end();
+ for (auto it = input.begin(); it != input_end; ++it)
+ result.add(internal::Clone(it->key), internal::Clone(it->value));
+ return result;
+ }
+};
+
+template <typename T>
+struct EqualsTraits<WTF::Vector<T>, false> {
+ static bool Equals(const WTF::Vector<T>& a, const WTF::Vector<T>& b) {
+ if (a.size() != b.size())
+ return false;
+ for (size_t i = 0; i < a.size(); ++i) {
+ if (!internal::Equals(a[i], b[i]))
+ return false;
+ }
+ return true;
+ }
+};
+
+template <typename K, typename V>
+struct EqualsTraits<WTF::HashMap<K, V>, false> {
+ static bool Equals(const WTF::HashMap<K, V>& a, const WTF::HashMap<K, V>& b) {
+ if (a.size() != b.size())
+ return false;
+
+ auto a_end = a.end();
+ auto b_end = b.end();
+
+ for (auto iter = a.begin(); iter != a_end; ++iter) {
+ auto b_iter = b.find(iter->key);
+ if (b_iter == b_end || !internal::Equals(iter->value, b_iter->value))
+ return false;
+ }
+ return true;
+ }
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h b/chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h
new file mode 100644
index 00000000000..cc590da67a0
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h
@@ -0,0 +1,132 @@
+// Copyright 2016 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_WTF_HASH_UTIL_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_HASH_UTIL_H_
+
+#include <type_traits>
+
+#include "mojo/public/cpp/bindings/lib/hash_util.h"
+#include "mojo/public/cpp/bindings/struct_ptr.h"
+#include "third_party/WebKit/Source/wtf/HashFunctions.h"
+#include "third_party/WebKit/Source/wtf/text/StringHash.h"
+#include "third_party/WebKit/Source/wtf/text/WTFString.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename T>
+size_t WTFHashCombine(size_t seed, const T& value) {
+ // Based on proposal in:
+ // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
+ //
+ // TODO(tibell): We'd like to use WTF::DefaultHash instead of std::hash, but
+ // there is no general template specialization of DefaultHash for enums
+ // and there can't be an instance for bool.
+ return seed ^ (std::hash<T>()(value) + (seed << 6) + (seed >> 2));
+}
+
+template <typename T, bool has_hash_method = HasHashMethod<T>::value>
+struct WTFHashTraits;
+
+template <typename T>
+size_t WTFHash(size_t seed, const T& value);
+
+template <typename T>
+struct WTFHashTraits<T, true> {
+ static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); }
+};
+
+template <typename T>
+struct WTFHashTraits<T, false> {
+ static size_t Hash(size_t seed, const T& value) {
+ return WTFHashCombine(seed, value);
+ }
+};
+
+template <>
+struct WTFHashTraits<WTF::String, false> {
+ static size_t Hash(size_t seed, const WTF::String& value) {
+ return HashCombine(seed, WTF::StringHash::hash(value));
+ }
+};
+
+template <typename T>
+size_t WTFHash(size_t seed, const T& value) {
+ return WTFHashTraits<T>::Hash(seed, value);
+}
+
+template <typename T>
+struct StructPtrHashFn {
+ static unsigned hash(const StructPtr<T>& value) {
+ return value.Hash(kHashSeed);
+ }
+ static bool equal(const StructPtr<T>& left, const StructPtr<T>& right) {
+ return left.Equals(right);
+ }
+ static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+template <typename T>
+struct InlinedStructPtrHashFn {
+ static unsigned hash(const InlinedStructPtr<T>& value) {
+ return value.Hash(kHashSeed);
+ }
+ static bool equal(const InlinedStructPtr<T>& left,
+ const InlinedStructPtr<T>& right) {
+ return left.Equals(right);
+ }
+ static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+} // namespace internal
+} // namespace mojo
+
+namespace WTF {
+
+template <typename T>
+struct DefaultHash<mojo::StructPtr<T>> {
+ using Hash = mojo::internal::StructPtrHashFn<T>;
+};
+
+template <typename T>
+struct HashTraits<mojo::StructPtr<T>>
+ : public GenericHashTraits<mojo::StructPtr<T>> {
+ static const bool hasIsEmptyValueFunction = true;
+ static bool isEmptyValue(const mojo::StructPtr<T>& value) {
+ return value.is_null();
+ }
+ static void constructDeletedValue(mojo::StructPtr<T>& slot, bool) {
+ mojo::internal::StructPtrWTFHelper<T>::ConstructDeletedValue(slot);
+ }
+ static bool isDeletedValue(const mojo::StructPtr<T>& value) {
+ return mojo::internal::StructPtrWTFHelper<T>::IsHashTableDeletedValue(
+ value);
+ }
+};
+
+template <typename T>
+struct DefaultHash<mojo::InlinedStructPtr<T>> {
+ using Hash = mojo::internal::InlinedStructPtrHashFn<T>;
+};
+
+template <typename T>
+struct HashTraits<mojo::InlinedStructPtr<T>>
+ : public GenericHashTraits<mojo::InlinedStructPtr<T>> {
+ static const bool hasIsEmptyValueFunction = true;
+ static bool isEmptyValue(const mojo::InlinedStructPtr<T>& value) {
+ return value.is_null();
+ }
+ static void constructDeletedValue(mojo::InlinedStructPtr<T>& slot, bool) {
+ mojo::internal::InlinedStructPtrWTFHelper<T>::ConstructDeletedValue(slot);
+ }
+ static bool isDeletedValue(const mojo::InlinedStructPtr<T>& value) {
+ return mojo::internal::InlinedStructPtrWTFHelper<
+ T>::IsHashTableDeletedValue(value);
+ }
+};
+
+} // namespace WTF
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_HASH_UTIL_H_
diff --git a/chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h b/chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h
index 91f24b5c558..132e19cd6b6 100644
--- a/chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h
+++ b/chromium/mojo/public/cpp/bindings/lib/wtf_serialization.h
@@ -8,6 +8,7 @@
#include "mojo/public/cpp/bindings/array_traits_wtf.h"
#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
#include "mojo/public/cpp/bindings/map_traits_wtf.h"
+#include "mojo/public/cpp/bindings/map_traits_wtf_hash_map.h"
#include "mojo/public/cpp/bindings/string_traits_wtf.h"
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_
diff --git a/chromium/mojo/public/cpp/bindings/map.h b/chromium/mojo/public/cpp/bindings/map.h
index 8fa3d6708dd..d4c79525ee8 100644
--- a/chromium/mojo/public/cpp/bindings/map.h
+++ b/chromium/mojo/public/cpp/bindings/map.h
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <map>
+#include <unordered_map>
#include <utility>
#include "base/logging.h"
@@ -135,14 +136,13 @@ class Map {
const std::map<Key, Value>& storage() const { return map_; }
// Passes the underlying storage and resets this map to null.
- //
- // TODO(yzshen): Consider changing this to a rvalue-ref-qualified conversion
- // to std::map<Key, Value> after we move to MSVC 2015.
std::map<Key, Value> PassStorage() {
is_null_ = true;
return std::move(map_);
}
+ operator const std::map<Key, Value>&() const { return map_; }
+
// Swaps the contents of this Map with another Map of the same type (including
// nullness).
void Swap(Map<Key, Value>* other) {
diff --git a/chromium/mojo/public/cpp/bindings/map_data_view.h b/chromium/mojo/public/cpp/bindings/map_data_view.h
new file mode 100644
index 00000000000..a65bb9eca14
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/map_data_view.h
@@ -0,0 +1,63 @@
+// Copyright 2016 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_MAP_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_MAP_DATA_VIEW_H_
+
+#include "base/logging.h"
+#include "mojo/public/cpp/bindings/array_data_view.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/map_data_internal.h"
+#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
+
+namespace mojo {
+
+template <typename K, typename V>
+class MapDataView {
+ public:
+ using Data_ = typename internal::MojomTypeTraits<MapDataView<K, V>>::Data;
+
+ MapDataView() {}
+
+ MapDataView(Data_* data, internal::SerializationContext* context)
+ : keys_(data ? data->keys.Get() : nullptr, context),
+ values_(data ? data->values.Get() : nullptr, context) {}
+
+ bool is_null() const {
+ DCHECK_EQ(keys_.is_null(), values_.is_null());
+ return keys_.is_null();
+ }
+
+ size_t size() const {
+ DCHECK_EQ(keys_.size(), values_.size());
+ return keys_.size();
+ }
+
+ ArrayDataView<K>& keys() { return keys_; }
+ const ArrayDataView<K>& keys() const { return keys_; }
+
+ template <typename U>
+ bool ReadKeys(U* output) {
+ return internal::Deserialize<ArrayDataView<K>>(keys_.data_, output,
+ keys_.context_);
+ }
+
+ ArrayDataView<V>& values() { return values_; }
+ const ArrayDataView<V>& values() const { return values_; }
+
+ template <typename U>
+ bool ReadValues(U* output) {
+ return internal::Deserialize<ArrayDataView<V>>(values_.data_, output,
+ values_.context_);
+ }
+
+ private:
+ ArrayDataView<K> keys_;
+ ArrayDataView<V> values_;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_DATA_VIEW_H_
diff --git a/chromium/mojo/public/cpp/bindings/map_traits.h b/chromium/mojo/public/cpp/bindings/map_traits.h
index 01dd66d6a69..5c0d8b2846c 100644
--- a/chromium/mojo/public/cpp/bindings/map_traits.h
+++ b/chromium/mojo/public/cpp/bindings/map_traits.h
@@ -37,13 +37,13 @@ namespace mojo {
// static const V& GetValue(CustomConstIterator& iterator);
//
// // Returning false results in deserialization failure and causes the
-// // message pipe receiving it to be disconnected.
+// // message pipe receiving it to be disconnected. |IK| and |IV| are
+// // separate input key/value template parameters that allows for the
+// // the key/value types to be forwarded.
+// template <typename IK, typename IV>
// static bool Insert(CustomMap<K, V>& input,
-// const K& key,
-// V&& value);
-// static bool Insert(CustomMap<K, V>& input,
-// const K& key,
-// const V& value);
+// IK&& key,
+// IV&& value);
//
// static void SetToEmpty(CustomMap<K, V>* output);
// };
diff --git a/chromium/mojo/public/cpp/bindings/map_traits_stl.h b/chromium/mojo/public/cpp/bindings/map_traits_stl.h
index 2d5c137ff35..83a4399ce06 100644
--- a/chromium/mojo/public/cpp/bindings/map_traits_stl.h
+++ b/chromium/mojo/public/cpp/bindings/map_traits_stl.h
@@ -6,6 +6,7 @@
#define MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_STL_H_
#include <map>
+#include <unordered_map>
#include "mojo/public/cpp/bindings/map_traits.h"
@@ -56,6 +57,53 @@ struct MapTraits<std::map<K, V>> {
static void SetToEmpty(std::map<K, V>* output) { output->clear(); }
};
+template <typename K, typename V>
+struct MapTraits<std::unordered_map<K, V>> {
+ using Key = K;
+ using Value = V;
+ using Iterator = typename std::unordered_map<K, V>::iterator;
+ using ConstIterator = typename std::unordered_map<K, V>::const_iterator;
+
+ static bool IsNull(const std::unordered_map<K, V>& input) {
+ // std::unordered_map<> is always converted to non-null mojom map.
+ return false;
+ }
+
+ static void SetToNull(std::unordered_map<K, V>* output) {
+ // std::unordered_map<> doesn't support null state. Set it to empty instead.
+ output->clear();
+ }
+
+ static size_t GetSize(const std::unordered_map<K, V>& input) {
+ return input.size();
+ }
+
+ static ConstIterator GetBegin(const std::unordered_map<K, V>& input) {
+ return input.begin();
+ }
+ static Iterator GetBegin(std::unordered_map<K, V>& input) {
+ return input.begin();
+ }
+
+ static void AdvanceIterator(ConstIterator& iterator) { iterator++; }
+ static void AdvanceIterator(Iterator& iterator) { iterator++; }
+
+ static const K& GetKey(Iterator& iterator) { return iterator->first; }
+ static const K& GetKey(ConstIterator& iterator) { return iterator->first; }
+
+ static V& GetValue(Iterator& iterator) { return iterator->second; }
+ static const V& GetValue(ConstIterator& iterator) { return iterator->second; }
+
+ template <typename IK, typename IV>
+ static bool Insert(std::unordered_map<K, V>& input, IK&& key, IV&& value) {
+ input.insert(
+ std::make_pair(std::forward<IK>(key), std::forward<IV>(value)));
+ return true;
+ }
+
+ static void SetToEmpty(std::unordered_map<K, V>* output) { output->clear(); }
+};
+
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_STL_H_
diff --git a/chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h b/chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h
new file mode 100644
index 00000000000..edde377607e
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h
@@ -0,0 +1,64 @@
+// Copyright 2016 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_MAP_TRAITS_WTF_HASH_MAP_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_WTF_HASH_MAP_H_
+
+#include "base/logging.h"
+#include "mojo/public/cpp/bindings/map_traits.h"
+#include "third_party/WebKit/Source/wtf/HashMap.h"
+
+namespace mojo {
+
+template <typename K, typename V>
+struct MapTraits<WTF::HashMap<K, V>> {
+ using Key = K;
+ using Value = V;
+ using Iterator = typename WTF::HashMap<K, V>::iterator;
+ using ConstIterator = typename WTF::HashMap<K, V>::const_iterator;
+
+ static bool IsNull(const WTF::HashMap<K, V>& input) {
+ // WTF::HashMap<> is always converted to non-null mojom map.
+ return false;
+ }
+
+ static void SetToNull(WTF::HashMap<K, V>* output) {
+ // WTF::HashMap<> doesn't support null state. Set it to empty instead.
+ output->clear();
+ }
+
+ static size_t GetSize(const WTF::HashMap<K, V>& input) {
+ return input.size();
+ }
+
+ static ConstIterator GetBegin(const WTF::HashMap<K, V>& input) {
+ return input.begin();
+ }
+ static Iterator GetBegin(WTF::HashMap<K, V>& input) { return input.begin(); }
+
+ static void AdvanceIterator(ConstIterator& iterator) { ++iterator; }
+ static void AdvanceIterator(Iterator& iterator) { ++iterator; }
+
+ static const K& GetKey(Iterator& iterator) { return iterator->key; }
+ static const K& GetKey(ConstIterator& iterator) { return iterator->key; }
+
+ static V& GetValue(Iterator& iterator) { return iterator->value; }
+ static const V& GetValue(ConstIterator& iterator) { return iterator->value; }
+
+ template <typename IK, typename IV>
+ static bool Insert(WTF::HashMap<K, V>& input, IK&& key, IV&& value) {
+ if (!WTF::HashMap<K, V>::isValidKey(key)) {
+ LOG(ERROR) << "The key value is disallowed by WTF::HashMap";
+ return false;
+ }
+ input.add(std::forward<IK>(key), std::forward<IV>(value));
+ return true;
+ }
+
+ static void SetToEmpty(WTF::HashMap<K, V>* output) { output->clear(); }
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_WTF_HASH_MAP_H_
diff --git a/chromium/mojo/public/cpp/bindings/message.h b/chromium/mojo/public/cpp/bindings/message.h
index e758432b9a9..cfb9d05f601 100644
--- a/chromium/mojo/public/cpp/bindings/message.h
+++ b/chromium/mojo/public/cpp/bindings/message.h
@@ -13,26 +13,43 @@
#include <string>
#include <vector>
+#include "base/callback.h"
+#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/message_buffer.h"
#include "mojo/public/cpp/bindings/lib/message_internal.h"
#include "mojo/public/cpp/system/message.h"
namespace mojo {
+using ReportBadMessageCallback = base::Callback<void(const std::string& error)>;
+
// 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 {
+class MOJO_CPP_BINDINGS_EXPORT Message {
public:
static const uint32_t kFlagExpectsResponse = 1 << 0;
static const uint32_t kFlagIsResponse = 1 << 1;
static const uint32_t kFlagIsSync = 1 << 2;
Message();
+ Message(Message&& other);
+
~Message();
+ Message& operator=(Message&& other);
+
+ // Resets the Message to an uninitialized state. Upon reset, the Message
+ // exists as if it were default-constructed: it has no data buffer and owns no
+ // handles.
+ void Reset();
+
+ // Indicates whether this Message is uninitialized.
+ bool IsNull() const { return !buffer_; }
+
// Initializes a Message with enough space for |capacity| bytes.
void Initialize(size_t capacity, bool zero_initialized);
@@ -41,10 +58,9 @@ class Message {
uint32_t num_bytes,
std::vector<Handle>* handles);
- // Transfers data and handles to |destination|.
- void MoveTo(Message* destination);
-
- uint32_t data_num_bytes() const { return buffer_->data_num_bytes(); }
+ uint32_t data_num_bytes() const {
+ return static_cast<uint32_t>(buffer_->size());
+ }
// Access the raw bytes of the message.
const uint8_t* data() const {
@@ -86,8 +102,8 @@ class Message {
const uint8_t* payload() const { return data() + header()->num_bytes; }
uint8_t* mutable_payload() { return const_cast<uint8_t*>(payload()); }
uint32_t payload_num_bytes() const {
- DCHECK(buffer_->data_num_bytes() >= header()->num_bytes);
- size_t num_bytes = buffer_->data_num_bytes() - header()->num_bytes;
+ DCHECK(data_num_bytes() >= header()->num_bytes);
+ size_t num_bytes = data_num_bytes() - header()->num_bytes;
DCHECK(num_bytes <= std::numeric_limits<uint32_t>::max());
return static_cast<uint32_t>(num_bytes);
}
@@ -186,6 +202,57 @@ class MessageReceiverWithResponderStatus : public MessageReceiver {
WARN_UNUSED_RESULT = 0;
};
+class MOJO_CPP_BINDINGS_EXPORT PassThroughFilter
+ : NON_EXPORTED_BASE(public MessageReceiver) {
+ public:
+ PassThroughFilter();
+ ~PassThroughFilter() override;
+
+ // MessageReceiver:
+ bool Accept(Message* message) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PassThroughFilter);
+};
+
+namespace internal {
+class SyncMessageResponseSetup;
+}
+
+// An object which should be constructed on the stack immediately before making
+// a sync request for which the caller wishes to perform custom validation of
+// the response value(s). It is illegal to make more than one sync call during
+// the lifetime of the topmost SyncMessageResponseContext, but it is legal to
+// nest contexts to support reentrancy.
+//
+// Usage should look something like:
+//
+// SyncMessageResponseContext response_context;
+// foo_interface->SomeSyncCall(&response_value);
+// if (response_value.IsBad())
+// response_context.ReportBadMessage("Bad response_value!");
+//
+class MOJO_CPP_BINDINGS_EXPORT SyncMessageResponseContext {
+ public:
+ SyncMessageResponseContext();
+ ~SyncMessageResponseContext();
+
+ static SyncMessageResponseContext* current();
+
+ void ReportBadMessage(const std::string& error);
+
+ const ReportBadMessageCallback& GetBadMessageCallback();
+
+ private:
+ friend class internal::SyncMessageResponseSetup;
+
+ SyncMessageResponseContext* outer_context_;
+ Message response_;
+ ReportBadMessageCallback bad_message_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncMessageResponseContext);
+};
+
// Read a single message from the pipe. The caller should have created the
// Message, but not called Initialize(). Returns MOJO_RESULT_SHOULD_WAIT if
// the caller should wait on the handle to become readable. Returns
@@ -195,6 +262,22 @@ class MessageReceiverWithResponderStatus : public MessageReceiver {
// NOTE: The message hasn't been validated and may be malformed!
MojoResult ReadMessage(MessagePipeHandle handle, Message* message);
+// Reports the currently dispatching Message as bad. Note that this is only
+// legal to call from directly within the stack frame of a message dispatch. If
+// you need to do asynchronous work before you can determine the legitimacy of
+// a message, use TakeBadMessageCallback() and retain its result until you're
+// ready to invoke or discard it.
+MOJO_CPP_BINDINGS_EXPORT
+void ReportBadMessage(const std::string& error);
+
+// Acquires a callback which may be run to report the currently dispatching
+// Message as bad. Note that this is only legal to call from directly within the
+// stack frame of a message dispatch, but the returned callback may be called
+// exactly once any time thereafter to report the message as bad. This may only
+// be called once per message.
+MOJO_CPP_BINDINGS_EXPORT
+ReportBadMessageCallback GetBadMessageCallback();
+
} // 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
deleted file mode 100644
index 638c53bc829..00000000000
--- a/chromium/mojo/public/cpp/bindings/message_filter.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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"
-
-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 = nullptr);
- ~MessageFilter() override;
-
- 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 = nullptr);
-
- bool Accept(Message* message) override;
-};
-
-} // namespace mojo
-
-#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_FILTER_H_
diff --git a/chromium/mojo/public/cpp/bindings/message_header_validator.h b/chromium/mojo/public/cpp/bindings/message_header_validator.h
index 3bcbd0a9563..50c19dbe048 100644
--- a/chromium/mojo/public/cpp/bindings/message_header_validator.h
+++ b/chromium/mojo/public/cpp/bindings/message_header_validator.h
@@ -5,16 +5,17 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_HEADER_VALIDATOR_H_
#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_HEADER_VALIDATOR_H_
+#include "base/compiler_specific.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/message.h"
-#include "mojo/public/cpp/bindings/message_filter.h"
namespace mojo {
-class MessageHeaderValidator : public MessageFilter {
+class MOJO_CPP_BINDINGS_EXPORT MessageHeaderValidator
+ : NON_EXPORTED_BASE(public MessageReceiver) {
public:
- explicit MessageHeaderValidator(MessageReceiver* sink = nullptr);
- MessageHeaderValidator(const std::string& description,
- MessageReceiver* sink = nullptr);
+ MessageHeaderValidator();
+ explicit MessageHeaderValidator(const std::string& description);
// Sets the description associated with this validator. Used for reporting
// more detailed validation errors.
diff --git a/chromium/mojo/public/cpp/bindings/native_enum.h b/chromium/mojo/public/cpp/bindings/native_enum.h
index 140045e4a2c..08b43b78bf9 100644
--- a/chromium/mojo/public/cpp/bindings/native_enum.h
+++ b/chromium/mojo/public/cpp/bindings/native_enum.h
@@ -5,6 +5,9 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_
#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_
+#include <functional>
+
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/native_enum_data.h"
namespace mojo {
@@ -14,4 +17,12 @@ enum class NativeEnum : int32_t {};
} // namespace mojo
+namespace std {
+
+template <>
+struct hash<mojo::NativeEnum>
+ : public mojo::internal::EnumHashImpl<mojo::NativeEnum> {};
+
+} // namespace std
+
#endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_
diff --git a/chromium/mojo/public/cpp/bindings/native_struct.h b/chromium/mojo/public/cpp/bindings/native_struct.h
index 882c970ce25..c9e263d277c 100644
--- a/chromium/mojo/public/cpp/bindings/native_struct.h
+++ b/chromium/mojo/public/cpp/bindings/native_struct.h
@@ -6,6 +6,7 @@
#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_H_
#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/lib/native_struct_data.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "mojo/public/cpp/bindings/type_converter.h"
@@ -17,7 +18,7 @@ using NativeStructPtr = StructPtr<NativeStruct>;
// Native-only structs correspond to "[Native] struct Foo;" definitions in
// mojom.
-class NativeStruct {
+class MOJO_CPP_BINDINGS_EXPORT NativeStruct {
public:
using Data_ = internal::NativeStruct_Data;
@@ -38,6 +39,7 @@ class NativeStruct {
NativeStructPtr Clone() const;
bool Equals(const NativeStruct& other) const;
+ size_t Hash(size_t seed) const;
Array<uint8_t> data;
};
diff --git a/chromium/mojo/public/cpp/bindings/native_struct_data_view.h b/chromium/mojo/public/cpp/bindings/native_struct_data_view.h
new file mode 100644
index 00000000000..613bd7a0b0e
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/native_struct_data_view.h
@@ -0,0 +1,36 @@
+// Copyright 2016 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_NATIVE_STRUCT_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_
+
+#include "mojo/public/cpp/bindings/lib/native_struct_data.h"
+#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+
+namespace mojo {
+
+class NativeStructDataView {
+ public:
+ using Data_ = internal::NativeStruct_Data;
+
+ NativeStructDataView() {}
+
+ NativeStructDataView(Data_* data, internal::SerializationContext* context)
+ : data_(data) {}
+
+ bool is_null() const { return !data_; }
+
+ size_t size() const { return data_->data.size(); }
+
+ uint8_t operator[](size_t index) const { return data_->data.at(index); }
+
+ const uint8_t* data() const { return data_->data.storage(); }
+
+ private:
+ Data_* data_ = nullptr;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_STRUCT_DATA_VIEW_H_
diff --git a/chromium/mojo/public/cpp/bindings/no_interface.h b/chromium/mojo/public/cpp/bindings/no_interface.h
index d8915cdf021..7520b8cceb4 100644
--- a/chromium/mojo/public/cpp/bindings/no_interface.h
+++ b/chromium/mojo/public/cpp/bindings/no_interface.h
@@ -6,7 +6,6 @@
#define MOJO_PUBLIC_CPP_BINDINGS_NO_INTERFACE_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 {
diff --git a/chromium/mojo/public/cpp/bindings/pipe_control_message_handler.h b/chromium/mojo/public/cpp/bindings/pipe_control_message_handler.h
index b387b061cfb..9428c1b2d8a 100644
--- a/chromium/mojo/public/cpp/bindings/pipe_control_message_handler.h
+++ b/chromium/mojo/public/cpp/bindings/pipe_control_message_handler.h
@@ -5,7 +5,9 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_H_
#define MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_HANDLER_H_
+#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/interface_id.h"
#include "mojo/public/cpp/bindings/lib/serialization_context.h"
#include "mojo/public/cpp/bindings/message.h"
@@ -15,7 +17,8 @@ namespace mojo {
class PipeControlMessageHandlerDelegate;
// Handler for messages defined in pipe_control_messages.mojom.
-class PipeControlMessageHandler : public MessageReceiver {
+class MOJO_CPP_BINDINGS_EXPORT PipeControlMessageHandler
+ : NON_EXPORTED_BASE(public MessageReceiver) {
public:
explicit PipeControlMessageHandler(
PipeControlMessageHandlerDelegate* delegate);
diff --git a/chromium/mojo/public/cpp/bindings/pipe_control_message_proxy.h b/chromium/mojo/public/cpp/bindings/pipe_control_message_proxy.h
index 7f3e006e09d..25ee2038469 100644
--- a/chromium/mojo/public/cpp/bindings/pipe_control_message_proxy.h
+++ b/chromium/mojo/public/cpp/bindings/pipe_control_message_proxy.h
@@ -6,6 +6,7 @@
#define MOJO_PUBLIC_CPP_BINDINGS_PIPE_CONTROL_MESSAGE_PROXY_H_
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/interface_id.h"
#include "mojo/public/cpp/bindings/lib/serialization_context.h"
@@ -14,7 +15,7 @@ namespace mojo {
class MessageReceiver;
// Proxy for request messages defined in pipe_control_messages.mojom.
-class PipeControlMessageProxy {
+class MOJO_CPP_BINDINGS_EXPORT PipeControlMessageProxy {
public:
// Doesn't take ownership of |receiver|. It must outlive this object.
explicit PipeControlMessageProxy(MessageReceiver* receiver);
diff --git a/chromium/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h b/chromium/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
index 1f45b0c5714..869c471a131 100644
--- a/chromium/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
+++ b/chromium/mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/interface_id.h"
namespace mojo {
@@ -15,7 +16,7 @@ class AssociatedGroupController;
// ScopedInterfaceEndpointHandle refers to one end of an interface, either the
// implementation side or the client side.
-class ScopedInterfaceEndpointHandle {
+class MOJO_CPP_BINDINGS_EXPORT ScopedInterfaceEndpointHandle {
public:
// Creates an invalid endpoint handle.
ScopedInterfaceEndpointHandle();
diff --git a/chromium/mojo/public/cpp/bindings/string.h b/chromium/mojo/public/cpp/bindings/string.h
index 7cfd713f669..892cc1c29ff 100644
--- a/chromium/mojo/public/cpp/bindings/string.h
+++ b/chromium/mojo/public/cpp/bindings/string.h
@@ -7,10 +7,12 @@
#include <stddef.h>
+#include <functional>
#include <string>
#include "base/logging.h"
#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/hash_util.h"
#include "mojo/public/cpp/bindings/type_converter.h"
namespace mojo {
@@ -193,4 +195,15 @@ struct TypeConverter<String, const char*> {
} // namespace mojo
+namespace std {
+
+template <>
+struct hash<mojo::String> {
+ size_t operator()(const mojo::String& value) const {
+ return value.is_null() ? 0 : hash<std::string>()(value.get());
+ }
+};
+
+} // namespace std
+
#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_H_
diff --git a/chromium/mojo/public/cpp/bindings/string_data_view.h b/chromium/mojo/public/cpp/bindings/string_data_view.h
new file mode 100644
index 00000000000..2b091b45f83
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/string_data_view.h
@@ -0,0 +1,34 @@
+// Copyright 2016 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_DATA_VIEW_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_STRING_DATA_VIEW_H_
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/serialization_context.h"
+
+namespace mojo {
+
+// Access to the contents of a serialized string.
+class StringDataView {
+ public:
+ StringDataView() {}
+
+ StringDataView(internal::String_Data* data,
+ internal::SerializationContext* context)
+ : data_(data) {}
+
+ bool is_null() const { return !data_; }
+
+ const char* storage() const { return data_->storage(); }
+
+ size_t size() const { return data_->size(); }
+
+ private:
+ internal::String_Data* data_ = nullptr;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_STRING_DATA_VIEW_H_
diff --git a/chromium/mojo/public/cpp/bindings/string_traits.h b/chromium/mojo/public/cpp/bindings/string_traits.h
index a6ade6fdf68..7d3075a5797 100644
--- a/chromium/mojo/public/cpp/bindings/string_traits.h
+++ b/chromium/mojo/public/cpp/bindings/string_traits.h
@@ -5,26 +5,10 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_
#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_H_
-#include "base/logging.h"
-#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/string_data_view.h"
namespace mojo {
-// Access to the contents of a serialized string.
-class StringDataView {
- public:
- explicit StringDataView(internal::String_Data* data) : data_(data) {
- DCHECK(data_);
- }
-
- const char* storage() const { return data_->storage(); }
-
- size_t size() const { return data_->size(); }
-
- private:
- internal::String_Data* data_;
-};
-
// This must be specialized for any type |T| to be serialized/deserialized as
// a mojom string.
//
@@ -40,6 +24,7 @@ class StringDataView {
// static size_t GetSize(const CustomString& input);
// static const char* GetData(const CustomString& input);
//
+// // The caller guarantees that |!input.is_null()|.
// static bool Read(StringDataView input, CustomString* output);
// };
//
diff --git a/chromium/mojo/public/cpp/bindings/string_traits_string16.h b/chromium/mojo/public/cpp/bindings/string_traits_string16.h
index 5a089080bd0..f96973ad914 100644
--- a/chromium/mojo/public/cpp/bindings/string_traits_string16.h
+++ b/chromium/mojo/public/cpp/bindings/string_traits_string16.h
@@ -6,12 +6,13 @@
#define MOJO_PUBLIC_CPP_BINDINGS_STRING_TRAITS_STRING16_H_
#include "base/strings/string16.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/string_traits.h"
namespace mojo {
template <>
-struct StringTraits<base::string16> {
+struct MOJO_CPP_BINDINGS_EXPORT StringTraits<base::string16> {
static bool IsNull(const base::string16& input) {
// base::string16 is always converted to non-null mojom string.
return false;
diff --git a/chromium/mojo/public/cpp/bindings/strong_binding.h b/chromium/mojo/public/cpp/bindings/strong_binding.h
index 7fb7eea245a..99d10956c6f 100644
--- a/chromium/mojo/public/cpp/bindings/strong_binding.h
+++ b/chromium/mojo/public/cpp/bindings/strong_binding.h
@@ -5,94 +5,53 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
#define MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
+#include <memory>
+#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/connection_error_callback.h"
+#include "mojo/public/cpp/bindings/filter_chain.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/bindings/lib/filter_chain.h"
#include "mojo/public/cpp/bindings/lib/router.h"
#include "mojo/public/cpp/bindings/message_header_validator.h"
#include "mojo/public/cpp/system/core.h"
namespace mojo {
+template <typename Interface>
+class StrongBinding;
+
+template <typename Interface>
+using StrongBindingPtr = base::WeakPtr<StrongBinding<Interface>>;
+
// This connects an interface implementation strongly to a pipe. When a
-// connection error is detected the implementation is deleted. Deleting the
-// connector also closes the pipe.
-//
-// Example of an implementation that is always bound strongly to a pipe
+// connection error is detected the implementation is deleted.
//
-// class StronglyBound : public Foo {
-// public:
-// explicit StronglyBound(InterfaceRequest<Foo> request)
-// : binding_(this, std::move(request)) {}
+// To use, call StrongBinding<T>::Create() (see below) or the helper
+// MakeStrongBinding function:
//
-// // Foo implementation here
+// mojo::MakeStrongBinding(base::MakeUnique<FooImpl>(),
+// std::move(foo_request));
//
-// private:
-// StrongBinding<Foo> binding_;
-// };
-//
-// class MyFooFactory : public InterfaceFactory<Foo> {
-// public:
-// void Create(..., InterfaceRequest<Foo> request) override {
-// new StronglyBound(std::move(request)); // The binding now owns the
-// // instance of StronglyBound.
-// }
-// };
-//
-// This class is thread hostile once it is bound to a message pipe. Until it is
-// bound, it may be bound or destroyed on any thread.
template <typename Interface>
class StrongBinding {
public:
- explicit StrongBinding(Interface* impl) : binding_(impl) {}
-
- StrongBinding(Interface* impl, ScopedMessagePipeHandle handle)
- : StrongBinding(impl) {
- Bind(std::move(handle));
- }
-
- StrongBinding(Interface* impl, InterfacePtr<Interface>* ptr)
- : StrongBinding(impl) {
- Bind(ptr);
- }
-
- StrongBinding(Interface* impl, InterfaceRequest<Interface> request)
- : StrongBinding(impl) {
- Bind(std::move(request));
- }
-
- ~StrongBinding() {}
-
- void Bind(ScopedMessagePipeHandle handle) {
- DCHECK(!binding_.is_bound());
- binding_.Bind(std::move(handle));
- binding_.set_connection_error_handler(
- base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
- }
-
- void Bind(InterfacePtr<Interface>* ptr) {
- DCHECK(!binding_.is_bound());
- binding_.Bind(ptr);
- binding_.set_connection_error_handler(
- base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
- }
-
- void Bind(InterfaceRequest<Interface> request) {
- DCHECK(!binding_.is_bound());
- binding_.Bind(std::move(request));
- binding_.set_connection_error_handler(
- base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
- }
-
- bool WaitForIncomingMethodCall() {
- return binding_.WaitForIncomingMethodCall();
+ // Create a new StrongBinding instance. The instance owns itself, cleaning up
+ // only in the event of a pipe connection error. Returns a WeakPtr to the new
+ // StrongBinding instance.
+ static StrongBindingPtr<Interface> Create(
+ std::unique_ptr<Interface> impl,
+ InterfaceRequest<Interface> request) {
+ StrongBinding* binding =
+ new StrongBinding(std::move(impl), std::move(request));
+ return binding->weak_factory_.GetWeakPtr();
}
// Note: The error handler must not delete the interface implementation.
@@ -102,25 +61,67 @@ class StrongBinding {
void set_connection_error_handler(const base::Closure& error_handler) {
DCHECK(binding_.is_bound());
connection_error_handler_ = error_handler;
+ connection_error_with_reason_handler_.Reset();
}
- Interface* impl() { return binding_.impl(); }
+ void set_connection_error_with_reason_handler(
+ const ConnectionErrorWithReasonCallback& error_handler) {
+ DCHECK(binding_.is_bound());
+ connection_error_with_reason_handler_ = error_handler;
+ connection_error_handler_.Reset();
+ }
+
+ // Forces the binding to close. This destroys the StrongBinding instance.
+ void Close() { delete this; }
+
+ Interface* impl() { return impl_.get(); }
+
// Exposed for testing, should not generally be used.
internal::Router* internal_router() { return binding_.internal_router(); }
- void OnConnectionError() {
+ // Sends a message on the underlying message pipe and runs the current
+ // message loop until its response is received. This can be used in tests to
+ // verify that no message was sent on a message pipe in response to some
+ // stimulus.
+ void FlushForTesting() { binding_.FlushForTesting(); }
+
+ private:
+ StrongBinding(std::unique_ptr<Interface> impl,
+ InterfaceRequest<Interface> request)
+ : impl_(std::move(impl)),
+ binding_(impl_.get(), std::move(request)),
+ weak_factory_(this) {
+ binding_.set_connection_error_with_reason_handler(
+ base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
+ }
+
+ ~StrongBinding() {}
+
+ void OnConnectionError(uint32_t custom_reason,
+ const std::string& description) {
if (!connection_error_handler_.is_null())
connection_error_handler_.Run();
- delete binding_.impl();
+ else if (!connection_error_with_reason_handler_.is_null())
+ connection_error_with_reason_handler_.Run(custom_reason, description);
+ Close();
}
- private:
+ std::unique_ptr<Interface> impl_;
base::Closure connection_error_handler_;
+ ConnectionErrorWithReasonCallback connection_error_with_reason_handler_;
Binding<Interface> binding_;
+ base::WeakPtrFactory<StrongBinding> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(StrongBinding);
};
+template <typename Interface, typename Impl>
+StrongBindingPtr<Interface> MakeStrongBinding(
+ std::unique_ptr<Impl> impl,
+ InterfaceRequest<Interface> request) {
+ return StrongBinding<Interface>::Create(std::move(impl), std::move(request));
+}
+
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
diff --git a/chromium/mojo/public/cpp/bindings/struct_ptr.h b/chromium/mojo/public/cpp/bindings/struct_ptr.h
index 92f2728a3a0..dbc3256ea78 100644
--- a/chromium/mojo/public/cpp/bindings/struct_ptr.h
+++ b/chromium/mojo/public/cpp/bindings/struct_ptr.h
@@ -5,15 +5,19 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
#define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
+#include <functional>
#include <new>
#include "base/logging.h"
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/lib/hash_util.h"
#include "mojo/public/cpp/bindings/type_converter.h"
namespace mojo {
namespace internal {
+constexpr size_t kHashSeed = 31;
+
template <typename Struct>
class StructHelper {
public:
@@ -23,6 +27,12 @@ class StructHelper {
}
};
+template <typename Struct>
+class StructPtrWTFHelper;
+
+template <typename Struct>
+class InlinedStructPtrWTFHelper;
+
} // namespace internal
// Smart pointer wrapping a mojom structure with move-only semantics.
@@ -78,28 +88,26 @@ class StructPtr {
// that it contains Mojo handles).
StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); }
+ // Compares the pointees (which might both be null).
+ // TODO(tibell): Get rid of Equals in favor of the operator. Same for Hash.
bool Equals(const StructPtr& other) const {
if (is_null() || other.is_null())
return is_null() && other.is_null();
return ptr_->Equals(*other.ptr_);
}
- private:
- // TODO(dcheng): Use an explicit conversion operator.
- typedef Struct* StructPtr::*Testable;
+ // Hashes based on the pointee (which might be null).
+ size_t Hash(size_t seed) const {
+ if (is_null())
+ return internal::HashCombine(seed, 0);
+ return ptr_->Hash(seed);
+ }
- public:
- operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; }
+ explicit operator bool() const { return !is_null(); }
private:
friend class internal::StructHelper<Struct>;
-
- // Forbid the == and != operators explicitly, otherwise StructPtr will be
- // converted to Testable to do == or != comparison.
- template <typename T>
- bool operator==(const StructPtr<T>& other) const = delete;
- template <typename T>
- bool operator!=(const StructPtr<T>& other) const = delete;
+ friend class internal::StructPtrWTFHelper<Struct>;
void Initialize() {
DCHECK(!ptr_);
@@ -116,14 +124,23 @@ class StructPtr {
DISALLOW_COPY_AND_ASSIGN(StructPtr);
};
+template <typename T>
+bool operator==(const StructPtr<T>& lhs, const StructPtr<T>& rhs) {
+ return lhs.Equals(rhs);
+}
+template <typename T>
+bool operator!=(const StructPtr<T>& lhs, const StructPtr<T>& rhs) {
+ return !(lhs == rhs);
+}
+
// Designed to be used when Struct is small and copyable.
template <typename S>
class InlinedStructPtr {
public:
using Struct = S;
- InlinedStructPtr() : is_null_(true) {}
- InlinedStructPtr(decltype(nullptr)) : is_null_(true) {}
+ InlinedStructPtr() : state_(NIL) {}
+ InlinedStructPtr(decltype(nullptr)) : state_(NIL) {}
~InlinedStructPtr() {}
@@ -132,7 +149,7 @@ class InlinedStructPtr {
return *this;
}
- InlinedStructPtr(InlinedStructPtr&& other) : is_null_(true) { Take(&other); }
+ InlinedStructPtr(InlinedStructPtr&& other) : state_(NIL) { Take(&other); }
InlinedStructPtr& operator=(InlinedStructPtr&& other) {
Take(&other);
return *this;
@@ -144,67 +161,138 @@ class InlinedStructPtr {
}
void reset() {
- is_null_ = true;
+ state_ = NIL;
value_. ~Struct();
new (&value_) Struct();
}
- bool is_null() const { return is_null_; }
+ bool is_null() const { return state_ == NIL; }
Struct& operator*() const {
- DCHECK(!is_null_);
+ DCHECK(state_ == VALID);
return value_;
}
Struct* operator->() const {
- DCHECK(!is_null_);
+ DCHECK(state_ == VALID);
return &value_;
}
Struct* get() const { return &value_; }
void Swap(InlinedStructPtr* other) {
std::swap(value_, other->value_);
- std::swap(is_null_, other->is_null_);
+ std::swap(state_, other->state_);
}
InlinedStructPtr Clone() const {
return is_null() ? InlinedStructPtr() : value_.Clone();
}
+
+ // Compares the pointees (which might both be null).
bool Equals(const InlinedStructPtr& other) const {
if (is_null() || other.is_null())
return is_null() && other.is_null();
return value_.Equals(other.value_);
}
- private:
- // TODO(dcheng): Use an explicit conversion operator.
- typedef Struct InlinedStructPtr::*Testable;
+ // Hashes based on the pointee (which might be null).
+ size_t Hash(size_t seed) const {
+ if (is_null())
+ return internal::HashCombine(seed, 0);
+ return value_.Hash(seed);
+ }
- public:
- operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; }
+ explicit operator bool() const { return !is_null(); }
private:
friend class internal::StructHelper<Struct>;
+ friend class internal::InlinedStructPtrWTFHelper<Struct>;
- // Forbid the == and != operators explicitly, otherwise InlinedStructPtr will
- // be converted to Testable to do == or != comparison.
- template <typename T>
- bool operator==(const InlinedStructPtr<T>& other) const = delete;
- template <typename T>
- bool operator!=(const InlinedStructPtr<T>& other) const = delete;
-
- void Initialize() { is_null_ = false; }
+ void Initialize() { state_ = VALID; }
void Take(InlinedStructPtr* other) {
reset();
Swap(other);
}
+ enum State {
+ VALID,
+ NIL,
+ DELETED, // For use in WTF::HashMap only
+ };
+
mutable Struct value_;
- bool is_null_;
+ State state_;
DISALLOW_COPY_AND_ASSIGN(InlinedStructPtr);
};
+template <typename T>
+bool operator==(const InlinedStructPtr<T>& lhs,
+ const InlinedStructPtr<T>& rhs) {
+ return lhs.Equals(rhs);
+}
+template <typename T>
+bool operator!=(const InlinedStructPtr<T>& lhs,
+ const InlinedStructPtr<T>& rhs) {
+ return !(lhs == rhs);
+}
+
+namespace internal {
+
+template <typename Struct>
+class StructPtrWTFHelper {
+ public:
+ static bool IsHashTableDeletedValue(const StructPtr<Struct>& value) {
+ return value.ptr_ == reinterpret_cast<Struct*>(1u);
+ }
+
+ static void ConstructDeletedValue(mojo::StructPtr<Struct>& slot) {
+ // |slot| refers to a previous, real value that got deleted and had its
+ // destructor run, so this is the first time the "deleted value" has its
+ // constructor called.
+ //
+ // Dirty trick: implant an invalid pointer in |ptr_|. Destructor isn't
+ // called for deleted buckets, so this is okay.
+ new (&slot) StructPtr<Struct>();
+ slot.ptr_ = reinterpret_cast<Struct*>(1u);
+ }
+};
+
+template <typename Struct>
+class InlinedStructPtrWTFHelper {
+ public:
+ static bool IsHashTableDeletedValue(const InlinedStructPtr<Struct>& value) {
+ return value.state_ == InlinedStructPtr<Struct>::DELETED;
+ }
+
+ static void ConstructDeletedValue(mojo::InlinedStructPtr<Struct>& slot) {
+ // |slot| refers to a previous, real value that got deleted and had its
+ // destructor run, so this is the first time the "deleted value" has its
+ // constructor called.
+ new (&slot) InlinedStructPtr<Struct>();
+ slot.state_ = InlinedStructPtr<Struct>::DELETED;
+ }
+};
+
+} // namespace internal
} // namespace mojo
+namespace std {
+
+template <typename T>
+struct hash<mojo::StructPtr<T>> {
+ size_t operator()(const mojo::StructPtr<T>& value) const {
+ return value.Hash(mojo::internal::kHashSeed);
+ }
+};
+
+template <typename T>
+struct hash<mojo::InlinedStructPtr<T>> {
+ size_t operator()(const mojo::InlinedStructPtr<T>& value) const {
+ return value.Hash(mojo::internal::kHashSeed);
+ }
+};
+
+} // namespace std
+
#endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
diff --git a/chromium/mojo/public/cpp/bindings/struct_traits.h b/chromium/mojo/public/cpp/bindings/struct_traits.h
index 0f0bea73dd7..a1379fe28c9 100644
--- a/chromium/mojo/public/cpp/bindings/struct_traits.h
+++ b/chromium/mojo/public/cpp/bindings/struct_traits.h
@@ -8,7 +8,11 @@
namespace mojo {
// This must be specialized for any type |T| to be serialized/deserialized as
-// a mojom struct of type |MojomType|.
+// a mojom struct. |DataViewType| is the corresponding data view type of the
+// mojom struct. For example, if the mojom struct is example.Foo,
+// |DataViewType| will be example::FooDataView, which can also be referred to by
+// example::Foo::DataView (in chromium) and example::blink::Foo::DataView (in
+// blink).
//
// Each specialization needs to implement a few things:
// 1. Static getters for each field in the Mojom type. These should be
@@ -20,19 +24,22 @@ namespace mojo {
// from |input|.
//
// Serializable form of a field:
-// Value or reference of the same type used in |MojomType|, or the
-// following alternatives:
+// Value or reference of the same type used in the generated stuct
+// wrapper type, or the following alternatives:
// - string:
// Value or reference of any type that has a StringTraits defined.
-// Supported by default: base::StringPiece, std::string.
+// Supported by default: base::StringPiece, std::string, mojo::String,
+// WTF::String (in blink).
//
// - array:
// Value or reference of any type that has an ArrayTraits defined.
-// Supported by default: std::vector, WTF::Vector (in blink), CArray.
+// Supported by default: std::vector, CArray, mojo::Array, WTF::Vector
+// (in blink), mojo::WTFArray (in blink).
//
// - map:
// Value or reference of any type that has a MapTraits defined.
-// Supported by default: std::map.
+// Supported by default: std::map, std::unordered_map, mojo::Map,
+// WTF::HashMap (in blink), mojo::WTFMap (in blink).
//
// - struct:
// Value or reference of any type that has a StructTraits defined.
@@ -40,6 +47,10 @@ namespace mojo {
// - enum:
// Value of any type that has an EnumTraits defined.
//
+// For any nullable string/struct/array/map/union field you could also
+// return value or reference of base::Optional<T>/WTF::Optional<T>, if T
+// has the right *Traits defined.
+//
// During serialization, getters for string/struct/array/map/union fields
// are called twice (one for size calculation and one for actual
// serialization). If you want to return a value (as opposed to a
@@ -49,13 +60,13 @@ namespace mojo {
// Getters for fields of other types are called once.
//
// 2. A static Read() method to set the contents of a |T| instance from a
-// |MojomType|DataView (e.g., if |MojomType| is test::Example, the data
-// view will be test::ExampleDataView).
+// DataViewType.
//
-// static bool Read(|MojomType|DataView data, T* output);
+// static bool Read(DataViewType data, T* output);
//
-// The generated |MojomType|DataView type provides a convenient,
-// inexpensive view of a serialized struct's field data.
+// The generated DataViewType provides a convenient, inexpensive view of a
+// serialized struct's field data. The caller guarantees that
+// |!data.is_null()|.
//
// Returning false indicates invalid incoming data and causes the message
// pipe receiving it to be disconnected. Therefore, you can do custom
@@ -111,9 +122,12 @@ namespace mojo {
// reference/value to the Mojo bindings for serialization:
// - if T is used in the "type_mappings" section of a typemap config file,
// you need to declare it as pass-by-value:
-// type_mappings = [ "MojomType=T(pass_by_value)" ]
-// - if another type U's StructTraits has a getter for T, it needs to return
-// non-const reference/value.
+// type_mappings = [ "MojomType=T[move_only]" ]
+// or
+// type_mappings = [ "MojomType=T[copyable_pass_by_value]" ]
+//
+// - if another type U's StructTraits/UnionTraits has a getter for T, it
+// needs to return non-const reference/value.
//
// EXAMPLE:
//
@@ -128,7 +142,7 @@ namespace mojo {
//
// StructTraits for Foo:
// template <>
-// struct StructTraits<Foo, CustomFoo> {
+// struct StructTraits<FooDataView, CustomFoo> {
// // Optional methods dealing with null:
// static bool IsNull(const CustomFoo& input);
// static void SetToNull(CustomFoo* output);
@@ -144,7 +158,7 @@ namespace mojo {
// static bool Read(FooDataView data, CustomFoo* output);
// };
//
-template <typename MojomType, typename T>
+template <typename DataViewType, typename T>
struct StructTraits;
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/bindings/sync_call_restrictions.h b/chromium/mojo/public/cpp/bindings/sync_call_restrictions.h
index 78c1b7f3b9d..dccd7309519 100644
--- a/chromium/mojo/public/cpp/bindings/sync_call_restrictions.h
+++ b/chromium/mojo/public/cpp/bindings/sync_call_restrictions.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/threading/thread_restrictions.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
#define ENABLE_SYNC_CALL_RESTRICTIONS 1
@@ -14,7 +15,7 @@
#define ENABLE_SYNC_CALL_RESTRICTIONS 0
#endif
-namespace mus {
+namespace ui {
class GpuService;
}
@@ -36,7 +37,7 @@ namespace mojo {
// a very compelling reason to disregard that (which should be very very rare),
// you can override it by constructing a ScopedAllowSyncCall object, which
// allows making sync calls on the current thread during its lifetime.
-class SyncCallRestrictions {
+class MOJO_CPP_BINDINGS_EXPORT SyncCallRestrictions {
public:
#if ENABLE_SYNC_CALL_RESTRICTIONS
// Checks whether the current thread is allowed to make sync calls, and causes
@@ -50,7 +51,7 @@ class SyncCallRestrictions {
private:
// DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to mojo/OWNERS first.
// BEGIN ALLOWED USAGE.
- friend class mus::GpuService; // http://crbug.com/620058
+ friend class ui::GpuService; // http://crbug.com/620058
// END ALLOWED USAGE.
// BEGIN USAGE THAT NEEDS TO BE FIXED.
diff --git a/chromium/mojo/public/cpp/bindings/sync_handle_registry.h b/chromium/mojo/public/cpp/bindings/sync_handle_registry.h
index 6c0701ef6f4..b5415af80df 100644
--- a/chromium/mojo/public/cpp/bindings/sync_handle_registry.h
+++ b/chromium/mojo/public/cpp/bindings/sync_handle_registry.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/system/core.h"
namespace mojo {
@@ -19,7 +20,8 @@ namespace mojo {
// be watched together.
//
// This class is not thread safe.
-class SyncHandleRegistry : public base::RefCounted<SyncHandleRegistry> {
+class MOJO_CPP_BINDINGS_EXPORT SyncHandleRegistry
+ : public base::RefCounted<SyncHandleRegistry> {
public:
// Returns a thread-local object.
static scoped_refptr<SyncHandleRegistry> current();
diff --git a/chromium/mojo/public/cpp/bindings/sync_handle_watcher.h b/chromium/mojo/public/cpp/bindings/sync_handle_watcher.h
index 36b796bf0d9..eff73dd66e0 100644
--- a/chromium/mojo/public/cpp/bindings/sync_handle_watcher.h
+++ b/chromium/mojo/public/cpp/bindings/sync_handle_watcher.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/bindings/sync_handle_registry.h"
#include "mojo/public/cpp/system/core.h"
@@ -25,7 +26,7 @@ namespace mojo {
// associated endpoints on different threads.
//
// This class is not thread safe.
-class SyncHandleWatcher {
+class MOJO_CPP_BINDINGS_EXPORT SyncHandleWatcher {
public:
// Note: |handle| must outlive this object.
SyncHandleWatcher(const Handle& handle,
diff --git a/chromium/mojo/public/cpp/bindings/tests/BUILD.gn b/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
index 4e38f15032a..7326f2a4a31 100644
--- a/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -2,8 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("../../../mojo_application.gni")
-
source_set("tests") {
testonly = true
@@ -13,20 +11,24 @@ source_set("tests") {
"associated_interface_unittest.cc",
"bind_task_runner_unittest.cc",
"binding_callback_unittest.cc",
+ "binding_set_unittest.cc",
"binding_unittest.cc",
"buffer_unittest.cc",
"connector_unittest.cc",
"constant_unittest.cc",
"container_test_util.cc",
"container_test_util.h",
+ "data_view_unittest.cc",
"equals_unittest.cc",
"handle_passing_unittest.cc",
+ "hash_unittest.cc",
"interface_ptr_unittest.cc",
"map_common_test.h",
"map_unittest.cc",
"message_queue.cc",
"message_queue.h",
"multiplex_router_unittest.cc",
+ "report_bad_message_unittest.cc",
"request_response_unittest.cc",
"router_test_util.cc",
"router_test_util.h",
@@ -46,10 +48,12 @@ source_set("tests") {
deps = [
":mojo_public_bindings_test_utils",
+ "//mojo/edk/system",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//mojo/public/cpp/test_support:test_utils",
"//mojo/public/interfaces/bindings/tests:test_associated_interfaces",
+ "//mojo/public/interfaces/bindings/tests:test_export_component",
"//mojo/public/interfaces/bindings/tests:test_interfaces",
"//mojo/public/interfaces/bindings/tests:test_interfaces_experimental",
"//mojo/public/interfaces/bindings/tests:test_struct_traits_interfaces",
@@ -83,6 +87,7 @@ if (!is_ios) {
"map_common_test.h",
"variant_test_util.h",
"wtf_array_unittest.cc",
+ "wtf_hash_unittest.cc",
"wtf_map_unittest.cc",
"wtf_types_unittest.cc",
]
@@ -91,6 +96,7 @@ if (!is_ios) {
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//mojo/public/interfaces/bindings/tests:test_interfaces",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces_blink",
"//mojo/public/interfaces/bindings/tests:test_wtf_types",
"//mojo/public/interfaces/bindings/tests:test_wtf_types_blink",
"//testing/gtest",
diff --git a/chromium/mojo/public/cpp/bindings/tests/rect_blink.typemap b/chromium/mojo/public/cpp/bindings/tests/rect_blink.typemap
index 37ee409edf1..657ea1a6cab 100644
--- a/chromium/mojo/public/cpp/bindings/tests/rect_blink.typemap
+++ b/chromium/mojo/public/cpp/bindings/tests/rect_blink.typemap
@@ -3,7 +3,16 @@
# found in the LICENSE file.
mojom = "//mojo/public/interfaces/bindings/tests/rect.mojom"
-public_headers = [ "//mojo/public/cpp/bindings/tests/rect_blink.h" ]
-traits_headers = [ "//mojo/public/cpp/bindings/tests/rect_blink_traits.h" ]
+public_headers = [
+ "//mojo/public/cpp/bindings/tests/rect_blink.h",
+ "//mojo/public/cpp/bindings/tests/shared_rect.h",
+]
+traits_headers = [
+ "//mojo/public/cpp/bindings/tests/rect_blink_traits.h",
+ "//mojo/public/cpp/bindings/tests/shared_rect_traits.h",
+]
-type_mappings = [ "mojo.test.TypemappedRect=mojo::test::RectBlink" ]
+type_mappings = [
+ "mojo.test.TypemappedRect=mojo::test::RectBlink[hashable]",
+ "mojo.test.SharedTypemappedRect=mojo::test::SharedRect",
+]
diff --git a/chromium/mojo/public/cpp/bindings/tests/rect_chromium.typemap b/chromium/mojo/public/cpp/bindings/tests/rect_chromium.typemap
index 0da40211a49..7e5df8401ae 100644
--- a/chromium/mojo/public/cpp/bindings/tests/rect_chromium.typemap
+++ b/chromium/mojo/public/cpp/bindings/tests/rect_chromium.typemap
@@ -3,7 +3,16 @@
# found in the LICENSE file.
mojom = "//mojo/public/interfaces/bindings/tests/rect.mojom"
-public_headers = [ "//mojo/public/cpp/bindings/tests/rect_chromium.h" ]
-traits_headers = [ "//mojo/public/cpp/bindings/tests/rect_chromium_traits.h" ]
+public_headers = [
+ "//mojo/public/cpp/bindings/tests/rect_chromium.h",
+ "//mojo/public/cpp/bindings/tests/shared_rect.h",
+]
+traits_headers = [
+ "//mojo/public/cpp/bindings/tests/rect_chromium_traits.h",
+ "//mojo/public/cpp/bindings/tests/shared_rect_traits.h",
+]
-type_mappings = [ "mojo.test.TypemappedRect=mojo::test::RectChromium" ]
+type_mappings = [
+ "mojo.test.TypemappedRect=mojo::test::RectChromium[hashable]",
+ "mojo.test.SharedTypemappedRect=mojo::test::SharedRect",
+]
diff --git a/chromium/mojo/public/cpp/bindings/tests/struct_with_traits.typemap b/chromium/mojo/public/cpp/bindings/tests/struct_with_traits.typemap
index fb9d01d38a1..752ce44b58e 100644
--- a/chromium/mojo/public/cpp/bindings/tests/struct_with_traits.typemap
+++ b/chromium/mojo/public/cpp/bindings/tests/struct_with_traits.typemap
@@ -19,6 +19,8 @@ type_mappings = [
"mojo.test.EnumWithTraits=mojo::test::EnumWithTraitsImpl",
"mojo.test.StructWithTraits=mojo::test::StructWithTraitsImpl",
"mojo.test.NestedStructWithTraits=mojo::test::NestedStructWithTraitsImpl",
- "mojo.test.PassByValueStructWithTraits=mojo::test::PassByValueStructWithTraitsImpl[pass_by_value]",
- "mojo.test.StructWithTraitsForUniquePtrTest=std::unique_ptr<int>[pass_by_value]",
+ "mojo.test.TrivialStructWithTraits=mojo::test::TrivialStructWithTraitsImpl[copyable_pass_by_value]",
+ "mojo.test.MoveOnlyStructWithTraits=mojo::test::MoveOnlyStructWithTraitsImpl[move_only]",
+ "mojo.test.StructWithTraitsForUniquePtr=std::unique_ptr<int>[move_only,nullable_is_same_type]",
+ "mojo.test.UnionWithTraits=std::unique_ptr<mojo::test::UnionWithTraitsBase>[move_only,nullable_is_same_type]",
]
diff --git a/chromium/mojo/public/cpp/bindings/union_traits.h b/chromium/mojo/public/cpp/bindings/union_traits.h
new file mode 100644
index 00000000000..292ee58f277
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/union_traits.h
@@ -0,0 +1,39 @@
+// Copyright 2016 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_UNION_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_UNION_TRAITS_H_
+
+namespace mojo {
+
+// This must be specialized for any type |T| to be serialized/deserialized as
+// a mojom union. |DataViewType| is the corresponding data view type of the
+// mojom union. For example, if the mojom union is example.Foo, |DataViewType|
+// will be example::FooDataView, which can also be referred to by
+// example::Foo::DataView (in chromium) and example::blink::Foo::DataView (in
+// blink).
+//
+// Similar to StructTraits, each specialization of UnionTraits implements the
+// following methods:
+// 1. Getters for each field in the Mojom type.
+// 2. Read() method.
+// 3. [Optional] IsNull() and SetToNull().
+// 4. [Optional] SetUpContext() and TearDownContext().
+// Please see the documentation of StructTraits for details of these methods.
+//
+// Unlike StructTraits, there is one more method to implement:
+// 5. A static GetTag() method indicating which field is the current active
+// field for serialization:
+//
+// static DataViewType::Tag GetTag(const T& input);
+//
+// During serialization, only the field getter corresponding to this tag
+// will be called.
+//
+template <typename DataViewType, typename T>
+struct UnionTraits;
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_UNION_TRAITS_H_
diff --git a/chromium/mojo/public/cpp/bindings/wtf_array.h b/chromium/mojo/public/cpp/bindings/wtf_array.h
index 116d1b9ddca..46d9a6958bd 100644
--- a/chromium/mojo/public/cpp/bindings/wtf_array.h
+++ b/chromium/mojo/public/cpp/bindings/wtf_array.h
@@ -12,6 +12,7 @@
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
+#include "mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "third_party/WebKit/Source/wtf/Vector.h"
@@ -147,9 +148,7 @@ class WTFArray {
WTFArray Clone() const {
WTFArray result;
result.is_null_ = is_null_;
- result.vec_.reserveCapacity(vec_.size());
- for (const auto& element : vec_)
- result.vec_.append(internal::Clone(element));
+ result.vec_ = internal::Clone(vec_);
return result;
}
@@ -159,13 +158,7 @@ class WTFArray {
bool Equals(const WTFArray& other) const {
if (is_null() != other.is_null())
return false;
- if (size() != other.size())
- return false;
- for (size_t i = 0; i < size(); ++i) {
- if (!internal::Equals(at(i), other.at(i)))
- return false;
- }
- return true;
+ return internal::Equals(vec_, other.vec_);
}
private:
diff --git a/chromium/mojo/public/cpp/bindings/wtf_map.h b/chromium/mojo/public/cpp/bindings/wtf_map.h
index 18d0c42b3ec..0aba9595172 100644
--- a/chromium/mojo/public/cpp/bindings/wtf_map.h
+++ b/chromium/mojo/public/cpp/bindings/wtf_map.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
+#include "mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "third_party/WebKit/Source/wtf/HashMap.h"
#include "third_party/WebKit/Source/wtf/text/StringHash.h"
@@ -156,9 +157,7 @@ class WTFMap {
WTFMap Clone() const {
WTFMap result;
result.is_null_ = is_null_;
- auto map_end = map_.end();
- for (auto it = map_.begin(); it != map_end; ++it)
- result.map_.add(internal::Clone(it->key), internal::Clone(it->value));
+ result.map_ = internal::Clone(map_);
return result;
}
@@ -168,20 +167,7 @@ class WTFMap {
bool Equals(const WTFMap& other) const {
if (is_null() != other.is_null())
return false;
- if (size() != other.size())
- return false;
-
- auto this_end = map_.end();
- auto other_end = other.map_.end();
-
- for (auto iter = map_.begin(); iter != this_end; ++iter) {
- auto other_iter = other.map_.find(iter->key);
- if (other_iter == other_end ||
- !internal::Equals(iter->value, other_iter->value)) {
- return false;
- }
- }
- return true;
+ return internal::Equals(map_, other.map_);
}
ConstIterator begin() const { return map_.begin(); }
diff --git a/chromium/mojo/public/cpp/system/BUILD.gn b/chromium/mojo/public/cpp/system/BUILD.gn
index 8dcec718688..0dc7af9d4d7 100644
--- a/chromium/mojo/public/cpp/system/BUILD.gn
+++ b/chromium/mojo/public/cpp/system/BUILD.gn
@@ -2,7 +2,26 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-source_set("system") {
+# Deletes libsystem.dylib from the build dir, since it shadows
+# /usr/lib/libSystem.dylib on macOS.
+# TODO(thakis): Remove this after a while.
+action("clean_up_old_dylib") {
+ script = "//build/rm.py"
+ stamp = "$target_gen_dir/clean_up_stamp"
+ outputs = [
+ stamp,
+ ]
+ args = [
+ "--stamp",
+ rebase_path(stamp, root_build_dir),
+ "-f",
+ "libsystem.dylib",
+ ]
+}
+
+component("system") {
+ output_name = "mojo_public_system_cpp"
+
sources = [
"buffer.cc",
"buffer.h",
@@ -14,6 +33,7 @@ source_set("system") {
"message_pipe.h",
"platform_handle.cc",
"platform_handle.h",
+ "system_export.h",
"watcher.cc",
"watcher.h",
]
@@ -22,4 +42,9 @@ source_set("system") {
"//base",
"//mojo/public/c/system",
]
+ deps = [
+ ":clean_up_old_dylib",
+ ]
+
+ defines = [ "MOJO_CPP_SYSTEM_IMPLEMENTATION" ]
}
diff --git a/chromium/mojo/public/cpp/system/buffer.h b/chromium/mojo/public/cpp/system/buffer.h
index 449c6ce02f3..1ae923cb751 100644
--- a/chromium/mojo/public/cpp/system/buffer.h
+++ b/chromium/mojo/public/cpp/system/buffer.h
@@ -20,6 +20,7 @@
#include "base/logging.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/cpp/system/handle.h"
+#include "mojo/public/cpp/system/system_export.h"
namespace mojo {
namespace internal {
@@ -41,7 +42,8 @@ typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;
// A strongly-typed representation of a |MojoHandle| referring to a shared
// buffer.
-class SharedBufferHandle : public Handle {
+class MOJO_CPP_SYSTEM_EXPORT SharedBufferHandle
+ : NON_EXPORTED_BASE(public Handle) {
public:
enum class AccessMode {
READ_WRITE,
diff --git a/chromium/mojo/public/cpp/system/platform_handle.h b/chromium/mojo/public/cpp/system/platform_handle.h
index 2a8173427b8..f30f2cfd8ec 100644
--- a/chromium/mojo/public/cpp/system/platform_handle.h
+++ b/chromium/mojo/public/cpp/system/platform_handle.h
@@ -22,6 +22,7 @@
#include "mojo/public/c/system/platform_handle.h"
#include "mojo/public/cpp/system/buffer.h"
#include "mojo/public/cpp/system/handle.h"
+#include "mojo/public/cpp/system/system_export.h"
#if defined(OS_WIN)
#include <windows.h>
@@ -50,9 +51,11 @@ const MojoPlatformHandleType kPlatformSharedBufferHandleType =
#endif // defined(OS_POSIX)
// Wraps a PlatformFile as a Mojo handle. Takes ownership of the file object.
+MOJO_CPP_SYSTEM_EXPORT
ScopedHandle WrapPlatformFile(base::PlatformFile platform_file);
// Unwraps a PlatformFile from a Mojo handle.
+MOJO_CPP_SYSTEM_EXPORT
MojoResult UnwrapPlatformFile(ScopedHandle handle, base::PlatformFile* file);
// Wraps a base::SharedMemoryHandle as a Mojo handle. Takes ownership of the
@@ -66,10 +69,11 @@ ScopedSharedBufferHandle WrapSharedMemoryHandle(
// Unwraps a base::SharedMemoryHandle from a Mojo handle. The caller assumes
// responsibility for the lifetime of the SharedMemoryHandle.
-MojoResult UnwrapSharedMemoryHandle(ScopedSharedBufferHandle handle,
- base::SharedMemoryHandle* memory_handle,
- size_t* size,
- bool* read_only);
+MOJO_CPP_SYSTEM_EXPORT MojoResult
+UnwrapSharedMemoryHandle(ScopedSharedBufferHandle handle,
+ base::SharedMemoryHandle* memory_handle,
+ size_t* size,
+ bool* read_only);
} // namespace mojo
diff --git a/chromium/mojo/public/cpp/system/system_export.h b/chromium/mojo/public/cpp/system/system_export.h
new file mode 100644
index 00000000000..c9bb140db3a
--- /dev/null
+++ b/chromium/mojo/public/cpp/system/system_export.h
@@ -0,0 +1,34 @@
+// Copyright 2016 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_SYSTEM_EXPORT_H_
+#define MOJO_PUBLIC_CPP_SYSTEM_SYSTEM_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+
+#if defined(WIN32)
+
+#if defined(MOJO_CPP_SYSTEM_IMPLEMENTATION)
+#define MOJO_CPP_SYSTEM_EXPORT __declspec(dllexport)
+#else
+#define MOJO_CPP_SYSTEM_EXPORT __declspec(dllimport)
+#endif
+
+#else // !defined(WIN32)
+
+#if defined(MOJO_CPP_SYSTEM_IMPLEMENTATION)
+#define MOJO_CPP_SYSTEM_EXPORT __attribute((visibility("default")))
+#else
+#define MOJO_CPP_SYSTEM_EXPORT
+#endif
+
+#endif // defined(WIN32)
+
+#else // !defined(COMPONENT_BUILD)
+
+#define MOJO_CPP_SYSTEM_EXPORT
+
+#endif // defined(COMPONENT_BUILD)
+
+#endif // MOJO_PUBLIC_CPP_SYSTEM_SYSTEM_EXPORT_H_
diff --git a/chromium/mojo/public/cpp/system/watcher.h b/chromium/mojo/public/cpp/system/watcher.h
index 82f3e816fb2..3284154b2d8 100644
--- a/chromium/mojo/public/cpp/system/watcher.h
+++ b/chromium/mojo/public/cpp/system/watcher.h
@@ -16,13 +16,14 @@
#include "base/threading/thread_task_runner_handle.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/handle.h"
+#include "mojo/public/cpp/system/system_export.h"
namespace mojo {
// A Watcher watches a single Mojo handle for signal state changes.
//
// NOTE: Watchers may only be used on threads which have a running MessageLoop.
-class Watcher {
+class MOJO_CPP_SYSTEM_EXPORT Watcher {
public:
// A callback to be called any time a watched handle changes state in some
// interesting way. The |result| argument indicates one of the following
diff --git a/chromium/mojo/public/cpp/test_support/BUILD.gn b/chromium/mojo/public/cpp/test_support/BUILD.gn
index 308b8036ff9..efa1712fff3 100644
--- a/chromium/mojo/public/cpp/test_support/BUILD.gn
+++ b/chromium/mojo/public/cpp/test_support/BUILD.gn
@@ -2,8 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# GYP version: mojo/public/mojo_public.gyp:mojo_public_test_utils
-source_set("test_utils") {
+static_library("test_utils") {
testonly = true
sources = [
diff --git a/chromium/mojo/public/interfaces/bindings/BUILD.gn b/chromium/mojo/public/interfaces/bindings/BUILD.gn
index c7421b9ece1..706e3efd5fc 100644
--- a/chromium/mojo/public/interfaces/bindings/BUILD.gn
+++ b/chromium/mojo/public/interfaces/bindings/BUILD.gn
@@ -9,4 +9,8 @@ mojom("bindings") {
"interface_control_messages.mojom",
"pipe_control_messages.mojom",
]
+
+ export_class_attribute = "MOJO_CPP_BINDINGS_EXPORT"
+ export_define = "MOJO_CPP_BINDINGS_IMPLEMENTATION"
+ export_header = "mojo/public/cpp/bindings/bindings_export.h"
}
diff --git a/chromium/mojo/public/interfaces/bindings/OWNERS b/chromium/mojo/public/interfaces/bindings/OWNERS
new file mode 100644
index 00000000000..08850f42120
--- /dev/null
+++ b/chromium/mojo/public/interfaces/bindings/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/mojo/public/interfaces/bindings/interface_control_messages.mojom b/chromium/mojo/public/interfaces/bindings/interface_control_messages.mojom
index 2143c06cce5..39d7bde9b0b 100644
--- a/chromium/mojo/public/interfaces/bindings/interface_control_messages.mojom
+++ b/chromium/mojo/public/interfaces/bindings/interface_control_messages.mojom
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-[JavaPackage="org.chromium.mojo.bindings"]
-module mojo;
+[JavaPackage="org.chromium.mojo.bindings.interfacecontrol"]
+module mojo.interface_control;
-// For each user-defined interface, some control functions are provided at the
-// same end of the message pipe as the user-defined interface, providing
-// information about the user-defined interface.
+// For each user-defined interface, some control functions are provided by the
+// interface endpoints at both sides.
////////////////////////////////////////////////////////////////////////////////
// Run@0xFFFFFFFF(RunInput input) => (RunOutput? output);
@@ -15,75 +14,63 @@ module mojo;
// This control function runs the input command. If the command is not
// supported, |output| is set to null; otherwise |output| stores the result,
// whose type depends on the input.
-//
-// TODO(yzshen): Once union support is ready, switch the following definition
-// to:
-// struct RunMessageParams {
-// RunInput input;
-// };
-// union RunInput {
-// QueryVersion query_version;
-// };
-//
-// struct RunResponseMessageParams {
-// RunOutput? output;
-// };
-// union RunOutput {
-// QueryVersionResult query_version_result;
-// };
const uint32 kRunMessageId = 0xFFFFFFFF;
struct RunMessageParams {
- // The reserved fields make the layout compatible with the RunInput union
- // described above.
- uint32 reserved0; // Must be set to 16.
- uint32 reserved1; // Must be set to 0;
+ RunInput input;
+};
+union RunInput {
QueryVersion query_version;
+ FlushForTesting flush_for_testing;
};
struct RunResponseMessageParams {
- // The reserved fields make the layout compatible with the RunOutput union
- // described above.
- uint32 reserved0; // Must be set to 16.
- uint32 reserved1; // Must be set to 0.
+ RunOutput? output;
+};
+union RunOutput {
QueryVersionResult query_version_result;
};
// Queries the max supported version of the user-defined interface.
+// Sent by the interface client side.
struct QueryVersion {
};
struct QueryVersionResult {
uint32 version;
};
+// Sent by either side of the interface.
+struct FlushForTesting {
+};
+
////////////////////////////////////////////////////////////////////////////////
// RunOrClosePipe@0xFFFFFFFE(RunOrClosePipeInput input);
//
// This control function runs the input command. If the operation fails or the
// command is not supported, the message pipe is closed.
-//
-// TODO(yzshen): Once union support is ready, switch the following definition
-// to:
-// struct RunOrClosePipeMessageParams {
-// RunOrClosePipeInput input;
-// };
-// union RunOrClosePipeInput {
-// RequireVersion require_version;
-// };
const uint32 kRunOrClosePipeMessageId = 0xFFFFFFFE;
struct RunOrClosePipeMessageParams {
- // The reserved fields make the layout compatible with the RunOrClosePipeInput
- // union described above.
- uint32 reserved0; // Must be set to 16.
- uint32 reserved1; // Must be set to 0.
+ RunOrClosePipeInput input;
+};
+union RunOrClosePipeInput {
RequireVersion require_version;
+ SendDisconnectReason send_disconnect_reason;
};
// If the specified version of the user-defined interface is not supported, the
// function fails and the pipe is closed.
+// Sent by the interface client side.
struct RequireVersion {
uint32 version;
};
+
+// A user-defined reason about why the interface is disconnected. The sender
+// usually send this message and immediately disconnect the interface.
+// Sent by either side of the interface.
+struct SendDisconnectReason {
+ uint32 custom_reason;
+ string description;
+};
diff --git a/chromium/mojo/public/interfaces/bindings/tests/BUILD.gn b/chromium/mojo/public/interfaces/bindings/tests/BUILD.gn
index 635b615f70e..72d6ba268df 100644
--- a/chromium/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/chromium/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -17,7 +17,9 @@ mojom("test_interfaces") {
"sample_service.mojom",
"scoping.mojom",
"serialization_test_structs.mojom",
+ "test_bad_messages.mojom",
"test_constants.mojom",
+ "test_data_view.mojom",
"test_native_types.mojom",
"test_structs.mojom",
"test_sync_methods.mojom",
@@ -29,6 +31,23 @@ mojom("test_interfaces") {
]
}
+component("test_export_component") {
+ testonly = true
+ deps = [
+ ":test_export",
+ ]
+}
+
+mojom("test_export") {
+ testonly = true
+ sources = [
+ "test_export.mojom",
+ ]
+ export_class_attribute = "MOJO_TEST_EXPORT"
+ export_define = "MOJO_TEST_IMPLEMENTATION=1"
+ export_header = "mojo/public/cpp/bindings/tests/mojo_test_export.h"
+}
+
mojom("test_mojom_import") {
testonly = true
sources = [
@@ -83,6 +102,10 @@ mojom("test_associated_interfaces") {
"test_associated_interfaces.mojom",
"validation_test_associated_interfaces.mojom",
]
+
+ public_deps = [
+ ":test_interfaces",
+ ]
}
mojom("versioning_test_service_interfaces") {
diff --git a/chromium/mojo/public/interfaces/bindings/tests/rect.mojom b/chromium/mojo/public/interfaces/bindings/tests/rect.mojom
index 833c76bb2a4..4ecc4d9660c 100644
--- a/chromium/mojo/public/interfaces/bindings/tests/rect.mojom
+++ b/chromium/mojo/public/interfaces/bindings/tests/rect.mojom
@@ -12,11 +12,20 @@ struct Rect {
int32 height;
};
-// A copy of Rect that can be typemapped. Arrays of Rect are currently used,
-// which do not support typemapping.
+// A copy of Rect that is typemapped differently in the chromium and blink
+// variants.
struct TypemappedRect {
int32 x;
int32 y;
int32 width;
int32 height;
};
+
+// A copy of Rect that is typemapped to the same custom type in the chromium and
+// blink variants.
+struct SharedTypemappedRect {
+ int32 x;
+ int32 y;
+ int32 width;
+ int32 height;
+}; \ No newline at end of file
diff --git a/chromium/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom b/chromium/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom
index b1b7437e89c..b50409ee88f 100644
--- a/chromium/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom
+++ b/chromium/mojo/public/interfaces/bindings/tests/struct_with_traits.mojom
@@ -23,6 +23,7 @@ struct StructWithTraits {
string f_string;
string f_string2;
array<string> f_string_array;
+ array<string> f_string_set;
NestedStructWithTraits f_struct;
array<NestedStructWithTraits> f_struct_array;
map<string, NestedStructWithTraits> f_struct_map;
@@ -33,28 +34,50 @@ struct StructWithTraitsContainer {
StructWithTraits f_struct;
};
-struct PassByValueStructWithTraits {
+// Maps to a pass-by-value trivial struct.
+struct TrivialStructWithTraits {
+ int32 value;
+};
+
+// Maps to a move-only struct.
+struct MoveOnlyStructWithTraits {
handle f_handle;
};
-// The custom type for PassByValueStructWithTraits is not clonable. Test that
+// The custom type for MoveOnlyStructWithTraits is not clonable. Test that
// this container can compile as long as Clone() is not used.
-struct PassByValueStructWithTraitsContainer {
- PassByValueStructWithTraits f_struct;
+struct MoveOnlyStructWithTraitsContainer {
+ MoveOnlyStructWithTraits f_struct;
};
-struct StructWithTraitsForUniquePtrTest {
+struct StructWithTraitsForUniquePtr {
int32 f_int32;
};
+union UnionWithTraits {
+ int32 f_int32;
+ NestedStructWithTraits f_struct;
+};
+
interface TraitsTestService {
EchoStructWithTraits(StructWithTraits s) => (StructWithTraits passed);
- EchoPassByValueStructWithTraits(PassByValueStructWithTraits s) =>
- (PassByValueStructWithTraits passed);
+ EchoTrivialStructWithTraits(TrivialStructWithTraits s) =>
+ (TrivialStructWithTraits passed);
+
+ EchoMoveOnlyStructWithTraits(MoveOnlyStructWithTraits s) =>
+ (MoveOnlyStructWithTraits passed);
+
+ EchoNullableMoveOnlyStructWithTraits(MoveOnlyStructWithTraits? s) =>
+ (MoveOnlyStructWithTraits? passed);
EchoEnumWithTraits(EnumWithTraits e) => (EnumWithTraits passed);
- EchoStructWithTraitsForUniquePtrTest(StructWithTraitsForUniquePtrTest e) => (
- StructWithTraitsForUniquePtrTest passed);
+ EchoStructWithTraitsForUniquePtr(StructWithTraitsForUniquePtr e) => (
+ StructWithTraitsForUniquePtr passed);
+
+ EchoNullableStructWithTraitsForUniquePtr(StructWithTraitsForUniquePtr? e) => (
+ StructWithTraitsForUniquePtr? passed);
+
+ EchoUnionWithTraits(UnionWithTraits u) => (UnionWithTraits passed);
};
diff --git a/chromium/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom b/chromium/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom
index 534cfd8d81e..a5ae0dcf974 100644
--- a/chromium/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom
+++ b/chromium/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom
@@ -4,6 +4,8 @@
module mojo.test;
+import "mojo/public/interfaces/bindings/tests/ping_service.mojom";
+
interface FooInterface {};
struct StructContainsAssociated {
@@ -42,3 +44,7 @@ interface IntegerSenderConnection {
GetSender(associated IntegerSender& sender);
AsyncGetSender() => (associated IntegerSender sender);
};
+
+interface AssociatedPingProvider {
+ GetPing(associated PingService& request);
+};
diff --git a/chromium/mojo/public/interfaces/bindings/tests/test_bad_messages.mojom b/chromium/mojo/public/interfaces/bindings/tests/test_bad_messages.mojom
new file mode 100644
index 00000000000..dcd594754d5
--- /dev/null
+++ b/chromium/mojo/public/interfaces/bindings/tests/test_bad_messages.mojom
@@ -0,0 +1,13 @@
+// Copyright 2016 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.test;
+
+interface TestBadMessages {
+ RejectEventually() => ();
+ RequestResponse() => ();
+
+ [Sync] RejectSync() => ();
+ [Sync] RequestResponseSync() => ();
+};
diff --git a/chromium/mojo/public/interfaces/bindings/tests/test_data_view.mojom b/chromium/mojo/public/interfaces/bindings/tests/test_data_view.mojom
new file mode 100644
index 00000000000..1fe8c6a8e22
--- /dev/null
+++ b/chromium/mojo/public/interfaces/bindings/tests/test_data_view.mojom
@@ -0,0 +1,41 @@
+// Copyright 2016 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.test.data_view;
+
+enum TestEnum {
+ VALUE_0,
+ VALUE_1
+};
+
+interface TestInterface {
+ [Sync]
+ Echo(int32 value) => (int32 out_value);
+};
+
+struct NestedStruct {
+ int32 f_int32;
+};
+
+[Native]
+struct TestNativeStruct;
+
+union TestUnion {
+ bool f_bool;
+ int32 f_int32;
+};
+
+struct TestStruct {
+ string f_string;
+ NestedStruct? f_struct;
+ TestNativeStruct? f_native_struct;
+ array<bool> f_bool_array;
+ array<int32> f_int32_array;
+ array<TestEnum> f_enum_array;
+ array<TestInterface> f_interface_array;
+ array<array<int32>> f_nested_array;
+ array<NestedStruct> f_struct_array;
+ array<TestUnion> f_union_array;
+ map<string, int32> f_map;
+};
diff --git a/chromium/mojo/public/interfaces/bindings/tests/test_export.mojom b/chromium/mojo/public/interfaces/bindings/tests/test_export.mojom
new file mode 100644
index 00000000000..9a532dd94d4
--- /dev/null
+++ b/chromium/mojo/public/interfaces/bindings/tests/test_export.mojom
@@ -0,0 +1,18 @@
+// Copyright 2016 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.test.test_export;
+
+struct StringPair {
+ string s1;
+ string s2;
+};
+
+// This is a regression test. On Windows, if we export the generated class *and*
+// not explicitly disallow copy constructor and assign operator, compilation
+// will fail because it tries to use copy constructor of
+// InlinedStructPtr<StringPair>.
+struct StringPairContainer {
+ array<StringPair> pairs;
+};
diff --git a/chromium/mojo/public/interfaces/bindings/tests/test_native_types.mojom b/chromium/mojo/public/interfaces/bindings/tests/test_native_types.mojom
index 46c6f694ce0..3df43182a37 100644
--- a/chromium/mojo/public/interfaces/bindings/tests/test_native_types.mojom
+++ b/chromium/mojo/public/interfaces/bindings/tests/test_native_types.mojom
@@ -34,4 +34,5 @@ interface PicklePasser {
interface RectService {
AddRect(TypemappedRect r);
GetLargestRect() => (TypemappedRect largest);
+ PassSharedRect(SharedTypemappedRect r) => (SharedTypemappedRect passed);
};
diff --git a/chromium/mojo/public/interfaces/bindings/tests/test_structs.mojom b/chromium/mojo/public/interfaces/bindings/tests/test_structs.mojom
index 2709d4923ff..683f0a56a08 100644
--- a/chromium/mojo/public/interfaces/bindings/tests/test_structs.mojom
+++ b/chromium/mojo/public/interfaces/bindings/tests/test_structs.mojom
@@ -126,6 +126,8 @@ struct MapKeyTypes {
map<float, float> f9;
map<double, double> f10;
map<string, string> f11;
+ // TODO(tibell): JS/Java don't support struct as key.
+ // map<Rect, Rect> f12;
};
// Used to verify that various map value types can be encoded and decoded
@@ -380,3 +382,23 @@ struct ContainsOther {
struct ContainsInterfaceRequest {
SomeInterface& request;
};
+
+// Used to verify that boolean fields are correctly serialized/deserialized.
+
+struct SingleBoolStruct {
+ bool value;
+};
+
+// Used to verify that structs containing typemapped types can be hashed (if the
+// typemapped type itself is hashable).
+
+struct ContainsHashable {
+ TypemappedRect rect;
+};
+
+// Used to test that nested structs can be hashed. The nested struct mustn't be
+// nullable.
+
+struct SimpleNestedStruct {
+ ContainsOther nested;
+};
diff --git a/chromium/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom b/chromium/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
index c46c0a5a403..2fb0d949b3e 100644
--- a/chromium/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
+++ b/chromium/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
@@ -56,6 +56,11 @@ enum EnumB {
ENUM_B_2
};
+union UnionA {
+ StructA struct_a;
+ bool b;
+};
+
// This interface is used for testing bounds-checking in the mojom
// binding code. If you add a method please update the files
// ./data/validation/boundscheck_*. If you add a response please update
@@ -84,6 +89,9 @@ interface ConformanceTestInterface {
Method15(array<EnumA>? param0, array<EnumB>? param1);
Method16(map<EnumA, EnumA>? param0);
Method17(array<InterfaceA> param0);
+ Method18(UnionA? param0);
+ Method19(Recursive recursive);
+ Method20(map<StructB, uint8> param0);
};
struct BasicStruct {
@@ -111,3 +119,8 @@ struct StructWithEnum {
A, B, C, D
};
};
+
+// This is used to test that deeply recursive structures don't blow the stack.
+struct Recursive {
+ Recursive? recursive;
+};
diff --git a/chromium/mojo/public/java/BUILD.gn b/chromium/mojo/public/java/BUILD.gn
index e33faaa9b09..8762db3985c 100644
--- a/chromium/mojo/public/java/BUILD.gn
+++ b/chromium/mojo/public/java/BUILD.gn
@@ -6,7 +6,6 @@ import("//build/config/android/rules.gni")
android_library("system") {
java_files = [
- "system/src/org/chromium/mojo/system/AsyncWaiter.java",
"system/src/org/chromium/mojo/system/Core.java",
"system/src/org/chromium/mojo/system/DataPipe.java",
"system/src/org/chromium/mojo/system/Flags.java",
@@ -20,6 +19,7 @@ android_library("system") {
"system/src/org/chromium/mojo/system/SharedBufferHandle.java",
"system/src/org/chromium/mojo/system/UntypedHandle.java",
"system/src/org/chromium/mojo/system/RunLoop.java",
+ "system/src/org/chromium/mojo/system/Watcher.java",
]
}
diff --git a/chromium/mojo/public/js/codec.js b/chromium/mojo/public/js/codec.js
index 4003b510c5e..70df7585599 100644
--- a/chromium/mojo/public/js/codec.js
+++ b/chromium/mojo/public/js/codec.js
@@ -711,6 +711,20 @@ define("mojo/public/js/codec", [
encoder.writeDouble(val);
};
+ function Enum(cls) {
+ this.cls = cls;
+ }
+
+ Enum.prototype.encodedSize = 4;
+
+ Enum.prototype.decode = function(decoder) {
+ return decoder.readInt32();
+ };
+
+ Enum.prototype.encode = function(encoder, val) {
+ encoder.writeInt32(val);
+ };
+
function PointerTo(cls) {
this.cls = cls;
}
@@ -863,6 +877,7 @@ define("mojo/public/js/codec", [
exports.Float = Float;
exports.Double = Double;
exports.String = String;
+ exports.Enum = Enum;
exports.NullableString = NullableString;
exports.PointerTo = PointerTo;
exports.NullablePointerTo = NullablePointerTo;
diff --git a/chromium/mojo/public/js/codec_unittests.js b/chromium/mojo/public/js/codec_unittests.js
index b610d9a1dbf..5fa4076c4f6 100644
--- a/chromium/mojo/public/js/codec_unittests.js
+++ b/chromium/mojo/public/js/codec_unittests.js
@@ -12,6 +12,7 @@ define([
testBar();
testFoo();
testNamedRegion();
+ testSingleBooleanStruct();
testTypes();
testAlign();
testUtf8();
@@ -176,6 +177,23 @@ define([
expect(result.rects[1]).toEqual(createRect(10, 20, 30, 40));
}
+ // Verify that a single boolean field in a struct is correctly decoded to
+ // boolean type.
+ function testSingleBooleanStruct() {
+ var single_bool = new structs.SingleBoolStruct();
+ single_bool.value = true;
+
+ var builder = new codec.MessageBuilder(
+ 1, structs.SingleBoolStruct.encodedSize);
+ builder.encodeStruct(structs.SingleBoolStruct, single_bool);
+ var reader = new codec.MessageReader(builder.finish());
+ var result = reader.decodeStruct(structs.SingleBoolStruct);
+
+ // Use toEqual() instead of toBeTruthy() to make sure the field type is
+ // actually boolean.
+ expect(result.value).toEqual(true);
+ }
+
function testTypes() {
function encodeDecode(cls, input, expectedResult, encodedSize) {
var messageName = 42;
diff --git a/chromium/mojo/public/js/connection.js b/chromium/mojo/public/js/connection.js
index 3f7e8392b3b..1ac88ed9e63 100644
--- a/chromium/mojo/public/js/connection.js
+++ b/chromium/mojo/public/js/connection.js
@@ -98,6 +98,25 @@ define("mojo/public/js/connection", [
return messagePipe.handle1;
}
+ // Return a handle and proxy for a message pipe that's connected to a proxy
+ // for remoteInterface. Used by generated code for outgoing interface&
+ // (request) parameters
+ function getProxy(remoteInterface) {
+ var messagePipe = core.createMessagePipe();
+ if (messagePipe.result != core.RESULT_OK)
+ throw new Error("createMessagePipe failed " + messagePipe.result);
+
+ var proxy = new remoteInterface.proxyClass;
+ var router = new Router(messagePipe.handle0);
+ var connection = new BaseConnection(undefined, proxy, router);
+ ProxyBindings(proxy).connection = connection;
+
+ return {
+ requestHandle: messagePipe.handle1,
+ proxy: proxy
+ };
+ }
+
// Return a handle for a message pipe that's connected to a stub for
// localInterface. Used by generated code for outgoing interface
// parameters: the caller is given the generated stub via
@@ -168,6 +187,7 @@ define("mojo/public/js/connection", [
exports.TestConnection = TestConnection;
exports.bindProxy = bindProxy;
+ exports.getProxy = getProxy;
exports.bindImpl = bindImpl;
exports.bindHandleToProxy = bindHandleToProxy;
exports.bindHandleToStub = bindHandleToStub;
diff --git a/chromium/mojo/public/js/core.js b/chromium/mojo/public/js/core.js
index b89a9560ea3..ef480eeba5b 100644
--- a/chromium/mojo/public/js/core.js
+++ b/chromium/mojo/public/js/core.js
@@ -114,6 +114,27 @@ var READ_DATA_FLAG_QUERY;
var READ_DATA_FLAG_PEEK;
/**
+ * MojoCreateSharedBufferOptionsFlags: Used to specify options to
+ * |createSharedBuffer()|.
+ * See core.h for more information.
+ */
+var CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE;
+
+/**
+ * MojoDuplicateBufferHandleOptionsFlags: Used to specify options to
+ * |duplicateBufferHandle()|.
+ * See core.h for more information.
+ */
+var DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE;
+var DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY;
+
+/**
+ * MojoMapBufferFlags: Used to specify options to |mapBuffer()|.
+ * See core.h for more information.
+ */
+var MAP_BUFFER_FLAG_NONE;
+
+/**
* Closes the given |handle|. See MojoClose for more info.
* @param {MojoHandle} Handle to close.
* @return {MojoResult} Result code.
@@ -236,3 +257,57 @@ function readData(handle, flags) { [native code] }
* @return true or false
*/
function isHandle(value) { [native code] }
+
+/**
+ * Creates shared buffer of specified size |num_bytes|.
+ * See MojoCreateSharedBuffer for more information including error codes.
+ *
+ * @param {number} num_bytes Size of the memory to be allocated for shared
+ * @param {MojoCreateSharedBufferOptionsFlags} flags Flags.
+ * buffer.
+ * @return {object} An object of the form {
+ * result, // |RESULT_OK| on success, error code otherwise.
+ * handle, // An MojoHandle for shared buffer (only on success).
+ * }
+ */
+function createSharedBuffer(num_bytes, flags) { [native code] }
+
+/**
+ * Duplicates the |buffer_handle| to a shared buffer. Duplicated handle can be
+ * sent to another process over message pipe. See MojoDuplicateBufferHandle for
+ * more information including error codes.
+ *
+ * @param {MojoHandle} buffer_handle MojoHandle.
+ * @param {MojoCreateSharedBufferOptionsFlags} flags Flags.
+ * @return {object} An object of the form {
+ * result, // |RESULT_OK| on success, error code otherwise.
+ * handle, // A duplicated MojoHandle for shared buffer (only on success).
+ * }
+ */
+function duplicateBufferHandle(buffer_handle, flags) { [native code] }
+
+/**
+ * Maps the part (at offset |offset| of length |num_bytes|) of the buffer given
+ * by |buffer_handle| into ArrayBuffer memory |buffer|, with options specified
+ * by |flags|. See MojoMapBuffer for more information including error codes.
+ *
+ * @param {MojoHandle} buffer_handle A sharedBufferHandle returned by
+ * createSharedBuffer.
+ * @param {number} offset Offset.
+ * @param {number} num_bytes Size of the memory to be mapped.
+ * @param {MojoMapBufferFlags} flags Flags.
+ * @return {object} An object of the form {
+ * result, // |RESULT_OK| on success, error code otherwise.
+ * buffer, // An ArrayBuffer (only on success).
+ * }
+ */
+function mapBuffer(buffer_handle, offset, num_bytes, flags) { [native code] }
+
+/**
+ * Unmaps buffer that was mapped using mapBuffer.
+ * See MojoUnmapBuffer for more information including error codes.
+ *
+ * @param {ArrayBuffer} buffer ArrayBuffer.
+ * @return {MojoResult} Result code.
+ */
+function unmapBuffer(buffer) { [native code] }
diff --git a/chromium/mojo/public/js/core_unittests.js b/chromium/mojo/public/js/core_unittests.js
index 12364dc67ef..395ed053eef 100644
--- a/chromium/mojo/public/js/core_unittests.js
+++ b/chromium/mojo/public/js/core_unittests.js
@@ -24,6 +24,7 @@ define([
runWithDataPipeWithOptions(testReadAndWriteDataPipe);
runWithMessagePipe(testIsHandleMessagePipe);
runWithDataPipe(testIsHandleDataPipe);
+ runWithSharedBuffer(testSharedBuffer);
gc.collectGarbage(); // should not crash
this.result = "PASS";
@@ -73,6 +74,17 @@ define([
expect(core.close(pipe.consumerHandle)).toBe(core.RESULT_OK);
}
+ function runWithSharedBuffer(test) {
+ let buffer_size = 32;
+ let sharedBuffer = core.createSharedBuffer(buffer_size,
+ core.CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE);
+
+ expect(sharedBuffer.result).toBe(core.RESULT_OK);
+ expect(core.isHandle(sharedBuffer.handle)).toBeTruthy();
+
+ test(sharedBuffer, buffer_size);
+ }
+
function testNop(pipe) {
}
@@ -195,4 +207,40 @@ define([
expect(core.isHandle(pipe.producerHandle)).toBeTruthy();
}
+ function testSharedBuffer(sharedBuffer, buffer_size) {
+ let offset = 0;
+ let mappedBuffer0 = core.mapBuffer(sharedBuffer.handle,
+ offset,
+ buffer_size,
+ core.MAP_BUFFER_FLAG_NONE);
+
+ expect(mappedBuffer0.result).toBe(core.RESULT_OK);
+
+ let dupedBufferHandle = core.duplicateBufferHandle(sharedBuffer.handle,
+ core.DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE);
+
+ expect(dupedBufferHandle.result).toBe(core.RESULT_OK);
+ expect(core.isHandle(dupedBufferHandle.handle)).toBeTruthy();
+
+ let mappedBuffer1 = core.mapBuffer(dupedBufferHandle.handle,
+ offset,
+ buffer_size,
+ core.MAP_BUFFER_FLAG_NONE);
+
+ expect(mappedBuffer1.result).toBe(core.RESULT_OK);
+
+ let buffer0 = new Uint8Array(mappedBuffer0.buffer);
+ let buffer1 = new Uint8Array(mappedBuffer1.buffer);
+ for(let i = 0; i < buffer0.length; ++i) {
+ buffer0[i] = i;
+ expect(buffer1[i]).toBe(i);
+ }
+
+ expect(core.unmapBuffer(mappedBuffer0.buffer)).toBe(core.RESULT_OK);
+ expect(core.unmapBuffer(mappedBuffer1.buffer)).toBe(core.RESULT_OK);
+
+ expect(core.close(dupedBufferHandle.handle)).toBe(core.RESULT_OK);
+ expect(core.close(sharedBuffer.handle)).toBe(core.RESULT_OK);
+ }
+
});
diff --git a/chromium/mojo/public/js/union_unittests.js b/chromium/mojo/public/js/union_unittests.js
index 5dcda7d1174..c3ee2979257 100644
--- a/chromium/mojo/public/js/union_unittests.js
+++ b/chromium/mojo/public/js/union_unittests.js
@@ -66,6 +66,16 @@ define([
expect(decoded).toEqual(s);
var s = new unions.WrapperStruct({
+ pod_union: new unions.PodUnion({
+ f_bool : true})});
+
+ var decoded = structEncodeDecode(s);
+ expect(decoded.pod_union.$tag).toEqual(unions.PodUnion.Tags.f_bool);
+ // Use toEqual() instead of toBeTruthy() to make sure the field type is
+ // actually boolean.
+ expect(decoded.pod_union.f_bool).toEqual(true);
+
+ var s = new unions.WrapperStruct({
object_union: new unions.ObjectUnion({
f_dummy: new unions.DummyStruct({
f_int8: 8})})});
diff --git a/chromium/mojo/public/js/validation_unittests.js b/chromium/mojo/public/js/validation_unittests.js
index 817d42c5715..4bdaa8f3e2d 100644
--- a/chromium/mojo/public/js/validation_unittests.js
+++ b/chromium/mojo/public/js/validation_unittests.js
@@ -227,15 +227,16 @@ define([
// because JS numbers are limited to 53 bits.
// TODO(yzshen) Skipping struct versioning tests (tests with "mthd11"
// in the name) because the feature is not supported in JS yet.
- // TODO(yzshen) Skipping enum validation tests (tests with "enum" in the
- // name) because the feature is not supported in JS yet. crbug.com/581390
// TODO(rudominer): Temporarily skipping 'no-such-method',
// 'invalid_request_flags', and 'invalid_response_flags' until additional
// logic in *RequestValidator and *ResponseValidator is ported from
// cpp to js.
+ // TODO(crbug/640298): Implement max recursion depth for JS.
+ // TODO(crbug/628104): Support struct map keys for JS.
if (testFiles[i].indexOf("overflow") != -1 ||
testFiles[i].indexOf("mthd11") != -1 ||
- testFiles[i].indexOf("enum") != -1 ||
+ testFiles[i].indexOf("conformance_mthd19") != -1 ||
+ testFiles[i].indexOf("conformance_mthd20") != -1 ||
testFiles[i].indexOf("no_such_method") != -1 ||
testFiles[i].indexOf("invalid_request_flags") != -1 ||
testFiles[i].indexOf("invalid_response_flags") != -1) {
diff --git a/chromium/mojo/public/js/validator.js b/chromium/mojo/public/js/validator.js
index cbf7521b5c3..48e36c61d22 100644
--- a/chromium/mojo/public/js/validator.js
+++ b/chromium/mojo/public/js/validator.js
@@ -24,10 +24,15 @@ define("mojo/public/js/validator", [
'VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP',
INVALID_UNION_SIZE: 'VALIDATION_ERROR_INVALID_UNION_SIZE',
UNEXPECTED_NULL_UNION: 'VALIDATION_ERROR_UNEXPECTED_NULL_UNION',
+ UNKNOWN_ENUM_VALUE: 'VALIDATION_ERROR_UNKNOWN_ENUM_VALUE',
};
var NULL_MOJO_POINTER = "NULL_MOJO_POINTER";
+ function isEnumClass(cls) {
+ return cls instanceof codec.Enum;
+ }
+
function isStringClass(cls) {
return cls === codec.String || cls === codec.NullableString;
}
@@ -98,6 +103,13 @@ define("mojo/public/js/validator", [
return true;
}
+ Validator.prototype.validateEnum = function(offset, enumClass, nullable) {
+ // Note: Assumes that enums are always 32 bits! But this matches
+ // mojom::generate::pack::PackedField::GetSizeForKind, so it should be okay.
+ var value = this.message.buffer.getInt32(offset);
+ return enumClass.validate(value);
+ }
+
Validator.prototype.validateHandle = function(offset, nullable) {
var index = this.message.buffer.getUint32(offset);
@@ -347,6 +359,8 @@ define("mojo/public/js/validator", [
return this.validateArrayElements(
elementsOffset, numElements, elementType.cls, nullable,
expectedDimensionSizes, currentDimension + 1);
+ if (isEnumClass(elementType))
+ return this.validateEnum(elementsOffset, elementType.cls, nullable);
return validationError.NONE;
}
diff --git a/chromium/mojo/public/mojo_application.gni b/chromium/mojo/public/mojo_application.gni
deleted file mode 100644
index 28c8a8d0936..00000000000
--- a/chromium/mojo/public/mojo_application.gni
+++ /dev/null
@@ -1,270 +0,0 @@
-# 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("//build/toolchain/toolchain.gni")
-import("//mojo/public/mojo_constants.gni")
-
-if (is_android) {
- import("//build/config/android/rules.gni")
- import("//build/config/zip.gni")
-}
-
-# Generate a binary Mojo application in a self-named directory.
-# Application resources are copied to a "resources" directory alongside the app.
-# The parameters of this template are those of a shared library.
-template("mojo_native_application") {
- base_target_name = target_name
- if (defined(invoker.output_name)) {
- base_target_name = invoker.output_name
- }
-
- final_target_name = target_name
-
- mojo_deps = []
- if (defined(invoker.deps)) {
- mojo_deps += invoker.deps
- }
-
- mojo_data_deps = []
-
- if (defined(invoker.resources)) {
- copy_step_name = "${base_target_name}__copy_resources"
- copy(copy_step_name) {
- sources = invoker.resources
- outputs = [
- "${root_out_dir}/${mojo_application_subdir}/${base_target_name}/resources/{{source_file_part}}",
- ]
- if (defined(invoker.testonly)) {
- testonly = invoker.testonly
- }
- deps = mojo_deps
- }
- mojo_data_deps += [ ":$copy_step_name" ]
- }
-
- output = base_target_name + ".mojo"
- library_target_name = base_target_name + "_library"
- library_name = "${shlib_prefix}${library_target_name}${shlib_extension}"
-
- shared_library(library_target_name) {
- if (defined(invoker.cflags)) {
- cflags = invoker.cflags
- }
- if (defined(invoker.cflags_c)) {
- cflags_c = invoker.cflags_c
- }
- if (defined(invoker.cflags_cc)) {
- cflags_cc = invoker.cflags_cc
- }
- if (defined(invoker.cflags_objc)) {
- cflags_objc = invoker.cflags_objc
- }
- if (defined(invoker.cflags_objcc)) {
- cflags_objcc = invoker.cflags_objcc
- }
- if (defined(invoker.defines)) {
- defines = invoker.defines
- }
- if (defined(invoker.include_dirs)) {
- include_dirs = invoker.include_dirs
- }
- if (defined(invoker.ldflags)) {
- ldflags = invoker.ldflags
- }
- if (defined(invoker.lib_dirs)) {
- lib_dirs = invoker.lib_dirs
- }
- if (defined(invoker.libs)) {
- libs = invoker.libs
- }
-
- data_deps = []
- if (!defined(invoker.avoid_runner_cycle) || !invoker.avoid_runner_cycle) {
- # Give the user an out; as some mojo services are depended on by the
- # runner.
- data_deps += [ "//services/shell/standalone" ]
- }
- if (defined(invoker.data_deps)) {
- data_deps += invoker.data_deps
- }
- data_deps += mojo_data_deps
-
- deps = [
- "//mojo/public/c/system:set_thunks_for_app",
- "//services/shell/public/cpp:application_support",
- ]
-
- deps += mojo_deps
- if (defined(invoker.public_deps)) {
- public_deps = invoker.public_deps
- }
- if (defined(invoker.all_dependent_configs)) {
- all_dependent_configs = invoker.all_dependent_configs
- }
- if (defined(invoker.public_configs)) {
- public_configs = invoker.public_configs
- }
- if (defined(invoker.check_includes)) {
- check_includes = invoker.check_includes
- }
- if (defined(invoker.configs)) {
- configs += invoker.configs
- }
- if (defined(invoker.data)) {
- data = invoker.data
- }
- if (defined(invoker.inputs)) {
- inputs = invoker.inputs
- }
- if (defined(invoker.public)) {
- public = invoker.public
- }
- if (defined(invoker.sources)) {
- sources = invoker.sources
- }
- if (defined(invoker.testonly)) {
- testonly = invoker.testonly
- }
- }
-
- copy(final_target_name) {
- forward_variables_from(invoker,
- [
- "testonly",
- "visibility",
- ])
- deps = [
- ":${library_target_name}",
- ]
-
- sources = [
- "${root_shlib_dir}/${library_name}",
- ]
- outputs = [
- "${root_out_dir}/${mojo_application_subdir}/${base_target_name}/${output}",
- ]
- }
-
- if (is_android) {
- android_assets("${final_target_name}_assets") {
- forward_variables_from(invoker, [ "testonly" ])
- deps = [
- ":${library_target_name}",
- ]
- if (defined(invoker.deps)) {
- deps += invoker.deps
- }
- renaming_sources = [ "${root_shlib_dir}/${library_name}" ]
- renaming_destinations = [ "${base_target_name}/${output}" ]
- if (defined(invoker.resources)) {
- renaming_sources += invoker.resources
- renaming_destinations += process_file_template(
- invoker.resources,
- [ "$base_target_name/resources/{{source_file_part}}" ])
- }
- }
- }
-}
-
-if (is_android) {
- # Declares an Android Mojo application consisting of an .so file and a
- # corresponding .dex.jar file.
- #
- # Variables:
- # input_so: the .so file to bundle
- # input_dex_jar: the .dex.jar file to bundle
- # deps / public_deps / data_deps (optional):
- # Dependencies. The targets that generate the .so/jar inputs should be
- # listed in either deps or public_deps.
- # output_name (optional): override for the output file name
- template("mojo_android_application") {
- assert(defined(invoker.input_so))
- assert(defined(invoker.input_dex_jar))
-
- base_target_name = target_name
- if (defined(invoker.output_name)) {
- base_target_name = invoker.output_name
- }
-
- mojo_data_deps = []
- if (defined(invoker.resources)) {
- copy_step_name = "${base_target_name}__copy_resources"
- copy(copy_step_name) {
- sources = invoker.resources
- outputs = [
- "${root_out_dir}/${mojo_application_subdir}/${base_target_name}/resources/{{source_file_part}}",
- ]
- if (defined(invoker.testonly)) {
- testonly = invoker.testonly
- }
- if (defined(invoker.deps)) {
- deps = invoker.deps
- }
- }
- mojo_data_deps += [ ":$copy_step_name" ]
- }
-
- zip_action_name = "${target_name}_zip"
- zip_action_output = "$target_gen_dir/${target_name}.zip"
- prepend_action_name = target_name
- zip(zip_action_name) {
- visibility = [ ":$prepend_action_name" ]
- inputs = [
- invoker.input_so,
- invoker.input_dex_jar,
- ]
- output = zip_action_output
- forward_variables_from(invoker,
- [
- "deps",
- "public_deps",
- "data_deps",
- ])
- }
-
- _mojo_output = "${root_out_dir}/${mojo_application_subdir}/${base_target_name}/${base_target_name}.mojo"
-
- action(target_name) {
- script = "//mojo/public/tools/prepend.py"
-
- input = zip_action_output
- inputs = [
- input,
- ]
-
- outputs = [
- _mojo_output,
- ]
-
- rebase_input = rebase_path(input, root_build_dir)
- rebase_output = rebase_path(_mojo_output, root_build_dir)
- args = [
- "--input=$rebase_input",
- "--output=$rebase_output",
- "--line=#!mojo mojo:android_handler",
- ]
-
- data_deps = mojo_data_deps
-
- public_deps = [
- ":$zip_action_name",
- ]
- }
-
- android_assets("${target_name}_assets") {
- forward_variables_from(invoker, [ "testonly" ])
- deps = [
- ":$prepend_action_name",
- ]
- renaming_sources = [ _mojo_output ]
- renaming_destinations = [ "${base_target_name}/${base_target_name}.mojo" ]
- if (defined(invoker.resources)) {
- renaming_sources += invoker.resources
- renaming_destinations += process_file_template(
- invoker.resources,
- [ "$base_target_name/resources/{{source_file_part}}" ])
- }
- }
- }
-}
diff --git a/chromium/mojo/public/mojo_application_manifest.gni b/chromium/mojo/public/mojo_application_manifest.gni
deleted file mode 100644
index 61844173058..00000000000
--- a/chromium/mojo/public/mojo_application_manifest.gni
+++ /dev/null
@@ -1,139 +0,0 @@
-# Copyright 2016 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/mojo_constants.gni")
-
-# Used to produce a Mojo Application Manifest for an application.
-#
-# Parameters:
-#
-# source
-# The manifest file template for this application, must be valid JSON with
-# a valid 'url' key matching application_name.
-#
-# base_manifest (optional)
-# A manifest file template to use as a base for |source|. Any properties
-# defined in |source| will overwrite or be merged with properties defined
-# in |base_manifest|.
-#
-# application_name
-# The host portion of the mojo: URL of the application. The script
-# validates that the value of this parameter matches the host name portion
-# of the 'url' property set in the manifest and throws a ValueError if
-# they do not.
-#
-# base_deps (optional)
-# Dependencies required to generate |base_manifest| if applicable.
-#
-# deps (optional)
-# An array of dependent instances of this template. This template enforces
-# that dependencies can only be instances of this template.
-#
-# packaged_applications (optional)
-# An array of application_names of the dependent applications.
-#
-# type (default is mojo)
-# Possible values are 'mojo' and 'exe'. Default is 'mojo'.
-#
-# Outputs:
-#
-# An instantiation of this template produces in
-# $outdir/<application_name>/manifest.json
-# a meta manifest from the source template and the output manifest of all
-# dependent children.
-#
-template("mojo_application_manifest") {
- assert(defined(invoker.source),
- "\"source\" must be defined for the $target_name template")
- assert(defined(invoker.application_name),
- "\"application_name\" must be defined for the $target_name template")
- if (defined(invoker.deps)) {
- assert(defined(invoker.packaged_applications),
- "\"packaged_applications\" listing the directory containing the " +
- "manifest.json of dependent applications must be provided.")
- }
- if (defined(invoker.packaged_applications)) {
- assert(defined(invoker.deps),
- "\"deps\" building the dependent packaged applications must be " +
- "provided.")
- }
- if (defined(invoker.type)) {
- assert(invoker.type == "mojo" || invoker.type == "exe",
- "\"type\" must be one of \"mojo\" or \"exe\".")
- }
-
- action(target_name) {
- script = "//mojo/public/tools/manifest/manifest_collator.py"
-
- type = "mojo"
- if (defined(invoker.type)) {
- type = invoker.type
- }
-
- application_name = invoker.application_name
- inputs = [
- invoker.source,
- ]
-
- if (type == "mojo") {
- output = "$root_out_dir/$mojo_application_subdir/$application_name/manifest.json"
- } else {
- output = "$root_out_dir/${application_name}_manifest.json"
- }
- outputs = [
- output,
- ]
-
- rebase_parent = rebase_path(invoker.source, root_build_dir)
- rebase_output = rebase_path(output, root_build_dir)
-
- args = [
- "--application-name=$application_name",
- "--parent=$rebase_parent",
- "--output=$rebase_output",
- ]
-
- if (defined(invoker.base_manifest)) {
- rebase_base = rebase_path(invoker.base_manifest, root_build_dir)
- args += [ "--base-manifest=$rebase_base" ]
- }
-
- if (defined(invoker.packaged_applications)) {
- foreach(application_name, invoker.packaged_applications) {
- input = "$root_out_dir/$mojo_application_subdir/$application_name/manifest.json"
- inputs += [ input ]
- args += [ rebase_path(input, root_build_dir) ]
- }
- }
- deps = []
- data_deps = []
- if (defined(invoker.deps)) {
- deps += invoker.deps
- data_deps += invoker.deps
- }
- if (defined(invoker.base_deps)) {
- deps += invoker.base_deps
- data_deps += invoker.base_deps
- }
- }
-
- all_deps = []
- if (defined(invoker.deps)) {
- all_deps += invoker.deps
- }
-
- group("${target_name}__is_mojo_application_manifest") {
- }
-
- # Explicitly ensure that all dependencies are mojo_application_manifest
- # targets themselves.
- group("${target_name}__check_deps_are_all_mojo_application_manifest") {
- deps = []
- foreach(d, all_deps) {
- name = get_label_info(d, "label_no_toolchain")
- toolchain = get_label_info(d, "toolchain")
- deps += [ "${name}__is_mojo_application_manifest(${toolchain})" ]
- }
- }
-}
diff --git a/chromium/mojo/public/mojo_application_manifest.gypi b/chromium/mojo/public/mojo_application_manifest.gypi
deleted file mode 100644
index 9b89abb93fd..00000000000
--- a/chromium/mojo/public/mojo_application_manifest.gypi
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2016 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': {
- 'variables': {
- 'application_name%': '<(application_name)',
- 'application_type%': '<(application_type)',
- 'base_manifest%': 'none',
- 'packaged_manifests%': []
- },
- 'application_type%': '<(application_type)',
- 'application_name%': '<(application_name)',
- 'base_manifest%': '<(base_manifest)',
- 'manifest_collator_script%':
- '<(DEPTH)/mojo/public/tools/manifest/manifest_collator.py',
- 'packaged_manifests%': '<(packaged_manifests)',
- 'source_manifest%': '<(source_manifest)',
- 'conditions': [
- ['application_type=="mojo"', {
- 'output_manifest%': '<(PRODUCT_DIR)/Mojo Applications/<(application_name)/manifest.json',
- }, {
- 'output_manifest%': '<(PRODUCT_DIR)/<(application_name)_manifest.json',
- }],
- ['base_manifest!="none"', {
- 'extra_args%': [
- '--base-manifest=<(base_manifest)',
- '<@(packaged_manifests)',
- ],
- }, {
- 'extra_args%': [
- '<@(packaged_manifests)',
- ],
- }]
- ],
- },
- 'actions': [{
- 'action_name': '<(_target_name)_collation',
- 'inputs': [
- '<(manifest_collator_script)',
- '<(source_manifest)',
- ],
- 'outputs': [
- '<(output_manifest)',
- ],
- 'action': [
- 'python',
- '<(manifest_collator_script)',
- '--application-name', '<(application_name)',
- '--parent=<(source_manifest)',
- '--output=<(output_manifest)',
- '<@(extra_args)',
- ],
- }],
-}
diff --git a/chromium/mojo/public/mojo_constants.gni b/chromium/mojo/public/mojo_constants.gni
deleted file mode 100644
index 3165a8dc9e2..00000000000
--- a/chromium/mojo/public/mojo_constants.gni
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright 2016 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.
-
-declare_args() {
- # Mojo application directories are created within this subdirectory.
- mojo_application_subdir = "Mojo Applications"
-}
diff --git a/chromium/mojo/public/tools/bindings/BUILD.gn b/chromium/mojo/public/tools/bindings/BUILD.gn
index eeea5c5b3f1..153d1103325 100644
--- a/chromium/mojo/public/tools/bindings/BUILD.gn
+++ b/chromium/mojo/public/tools/bindings/BUILD.gn
@@ -16,7 +16,9 @@ action("precompile_templates") {
"$mojom_generator_root/generators/cpp_templates/interface_request_validator_declaration.tmpl",
"$mojom_generator_root/generators/cpp_templates/interface_response_validator_declaration.tmpl",
"$mojom_generator_root/generators/cpp_templates/interface_stub_declaration.tmpl",
- "$mojom_generator_root/generators/cpp_templates/module-internal.h.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module-shared-internal.h.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module-shared.cc.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module-shared.h.tmpl",
"$mojom_generator_root/generators/cpp_templates/module.cc.tmpl",
"$mojom_generator_root/generators/cpp_templates/module.h.tmpl",
"$mojom_generator_root/generators/cpp_templates/struct_data_view_declaration.tmpl",
@@ -25,11 +27,15 @@ action("precompile_templates") {
"$mojom_generator_root/generators/cpp_templates/struct_definition.tmpl",
"$mojom_generator_root/generators/cpp_templates/struct_macros.tmpl",
"$mojom_generator_root/generators/cpp_templates/struct_serialization_declaration.tmpl",
- "$mojom_generator_root/generators/cpp_templates/struct_serialization_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_traits_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_traits_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_data_view_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_data_view_definition.tmpl",
"$mojom_generator_root/generators/cpp_templates/union_declaration.tmpl",
"$mojom_generator_root/generators/cpp_templates/union_definition.tmpl",
"$mojom_generator_root/generators/cpp_templates/union_serialization_declaration.tmpl",
- "$mojom_generator_root/generators/cpp_templates/union_serialization_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_traits_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_traits_definition.tmpl",
"$mojom_generator_root/generators/cpp_templates/validation_macros.tmpl",
"$mojom_generator_root/generators/cpp_templates/wrapper_class_declaration.tmpl",
"$mojom_generator_root/generators/cpp_templates/wrapper_class_definition.tmpl",
diff --git a/chromium/mojo/public/tools/bindings/bindings.gyp b/chromium/mojo/public/tools/bindings/bindings.gyp
deleted file mode 100644
index 0f00114b332..00000000000
--- a/chromium/mojo/public/tools/bindings/bindings.gyp
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright 2016 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.
-
-{
- 'includes': [
- '../../../mojom_bindings_generator_variables.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'precompile_mojom_bindings_generator_templates',
- 'type': 'none',
- 'actions': [
- {
- 'action_name': 'precompile_mojom_bindings_generator_templates',
- 'inputs': [
- '<@(mojom_bindings_generator_sources)',
- 'generators/cpp_templates/enum_macros.tmpl',
- 'generators/cpp_templates/enum_serialization_declaration.tmpl',
- 'generators/cpp_templates/interface_declaration.tmpl',
- 'generators/cpp_templates/interface_definition.tmpl',
- 'generators/cpp_templates/interface_macros.tmpl',
- 'generators/cpp_templates/interface_proxy_declaration.tmpl',
- 'generators/cpp_templates/interface_request_validator_declaration.tmpl',
- 'generators/cpp_templates/interface_response_validator_declaration.tmpl',
- 'generators/cpp_templates/interface_stub_declaration.tmpl',
- 'generators/cpp_templates/module.cc.tmpl',
- 'generators/cpp_templates/module.h.tmpl',
- 'generators/cpp_templates/module-internal.h.tmpl',
- 'generators/cpp_templates/struct_data_view_declaration.tmpl',
- 'generators/cpp_templates/struct_data_view_definition.tmpl',
- 'generators/cpp_templates/struct_declaration.tmpl',
- 'generators/cpp_templates/struct_definition.tmpl',
- 'generators/cpp_templates/struct_macros.tmpl',
- 'generators/cpp_templates/struct_serialization_declaration.tmpl',
- 'generators/cpp_templates/struct_serialization_definition.tmpl',
- 'generators/cpp_templates/union_declaration.tmpl',
- 'generators/cpp_templates/union_definition.tmpl',
- 'generators/cpp_templates/union_serialization_declaration.tmpl',
- 'generators/cpp_templates/union_serialization_definition.tmpl',
- 'generators/cpp_templates/validation_macros.tmpl',
- 'generators/cpp_templates/wrapper_class_declaration.tmpl',
- 'generators/cpp_templates/wrapper_class_definition.tmpl',
- 'generators/cpp_templates/wrapper_class_template_definition.tmpl',
- 'generators/cpp_templates/wrapper_union_class_declaration.tmpl',
- 'generators/cpp_templates/wrapper_union_class_definition.tmpl',
- 'generators/cpp_templates/wrapper_union_class_template_definition.tmpl',
- 'generators/java_templates/constant_definition.tmpl',
- 'generators/java_templates/constants.java.tmpl',
- 'generators/java_templates/data_types_definition.tmpl',
- 'generators/java_templates/enum_definition.tmpl',
- 'generators/java_templates/enum.java.tmpl',
- 'generators/java_templates/header.java.tmpl',
- 'generators/java_templates/interface_definition.tmpl',
- 'generators/java_templates/interface_internal.java.tmpl',
- 'generators/java_templates/interface.java.tmpl',
- 'generators/java_templates/struct.java.tmpl',
- 'generators/java_templates/union.java.tmpl',
- 'generators/js_templates/enum_definition.tmpl',
- 'generators/js_templates/interface_definition.tmpl',
- 'generators/js_templates/module_definition.tmpl',
- 'generators/js_templates/module.amd.tmpl',
- 'generators/js_templates/struct_definition.tmpl',
- 'generators/js_templates/union_definition.tmpl',
- 'generators/js_templates/validation_macros.tmpl',
- ],
- 'outputs': [
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/cpp_templates.zip',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/java_templates.zip',
- '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings/js_templates.zip',
- ],
- 'action': [
- 'python', '<@(mojom_bindings_generator)',
- '--use_bundled_pylibs', 'precompile',
- '-o', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings',
- ],
- }
- ],
- 'hard_dependency': 1,
- },
- ],
-}
-
diff --git a/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni b/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni
index ef19cc3c55c..8598cd81e2a 100644
--- a/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni
+++ b/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni
@@ -9,10 +9,15 @@ for_blink = true
_typemap_imports = [
"//mojo/public/cpp/bindings/tests/blink_typemaps.gni",
"//third_party/WebKit/Source/platform/mojo/blink_typemaps.gni",
+ "//third_party/WebKit/public/blink_typemaps.gni",
+ "//third_party/WebKit/public/public_typemaps.gni",
]
_typemaps = []
foreach(typemap_import, _typemap_imports) {
+ # Avoid reassignment error by assigning to empty scope first.
+ _imported = {
+ }
_imported = read_file(typemap_import, "scope")
_typemaps += _imported.typemaps
}
diff --git a/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni
index 44c2ae6a914..2250cb1d91a 100644
--- a/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni
+++ b/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -3,15 +3,27 @@
# found in the LICENSE file.
_typemap_imports = [
+ "//ash/public/interfaces/typemaps.gni",
"//cc/ipc/typemaps.gni",
- "//device/bluetooth/public/interfaces/typemaps.gni",
+ "//chrome/browser/media/router/mojo/typemaps.gni",
"//components/arc/common/typemaps.gni",
+ "//components/metrics/public/cpp/typemaps.gni",
"//components/typemaps.gni",
+ "//content/common/bluetooth/typemaps.gni",
+ "//content/common/typemaps.gni",
+ "//content/public/common/typemaps.gni",
+ "//device/bluetooth/public/interfaces/typemaps.gni",
+ "//device/generic_sensor/public/interfaces/typemaps.gni",
"//gpu/ipc/common/typemaps.gni",
"//media/mojo/interfaces/typemaps.gni",
"//mojo/common/typemaps.gni",
"//mojo/public/cpp/bindings/tests/chromium_typemaps.gni",
+ "//services/shell/public/cpp/typemaps.gni",
+ "//services/ui/public/interfaces/display/typemaps.gni",
+ "//services/video_capture/public/interfaces/typemaps.gni",
"//skia/public/interfaces/typemaps.gni",
+ "//third_party/WebKit/public/public_typemaps.gni",
+ "//ui/base/mojo/typemaps.gni",
"//ui/events/devices/mojo/typemaps.gni",
"//ui/events/mojo/typemaps.gni",
"//ui/gfx/typemaps.gni",
@@ -20,6 +32,9 @@ _typemap_imports = [
_typemaps = []
foreach(typemap_import, _typemap_imports) {
+ # Avoid reassignment error by assigning to empty scope first.
+ _imported = {
+ }
_imported = read_file(typemap_import, "scope")
_typemaps += _imported.typemaps
}
diff --git a/chromium/mojo/public/tools/bindings/generate_type_mappings.py b/chromium/mojo/public/tools/bindings/generate_type_mappings.py
index 77915892967..16e3035dc98 100755
--- a/chromium/mojo/public/tools/bindings/generate_type_mappings.py
+++ b/chromium/mojo/public/tools/bindings/generate_type_mappings.py
@@ -97,9 +97,9 @@ def ParseTypemap(typemap):
mojom_type = match_result.group(1)
native_type = match_result.group(2)
- # The only attribute supported currently is "pass_by_value".
- pass_by_value = (match_result.group(3) and
- match_result.group(3) == "pass_by_value")
+ attributes = []
+ if match_result.group(3):
+ attributes = match_result.group(3).split(',')
assert mojom_type not in result, (
"Cannot map multiple native types (%s, %s) to the same mojom type: %s" %
@@ -107,7 +107,10 @@ def ParseTypemap(typemap):
result[mojom_type] = {
'typename': native_type,
- 'pass_by_value': pass_by_value,
+ 'move_only': 'move_only' in attributes,
+ 'copyable_pass_by_value': 'copyable_pass_by_value' in attributes,
+ 'nullable_is_same_type': 'nullable_is_same_type' in attributes,
+ 'hashable': 'hashable' in attributes,
'public_headers': values['public_headers'],
'traits_headers': values['traits_headers'],
}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl
index 36856e8f601..087f225517d 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl
@@ -1,20 +1,49 @@
{#---
Macro for enum definition, and the declaration of associated functions.
---#}
+
{%- macro enum_decl(enum) %}
-enum class {{enum.name}} : int32_t {
-{%- for field in enum.fields %}
-{%- if field.value %}
+{%- set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}
+enum class {{enum_name}} : int32_t {
+{%- for field in enum.fields %}
+{%- if field.value %}
{{field.name}} = {{field.value|expression_to_text}},
-{%- else %}
+{%- else %}
{{field.name}},
-{%- endif %}
-{%- endfor %}
+{%- endif %}
+{%- endfor %}
};
+
+inline std::ostream& operator<<(std::ostream& os, {{enum_name}} value) {
+ switch(value) {
+{%- for _, values in enum.fields|groupby('numeric_value') %}
+ case {{enum_name}}::{{values[0].name}}:
+ return os << "{{enum_name}}::
+{%- if values|length > 1 -%}
+ {{'{'}}
+{%- endif -%}
+ {{values|map(attribute='name')|join(', ')}}
+{%- if values|length > 1 -%}
+ {{'}'}}
+{%- endif -%}
+ ";
+{%- endfor %}
+ default:
+ return os << "Unknown {{enum_name}} value: " << static_cast<int32_t>(value);
+ }
+}
+
+{#- Returns true if the given enum value exists in this version of enum. #}
+inline bool IsKnownEnumValue({{enum_name}} value) {
+ return {{enum|get_name_for_kind(internal=True,
+ flatten_nested_kind=True)}}::IsKnownValue(
+ static_cast<int32_t>(value));
+}
{%- endmacro %}
{%- macro enum_data_decl(enum) %}
-struct {{enum.name}}_Data {
+{%- set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}
+struct {{enum_name}}_Data {
public:
static bool const kIsExtensible = {% if enum.extensible %}true{% else %}false{% endif %};
@@ -42,36 +71,10 @@ struct {{enum.name}}_Data {
};
{%- endmacro %}
-{#--- macros for enum-associated functions. Namely:
- * operator<<(): outputs the given enum value.
- * IsKnownEnumValue(): returns true if the given enum value exists in this
- generated version of enum.
----#}
-
-{%- macro enum_stream_operator(enum) %}
-inline std::ostream& operator<<(std::ostream& os, {{enum|get_name_for_kind}} value) {
- switch(value) {
-{%- for _, values in enum.fields|groupby('numeric_value') %}
- case {{enum|get_name_for_kind}}::{{values[0].name}}:
- return os << "{{enum|get_name_for_kind}}::
-{%- if values|length > 1 -%}
- {{'{'}}
-{%- endif -%}
- {{values|map(attribute='name')|join(', ')}}
-{%- if values|length > 1 -%}
- {{'}'}}
-{%- endif -%}
- ";
-{%- endfor %}
- default:
- return os << "Unknown {{enum|get_name_for_kind}} value: " << static_cast<int32_t>(value);
- }
-}
-{%- endmacro %}
-
-{%- macro is_known_enum_value(enum) %}
-inline bool IsKnownEnumValue({{enum|get_name_for_kind}} value) {
- return {{enum|get_qualified_name_for_kind(internal=True)}}::IsKnownValue(
- static_cast<int32_t>(value));
-}
+{%- macro enum_hash(enum) %}
+{%- set enum_name = enum|get_qualified_name_for_kind(
+ flatten_nested_kind=True) %}
+template <>
+struct hash<{{enum_name}}>
+ : public mojo::internal::EnumHashImpl<{{enum_name}}> {};
{%- endmacro %}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_serialization_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_serialization_declaration.tmpl
index e42128d5381..d7d0e5d8738 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_serialization_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_serialization_declaration.tmpl
@@ -1,4 +1,5 @@
-{%- set mojom_type = enum|get_qualified_name_for_kind %}
+{%- set mojom_type = enum|get_qualified_name_for_kind(
+ flatten_nested_kind=True) %}
template <>
struct EnumTraits<{{mojom_type}}, {{mojom_type}}> {
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
index b5f8e163b4d..c6b8c6d01cb 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
@@ -7,7 +7,8 @@ class {{interface.name}}RequestValidator;
class {{interface.name}}ResponseValidator;
{%- endif %}
-class {{interface.name}} {
+class {{export_attribute}} {{interface.name}}
+ : public {{interface.name}}InterfaceBase {
public:
static const char Name_[];
static const uint32_t Version_ = {{interface.version}};
@@ -25,13 +26,8 @@ class {{interface.name}} {
{%- endif %}
{#--- Enums #}
-{% from "enum_macros.tmpl" import enum_decl -%}
{%- for enum in interface.enums %}
-{%- if enum|is_native_only_kind %}
- using {{enum.name}} = mojo::NativeEnum;
-{%- else %}
- {{enum_decl(enum)|indent(2)}}
-{%- endif %}
+ using {{enum.name}} = {{enum|get_name_for_kind(flatten_nested_kind=True)}};
{%- endfor %}
{#--- Constants #}
@@ -54,7 +50,8 @@ class {{interface.name}} {
virtual bool {{method.name}}({{interface_macros.declare_sync_method_params("", method)}});
{%- endif %}
- using {{method.name}}Callback = {{interface_macros.declare_callback(method, for_blink)}};
+ using {{method.name}}Callback = {{interface_macros.declare_callback(method,
+ for_blink, use_new_wrapper_types)}};
{%- endif %}
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
index 4e4efce37a6..23908c26a60 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -7,7 +7,6 @@
{%- macro alloc_params(struct, params, message, serialization_context,
description) %}
- ({{params}})->DecodePointers();
({{serialization_context}})->handles.Swap(({{message}})->mutable_handles());
bool success = true;
{%- for param in struct.packed.packed_fields_in_ordinal_order %}
@@ -17,13 +16,10 @@
{{serialization_context}});
{{struct_macros.deserialize(struct, "input_data_view", "p_%s", "success")}}
if (!success) {
- mojo::internal::ValidationContext validation_context(
- {{message}}->data(), {{message}}->data_num_bytes(),
- {{message}}->handles()->size(), {{message}},
+ ReportValidationErrorForMessage(
+ {{message}},
+ mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,
"{{description}} deserializer");
- ReportValidationError(
- &validation_context,
- mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED);
return false;
}
{%- endmacro %}
@@ -42,8 +38,6 @@ std::move(p_{{param.name}})
serialization_context)}}
({{serialization_context}})->handles.Swap(
builder.message()->mutable_handles());
- params->EncodePointers();
-
{%- endmacro %}
{#--- Begin #}
@@ -103,13 +97,15 @@ bool {{class_name}}_{{method.name}}_HandleSyncResponse::Accept(
reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>(
message->mutable_payload());
+{%- set desc = class_name~"::"~method.name~" response" %}
{{alloc_params(method.response_param_struct, "params", "message",
- "&serialization_context_",
- "{{class_name}}::{{method.name}} response")}}
+ "&serialization_context_", desc)}}
{%- for param in method.response_parameters %}
*out_{{param.name}}_ = std::move(p_{{param.name}});
{%- endfor %}
+ mojo::internal::SyncMessageResponseSetup::SetCurrentSyncResponseMessage(
+ message);
*result_ = true;
return true;
}
@@ -136,18 +132,20 @@ bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept(
reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>(
message->mutable_payload());
+{%- set desc = class_name~"::"~method.name~" response" %}
{{alloc_params(method.response_param_struct, "params", "message",
- "&serialization_context_",
- "{{class_name}}_{{method.name}} response")}}
- if (!callback_.is_null())
+ "&serialization_context_", desc)}}
+ if (!callback_.is_null()) {
+ mojo::internal::MessageDispatchContext context(message);
callback_.Run({{pass_params(method.response_parameters)}});
+ }
return true;
}
{%- endif %}
{%- endfor %}
{{proxy_name}}::{{proxy_name}}(mojo::MessageReceiverWithResponder* receiver)
- : ControlMessageProxy(receiver) {
+ : receiver_(receiver) {
}
{#--- Proxy definitions #}
@@ -220,9 +218,7 @@ void {{proxy_name}}::{{method.name}}(
{%- set response_params_struct = method.response_param_struct %}
{%- set params_description =
"%s.%s response"|format(interface.name, method.name) %}
-class {{class_name}}_{{method.name}}_ProxyToResponder
- : public base::RefCountedThreadSafe<
- {{class_name}}_{{method.name}}_ProxyToResponder> {
+class {{class_name}}_{{method.name}}_ProxyToResponder {
public:
static {{class_name}}::{{method.name}}Callback CreateCallback(
uint64_t request_id,
@@ -230,26 +226,11 @@ class {{class_name}}_{{method.name}}_ProxyToResponder
mojo::MessageReceiverWithStatus* responder,
scoped_refptr<mojo::AssociatedGroupController>
group_controller) {
- scoped_refptr<{{class_name}}_{{method.name}}_ProxyToResponder> proxy
- = new {{class_name}}_{{method.name}}_ProxyToResponder(
- request_id, is_sync, responder, group_controller);
+ std::unique_ptr<{{class_name}}_{{method.name}}_ProxyToResponder> proxy(
+ new {{class_name}}_{{method.name}}_ProxyToResponder(
+ request_id, is_sync, responder, group_controller));
return base::Bind(&{{class_name}}_{{method.name}}_ProxyToResponder::Run,
- proxy);
- }
-
- private:
- friend class base::RefCountedThreadSafe<
- {{class_name}}_{{method.name}}_ProxyToResponder>;
-
- {{class_name}}_{{method.name}}_ProxyToResponder(
- uint64_t request_id,
- bool is_sync,
- mojo::MessageReceiverWithStatus* responder,
- scoped_refptr<mojo::AssociatedGroupController> group_controller)
- : request_id_(request_id),
- is_sync_(is_sync),
- responder_(responder),
- serialization_context_(std::move(group_controller)) {
+ base::Passed(&proxy));
}
~{{class_name}}_{{method.name}}_ProxyToResponder() {
@@ -266,9 +247,22 @@ class {{class_name}}_{{method.name}}_ProxyToResponder
delete responder_;
}
+ private:
+ {{class_name}}_{{method.name}}_ProxyToResponder(
+ uint64_t request_id,
+ bool is_sync,
+ mojo::MessageReceiverWithStatus* responder,
+ scoped_refptr<mojo::AssociatedGroupController> group_controller)
+ : request_id_(request_id),
+ is_sync_(is_sync),
+ responder_(responder),
+ serialization_context_(std::move(group_controller)) {
+ }
+
void Run(
{{interface_macros.declare_responder_params(
- "in_", method.response_parameters, for_blink)}});
+ "in_", method.response_parameters, for_blink,
+ use_new_wrapper_types)}});
uint64_t request_id_;
bool is_sync_;
@@ -281,7 +275,8 @@ class {{class_name}}_{{method.name}}_ProxyToResponder
void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
{{interface_macros.declare_responder_params(
- "in_", method.response_parameters, for_blink)}}) {
+ "in_", method.response_parameters, for_blink,
+ use_new_wrapper_types)}}) {
{{struct_macros.get_serialized_size(response_params_struct, "in_%s",
"&serialization_context_")}}
mojo::internal::ResponseMessageBuilder builder(
@@ -301,8 +296,7 @@ void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
{%- endfor %}
{{class_name}}Stub::{{class_name}}Stub()
- : sink_(nullptr),
- control_message_handler_({{interface.name}}::Version_) {
+ : sink_(nullptr) {
}
{{class_name}}Stub::~{{interface.name}}Stub() {}
@@ -310,8 +304,6 @@ void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
{#--- Stub definition #}
bool {{class_name}}Stub::Accept(mojo::Message* message) {
- if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
- return control_message_handler_.Accept(message);
{%- if interface.methods %}
switch (message->header()->name) {
{%- for method in interface.methods %}
@@ -321,12 +313,13 @@ bool {{class_name}}Stub::Accept(mojo::Message* message) {
reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
message->mutable_payload());
+{%- set desc = class_name~"::"~method.name %}
{{alloc_params(method.param_struct, "params", "message",
- "&serialization_context_", "{{class_name}}::{{method.name}}")
- |indent(4)}}
+ "&serialization_context_", desc)|indent(4)}}
// A null |sink_| means no implementation was bound.
assert(sink_);
TRACE_EVENT0("mojom", "{{class_name}}::{{method.name}}");
+ mojo::internal::MessageDispatchContext context(message);
sink_->{{method.name}}({{pass_params(method.parameters)}});
return true;
{%- else %}
@@ -341,8 +334,6 @@ bool {{class_name}}Stub::Accept(mojo::Message* message) {
bool {{class_name}}Stub::AcceptWithResponder(
mojo::Message* message, mojo::MessageReceiverWithStatus* responder) {
- if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
- return control_message_handler_.AcceptWithResponder(message, responder);
{%- if interface.methods %}
switch (message->header()->name) {
{%- for method in interface.methods %}
@@ -352,8 +343,9 @@ bool {{class_name}}Stub::AcceptWithResponder(
reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
message->mutable_payload());
+{%- set desc = class_name~"::"~method.name %}
{{alloc_params(method.param_struct, "params", "message",
- "&serialization_context_", "{{class_name}}::{{method.name}}")|
+ "&serialization_context_", desc)|
indent(4)}}
{{class_name}}::{{method.name}}Callback callback =
{{class_name}}_{{method.name}}_ProxyToResponder::CreateCallback(
@@ -364,6 +356,7 @@ bool {{class_name}}Stub::AcceptWithResponder(
// A null |sink_| means no implementation was bound.
assert(sink_);
TRACE_EVENT0("mojom", "{{class_name}}::{{method.name}}");
+ mojo::internal::MessageDispatchContext context(message);
sink_->{{method.name}}(
{%- if method.parameters -%}{{pass_params(method.parameters)}}, {% endif -%}callback);
return true;
@@ -379,23 +372,14 @@ bool {{class_name}}Stub::AcceptWithResponder(
{#--- Request validator definitions #}
-{{class_name}}RequestValidator::{{class_name}}RequestValidator(
- mojo::MessageReceiver* sink) : MessageFilter(sink) {
-}
-
bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
- assert(sink_);
+ if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
+ return true;
mojo::internal::ValidationContext validation_context(
message->data(), message->data_num_bytes(), message->handles()->size(),
message, "{{class_name}} RequestValidator");
- if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) {
- if (!mojo::internal::ValidateControlRequest(message, &validation_context))
- return false;
- return sink_->Accept(message);
- }
-
switch (message->header()->name) {
{%- for method in interface.methods %}
case internal::k{{class_name}}_{{method.name}}_Name: {
@@ -415,7 +399,7 @@ bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
message, &validation_context)) {
return false;
}
- return sink_->Accept(message);
+ return true;
}
{%- endfor %}
default:
@@ -431,23 +415,14 @@ bool {{class_name}}RequestValidator::Accept(mojo::Message* 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) {
- assert(sink_);
+ if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
+ return true;
mojo::internal::ValidationContext validation_context(
message->data(), message->data_num_bytes(), message->handles()->size(),
message, "{{class_name}} ResponseValidator");
- if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) {
- if (!mojo::internal::ValidateControlResponse(message, &validation_context))
- return false;
- return sink_->Accept(message);
- }
-
if (!mojo::internal::ValidateMessageIsResponse(message, &validation_context))
return false;
switch (message->header()->name) {
@@ -458,7 +433,7 @@ bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) {
message, &validation_context)) {
return false;
}
- return sink_->Accept(message);
+ return true;
}
{%- endfor %}
default:
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
index c996adc3f2b..4bec4c64f59 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
@@ -5,9 +5,10 @@
{%- endfor %}
{%- endmacro %}
-{%- macro declare_responder_params(prefix, parameters, for_blink) %}
+{%- macro declare_responder_params(prefix, parameters, for_blink, use_new_wrapper_types) %}
{%- for param in parameters -%}
-{%- if (not param.kind|is_string_kind) or for_blink -%}
+{%- if (not param.kind|is_string_kind) or for_blink or
+ use_new_wrapper_types -%}
{{param.kind|cpp_wrapper_param_type}} {{prefix}}{{param.name}}
{%- else %}
mojo::String {{prefix}}{{param.name}}
@@ -16,17 +17,18 @@ mojo::String {{prefix}}{{param.name}}
{%- endfor %}
{%- endmacro %}
-{%- macro declare_callback(method, for_blink) -%}
+{%- macro declare_callback(method, for_blink, use_new_wrapper_types) -%}
base::Callback<void(
{%- for param in method.response_parameters -%}
{#- TODO(yzshen): For historical reasons, we use mojo::String here (instead of
const mojo::String&) inconsistently. Preserve the behavior temporarily. #}
-{%- if (not param.kind|is_string_kind) or for_blink -%}
+{%- if (not param.kind|is_string_kind) or for_blink or
+ use_new_wrapper_types -%}
{{param.kind|cpp_wrapper_param_type}}
-{%- else -%}
+{%- else -%}
mojo::String
-{%- endif %}
-{%- if not loop.last %}, {% endif %}
+{%- endif %}
+{%- if not loop.last %}, {% endif %}
{%- endfor -%}
)>
{%- 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
index 477116b105f..cfc4ef6770d 100644
--- 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
@@ -1,7 +1,6 @@
{%- import "interface_macros.tmpl" as interface_macros %}
-class {{interface.name}}Proxy
- : public {{interface.name}},
- public mojo::internal::ControlMessageProxy {
+class {{export_attribute}} {{interface.name}}Proxy
+ : public {{interface.name}} {
public:
explicit {{interface.name}}Proxy(mojo::MessageReceiverWithResponder* receiver);
@@ -17,5 +16,6 @@ class {{interface.name}}Proxy
}
private:
+ mojo::MessageReceiverWithResponder* receiver_;
mojo::internal::SerializationContext serialization_context_;
};
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
index 29917ea8e9b..a00d14886d8 100644
--- 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
@@ -1,6 +1,4 @@
-class {{interface.name}}RequestValidator : public mojo::MessageFilter {
+class {{export_attribute}} {{interface.name}}RequestValidator : public NON_EXPORTED_BASE(mojo::MessageReceiver) {
public:
- explicit {{interface.name}}RequestValidator(mojo::MessageReceiver* sink = nullptr);
-
bool Accept(mojo::Message* message) 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
index 5893bfd807f..e2caa02c79d 100644
--- 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
@@ -1,6 +1,4 @@
-class {{interface.name}}ResponseValidator : public mojo::MessageFilter {
+class {{export_attribute}} {{interface.name}}ResponseValidator : public NON_EXPORTED_BASE(mojo::MessageReceiver) {
public:
- explicit {{interface.name}}ResponseValidator(mojo::MessageReceiver* sink = nullptr);
-
bool Accept(mojo::Message* message) 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
index 30b5de7cb3f..8f1a45c3f43 100644
--- 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
@@ -1,4 +1,4 @@
-class {{interface.name}}Stub : public mojo::MessageReceiverWithResponderStatus {
+class {{export_attribute}} {{interface.name}}Stub : public NON_EXPORTED_BASE(mojo::MessageReceiverWithResponderStatus) {
public:
{{interface.name}}Stub();
~{{interface.name}}Stub() override;
@@ -15,5 +15,4 @@ class {{interface.name}}Stub : public mojo::MessageReceiverWithResponderStatus {
private:
{{interface.name}}* sink_;
mojo::internal::SerializationContext serialization_context_;
- mojo::internal::ControlMessageHandler control_message_handler_;
};
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
deleted file mode 100644
index 5256e752e56..00000000000
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
+++ /dev/null
@@ -1,126 +0,0 @@
-// 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 variant -%}
-{%- set variant_path = "%s-%s"|format(module.path, variant) -%}
-{%- else -%}
-{%- set variant_path = module.path -%}
-{%- endif -%}
-
-{%- set header_guard = "%s_INTERNAL_H_"|format(
- variant_path|upper|replace("/","_")|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"
-#include "mojo/public/cpp/bindings/lib/serialization.h"
-#include "mojo/public/cpp/bindings/lib/union_accessor.h"
-#include "mojo/public/cpp/bindings/struct_ptr.h"
-
-{%- for import in imports %}
-{%- if variant %}
-#include "{{"%s-%s-internal.h"|format(import.module.path, variant)}}"
-{%- else %}
-#include "{{import.module.path}}-internal.h"
-{%- endif %}
-{%- endfor %}
-
-namespace mojo {
-namespace internal {
-class ValidationContext;
-}
-}
-
-{%- for namespace in namespaces_as_array %}
-namespace {{namespace}} {
-{%- endfor %}
-{%- if variant %}
-namespace {{variant}} {
-{%- endif %}
-
-{#--- Wrapper forward declarations #}
-{% for struct in structs %}
-{%- if struct|is_native_only_kind %}
-using {{struct.name}} = mojo::NativeStruct;
-{%- else %}
-class {{struct.name}};
-{%- endif %}
-{%- endfor %}
-
-{#--- Wrapper forward declarations for unions #}
-{% for union in unions %}
-class {{union.name}};
-{%- endfor %}
-
-namespace internal {
-
-{#--- Internal forward declarations #}
-{% for struct in structs %}
-{%- if struct|is_native_only_kind %}
-using {{struct.name}}_Data = mojo::internal::NativeStruct_Data;
-{%- else %}
-class {{struct.name}}_Data;
-{%- endif %}
-{%- endfor %}
-
-{% for union in unions %}
-class {{union.name}}_Data;
-{%- endfor %}
-
-{#--- Enums #}
-{% from "enum_macros.tmpl" import enum_data_decl -%}
-{%- for enum in enums %}
-{%- if enum|is_native_only_kind %}
- using {{enum.name}}_Data = mojo::internal::NativeEnum_Data;
-{%- else %}
- {{enum_data_decl(enum)}}
-{%- endif %}
-{%- endfor %}
-
-#pragma pack(push, 1)
-
-{#--- Unions must be declared first because they can be members of structs #}
-{#--- Union class declarations #}
-{% for union in unions %}
-{% include "union_declaration.tmpl" %}
-{%- endfor %}
-
-{#--- Struct class declarations #}
-{% for struct in structs %}
-{%- if not struct|is_native_only_kind %}
-{% include "struct_declaration.tmpl" %}
-{%- endif %}
-{%- endfor %}
-
-{#--- Interface class declarations. They are needed only when they contain
- enums. #}
-{%- for interface in interfaces %}
-{%- if interface.enums %}
-class {{interface.name}}_Data {
- public:
-{%- for enum in interface.enums %}
-{%- if enum|is_native_only_kind %}
- using {{enum.name}}_Data = mojo::internal::NativeEnum_Data;
-{%- else %}
- {{enum_data_decl(enum)|indent(2)}}
-{%- endif %}
-{%- endfor %}
-};
-{%- endif %}
-{%- endfor %}
-
-#pragma pack(pop)
-
-} // namespace internal
-{%- if variant %}
-} // namespace {{variant}}
-{%- 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/module-shared-internal.h.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl
new file mode 100644
index 00000000000..bb5acd93433
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl
@@ -0,0 +1,95 @@
+// Copyright 2016 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_SHARED_INTERNAL_H_"|format(
+ module.path|upper|replace("/","_")|replace(".","_")|
+ replace("-", "_")) %}
+
+#ifndef {{header_guard}}
+#define {{header_guard}}
+
+#include <stdint.h>
+
+#include "mojo/public/cpp/bindings/lib/array_internal.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/map_data_internal.h"
+#include "mojo/public/cpp/bindings/lib/native_enum_data.h"
+#include "mojo/public/cpp/bindings/lib/native_struct_data.h"
+#include "mojo/public/cpp/bindings/lib/buffer.h"
+
+{%- for import in imports %}
+#include "{{import.module.path}}-shared-internal.h"
+{%- endfor %}
+
+namespace mojo {
+namespace internal {
+class ValidationContext;
+}
+}
+
+{%- for namespace in namespaces_as_array %}
+namespace {{namespace}} {
+{%- endfor %}
+namespace internal {
+
+{#--- Internal forward declarations #}
+{%- for struct in structs %}
+{%- if struct|is_native_only_kind %}
+using {{struct.name}}_Data = mojo::internal::NativeStruct_Data;
+{%- else %}
+class {{struct.name}}_Data;
+{%- endif %}
+{%- endfor %}
+
+{%- for union in unions %}
+class {{union.name}}_Data;
+{%- endfor %}
+
+{#--- Enums #}
+{%- from "enum_macros.tmpl" import enum_data_decl -%}
+{%- for enum in all_enums %}
+{%- if enum|is_native_only_kind %}
+using {{enum.name}}_Data = mojo::internal::NativeEnum_Data;
+{%- else %}
+{{enum_data_decl(enum)}}
+{%- endif %}
+{%- endfor %}
+
+#pragma pack(push, 1)
+
+{#--- Unions must be declared first because they can be members of structs #}
+{#--- Union class declarations #}
+{%- for union in unions %}
+{% include "union_declaration.tmpl" %}
+{%- endfor %}
+
+{#--- Struct class declarations #}
+{%- for struct in structs %}
+{%- if not struct|is_native_only_kind %}
+{% include "struct_declaration.tmpl" %}
+{%- endif %}
+{%- endfor %}
+
+{#--- 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.param_struct %}
+{% include "struct_declaration.tmpl" %}
+{%- if method.response_parameters != None %}
+{%- set struct = method.response_param_struct %}
+{% include "struct_declaration.tmpl" %}
+{%- endif %}
+{%- endfor %}
+{%- 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-shared.cc.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl
new file mode 100644
index 00000000000..645bb692b00
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl
@@ -0,0 +1,64 @@
+// Copyright 2016 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(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4065)
+#endif
+
+#include "{{module.path}}-shared.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "mojo/public/cpp/bindings/lib/validate_params.h"
+#include "mojo/public/cpp/bindings/lib/validation_context.h"
+#include "mojo/public/cpp/bindings/lib/validation_errors.h"
+#include "mojo/public/cpp/bindings/lib/validation_util.h"
+
+{%- for header in extra_traits_headers %}
+#include "{{header}}"
+{%- endfor %}
+
+{%- for namespace in namespaces_as_array %}
+namespace {{namespace}} {
+{%- endfor %}
+
+namespace internal {
+
+{#--- Union definitions #}
+{%- for union in unions %}
+{% include "union_definition.tmpl" %}
+{%- endfor %}
+
+{#--- Struct definitions #}
+{%- for struct in structs %}
+{%- if not struct|is_native_only_kind %}
+{% include "struct_definition.tmpl" %}
+{%- endif %}
+{%- endfor %}
+
+{#--- Interface parameter definitions #}
+{%- for interface in interfaces %}
+{%- for method in interface.methods %}
+{%- set method_name = "k%s_%s_Name"|format(interface.name, method.name) %}
+{%- set struct = method.param_struct %}
+{% include "struct_definition.tmpl" %}
+{%- if method.response_parameters != None %}
+{%- set struct = method.response_param_struct %}
+{% include "struct_definition.tmpl" %}
+{%- endif %}
+{%- endfor %}
+{%- endfor %}
+
+} // namespace internal
+
+{%- for namespace in namespaces_as_array|reverse %}
+} // namespace {{namespace}}
+{%- endfor %}
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl
new file mode 100644
index 00000000000..4b18a218709
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl
@@ -0,0 +1,212 @@
+// Copyright 2016 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_SHARED_H_"|format(
+ module.path|upper|replace("/","_")|replace(".","_")|
+ replace("-", "_")) %}
+
+{%- macro mojom_type_traits(kind) %}
+template <>
+struct MojomTypeTraits<{{kind|get_qualified_name_for_kind}}DataView> {
+ using Data = {{kind|get_qualified_name_for_kind(internal=True)}};
+{%- if kind|is_union_kind %}
+ using DataAsArrayElement = Data;
+ static const MojomTypeCategory category = MojomTypeCategory::UNION;
+{%- else %}
+ using DataAsArrayElement = Pointer<Data>;
+ static const MojomTypeCategory category = MojomTypeCategory::STRUCT;
+{%- endif %}
+};
+{%- endmacro %}
+
+{%- macro namespace_begin() %}
+{%- for namespace in namespaces_as_array %}
+namespace {{namespace}} {
+{%- endfor %}
+{%- endmacro %}
+
+{%- macro namespace_end() %}
+{%- for namespace in namespaces_as_array|reverse %}
+} // namespace {{namespace}}
+{%- endfor %}
+{%- endmacro %}
+
+#ifndef {{header_guard}}
+#define {{header_guard}}
+
+#include <stdint.h>
+
+#include <functional>
+#include <ostream>
+#include <type_traits>
+#include <utility>
+
+#include "base/compiler_specific.h"
+#include "mojo/public/cpp/bindings/array_data_view.h"
+#include "mojo/public/cpp/bindings/enum_traits.h"
+#include "mojo/public/cpp/bindings/interface_data_view.h"
+#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
+#include "mojo/public/cpp/bindings/lib/serialization.h"
+#include "mojo/public/cpp/bindings/map_data_view.h"
+#include "mojo/public/cpp/bindings/native_enum.h"
+#include "mojo/public/cpp/bindings/native_struct_data_view.h"
+#include "mojo/public/cpp/bindings/string_data_view.h"
+#include "{{module.path}}-shared-internal.h"
+{%- for import in imports %}
+#include "{{import.module.path}}-shared.h"
+{%- endfor %}
+
+{{namespace_begin()}}
+
+{#--- Struct Forward Declarations -#}
+{%- for struct in structs %}
+{%- if struct|is_native_only_kind %}
+using {{struct.name}}DataView = mojo::NativeStructDataView;
+{%- else %}
+class {{struct.name}}DataView;
+{%- endif %}
+{% endfor %}
+
+{#--- Union Forward Declarations -#}
+{%- for union in unions %}
+class {{union.name}}DataView;
+{%- endfor %}
+
+{{namespace_end()}}
+
+namespace mojo {
+namespace internal {
+
+{%- for struct in structs %}
+{%- if not struct|is_native_only_kind %}
+{{mojom_type_traits(struct)}}
+{%- endif %}
+{%- endfor %}
+
+{%- for union in unions %}
+{{mojom_type_traits(union)}}
+{%- endfor %}
+
+} // namespace internal
+} // namespace mojo
+
+{{namespace_begin()}}
+
+{#--- Enums #}
+{%- from "enum_macros.tmpl" import enum_decl%}
+{%- for enum in all_enums %}
+{%- if enum|is_native_only_kind %}
+using {{enum.name}} = mojo::NativeEnum;
+{%- else %}
+{{enum_decl(enum)}}
+{%- endif %}
+{%- endfor %}
+
+{#--- Interfaces #}
+{%- if interfaces %}
+// Interface base classes. They are used for type safety check.
+{%- endif %}
+{%- for interface in interfaces %}
+class {{interface.name}}InterfaceBase {};
+
+using {{interface.name}}PtrDataView =
+ mojo::InterfacePtrDataView<{{interface.name}}InterfaceBase>;
+using {{interface.name}}RequestDataView =
+ mojo::InterfaceRequestDataView<{{interface.name}}InterfaceBase>;
+using {{interface.name}}AssociatedPtrInfoDataView =
+ mojo::AssociatedInterfacePtrInfoDataView<{{interface.name}}InterfaceBase>;
+using {{interface.name}}AssociatedRequestDataView =
+ mojo::AssociatedInterfaceRequestDataView<{{interface.name}}InterfaceBase>;
+
+{%- endfor %}
+
+{#--- Structs #}
+{%- for struct in structs %}
+{%- if not struct|is_native_only_kind %}
+{% include "struct_data_view_declaration.tmpl" %}
+{%- endif %}
+{%- endfor %}
+
+{#--- Interface parameter definitions #}
+{%- for interface in interfaces %}
+{%- for method in interface.methods %}
+{%- set struct = method.param_struct %}
+{% include "struct_data_view_declaration.tmpl" %}
+{%- if method.response_parameters != None %}
+{%- set struct = method.response_param_struct %}
+{% include "struct_data_view_declaration.tmpl" %}
+{%- endif %}
+{%- endfor %}
+{%- endfor %}
+
+{#--- Unions #}
+{%- for union in unions %}
+{% include "union_data_view_declaration.tmpl" %}
+{%- endfor %}
+
+{{namespace_end()}}
+
+namespace std {
+
+{%- from "enum_macros.tmpl" import enum_hash %}
+{%- for enum in all_enums %}
+{%- if not enum|is_native_only_kind %}
+{{enum_hash(enum)}}
+{%- endif %}
+{%- endfor %}
+
+} // namespace std
+
+namespace mojo {
+
+{#--- Enum Serialization Helpers -#}
+{%- for enum in all_enums %}
+{%- if not enum|is_native_only_kind %}
+{% include "enum_serialization_declaration.tmpl" %}
+{%- endif %}
+{%- endfor %}
+
+{#--- Struct Serialization Helpers -#}
+{% for struct in structs %}
+{%- if not struct|is_native_only_kind %}
+{% include "struct_serialization_declaration.tmpl" %}
+{%- endif %}
+{%- endfor %}
+
+{#--- Union Serialization Helpers -#}
+{% if unions %}
+{%- for union in unions %}
+{% include "union_serialization_declaration.tmpl" %}
+{%- endfor %}
+{%- endif %}
+
+} // namespace mojo
+
+{{namespace_begin()}}
+
+{%- for struct in structs %}
+{%- if not struct|is_native_only_kind %}
+{% include "struct_data_view_definition.tmpl" %}
+{%- endif %}
+{%- endfor %}
+
+{%- for interface in interfaces %}
+{%- for method in interface.methods %}
+{%- set struct = method.param_struct %}
+{% include "struct_data_view_definition.tmpl" %}
+{%- if method.response_parameters != None %}
+{%- set struct = method.response_param_struct %}
+{% include "struct_data_view_definition.tmpl" %}
+{%- endif %}
+{%- endfor %}
+{%- endfor %}
+
+{%- for union in unions %}
+{% include "union_data_view_definition.tmpl" %}
+{%- endfor %}
+
+{{namespace_end()}}
+
+#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
index efb9db66fd9..4383acbd8fa 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
@@ -26,13 +26,11 @@
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
-#include "mojo/public/cpp/bindings/lib/map_data_internal.h"
#include "mojo/public/cpp/bindings/lib/message_builder.h"
#include "mojo/public/cpp/bindings/lib/serialization_util.h"
#include "mojo/public/cpp/bindings/lib/validate_params.h"
#include "mojo/public/cpp/bindings/lib/validation_context.h"
#include "mojo/public/cpp/bindings/lib/validation_errors.h"
-#include "mojo/public/cpp/bindings/lib/validation_util.h"
#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
{%- if for_blink %}
@@ -57,63 +55,6 @@ const {{constant.kind|cpp_pod_type}} {{constant.name}} = {{constant|constant_val
{%- endif %}
{%- 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.param_struct %}
-{% include "struct_declaration.tmpl" %}
-{%- include "struct_definition.tmpl" %}
-{%- if method.response_parameters != None %}
-{%- set struct = method.response_param_struct %}
-{% include "struct_declaration.tmpl" %}
-{%- include "struct_definition.tmpl" %}
-{%- endif %}
-{%- endfor %}
-{%- endfor %}
-
-#pragma pack(pop)
-
-} // namespace
-
-{#--- Struct definitions #}
-{% for struct in structs %}
-{%- if not struct|is_native_only_kind %}
-{%- include "struct_definition.tmpl" %}
-{%- endif %}
-{%- endfor %}
-
-{#--- Union definitions #}
-{% for union in unions %}
-{%- include "union_definition.tmpl" %}
-{%- endfor %}
-
-} // namespace internal
-
-namespace {
-
-{#--- Interface parameter data view definitions #}
-{%- for interface in interfaces %}
-{%- for method in interface.methods %}
-{% set struct = method.param_struct %}
-{% include "struct_data_view_declaration.tmpl" %}
-{% include "struct_data_view_definition.tmpl" %}
-{%- if method.response_parameters != None %}
-{%- set struct = method.response_param_struct %}
-{% include "struct_data_view_declaration.tmpl" %}
-{% include "struct_data_view_definition.tmpl" %}
-{%- endif %}
-{%- endfor %}
-{%- endfor %}
-
-} // namespace
-
{#--- Struct Constants #}
{%- for struct in structs %}
{%- for constant in struct.constants %}
@@ -129,7 +70,6 @@ const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}} = {{cons
{%- for struct in structs %}
{%- if not struct|is_native_only_kind %}
{%- include "wrapper_class_definition.tmpl" %}
-{%- include "struct_data_view_definition.tmpl" %}
{%- endif %}
{%- endfor %}
@@ -155,18 +95,17 @@ namespace mojo {
{#--- Struct Serialization Helpers -#}
{% for struct in structs %}
{%- if not struct|is_native_only_kind %}
-{% include "struct_serialization_definition.tmpl" %}
+{% include "struct_traits_definition.tmpl" %}
{%- endif %}
{%- endfor %}
{#--- Union Serialization Helpers #}
{%- for union in unions %}
-{%- include "union_serialization_definition.tmpl" %}
+{%- include "union_traits_definition.tmpl" %}
{%- endfor %}
} // namespace mojo
-
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(_MSC_VER)
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
index 97f8e3a0b44..f89d207409f 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -12,16 +12,34 @@
variant_path|upper|replace("/","_")|replace(".","_")|
replace("-", "_")) %}
+{%- macro namespace_begin() %}
+{%- for namespace in namespaces_as_array %}
+namespace {{namespace}} {
+{%- endfor %}
+{%- if variant %}
+namespace {{variant}} {
+{%- endif %}
+{%- endmacro %}
+
+{%- macro namespace_end() %}
+{%- if variant %}
+} // namespace {{variant}}
+{%- endif %}
+{%- for namespace in namespaces_as_array|reverse %}
+} // namespace {{namespace}}
+{%- endfor %}
+{%- endmacro %}
+
#ifndef {{header_guard}}
#define {{header_guard}}
#include <stdint.h>
-#include <ostream>
+
#include <type_traits>
#include <utility>
#include "base/callback.h"
-#include "base/strings/string_piece.h"
+#include "base/optional.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
#include "mojo/public/cpp/bindings/associated_interface_request.h"
@@ -30,14 +48,14 @@
#include "mojo/public/cpp/bindings/lib/control_message_handler.h"
#include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
#include "mojo/public/cpp/bindings/lib/serialization.h"
+#include "mojo/public/cpp/bindings/lib/union_accessor.h"
#include "mojo/public/cpp/bindings/map.h"
-#include "mojo/public/cpp/bindings/message_filter.h"
-#include "mojo/public/cpp/bindings/native_enum.h"
#include "mojo/public/cpp/bindings/native_struct.h"
#include "mojo/public/cpp/bindings/no_interface.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "{{variant_path}}-internal.h"
+#include "mojo/public/cpp/bindings/union_traits.h"
+#include "{{module.path}}-shared.h"
{%- for import in imports %}
{%- if variant %}
#include "{{"%s-%s.h"|format(import.module.path, variant)}}"
@@ -49,8 +67,13 @@
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/string.h"
{%- else %}
+{# hash_util.h includes template specializations that should be present for
+ every use of {Inlined}StructPtr. #}
+#include "mojo/public/cpp/bindings/lib/wtf_hash_util.h"
#include "mojo/public/cpp/bindings/wtf_array.h"
#include "mojo/public/cpp/bindings/wtf_map.h"
+#include "third_party/WebKit/Source/wtf/HashFunctions.h"
+#include "third_party/WebKit/Source/wtf/Optional.h"
#include "third_party/WebKit/Source/wtf/text/WTFString.h"
{%- endif %}
@@ -58,26 +81,18 @@
#include "{{header}}"
{%- endfor %}
-{%- for namespace in namespaces_as_array %}
-namespace {{namespace}} {
-{%- endfor %}
-{%- if variant %}
-namespace {{variant}} {
+{%- if export_header %}
+#include "{{export_header}}"
{%- endif %}
+{{namespace_begin()}}
+
{#--- Enums #}
-{% from "enum_macros.tmpl" import enum_decl -%}
-{% from "enum_macros.tmpl" import enum_stream_operator -%}
-{% from "enum_macros.tmpl" import is_known_enum_value -%}
-{%- for enum in enums %}
-{%- if enum|is_native_only_kind %}
-using {{enum.name}} = mojo::NativeEnum;
-{%- else %}
-{{enum_decl(enum)}}
-{{enum_stream_operator(enum)}}
-{{is_known_enum_value(enum)}}
-{%- endif %}
-{%- endfor %}
+{%- if variant %}
+{%- for enum in enums %}
+using {{enum.name}} = {{enum.name}}; // Alias for definition in the parent namespace.
+{%- endfor %}
+{%- endif %}
{#--- Constants #}
{%- for constant in module.constants %}
@@ -111,7 +126,6 @@ using {{struct.name}} = mojo::NativeStruct;
using {{struct.name}}Ptr = mojo::NativeStructPtr;
{%- else %}
class {{struct.name}};
-class {{struct.name}}DataView;
{%- if struct|should_inline %}
using {{struct.name}}Ptr = mojo::InlinedStructPtr<{{struct.name}}>;
{%- else %}
@@ -162,7 +176,6 @@ typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr;
{% for struct in structs %}
{% if struct|should_inline and not struct|is_native_only_kind %}
{% include "wrapper_class_declaration.tmpl" %}
-{% include "struct_data_view_declaration.tmpl" %}
{% endif %}
{%- endfor %}
@@ -177,7 +190,6 @@ typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr;
{% for struct in structs %}
{% if not struct|should_inline and not struct|is_native_only_kind %}
{% include "wrapper_class_declaration.tmpl" %}
-{% include "struct_data_view_declaration.tmpl" %}
{% endif %}
{%- endfor %}
@@ -189,67 +201,23 @@ typedef mojo::StructPtr<{{union.name}}> {{union.name}}Ptr;
{%- if not struct|is_native_only_kind %}
{% include "wrapper_class_template_definition.tmpl" %}
{%- endif %}
-
-{%- for enum in struct.enums %}
-{%- if not enum|is_native_only_kind %}
-{{enum_stream_operator(enum)}}
-{{is_known_enum_value(enum)}}
-{%- endif %}
-{%- endfor %}
-{%- endfor %}
-
-{%- for interface in interfaces %}
-{%- for enum in interface.enums %}
-{%- if not enum|is_native_only_kind %}
-{{enum_stream_operator(enum)}}
-{{is_known_enum_value(enum)}}
-{%- endif %}
-{%- endfor %}
{%- endfor %}
-{%- if variant %}
-} // namespace {{variant}}
-{%- endif %}
-{%- for namespace in namespaces_as_array|reverse %}
-} // namespace {{namespace}}
-{%- endfor %}
+{{namespace_end()}}
namespace mojo {
-{#--- Enum Serialization Helpers -#}
-{%- for enum in enums %}
-{%- if not enum|is_native_only_kind %}
-{% include "enum_serialization_declaration.tmpl" %}
-{%- endif %}
-{%- endfor %}
-
-{%- for struct in structs %}
-{%- for enum in struct.enums %}
-{%- if not enum|is_native_only_kind %}
-{% include "enum_serialization_declaration.tmpl" %}
-{%- endif %}
-{%- endfor %}
-{%- endfor %}
-
-{%- for interface in interfaces %}
-{%- for enum in interface.enums %}
-{%- if not enum|is_native_only_kind %}
-{% include "enum_serialization_declaration.tmpl" %}
-{%- endif %}
-{%- endfor %}
-{%- endfor %}
-
{#--- Struct Serialization Helpers -#}
{% for struct in structs %}
{%- if not struct|is_native_only_kind %}
-{% include "struct_serialization_declaration.tmpl" %}
+{% include "struct_traits_declaration.tmpl" %}
{%- endif %}
{%- endfor %}
{#--- Union Serialization Helpers -#}
{% if unions %}
{%- for union in unions %}
-{% include "union_serialization_declaration.tmpl" %}
+{% include "union_traits_declaration.tmpl" %}
{%- endfor %}
{%- endif %}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl
index 78bb4322b12..96e0d614d8e 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl
@@ -1,29 +1,56 @@
class {{struct.name}}DataView {
public:
+ {{struct.name}}DataView() {}
+
{{struct.name}}DataView(
internal::{{struct.name}}_Data* data,
- mojo::internal::SerializationContext* context);
+ mojo::internal::SerializationContext* context)
+{%- if struct|requires_context_for_data_view %}
+ : data_(data), context_(context) {}
+{%- else %}
+ : data_(data) {}
+{%- endif %}
+
+ bool is_null() const { return !data_; }
{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
-{%- set kind = pf.field.kind -%}
-{%- set name = pf.field.name -%}
-{%- if kind|is_struct_kind or kind|is_array_kind or kind|is_string_kind
- or kind|is_map_kind %}
+{%- set kind = pf.field.kind %}
+{%- set name = pf.field.name %}
+{%- if kind|is_union_kind %}
+ inline void Get{{name|under_to_camel}}DataView(
+ {{kind|cpp_data_view_type}}* output);
+
+ template <typename UserType>
+ WARN_UNUSED_RESULT bool Read{{name|under_to_camel}}(UserType* output) {
+{%- if pf.min_version != 0 %}
+ auto* pointer = data_->header_.version >= {{pf.min_version}}
+ ? &data_->{{name}} : nullptr;
+{%- else %}
+ auto* pointer = &data_->{{name}};
+{%- endif %}
+ return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
+ pointer, output, context_);
+ }
+
+{%- elif kind|is_object_kind %}
+ inline void Get{{name|under_to_camel}}DataView(
+ {{kind|cpp_data_view_type}}* output);
+
template <typename UserType>
- bool Read{{name|under_to_camel}}(UserType* value) {
-{%- if pf.min_version != 0 %}
- auto pointer = data_->header_.version >= {{pf.min_version}}
- ? data_->{{name}}.ptr : nullptr;
-{%- else %}
- auto pointer = data_->{{name}}.ptr;
-{%- endif %}
+ WARN_UNUSED_RESULT bool Read{{name|under_to_camel}}(UserType* output) {
+{%- if pf.min_version != 0 %}
+ auto* pointer = data_->header_.version >= {{pf.min_version}}
+ ? data_->{{name}}.Get() : nullptr;
+{%- else %}
+ auto* pointer = data_->{{name}}.Get();
+{%- endif %}
return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
- pointer, value, context_);
+ pointer, output, context_);
}
{%- elif kind|is_enum_kind %}
template <typename UserType>
- bool Read{{name|under_to_camel}}(UserType* value) const {
+ WARN_UNUSED_RESULT bool Read{{name|under_to_camel}}(UserType* output) const {
{%- if pf.min_version != 0 %}
auto data_value = data_->header_.version >= {{pf.min_version}}
? data_->{{name}} : 0;
@@ -31,23 +58,61 @@ class {{struct.name}}DataView {
auto data_value = data_->{{name}};
{%- endif %}
return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
- data_value, value);
+ data_value, output);
}
- {{kind|get_qualified_name_for_kind}} {{name}}() const;
+ {{kind|cpp_data_view_type}} {{name}}() const {
+{%- if pf.min_version != 0 %}
+ if (data_->header_.version < {{pf.min_version}})
+ return {{kind|get_qualified_name_for_kind}}{};
+{%- endif %}
+ return static_cast<{{kind|cpp_data_view_type}}>(data_->{{name}});
+ }
-{%- elif kind|is_union_kind %}
- bool Read{{name|under_to_camel}}({{kind|cpp_wrapper_type}}* value);
+{%- elif kind|is_any_handle_kind %}
+ {{kind|cpp_data_view_type}} Take{{name|under_to_camel}}() {
+ {{kind|cpp_data_view_type}} result;
+{%- if pf.min_version != 0 %}
+ if (data_->header_.version < {{pf.min_version}})
+ return result;
+{%- endif %}
+ bool ret =
+ mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
+ &data_->{{name}}, &result, context_);
+ DCHECK(ret);
+ return result;
+ }
-{%- elif kind|is_any_handle_or_interface_kind %}
- {{kind|cpp_wrapper_type}} Take{{name|under_to_camel}}();
+{%- elif kind|is_any_interface_kind %}
+ template <typename UserType>
+ UserType Take{{name|under_to_camel}}() {
+ UserType result;
+{%- if pf.min_version != 0 %}
+ if (data_->header_.version < {{pf.min_version}})
+ return result;
+{%- endif %}
+ bool ret =
+ mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
+ &data_->{{name}}, &result, context_);
+ DCHECK(ret);
+ return result;
+ }
{%- else %}
- {{kind|cpp_wrapper_type}} {{name}}() const;
+ {{kind|cpp_data_view_type}} {{name}}() const {
+{%- if pf.min_version != 0 %}
+ if (data_->header_.version < {{pf.min_version}})
+ return {{kind|cpp_data_view_type}}{};
+{%- endif %}
+ return data_->{{name}};
+ }
+
{%- endif %}
{%- endfor %}
private:
- internal::{{struct.name}}_Data* data_;
- mojo::internal::SerializationContext* context_;
+ internal::{{struct.name}}_Data* data_ = nullptr;
+{%- if struct|requires_context_for_data_view %}
+ mojo::internal::SerializationContext* context_ = nullptr;
+{%- endif %}
};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl
index 2be92b30a30..95311dc124c 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl
@@ -1,59 +1,29 @@
-{{struct.name}}DataView::{{struct.name}}DataView(
- internal::{{struct.name}}_Data* data,
- mojo::internal::SerializationContext* context)
- : data_(data), context_(context) {
- DCHECK(data_);
-}
-
{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
-{%- set kind = pf.field.kind -%}
-{%- set name = pf.field.name -%}
-{%- if kind|is_struct_kind or kind|is_array_kind or kind|is_string_kind or
- kind|is_map_kind %}
-{#- Does nothing. They are already defined in the class declaration. #}
-
-{%- elif kind|is_enum_kind %}
-{{kind|get_qualified_name_for_kind}} {{struct.name}}DataView::{{name}}() const {
-{%- if pf.min_version != 0 %}
- if (data_->header_.version < {{pf.min_version}})
- return {{kind|get_qualified_name_for_kind}}{};
-{%- endif %}
- return static_cast<{{kind|get_qualified_name_for_kind}}>(data_->{{name}});
-}
+{%- set kind = pf.field.kind %}
+{%- set name = pf.field.name %}
-{%- elif kind|is_union_kind %}
-bool {{struct.name}}DataView::Read{{name|under_to_camel}}(
- {{kind|cpp_wrapper_type}}* value) {
+{%- if kind|is_union_kind %}
+inline void {{struct.name}}DataView::Get{{name|under_to_camel}}DataView(
+ {{kind|cpp_data_view_type}}* output) {
{%- if pf.min_version != 0 %}
- auto pointer = data_->header_.version >= {{pf.min_version}}
- ? &data_->{{name}} : nullptr;
+ auto pointer = data_->header_.version >= {{pf.min_version}}
+ ? &data_->{{name}} : nullptr;
{%- else %}
- auto pointer = &data_->{{name}};
+ auto pointer = &data_->{{name}};
{%- endif %}
- return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
- pointer, value, context_);
+ *output = {{kind|cpp_data_view_type}}(pointer, context_);
}
-{%- elif kind|is_any_handle_or_interface_kind %}
-{{kind|cpp_wrapper_type}} {{struct.name}}DataView::Take{{name|under_to_camel}}() {
- {{kind|cpp_wrapper_type}} result;
+{%- elif kind|is_object_kind %}
+inline void {{struct.name}}DataView::Get{{name|under_to_camel}}DataView(
+ {{kind|cpp_data_view_type}}* output) {
{%- if pf.min_version != 0 %}
- if (data_->header_.version < {{pf.min_version}})
- return result;
-{%- endif %}
- bool ret = mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
- &data_->{{name}}, &result, context_);
- DCHECK(ret);
- return result;
-}
-
-{%- else %}
-{{kind|cpp_wrapper_type}} {{struct.name}}DataView::{{name}}() const {
-{%- if pf.min_version != 0 %}
- if (data_->header_.version < {{pf.min_version}})
- return {{kind|cpp_wrapper_type}}{};
+ auto pointer = data_->header_.version >= {{pf.min_version}}
+ ? data_->{{name}}.Get() : nullptr;
+{%- else %}
+ auto pointer = data_->{{name}}.Get();
{%- endif %}
- return data_->{{name}};
+ *output = {{kind|cpp_data_view_type}}(pointer, context_);
}
{%- endif %}
{%- endfor %}
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
index 9fb10b0ef5b..156f7742c4c 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
@@ -2,24 +2,13 @@
class {{class_name}} {
public:
- static {{class_name}}* New(mojo::internal::Buffer* buf);
+ 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::ValidationContext* validation_context);
- void EncodePointers();
- void DecodePointers();
-
-{% from "enum_macros.tmpl" import enum_data_decl -%}
-{#--- Enums #}
-{%- for enum in struct.enums -%}
-{%- if enum|is_native_only_kind %}
- using {{enum.name}}_Data = mojo::internal::NativeEnum_Data;
-{%- else %}
- {{enum_data_decl(enum)|indent(2)}}
-{%- endif %}
-{%- endfor %}
-
mojo::internal::StructHeader header_;
{%- for packed_field in struct.packed.packed_fields %}
{%- set name = packed_field.field.name %}
@@ -49,7 +38,8 @@ class {{class_name}} {
{%- endif %}
private:
- {{class_name}}();
+ {{class_name}}() : header_({sizeof(*this), {{struct.versions[-1].version}}}) {
+ }
~{{class_name}}() = delete;
};
static_assert(sizeof({{class_name}}) == {{struct.versions[-1].num_bytes}},
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
index ffd32222a55..374b0976b18 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
@@ -2,11 +2,6 @@
{%- 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::ValidationContext* validation_context) {
@@ -73,44 +68,3 @@ bool {{class_name}}::Validate(
return true;
}
-void {{class_name}}::EncodePointers() {
- CHECK(header_.version == {{struct.versions[-1].version}});
-{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
-{%- if pf.field.kind|is_union_kind %}
- this->{{pf.field.name}}.EncodePointers();
-{%- elif pf.field.kind|is_object_kind %}
- mojo::internal::Encode(&this->{{pf.field.name}});
-{%- endif %}
-{%- endfor %}
-}
-
-void {{class_name}}::DecodePointers() {
- // NOTE: The memory backing |this| may be smaller than |sizeof(*this)|, if the
- // message comes from an older version.
-{#- Before decoding fields introduced at a certain version, we need to add
- a version check, which makes sure we skip further decoding if |this|
- is from an earlier version. |last_checked_version| records the last
- version that we have added such version check. #}
-{%- set last_checked_version = 0 %}
-{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
-{%- set name = pf.field.name %}
-{%- set kind = pf.field.kind %}
-{%- if kind|is_object_kind %}
-{%- if pf.min_version > last_checked_version %}
-{%- set last_checked_version = pf.min_version %}
- if (header_.version < {{pf.min_version}})
- return;
-{%- endif %}
-{%- if kind|is_union_kind %}
- this->{{name}}.DecodePointers();
-{%- elif kind|is_object_kind %}
- mojo::internal::Decode(&this->{{name}});
-{%- endif %}
-{%- endif %}
-{%- endfor %}
-}
-
-{{class_name}}::{{class_name}}() {
- header_.num_bytes = sizeof(*this);
- header_.version = {{struct.versions[-1].version}};
-}
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
index d44ffa86940..fbf60dd9541 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
@@ -60,40 +60,44 @@
buffer, context, input_may_be_temp=False) -%}
auto {{output}} =
{{struct|get_qualified_name_for_kind(internal=True)}}::New({{buffer}});
+ ALLOW_UNUSED_LOCAL({{output}});
{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
{%- set input_field = input_field_pattern|format(pf.field.name) %}
{%- set name = pf.field.name %}
{%- set kind = pf.field.kind %}
{%- set serializer_type = kind|unmapped_type_for_serializer %}
-{%- if kind|is_object_kind %}
+
+{%- if kind|is_object_kind or kind|is_any_handle_or_interface_kind %}
{%- set original_input_field = input_field_pattern|format(name) %}
{%- set input_field = "in_%s"|format(name) if input_may_be_temp
else original_input_field %}
{%- if input_may_be_temp %}
decltype({{original_input_field}}) in_{{name}} = {{original_input_field}};
{%- endif %}
+{%- endif %}
+{%- if kind|is_object_kind %}
{%- if kind|is_array_kind or kind|is_map_kind %}
+ typename decltype({{output}}->{{name}})::BaseType* {{name}}_ptr;
const mojo::internal::ContainerValidateParams {{name}}_validate_params(
{{kind|get_container_validate_params_ctor_args|indent(10)}});
mojo::internal::Serialize<{{serializer_type}}>(
- {{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr,
- &{{name}}_validate_params, {{context}});
+ {{input_field}}, {{buffer}}, &{{name}}_ptr, &{{name}}_validate_params,
+ {{context}});
+ {{output}}->{{name}}.Set({{name}}_ptr);
{%- elif kind|is_union_kind %}
auto {{name}}_ptr = &{{output}}->{{name}};
mojo::internal::Serialize<{{serializer_type}}>(
{{input_field}}, {{buffer}}, &{{name}}_ptr, true, {{context}});
{%- else %}
+ typename decltype({{output}}->{{name}})::BaseType* {{name}}_ptr;
mojo::internal::Serialize<{{serializer_type}}>(
- {{input_field}}, {{buffer}}, &{{output}}->{{name}}.ptr, {{context}});
+ {{input_field}}, {{buffer}}, &{{name}}_ptr, {{context}});
+ {{output}}->{{name}}.Set({{name}}_ptr);
{%- endif %}
{%- if not kind|is_nullable_kind %}
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
-{%- if kind|is_union_kind %}
{{output}}->{{name}}.is_null(),
-{%- else %}
- !{{output}}->{{name}}.ptr,
-{%- endif %}
mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
"null {{name}} in {{struct_display_name}}");
{%- endif %}
@@ -144,8 +148,11 @@
{%- if kind|is_object_kind or kind|is_enum_kind %}
if (!{{input}}.Read{{name|under_to_camel}}(&{{output_field}}))
{{success}} = false;
-{%- elif kind|is_any_handle_or_interface_kind %}
+{%- elif kind|is_any_handle_kind %}
{{output_field}} = {{input}}.Take{{name|under_to_camel}}();
+{%- elif kind|is_any_interface_kind %}
+ {{output_field}} =
+ {{input}}.Take{{name|under_to_camel}}<decltype({{output_field}})>();
{%- else %}
{{output_field}} = {{input}}.{{name}}();
{%- endif %}
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
index aede1a72a9a..835178bedae 100644
--- 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
@@ -1,37 +1,13 @@
{%- import "struct_macros.tmpl" as struct_macros %}
-{%- set mojom_type = struct|get_qualified_name_for_kind %}
+{%- set data_view = struct|get_qualified_name_for_kind ~ "DataView" %}
{%- set data_type = struct|get_qualified_name_for_kind(internal=True) %}
-template <>
-struct StructTraits<{{mojom_type}}, {{mojom_type}}Ptr> {
- static bool IsNull(const {{mojom_type}}Ptr& input) { return !input; }
- static void SetToNull({{mojom_type}}Ptr* output) { output->reset(); }
-
-{%- for field in struct.fields %}
-{%- set return_ref = field.kind|is_object_kind or
- field.kind|is_any_handle_or_interface_kind %}
-{%- if return_ref %}
- static decltype({{mojom_type}}::{{field.name}})& {{field.name}}(
- {{mojom_type}}Ptr& input) {
- return input->{{field.name}};
- }
-{%- else %}
- static decltype({{mojom_type}}::{{field.name}}) {{field.name}}(
- const {{mojom_type}}Ptr& input) {
- return input->{{field.name}};
- }
-{%- endif %}
-{%- endfor %}
-
- static bool Read({{mojom_type}}DataView input, {{mojom_type}}Ptr* output);
-};
-
namespace internal {
template <typename MaybeConstUserType>
-struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType> {
+struct Serializer<{{data_view}}, MaybeConstUserType> {
using UserType = typename std::remove_const<MaybeConstUserType>::type;
- using Traits = StructTraits<{{mojom_type}}, UserType>;
+ using Traits = StructTraits<{{data_view}}, UserType>;
static size_t PrepareToSerialize(MaybeConstUserType& input,
SerializationContext* context) {
@@ -61,7 +37,7 @@ struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType> {
{{struct_macros.serialize(
struct, struct.name ~ " struct",
"CallWithContext(Traits::%s, input, custom_context)", "result",
- "buffer", "context", True)|indent(4)}}
+ "buffer", "context", True)|indent(2)}}
*output = result;
CustomContextHelper<Traits>::TearDown(input, custom_context);
@@ -73,7 +49,7 @@ struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType> {
if (!input)
return CallSetToNullIfExists<Traits>(output);
- {{mojom_type}}DataView data_view(input, context);
+ {{data_view}} data_view(input, context);
return Traits::Read(data_view, output);
}
};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_declaration.tmpl
new file mode 100644
index 00000000000..1b7cf8954ba
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_declaration.tmpl
@@ -0,0 +1,32 @@
+{%- set mojom_type = struct|get_qualified_name_for_kind %}
+
+template <>
+struct {{export_attribute}} StructTraits<{{mojom_type}}::DataView,
+ {{mojom_type}}Ptr> {
+ static bool IsNull(const {{mojom_type}}Ptr& input) { return !input; }
+ static void SetToNull({{mojom_type}}Ptr* output) { output->reset(); }
+
+{%- for field in struct.fields %}
+{%- set return_ref = field.kind|is_object_kind or
+ field.kind|is_any_handle_or_interface_kind %}
+{# We want the field accessor to be const whenever possible to allow
+ structs to be used as map keys.
+ TODO(tibell): Make this check more precise to deal with e.g.
+ custom types which don't contain handles but require non-const
+ reference for serialization. #}
+{%- set maybe_const = "" if field.kind|contains_handles_or_interfaces else "const" %}
+{%- if return_ref %}
+ static {{maybe_const}} decltype({{mojom_type}}::{{field.name}})& {{field.name}}(
+ {{maybe_const}} {{mojom_type}}Ptr& input) {
+ return input->{{field.name}};
+ }
+{%- else %}
+ static decltype({{mojom_type}}::{{field.name}}) {{field.name}}(
+ const {{mojom_type}}Ptr& input) {
+ return input->{{field.name}};
+ }
+{%- endif %}
+{%- endfor %}
+
+ static bool Read({{mojom_type}}::DataView input, {{mojom_type}}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_traits_definition.tmpl
index 7421abcd787..f84337f5bf4 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_definition.tmpl
@@ -2,8 +2,8 @@
{%- set mojom_type = struct|get_qualified_name_for_kind %}
// static
-bool StructTraits<{{mojom_type}}, {{mojom_type}}Ptr>::Read(
- {{mojom_type}}DataView input,
+bool StructTraits<{{mojom_type}}::DataView, {{mojom_type}}Ptr>::Read(
+ {{mojom_type}}::DataView input,
{{mojom_type}}Ptr* output) {
bool success = true;
{{mojom_type}}Ptr result({{mojom_type}}::New());
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl
new file mode 100644
index 00000000000..5973ba294b2
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl
@@ -0,0 +1,92 @@
+class {{union.name}}DataView {
+ public:
+ using Tag = internal::{{union.name}}_Data::{{union.name}}_Tag;
+
+ {{union.name}}DataView() {}
+
+ {{union.name}}DataView(
+ internal::{{union.name}}_Data* data,
+ mojo::internal::SerializationContext* context)
+{%- if union|requires_context_for_data_view %}
+ : data_(data), context_(context) {}
+{%- else %}
+ : data_(data) {}
+{%- endif %}
+
+ bool is_null() const {
+ // For inlined unions, |data_| is always non-null. In that case we need to
+ // check |data_->is_null()|.
+ return !data_ || data_->is_null();
+ }
+
+ Tag tag() const { return data_->tag; }
+
+{%- for field in union.fields %}
+{%- set kind = field.kind %}
+{%- set name = field.name %}
+ bool is_{{name}}() const { return data_->tag == Tag::{{name|upper}}; }
+
+{%- if kind|is_object_kind %}
+ inline void Get{{name|under_to_camel}}DataView(
+ {{kind|cpp_data_view_type}}* output);
+
+ template <typename UserType>
+ WARN_UNUSED_RESULT bool Read{{name|under_to_camel}}(UserType* output) {
+ DCHECK(is_{{name}}());
+ return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
+ data_->data.f_{{name}}.Get(), output, context_);
+ }
+
+{%- elif kind|is_enum_kind %}
+ template <typename UserType>
+ WARN_UNUSED_RESULT bool Read{{name|under_to_camel}}(UserType* output) const {
+ DCHECK(is_{{name}}());
+ return mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
+ data_->data.f_{{name}}, output);
+ }
+
+ {{kind|cpp_data_view_type}} {{name}}() const {
+ DCHECK(is_{{name}}());
+ return static_cast<{{kind|cpp_data_view_type}}>(
+ data_->data.f_{{name}});
+ }
+
+{%- elif kind|is_any_handle_kind %}
+ {{kind|cpp_data_view_type}} Take{{name|under_to_camel}}() {
+ DCHECK(is_{{name}}());
+ {{kind|cpp_data_view_type}} result;
+ bool ret =
+ mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
+ &data_->data.f_{{name}}, &result, context_);
+ DCHECK(ret);
+ return result;
+ }
+
+{%- elif kind|is_any_interface_kind %}
+ template <typename UserType>
+ UserType Take{{name|under_to_camel}}() {
+ DCHECK(is_{{name}}());
+ UserType result;
+ bool ret =
+ mojo::internal::Deserialize<{{kind|unmapped_type_for_serializer}}>(
+ &data_->data.f_{{name}}, &result, context_);
+ DCHECK(ret);
+ return result;
+ }
+
+{%- else %}
+ {{kind|cpp_data_view_type}} {{name}}() const {
+ DCHECK(is_{{name}}());
+ return data_->data.f_{{name}};
+ }
+
+{%- endif %}
+{%- endfor %}
+
+ private:
+ internal::{{union.name}}_Data* data_ = nullptr;
+{%- if union|requires_context_for_data_view %}
+ mojo::internal::SerializationContext* context_ = nullptr;
+{%- endif %}
+};
+
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_definition.tmpl
new file mode 100644
index 00000000000..6da9280a732
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_definition.tmpl
@@ -0,0 +1,12 @@
+{%- for field in union.fields %}
+{%- set kind = field.kind %}
+{%- set name = field.name %}
+
+{%- if kind|is_object_kind %}
+inline void {{union.name}}DataView::Get{{name|under_to_camel}}DataView(
+ {{kind|cpp_data_view_type}}* output) {
+ DCHECK(is_{{name}}());
+ *output = {{kind|cpp_data_view_type}}(data_->data.f_{{name}}.Get(), context_);
+}
+{%- endif %}
+{%- endfor %}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
index d61b60c1308..005ba76b611 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -6,20 +6,27 @@ class {{class_name}} {
public:
// Used to identify Mojom Union Data Classes.
typedef void MojomUnionDataType;
- static {{class_name}}* New(mojo::internal::Buffer* buf);
- {{class_name}}();
- // Do nothing in the destructor since it won't be called.
+
+ {{class_name}}() {}
+ // Do nothing in the destructor since it won't be called when it is a
+ // non-inlined union.
~{{class_name}}() {}
+ 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::ValidationContext* validation_context,
bool inlined);
- bool is_null() const {
- return size == 0;
- }
+ bool is_null() const { return size == 0; }
- void set_null();
+ void set_null() {
+ size = 0U;
+ tag = static_cast<{{enum_name}}>(0);
+ data.unknown = 0U;
+ }
enum class {{enum_name}} : uint32_t {
{% for field in union.fields %}
@@ -44,9 +51,6 @@ class {{class_name}} {
uint32_t size;
{{enum_name}} tag;
Union_ data;
-
- void EncodePointers();
- void DecodePointers();
};
static_assert(sizeof({{class_name}}) == mojo::internal::kUnionDataSize,
"Bad sizeof({{class_name}})");
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
index 7f4603691e5..af5ea9f8a83 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
@@ -3,24 +3,31 @@
{%- set enum_name = union.name ~ "_Tag" -%}
// 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::ValidationContext* validation_context,
bool inlined) {
- if (!data)
+ if (!data) {
+ DCHECK(!inlined);
return true;
+ }
+
+ // If it is inlined, the alignment is already enforced by its enclosing
+ // object. We don't have to validate that.
+ DCHECK(!inlined || mojo::internal::IsAligned(data));
- if (!ValidateUnionHeaderAndClaimMemory(data, inlined, validation_context))
+ if (!inlined &&
+ !mojo::internal::ValidateNonInlinedUnionHeaderAndClaimMemory(
+ data, validation_context)) {
return false;
+ }
const {{class_name}}* object = static_cast<const {{class_name}}*>(data);
ALLOW_UNUSED_LOCAL(object);
+ if (inlined && object->is_null())
+ return true;
+
switch (object->tag) {
{% for field in union.fields %}
case {{enum_name}}::{{field.name|upper}}: {
@@ -38,38 +45,3 @@ bool {{class_name}}::Validate(
}
}
}
-
-void {{class_name}}::set_null() {
- size = 0U;
- tag = static_cast<{{enum_name}}>(0);
- data.unknown = 0U;
-}
-
-{{class_name}}::{{class_name}}() {
-}
-
-void {{class_name}}::EncodePointers() {
- switch (tag) {
-{%- for field in union.fields %}
- case {{enum_name}}::{{field.name|upper}}: {
-{%- if field.kind|is_object_kind %}
- mojo::internal::Encode(&data.f_{{field.name}});
-{%- endif %}
- return;
- }
-{%- endfor %}
- }
-}
-
-void {{class_name}}::DecodePointers() {
- switch (tag) {
-{%- for field in union.fields %}
- case {{enum_name}}::{{field.name|upper}}: {
-{%- if field.kind|is_object_kind %}
- mojo::internal::Decode(&data.f_{{field.name}});
-{%- endif %}
- return;
- }
-{%- endfor %}
- }
-}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
index bab90452272..9a1aa8e2faa 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
@@ -1,37 +1,141 @@
-{%- set mojom_type = union|get_qualified_name_for_kind %}
+{%- set data_view = union|get_qualified_name_for_kind ~ "DataView" %}
{%- set data_type = union|get_qualified_name_for_kind(internal=True) %}
namespace internal {
-template <typename MojomType>
-struct UnionSerializerImpl;
+template <typename MaybeConstUserType>
+struct Serializer<{{data_view}}, MaybeConstUserType> {
+ using UserType = typename std::remove_const<MaybeConstUserType>::type;
+ using Traits = UnionTraits<{{data_view}}, UserType>;
-template <>
-struct UnionSerializerImpl<{{mojom_type}}Ptr> {
- static size_t PrepareToSerialize({{mojom_type}}Ptr& input,
+ static size_t PrepareToSerialize(MaybeConstUserType& input,
bool inlined,
- SerializationContext* context);
+ SerializationContext* context) {
+ size_t size = inlined ? 0 : sizeof({{data_type}});
+
+ if (CallIsNullIfExists<Traits>(input))
+ return size;
+
+ void* custom_context = CustomContextHelper<Traits>::SetUp(input, context);
+ ALLOW_UNUSED_LOCAL(custom_context);
- static void Serialize({{mojom_type}}Ptr& input,
+ switch (CallWithContext(Traits::GetTag, input, custom_context)) {
+{%- for field in union.fields %}
+{%- set name = field.name %}
+ case {{data_view}}::Tag::{{name|upper}}: {
+{%- if field.kind|is_object_kind %}
+{%- set kind = field.kind %}
+{%- set serializer_type = kind|unmapped_type_for_serializer %}
+ decltype(CallWithContext(Traits::{{name}}, input, custom_context))
+ in_{{name}} = CallWithContext(Traits::{{name}}, input,
+ custom_context);
+{%- if kind|is_union_kind %}
+ size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
+ in_{{name}}, false, context);
+{%- else %}
+ size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
+ in_{{name}}, context);
+{%- endif %}
+{%- endif %}
+ break;
+ }
+{%- endfor %}
+ }
+ return size;
+ }
+
+ static void Serialize(MaybeConstUserType& input,
Buffer* buffer,
{{data_type}}** output,
bool inlined,
- SerializationContext* context);
+ SerializationContext* context) {
+ if (CallIsNullIfExists<Traits>(input)) {
+ if (inlined)
+ (*output)->set_null();
+ else
+ *output = nullptr;
+ return;
+ }
- static bool Deserialize({{data_type}}* input,
- {{mojom_type}}Ptr* output,
- SerializationContext* context);
-};
+ void* custom_context = CustomContextHelper<Traits>::GetNext(context);
-template <typename MaybeConstUserType>
-struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType>
- : public UnionSerializerImpl<{{mojom_type}}Ptr> {
- using UserType = typename std::remove_const<MaybeConstUserType>::type;
+ if (!inlined)
+ *output = {{data_type}}::New(buffer);
+
+ {{data_type}}* result = *output;
+ ALLOW_UNUSED_LOCAL(result);
+ // TODO(azani): Handle unknown and objects.
+ // Set the not-null flag.
+ result->size = kUnionDataSize;
+ result->tag = CallWithContext(Traits::GetTag, input, custom_context);
+ switch (result->tag) {
+{%- for field in union.fields %}
+{%- set name = field.name %}
+{%- set kind = field.kind %}
+{%- set serializer_type = kind|unmapped_type_for_serializer %}
+ case {{data_view}}::Tag::{{field.name|upper}}: {
+ decltype(CallWithContext(Traits::{{name}}, input, custom_context))
+ in_{{name}} = CallWithContext(Traits::{{name}}, input,
+ custom_context);
+{%- if kind|is_object_kind %}
+ typename decltype(result->data.f_{{name}})::BaseType* ptr;
+{%- if kind|is_union_kind %}
+ mojo::internal::Serialize<{{serializer_type}}>(
+ in_{{name}}, buffer, &ptr, false, context);
+{%- elif kind|is_array_kind or kind|is_map_kind %}
+ const ContainerValidateParams {{name}}_validate_params(
+ {{kind|get_container_validate_params_ctor_args|indent(16)}});
+ mojo::internal::Serialize<{{serializer_type}}>(
+ in_{{name}}, buffer, &ptr, &{{name}}_validate_params, context);
+{%- else %}
+ mojo::internal::Serialize<{{serializer_type}}>(
+ in_{{name}}, buffer, &ptr, context);
+{%- endif %}
+ result->data.f_{{name}}.Set(ptr);
+{%- if not kind|is_nullable_kind %}
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ !ptr, mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
+ "null {{name}} in {{union.name}} union");
+{%- endif %}
+
+{%- elif kind|is_any_handle_or_interface_kind %}
+ mojo::internal::Serialize<{{serializer_type}}>(
+ in_{{name}}, &result->data.f_{{name}}, context);
+{%- if not kind|is_nullable_kind %}
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ !mojo::internal::IsHandleOrInterfaceValid(result->data.f_{{name}}),
+{%- if kind|is_associated_kind %}
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID,
+{%- else %}
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
+{%- endif %}
+ "invalid {{name}} in {{union.name}} union");
+{%- endif %}
+
+{%- elif kind|is_enum_kind %}
+ mojo::internal::Serialize<{{serializer_type}}>(
+ in_{{name}}, &result->data.f_{{name}});
+
+{%- else %}
+ result->data.f_{{name}} = in_{{name}};
+{%- endif %}
+ break;
+ }
+{%- endfor %}
+ }
+
+ CustomContextHelper<Traits>::TearDown(input, custom_context);
+ }
+
+ static bool Deserialize({{data_type}}* input,
+ UserType* output,
+ SerializationContext* context) {
+ if (!input || input->is_null())
+ return CallSetToNullIfExists<Traits>(output);
- static_assert(std::is_same<MaybeConstUserType, UserType>::value,
- "Only support serialization of non-const Unions.");
- static_assert(std::is_same<UserType, {{mojom_type}}Ptr>::value,
- "Custom mapping of mojom union is not supported.");
+ {{data_view}} data_view(input, context);
+ return Traits::Read(data_view, output);
+ }
};
} // namespace internal
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
deleted file mode 100644
index c7f559d9775..00000000000
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
+++ /dev/null
@@ -1,166 +0,0 @@
-{%- set mojom_type = union|get_qualified_name_for_kind %}
-{%- set data_type = union|get_qualified_name_for_kind(internal=True) %}
-
-namespace internal {
-
-// static
-size_t UnionSerializerImpl<{{mojom_type}}Ptr>::PrepareToSerialize(
- {{mojom_type}}Ptr& input,
- bool inlined,
- SerializationContext* context) {
- size_t size = inlined ? 0 : sizeof({{data_type}});
-
- if (!input)
- return size;
-
- UnionAccessor<{{mojom_type}}> input_acc(input.get());
- switch (input->which()) {
-{% for field in union.fields %}
-{% if field.kind|is_object_kind %}
-{%- set serializer_type = field.kind|unmapped_type_for_serializer %}
- case {{mojom_type}}::Tag::{{field.name|upper}}:
-{% if field.kind|is_union_kind %}
- size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
- *(input_acc.data()->{{field.name}}), false, context);
-{% else %}
- size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
- *(input_acc.data()->{{field.name}}), context);
-{% endif %}
- break;
-{%- endif %}
-{%- endfor %}
- default:
- break;
- }
- return size;
-}
-
-// static
-void UnionSerializerImpl<{{mojom_type}}Ptr>::Serialize(
- {{mojom_type}}Ptr& input,
- Buffer* buf,
- {{data_type}}** output,
- bool inlined,
- SerializationContext* context) {
- {{data_type}}* result = *output;
- if (input) {
- if (!inlined)
- result = {{data_type}}::New(buf);
- UnionAccessor<{{mojom_type}}> input_acc(input.get());
- // TODO(azani): Handle unknown and objects.
- // Set the not-null flag.
- result->size = 16;
- result->tag = input->which();
- switch (input->which()) {
-{%- for field in union.fields %}
- case {{mojom_type}}::Tag::{{field.name|upper}}: {
-{%- set serializer_type = field.kind|unmapped_type_for_serializer %}
-{%- if field.kind|is_object_kind %}
-{%- if field.kind|is_union_kind %}
- mojo::internal::Serialize<{{serializer_type}}>(
- *(input_acc.data()->{{field.name}}), buf,
- &result->data.f_{{field.name}}.ptr, false, context);
-{%- elif field.kind|is_array_kind or field.kind|is_map_kind %}
- const ContainerValidateParams {{field.name}}_validate_params(
- {{field.kind|get_container_validate_params_ctor_args|indent(16)}});
- mojo::internal::Serialize<{{serializer_type}}>(
- *(input_acc.data()->{{field.name}}), buf,
- &result->data.f_{{field.name}}.ptr, &{{field.name}}_validate_params,
- context);
-{%- else %}
- mojo::internal::Serialize<{{serializer_type}}>(
- *(input_acc.data()->{{field.name}}), buf,
- &result->data.f_{{field.name}}.ptr, context);
-{%- endif %}
-{%- if not field.kind|is_nullable_kind %}
- MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !result->data.f_{{field.name}}.ptr,
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
- "null {{field.name}} in {{union.name}} union");
-{%- endif %}
-
-{%- elif field.kind|is_any_handle_or_interface_kind %}
- mojo::internal::Serialize<{{serializer_type}}>(
- *input_acc.data()->{{field.name}}, &result->data.f_{{field.name}},
- context);
-{%- if not field.kind|is_nullable_kind %}
- MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !mojo::internal::IsHandleOrInterfaceValid(result->data.f_{{field.name}}),
-{%- if field.kind|is_associated_kind %}
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID,
-{%- else %}
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
-{%- endif %}
- "invalid {{field.name}} in {{union.name}} union");
-{%- endif %}
-
-{%- elif field.kind|is_enum_kind %}
- mojo::internal::Serialize<{{serializer_type}}>(
- input_acc.data()->{{field.name}}, &result->data.f_{{field.name}});
-
-{%- else %}
- result->data.f_{{field.name}} = input_acc.data()->{{field.name}};
-{%- endif %}
- break;
- }
-{%- endfor %}
- }
- } else if (inlined) {
- result->set_null();
- } else {
- result = nullptr;
- }
- *output = result;
-}
-
-// static
-bool UnionSerializerImpl<{{mojom_type}}Ptr>::Deserialize(
- {{data_type}}* input,
- {{mojom_type}}Ptr* output,
- SerializationContext* context) {
- bool success = true;
- if (input && !input->is_null()) {
- {{mojom_type}}Ptr result({{mojom_type}}::New());
- UnionAccessor<{{mojom_type}}> result_acc(result.get());
- switch (input->tag) {
-{%- for field in union.fields %}
- case {{mojom_type}}::Tag::{{field.name|upper}}: {
-{%- set serializer_type = field.kind|unmapped_type_for_serializer %}
-{%- if field.kind|is_object_kind %}
- result_acc.SwitchActive({{mojom_type}}::Tag::{{field.name|upper}});
- if (!mojo::internal::Deserialize<{{serializer_type}}>(
- input->data.f_{{field.name}}.ptr,
- result_acc.data()->{{field.name}}, context))
- success = false;
-
-{%- elif field.kind|is_any_handle_or_interface_kind %}
- typename std::remove_reference<
- decltype(result->get_{{field.name}}())>::type result_{{field.name}};
- bool ret = mojo::internal::Deserialize<{{serializer_type}}>(
- &input->data.f_{{field.name}}, &result_{{field.name}}, context);
- DCHECK(ret);
- result->set_{{field.name}}(std::move(result_{{field.name}}));
-
-{%- elif field.kind|is_enum_kind %}
- decltype(result->get_{{field.name}}()) result_{{field.name}};
- if (!mojo::internal::Deserialize<{{serializer_type}}>(
- input->data.f_{{field.name}}, &result_{{field.name}}))
- success = false;
- else
- result->set_{{field.name}}(result_{{field.name}});
-
-{%- else %}
- result->set_{{field.name}}(input->data.f_{{field.name}});
-{%- endif %}
- break;
- }
-{%- endfor %}
- }
- *output = std::move(result);
- } else {
- output->reset();
- }
- return success;
-}
-
-} // namespace internal
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_declaration.tmpl
new file mode 100644
index 00000000000..4933e57871b
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_declaration.tmpl
@@ -0,0 +1,24 @@
+{%- set mojom_type = union|get_qualified_name_for_kind %}
+
+template <>
+struct {{export_attribute}} UnionTraits<{{mojom_type}}::DataView,
+ {{mojom_type}}Ptr> {
+ static bool IsNull(const {{mojom_type}}Ptr& input) { return !input; }
+ static void SetToNull({{mojom_type}}Ptr* output) { output->reset(); }
+
+ static {{mojom_type}}::Tag GetTag(const {{mojom_type}}Ptr& input) {
+ return input->which();
+ }
+
+{%- for field in union.fields %}
+{%- set maybe_const_in = "" if field.kind|contains_handles_or_interfaces else "const" %}
+{%- set maybe_const_out = "" if field.kind|contains_handles_or_interfaces or not field.kind|is_reference_kind else "const" %}
+{# We want the field accessor to be const whenever possible to allow
+ structs to be used as map keys. #}
+ static {{maybe_const_out}} {{field.kind|cpp_union_trait_getter_return_type}} {{field.name}}({{maybe_const_in}} {{mojom_type}}Ptr& input) {
+ return input->get_{{field.name}}();
+ }
+{%- endfor %}
+
+ static bool Read({{mojom_type}}::DataView input, {{mojom_type}}Ptr* output);
+};
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_definition.tmpl
new file mode 100644
index 00000000000..cde3f956693
--- /dev/null
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_definition.tmpl
@@ -0,0 +1,47 @@
+{%- set mojom_type = union|get_qualified_name_for_kind %}
+
+// static
+bool UnionTraits<{{mojom_type}}::DataView, {{mojom_type}}Ptr>::Read(
+ {{mojom_type}}::DataView input,
+ {{mojom_type}}Ptr* output) {
+ *output = {{mojom_type}}::New();
+ {{mojom_type}}Ptr& result = *output;
+
+ internal::UnionAccessor<{{mojom_type}}> result_acc(result.get());
+ switch (input.tag()) {
+{%- for field in union.fields %}
+ case {{mojom_type}}::Tag::{{field.name|upper}}: {
+{%- set name = field.name %}
+{%- set kind = field.kind %}
+{%- set serializer_type = kind|unmapped_type_for_serializer %}
+{%- if kind|is_object_kind %}
+ result_acc.SwitchActive({{mojom_type}}::Tag::{{name|upper}});
+ if (!input.Read{{name|under_to_camel}}(result_acc.data()->{{name}}))
+ return false;
+
+{%- elif kind|is_any_handle_kind %}
+ auto result_{{name}} = input.Take{{name|under_to_camel}}();
+ result->set_{{name}}(std::move(result_{{name}}));
+
+{%- elif kind|is_any_interface_kind %}
+ auto result_{{name}} =
+ input.Take{{name|under_to_camel}}<typename std::remove_reference<decltype(result->get_{{name}}())>::type>();
+ result->set_{{name}}(std::move(result_{{name}}));
+
+{%- elif kind|is_enum_kind %}
+ decltype(result->get_{{name}}()) result_{{name}};
+ if (!input.Read{{name|under_to_camel}}(&result_{{name}}))
+ return false;
+ result->set_{{name}}(result_{{name}});
+
+{%- else %}
+ result->set_{{name}}(input.{{name}}());
+{%- endif %}
+ break;
+ }
+{%- endfor %}
+ default:
+ return false;
+ }
+ return true;
+}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl
index 76a3637e33b..a50a585c09a 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl
@@ -20,18 +20,11 @@
}
{%- endif %}
{%- endif %}
-{%- if kind|is_array_kind or kind|is_string_kind %}
+{%- if kind|is_array_kind or kind|is_string_kind or kind|is_map_kind %}
const mojo::internal::ContainerValidateParams {{name}}_validate_params(
{{kind|get_container_validate_params_ctor_args|indent(6)}});
- if (!mojo::internal::ValidateArray({{field_expr}}, validation_context,
- &{{name}}_validate_params)) {
- return false;
- }
-{%- elif kind|is_map_kind %}
- const mojo::internal::ContainerValidateParams {{name}}_validate_params(
- {{kind|get_container_validate_params_ctor_args|indent(6)}});
- if (!mojo::internal::ValidateMap({{field_expr}}, validation_context,
- &{{name}}_validate_params)) {
+ if (!mojo::internal::ValidateContainer({{field_expr}}, validation_context,
+ &{{name}}_validate_params)) {
return false;
}
{%- elif kind|is_struct_kind %}
@@ -73,7 +66,7 @@
{#- Validates the specified field, which is supposed to be an enum.
This macro is expanded by the Validate() method. #}
{%- macro validate_enum(field, field_expr) %}
- if (!{{field.kind|get_qualified_name_for_kind(internal=True)}}
+ if (!{{field.kind|get_qualified_name_for_kind(internal=True,flatten_nested_kind=True)}}
::Validate({{field_expr}}, validation_context))
return false;
{%- endmacro %}
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
index 1c4d9f71b89..4c5ed38c998 100644
--- 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
@@ -1,17 +1,11 @@
-{% from "enum_macros.tmpl" import enum_decl -%}
-
-class {{struct.name}} {
+class {{export_attribute}} {{struct.name}} {
public:
using DataView = {{struct.name}}DataView;
using Data_ = internal::{{struct.name}}_Data;
{#--- Enums #}
{%- for enum in struct.enums -%}
-{%- if enum|is_native_only_kind %}
- using {{enum.name}} = mojo::NativeEnum;
-{%- else %}
- {{enum_decl(enum)|indent(2)}}
-{%- endif %}
+ using {{enum.name}} = {{enum|get_name_for_kind(flatten_nested_kind=True)}};
{%- endfor %}
{#--- Constants #}
@@ -52,21 +46,25 @@ class {{struct.name}} {
T, {{struct.name}}>::value>::type* = nullptr>
bool Equals(const T& other) const;
+{%- if struct|is_hashable %}
+ size_t Hash(size_t seed) const;
+{%- endif %}
+
{%- set serialization_result_type = "mojo::WTFArray<uint8_t>"
if for_blink else "mojo::Array<uint8_t>" %}
template <typename UserType>
static {{serialization_result_type}} Serialize(UserType* input) {
return mojo::internal::StructSerializeImpl<
- {{struct.name}}Ptr, {{serialization_result_type}}>(input);
+ {{struct.name}}::DataView, {{serialization_result_type}}>(input);
}
template <typename UserType>
- static bool Deserialize({{serialization_result_type}} input,
+ static bool Deserialize(const {{serialization_result_type}}& input,
UserType* output) {
return mojo::internal::StructDeserializeImpl<
- {{struct.name}}Ptr, {{serialization_result_type}}>(
- std::move(input), output);
+ {{struct.name}}::DataView, {{serialization_result_type}}>(
+ input, output);
}
{#--- Struct members #}
@@ -75,5 +73,10 @@ class {{struct.name}} {
{%- set name = field.name %}
{{type}} {{name}};
{%- endfor %}
+
+{%- if struct|contains_move_only_members %}
+ private:
+ DISALLOW_COPY_AND_ASSIGN({{struct.name}});
+{%- endif %}
};
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
index 0bb1cda14b5..e6d04268520 100644
--- 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
@@ -13,3 +13,16 @@
{{struct.name}}::~{{struct.name}}() {
}
+
+{%- if struct|is_hashable %}
+size_t {{struct.name}}::Hash(size_t seed) const {
+{%- for field in struct.fields %}
+{%- if for_blink %}
+ seed = mojo::internal::WTFHash(seed, this->{{field.name}});
+{%- else %}
+ seed = mojo::internal::Hash(seed, this->{{field.name}});
+{%- endif %}
+{%- endfor %}
+ return seed;
+}
+{%- endif %}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
index f62bc72f51a..8b7cf9e6b1d 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
@@ -1,5 +1,6 @@
-class {{union.name}} {
+class {{export_attribute}} {{union.name}} {
public:
+ using DataView = {{union.name}}DataView;
using Data_ = internal::{{union.name}}_Data;
using Tag = Data_::{{union.name}}_Tag;
@@ -32,13 +33,27 @@ class {{union.name}} {
T, {{union.name}}>::value>::type* = nullptr>
bool Equals(const T& other) const;
+{%- if union|is_hashable %}
+ size_t Hash(size_t seed) const;
+{%- endif %}
+
Tag which() const {
return tag_;
}
{% for field in union.fields %}
- bool is_{{field.name}}() const;
- {{field.kind|cpp_union_getter_return_type}} get_{{field.name}}() const;
+ bool is_{{field.name}}() const { return tag_ == Tag::{{field.name|upper}}; }
+
+ {{field.kind|cpp_union_getter_return_type}} get_{{field.name}}() const {
+ DCHECK(tag_ == Tag::{{field.name|upper}});
+{%- if field.kind|is_object_kind or
+ field.kind|is_any_handle_or_interface_kind %}
+ return *(data_.{{field.name}});
+{%- else %}
+ return data_.{{field.name}};
+{%- endif %}
+ }
+
void set_{{field.name}}({{field.kind|cpp_wrapper_param_type}} {{field.name}});
{%- endfor %}
diff --git a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
index 85cc4e61449..80527a21ce7 100644
--- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
@@ -16,20 +16,6 @@
}
{% for field in union.fields %}
-bool {{union.name}}::is_{{field.name}}() const {
- return tag_ == Tag::{{field.name|upper}};
-}
-
-{{field.kind|cpp_union_getter_return_type}} {{union.name}}::get_{{field.name}}() const {
- DCHECK(tag_ == Tag::{{field.name|upper}});
-{% if field.kind|is_object_kind or
- field.kind|is_any_handle_or_interface_kind %}
- return *(data_.{{field.name}});
-{%- else %}
- return data_.{{field.name}};
-{%- endif %}
-}
-
void {{union.name}}::set_{{field.name}}({{field.kind|cpp_wrapper_param_type}} {{field.name}}) {
SwitchActive(Tag::{{field.name|upper}});
{% if field.kind|is_string_kind %}
@@ -79,3 +65,23 @@ void {{union.name}}::DestroyActive() {
{%- endfor %}
}
}
+
+{%- if union|is_hashable %}
+size_t {{union.name}}::Hash(size_t seed) const {
+ seed = mojo::internal::HashCombine(seed, static_cast<uint32_t>(tag_));
+ switch (tag_) {
+{% for field in union.fields %}
+ case Tag::{{field.name|upper}}:
+{%- if for_blink %}
+ return mojo::internal::WTFHash(seed, data_.{{field.name}});
+{%- else %}
+ return mojo::internal::Hash(seed, data_.{{field.name}});
+{%- endif %}
+{%- endfor %}
+ default:
+ NOTREACHED();
+ return seed;
+ }
+}
+
+{%- endif %}
diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl
index 5cf9a6812df..aa3f6f6d9d2 100644
--- a/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl
@@ -168,7 +168,7 @@ if ({{variable}} != null) {
{% for field in struct.fields %}
{% if field.default %}
{{field|name}} = {{field|default_value}};
-{% elif field.kind|is_any_handle_kind and not field.kind|is_interface_request_kind %}
+{% elif field.kind|is_any_handle_kind %}
{{field|name}} = org.chromium.mojo.system.InvalidHandle.INSTANCE;
{% endif %}
{% endfor %}
@@ -182,6 +182,19 @@ if ({{variable}} != null) {
return decode(new org.chromium.mojo.bindings.Decoder(message));
}
+ /**
+ * Similar to the method above, but deserializes from a |ByteBuffer| instance.
+ *
+ * @throws org.chromium.mojo.bindings.DeserializationException on deserialization failure.
+ */
+ public static {{struct|name}} deserialize(java.nio.ByteBuffer data) {
+ if (data == null)
+ return null;
+
+ return deserialize(new org.chromium.mojo.bindings.Message(
+ data, new java.util.ArrayList<org.chromium.mojo.system.Handle>()));
+ }
+
@SuppressWarnings("unchecked")
public static {{struct|name}} decode(org.chromium.mojo.bindings.Decoder decoder0) {
if (decoder0 == null) {
diff --git a/chromium/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl
index 527e15fbfcf..c7dcbbc7cbe 100644
--- a/chromium/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl
@@ -91,11 +91,11 @@ try {
}
switch(header.getType()) {
{% if with_response %}
- case org.chromium.mojo.bindings.InterfaceControlMessagesConstants.RUN_MESSAGE_ID:
+ case org.chromium.mojo.bindings.interfacecontrol.InterfaceControlMessagesConstants.RUN_MESSAGE_ID:
return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRun(
getCore(), {{interface|name}}_Internal.MANAGER, messageWithHeader, receiver);
{% else %}
- case org.chromium.mojo.bindings.InterfaceControlMessagesConstants.RUN_OR_CLOSE_PIPE_MESSAGE_ID:
+ case org.chromium.mojo.bindings.interfacecontrol.InterfaceControlMessagesConstants.RUN_OR_CLOSE_PIPE_MESSAGE_ID:
return org.chromium.mojo.bindings.InterfaceControlMessagesHelper.handleRunOrClosePipe(
{{interface|name}}_Internal.MANAGER, messageWithHeader);
{% endif %}
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
index 4ae0a9b5cdb..019b1b63836 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl
@@ -1,13 +1,33 @@
{%- macro enum_def(enum_name, enum) -%}
{{enum_name}} = {};
-{%- set prev_enum = 0 %}
-{%- for field in enum.fields %}
-{%- if field.value %}
+{%- set prev_enum = 0 %}
+{%- for field in enum.fields %}
+{%- if field.value %}
{{enum_name}}.{{field.name}} = {{field.value|expression_to_text}};
-{%- elif loop.first %}
+{%- elif loop.first %}
{{enum_name}}.{{field.name}} = 0;
-{%- else %}
+{%- else %}
{{enum_name}}.{{field.name}} = {{enum_name}}.{{enum.fields[loop.index0 - 1].name}} + 1;
+{%- endif %}
+{%- endfor %}
+
+ {{enum_name}}.isKnownEnumValue = function(value) {
+{%- if enum.fields %}
+ switch (value) {
+{%- for enum_field in enum.fields|groupby('numeric_value') %}
+ case {{enum_field[0]}}:
+{%- endfor %}
+ return true;
+ }
{%- endif %}
-{%- endfor %}
+ return false;
+ };
+
+ {{enum_name}}.validate = function(enumValue) {
+ var isExtensible = {% if enum.extensible %}true{% else %}false{% endif %};
+ if (isExtensible || this.isKnownEnumValue(enumValue))
+ return validator.validationError.NONE;
+
+ return validator.validationError.UNKNOWN_ENUM_VALUE;
+ };
{%- endmacro %}
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
index ca80d677de9..b16d673deb1 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl
@@ -59,7 +59,8 @@
var numberOfBytes = decoder.readUint32();
var version = decoder.readUint32();
{%- for byte in struct.bytes %}
-{%- if byte.packed_fields|length > 1 %}
+{%- if byte.packed_fields|length >= 1 and
+ byte.packed_fields[0].field|is_bool_field %}
packed = decoder.readUint8();
{%- for packed_field in byte.packed_fields %}
val.{{packed_field.field.name}} = (packed >> {{packed_field.bit}}) & 1 ? true : false;
@@ -82,7 +83,8 @@
encoder.writeUint32({{struct.versions[-1].version}});
{%- for byte in struct.bytes %}
-{%- if byte.packed_fields|length > 1 %}
+{%- if byte.packed_fields|length >= 1 and
+ byte.packed_fields[0].field|is_bool_field %}
packed = 0;
{%- for packed_field in byte.packed_fields %}
packed |= (val.{{packed_field.field.name}} & 1) << {{packed_field.bit}}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl
index 3c903bc1f29..4823febeca9 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl
@@ -89,7 +89,11 @@ Object.defineProperty({{union.name}}.prototype, "{{field.name}}", {
switch (val.$tag) {
{%- for field in union.fields %}
case {{union.name}}.Tags.{{field.name}}:
+{%- if field|is_bool_field %}
+ encoder.writeUint8(val.{{field.name}} ? 1 : 0);
+{%- else %}
encoder.{{field.kind|union_encode_snippet}}val.{{field.name}});
+{%- endif %}
break;
{%- endfor %}
}
@@ -111,7 +115,11 @@ Object.defineProperty({{union.name}}.prototype, "{{field.name}}", {
switch (tag) {
{%- for field in union.fields %}
case {{union.name}}.Tags.{{field.name}}:
+{%- if field|is_bool_field %}
+ result.{{field.name}} = decoder.readUint8() ? true : false;
+{%- else %}
result.{{field.name}} = decoder.{{field.kind|union_decode_snippet}};
+{%- endif %}
break;
{%- endfor %}
}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl
index 7a39749b6bf..3d0be6e95e3 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl
@@ -24,10 +24,14 @@ err = messageValidator.validateMapPointer({{offset}}, {{field|validate_map_param
// validate {{name}}
err = messageValidator.validateInterface({{offset}}, {{field|validate_interface_params}});
{{_check_err()}}
-{%- elif field|is_handle_field %}
+{%- elif field|is_handle_field or field|is_interface_request_field %}
// validate {{name}}
err = messageValidator.validateHandle({{offset}}, {{field|validate_handle_params}})
{{_check_err()}}
+{%- elif field|is_enum_field %}
+// validate {{name}}
+err = messageValidator.validateEnum({{offset}}, {{field|validate_enum_params}});
+{{_check_err()}}
{%- endif %}
{%- endmacro %}
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index cd37489a455..07eb45bfc3e 100644
--- a/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -36,6 +36,7 @@ _kind_to_cpp_literal_suffix = {
# generator library code so that filters can use the generator as context.
_current_typemap = {}
_for_blink = False
+_use_new_wrapper_types = False
# TODO(rockot, yzshen): The variant handling is kind of a hack currently. Make
# it right.
_variant = None
@@ -49,22 +50,40 @@ class _NameFormatter(object):
self._variant = variant
def Format(self, separator, prefixed=False, internal=False,
- include_variant=False, add_same_module_namespaces=False):
+ include_variant=False, add_same_module_namespaces=False,
+ flatten_nested_kind=False):
+ """Formats the name according to the given configuration.
+
+ Args:
+ separator: Separator between different parts of the name.
+ prefixed: Whether a leading separator should be added.
+ internal: Returns the name in the "internal" namespace.
+ include_variant: Whether to include variant as namespace. If |internal| is
+ True, then this flag is ignored and variant is not included.
+ add_same_module_namespaces: Includes all namespaces even if the token is
+ from the same module as the current mojom file.
+ flatten_nested_kind: It is allowed to define enums inside structs and
+ interfaces. If this flag is set to True, this method concatenates the
+ parent kind and the nested kind with '_', instead of treating the
+ parent kind as a scope."""
+
parts = []
if self._ShouldIncludeNamespace(add_same_module_namespaces):
if prefixed:
parts.append("")
parts.extend(self._GetNamespace())
- if include_variant and self._variant:
+ if include_variant and self._variant and not internal:
parts.append(self._variant)
- parts.extend(self._GetName(internal))
+ parts.extend(self._GetName(internal, flatten_nested_kind))
return separator.join(parts)
- def FormatForCpp(self, add_same_module_namespaces=False, internal=False):
+ def FormatForCpp(self, add_same_module_namespaces=False, internal=False,
+ flatten_nested_kind=False):
return self.Format(
"::", prefixed=True,
add_same_module_namespaces=add_same_module_namespaces,
- internal=internal, include_variant=True)
+ internal=internal, include_variant=True,
+ flatten_nested_kind=flatten_nested_kind)
def FormatForMojom(self):
return self.Format(".", add_same_module_namespaces=True)
@@ -73,24 +92,32 @@ class _NameFormatter(object):
if not internal:
return token.name
if (mojom.IsStructKind(token) or mojom.IsUnionKind(token) or
- mojom.IsInterfaceKind(token) or mojom.IsEnumKind(token)):
+ mojom.IsEnumKind(token)):
return token.name + "_Data"
return token.name
- def _GetName(self, internal):
- name = []
+ def _GetName(self, internal, flatten_nested_kind):
+ if isinstance(self._token, mojom.EnumValue):
+ name_parts = _NameFormatter(self._token.enum, self._variant)._GetName(
+ internal, flatten_nested_kind)
+ name_parts.append(self._token.name)
+ return name_parts
+
+ name_parts = []
if internal:
- name.append("internal")
+ name_parts.append("internal")
+
+ if (flatten_nested_kind and mojom.IsEnumKind(self._token) and
+ self._token.parent_kind):
+ name = "%s_%s" % (self._token.parent_kind.name,
+ self._MapKindName(self._token, internal))
+ name_parts.append(name)
+ return name_parts
+
if self._token.parent_kind:
- name.append(self._MapKindName(self._token.parent_kind, internal))
- # Both variable and enum constants are constructed like:
- # Namespace::Struct::CONSTANT_NAME
- # For enums, CONSTANT_NAME is EnumName::ENUM_VALUE.
- if isinstance(self._token, mojom.EnumValue):
- name.extend([self._token.enum.name, self._token.name])
- else:
- name.append(self._MapKindName(self._token, internal))
- return name
+ name_parts.append(self._MapKindName(self._token.parent_kind, internal))
+ name_parts.append(self._MapKindName(self._token, internal))
+ return name_parts
def _ShouldIncludeNamespace(self, add_same_module_namespaces):
return add_same_module_namespaces or self._token.imported_from
@@ -106,27 +133,35 @@ class _NameFormatter(object):
def ConstantValue(constant):
return ExpressionToText(constant.value, kind=constant.kind)
+# TODO(yzshen): Revisit the default value feature. It was designed prior to
+# custom type mapping.
def DefaultValue(field):
if field.default:
if mojom.IsStructKind(field.kind):
assert field.default == "default"
- return "%s::New()" % GetNameForKind(field.kind)
+ if not IsTypemappedKind(field.kind):
+ return "%s::New()" % GetNameForKind(field.kind)
return ExpressionToText(field.default, kind=field.kind)
- if mojom.IsArrayKind(field.kind) or mojom.IsMapKind(field.kind):
- return "nullptr";
- if mojom.IsStringKind(field.kind):
- return "" if _for_blink else "nullptr"
+ if not _use_new_wrapper_types:
+ if mojom.IsArrayKind(field.kind) or mojom.IsMapKind(field.kind):
+ return "nullptr";
+ if mojom.IsStringKind(field.kind):
+ return "" if _for_blink else "nullptr"
return ""
def NamespaceToArray(namespace):
return namespace.split(".") if namespace else []
-def GetNameForKind(kind, internal=False):
- return _NameFormatter(kind, _variant).FormatForCpp(internal=internal)
+def GetNameForKind(kind, internal=False, flatten_nested_kind=False,
+ add_same_module_namespaces=False):
+ return _NameFormatter(kind, _variant).FormatForCpp(
+ internal=internal, flatten_nested_kind=flatten_nested_kind,
+ add_same_module_namespaces=add_same_module_namespaces)
-def GetQualifiedNameForKind(kind, internal=False):
+def GetQualifiedNameForKind(kind, internal=False, flatten_nested_kind=False):
return _NameFormatter(kind, _variant).FormatForCpp(
- internal=internal, add_same_module_namespaces=True)
+ internal=internal, add_same_module_namespaces=True,
+ flatten_nested_kind=flatten_nested_kind)
def GetFullMojomNameForKind(kind):
return _NameFormatter(kind, _variant).FormatForMojom()
@@ -139,64 +174,116 @@ def IsNativeOnlyKind(kind):
return (mojom.IsStructKind(kind) or mojom.IsEnumKind(kind)) and \
kind.native_only
+
+def IsHashableKind(kind):
+ """Check if the kind can be hashed.
+
+ Args:
+ kind: {Kind} The kind to check.
+
+ Returns:
+ {bool} True if a value of this kind can be hashed.
+ """
+ checked = set()
+ def Check(kind):
+ if kind.spec in checked:
+ return True
+ checked.add(kind.spec)
+ if mojom.IsNullableKind(kind):
+ return False
+ elif mojom.IsStructKind(kind):
+ if (IsTypemappedKind(kind) and
+ not _current_typemap[GetFullMojomNameForKind(kind)]["hashable"]):
+ return False
+ return all(Check(field.kind) for field in kind.fields)
+ elif mojom.IsUnionKind(kind):
+ return all(Check(field.kind) for field in kind.fields)
+ elif mojom.IsAnyHandleKind(kind):
+ return False
+ elif mojom.IsAnyInterfaceKind(kind):
+ return False
+ # TODO(tibell): Arrays and maps could be made hashable. We just don't have a
+ # use case yet.
+ elif mojom.IsArrayKind(kind):
+ return False
+ elif mojom.IsMapKind(kind):
+ return False
+ else:
+ return True
+ return Check(kind)
+
+
def GetNativeTypeName(typemapped_kind):
return _current_typemap[GetFullMojomNameForKind(typemapped_kind)]["typename"]
-def GetCppType(kind):
- if mojom.IsArrayKind(kind):
- return "mojo::internal::Array_Data<%s>*" % GetCppType(kind.kind)
- if mojom.IsMapKind(kind):
- return "mojo::internal::Map_Data<%s, %s>*" % (
- GetCppType(kind.key_kind), GetCppType(kind.value_kind))
- if mojom.IsStructKind(kind):
- return "%s*" % GetNameForKind(kind, internal=True)
- if mojom.IsUnionKind(kind):
- return "%s" % GetNameForKind(kind, internal=True)
- if mojom.IsInterfaceKind(kind):
- return "mojo::internal::Interface_Data"
- if mojom.IsInterfaceRequestKind(kind):
- return "mojo::internal::Handle_Data"
- if mojom.IsAssociatedInterfaceKind(kind):
- return "mojo::internal::AssociatedInterface_Data"
- if mojom.IsAssociatedInterfaceRequestKind(kind):
- return "mojo::internal::AssociatedInterfaceRequest_Data"
- if mojom.IsEnumKind(kind):
- return "int32_t"
- if mojom.IsStringKind(kind):
- return "mojo::internal::String_Data*"
- if mojom.IsAnyHandleKind(kind):
- return "mojo::internal::Handle_Data"
- return _kind_to_cpp_type[kind]
-
def GetCppPodType(kind):
if mojom.IsStringKind(kind):
return "char*"
return _kind_to_cpp_type[kind]
-def GetCppWrapperType(kind):
+def GetCppWrapperType(kind, add_same_module_namespaces=False):
+ def _AddOptional(type_name):
+ pattern = "WTF::Optional<%s>" if _for_blink else "base::Optional<%s>"
+ return pattern % type_name
+
if IsTypemappedKind(kind):
- return GetNativeTypeName(kind)
+ type_name = GetNativeTypeName(kind)
+ if (mojom.IsNullableKind(kind) and
+ not _current_typemap[GetFullMojomNameForKind(kind)][
+ "nullable_is_same_type"]):
+ type_name = _AddOptional(type_name)
+ return type_name
if mojom.IsEnumKind(kind):
- return GetNameForKind(kind)
+ return GetNameForKind(
+ kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
- return "%sPtr" % GetNameForKind(kind)
+ return "%sPtr" % GetNameForKind(
+ kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsArrayKind(kind):
- pattern = "mojo::WTFArray<%s>" if _for_blink else "mojo::Array<%s>"
- return pattern % GetCppWrapperType(kind.kind)
+ pattern = None
+ if _use_new_wrapper_types:
+ pattern = "WTF::Vector<%s>" if _for_blink else "std::vector<%s>"
+ if mojom.IsNullableKind(kind):
+ pattern = _AddOptional(pattern)
+ else:
+ pattern = "mojo::WTFArray<%s>" if _for_blink else "mojo::Array<%s>"
+ return pattern % GetCppWrapperType(
+ kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsMapKind(kind):
- pattern = "mojo::WTFMap<%s, %s>" if _for_blink else "mojo::Map<%s, %s>"
- return pattern % (GetCppWrapperType(kind.key_kind),
- GetCppWrapperType(kind.value_kind))
+ pattern = None
+ if _use_new_wrapper_types:
+ pattern = ("WTF::HashMap<%s, %s>" if _for_blink else
+ "std::unordered_map<%s, %s>")
+ if mojom.IsNullableKind(kind):
+ pattern = _AddOptional(pattern)
+ else:
+ pattern = "mojo::WTFMap<%s, %s>" if _for_blink else "mojo::Map<%s, %s>"
+ return pattern % (
+ GetCppWrapperType(
+ kind.key_kind,
+ add_same_module_namespaces=add_same_module_namespaces),
+ GetCppWrapperType(
+ kind.value_kind,
+ add_same_module_namespaces=add_same_module_namespaces))
if mojom.IsInterfaceKind(kind):
- return "%sPtr" % GetNameForKind(kind)
+ return "%sPtr" % GetNameForKind(
+ kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsInterfaceRequestKind(kind):
- return "%sRequest" % GetNameForKind(kind.kind)
+ return "%sRequest" % GetNameForKind(
+ kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsAssociatedInterfaceKind(kind):
- return "%sAssociatedPtrInfo" % GetNameForKind(kind.kind)
+ return "%sAssociatedPtrInfo" % GetNameForKind(
+ kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsAssociatedInterfaceRequestKind(kind):
- return "%sAssociatedRequest" % GetNameForKind(kind.kind)
+ return "%sAssociatedRequest" % GetNameForKind(
+ kind.kind, add_same_module_namespaces=add_same_module_namespaces)
if mojom.IsStringKind(kind):
- return "WTF::String" if _for_blink else "mojo::String"
+ if _for_blink:
+ return "WTF::String"
+ if not _use_new_wrapper_types:
+ return "mojo::String"
+ type_name = "std::string"
+ return _AddOptional(type_name) if mojom.IsNullableKind(kind) else type_name
if mojom.IsGenericHandleKind(kind):
return "mojo::ScopedHandle"
if mojom.IsDataPipeConsumerKind(kind):
@@ -211,12 +298,30 @@ def GetCppWrapperType(kind):
raise Exception("Unrecognized kind %s" % kind.spec)
return _kind_to_cpp_type[kind]
-def ShouldPassParamByValue(kind):
+def IsMoveOnlyKind(kind):
if IsTypemappedKind(kind):
if mojom.IsEnumKind(kind):
- return True
- return _current_typemap[GetFullMojomNameForKind(kind)]["pass_by_value"]
- return not mojom.IsStringKind(kind)
+ return False
+ return _current_typemap[GetFullMojomNameForKind(kind)]["move_only"]
+ if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
+ return True
+ if mojom.IsArrayKind(kind):
+ return IsMoveOnlyKind(kind.kind) if _use_new_wrapper_types else True
+ if mojom.IsMapKind(kind):
+ return IsMoveOnlyKind(kind.value_kind) if _use_new_wrapper_types else True
+ if mojom.IsAnyHandleOrInterfaceKind(kind):
+ return True
+ return False
+
+def IsCopyablePassByValue(kind):
+ if not IsTypemappedKind(kind):
+ return False
+ return _current_typemap[GetFullMojomNameForKind(kind)][
+ "copyable_pass_by_value"]
+
+def ShouldPassParamByValue(kind):
+ return ((not mojom.IsReferenceKind(kind)) or IsMoveOnlyKind(kind) or
+ IsCopyablePassByValue(kind))
def GetCppWrapperParamType(kind):
cpp_wrapper_type = GetCppWrapperType(kind)
@@ -231,10 +336,10 @@ def GetCppFieldType(kind):
return "%s" % GetNameForKind(kind, internal=True)
if mojom.IsArrayKind(kind):
return ("mojo::internal::Pointer<mojo::internal::Array_Data<%s>>" %
- GetCppType(kind.kind))
+ GetCppFieldType(kind.kind))
if mojom.IsMapKind(kind):
return ("mojo::internal::Pointer<mojo::internal::Map_Data<%s, %s>>" %
- (GetCppType(kind.key_kind), GetCppType(kind.value_kind)))
+ (GetCppFieldType(kind.key_kind), GetCppFieldType(kind.value_kind)))
if mojom.IsInterfaceKind(kind):
return "mojo::internal::Interface_Data"
if mojom.IsInterfaceRequestKind(kind):
@@ -261,29 +366,47 @@ def GetUnionGetterReturnType(kind):
return "%s&" % GetCppWrapperType(kind)
return GetCppWrapperType(kind)
-# TODO(yzshen): It is unfortunate that we have so many functions for returning
-# types. Refactor them.
-def GetUnmappedTypeForSerializer(kind):
+def GetUnionTraitGetterReturnType(kind):
+ """Get field type used in UnionTraits template specialization.
+
+ The type may be qualified as UnionTraits specializations live outside the
+ namespace where e.g. structs are defined.
+
+ Args:
+ kind: {Kind} The type of the field.
+
+ Returns:
+ {str} The C++ type to use for the field.
+ """
+ if mojom.IsReferenceKind(kind):
+ return "%s&" % GetCppWrapperType(kind, add_same_module_namespaces=True)
+ return GetCppWrapperType(kind, add_same_module_namespaces=True)
+
+def GetCppDataViewType(kind, qualified=False):
+ def _GetName(input_kind):
+ return _NameFormatter(input_kind, None).FormatForCpp(
+ add_same_module_namespaces=qualified, flatten_nested_kind=True)
+
if mojom.IsEnumKind(kind):
- return GetQualifiedNameForKind(kind)
+ return _GetName(kind)
if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
- return "%sPtr" % GetQualifiedNameForKind(kind)
+ return "%sDataView" % _GetName(kind)
if mojom.IsArrayKind(kind):
- return "mojo::Array<%s>" % GetUnmappedTypeForSerializer(kind.kind)
+ return "mojo::ArrayDataView<%s>" % GetCppDataViewType(kind.kind, qualified)
if mojom.IsMapKind(kind):
- return "mojo::Map<%s, %s>" % (
- GetUnmappedTypeForSerializer(kind.key_kind),
- GetUnmappedTypeForSerializer(kind.value_kind))
+ return ("mojo::MapDataView<%s, %s>" % (
+ GetCppDataViewType(kind.key_kind, qualified),
+ GetCppDataViewType(kind.value_kind, qualified)))
+ if mojom.IsStringKind(kind):
+ return "mojo::StringDataView"
if mojom.IsInterfaceKind(kind):
- return "%sPtr" % GetQualifiedNameForKind(kind)
+ return "%sPtrDataView" % _GetName(kind)
if mojom.IsInterfaceRequestKind(kind):
- return "%sRequest" % GetQualifiedNameForKind(kind.kind)
+ return "%sRequestDataView" % _GetName(kind.kind)
if mojom.IsAssociatedInterfaceKind(kind):
- return "%sAssociatedPtrInfo" % GetQualifiedNameForKind(kind.kind)
+ return "%sAssociatedPtrInfoDataView" % _GetName(kind.kind)
if mojom.IsAssociatedInterfaceRequestKind(kind):
- return "%sAssociatedRequest" % GetQualifiedNameForKind(kind.kind)
- if mojom.IsStringKind(kind):
- return "mojo::String"
+ return "%sAssociatedRequestDataView" % _GetName(kind.kind)
if mojom.IsGenericHandleKind(kind):
return "mojo::ScopedHandle"
if mojom.IsDataPipeConsumerKind(kind):
@@ -296,9 +419,13 @@ def GetUnmappedTypeForSerializer(kind):
return "mojo::ScopedSharedBufferHandle"
return _kind_to_cpp_type[kind]
+def GetUnmappedTypeForSerializer(kind):
+ return GetCppDataViewType(kind, qualified=True)
+
def TranslateConstants(token, kind):
if isinstance(token, mojom.NamedValue):
- return _NameFormatter(token, _variant).FormatForCpp()
+ return _NameFormatter(token, _variant).FormatForCpp(
+ flatten_nested_kind=True)
if isinstance(token, mojom.BuiltinValue):
if token.value == "double.INFINITY" or token.value == "float.INFINITY":
@@ -332,17 +459,31 @@ def TranslateConstants(token, kind):
def ExpressionToText(value, kind=None):
return TranslateConstants(value, kind)
+def RequiresContextForDataView(kind):
+ for field in kind.fields:
+ if mojom.IsReferenceKind(field.kind):
+ 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 mojom.IsMoveOnlyKind(field.kind):
+ if mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind):
return False
return True
+def ContainsMoveOnlyMembers(struct):
+ for field in struct.fields:
+ if IsMoveOnlyKind(field.kind):
+ return True
+ return False
+
def ShouldInlineUnion(union):
- return not any(mojom.IsMoveOnlyKind(field.kind) for field in union.fields)
+ return not any(
+ mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind)
+ for field in union.fields)
def GetContainerValidateParamsCtorArgs(kind):
if mojom.IsStringKind(kind):
@@ -366,7 +507,8 @@ def GetContainerValidateParamsCtorArgs(kind):
element_validate_params = GetNewContainerValidateParams(kind.kind)
if mojom.IsEnumKind(kind.kind):
enum_validate_func = ("%s::Validate" %
- GetQualifiedNameForKind(kind.kind, internal=True))
+ GetQualifiedNameForKind(kind.kind, internal=True,
+ flatten_nested_kind=True))
else:
enum_validate_func = "nullptr"
@@ -392,32 +534,41 @@ class Generator(generator.Generator):
cpp_filters = {
"constant_value": ConstantValue,
+ "contains_handles_or_interfaces": mojom.ContainsHandlesOrInterfaces,
+ "contains_move_only_members": ContainsMoveOnlyMembers,
"cpp_wrapper_param_type": GetCppWrapperParamType,
+ "cpp_data_view_type": GetCppDataViewType,
"cpp_field_type": GetCppFieldType,
"cpp_union_field_type": GetCppUnionFieldType,
"cpp_pod_type": GetCppPodType,
"cpp_union_getter_return_type": GetUnionGetterReturnType,
+ "cpp_union_trait_getter_return_type": GetUnionTraitGetterReturnType,
"cpp_wrapper_type": GetCppWrapperType,
"default_value": DefaultValue,
"expression_to_text": ExpressionToText,
"get_container_validate_params_ctor_args":
- GetContainerValidateParamsCtorArgs,
+ GetContainerValidateParamsCtorArgs,
"get_name_for_kind": GetNameForKind,
"get_pad": pack.GetPad,
"get_qualified_name_for_kind": GetQualifiedNameForKind,
"has_callbacks": mojom.HasCallbacks,
"has_sync_methods": mojom.HasSyncMethods,
+ "requires_context_for_data_view": RequiresContextForDataView,
"should_inline": ShouldInlineStruct,
"should_inline_union": ShouldInlineUnion,
"is_array_kind": mojom.IsArrayKind,
"is_enum_kind": mojom.IsEnumKind,
"is_integral_kind": mojom.IsIntegralKind,
"is_native_only_kind": IsNativeOnlyKind,
+ "is_any_handle_kind": mojom.IsAnyHandleKind,
+ "is_any_interface_kind": mojom.IsAnyInterfaceKind,
"is_any_handle_or_interface_kind": mojom.IsAnyHandleOrInterfaceKind,
"is_associated_kind": mojom.IsAssociatedKind,
+ "is_hashable": IsHashableKind,
"is_map_kind": mojom.IsMapKind,
"is_nullable_kind": mojom.IsNullableKind,
"is_object_kind": mojom.IsObjectKind,
+ "is_reference_kind": mojom.IsReferenceKind,
"is_string_kind": mojom.IsStringKind,
"is_struct_kind": mojom.IsStructKind,
"is_typemapped_kind": IsTypemappedKind,
@@ -442,6 +593,14 @@ class Generator(generator.Generator):
return list(extra_headers)
def GetJinjaExports(self):
+ structs = self.GetStructs()
+ interfaces = self.GetInterfaces()
+ all_enums = list(self.module.enums)
+ for struct in structs:
+ all_enums.extend(struct.enums)
+ for interface in interfaces:
+ all_enums.extend(interface.enums)
+
return {
"module": self.module,
"namespace": self.module.namespace,
@@ -449,13 +608,17 @@ class Generator(generator.Generator):
"imports": self.module.imports,
"kinds": self.module.kinds,
"enums": self.module.enums,
- "structs": self.GetStructs(),
+ "all_enums": all_enums,
+ "structs": structs,
"unions": self.GetUnions(),
- "interfaces": self.GetInterfaces(),
+ "interfaces": interfaces,
"variant": self.variant,
"extra_traits_headers": self.GetExtraTraitsHeaders(),
"extra_public_headers": self.GetExtraPublicHeaders(),
"for_blink": self.for_blink,
+ "use_new_wrapper_types": self.use_new_wrapper_types,
+ "export_attribute": self.export_attribute,
+ "export_header": self.export_header,
}
@staticmethod
@@ -470,25 +633,43 @@ class Generator(generator.Generator):
def GenerateModuleHeader(self):
return self.GetJinjaExports()
- @UseJinja("module-internal.h.tmpl")
- def GenerateModuleInternalHeader(self):
- return self.GetJinjaExports()
-
@UseJinja("module.cc.tmpl")
def GenerateModuleSource(self):
return self.GetJinjaExports()
+ @UseJinja("module-shared.h.tmpl")
+ def GenerateModuleSharedHeader(self):
+ return self.GetJinjaExports()
+
+ @UseJinja("module-shared-internal.h.tmpl")
+ def GenerateModuleSharedInternalHeader(self):
+ return self.GetJinjaExports()
+
+ @UseJinja("module-shared.cc.tmpl")
+ def GenerateModuleSharedSource(self):
+ return self.GetJinjaExports()
+
def GenerateFiles(self, args):
- global _current_typemap
- _current_typemap = self.typemap
- global _for_blink
- _for_blink = self.for_blink
- global _variant
- _variant = self.variant
- suffix = "-%s" % self.variant if self.variant else ""
- self.Write(self.GenerateModuleHeader(),
- self.MatchMojomFilePath("%s%s.h" % (self.module.name, suffix)))
- self.Write(self.GenerateModuleInternalHeader(),
- self.MatchMojomFilePath("%s%s-internal.h" % (self.module.name, suffix)))
- self.Write(self.GenerateModuleSource(),
- self.MatchMojomFilePath("%s%s.cc" % (self.module.name, suffix)))
+ if self.generate_non_variant_code:
+ self.Write(self.GenerateModuleSharedHeader(),
+ self.MatchMojomFilePath("%s-shared.h" % self.module.name))
+ self.Write(
+ self.GenerateModuleSharedInternalHeader(),
+ self.MatchMojomFilePath("%s-shared-internal.h" % self.module.name))
+ self.Write(self.GenerateModuleSharedSource(),
+ self.MatchMojomFilePath("%s-shared.cc" % self.module.name))
+ else:
+ global _current_typemap
+ _current_typemap = self.typemap
+ global _for_blink
+ _for_blink = self.for_blink
+ global _use_new_wrapper_types
+ _use_new_wrapper_types = self.use_new_wrapper_types
+ global _variant
+ _variant = self.variant
+ suffix = "-%s" % self.variant if self.variant else ""
+ self.Write(self.GenerateModuleHeader(),
+ self.MatchMojomFilePath("%s%s.h" % (self.module.name, suffix)))
+ self.Write(
+ self.GenerateModuleSource(),
+ self.MatchMojomFilePath("%s%s.cc" % (self.module.name, suffix)))
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py
index 481efbc3d1f..c7657ff99ad 100644
--- a/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -10,8 +10,8 @@ import contextlib
import os
import re
import shutil
+import sys
import tempfile
-import zipfile
from jinja2 import contextfilter
@@ -20,6 +20,11 @@ import mojom.generate.generator as generator
import mojom.generate.module as mojom
from mojom.generate.template_expander import UseJinja
+sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir,
+ os.pardir, os.pardir, os.pardir, os.pardir,
+ 'build', 'android', 'gyp'))
+from util import build_utils
+
GENERATOR_PREFIX = 'java'
@@ -219,8 +224,8 @@ def GetPackage(module):
return ParseStringAttribute(module.attributes['JavaPackage'])
# Default package.
if module.namespace:
- return 'org.chromium.mojom.' + module.namespace
- return 'org.chromium.mojom'
+ return 'org.chromium.' + module.namespace
+ return 'org.chromium'
def GetNameForKind(context, kind):
def _GetNameHierachy(kind):
@@ -397,14 +402,6 @@ def TempDir():
finally:
shutil.rmtree(dirname)
-def ZipContentInto(root, zip_filename):
- with zipfile.ZipFile(zip_filename, 'w') as zip_file:
- for dirname, _, files in os.walk(root):
- for filename in files:
- path = os.path.join(dirname, filename)
- path_in_archive = os.path.relpath(path, root)
- zip_file.write(path, path_in_archive)
-
class Generator(generator.Generator):
java_filters = {
@@ -533,7 +530,7 @@ class Generator(generator.Generator):
with TempDir() as temp_java_root:
self.output_dir = os.path.join(temp_java_root, package_path)
self.DoGenerateFiles();
- ZipContentInto(temp_java_root, zip_filename)
+ build_utils.ZipDir(zip_filename, temp_java_root)
if args.java_output_directory:
# If requested, generate the java files directly into indicated directory.
diff --git a/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py b/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py
index e9a488388d6..27ac18a8274 100644
--- a/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/chromium/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -37,9 +37,13 @@ _kind_to_javascript_default_value = {
def JavaScriptType(kind):
+ name = []
if kind.imported_from:
- return kind.imported_from["unique_name"] + "." + kind.name
- return kind.name
+ name.append(kind.imported_from["unique_name"])
+ if kind.parent_kind:
+ name.append(kind.parent_kind.name)
+ name.append(kind.name)
+ return ".".join(name)
def JavaScriptDefaultValue(field):
@@ -129,7 +133,7 @@ def CodecType(kind):
if mojom.IsAssociatedInterfaceRequestKind(kind):
return "codec.AssociatedInterfaceRequestNotSupported"
if mojom.IsEnumKind(kind):
- return _kind_to_codec_type[mojom.INT32]
+ return "new codec.Enum(%s)" % JavaScriptType(kind)
if mojom.IsMapKind(kind):
map_type = "NullableMapOf" if mojom.IsNullableKind(kind) else "MapOf"
key_type = ElementCodecType(kind.key_kind)
@@ -141,6 +145,7 @@ def CodecType(kind):
def ElementCodecType(kind):
return "codec.PackedBool" if mojom.IsBoolKind(kind) else CodecType(kind)
+
def JavaScriptDecodeSnippet(kind):
if (kind in mojom.PRIMITIVES or mojom.IsUnionKind(kind) or
mojom.IsInterfaceKind(kind) or mojom.IsAssociatedKind(kind)):
@@ -228,6 +233,11 @@ def JavaScriptValidateArrayParams(field):
expected_dimension_sizes)
+def JavaScriptValidateEnumParams(field):
+ nullable = JavaScriptNullableParam(field)
+ enum_type = JavaScriptType(field.kind)
+ return "%s, %s" % (enum_type, nullable)
+
def JavaScriptValidateStructParams(field):
nullable = JavaScriptNullableParam(field)
struct_type = JavaScriptType(field.kind)
@@ -316,6 +326,9 @@ def ExpressionToText(value):
def IsArrayPointerField(field):
return mojom.IsArrayKind(field.kind)
+def IsEnumField(field):
+ return mojom.IsEnumKind(field.kind)
+
def IsStringPointerField(field):
return mojom.IsStringKind(field.kind)
@@ -331,9 +344,15 @@ def IsHandleField(field):
def IsInterfaceField(field):
return mojom.IsInterfaceKind(field.kind)
+def IsInterfaceRequestField(field):
+ return mojom.IsInterfaceRequestKind(field.kind)
+
def IsUnionField(field):
return mojom.IsUnionKind(field.kind)
+def IsBoolField(field):
+ return mojom.IsBoolKind(field.kind)
+
class Generator(generator.Generator):
@@ -348,17 +367,21 @@ class Generator(generator.Generator):
"field_offset": JavaScriptFieldOffset,
"has_callbacks": mojom.HasCallbacks,
"is_array_pointer_field": IsArrayPointerField,
+ "is_bool_field": IsBoolField,
+ "is_enum_field": IsEnumField,
"is_map_pointer_field": IsMapPointerField,
"is_struct_pointer_field": IsStructPointerField,
"is_string_pointer_field": IsStringPointerField,
"is_union_field": IsUnionField,
"is_handle_field": IsHandleField,
"is_interface_field": IsInterfaceField,
+ "is_interface_request_field": IsInterfaceRequestField,
"js_type": JavaScriptType,
"js_proxy_method_parameter_value": JavaScriptProxyMethodParameterValue,
"js_stub_method_parameter_value": JavaScriptStubMethodParameterValue,
"stylize_method": generator.StudlyCapsToCamel,
"validate_array_params": JavaScriptValidateArrayParams,
+ "validate_enum_params": JavaScriptValidateEnumParams,
"validate_handle_params": JavaScriptValidateHandleParams,
"validate_interface_params": JavaScriptValidateInterfaceParams,
"validate_map_params": JavaScriptValidateMapParams,
diff --git a/chromium/mojo/public/tools/bindings/mojom.gni b/chromium/mojo/public/tools/bindings/mojom.gni
index 0caaabf3814..be36cb49d62 100644
--- a/chromium/mojo/public/tools/bindings/mojom.gni
+++ b/chromium/mojo/public/tools/bindings/mojom.gni
@@ -69,11 +69,50 @@ foreach(configuration, _bindings_configurations) {
# testonly (optional)
#
# visibility (optional)
+#
+# use_new_wrapper_types (optional)
+# If set to true, mojom array/map/string will be mapped to STL (for
+# chromium variant) or WTF (for blink) types. Otherwise, they will be
+# mapped to mojo::Array/Map/String/etc.
+# Default value is true.
+# TODO(yzshen):
+# - convert all users to use the new mode;
+# - remove support for the old mode.
+#
+# The following parameters are used to support the component build. They are
+# needed so that bindings which are linked with a component can use the same
+# export settings for classes. The first three are for the chromium variant, and
+# the last three are for the blink variant.
+# export_class_attribute (optional)
+# The attribute to add to the class declaration. e.g. "CONTENT_EXPORT"
+# export_define (optional)
+# A define to be added to the source_set which is needed by the export
+# header. e.g. "CONTENT_IMPLEMENTATION=1"
+# export_header (optional)
+# A header to be added to the generated bindings to support the component
+# build. e.g. "content/common/content_export.h"
+# export_class_attribute_blink (optional)
+# export_define_blink (optional)
+# export_header_blink (optional)
+# These three parameters are the blink variants of the previous 3.
template("mojom") {
assert(
defined(invoker.sources) || defined(invoker.deps) ||
defined(invoker.public_deps),
"\"sources\" or \"deps\" must be defined for the $target_name template.")
+ if (defined(invoker.export_class_attribute) ||
+ defined(invoker.export_define) || defined(invoker.export_header)) {
+ assert(defined(invoker.export_class_attribute))
+ assert(defined(invoker.export_define))
+ assert(defined(invoker.export_header))
+ }
+ if (defined(invoker.export_class_attribute_blink) ||
+ defined(invoker.export_define_blink) ||
+ defined(invoker.export_header_blink)) {
+ assert(defined(invoker.export_class_attribute_blink))
+ assert(defined(invoker.export_define_blink))
+ assert(defined(invoker.export_header_blink))
+ }
all_deps = []
if (defined(invoker.deps)) {
@@ -97,6 +136,77 @@ template("mojom") {
}
}
+ # Generate code that is shared by different variants.
+ if (defined(invoker.sources)) {
+ common_generator_args = [
+ "--use_bundled_pylibs",
+ "generate",
+ "{{source}}",
+ "-d",
+ rebase_path("//", root_build_dir),
+ "-I",
+ rebase_path("//", root_build_dir),
+ "-o",
+ rebase_path(root_gen_dir),
+ "--bytecode_path",
+ rebase_path("$root_gen_dir/mojo/public/tools/bindings"),
+ ]
+
+ if (defined(invoker.import_dirs)) {
+ foreach(import_dir, invoker.import_dirs) {
+ common_generator_args += [
+ "-I",
+ rebase_path(import_dir, root_build_dir),
+ ]
+ }
+ }
+
+ generator_shared_cpp_outputs = [
+ "{{source_gen_dir}}/{{source_name_part}}.mojom-shared-internal.h",
+ "{{source_gen_dir}}/{{source_name_part}}.mojom-shared.cc",
+ "{{source_gen_dir}}/{{source_name_part}}.mojom-shared.h",
+ ]
+ generator_shared_target_name = "${target_name}_shared__generator"
+ action_foreach(generator_shared_target_name) {
+ script = mojom_generator_script
+ inputs = mojom_generator_sources
+ sources = invoker.sources
+ deps = [
+ "//mojo/public/tools/bindings:precompile_templates",
+ ]
+ outputs = generator_shared_cpp_outputs
+ args = common_generator_args
+ args += [
+ "--generate_non_variant_code",
+ "-g",
+ "c++",
+ ]
+ }
+ }
+
+ shared_cpp_sources_suffix = "shared_cpp_sources"
+ shared_cpp_sources_target_name = "${target_name}_${shared_cpp_sources_suffix}"
+ source_set(shared_cpp_sources_target_name) {
+ if (defined(invoker.testonly)) {
+ testonly = invoker.testonly
+ }
+ deps = []
+ if (defined(invoker.sources)) {
+ sources =
+ process_file_template(invoker.sources, generator_shared_cpp_outputs)
+ deps += [ ":$generator_shared_target_name" ]
+ }
+ public_deps = []
+ foreach(d, all_deps) {
+ # Resolve the name, so that a target //mojo/something becomes
+ # //mojo/something:something and we can append shared_cpp_sources_suffix
+ # to get the cpp dependency name.
+ full_name = get_label_info("$d", "label_no_toolchain")
+ public_deps += [ "${full_name}_${shared_cpp_sources_suffix}" ]
+ }
+ }
+
+ # Generate code for variants.
foreach(bindings_configuration, _bindings_configurations) {
cpp_only = false
variant_suffix = ""
@@ -124,7 +234,6 @@ template("mojom") {
generator_cpp_outputs += [
"{{source_gen_dir}}/{{source_name_part}}.mojom${variant_dash_suffix}.cc",
"{{source_gen_dir}}/{{source_name_part}}.mojom${variant_dash_suffix}.h",
- "{{source_gen_dir}}/{{source_name_part}}.mojom${variant_dash_suffix}-internal.h",
]
enabled_sources = []
if (defined(bindings_configuration.blacklist)) {
@@ -168,28 +277,7 @@ template("mojom") {
]
outputs = generator_cpp_outputs + generator_java_outputs +
generator_js_outputs
- args = [
- "--use_bundled_pylibs",
- "generate",
- "{{source}}",
- "-d",
- rebase_path("//", root_build_dir),
- "-I",
- rebase_path("//", root_build_dir),
- "-o",
- rebase_path(root_gen_dir),
- "--bytecode_path",
- rebase_path("$root_gen_dir/mojo/public/tools/bindings"),
- ]
-
- if (defined(invoker.import_dirs)) {
- foreach(import_dir, invoker.import_dirs) {
- args += [
- "-I",
- rebase_path(import_dir, root_build_dir),
- ]
- }
- }
+ args = common_generator_args
if (cpp_only) {
args += [
@@ -218,6 +306,28 @@ template("mojom") {
if (defined(bindings_configuration.for_blink) &&
bindings_configuration.for_blink) {
args += [ "--for_blink" ]
+ if (defined(invoker.export_class_attribute_blink)) {
+ args += [
+ "--export_attribute",
+ invoker.export_class_attribute_blink,
+ "--export_header",
+ invoker.export_header_blink,
+ ]
+ }
+ } else {
+ if (defined(invoker.export_class_attribute)) {
+ args += [
+ "--export_attribute",
+ invoker.export_class_attribute,
+ "--export_header",
+ invoker.export_header,
+ ]
+ }
+ }
+
+ if (!defined(invoker.use_new_wrapper_types) ||
+ invoker.use_new_wrapper_types) {
+ args += [ "--use_new_wrapper_types" ]
}
}
}
@@ -292,10 +402,16 @@ template("mojom") {
"//mojo/public/cpp/bindings",
]
if (defined(invoker.deps)) {
- public_deps += invoker.deps
+ foreach(dep, invoker.deps) {
+ public_deps +=
+ [ get_label_info(dep, "label_no_toolchain") + variant_suffix ]
+ }
}
if (defined(invoker.public_deps)) {
- public_deps += invoker.public_deps
+ foreach(dep, invoker.public_deps) {
+ public_deps +=
+ [ get_label_info(dep, "label_no_toolchain") + variant_suffix ]
+ }
}
deps = []
@@ -311,20 +427,29 @@ template("mojom") {
# this target *except* mojo/public/cpp/bindings and other *_cpp_sources
# targets.
source_set(cpp_sources_target_name) {
+ defines = []
if (defined(invoker.testonly)) {
testonly = invoker.testonly
}
+ if (defined(invoker.export_define)) {
+ defines += [ invoker.export_define ]
+ }
+ if (defined(invoker.export_define_blink)) {
+ defines += [ invoker.export_define_blink ]
+ }
if (enabled_sources != []) {
sources = process_file_template(enabled_sources, generator_cpp_outputs)
}
deps = [
"//mojo/public/cpp/bindings:struct_traits",
"//mojo/public/interfaces/bindings:bindings__generator",
+ "//mojo/public/interfaces/bindings:bindings_shared__generator",
]
if (enabled_sources != []) {
deps += [ ":$generator_target_name" ]
}
public_deps = [
+ ":$shared_cpp_sources_target_name",
"//base",
]
foreach(d, all_deps) {
diff --git a/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py b/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py
index 130e730abc9..93bcaf34737 100755
--- a/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py
+++ b/chromium/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -49,6 +49,7 @@ _BUILTIN_GENERATORS = {
"java": "mojom_java_generator.py",
}
+
def LoadGenerators(generators_string):
if not generators_string:
return [] # No generators.
@@ -77,12 +78,28 @@ def MakeImportStackMessage(imported_filename_stack):
zip(imported_filename_stack[1:], imported_filename_stack)]))
-def FindImportFile(dir_name, file_name, search_dirs):
- for search_dir in [dir_name] + search_dirs:
- path = os.path.join(search_dir, file_name)
+class RelativePath(object):
+ """Represents a path relative to the source tree."""
+ def __init__(self, path, source_root):
+ self.path = path
+ self.source_root = source_root
+
+ def relative_path(self):
+ return os.path.relpath(os.path.abspath(self.path),
+ os.path.abspath(self.source_root))
+
+
+def FindImportFile(rel_dir, file_name, search_rel_dirs):
+ """Finds |file_name| in either |rel_dir| or |search_rel_dirs|. Returns a
+ RelativePath with first file found, or an arbitrary non-existent file
+ otherwise."""
+ for rel_search_dir in [rel_dir] + search_rel_dirs:
+ path = os.path.join(rel_search_dir.path, file_name)
if os.path.isfile(path):
- return path
- return os.path.join(dir_name, file_name)
+ return RelativePath(path, rel_search_dir.source_root)
+ return RelativePath(os.path.join(rel_dir.path, file_name),
+ rel_dir.source_root)
+
class MojomProcessor(object):
def __init__(self, should_generate):
@@ -105,18 +122,20 @@ class MojomProcessor(object):
self._typemap[language] = language_map
def ProcessFile(self, args, remaining_args, generator_modules, filename):
- self._ParseFileAndImports(filename, args.import_directories, [])
+ self._ParseFileAndImports(RelativePath(filename, args.depth),
+ args.import_directories, [])
return self._GenerateModule(args, remaining_args, generator_modules,
- filename)
+ RelativePath(filename, args.depth))
- def _GenerateModule(self, args, remaining_args, generator_modules, filename):
+ def _GenerateModule(self, args, remaining_args, generator_modules,
+ rel_filename):
# Return the already-generated module.
- if filename in self._processed_files:
- return self._processed_files[filename]
- tree = self._parsed_files[filename]
+ if rel_filename.path in self._processed_files:
+ return self._processed_files[rel_filename.path]
+ tree = self._parsed_files[rel_filename.path]
- dirname, name = os.path.split(filename)
+ dirname, name = os.path.split(rel_filename.path)
mojom = Translate(tree, name)
if args.debug_print_intermediate:
pprint.PrettyPrinter().pprint(mojom)
@@ -124,27 +143,30 @@ class MojomProcessor(object):
# 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 = FindImportFile(dirname,
- import_data['filename'],
- args.import_directories)
+ rel_import_file = FindImportFile(
+ RelativePath(dirname, rel_filename.source_root),
+ import_data['filename'], args.import_directories)
import_data['module'] = self._GenerateModule(
- args, remaining_args, generator_modules, import_filename)
+ args, remaining_args, generator_modules, rel_import_file)
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))
+ module.path = rel_filename.relative_path()
# Normalize to unix-style path here to keep the generators simpler.
module.path = module.path.replace('\\', '/')
- if self._should_generate(filename):
+ if self._should_generate(rel_filename.path):
for language, generator_module in generator_modules.iteritems():
generator = generator_module.Generator(
module, args.output_dir, typemap=self._typemap.get(language, {}),
variant=args.variant, bytecode_path=args.bytecode_path,
- for_blink=args.for_blink)
+ for_blink=args.for_blink,
+ use_new_wrapper_types=args.use_new_wrapper_types,
+ export_attribute=args.export_attribute,
+ export_header=args.export_header,
+ generate_non_variant_code=args.generate_non_variant_code)
filtered_args = []
if hasattr(generator_module, 'GENERATOR_PREFIX'):
prefix = '--' + generator_module.GENERATOR_PREFIX + '_'
@@ -153,49 +175,56 @@ class MojomProcessor(object):
generator.GenerateFiles(filtered_args)
# Save result.
- self._processed_files[filename] = module
+ self._processed_files[rel_filename.path] = module
return module
- def _ParseFileAndImports(self, filename, import_directories,
+ def _ParseFileAndImports(self, rel_filename, import_directories,
imported_filename_stack):
# Ignore already-parsed files.
- if filename in self._parsed_files:
+ if rel_filename.path in self._parsed_files:
return
- if filename in imported_filename_stack:
- print "%s: Error: Circular dependency" % filename + \
- MakeImportStackMessage(imported_filename_stack + [filename])
+ if rel_filename.path in imported_filename_stack:
+ print "%s: Error: Circular dependency" % rel_filename.path + \
+ MakeImportStackMessage(imported_filename_stack + [rel_filename.path])
sys.exit(1)
try:
- with open(filename) as f:
+ with open(rel_filename.path) as f:
source = f.read()
except IOError as e:
- print "%s: Error: %s" % (e.filename, e.strerror) + \
- MakeImportStackMessage(imported_filename_stack + [filename])
+ print "%s: Error: %s" % (e.rel_filename.path, e.strerror) + \
+ MakeImportStackMessage(imported_filename_stack + [rel_filename.path])
sys.exit(1)
try:
- tree = Parse(source, filename)
+ tree = Parse(source, rel_filename.path)
except Error as e:
- full_stack = imported_filename_stack + [filename]
+ full_stack = imported_filename_stack + [rel_filename.path]
print str(e) + MakeImportStackMessage(full_stack)
sys.exit(1)
- dirname = os.path.split(filename)[0]
+ dirname = os.path.split(rel_filename.path)[0]
for imp_entry in tree.import_list:
- import_filename = FindImportFile(dirname,
+ import_file_entry = FindImportFile(
+ RelativePath(dirname, rel_filename.source_root),
imp_entry.import_filename, import_directories)
- self._ParseFileAndImports(import_filename, import_directories,
- imported_filename_stack + [filename])
+ self._ParseFileAndImports(import_file_entry, import_directories,
+ imported_filename_stack + [rel_filename.path])
- self._parsed_files[filename] = tree
+ self._parsed_files[rel_filename.path] = tree
def _Generate(args, remaining_args):
if args.variant == "none":
args.variant = None
+ for idx, import_dir in enumerate(args.import_directories):
+ tokens = import_dir.split(":")
+ if len(tokens) >= 2:
+ args.import_directories[idx] = RelativePath(tokens[0], tokens[1])
+ else:
+ args.import_directories[idx] = RelativePath(tokens[0], args.depth)
generator_modules = LoadGenerators(args.generators_string)
fileutil.EnsureDirectoryExists(args.output_dir)
@@ -242,7 +271,10 @@ def main():
help="comma-separated list of generators")
generate_parser.add_argument(
"-I", dest="import_directories", action="append", metavar="directory",
- default=[], help="add a directory to be searched for import files")
+ default=[],
+ help="add a directory to be searched for import files. The depth from "
+ "source root can be specified for each import by appending it after "
+ "a colon")
generate_parser.add_argument("--typemap", action="append", metavar="TYPEMAP",
default=[], dest="typemaps",
help="apply TYPEMAP to generated output")
@@ -256,6 +288,21 @@ def main():
generate_parser.add_argument("--for_blink", action="store_true",
help="Use WTF types as generated types for mojo "
"string/array/map.")
+ generate_parser.add_argument(
+ "--use_new_wrapper_types", action="store_true",
+ help="Map mojom array/map/string to STL (for chromium variant) or WTF "
+ "(for blink variant) types directly.")
+ generate_parser.add_argument(
+ "--export_attribute", type=str, default="",
+ help="Optional attribute to specify on class declaration to export it "
+ "for the component build.")
+ generate_parser.add_argument(
+ "--export_header", type=str, default="",
+ help="Optional header to include in the generated headers to support the "
+ "component build.")
+ generate_parser.add_argument(
+ "--generate_non_variant_code", action="store_true",
+ help="Generate code that is shared by different variants.")
generate_parser.set_defaults(func=_Generate)
precompile_parser = subparsers.add_parser("precompile",
diff --git a/chromium/mojo/public/tools/bindings/mojom_list_outputs.py b/chromium/mojo/public/tools/bindings/mojom_list_outputs.py
deleted file mode 100755
index 267bd806347..00000000000
--- a/chromium/mojo/public/tools/bindings/mojom_list_outputs.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/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.
-
-import argparse
-import os.path
-import sys
-
-def main():
- parser = argparse.ArgumentParser(
- description="GYP helper script for mapping mojoms => generated outputs.")
- parser.add_argument("--basedir", required=True)
- parser.add_argument("--variant", required=True)
- parser.add_argument("mojom", nargs="*")
-
- args = parser.parse_args()
-
- variant = args.variant if args.variant != "none" else None
-
- for mojom in args.mojom:
- full = os.path.join("<(SHARED_INTERMEDIATE_DIR)", args.basedir, mojom)
- base, ext = os.path.splitext(full)
-
- # Ignore non-mojom files.
- if ext != ".mojom":
- continue
-
- # Fix filename escaping issues on Windows.
- base = base.replace("\\", "/")
- if variant:
- print base + ".mojom-%s.cc" % variant
- print base + ".mojom-%s.h" % variant
- print base + ".mojom-%s-internal.h" % variant
- else:
- print base + ".mojom.cc"
- print base + ".mojom.h"
- print base + ".mojom-internal.h"
- print base + ".mojom.js"
-
- return 0
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
index a97d2eac3a5..f76cc2e197a 100644
--- a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
@@ -37,13 +37,19 @@ 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, typemap=None, variant=None,
- bytecode_path=None, for_blink=False):
+ bytecode_path=None, for_blink=False, use_new_wrapper_types=False,
+ export_attribute=None, export_header=None,
+ generate_non_variant_code=False):
self.module = module
self.output_dir = output_dir
self.typemap = typemap or {}
self.variant = variant
self.bytecode_path = bytecode_path
self.for_blink = for_blink
+ self.use_new_wrapper_types = use_new_wrapper_types
+ self.export_attribute = export_attribute
+ self.export_header = export_header
+ self.generate_non_variant_code = generate_non_variant_code
def GetStructsFromMethods(self):
result = []
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py
index 97f1f0effd0..b763f02cd50 100644
--- a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -294,6 +294,20 @@ class UnionField(Field): pass
class Struct(ReferenceKind):
+ """A struct with typed fields.
+
+ Attributes:
+ name: {str} The name of the struct type.
+ native_only: {bool} Does the struct have a body (i.e. any fields) or is it
+ purely a native struct.
+ module: {Module} The defining module.
+ imported_from: {dict} Information about where this union was
+ imported from.
+ fields: {List[StructField]} The members of the union.
+ attributes: {dict} Additional information about the struct, such as
+ if it's a native struct.
+ """
+
ReferenceKind.AddSharedProperty('name')
ReferenceKind.AddSharedProperty('native_only')
ReferenceKind.AddSharedProperty('module')
@@ -425,14 +439,9 @@ class Map(ReferenceKind):
']')
if IsNullableKind(key_kind):
raise Exception("Nullable kinds cannot be keys in maps.")
- if IsStructKind(key_kind):
- # TODO(erg): It would sometimes be nice if we could key on struct
- # values. However, what happens if the struct has a handle in it? Or
- # non-copyable data like an array?
- raise Exception("Structs cannot be keys in maps.")
if IsAnyHandleKind(key_kind):
raise Exception("Handles cannot be keys in maps.")
- if IsInterfaceKind(key_kind):
+ if IsAnyInterfaceKind(key_kind):
raise Exception("Interfaces cannot be keys in maps.")
if IsArrayKind(key_kind):
raise Exception("Arrays cannot be keys in maps.")
@@ -771,32 +780,29 @@ def IsPointerKind(kind):
IsMapKind(kind))
-# Please note that interface is not considered as handle kind, since it is an
-# aggregate type consisting of a handle and a version number.
+# Please note that it doesn't include any interface kind.
def IsAnyHandleKind(kind):
return (IsGenericHandleKind(kind) or
IsDataPipeConsumerKind(kind) or
IsDataPipeProducerKind(kind) or
IsMessagePipeKind(kind) or
- IsSharedBufferKind(kind) or
- IsInterfaceRequestKind(kind))
+ IsSharedBufferKind(kind))
-def IsAnyHandleOrInterfaceKind(kind):
- return (IsAnyHandleKind(kind) or IsInterfaceKind(kind) or
+def IsAnyInterfaceKind(kind):
+ return (IsInterfaceKind(kind) or IsInterfaceRequestKind(kind) or
IsAssociatedKind(kind))
+def IsAnyHandleOrInterfaceKind(kind):
+ return IsAnyHandleKind(kind) or IsAnyInterfaceKind(kind)
+
+
def IsAssociatedKind(kind):
return (IsAssociatedInterfaceKind(kind) or
IsAssociatedInterfaceRequestKind(kind))
-def IsMoveOnlyKind(kind):
- return (not IsStringKind(kind) and IsObjectKind(kind)) or \
- IsAnyHandleKind(kind) or IsInterfaceKind(kind) or IsAssociatedKind(kind)
-
-
def HasCallbacks(interface):
for method in interface.methods:
if method.response_parameters != None:
@@ -843,3 +849,39 @@ def HasSyncMethods(interface):
if method.sync:
return True
return False
+
+
+def ContainsHandlesOrInterfaces(kind):
+ """Check if the kind contains any handles.
+
+ This check is recursive so it checks all struct fields, containers elements,
+ etc.
+
+ Args:
+ struct: {Kind} The kind to check.
+
+ Returns:
+ {bool}: True if the kind contains handles.
+ """
+ # We remember the types we already checked to avoid infinite recursion when
+ # checking recursive (or mutually recursive) types:
+ checked = set()
+ def Check(kind):
+ if kind.spec in checked:
+ return False
+ checked.add(kind.spec)
+ if IsStructKind(kind):
+ return any(Check(field.kind) for field in kind.fields)
+ elif IsUnionKind(kind):
+ return any(Check(field.kind) for field in kind.fields)
+ elif IsAnyHandleKind(kind):
+ return True
+ elif IsAnyInterfaceKind(kind):
+ return True
+ elif IsArrayKind(kind):
+ return Check(kind.kind)
+ elif IsMapKind(kind):
+ return Check(kind.key_kind) or Check(kind.value_kind)
+ else:
+ return False
+ return Check(kind)
diff --git a/chromium/mojo/public/tools/gn/zip.py b/chromium/mojo/public/tools/gn/zip.py
index 0d4960f4a1a..adc9cb1cba8 100755
--- a/chromium/mojo/public/tools/gn/zip.py
+++ b/chromium/mojo/public/tools/gn/zip.py
@@ -20,25 +20,30 @@ sys.path.append(os.path.join(os.path.dirname(__file__),
"build"))
import gn_helpers
+sys.path.append(os.path.join(os.path.dirname(__file__),
+ os.pardir, os.pardir, os.pardir, os.pardir,
+ 'build', 'android', 'gyp'))
+from util import build_utils
+
+
def DoZip(inputs, link_inputs, zip_inputs, output, base_dir):
files = []
with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) as outfile:
for f in inputs:
file_name = os.path.relpath(f, base_dir)
files.append(file_name)
- outfile.write(f, file_name)
+ build_utils.AddToZipHermetic(outfile, file_name, f)
for f in link_inputs:
realf = os.path.realpath(f) # Resolve symlinks.
file_name = os.path.relpath(realf, base_dir)
files.append(file_name)
- outfile.write(realf, file_name)
+ build_utils.AddToZipHermetic(outfile, file_name, realf)
for zf_name in zip_inputs:
with zipfile.ZipFile(zf_name, 'r') as zf:
for f in zf.namelist():
if f not in files:
files.append(f)
- with zf.open(f) as zff:
- outfile.writestr(f, zff.read())
+ build_utils.AddToZipHermetic(outfile, f, data=zf.read(f))
def main():
diff --git a/chromium/mojo/public/tools/manifest/manifest_collator.py b/chromium/mojo/public/tools/manifest/manifest_collator.py
deleted file mode 100755
index 9a6d0e9b010..00000000000
--- a/chromium/mojo/public/tools/manifest/manifest_collator.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 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.
-
-""" A collator for Mojo Application Manifests """
-
-import argparse
-import json
-import os
-import shutil
-import sys
-import urlparse
-
-eater_relative = '../../../../../tools/json_comment_eater'
-eater_relative = os.path.join(os.path.abspath(__file__), eater_relative)
-sys.path.insert(0, os.path.normpath(eater_relative))
-try:
- import json_comment_eater
-finally:
- sys.path.pop(0)
-
-def ParseJSONFile(filename):
- with open(filename) as json_file:
- try:
- return json.loads(json_comment_eater.Nom(json_file.read()))
- except ValueError:
- print "%s is not a valid JSON document" % filename
- return None
-
-def MergeDicts(left, right):
- for k, v in right.iteritems():
- if k not in left:
- left[k] = v
- else:
- if isinstance(v, dict):
- assert isinstance(left[k], dict)
- MergeDicts(left[k], v)
- elif isinstance(v, list):
- assert isinstance(left[k], list)
- left[k].extend(v)
- else:
- raise "Refusing to merge conflicting non-collection values."
- return left
-
-
-def MergeBaseManifest(parent, base):
- MergeDicts(parent["capabilities"], base["capabilities"])
-
- if "applications" in base:
- if "applications" not in parent:
- parent["applications"] = []
- parent["applications"].extend(base["applications"])
-
- if "process-group" in base:
- parent["process-group"] = base["process-group"]
-
-
-def main():
- parser = argparse.ArgumentParser(
- description="Collate Mojo application manifests.")
- parser.add_argument("--parent")
- parser.add_argument("--output")
- parser.add_argument("--application-name")
- parser.add_argument("--base-manifest", default=None)
- args, children = parser.parse_known_args()
-
- parent = ParseJSONFile(args.parent)
- if parent == None:
- return 1
-
- if args.base_manifest:
- base = ParseJSONFile(args.base_manifest)
- if base == None:
- return 1
- MergeBaseManifest(parent, base)
-
- app_path = parent['name'].split(':')[1]
- if app_path.startswith('//'):
- raise ValueError("Application name path component '%s' must not start " \
- "with //" % app_path)
-
- if args.application_name != app_path:
- raise ValueError("Application name '%s' specified in build file does not " \
- "match application name '%s' specified in manifest." %
- (args.application_name, app_path))
-
- applications = []
- for child in children:
- application = ParseJSONFile(child)
- if application == None:
- return 1
- applications.append(application)
-
- if len(applications) > 0:
- parent['applications'] = applications
-
- with open(args.output, 'w') as output_file:
- json.dump(parent, output_file)
-
- return 0
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/chromium/mojo/public/tools/prepend.py b/chromium/mojo/public/tools/prepend.py
deleted file mode 100755
index de70a82cf6c..00000000000
--- a/chromium/mojo/public/tools/prepend.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/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.
-
-"""
-Prepends a given file with a given line. This can be used to add a shebang line
-to a generated file.
-"""
-
-import optparse
-import os
-import shutil
-import sys
-
-
-def main():
- parser = optparse.OptionParser()
- parser.add_option('--input', help='The file to prepend the line to.')
- parser.add_option('--line', help='The line to be prepended.')
- parser.add_option('--output', help='The output file.')
-
- options, _ = parser.parse_args()
- input_path = options.input
- output_path = options.output
- line = options.line
-
- # Warning - this reads all of the input file into memory.
- with open(output_path, 'w') as output_file:
- output_file.write(line + '\n')
- with open(input_path, 'r') as input_file:
- shutil.copyfileobj(input_file, output_file)
-
-
-if __name__ == '__main__':
- sys.exit(main())