From 39d357e3248f80abea0159765ff39554affb40db Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 4 Jan 2017 14:17:57 +0100 Subject: BASELINE: Update Chromium to 55.0.2883.105 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And updates ninja to 1.7.2 Change-Id: I20d43c737f82764d857ada9a55586901b18b9243 Reviewed-by: Michael BrĂ¼ning --- chromium/mojo/BUILD.gn | 4 - chromium/mojo/OWNERS | 2 +- chromium/mojo/android/BUILD.gn | 14 +- chromium/mojo/android/javatests/init_library.cc | 8 +- chromium/mojo/android/javatests/mojo_test_case.cc | 5 +- .../mojo/android/javatests/validation_test_util.cc | 9 +- chromium/mojo/android/system/base_run_loop.cc | 29 +- chromium/mojo/android/system/core_impl.cc | 87 +--- chromium/mojo/android/system/watcher_impl.cc | 78 ++++ chromium/mojo/android/system/watcher_impl.h | 20 + chromium/mojo/common/BUILD.gn | 18 +- chromium/mojo/common/OWNERS | 4 + chromium/mojo/common/common_custom_types.mojom | 23 +- chromium/mojo/common/common_custom_types.typemap | 20 +- .../common/common_custom_types_struct_traits.cc | 66 +++ .../common/common_custom_types_struct_traits.h | 71 +++ .../mojo/common/common_custom_types_unittest.cc | 108 ++++- chromium/mojo/common/common_type_converters.h | 1 + chromium/mojo/common/struct_traits_unittest.cc | 57 +++ .../mojo/common/test_common_custom_types.mojom | 11 + chromium/mojo/common/traits_test_service.mojom | 14 + chromium/mojo/converters/blink/BUILD.gn | 44 -- chromium/mojo/converters/blink/DEPS | 5 - .../blink/blink_input_events_type_converters.cc | 248 ----------- .../blink/blink_input_events_type_converters.h | 31 -- .../blink_input_events_type_converters_unittest.cc | 140 ------ chromium/mojo/converters/blink/mojo_blink_export.h | 32 -- chromium/mojo/edk/embedder/BUILD.gn | 8 + chromium/mojo/edk/embedder/embedder.cc | 13 +- chromium/mojo/edk/embedder/embedder.h | 21 +- .../edk/embedder/named_platform_channel_pair.h | 8 +- .../embedder/named_platform_channel_pair_win.cc | 76 +--- chromium/mojo/edk/embedder/named_platform_handle.h | 51 +++ .../edk/embedder/named_platform_handle_utils.h | 31 ++ .../embedder/named_platform_handle_utils_posix.cc | 147 ++++++ .../embedder/named_platform_handle_utils_win.cc | 82 ++++ .../platform_channel_pair_posix_unittest.cc | 4 +- .../edk/embedder/platform_channel_utils_posix.cc | 84 ++++ .../edk/embedder/platform_channel_utils_posix.h | 9 + chromium/mojo/edk/embedder/platform_handle.h | 3 + .../edk/embedder/platform_handle_utils_posix.cc | 4 +- .../mojo/edk/embedder/platform_shared_buffer.cc | 21 +- chromium/mojo/edk/js/core.cc | 95 ++++ chromium/mojo/edk/system/BUILD.gn | 7 +- chromium/mojo/edk/system/async_waiter.cc | 23 - chromium/mojo/edk/system/async_waiter.h | 38 -- chromium/mojo/edk/system/broker_host.cc | 165 +++++++ chromium/mojo/edk/system/broker_host.h | 22 +- chromium/mojo/edk/system/broker_host_posix.cc | 129 ------ chromium/mojo/edk/system/broker_messages.h | 23 +- chromium/mojo/edk/system/broker_posix.cc | 2 +- chromium/mojo/edk/system/broker_win.cc | 144 ++++++ chromium/mojo/edk/system/channel.cc | 4 +- chromium/mojo/edk/system/channel_posix.cc | 38 +- chromium/mojo/edk/system/channel_win.cc | 5 +- chromium/mojo/edk/system/core.cc | 33 +- chromium/mojo/edk/system/core.h | 21 +- chromium/mojo/edk/system/core_unittest.cc | 24 - .../edk/system/data_pipe_consumer_dispatcher.cc | 1 + .../edk/system/data_pipe_producer_dispatcher.cc | 6 +- chromium/mojo/edk/system/data_pipe_unittest.cc | 93 +++- chromium/mojo/edk/system/mach_port_relay.cc | 2 +- .../mojo/edk/system/message_pipe_dispatcher.cc | 8 +- chromium/mojo/edk/system/message_pipe_unittest.cc | 11 + .../system/multiprocess_message_pipe_unittest.cc | 118 ++++- chromium/mojo/edk/system/node_channel.cc | 36 +- chromium/mojo/edk/system/node_channel.h | 11 +- chromium/mojo/edk/system/node_controller.cc | 233 ++++++++-- chromium/mojo/edk/system/node_controller.h | 43 +- .../system/platform_handle_dispatcher_unittest.cc | 4 +- chromium/mojo/edk/system/ports/message_queue.cc | 2 +- chromium/mojo/edk/system/ports/node.cc | 12 +- chromium/mojo/edk/system/waiter.h | 2 +- chromium/mojo/edk/system/watch_unittest.cc | 31 +- chromium/mojo/edk/test/BUILD.gn | 4 +- chromium/mojo/message_pump/BUILD.gn | 24 - chromium/mojo/message_pump/handle_watcher.cc | 480 -------------------- chromium/mojo/message_pump/handle_watcher.h | 65 --- .../mojo/message_pump/handle_watcher_perftest.cc | 207 --------- .../mojo/message_pump/handle_watcher_unittest.cc | 493 --------------------- chromium/mojo/message_pump/message_pump_mojo.cc | 448 ------------------- chromium/mojo/message_pump/message_pump_mojo.h | 178 -------- .../mojo/message_pump/message_pump_mojo_handler.h | 29 -- .../message_pump/message_pump_mojo_unittest.cc | 193 -------- .../mojo/message_pump/mojo_message_pump_export.h | 32 -- chromium/mojo/message_pump/time_helper.cc | 33 -- chromium/mojo/message_pump/time_helper.h | 34 -- chromium/mojo/mojo.gyp | 18 - chromium/mojo/mojo_base.gyp | 192 -------- chromium/mojo/mojo_common_unittests.isolate | 23 - chromium/mojo/mojo_edk.gyp | 233 ---------- chromium/mojo/mojo_edk.gypi | 123 ----- chromium/mojo/mojo_edk_nacl.gyp | 85 ---- chromium/mojo/mojo_edk_tests.gyp | 397 ----------------- chromium/mojo/mojo_js_integration_tests.isolate | 49 -- chromium/mojo/mojo_js_unittests.isolate | 46 -- chromium/mojo/mojo_public.gyp | 308 ------------- chromium/mojo/mojo_public.gypi | 152 ------- .../mojo/mojo_public_bindings_unittests.isolate | 24 - chromium/mojo/mojo_public_nacl.gyp | 87 ---- chromium/mojo/mojo_public_system_unittests.isolate | 23 - chromium/mojo/mojo_public_tests.gyp | 162 ------- chromium/mojo/mojo_system_unittests.isolate | 23 - chromium/mojo/mojo_test_apk.isolate | 11 - chromium/mojo/mojom_bindings_generator.gypi | 166 ------- .../mojo/mojom_bindings_generator_explicit.gypi | 183 -------- .../mojo/mojom_bindings_generator_variables.gypi | 29 -- chromium/mojo/public/c/system/BUILD.gn | 2 +- chromium/mojo/public/c/system/core.h | 1 - chromium/mojo/public/c/system/main.h | 35 -- chromium/mojo/public/c/test_support/BUILD.gn | 1 - chromium/mojo/public/cpp/bindings/BUILD.gn | 45 +- chromium/mojo/public/cpp/bindings/array.h | 30 +- .../mojo/public/cpp/bindings/array_data_view.h | 244 ++++++++++ chromium/mojo/public/cpp/bindings/array_traits.h | 4 +- .../mojo/public/cpp/bindings/array_traits_carray.h | 23 + .../mojo/public/cpp/bindings/array_traits_stl.h | 41 +- .../mojo/public/cpp/bindings/associated_binding.h | 48 +- .../public/cpp/bindings/associated_binding_set.h | 27 ++ .../mojo/public/cpp/bindings/associated_group.h | 3 +- .../cpp/bindings/associated_group_controller.h | 14 +- .../public/cpp/bindings/associated_interface_ptr.h | 35 ++ .../cpp/bindings/associated_interface_request.h | 28 ++ chromium/mojo/public/cpp/bindings/binding.h | 31 +- chromium/mojo/public/cpp/bindings/binding_set.h | 239 +++++++--- .../mojo/public/cpp/bindings/bindings_export.h | 34 ++ .../cpp/bindings/connection_error_callback.h | 21 + chromium/mojo/public/cpp/bindings/connector.h | 30 +- chromium/mojo/public/cpp/bindings/filter_chain.h | 61 +++ .../mojo/public/cpp/bindings/interface_data_view.h | 25 ++ .../cpp/bindings/interface_endpoint_client.h | 47 +- chromium/mojo/public/cpp/bindings/interface_ptr.h | 42 +- .../mojo/public/cpp/bindings/interface_request.h | 17 + .../mojo/public/cpp/bindings/lib/array_internal.h | 105 +---- .../public/cpp/bindings/lib/array_serialization.h | 75 ++-- .../bindings/lib/associated_group_controller.cc | 5 - .../bindings/lib/associated_interface_ptr_state.h | 38 +- .../mojo/public/cpp/bindings/lib/binding_state.cc | 166 +++++++ .../mojo/public/cpp/bindings/lib/binding_state.h | 258 +++++------ .../public/cpp/bindings/lib/bindings_internal.h | 136 ++++-- chromium/mojo/public/cpp/bindings/lib/buffer.h | 54 ++- .../public/cpp/bindings/lib/clone_equals_util.h | 161 +++++++ chromium/mojo/public/cpp/bindings/lib/connector.cc | 89 ++-- .../cpp/bindings/lib/control_message_handler.cc | 121 +++-- .../cpp/bindings/lib/control_message_handler.h | 18 +- .../cpp/bindings/lib/control_message_proxy.cc | 188 ++++++-- .../cpp/bindings/lib/control_message_proxy.h | 29 +- .../mojo/public/cpp/bindings/lib/filter_chain.cc | 22 +- .../mojo/public/cpp/bindings/lib/filter_chain.h | 66 --- .../mojo/public/cpp/bindings/lib/fixed_buffer.cc | 43 +- .../mojo/public/cpp/bindings/lib/fixed_buffer.h | 55 +-- .../bindings/lib/handle_interface_serialization.h | 27 +- chromium/mojo/public/cpp/bindings/lib/hash_util.h | 73 +++ .../cpp/bindings/lib/interface_endpoint_client.cc | 86 +++- .../public/cpp/bindings/lib/interface_ptr_state.h | 105 +++-- .../public/cpp/bindings/lib/map_data_internal.h | 53 +-- .../public/cpp/bindings/lib/map_serialization.h | 43 +- .../mojo/public/cpp/bindings/lib/may_auto_lock.h | 54 +++ chromium/mojo/public/cpp/bindings/lib/message.cc | 130 +++++- .../mojo/public/cpp/bindings/lib/message_buffer.cc | 37 +- .../mojo/public/cpp/bindings/lib/message_buffer.h | 15 +- .../mojo/public/cpp/bindings/lib/message_builder.h | 6 +- .../mojo/public/cpp/bindings/lib/message_filter.cc | 23 - .../cpp/bindings/lib/message_header_validator.cc | 11 +- .../public/cpp/bindings/lib/message_internal.h | 30 ++ .../public/cpp/bindings/lib/multiplex_router.cc | 211 +++++---- .../public/cpp/bindings/lib/multiplex_router.h | 59 ++- .../mojo/public/cpp/bindings/lib/native_struct.cc | 6 + .../public/cpp/bindings/lib/native_struct_data.h | 6 +- .../bindings/lib/native_struct_serialization.cc | 10 +- .../cpp/bindings/lib/native_struct_serialization.h | 6 +- .../bindings/lib/pipe_control_message_handler.cc | 4 +- .../cpp/bindings/lib/pipe_control_message_proxy.cc | 8 +- chromium/mojo/public/cpp/bindings/lib/router.cc | 66 ++- chromium/mojo/public/cpp/bindings/lib/router.h | 39 +- .../mojo/public/cpp/bindings/lib/serialization.h | 20 +- .../cpp/bindings/lib/serialization_context.h | 5 +- .../cpp/bindings/lib/serialization_forward.h | 73 ++- .../public/cpp/bindings/lib/serialization_util.cc | 53 --- .../public/cpp/bindings/lib/serialization_util.h | 83 ---- .../public/cpp/bindings/lib/string_serialization.h | 6 +- .../public/cpp/bindings/lib/string_traits_wtf.cc | 5 +- .../cpp/bindings/lib/sync_handle_registry.cc | 9 +- .../public/cpp/bindings/lib/sync_handle_registry.h | 67 --- .../mojo/public/cpp/bindings/lib/template_util.h | 48 -- .../public/cpp/bindings/lib/validation_context.cc | 52 +-- .../public/cpp/bindings/lib/validation_context.h | 73 ++- .../public/cpp/bindings/lib/validation_errors.cc | 13 + .../public/cpp/bindings/lib/validation_errors.h | 28 +- .../public/cpp/bindings/lib/validation_util.cc | 52 +-- .../mojo/public/cpp/bindings/lib/validation_util.h | 151 ++++--- .../cpp/bindings/lib/wtf_clone_equals_util.h | 76 ++++ .../mojo/public/cpp/bindings/lib/wtf_hash_util.h | 132 ++++++ .../public/cpp/bindings/lib/wtf_serialization.h | 1 + chromium/mojo/public/cpp/bindings/map.h | 6 +- chromium/mojo/public/cpp/bindings/map_data_view.h | 63 +++ chromium/mojo/public/cpp/bindings/map_traits.h | 12 +- chromium/mojo/public/cpp/bindings/map_traits_stl.h | 48 ++ .../public/cpp/bindings/map_traits_wtf_hash_map.h | 64 +++ chromium/mojo/public/cpp/bindings/message.h | 97 +++- chromium/mojo/public/cpp/bindings/message_filter.h | 38 -- .../public/cpp/bindings/message_header_validator.h | 11 +- chromium/mojo/public/cpp/bindings/native_enum.h | 11 + chromium/mojo/public/cpp/bindings/native_struct.h | 4 +- .../public/cpp/bindings/native_struct_data_view.h | 36 ++ chromium/mojo/public/cpp/bindings/no_interface.h | 1 - .../cpp/bindings/pipe_control_message_handler.h | 5 +- .../cpp/bindings/pipe_control_message_proxy.h | 3 +- .../bindings/scoped_interface_endpoint_handle.h | 3 +- chromium/mojo/public/cpp/bindings/string.h | 13 + .../mojo/public/cpp/bindings/string_data_view.h | 34 ++ chromium/mojo/public/cpp/bindings/string_traits.h | 19 +- .../public/cpp/bindings/string_traits_string16.h | 3 +- chromium/mojo/public/cpp/bindings/strong_binding.h | 141 +++--- chromium/mojo/public/cpp/bindings/struct_ptr.h | 156 +++++-- chromium/mojo/public/cpp/bindings/struct_traits.h | 46 +- .../public/cpp/bindings/sync_call_restrictions.h | 7 +- .../public/cpp/bindings/sync_handle_registry.h | 4 +- .../mojo/public/cpp/bindings/sync_handle_watcher.h | 3 +- chromium/mojo/public/cpp/bindings/tests/BUILD.gn | 10 +- .../public/cpp/bindings/tests/rect_blink.typemap | 15 +- .../cpp/bindings/tests/rect_chromium.typemap | 15 +- .../cpp/bindings/tests/struct_with_traits.typemap | 6 +- chromium/mojo/public/cpp/bindings/union_traits.h | 39 ++ chromium/mojo/public/cpp/bindings/wtf_array.h | 13 +- chromium/mojo/public/cpp/bindings/wtf_map.h | 20 +- chromium/mojo/public/cpp/system/BUILD.gn | 27 +- chromium/mojo/public/cpp/system/buffer.h | 4 +- chromium/mojo/public/cpp/system/platform_handle.h | 12 +- chromium/mojo/public/cpp/system/system_export.h | 34 ++ chromium/mojo/public/cpp/system/watcher.h | 3 +- chromium/mojo/public/cpp/test_support/BUILD.gn | 3 +- chromium/mojo/public/interfaces/bindings/BUILD.gn | 4 + chromium/mojo/public/interfaces/bindings/OWNERS | 2 + .../bindings/interface_control_messages.mojom | 71 ++- .../mojo/public/interfaces/bindings/tests/BUILD.gn | 23 + .../public/interfaces/bindings/tests/rect.mojom | 13 +- .../bindings/tests/struct_with_traits.mojom | 41 +- .../tests/test_associated_interfaces.mojom | 6 + .../bindings/tests/test_bad_messages.mojom | 13 + .../interfaces/bindings/tests/test_data_view.mojom | 41 ++ .../interfaces/bindings/tests/test_export.mojom | 18 + .../bindings/tests/test_native_types.mojom | 1 + .../interfaces/bindings/tests/test_structs.mojom | 22 + .../tests/validation_test_interfaces.mojom | 13 + chromium/mojo/public/java/BUILD.gn | 2 +- chromium/mojo/public/js/codec.js | 15 + chromium/mojo/public/js/codec_unittests.js | 18 + chromium/mojo/public/js/connection.js | 20 + chromium/mojo/public/js/core.js | 75 ++++ chromium/mojo/public/js/core_unittests.js | 48 ++ chromium/mojo/public/js/union_unittests.js | 10 + chromium/mojo/public/js/validation_unittests.js | 7 +- chromium/mojo/public/js/validator.js | 14 + chromium/mojo/public/mojo_application.gni | 270 ----------- chromium/mojo/public/mojo_application_manifest.gni | 139 ------ .../mojo/public/mojo_application_manifest.gypi | 56 --- chromium/mojo/public/mojo_constants.gni | 8 - chromium/mojo/public/tools/bindings/BUILD.gn | 12 +- chromium/mojo/public/tools/bindings/bindings.gyp | 83 ---- .../bindings/blink_bindings_configuration.gni | 5 + .../bindings/chromium_bindings_configuration.gni | 17 +- .../tools/bindings/generate_type_mappings.py | 11 +- .../generators/cpp_templates/enum_macros.tmpl | 81 ++-- .../enum_serialization_declaration.tmpl | 3 +- .../cpp_templates/interface_declaration.tmpl | 13 +- .../cpp_templates/interface_definition.tmpl | 119 ++--- .../generators/cpp_templates/interface_macros.tmpl | 16 +- .../cpp_templates/interface_proxy_declaration.tmpl | 6 +- .../interface_request_validator_declaration.tmpl | 4 +- .../interface_response_validator_declaration.tmpl | 4 +- .../cpp_templates/interface_stub_declaration.tmpl | 3 +- .../cpp_templates/module-internal.h.tmpl | 126 ------ .../cpp_templates/module-shared-internal.h.tmpl | 95 ++++ .../generators/cpp_templates/module-shared.cc.tmpl | 64 +++ .../generators/cpp_templates/module-shared.h.tmpl | 212 +++++++++ .../generators/cpp_templates/module.cc.tmpl | 65 +-- .../generators/cpp_templates/module.h.tmpl | 112 ++--- .../struct_data_view_declaration.tmpl | 111 ++++- .../cpp_templates/struct_data_view_definition.tmpl | 64 +-- .../cpp_templates/struct_declaration.tmpl | 20 +- .../cpp_templates/struct_definition.tmpl | 46 -- .../generators/cpp_templates/struct_macros.tmpl | 25 +- .../struct_serialization_declaration.tmpl | 34 +- .../struct_serialization_definition.tmpl | 14 - .../cpp_templates/struct_traits_declaration.tmpl | 32 ++ .../cpp_templates/struct_traits_definition.tmpl | 14 + .../cpp_templates/union_data_view_declaration.tmpl | 92 ++++ .../cpp_templates/union_data_view_definition.tmpl | 12 + .../cpp_templates/union_declaration.tmpl | 24 +- .../generators/cpp_templates/union_definition.tmpl | 56 +-- .../union_serialization_declaration.tmpl | 146 +++++- .../union_serialization_definition.tmpl | 166 ------- .../cpp_templates/union_traits_declaration.tmpl | 24 + .../cpp_templates/union_traits_definition.tmpl | 47 ++ .../cpp_templates/validation_macros.tmpl | 15 +- .../cpp_templates/wrapper_class_declaration.tmpl | 27 +- .../cpp_templates/wrapper_class_definition.tmpl | 13 + .../wrapper_union_class_declaration.tmpl | 21 +- .../wrapper_union_class_definition.tmpl | 34 +- .../java_templates/data_types_definition.tmpl | 15 +- .../java_templates/interface_definition.tmpl | 4 +- .../generators/js_templates/enum_definition.tmpl | 32 +- .../generators/js_templates/struct_definition.tmpl | 6 +- .../generators/js_templates/union_definition.tmpl | 8 + .../generators/js_templates/validation_macros.tmpl | 6 +- .../bindings/generators/mojom_cpp_generator.py | 405 ++++++++++++----- .../bindings/generators/mojom_java_generator.py | 21 +- .../bindings/generators/mojom_js_generator.py | 29 +- chromium/mojo/public/tools/bindings/mojom.gni | 175 ++++++-- .../tools/bindings/mojom_bindings_generator.py | 121 +++-- .../public/tools/bindings/mojom_list_outputs.py | 44 -- .../bindings/pylib/mojom/generate/generator.py | 8 +- .../tools/bindings/pylib/mojom/generate/module.py | 76 +++- chromium/mojo/public/tools/gn/zip.py | 13 +- .../public/tools/manifest/manifest_collator.py | 104 ----- chromium/mojo/public/tools/prepend.py | 37 -- 317 files changed, 8261 insertions(+), 9373 deletions(-) create mode 100644 chromium/mojo/android/system/watcher_impl.cc create mode 100644 chromium/mojo/android/system/watcher_impl.h create mode 100644 chromium/mojo/common/common_custom_types_struct_traits.cc create mode 100644 chromium/mojo/common/common_custom_types_struct_traits.h create mode 100644 chromium/mojo/common/struct_traits_unittest.cc create mode 100644 chromium/mojo/common/traits_test_service.mojom delete mode 100644 chromium/mojo/converters/blink/BUILD.gn delete mode 100644 chromium/mojo/converters/blink/DEPS delete mode 100644 chromium/mojo/converters/blink/blink_input_events_type_converters.cc delete mode 100644 chromium/mojo/converters/blink/blink_input_events_type_converters.h delete mode 100644 chromium/mojo/converters/blink/blink_input_events_type_converters_unittest.cc delete mode 100644 chromium/mojo/converters/blink/mojo_blink_export.h create mode 100644 chromium/mojo/edk/embedder/named_platform_handle.h create mode 100644 chromium/mojo/edk/embedder/named_platform_handle_utils.h create mode 100644 chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc create mode 100644 chromium/mojo/edk/embedder/named_platform_handle_utils_win.cc delete mode 100644 chromium/mojo/edk/system/async_waiter.cc delete mode 100644 chromium/mojo/edk/system/async_waiter.h create mode 100644 chromium/mojo/edk/system/broker_host.cc delete mode 100644 chromium/mojo/edk/system/broker_host_posix.cc create mode 100644 chromium/mojo/edk/system/broker_win.cc delete mode 100644 chromium/mojo/message_pump/BUILD.gn delete mode 100644 chromium/mojo/message_pump/handle_watcher.cc delete mode 100644 chromium/mojo/message_pump/handle_watcher.h delete mode 100644 chromium/mojo/message_pump/handle_watcher_perftest.cc delete mode 100644 chromium/mojo/message_pump/handle_watcher_unittest.cc delete mode 100644 chromium/mojo/message_pump/message_pump_mojo.cc delete mode 100644 chromium/mojo/message_pump/message_pump_mojo.h delete mode 100644 chromium/mojo/message_pump/message_pump_mojo_handler.h delete mode 100644 chromium/mojo/message_pump/message_pump_mojo_unittest.cc delete mode 100644 chromium/mojo/message_pump/mojo_message_pump_export.h delete mode 100644 chromium/mojo/message_pump/time_helper.cc delete mode 100644 chromium/mojo/message_pump/time_helper.h delete mode 100644 chromium/mojo/mojo.gyp delete mode 100644 chromium/mojo/mojo_base.gyp delete mode 100644 chromium/mojo/mojo_common_unittests.isolate delete mode 100644 chromium/mojo/mojo_edk.gyp delete mode 100644 chromium/mojo/mojo_edk.gypi delete mode 100644 chromium/mojo/mojo_edk_nacl.gyp delete mode 100644 chromium/mojo/mojo_edk_tests.gyp delete mode 100644 chromium/mojo/mojo_js_integration_tests.isolate delete mode 100644 chromium/mojo/mojo_js_unittests.isolate delete mode 100644 chromium/mojo/mojo_public.gyp delete mode 100644 chromium/mojo/mojo_public.gypi delete mode 100644 chromium/mojo/mojo_public_bindings_unittests.isolate delete mode 100644 chromium/mojo/mojo_public_nacl.gyp delete mode 100644 chromium/mojo/mojo_public_system_unittests.isolate delete mode 100644 chromium/mojo/mojo_public_tests.gyp delete mode 100644 chromium/mojo/mojo_system_unittests.isolate delete mode 100644 chromium/mojo/mojo_test_apk.isolate delete mode 100644 chromium/mojo/mojom_bindings_generator.gypi delete mode 100644 chromium/mojo/mojom_bindings_generator_explicit.gypi delete mode 100644 chromium/mojo/mojom_bindings_generator_variables.gypi delete mode 100644 chromium/mojo/public/c/system/main.h create mode 100644 chromium/mojo/public/cpp/bindings/array_data_view.h create mode 100644 chromium/mojo/public/cpp/bindings/associated_binding_set.h create mode 100644 chromium/mojo/public/cpp/bindings/bindings_export.h create mode 100644 chromium/mojo/public/cpp/bindings/connection_error_callback.h create mode 100644 chromium/mojo/public/cpp/bindings/filter_chain.h create mode 100644 chromium/mojo/public/cpp/bindings/interface_data_view.h create mode 100644 chromium/mojo/public/cpp/bindings/lib/binding_state.cc create mode 100644 chromium/mojo/public/cpp/bindings/lib/clone_equals_util.h delete mode 100644 chromium/mojo/public/cpp/bindings/lib/filter_chain.h create mode 100644 chromium/mojo/public/cpp/bindings/lib/hash_util.h create mode 100644 chromium/mojo/public/cpp/bindings/lib/may_auto_lock.h delete mode 100644 chromium/mojo/public/cpp/bindings/lib/message_filter.cc delete mode 100644 chromium/mojo/public/cpp/bindings/lib/serialization_util.cc delete mode 100644 chromium/mojo/public/cpp/bindings/lib/sync_handle_registry.h create mode 100644 chromium/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h create mode 100644 chromium/mojo/public/cpp/bindings/lib/wtf_hash_util.h create mode 100644 chromium/mojo/public/cpp/bindings/map_data_view.h create mode 100644 chromium/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h delete mode 100644 chromium/mojo/public/cpp/bindings/message_filter.h create mode 100644 chromium/mojo/public/cpp/bindings/native_struct_data_view.h create mode 100644 chromium/mojo/public/cpp/bindings/string_data_view.h create mode 100644 chromium/mojo/public/cpp/bindings/union_traits.h create mode 100644 chromium/mojo/public/cpp/system/system_export.h create mode 100644 chromium/mojo/public/interfaces/bindings/OWNERS create mode 100644 chromium/mojo/public/interfaces/bindings/tests/test_bad_messages.mojom create mode 100644 chromium/mojo/public/interfaces/bindings/tests/test_data_view.mojom create mode 100644 chromium/mojo/public/interfaces/bindings/tests/test_export.mojom delete mode 100644 chromium/mojo/public/mojo_application.gni delete mode 100644 chromium/mojo/public/mojo_application_manifest.gni delete mode 100644 chromium/mojo/public/mojo_application_manifest.gypi delete mode 100644 chromium/mojo/public/mojo_constants.gni delete mode 100644 chromium/mojo/public/tools/bindings/bindings.gyp delete mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl delete mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_declaration.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_definition.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/union_data_view_definition.tmpl delete mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_declaration.tmpl create mode 100644 chromium/mojo/public/tools/bindings/generators/cpp_templates/union_traits_definition.tmpl delete mode 100755 chromium/mojo/public/tools/bindings/mojom_list_outputs.py delete mode 100755 chromium/mojo/public/tools/manifest/manifest_collator.py delete mode 100755 chromium/mojo/public/tools/prepend.py (limited to 'chromium/mojo') 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 ParseData( input, &data, &num_handles, &error_message)) { ScopedJavaLocalRef 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 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& jcaller) { - base::MessageLoop* message_loop = - new base::MessageLoop(common::MessagePumpMojo::Create()); + base::MessageLoop* message_loop = new base::MessageLoop; return reinterpret_cast(message_loop); } static void Run(JNIEnv* env, - const JavaParamRef& jcaller, - jlong runLoopID) { - reinterpret_cast(runLoopID)->Run(); + const JavaParamRef& jcaller) { + base::RunLoop().Run(); } static void RunUntilIdle(JNIEnv* env, - const JavaParamRef& jcaller, - jlong runLoopID) { - reinterpret_cast(runLoopID)->RunUntilIdle(); + const JavaParamRef& 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& 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(runLoopID)->PostDelayedTask( - FROM_HERE, base::Bind(&RunJavaRunnable, runnable_ref), - base::TimeDelta::FromMicroseconds(delay)); + reinterpret_cast(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 #include -#include - #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 core_impl; - base::android::ScopedJavaGlobalRef callback; - base::android::ScopedJavaGlobalRef 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 callback_data( - static_cast(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& jcaller) { return MojoGetTimeTicksNow(); @@ -365,51 +329,6 @@ static int Unmap(JNIEnv* env, return MojoUnmapBuffer(buffer_start); } -static ScopedJavaLocalRef AsyncWait( - JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - jint signals, - jlong deadline, - const JavaParamRef& callback) { - AsyncWaitCallbackData* callback_data = - new AsyncWaitCallbackData(env, jcaller, callback); - MojoAsyncWaitID cancel_id; - if (static_cast(mojo_handle) != MOJO_HANDLE_INVALID) { - common::HandleWatcher* watcher = new common::HandleWatcher(); - cancel_id = reinterpret_cast(watcher); - watcher->Start(Handle(static_cast(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 cancellable = - Java_CoreImpl_newAsyncWaiterCancellableImpl( - env, jcaller, cancel_id, reinterpret_cast(callback_data)); - callback_data->cancellable.Reset(env, cancellable.obj()); - return cancellable; -} - -static void CancelAsyncWait(JNIEnv* env, - const JavaParamRef& 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 deleter( - reinterpret_cast(data_ptr)); - delete reinterpret_cast( - static_cast(id)); -} - static jint GetNativeBufferOffset(JNIEnv* env, const JavaParamRef& jcaller, const JavaParamRef& 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 +#include + +#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& 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 java_watcher_; +}; + +} // namespace + +static jlong CreateWatcher(JNIEnv* env, const JavaParamRef& jcaller) { + return reinterpret_cast(new Watcher); +} + +static jint Start(JNIEnv* env, + const JavaParamRef& jcaller, + jlong watcher_ptr, + jint mojo_handle, + jint signals) { + Watcher* watcher = reinterpret_cast(watcher_ptr); + return watcher->Start( + mojo::Handle(static_cast(mojo_handle)), + static_cast(signals), + base::Bind(&JavaWatcherCallback::OnHandleReady, + base::Owned(new JavaWatcherCallback(env, jcaller)))); +} + +static void Cancel(JNIEnv* env, + const JavaParamRef& jcaller, + jlong watcher_ptr) { + reinterpret_cast(watcher_ptr)->Cancel(); +} + +static void Delete(JNIEnv* env, + const JavaParamRef& jcaller, + jlong watcher_ptr) { + delete reinterpret_cast(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 + +#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 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 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 + +namespace mojo { + +// static +mojo::ConstCArray +StructTraits::data( + const base::string16& str) { + return mojo::ConstCArray( + str.size(), reinterpret_cast(str.data())); +} + +// static +bool StructTraits::Read( + mojo::common::mojom::String16DataView data, + base::string16* out) { + mojo::ArrayDataView view; + data.GetDataDataView(&view); + if (view.is_null()) + return false; + out->assign(reinterpret_cast(view.data()), view.size()); + return true; +} + +// static +const std::vector& +StructTraits::components( + const base::Version& version) { + return version.components(); +} + +// static +bool StructTraits::Read( + mojo::common::mojom::VersionDataView data, + base::Version* out) { + std::vector components; + if (!data.ReadComponents(&components)) + return false; + + *out = base::Version(base::Version(std::move(components))); + return out->IsValid(); +} + +// static +bool StructTraits:: + 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 { + static mojo::ConstCArray data(const base::string16& str); + static bool Read(mojo::common::mojom::String16DataView data, + base::string16* out); +}; + +template <> +struct StructTraits { + 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& 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 { + 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 { + 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" @@ -39,17 +40,38 @@ struct BounceTestTraits { } }; +template +struct PassTraits { + using Type = const T&; +}; + +template <> +struct PassTraits { + using Type = base::Time; +}; + +template <> +struct PassTraits { + using Type = base::TimeDelta; +}; + +template <> +struct PassTraits { + using Type = base::TimeTicks; +}; + template void DoExpectResponse(T* expected_value, const base::Closure& closure, - const T& value) { + typename PassTraits::Type value) { BounceTestTraits::ExpectEquality(*expected_value, value); closure.Run(); } template -base::Callback ExpectResponse(T* expected_value, - const base::Closure& closure) { +base::Callback::Type)> ExpectResponse( + T* expected_value, + const base::Closure& closure) { return base::Bind(&DoExpectResponse, expected_value, closure); } @@ -68,24 +90,38 @@ class TestFilePathImpl : public TestFilePath { mojo::Binding 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 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 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 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 +#include #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& m, + const EchoVersionCallback& callback) override { + callback.Run(m); + } + + base::MessageLoop loop_; + mojo::BindingSet 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 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 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 - -#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(located_event.x()); - web_event->y = static_cast(located_event.y()); - web_event->globalX = static_cast(located_event.root_location_f().x()); - web_event->globalY = static_cast(located_event.root_location_f().y()); -} - -std::unique_ptr BuildWebMouseEventFrom( - const ui::PointerEvent& event) { - std::unique_ptr 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 BuildWebKeyboardEvent( - const ui::KeyEvent& event) { - std::unique_ptr 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 BuildWebMouseWheelEventFrom( - const ui::MouseWheelEvent& event) { - std::unique_ptr 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 BuildWebTouchEvent( - const ui::PointerEvent& event) { - std::unique_ptr 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 -TypeConverter, 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 - -#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, ui::Event> { - static std::unique_ptr 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 web_event( - TypeConverter, - 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(web_event.get()); - ASSERT_EQ(static_cast(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 web_event( - TypeConverter, 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(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 web_event( - TypeConverter, - 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(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 web_event( - TypeConverter, - 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(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& 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& 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 #include #include @@ -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 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 + +#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 +#include +#include +#include + +#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(&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(&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 +#include + +#include + +#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 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 #include +#include + +#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 @@ -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(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 . 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* 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 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 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& 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 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 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; - - // |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.cc b/chromium/mojo/edk/system/broker_host.cc new file mode 100644 index 00000000000..a5a5f9cf04b --- /dev/null +++ b/chromium/mojo/edk/system/broker_host.cc @@ -0,0 +1,165 @@ +// 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/system/broker_host.h" + +#include + +#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/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" + +namespace mojo { +namespace edk { + +namespace { + +// To prevent abuse, limit the maximum size of shared memory buffers. +// TODO(rockot): Re-consider this limit, or do something smarter. +const uint32_t kMaxSharedBufferSize = 16 * 1024 * 1024; + +} // 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_->Start(); +} + +BrokerHost::~BrokerHost() { + // We're always destroyed on the creation thread, which is the IO thread. + base::MessageLoop::current()->RemoveDestructionObserver(this); + + if (channel_) + channel_->ShutDown(); +} + +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(); + + // 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; +} + +#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(&name_data)); + data->pipe_name_length = static_cast(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 buffer; + scoped_refptr read_only_buffer; + if (num_bytes <= kMaxSharedBufferSize) { + buffer = PlatformSharedBuffer::Create(num_bytes); + if (buffer) + read_only_buffer = buffer->CreateReadOnlyDuplicate(); + if (!read_only_buffer) + buffer = nullptr; + } else { + LOG(ERROR) << "Shared buffer request too large: " << num_bytes; + } + + Channel::MessagePtr message = CreateBrokerMessage( + BrokerMessageType::BUFFER_RESPONSE, buffer ? 2 : 0, nullptr); + if (buffer) { + ScopedPlatformHandleVectorPtr handles; + 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)); + } + + channel_->Write(std::move(message)); +} + +void BrokerHost::OnChannelMessage(const void* payload, + size_t payload_size, + ScopedPlatformHandleVectorPtr handles) { + if (payload_size < sizeof(BrokerMessageHeader)) + return; + + const BrokerMessageHeader* header = + static_cast(payload); + switch (header->type) { + case BrokerMessageType::BUFFER_REQUEST: + if (payload_size == + sizeof(BrokerMessageHeader) + sizeof(BufferRequestData)) { + const BufferRequestData* request = + reinterpret_cast(header + 1); + OnBufferRequest(request->size); + } + break; + + default: + LOG(ERROR) << "Unexpected broker message type: " << header->type; + break; + } +} + +void BrokerHost::OnChannelError() { 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 + #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_; diff --git a/chromium/mojo/edk/system/broker_host_posix.cc b/chromium/mojo/edk/system/broker_host_posix.cc deleted file mode 100644 index ed8e213c1c0..00000000000 --- a/chromium/mojo/edk/system/broker_host_posix.cc +++ /dev/null @@ -1,129 +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/edk/system/broker_host.h" - -#include -#include - -#include - -#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/platform_handle_vector.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/broker_messages.h" - -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; -} - -BrokerHost::BrokerHost(ScopedPlatformHandle platform_handle) { - CHECK(platform_handle.is_valid()); - - base::MessageLoop::current()->AddDestructionObserver(this); - - channel_ = Channel::Create(this, std::move(platform_handle), - base::ThreadTaskRunnerHandle::Get()); - channel_->Start(); -} - -BrokerHost::~BrokerHost() { - // We're always destroyed on the creation thread, which is the IO thread. - base::MessageLoop::current()->RemoveDestructionObserver(this); - - if (channel_) - channel_->ShutDown(); -} - -void BrokerHost::SendChannel(ScopedPlatformHandle handle) { - CHECK(handle.is_valid()); - CHECK(channel_); - - Channel::MessagePtr message = - CreateBrokerMessage(BrokerMessageType::INIT, 1, nullptr); - ScopedPlatformHandleVectorPtr handles; - handles.reset(new PlatformHandleVector(1)); - handles->at(0) = handle.release(); - message->SetHandles(std::move(handles)); - - channel_->Write(std::move(message)); -} - -void BrokerHost::OnBufferRequest(size_t num_bytes) { - scoped_refptr buffer; - scoped_refptr read_only_buffer; - if (num_bytes <= kMaxSharedBufferSize) { - buffer = PlatformSharedBuffer::Create(num_bytes); - if (buffer) - read_only_buffer = buffer->CreateReadOnlyDuplicate(); - if (!read_only_buffer) - buffer = nullptr; - } else { - LOG(ERROR) << "Shared buffer request too large: " << num_bytes; - } - - Channel::MessagePtr message = CreateBrokerMessage( - BrokerMessageType::BUFFER_RESPONSE, buffer ? 2 : 0, nullptr); - if (buffer) { - ScopedPlatformHandleVectorPtr handles; - handles.reset(new PlatformHandleVector(2)); - handles->at(0) = buffer->PassPlatformHandle().release(); - handles->at(1) = read_only_buffer->PassPlatformHandle().release(); - message->SetHandles(std::move(handles)); - } - - channel_->Write(std::move(message)); -} - -void BrokerHost::OnChannelMessage(const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) { - if (payload_size < sizeof(BrokerMessageHeader)) - return; - - const BrokerMessageHeader* header = - static_cast(payload); - switch (header->type) { - case BrokerMessageType::BUFFER_REQUEST: - if (payload_size == - sizeof(BrokerMessageHeader) + sizeof(BufferRequestData)) { - const BufferRequestData* request = - reinterpret_cast(header + 1); - OnBufferRequest(request->size); - return; - } - break; - - default: - break; - } - - LOG(ERROR) << "Unexpected broker message type: " << header->type; -} - -void BrokerHost::OnChannelError() { - if (channel_) { - channel_->ShutDown(); - channel_ = nullptr; - } - - delete this; -} - -void BrokerHost::WillDestroyCurrentMessageLoop() { - delete this; -} - -} // namespace edk -} // namespace mojo 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 -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(message->mutable_payload()); header->type = type; header->padding = 0; *out_message_data = reinterpret_cast(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 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 + +#include +#include + +#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(bytes_read)); + if (!message || message->payload_size() < sizeof(BrokerMessageHeader)) { + LOG(ERROR) << "Invalid broker message"; + return nullptr; + } + + const BrokerMessageHeader* header = + reinterpret_cast(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(message->payload()); + CHECK_GE(message->payload_size(), + sizeof(BrokerMessageHeader) + sizeof(InitData)); + const InitData* data = reinterpret_cast(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(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 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(num_bytes); + DWORD bytes_written = 0; + BOOL result = ::WriteFile(sync_channel_.get().handle, out_message->data(), + static_cast(out_message->data_num_bytes()), + &bytes_written, nullptr); + if (!result || + static_cast(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( - static_cast(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(extra_header); for (size_t i = 0; i < num_handles; i++) { - (*handles)->at(i).handle = reinterpret_cast( - static_cast(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 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& callback) { - scoped_refptr dispatcher = GetDispatcher(handle); - DCHECK(dispatcher); - - std::unique_ptr 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(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 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& callback); - MojoResult SetProperty(MojoPropertyType type, const void* value); // --------------------------------------------------------------------------- @@ -298,6 +299,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { // to access it. std::unique_ptr 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 { + 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, 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, 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(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(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& observer) { @@ -309,6 +322,7 @@ void NodeController::MergePortIntoParent(const std::string& token, } scoped_refptr 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 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 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 channel = NodeChannel::Create( + this, std::move(server_handle), io_task_runner_, process_error_callback); + +#else // !defined(OS_MACOSX) && !defined(OS_NACL) scoped_refptr 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 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 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 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 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 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_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 GetPeerChannel(const ports::NodeName& name); scoped_refptr GetParentChannel(); scoped_refptr GetBrokerChannel(); @@ -153,10 +161,11 @@ class NodeController : public ports::NodeDelegate, void AddPeer(const ports::NodeName& name, scoped_refptr 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 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> 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 pending_relay_messages_; - // Guards |incoming_messages_|. + // Guards |incoming_messages_| and |incoming_messages_task_posted_|. base::Lock messages_lock_; std::queue 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::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_; #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 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 +#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 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(*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 #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; - 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(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(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 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 -#include - -#include - -#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 callback; - scoped_refptr 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 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& 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 Requests; - - friend struct base::DefaultSingletonTraits; - - 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::get(); -} - -WatcherID WatcherThreadManager::StartWatching( - const Handle& handle, - MojoHandleSignals handle_signals, - base::TimeTicks deadline, - const base::Callback& 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& 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 callback = callback_; - watcher_->Stop(); // Destroys |this|. - - callback.Run(result); - } - - HandleWatcher* watcher_; - base::Callback 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& 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& 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 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& 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 - -#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& 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 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 - -#include -#include - -#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 CreateMessageLoop(MessageLoopConfig config) { - std::unique_ptr 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 { - public: - HandleWatcherPerftest() : message_loop_(CreateMessageLoop(GetParam())) {} - - protected: - std::string GetMessageLoopName() const { - return (GetParam() == MESSAGE_LOOP_CONFIG_DEFAULT) ? "DefaultMessageLoop" - : "MojoMessageLoop"; - } - - private: - std::unique_ptr 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 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 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 data_vector; - for (uint64_t i = 0; i < kWaitingHandles; i++) { - std::unique_ptr 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 -#include - -#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 next_callback, - MojoResult result) { - delete watcher; - next_callback.Run(result); -} - -std::unique_ptr CreateMessageLoop(MessageLoopConfig config) { - std::unique_ptr 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 reseter(&run_loop_, &run_loop); - run_loop.Run(); - } - - base::Callback 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& 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 weak_factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(CallbackHelper); -}; - -class HandleWatcherTest : public testing::TestWithParam { - 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 at_exit_; - std::unique_ptr 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 task_runner, - base::RunLoop* run_loop, - int* active_count) { - struct TestData { - MessagePipe pipe; - HandleWatcher watcher; - }; - ScopedVector 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 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 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 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 - -#include -#include -#include - -#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 >::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(0) : - static_cast(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 MessagePumpMojo::Create() { - return std::unique_ptr(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, 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 . Then, iterate over those expired handles and remove - // them. The two-step process is because a handler can add/remove new - // handlers. - std::map 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 - -#include -#include -#include -#include - -#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 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()(static_cast(handle.value())); - } - }; - - using HandleToHandler = std::unordered_map; - - // 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 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 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 CreateMojoMessagePump() { - return std::unique_ptr(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(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': - '& 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 after we move to MSVC 2015. std::vector PassStorage() { is_null_ = true; return std::move(vec_); } + operator const std::vector&() 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 + +#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 +class ArrayDataViewImpl; + +template +class ArrayDataViewImpl< + T, + typename std::enable_if< + BelongsTo::value>::type> { + public: + using Data_ = typename MojomTypeTraits>::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 +class ArrayDataViewImpl< + T, + typename std::enable_if< + BelongsTo::value>::type> { + public: + using Data_ = typename MojomTypeTraits>::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 +class ArrayDataViewImpl< + T, + typename std::enable_if< + BelongsTo::value>::type> { + public: + static_assert(sizeof(T) == sizeof(int32_t), "Unexpected enum size"); + + using Data_ = typename MojomTypeTraits>::Data; + + ArrayDataViewImpl(Data_* data, SerializationContext* context) + : data_(data), context_(context) {} + + T operator[](size_t index) const { return static_cast(data_->at(index)); } + + const T* data() const { return reinterpret_cast(data_->storage()); } + + template + bool Read(size_t index, U* output) { + return Deserialize(data_->at(index), output); + } + + protected: + Data_* data_; + SerializationContext* context_; +}; + +template +class ArrayDataViewImpl< + T, + typename std::enable_if< + BelongsTo::value>::type> { + public: + using Data_ = typename MojomTypeTraits>::Data; + + ArrayDataViewImpl(Data_* data, SerializationContext* context) + : data_(data), context_(context) {} + + template + U Take(size_t index) { + U result; + bool ret = Deserialize(&data_->at(index), &result, context_); + DCHECK(ret); + return result; + } + + protected: + Data_* data_; + SerializationContext* context_; +}; + +template +class ArrayDataViewImpl< + T, + typename std::enable_if< + BelongsTo::value>::type> { + public: + using Data_ = typename MojomTypeTraits>::Data; + + ArrayDataViewImpl(Data_* data, SerializationContext* context) + : data_(data), context_(context) {} + + T Take(size_t index) { + T result; + bool ret = Deserialize(&data_->at(index), &result, context_); + DCHECK(ret); + return result; + } + + protected: + Data_* data_; + SerializationContext* context_; +}; + +template +class ArrayDataViewImpl::value>::type> { + public: + using Data_ = typename MojomTypeTraits>::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 + bool Read(size_t index, U* output) { + return Deserialize(data_->at(index).Get(), output, context_); + } + + protected: + Data_* data_; + SerializationContext* context_; +}; + +template +class ArrayDataViewImpl< + T, + typename std::enable_if< + BelongsTo::value>::type> { + public: + using Data_ = typename MojomTypeTraits>::Data; + + ArrayDataViewImpl(Data_* data, SerializationContext* context) + : data_(data), context_(context) {} + + void GetDataView(size_t index, T* output) { + *output = T(&data_->at(index), context_); + } + + template + bool Read(size_t index, U* output) { + return Deserialize(&data_->at(index), output, context_); + } + + protected: + Data_* data_; + SerializationContext* context_; +}; + +} // namespace internal + +template +class MapDataView; + +template +class ArrayDataView : public internal::ArrayDataViewImpl { + public: + using Element = T; + using Data_ = typename internal::ArrayDataViewImpl::Data_; + + ArrayDataView() : internal::ArrayDataViewImpl(nullptr, nullptr) {} + + ArrayDataView(Data_* data, internal::SerializationContext* context) + : internal::ArrayDataViewImpl(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 + // bool Read(size_t index, U* output); + + // Handles: + // T Take(size_t index); + + // Interfaces: + // template + // U Take(size_t index); + + // Object types: + // void GetDataView(size_t index, T* output); + // template + // bool Read(size_t index, U* output); + + private: + template + 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 @@ -19,6 +19,14 @@ struct CArray { T* data; }; +template +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 struct ArrayTraits> { using Element = T; @@ -48,6 +56,21 @@ struct ArrayTraits> { } }; +template +struct ArrayTraits> { + using Element = T; + + static bool IsNull(const ConstCArray& input) { return !input.data; } + + static size_t GetSize(const ConstCArray& input) { return input.size; } + + static const T* GetData(const ConstCArray& input) { return input.data; } + + static const T& GetAt(const ConstCArray& 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> { return input[index]; } - static bool Resize(std::vector& input, size_t size) { - input.resize(size); + static inline bool Resize(std::vector& input, size_t size) { + // Instead of calling std::vector::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>. + // 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 temp(size); + input.swap(temp); + } + return true; } }; +// This ArrayTraits specialization is used only for serialization. +template +struct ArrayTraits> { + using Element = T; + using ConstIterator = typename std::set::const_iterator; + + static bool IsNull(const std::set& input) { + // std::set<> is always converted to non-null mojom array. + return false; + } + + static size_t GetSize(const std::set& input) { return input.size(); } + + static ConstIterator GetBegin(const std::set& 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 +#include #include #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 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 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 +struct BindingSetTraits> { + using ProxyType = AssociatedInterfacePtr; + using RequestType = AssociatedInterfaceRequest; +}; + +template +using AssociatedBindingSet = + BindingSet>; + +} // 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 { +class MOJO_CPP_BINDINGS_EXPORT AssociatedGroupController + : public base::RefCountedThreadSafe { public: - explicit AssociatedGroupController( - scoped_refptr 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 CreateAssociatedGroup(); protected: - friend class base::RefCountedDeleteOnMessageLoop; - friend class base::DeleteHelper; + friend class base::RefCountedThreadSafe; // 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 + +#include #include #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 GetProxy( return request; } +// Creates an associated interface proxy which casts its messages into the void. +template +void GetDummyProxyForTesting(AssociatedInterfacePtr* proxy) { + MessagePipe pipe; + scoped_refptr router = + new internal::MultiplexRouter(std::move(pipe.handle0), + internal::MultiplexRouter::MULTI_INTERFACE, + false, base::ThreadTaskRunnerHandle::Get()); + std::unique_ptr 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 #include #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(), 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 #include #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 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 - internal_state_; + internal::BindingState 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 +#include #include -#include #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 +struct BindingSetTraits; + +template +struct BindingSetTraits> { + using ProxyType = InterfacePtr; + using RequestType = InterfaceRequest; + + 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 +template > class BindingSet { public: - BindingSet() {} - ~BindingSet() { CloseAllBindings(); } + using PreDispatchCallback = base::Callback; + using Traits = BindingSetTraits; + 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 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 CreateInterfacePtrAndBind(Interface* impl) { - InterfacePtr 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 = + base::MakeUnique(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 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(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 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 binding_; - base::Closure error_handler_; - base::WeakPtrFactory 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& 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> bindings_; + ConnectionErrorWithReasonCallback error_with_reason_handler_; + PreDispatchCallback pre_dispatch_handler_; + BindingId next_binding_id_ = 0; + std::map> 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; + +} // 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 #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 task_runner_; - Watcher handle_watcher_; + std::unique_ptr 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 lock_; std::unique_ptr 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 weak_self_; base::WeakPtrFactory weak_factory_; diff --git a/chromium/mojo/public/cpp/bindings/filter_chain.h b/chromium/mojo/public/cpp/bindings/filter_chain.h new file mode 100644 index 00000000000..1262f39b803 --- /dev/null +++ b/chromium/mojo/public/cpp/bindings/filter_chain.h @@ -0,0 +1,61 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_ + +#include +#include + +#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" + +namespace mojo { + +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. + explicit FilterChain(MessageReceiver* sink = nullptr); + + FilterChain(FilterChain&& other); + FilterChain& operator=(FilterChain&& other); + ~FilterChain() override; + + template + inline void Append(Args&&... args); + + void Append(std::unique_ptr filter); + + // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while + // this object is alive. + void SetSink(MessageReceiver* sink); + + // MessageReceiver: + bool Accept(Message* message) override; + + private: + std::vector> filters_; + + MessageReceiver* sink_; + + DISALLOW_COPY_AND_ASSIGN(FilterChain); +}; + +template +inline void FilterChain::Append(Args&&... args) { + Append(base::MakeUnique(std::forward(args)...)); +} + +template <> +inline void FilterChain::Append() { +} + +} // namespace mojo + +#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 +class AssociatedInterfacePtrInfoDataView {}; + +template +class AssociatedInterfaceRequestDataView {}; + +template +class InterfacePtrDataView {}; + +template +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 #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 payload_validator, + std::unique_ptr payload_validator, bool expect_sync_requests, - scoped_refptr runner); + scoped_refptr 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 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 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 associated_group_; InterfaceEndpointController* controller_; MessageReceiverWithResponderStatus* const incoming_receiver_; - std::unique_ptr 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 task_runner_; + internal::ControlMessageProxy control_message_proxy_; + internal::ControlMessageHandler control_message_handler_; + + bool observing_message_loop_destruction_ = true; + base::ThreadChecker thread_checker_; base::WeakPtrFactory 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 + +#include #include #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* - internal_state() { + internal::InterfacePtrState* 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 - InterfacePtr::*Testable; + typedef internal::InterfacePtrState InterfacePtr::*Testable; public: operator Testable() const { @@ -218,8 +225,7 @@ class InterfacePtr { template bool operator!=(const InterfacePtr& other) const = delete; - typedef internal::InterfacePtrState State; + typedef internal::InterfacePtrState 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 #include #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 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 struct ArrayDataTraits { @@ -58,28 +59,6 @@ struct ArrayDataTraits { } }; -template -struct ArrayDataTraits { - using StorageType = Pointer

; - using Ref = P*&; - using ConstRef = P* const&; - - static const uint32_t kMaxNumElements = - (std::numeric_limits::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 { // 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 { // // 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 @@ -141,12 +120,6 @@ template struct ArraySerializationHelper { using ElementType = typename ArrayDataTraits::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 struct ArraySerializationHelper { using ElementType = typename ArrayDataTraits::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 { } }; -template -struct ArraySerializationHelper { - using ElementType = typename ArrayDataTraits::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 +struct ArraySerializationHelper, false, false> { + using ElementType = typename ArrayDataTraits>::StorageType; static bool ValidateElements(const ArrayHeader* header, const ElementType* elements, @@ -237,7 +194,7 @@ struct ArraySerializationHelper { i).c_str()); return false; } - if (!ValidateCaller

::Run(elements[i], validation_context, + if (!ValidateCaller::Run(elements[i], validation_context, validate_params->element_validate_params)) { return false; } @@ -246,9 +203,11 @@ struct ArraySerializationHelper { } private: - template + template ::value || + IsSpecializationOf::value> struct ValidateCaller { - static bool Run(const Pointer& data, + static bool Run(const Pointer& data, ValidationContext* validation_context, const ContainerValidateParams* validate_params) { DCHECK(!validate_params) @@ -258,21 +217,12 @@ struct ArraySerializationHelper { } }; - template - struct ValidateCaller> { - static bool Run(const Pointer>& data, + template + struct ValidateCaller { + static bool Run(const Pointer& data, ValidationContext* validation_context, const ContainerValidateParams* validate_params) { - return ValidateMap(data, validation_context, validate_params); - } - }; - - template - struct ValidateCaller> { - static bool Run(const Pointer>& 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 struct ArraySerializationHelper { using ElementType = typename ArrayDataTraits::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(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 #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 { using GetNextResult = decltype(Traits::GetValue(std::declval())); 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; - static_assert(std::is_same::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(input->GetNext(), &output->at(i), context); + typename UserTypeIterator::GetNextResult next = input->GetNext(); + Serialize(next, &output->at(i), context); static const ValidationError kError = BelongsTo::value>::type> { using UserType = typename std::remove_const::type; using Data = typename MojomTypeTraits::Data; - using DataElement = typename Data::Element; using Element = typename MojomType::Element; + using DataElementPtr = typename MojomTypeTraits::Data*; using Traits = ArrayTraits; static size_t GetSerializedSize(UserTypeIterator* input, SerializationContext* context) { size_t element_count = input->GetSize(); - size_t size = - sizeof(Data) + - element_count * - sizeof(Pointer::type>); - for (size_t i = 0; i < element_count; ++i) - size += PrepareToSerialize(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(next, context); + } return size; } @@ -376,13 +373,14 @@ struct ArraySerializerGetSize(); for (size_t i = 0; i < size; ++i) { - DataElement element; - SerializeCaller::Run(input->GetNext(), buf, &element, + DataElementPtr data_ptr; + typename UserTypeIterator::GetNextResult next = input->GetNext(); + SerializeCaller::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 ArraySerializersize())) return false; ArrayIterator 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(input->at(i), &iterator.GetNext(), context)) { - success = false; - } + if (!Deserialize(input->at(i).Get(), &iterator.GetNext(), + context)) + return false; } - return success; + return true; } private: @@ -415,7 +409,7 @@ struct ArraySerializer static void Run(InputElementType&& input, Buffer* buf, - DataElement* output, + DataElementPtr* output, const ContainerValidateParams* validate_params, SerializationContext* context) { Serialize(std::forward(input), buf, output, context); @@ -427,7 +421,7 @@ struct ArraySerializer static void Run(InputElementType&& input, Buffer* buf, - DataElement* output, + DataElementPtr* output, const ContainerValidateParams* validate_params, SerializationContext* context) { Serialize(std::forward(input), buf, output, @@ -451,10 +445,6 @@ struct ArraySerializer< using Element = typename MojomType::Element; using Traits = ArrayTraits; - static_assert(std::is_same::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(input->GetNext(), false, context); + typename UserTypeIterator::GetNextResult next = input->GetNext(); + size += PrepareToSerialize(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(input->GetNext(), buf, &result, true, context); + typename UserTypeIterator::GetNextResult next = input->GetNext(); + Serialize(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 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(&input->at(i), &iterator.GetNext(), context)) { - success = false; - } + if (!Deserialize(&input->at(i), &iterator.GetNext(), context)) + return false; } - return success; + return true; } }; template -struct Serializer, MaybeConstUserType> { +struct Serializer, MaybeConstUserType> { using UserType = typename std::remove_const::type; using Traits = ArrayTraits; - using Impl = ArraySerializer, + using Impl = ArraySerializer, MaybeConstUserType, ArrayIterator>; - using Data = typename MojomTypeTraits>::Data; + using Data = typename MojomTypeTraits>::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 task_runner) - : base::RefCountedDeleteOnMessageLoop( - task_runner) {} - AssociatedGroupController::~AssociatedGroupController() {} std::unique_ptr 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 // For |std::swap()|. #include +#include #include #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& 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(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(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 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 runner, + const char* interface_name, + std::unique_ptr request_validator, + bool has_sync_methods, + MessageReceiverWithResponderStatus* stub, + uint32_t interface_version) { + FilterChain filters; + filters.Append(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 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 runner, + const char* interface_name, + std::unique_ptr 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 +#include #include #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 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 runner, + const char* interface_name, + std::unique_ptr request_validator, + bool has_sync_methods, + MessageReceiverWithResponderStatus* stub, + uint32_t interface_version); + + void DestroyRouter(); + + internal::Router* router_ = nullptr; +}; + template 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 -class BindingState { +class BindingState : public SimpleBindingState { public: explicit BindingState(Interface* impl) : impl_(impl) { stub_.set_sink(impl_); @@ -50,42 +111,10 @@ class BindingState { void Bind(ScopedMessagePipeHandle handle, scoped_refptr runner) { DCHECK(!router_); - internal::FilterChain filters; - filters.Append(Interface::Name_); - filters.Append(); - - 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(), + Interface::HasSyncMethods_, &stub_, Interface::Version_); } InterfaceRequest Unbind() { @@ -95,12 +124,45 @@ class BindingState { 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 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 { 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 runner, + const char* interface_name, + std::unique_ptr request_validator, + bool passes_associated_kinds, + bool has_sync_methods, + MessageReceiverWithResponderStatus* stub, + uint32_t interface_version); - DISALLOW_COPY_AND_ASSIGN(BindingState); + scoped_refptr router_; + std::unique_ptr endpoint_client_; }; // Uses a multiplexing router. If |Interface| has methods to pass associated // interface pointers or requests, this specialization should be used. template -class BindingState { +class BindingState : public MultiplexedBindingState { public: explicit BindingState(Interface* impl) : impl_(impl) { stub_.set_sink(impl_); @@ -150,49 +206,12 @@ class BindingState { void Bind(ScopedMessagePipeHandle handle, scoped_refptr 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(), + 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 Unbind() { @@ -200,45 +219,14 @@ class BindingState { InterfaceRequest request = MakeRequest(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 router_; - std::unique_ptr 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 +#include + +#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 -class Array; +class ArrayDataView; template -class AssociatedInterfacePtrInfo; +class AssociatedInterfacePtrInfoDataView; template -class AssociatedInterfaceRequest; +class AssociatedInterfaceRequestDataView; template -class InterfacePtr; +class InterfacePtrDataView; template -class InterfaceRequest; +class InterfaceRequestDataView; template -class Map; - -class String; +class MapDataView; -template -class StructPtr; +class NativeStructDataView; -template -class InlinedStructPtr; +class StringDataView; namespace internal { @@ -55,8 +54,46 @@ class Array_Data; template class Map_Data; +class NativeStruct_Data; + using String_Data = Array_Data; +inline size_t Align(size_t size) { + return (size + 7) & ~0x7; +} + +inline bool IsAligned(const void* ptr) { + return !(reinterpret_cast(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(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(ptr); + const char* p_slot = reinterpret_cast(offset); + DCHECK(p_obj > p_slot); + + *offset = static_cast(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(offset) + *offset; +} + #pragma pack(push, 1) struct StructHeader { @@ -72,9 +109,18 @@ struct ArrayHeader { static_assert(sizeof(ArrayHeader) == 8, "Bad_sizeof(ArrayHeader)"); template -union Pointer { +struct Pointer { + using BaseType = T; + + void Set(T* ptr) { EncodePointer(ptr, &offset); } + const T* Get() const { return static_cast(DecodePointer(&offset)); } + T* Get() { + return static_cast(const_cast(DecodePointer(&offset))); + } + + bool is_null() const { return offset == 0; } + uint64_t offset; - T* ptr; }; static_assert(sizeof(Pointer) == 8, "Bad_sizeof(Pointer)"); @@ -170,15 +216,15 @@ struct MojomTypeTraits { }; template -struct MojomTypeTraits, false> { +struct MojomTypeTraits, false> { using Data = Array_Data::DataAsArrayElement>; - using DataAsArrayElement = Data*; + using DataAsArrayElement = Pointer; static const MojomTypeCategory category = MojomTypeCategory::ARRAY; }; template -struct MojomTypeTraits, false> { +struct MojomTypeTraits, false> { using Data = AssociatedInterface_Data; using DataAsArrayElement = Data; @@ -187,7 +233,7 @@ struct MojomTypeTraits, false> { }; template -struct MojomTypeTraits, false> { +struct MojomTypeTraits, false> { using Data = AssociatedInterfaceRequest_Data; using DataAsArrayElement = Data; @@ -220,7 +266,7 @@ struct MojomTypeTraits, false> { }; template -struct MojomTypeTraits, false> { +struct MojomTypeTraits, false> { using Data = Interface_Data; using DataAsArrayElement = Data; @@ -228,7 +274,7 @@ struct MojomTypeTraits, false> { }; template -struct MojomTypeTraits, false> { +struct MojomTypeTraits, false> { using Data = Handle_Data; using DataAsArrayElement = Data; @@ -237,46 +283,28 @@ struct MojomTypeTraits, false> { }; template -struct MojomTypeTraits, false> { +struct MojomTypeTraits, false> { using Data = Map_Data::DataAsArrayElement, typename MojomTypeTraits::DataAsArrayElement>; - using DataAsArrayElement = Data*; + using DataAsArrayElement = Pointer; static const MojomTypeCategory category = MojomTypeCategory::MAP; }; template <> -struct MojomTypeTraits { - using Data = String_Data; - using DataAsArrayElement = Data*; +struct MojomTypeTraits { + using Data = internal::NativeStruct_Data; + using DataAsArrayElement = Pointer; - static const MojomTypeCategory category = MojomTypeCategory::STRING; + static const MojomTypeCategory category = MojomTypeCategory::STRUCT; }; -template -struct MojomTypeTraits, false> { - using Data = typename T::Data_; - using DataAsArrayElement = - typename std::conditional::value, - Data, - Data*>::type; - - static const MojomTypeCategory category = IsUnionDataType::value - ? MojomTypeCategory::UNION - : MojomTypeCategory::STRUCT; -}; +template <> +struct MojomTypeTraits { + using Data = String_Data; + using DataAsArrayElement = Pointer; -template -struct MojomTypeTraits, false> { - using Data = typename T::Data_; - using DataAsArrayElement = - typename std::conditional::value, - Data, - Data*>::type; - - static const MojomTypeCategory category = IsUnionDataType::value - ? MojomTypeCategory::UNION - : MojomTypeCategory::STRUCT; + static const MojomTypeCategory category = MojomTypeCategory::STRING; }; template @@ -285,6 +313,16 @@ struct BelongsTo { static_cast(MojomTypeTraits::category & categories) != 0; }; +template +struct EnumHashImpl { + static_assert(std::is_enum::value, "Incorrect hash function."); + + size_t operator()(T input) const { + using UnderlyingType = typename base::underlying_type::type; + return std::hash()(static_cast(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 +#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(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(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 +#include +#include + +#include "base/optional.h" +#include "mojo/public/cpp/bindings/lib/template_util.h" + +namespace mojo { +namespace internal { + +template +struct HasCloneMethod { + template + static char Test(decltype(&U::Clone)); + template + static int Test(...); + static const bool value = sizeof(Test(0)) == sizeof(char); + + private: + EnsureTypeIsComplete check_t_; +}; + +template ::value> +struct CloneTraits; + +template +T Clone(const T& input); + +template +struct CloneTraits { + static T Clone(const T& input) { return input.Clone(); } +}; + +template +struct CloneTraits { + static T Clone(const T& input) { return input; } +}; + +template +struct CloneTraits, false> { + static base::Optional Clone(const base::Optional& input) { + if (!input) + return base::nullopt; + + return base::Optional(internal::Clone(*input)); + } +}; + +template +struct CloneTraits, false> { + static std::vector Clone(const std::vector& input) { + std::vector result; + result.reserve(input.size()); + for (const auto& element : input) + result.push_back(internal::Clone(element)); + + return result; + } +}; + +template +struct CloneTraits, false> { + static std::unordered_map Clone(const std::unordered_map& input) { + std::unordered_map result; + for (const auto& element : input) { + result.insert(std::make_pair(internal::Clone(element.first), + internal::Clone(element.second))); + } + return result; + } +}; + +template +T Clone(const T& input) { + return CloneTraits::Clone(input); +}; + +template +struct HasEqualsMethod { + template + static char Test(decltype(&U::Equals)); + template + static int Test(...); + static const bool value = sizeof(Test(0)) == sizeof(char); + + private: + EnsureTypeIsComplete check_t_; +}; + +template ::value> +struct EqualsTraits; + +template +bool Equals(const T& a, const T& b); + +template +struct EqualsTraits { + static bool Equals(const T& a, const T& b) { return a.Equals(b); } +}; + +template +struct EqualsTraits { + static bool Equals(const T& a, const T& b) { return a == b; } +}; + +template +struct EqualsTraits, false> { + static bool Equals(const base::Optional& a, const base::Optional& b) { + if (!a && !b) + return true; + if (!a || !b) + return false; + + return internal::Equals(*a, *b); + } +}; + +template +struct EqualsTraits, false> { + static bool Equals(const std::vector& a, const std::vector& 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 +struct EqualsTraits, false> { + static bool Equals(const std::unordered_map& a, + const std::unordered_map& 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 +bool Equals(const T& a, const T& b) { + return EqualsTraits::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 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 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( - response_params_ptr, &context_); - ResponseMessageBuilder builder(kRunMessageId, size, message->request_id()); - - RunResponseMessageParams_Data* response_params = nullptr; - Serialize(response_params_ptr, builder.buffer(), - &response_params, &context_); - response_params->EncodePointers(); + interface_control::internal::RunMessageParams_Data* params = + reinterpret_cast( + message->mutable_payload()); + interface_control::RunMessageParamsPtr params_ptr; + Deserialize(params, ¶ms_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( + response_params_ptr, &context_); + ResponseMessageBuilder builder(interface_control::kRunMessageId, size, + message->request_id()); + + interface_control::internal::RunResponseMessageParams_Data* response_params = + nullptr; + Serialize( + 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( + interface_control::internal::RunOrClosePipeMessageParams_Data* params = + reinterpret_cast< + interface_control::internal::RunOrClosePipeMessageParams_Data*>( message->mutable_payload()); - params->DecodePointers(); + interface_control::RunOrClosePipeMessageParamsPtr params_ptr; + Deserialize( + params, ¶ms_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(params, ¶ms_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 +#include + +#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 #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; +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; 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( - 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(params, ¶ms_ptr, &context); + Deserialize( + params, ¶ms_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(params_ptr, context); - RequestMessageBuilder builder(kRunMessageId, size); - - RunMessageParams_Data* params = nullptr; - Serialize(params_ptr, builder.buffer(), ¶ms, - 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( + params_ptr, &context); + RequestMessageBuilder builder(interface_control::kRunMessageId, size); + + interface_control::internal::RunMessageParams_Data* params = nullptr; + Serialize( + params_ptr, builder.buffer(), ¶ms, &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(params_ptr, context); - MessageBuilder builder(kRunOrClosePipeMessageId, size); - - RunOrClosePipeMessageParams_Data* params = nullptr; - Serialize(params_ptr, builder.buffer(), - ¶ms, 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( + params_ptr, builder.buffer(), ¶ms, &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& callback, - QueryVersionResultPtr query_version_result) { - callback.Run(query_version_result->version); +void RunVersionCallback( + const base::Callback& 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& 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 -#include "base/callback_forward.h" +#include + +#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& 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 #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::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 filter) { + filters_.emplace_back(std::move(filter)); } -} // namespace internal } // namespace mojo diff --git a/chromium/mojo/public/cpp/bindings/lib/filter_chain.h b/chromium/mojo/public/cpp/bindings/lib/filter_chain.h deleted file mode 100644 index 447be3d1368..00000000000 --- a/chromium/mojo/public/cpp/bindings/lib/filter_chain.h +++ /dev/null @@ -1,66 +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_LIB_FILTER_CHAIN_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_FILTER_CHAIN_H_ - -#include -#include - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/message_filter.h" - -namespace mojo { -namespace internal { - -class FilterChain { - public: - // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while - // this object is alive. - explicit FilterChain(MessageReceiver* sink = nullptr); - - FilterChain(FilterChain&& other); - FilterChain& operator=(FilterChain&& other); - ~FilterChain(); - - template - inline void Append(Args&&... args); - - // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while - // this object is alive. - void SetSink(MessageReceiver* sink); - - // Returns a receiver to accept messages. Messages flow through all filters in - // the same order as they were appended to the chain. If all filters allow a - // message to pass, it will be forwarded to |sink_|. - // The returned value is invalidated when this object goes away. - MessageReceiver* GetHead(); - - private: - // Owned by this object. - // TODO(dcheng): Use unique_ptr. - std::vector filters_; - - MessageReceiver* sink_; - - DISALLOW_COPY_AND_ASSIGN(FilterChain); -}; - -template -inline void FilterChain::Append(Args&&... args) { - FilterType* filter = new FilterType(std::forward(args)..., sink_); - if (!filters_.empty()) - filters_.back()->set_sink(filter); - filters_.push_back(filter); -} - -template <> -inline void FilterChain::Append() { -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_FILTER_CHAIN_H_ diff --git a/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/chromium/mojo/public/cpp/bindings/lib/fixed_buffer.cc 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 #include -#include - -#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(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(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 +#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(buf->Allocate(sizeof(int))); -// *a = 2; -// -// double* b = static_cast(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 + #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 -struct Serializer, +template +struct Serializer, AssociatedInterfacePtrInfo> { + static_assert(std::is_base_of::value, "Interface type mismatch."); + static void Serialize(AssociatedInterfacePtrInfo& input, AssociatedInterface_Data* output, SerializationContext* context) { @@ -41,9 +46,11 @@ struct Serializer, } }; -template -struct Serializer, +template +struct Serializer, AssociatedInterfaceRequest> { + static_assert(std::is_base_of::value, "Interface type mismatch."); + static void Serialize(AssociatedInterfaceRequest& input, AssociatedInterfaceRequest_Data* output, SerializationContext* context) { @@ -62,8 +69,10 @@ struct Serializer, } }; -template -struct Serializer, InterfacePtr> { +template +struct Serializer, InterfacePtr> { + static_assert(std::is_base_of::value, "Interface type mismatch."); + static void Serialize(InterfacePtr& input, Interface_Data* output, SerializationContext* context) { @@ -82,8 +91,10 @@ struct Serializer, InterfacePtr> { } }; -template -struct Serializer, InterfaceRequest> { +template +struct Serializer, InterfaceRequest> { + static_assert(std::is_base_of::value, "Interface type mismatch."); + static void Serialize(InterfaceRequest& 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 +#include +#include +#include + +#include "mojo/public/cpp/bindings/lib/template_util.h" + +namespace mojo { +namespace internal { + +template +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()(value) + (seed << 6) + (seed >> 2)); +} + +template +struct HasHashMethod { + template + static char Test(decltype(&U::Hash)); + template + static int Test(...); + static const bool value = sizeof(Test(0)) == sizeof(char); + + private: + EnsureTypeIsComplete check_t_; +}; + +template ::value> +struct HashTraits; + +template +size_t Hash(size_t seed, const T& value); + +template +struct HashTraits { + static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); } +}; + +template +struct HashTraits { + static size_t Hash(size_t seed, const T& value) { + return HashCombine(seed, value); + } +}; + +template +struct HashTraits, false> { + static size_t Hash(size_t seed, const std::vector& value) { + for (const auto& element : value) { + seed = HashCombine(seed, element); + } + return seed; + } +}; + +template +size_t Hash(size_t seed, const T& value) { + return HashTraits::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 payload_validator, + std::unique_ptr payload_validator, bool expect_sync_requests, - scoped_refptr runner) + scoped_refptr 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 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 sync_responder(responder); sync_responses_.insert(std::make_pair( - request_id, base::WrapUnique(new SyncResponseInfo(&response_received)))); + request_id, base::MakeUnique(&response_received))); base::WeakPtr 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 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 // For |std::swap()|. #include +#include #include #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 { void QueryVersion(const base::Callback& 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(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 { return; version_ = version; - // Do a static cast in case the interface contains methods with the same - // name. - static_cast(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 { 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 PassInterface() { @@ -135,6 +139,14 @@ class InterfacePtrState { 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 { filters.Append(Interface::Name_); filters.Append(); + // 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 { void QueryVersion(const base::Callback& 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(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 { return; version_ = version; - // Do a static cast in case the interface contains methods with the same - // name. - static_cast(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 { 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 PassInterface() { @@ -294,6 +308,14 @@ class InterfacePtrState { 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 { 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::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::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(DecodePointerRaw(&object->keys.offset)); - const ArrayHeader* value_header = static_cast( - 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> keys; Pointer> 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 #include -#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 { public: using Base = MapReaderBase; 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())); + GetNextResult GetNext() { + GetNextResult key = Traits::GetKey(this->iter_); Traits::AdvanceIterator(this->iter_); return key; } @@ -78,17 +81,17 @@ class MapValueReader : public MapReaderBase { }; template -struct Serializer, MaybeConstUserType> { +struct Serializer, MaybeConstUserType> { using UserType = typename std::remove_const::type; using Traits = MapTraits; using UserKey = typename Traits::Key; using UserValue = typename Traits::Value; - using Data = typename MojomTypeTraits>::Data; - using KeyArraySerializer = ArraySerializer, + using Data = typename MojomTypeTraits>::Data; + using KeyArraySerializer = ArraySerializer, std::vector, MapKeyReader>; using ValueArraySerializer = - ArraySerializer, + ArraySerializer, std::vector, MapValueReader>; @@ -122,22 +125,24 @@ struct Serializer, MaybeConstUserType> { auto result = Data::New(buf); if (result) { - result->keys.ptr = - MojomTypeTraits>::Data::New(Traits::GetSize(input), buf); - if (result->keys.ptr) { + auto keys_ptr = MojomTypeTraits>::Data::New( + Traits::GetSize(input), buf); + if (keys_ptr) { MapKeyReader 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>::Data::New(Traits::GetSize(input), buf); - if (result->values.ptr) { + auto values_ptr = MojomTypeTraits>::Data::New( + Traits::GetSize(input), buf); + if (values_ptr) { MapValueReader 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, MaybeConstUserType> { std::vector keys; std::vector 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 #include +#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> + g_tls_message_dispatch_context = LAZY_INSTANCE_INITIALIZER; + +base::LazyInstance> + 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::max()); - data_num_bytes_ = static_cast(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(data_num_bytes_)); - DCHECK_GT(bytes_claimed_ + static_cast(delta), bytes_claimed_); - - uint32_t new_bytes_claimed = bytes_claimed_ + static_cast(delta); - if (new_bytes_claimed > data_num_bytes_) { - NOTREACHED(); - return nullptr; - } - - char* start = static_cast(buffer_) + bytes_claimed_; - bytes_claimed_ = new_bytes_claimed; - return static_cast(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 #include #include @@ -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 #include +#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 +#include + +#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& GetBadMessageCallback(); + + private: + MessageDispatchContext* outer_context_; + Message* message_; + base::Callback 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 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() 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 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 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; scoped_refptr 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 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 header_validator = + base::MakeUnique(); + 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 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 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(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(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 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 #include +#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 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 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 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 +#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 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>(input->data, context); + return internal::PrepareToSerialize>(input->data, + context); } // static @@ -31,8 +32,8 @@ void UnmappedNativeStructSerializerImpl::Serialize( Array_Data* data = nullptr; const ContainerValidateParams params(0, false, nullptr); - internal::Serialize>(input->data, buffer, &data, ¶ms, - context); + internal::Serialize>(input->data, buffer, &data, + ¶ms, context); *output = reinterpret_cast(data); } @@ -44,7 +45,8 @@ bool UnmappedNativeStructSerializerImpl::Deserialize( Array_Data* data = reinterpret_cast*>(input); NativeStructPtr result(NativeStruct::New()); - if (!internal::Deserialize>(data, &result->data, context)) { + if (!internal::Deserialize>(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 : public UnmappedNativeStructSerializerImpl {}; template -struct Serializer +struct Serializer : public NativeStructSerializerImpl {}; } // 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( + internal::Deserialize( params, ¶ms_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( + internal::Serialize( params_ptr, builder.buffer(), ¶ms, 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 runner) + scoped_refptr 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 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 sync_responder(responder); sync_responses_.insert(std::make_pair( - request_id, base::WrapUnique(new SyncResponseInfo(&response_received)))); + request_id, base::MakeUnique(&response_received))); base::WeakPtr 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 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 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 weak_self = weak_factory_.GetWeakPtr(); while (!pending_messages_.empty()) { - std::unique_ptr 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 #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 runner); + scoped_refptr 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 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 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> pending_messages_; + std::queue 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 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::Data* data = nullptr; Serialize(*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 -bool StructDeserializeImpl(DataArrayType input, UserType* output) { +bool StructDeserializeImpl(const DataArrayType& input, UserType* output) { static_assert(BelongsTo::value, "Unexpected type."); - using DataType = typename MojomType::Struct::Data_; + using DataType = typename MojomTypeTraits::Data; if (input.is_null()) return false; - void* input_buffer = input.empty() ? nullptr : &input.front(); + void* input_buffer = + input.empty() + ? nullptr + : const_cast(reinterpret_cast(&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(input_buffer); - if (data) - data->DecodePointers(); - SerializationContext context; result = Deserialize(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 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 struct Serializer; +template +struct IsOptionalWrapper { + static const bool value = IsSpecializationOf< + base::Optional, + typename std::remove_const< + typename std::remove_reference::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 +template ::value>::type* = nullptr> size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { return Serializer::type>:: @@ -34,7 +49,11 @@ size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { std::forward(args)...); } -template +template ::value>::type* = nullptr> void Serialize(InputUserType&& input, Args&&... args) { Serializer::type>:: Serialize(std::forward(input), @@ -44,12 +63,60 @@ void Serialize(InputUserType&& input, Args&&... args) { template + typename... Args, + typename std::enable_if< + !IsOptionalWrapper::value>::type* = nullptr> bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { return Serializer::Deserialize( std::forward(input), output, std::forward(args)...); } +// Specialization that unwraps base::Optional<>. +template ::value>::type* = nullptr> +size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { + if (!input) + return 0; + return PrepareToSerialize(*input, std::forward(args)...); +} + +template ::value>::type* = nullptr> +void Serialize(InputUserType&& input, + Buffer* buffer, + DataType** output, + Args&&... args) { + if (!input) { + *output = nullptr; + return; + } + Serialize(*input, buffer, output, std::forward(args)...); +} + +template ::value>::type* = nullptr> +bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { + if (!input) { + *output = base::nullopt; + return true; + } + if (!*output) + output->emplace(); + return Deserialize(std::forward(input), &output->value(), + std::forward(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 -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(AlignImpl(reinterpret_cast(ptr))); -} - -bool IsAligned(const void* ptr) { - return !(reinterpret_cast(ptr) % kAlignment); -} - -void EncodePointer(const void* ptr, uint64_t* offset) { - if (!ptr) { - *offset = 0; - return; - } - - const char* p_obj = reinterpret_cast(ptr); - const char* p_slot = reinterpret_cast(offset); - DCHECK(p_obj > p_slot); - - *offset = static_cast(p_obj - p_slot); -} - -const void* DecodePointerRaw(const uint64_t* offset) { - if (!*offset) - return nullptr; - return reinterpret_cast(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(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 -inline void DecodePointer(const uint64_t* offset, T** ptr) { - *ptr = reinterpret_cast(const_cast(DecodePointerRaw(offset))); -} - -// The following 2 functions are used to encode/decode all objects (structs and -// arrays) in a consistent manner. - -template -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 -inline void Decode(T* obj) { - DecodePointer(&obj->offset, &obj->ptr); - if (obj->ptr) - obj->ptr->DecodePointers(); -} - -template -inline void AssociatedInterfacePtrInfoToData( - AssociatedInterfacePtrInfo input, - AssociatedInterface_Data* output) { - output->version = input.version(); - output->interface_id = input.PassHandle().release(); -} - -template -inline void AssociatedInterfaceDataToPtrInfo( - AssociatedInterface_Data* input, - AssociatedInterfacePtrInfo* output, - AssociatedGroupController* group_controller) { - output->set_handle(group_controller->CreateLocalEndpointHandle( - FetchAndReset(&input->interface_id))); - output->set_version(input->version); -} - -template -inline void InterfacePointerToData(InterfacePtr input, - Interface_Data* output, - SerializationContext* context) { - InterfacePtrInfo info = input.PassInterface(); - output->handle = context->handles.AddHandle(info.PassHandle().release()); - output->version = info.version(); -} - -template -inline void InterfaceDataToPointer(Interface_Data* input, - InterfacePtr* output, - SerializationContext* context) { - output->Bind(InterfacePtrInfo( - context->handles.TakeHandleAs(input->handle), - input->version)); -} - template struct HasIsNullMethod { template 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 -struct Serializer { +struct Serializer { using UserType = typename std::remove_const::type; using Traits = StringTraits; @@ -60,7 +60,7 @@ struct Serializer { SerializationContext* context) { if (!input) return CallSetToNullIfExists(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(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(context); #if DCHECK_IS_ON() - DCHECK_EQ(adaptor->original_size_in_bytes, - static_cast(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 - -#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 { - public: - // Returns a thread-local object. - static scoped_refptr current(); - - using HandleCallback = base::Callback; - 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; - - struct HandleHasher { - size_t operator()(const Handle& handle) const { - return std::hash()(static_cast(handle.value())); - } - }; - using HandleMap = std::unordered_map; - - 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 { typedef F type; }; -template -struct HasCloneMethod { - template - static char Test(decltype(&U::Clone)); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template ::value>::type* = nullptr> -T Clone(const T& input) { - return input.Clone(); -}; - -template ::value>::type* = nullptr> -T Clone(const T& input) { - return input; -} - -template -struct HasEqualsMethod { - template - static char Test(decltype(&U::Equals)); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template ::value>::type* = nullptr> -bool Equals(const T& a, const T& b) { - return a.Equals(b); -}; - -template ::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 -#include - #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(data)), data_end_(data_begin_ + data_num_bytes), handle_begin_(0), - handle_end_(static_cast(num_handles)) { + handle_end_(static_cast(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(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(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 #include +#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(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(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::max() && - (reinterpret_cast(offset) + - static_cast(*offset) >= - reinterpret_cast(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(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(message, - validation_context); - case kRunOrClosePipeMessageId: - return ValidateMessageIsRequestWithoutResponse(message, - validation_context) && - ValidateMessagePayload( - 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( - 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 +#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::max() && + (reinterpret_cast(offset) + + static_cast(*offset) >= + reinterpret_cast(offset)); +} + +template +bool ValidatePointer(const Pointer& 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 @@ -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 @@ -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 -bool ValidateArray(const Pointer>& input, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - if (!ValidateEncodedPointer(&input.offset)) { - ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER); - return false; - } - - return Array_Data::Validate(DecodePointerRaw(&input.offset), - validation_context, validate_params); -} - -template -bool ValidateMap(const Pointer& input, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - if (!ValidateEncodedPointer(&input.offset)) { - ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER); +bool ValidateContainer(const Pointer& 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 bool ValidateStruct(const Pointer& 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 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 bool ValidateNonInlinedUnion(const Pointer& 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 + +#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 +struct CloneTraits, false> { + static WTF::Vector Clone(const WTF::Vector& input) { + WTF::Vector result; + result.reserveCapacity(input.size()); + for (const auto& element : input) + result.append(internal::Clone(element)); + + return result; + } +}; + +template +struct CloneTraits, false> { + static WTF::HashMap Clone(const WTF::HashMap& input) { + WTF::HashMap 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 +struct EqualsTraits, false> { + static bool Equals(const WTF::Vector& a, const WTF::Vector& 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 +struct EqualsTraits, false> { + static bool Equals(const WTF::HashMap& a, const WTF::HashMap& 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 + +#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 +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()(value) + (seed << 6) + (seed >> 2)); +} + +template ::value> +struct WTFHashTraits; + +template +size_t WTFHash(size_t seed, const T& value); + +template +struct WTFHashTraits { + static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); } +}; + +template +struct WTFHashTraits { + static size_t Hash(size_t seed, const T& value) { + return WTFHashCombine(seed, value); + } +}; + +template <> +struct WTFHashTraits { + static size_t Hash(size_t seed, const WTF::String& value) { + return HashCombine(seed, WTF::StringHash::hash(value)); + } +}; + +template +size_t WTFHash(size_t seed, const T& value) { + return WTFHashTraits::Hash(seed, value); +} + +template +struct StructPtrHashFn { + static unsigned hash(const StructPtr& value) { + return value.Hash(kHashSeed); + } + static bool equal(const StructPtr& left, const StructPtr& right) { + return left.Equals(right); + } + static const bool safeToCompareToEmptyOrDeleted = false; +}; + +template +struct InlinedStructPtrHashFn { + static unsigned hash(const InlinedStructPtr& value) { + return value.Hash(kHashSeed); + } + static bool equal(const InlinedStructPtr& left, + const InlinedStructPtr& right) { + return left.Equals(right); + } + static const bool safeToCompareToEmptyOrDeleted = false; +}; + +} // namespace internal +} // namespace mojo + +namespace WTF { + +template +struct DefaultHash> { + using Hash = mojo::internal::StructPtrHashFn; +}; + +template +struct HashTraits> + : public GenericHashTraits> { + static const bool hasIsEmptyValueFunction = true; + static bool isEmptyValue(const mojo::StructPtr& value) { + return value.is_null(); + } + static void constructDeletedValue(mojo::StructPtr& slot, bool) { + mojo::internal::StructPtrWTFHelper::ConstructDeletedValue(slot); + } + static bool isDeletedValue(const mojo::StructPtr& value) { + return mojo::internal::StructPtrWTFHelper::IsHashTableDeletedValue( + value); + } +}; + +template +struct DefaultHash> { + using Hash = mojo::internal::InlinedStructPtrHashFn; +}; + +template +struct HashTraits> + : public GenericHashTraits> { + static const bool hasIsEmptyValueFunction = true; + static bool isEmptyValue(const mojo::InlinedStructPtr& value) { + return value.is_null(); + } + static void constructDeletedValue(mojo::InlinedStructPtr& slot, bool) { + mojo::internal::InlinedStructPtrWTFHelper::ConstructDeletedValue(slot); + } + static bool isDeletedValue(const mojo::InlinedStructPtr& 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 #include +#include #include #include "base/logging.h" @@ -135,14 +136,13 @@ class Map { const std::map& 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 after we move to MSVC 2015. std::map PassStorage() { is_null_ = true; return std::move(map_); } + operator const std::map&() const { return map_; } + // Swaps the contents of this Map with another Map of the same type (including // nullness). void Swap(Map* 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 +class MapDataView { + public: + using Data_ = typename internal::MojomTypeTraits>::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& keys() { return keys_; } + const ArrayDataView& keys() const { return keys_; } + + template + bool ReadKeys(U* output) { + return internal::Deserialize>(keys_.data_, output, + keys_.context_); + } + + ArrayDataView& values() { return values_; } + const ArrayDataView& values() const { return values_; } + + template + bool ReadValues(U* output) { + return internal::Deserialize>(values_.data_, output, + values_.context_); + } + + private: + ArrayDataView keys_; + ArrayDataView 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 // static bool Insert(CustomMap& input, -// const K& key, -// V&& value); -// static bool Insert(CustomMap& input, -// const K& key, -// const V& value); +// IK&& key, +// IV&& value); // // static void SetToEmpty(CustomMap* 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 +#include #include "mojo/public/cpp/bindings/map_traits.h" @@ -56,6 +57,53 @@ struct MapTraits> { static void SetToEmpty(std::map* output) { output->clear(); } }; +template +struct MapTraits> { + using Key = K; + using Value = V; + using Iterator = typename std::unordered_map::iterator; + using ConstIterator = typename std::unordered_map::const_iterator; + + static bool IsNull(const std::unordered_map& input) { + // std::unordered_map<> is always converted to non-null mojom map. + return false; + } + + static void SetToNull(std::unordered_map* output) { + // std::unordered_map<> doesn't support null state. Set it to empty instead. + output->clear(); + } + + static size_t GetSize(const std::unordered_map& input) { + return input.size(); + } + + static ConstIterator GetBegin(const std::unordered_map& input) { + return input.begin(); + } + static Iterator GetBegin(std::unordered_map& 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 + static bool Insert(std::unordered_map& input, IK&& key, IV&& value) { + input.insert( + std::make_pair(std::forward(key), std::forward(value))); + return true; + } + + static void SetToEmpty(std::unordered_map* 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 +struct MapTraits> { + using Key = K; + using Value = V; + using Iterator = typename WTF::HashMap::iterator; + using ConstIterator = typename WTF::HashMap::const_iterator; + + static bool IsNull(const WTF::HashMap& input) { + // WTF::HashMap<> is always converted to non-null mojom map. + return false; + } + + static void SetToNull(WTF::HashMap* output) { + // WTF::HashMap<> doesn't support null state. Set it to empty instead. + output->clear(); + } + + static size_t GetSize(const WTF::HashMap& input) { + return input.size(); + } + + static ConstIterator GetBegin(const WTF::HashMap& input) { + return input.begin(); + } + static Iterator GetBegin(WTF::HashMap& 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 + static bool Insert(WTF::HashMap& input, IK&& key, IV&& value) { + if (!WTF::HashMap::isValidKey(key)) { + LOG(ERROR) << "The key value is disallowed by WTF::HashMap"; + return false; + } + input.add(std::forward(key), std::forward(value)); + return true; + } + + static void SetToEmpty(WTF::HashMap* 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 #include +#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; + // 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* 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(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(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::max()); return static_cast(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 + +#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 + : public mojo::internal::EnumHashImpl {}; + +} // 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; // 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 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 +#include #include #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 { } // namespace mojo +namespace std { + +template <> +struct hash { + size_t operator()(const mojo::String& value) const { + return value.is_null() ? 0 : hash()(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 { +struct MOJO_CPP_BINDINGS_EXPORT StringTraits { 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 +#include #include #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 +class StrongBinding; + +template +using StrongBindingPtr = base::WeakPtr>; + // 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 request) -// : binding_(this, std::move(request)) {} +// To use, call StrongBinding::Create() (see below) or the helper +// MakeStrongBinding function: // -// // Foo implementation here +// mojo::MakeStrongBinding(base::MakeUnique(), +// std::move(foo_request)); // -// private: -// StrongBinding binding_; -// }; -// -// class MyFooFactory : public InterfaceFactory { -// public: -// void Create(..., InterfaceRequest 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 class StrongBinding { public: - explicit StrongBinding(Interface* impl) : binding_(impl) {} - - StrongBinding(Interface* impl, ScopedMessagePipeHandle handle) - : StrongBinding(impl) { - Bind(std::move(handle)); - } - - StrongBinding(Interface* impl, InterfacePtr* ptr) - : StrongBinding(impl) { - Bind(ptr); - } - - StrongBinding(Interface* impl, InterfaceRequest 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* ptr) { - DCHECK(!binding_.is_bound()); - binding_.Bind(ptr); - binding_.set_connection_error_handler( - base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this))); - } - - void Bind(InterfaceRequest 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 Create( + std::unique_ptr impl, + InterfaceRequest 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 impl, + InterfaceRequest 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 impl_; base::Closure connection_error_handler_; + ConnectionErrorWithReasonCallback connection_error_with_reason_handler_; Binding binding_; + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(StrongBinding); }; +template +StrongBindingPtr MakeStrongBinding( + std::unique_ptr impl, + InterfaceRequest request) { + return StrongBinding::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 #include #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 class StructHelper { public: @@ -23,6 +27,12 @@ class StructHelper { } }; +template +class StructPtrWTFHelper; + +template +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; - - // Forbid the == and != operators explicitly, otherwise StructPtr will be - // converted to Testable to do == or != comparison. - template - bool operator==(const StructPtr& other) const = delete; - template - bool operator!=(const StructPtr& other) const = delete; + friend class internal::StructPtrWTFHelper; void Initialize() { DCHECK(!ptr_); @@ -116,14 +124,23 @@ class StructPtr { DISALLOW_COPY_AND_ASSIGN(StructPtr); }; +template +bool operator==(const StructPtr& lhs, const StructPtr& rhs) { + return lhs.Equals(rhs); +} +template +bool operator!=(const StructPtr& lhs, const StructPtr& rhs) { + return !(lhs == rhs); +} + // Designed to be used when Struct is small and copyable. template 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; + friend class internal::InlinedStructPtrWTFHelper; - // Forbid the == and != operators explicitly, otherwise InlinedStructPtr will - // be converted to Testable to do == or != comparison. - template - bool operator==(const InlinedStructPtr& other) const = delete; - template - bool operator!=(const InlinedStructPtr& 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 +bool operator==(const InlinedStructPtr& lhs, + const InlinedStructPtr& rhs) { + return lhs.Equals(rhs); +} +template +bool operator!=(const InlinedStructPtr& lhs, + const InlinedStructPtr& rhs) { + return !(lhs == rhs); +} + +namespace internal { + +template +class StructPtrWTFHelper { + public: + static bool IsHashTableDeletedValue(const StructPtr& value) { + return value.ptr_ == reinterpret_cast(1u); + } + + static void ConstructDeletedValue(mojo::StructPtr& 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(); + slot.ptr_ = reinterpret_cast(1u); + } +}; + +template +class InlinedStructPtrWTFHelper { + public: + static bool IsHashTableDeletedValue(const InlinedStructPtr& value) { + return value.state_ == InlinedStructPtr::DELETED; + } + + static void ConstructDeletedValue(mojo::InlinedStructPtr& 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(); + slot.state_ = InlinedStructPtr::DELETED; + } +}; + +} // namespace internal } // namespace mojo +namespace std { + +template +struct hash> { + size_t operator()(const mojo::StructPtr& value) const { + return value.Hash(mojo::internal::kHashSeed); + } +}; + +template +struct hash> { + size_t operator()(const mojo::InlinedStructPtr& 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/WTF::Optional, 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 { +// struct StructTraits { // // 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 +template 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 { +class MOJO_CPP_BINDINGS_EXPORT SyncHandleRegistry + : public base::RefCounted { public: // Returns a thread-local object. static scoped_refptr 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[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[move_only,nullable_is_same_type]", + "mojo.test.UnionWithTraits=std::unique_ptr[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 +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 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 @@ -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 f_string_array; + array f_string_set; NestedStructWithTraits f_struct; array f_struct_array; map 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 f_bool_array; + array f_int32_array; + array f_enum_array; + array f_interface_array; + array> f_nested_array; + array f_struct_array; + array f_union_array; + map 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. +struct StringPairContainer { + array 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 f9; map f10; map f11; + // TODO(tibell): JS/Java don't support struct as key. + // map 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? param0, array? param1); Method16(map? param0); Method17(array param0); + Method18(UnionA? param0); + Method19(Recursive recursive); + Method20(map 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 @@ -113,6 +113,27 @@ var READ_DATA_FLAG_DISCARD; 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. @@ -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 @@ -65,6 +65,16 @@ define([ var decoded = structEncodeDecode(s); 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({ 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//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(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(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(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(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( 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( 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 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 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 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( 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( 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 {%- 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 + +#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 + +#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; + 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 + +#include +#include +#include +#include + +#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 -#include + #include #include #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 + 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 - 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 - 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 + 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 @@ -1,11 +1,6 @@ {%- import "validation_macros.tmpl" as validation_macros %} {%- set class_name = struct.name ~ "_Data" %} -// static -{{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) { - return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}(); -} - // static bool {{class_name}}::Validate( const void* data, @@ -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}}(); {%- 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 -struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType> { +struct Serializer<{{data_view}}, MaybeConstUserType> { using UserType = typename std::remove_const::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::TearDown(input, custom_context); @@ -73,7 +49,7 @@ struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType> { if (!input) return CallSetToNullIfExists(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_serialization_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl deleted file mode 100644 index 7421abcd787..00000000000 --- a/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl +++ /dev/null @@ -1,14 +0,0 @@ -{%- import "struct_macros.tmpl" as struct_macros %} -{%- set mojom_type = struct|get_qualified_name_for_kind %} - -// static -bool StructTraits<{{mojom_type}}, {{mojom_type}}Ptr>::Read( - {{mojom_type}}DataView input, - {{mojom_type}}Ptr* output) { - bool success = true; - {{mojom_type}}Ptr result({{mojom_type}}::New()); - {{struct_macros.deserialize(struct, "input", "result->%s", - "success")|indent(4)}} - *output = std::move(result); - return success; -} 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_traits_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_definition.tmpl new file mode 100644 index 00000000000..f84337f5bf4 --- /dev/null +++ b/chromium/mojo/public/tools/bindings/generators/cpp_templates/struct_traits_definition.tmpl @@ -0,0 +1,14 @@ +{%- import "struct_macros.tmpl" as struct_macros %} +{%- set mojom_type = struct|get_qualified_name_for_kind %} + +// static +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()); + {{struct_macros.deserialize(struct, "input", "result->%s", + "success")|indent(4)}} + *output = std::move(result); + return success; +} 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 + 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 + 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 + 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 @@ -2,25 +2,32 @@ {%- set class_name = union.name ~ "_Data" %} {%- 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(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 -struct UnionSerializerImpl; +template +struct Serializer<{{data_view}}, MaybeConstUserType> { + using UserType = typename std::remove_const::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(input)) + return size; + + void* custom_context = CustomContextHelper::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(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::GetNext(context); -template -struct Serializer<{{mojom_type}}Ptr, MaybeConstUserType> - : public UnionSerializerImpl<{{mojom_type}}Ptr> { - using UserType = typename std::remove_const::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::TearDown(input, custom_context); + } + + static bool Deserialize({{data_type}}* input, + UserType* output, + SerializationContext* context) { + if (!input || input->is_null()) + return CallSetToNullIfExists(output); - static_assert(std::is_same::value, - "Only support serialization of non-const Unions."); - static_assert(std::is_same::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}}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" if for_blink else "mojo::Array" %} template 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 - 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(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())); + } + @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>" % - GetCppType(kind.kind)) + GetCppFieldType(kind.kind)) if mojom.IsMapKind(kind): return ("mojo::internal::Pointer>" % - (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()) -- cgit v1.2.1