summaryrefslogtreecommitdiff
path: root/chromium/mojo
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/mojo
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
downloadqtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/mojo')
-rw-r--r--chromium/mojo/BUILD.gn17
-rw-r--r--chromium/mojo/README.md77
-rw-r--r--chromium/mojo/android/javatests/DEPS4
-rw-r--r--chromium/mojo/core/BUILD.gn325
-rw-r--r--chromium/mojo/core/DEPS (renamed from chromium/mojo/edk/DEPS)0
-rw-r--r--chromium/mojo/core/OWNERS (renamed from chromium/mojo/edk/system/OWNERS)0
-rw-r--r--chromium/mojo/core/atomic_flag.h (renamed from chromium/mojo/edk/system/atomic_flag.h)18
-rw-r--r--chromium/mojo/core/broker.h (renamed from chromium/mojo/edk/system/broker.h)27
-rw-r--r--chromium/mojo/core/broker_host.cc (renamed from chromium/mojo/edk/system/broker_host.cc)71
-rw-r--r--chromium/mojo/core/broker_host.h (renamed from chromium/mojo/edk/system/broker_host.h)35
-rw-r--r--chromium/mojo/core/broker_messages.h (renamed from chromium/mojo/edk/system/broker_messages.h)13
-rw-r--r--chromium/mojo/core/broker_posix.cc (renamed from chromium/mojo/edk/system/broker_posix.cc)75
-rw-r--r--chromium/mojo/core/broker_win.cc (renamed from chromium/mojo/edk/system/broker_win.cc)64
-rw-r--r--chromium/mojo/core/channel.cc (renamed from chromium/mojo/edk/system/channel.cc)198
-rw-r--r--chromium/mojo/core/channel.h (renamed from chromium/mojo/edk/system/channel.h)96
-rw-r--r--chromium/mojo/core/channel_fuchsia.cc (renamed from chromium/mojo/edk/system/channel_fuchsia.cc)149
-rw-r--r--chromium/mojo/core/channel_posix.cc (renamed from chromium/mojo/edk/system/channel_posix.cc)355
-rw-r--r--chromium/mojo/core/channel_unittest.cc (renamed from chromium/mojo/edk/system/channel_unittest.cc)47
-rw-r--r--chromium/mojo/core/channel_win.cc (renamed from chromium/mojo/edk/system/channel_win.cc)116
-rw-r--r--chromium/mojo/core/configuration.cc (renamed from chromium/mojo/edk/system/configuration.cc)6
-rw-r--r--chromium/mojo/core/configuration.h (renamed from chromium/mojo/edk/system/configuration.h)14
-rw-r--r--chromium/mojo/core/connection_params.cc31
-rw-r--r--chromium/mojo/core/connection_params.h49
-rw-r--r--chromium/mojo/core/core.cc (renamed from chromium/mojo/edk/system/core.cc)352
-rw-r--r--chromium/mojo/core/core.h (renamed from chromium/mojo/edk/system/core.h)87
-rw-r--r--chromium/mojo/core/core_test_base.cc (renamed from chromium/mojo/edk/system/core_test_base.cc)23
-rw-r--r--chromium/mojo/core/core_test_base.h (renamed from chromium/mojo/edk/system/core_test_base.h)12
-rw-r--r--chromium/mojo/core/core_unittest.cc (renamed from chromium/mojo/edk/system/core_unittest.cc)22
-rw-r--r--chromium/mojo/core/data_pipe_consumer_dispatcher.cc (renamed from chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc)40
-rw-r--r--chromium/mojo/core/data_pipe_consumer_dispatcher.h (renamed from chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h)23
-rw-r--r--chromium/mojo/core/data_pipe_control_message.cc (renamed from chromium/mojo/edk/system/data_pipe_control_message.cc)13
-rw-r--r--chromium/mojo/core/data_pipe_control_message.h (renamed from chromium/mojo/edk/system/data_pipe_control_message.h)13
-rw-r--r--chromium/mojo/core/data_pipe_producer_dispatcher.cc (renamed from chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc)42
-rw-r--r--chromium/mojo/core/data_pipe_producer_dispatcher.h (renamed from chromium/mojo/edk/system/data_pipe_producer_dispatcher.h)23
-rw-r--r--chromium/mojo/core/data_pipe_unittest.cc (renamed from chromium/mojo/edk/system/data_pipe_unittest.cc)12
-rw-r--r--chromium/mojo/core/dispatcher.cc (renamed from chromium/mojo/edk/system/dispatcher.cc)40
-rw-r--r--chromium/mojo/core/dispatcher.h (renamed from chromium/mojo/edk/system/dispatcher.h)59
-rw-r--r--chromium/mojo/core/embedder/BUILD.gn29
-rw-r--r--chromium/mojo/core/embedder/README.md86
-rw-r--r--chromium/mojo/core/embedder/configuration.h (renamed from chromium/mojo/edk/embedder/configuration.h)12
-rw-r--r--chromium/mojo/core/embedder/embedder.cc50
-rw-r--r--chromium/mojo/core/embedder/embedder.h65
-rw-r--r--chromium/mojo/core/embedder/process_error_callback.h (renamed from chromium/mojo/edk/embedder/process_error_callback.h)10
-rw-r--r--chromium/mojo/core/embedder/scoped_ipc_support.cc (renamed from chromium/mojo/edk/embedder/scoped_ipc_support.cc)13
-rw-r--r--chromium/mojo/core/embedder/scoped_ipc_support.h (renamed from chromium/mojo/edk/embedder/scoped_ipc_support.h)16
-rw-r--r--chromium/mojo/core/embedder_unittest.cc (renamed from chromium/mojo/edk/embedder/embedder_unittest.cc)219
-rw-r--r--chromium/mojo/core/entrypoints.cc (renamed from chromium/mojo/edk/embedder/entrypoints.cc)47
-rw-r--r--chromium/mojo/core/entrypoints.h (renamed from chromium/mojo/edk/embedder/entrypoints.h)12
-rw-r--r--chromium/mojo/core/export_only_thunks_api.lst (renamed from chromium/mojo/edk/export_only_thunks_api.lst)0
-rw-r--r--chromium/mojo/core/handle_signals_state.h (renamed from chromium/mojo/edk/system/handle_signals_state.h)17
-rw-r--r--chromium/mojo/core/handle_table.cc (renamed from chromium/mojo/edk/system/handle_table.cc)13
-rw-r--r--chromium/mojo/core/handle_table.h (renamed from chromium/mojo/edk/system/handle_table.h)28
-rw-r--r--chromium/mojo/core/handle_table_unittest.cc (renamed from chromium/mojo/edk/system/handle_table_unittest.cc)13
-rw-r--r--chromium/mojo/core/invitation_dispatcher.cc (renamed from chromium/mojo/edk/system/invitation_dispatcher.cc)8
-rw-r--r--chromium/mojo/core/invitation_dispatcher.h (renamed from chromium/mojo/edk/system/invitation_dispatcher.h)17
-rw-r--r--chromium/mojo/core/invitation_unittest.cc (renamed from chromium/mojo/edk/system/invitation_unittest.cc)370
-rw-r--r--chromium/mojo/core/mach_port_relay.cc (renamed from chromium/mojo/edk/system/mach_port_relay.cc)107
-rw-r--r--chromium/mojo/core/mach_port_relay.h (renamed from chromium/mojo/edk/system/mach_port_relay.h)40
-rw-r--r--chromium/mojo/core/message_pipe_dispatcher.cc (renamed from chromium/mojo/edk/system/message_pipe_dispatcher.cc)87
-rw-r--r--chromium/mojo/core/message_pipe_dispatcher.h (renamed from chromium/mojo/edk/system/message_pipe_dispatcher.h)40
-rw-r--r--chromium/mojo/core/message_pipe_perftest.cc (renamed from chromium/mojo/edk/system/message_pipe_perftest.cc)15
-rw-r--r--chromium/mojo/core/message_pipe_unittest.cc (renamed from chromium/mojo/edk/system/message_pipe_unittest.cc)35
-rw-r--r--chromium/mojo/core/message_unittest.cc (renamed from chromium/mojo/edk/system/message_unittest.cc)39
-rw-r--r--chromium/mojo/core/mojo_core.cc (renamed from chromium/mojo/edk/mojo_core.cc)8
-rw-r--r--chromium/mojo/core/mojo_core.def10
-rw-r--r--chromium/mojo/core/mojo_core_unittest.cc (renamed from chromium/mojo/edk/mojo_core_unittest.cc)0
-rw-r--r--chromium/mojo/core/multiprocess_message_pipe_unittest.cc (renamed from chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc)125
-rw-r--r--chromium/mojo/core/node_channel.cc (renamed from chromium/mojo/edk/system/node_channel.cc)257
-rw-r--r--chromium/mojo/core/node_channel.h (renamed from chromium/mojo/edk/system/node_channel.h)78
-rw-r--r--chromium/mojo/core/node_controller.cc (renamed from chromium/mojo/edk/system/node_controller.cc)311
-rw-r--r--chromium/mojo/core/node_controller.h (renamed from chromium/mojo/edk/system/node_controller.h)102
-rw-r--r--chromium/mojo/core/options_validation.h (renamed from chromium/mojo/edk/system/options_validation.h)12
-rw-r--r--chromium/mojo/core/options_validation_unittest.cc (renamed from chromium/mojo/edk/system/options_validation_unittest.cc)6
-rw-r--r--chromium/mojo/core/platform_handle_dispatcher.cc (renamed from chromium/mojo/edk/system/platform_handle_dispatcher.cc)29
-rw-r--r--chromium/mojo/core/platform_handle_dispatcher.h (renamed from chromium/mojo/edk/system/platform_handle_dispatcher.h)28
-rw-r--r--chromium/mojo/core/platform_handle_dispatcher_unittest.cc (renamed from chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc)31
-rw-r--r--chromium/mojo/core/platform_handle_in_transit.cc156
-rw-r--r--chromium/mojo/core/platform_handle_in_transit.h107
-rw-r--r--chromium/mojo/core/platform_handle_utils.cc67
-rw-r--r--chromium/mojo/core/platform_handle_utils.h35
-rw-r--r--chromium/mojo/core/platform_shared_memory_mapping.cc (renamed from chromium/mojo/edk/system/platform_shared_memory_mapping.cc)6
-rw-r--r--chromium/mojo/core/platform_shared_memory_mapping.h (renamed from chromium/mojo/edk/system/platform_shared_memory_mapping.h)12
-rw-r--r--chromium/mojo/core/platform_wrapper_unittest.cc (renamed from chromium/mojo/edk/system/platform_wrapper_unittest.cc)17
-rw-r--r--chromium/mojo/core/ports/BUILD.gn (renamed from chromium/mojo/edk/system/ports/BUILD.gn)4
-rw-r--r--chromium/mojo/core/ports/event.cc (renamed from chromium/mojo/edk/system/ports/event.cc)14
-rw-r--r--chromium/mojo/core/ports/event.h (renamed from chromium/mojo/edk/system/ports/event.h)30
-rw-r--r--chromium/mojo/core/ports/message_filter.h (renamed from chromium/mojo/edk/system/ports/message_filter.h)10
-rw-r--r--chromium/mojo/core/ports/message_queue.cc (renamed from chromium/mojo/edk/system/ports/message_queue.cc)11
-rw-r--r--chromium/mojo/core/ports/message_queue.h (renamed from chromium/mojo/edk/system/ports/message_queue.h)23
-rw-r--r--chromium/mojo/core/ports/name.cc (renamed from chromium/mojo/edk/system/ports/name.cc)6
-rw-r--r--chromium/mojo/core/ports/name.h (renamed from chromium/mojo/edk/system/ports/name.h)30
-rw-r--r--chromium/mojo/core/ports/name_unittest.cc (renamed from chromium/mojo/edk/system/ports/name_unittest.cc)6
-rw-r--r--chromium/mojo/core/ports/node.cc (renamed from chromium/mojo/edk/system/ports/node.cc)15
-rw-r--r--chromium/mojo/core/ports/node.h (renamed from chromium/mojo/edk/system/ports/node.h)24
-rw-r--r--chromium/mojo/core/ports/node_delegate.h (renamed from chromium/mojo/edk/system/ports/node_delegate.h)16
-rw-r--r--chromium/mojo/core/ports/port.cc (renamed from chromium/mojo/edk/system/ports/port.cc)6
-rw-r--r--chromium/mojo/core/ports/port.h (renamed from chromium/mojo/edk/system/ports/port.h)16
-rw-r--r--chromium/mojo/core/ports/port_locker.cc (renamed from chromium/mojo/edk/system/ports/port_locker.cc)8
-rw-r--r--chromium/mojo/core/ports/port_locker.h (renamed from chromium/mojo/edk/system/ports/port_locker.h)12
-rw-r--r--chromium/mojo/core/ports/port_ref.cc (renamed from chromium/mojo/edk/system/ports/port_ref.cc)14
-rw-r--r--chromium/mojo/core/ports/port_ref.h (renamed from chromium/mojo/edk/system/ports/port_ref.h)14
-rw-r--r--chromium/mojo/core/ports/ports_unittest.cc (renamed from chromium/mojo/edk/system/ports/ports_unittest.cc)12
-rw-r--r--chromium/mojo/core/ports/user_data.h (renamed from chromium/mojo/edk/system/ports/user_data.h)10
-rw-r--r--chromium/mojo/core/ports/user_message.cc (renamed from chromium/mojo/edk/system/ports/user_message.cc)10
-rw-r--r--chromium/mojo/core/ports/user_message.h (renamed from chromium/mojo/edk/system/ports/user_message.h)16
-rw-r--r--chromium/mojo/core/quota_unittest.cc314
-rw-r--r--chromium/mojo/core/request_context.cc (renamed from chromium/mojo/edk/system/request_context.cc)16
-rw-r--r--chromium/mojo/core/request_context.h (renamed from chromium/mojo/edk/system/request_context.h)19
-rw-r--r--chromium/mojo/core/run_all_core_unittests.cc (renamed from chromium/mojo/edk/run_all_core_unittests.cc)0
-rw-r--r--chromium/mojo/core/scoped_process_handle.cc90
-rw-r--r--chromium/mojo/core/scoped_process_handle.h (renamed from chromium/mojo/edk/system/scoped_process_handle.h)40
-rw-r--r--chromium/mojo/core/shared_buffer_dispatcher.cc (renamed from chromium/mojo/edk/system/shared_buffer_dispatcher.cc)56
-rw-r--r--chromium/mojo/core/shared_buffer_dispatcher.h (renamed from chromium/mojo/edk/system/shared_buffer_dispatcher.h)19
-rw-r--r--chromium/mojo/core/shared_buffer_dispatcher_unittest.cc (renamed from chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc)30
-rw-r--r--chromium/mojo/core/shared_buffer_unittest.cc (renamed from chromium/mojo/edk/system/shared_buffer_unittest.cc)11
-rw-r--r--chromium/mojo/core/signals_unittest.cc (renamed from chromium/mojo/edk/system/signals_unittest.cc)26
-rw-r--r--chromium/mojo/core/system_impl_export.h (renamed from chromium/mojo/edk/system/system_impl_export.h)10
-rw-r--r--chromium/mojo/core/test/BUILD.gn (renamed from chromium/mojo/edk/test/BUILD.gn)14
-rw-r--r--chromium/mojo/core/test_utils.cc (renamed from chromium/mojo/edk/system/test_utils.cc)12
-rw-r--r--chromium/mojo/core/test_utils.h (renamed from chromium/mojo/edk/system/test_utils.h)10
-rw-r--r--chromium/mojo/core/trap_unittest.cc1763
-rw-r--r--chromium/mojo/core/user_message_impl.cc (renamed from chromium/mojo/edk/system/user_message_impl.cc)47
-rw-r--r--chromium/mojo/core/user_message_impl.h (renamed from chromium/mojo/edk/system/user_message_impl.h)26
-rw-r--r--chromium/mojo/core/watch.cc (renamed from chromium/mojo/edk/system/watch.cc)10
-rw-r--r--chromium/mojo/core/watch.h (renamed from chromium/mojo/edk/system/watch.h)14
-rw-r--r--chromium/mojo/core/watcher_dispatcher.cc (renamed from chromium/mojo/edk/system/watcher_dispatcher.cc)36
-rw-r--r--chromium/mojo/core/watcher_dispatcher.h (renamed from chromium/mojo/edk/system/watcher_dispatcher.h)22
-rw-r--r--chromium/mojo/core/watcher_set.cc (renamed from chromium/mojo/edk/system/watcher_set.cc)6
-rw-r--r--chromium/mojo/core/watcher_set.h (renamed from chromium/mojo/edk/system/watcher_set.h)14
-rw-r--r--chromium/mojo/edk/BUILD.gn304
-rw-r--r--chromium/mojo/edk/embedder/BUILD.gn27
-rw-r--r--chromium/mojo/edk/embedder/README.md325
-rw-r--r--chromium/mojo/edk/embedder/connection_params.cc33
-rw-r--r--chromium/mojo/edk/embedder/connection_params.h42
-rw-r--r--chromium/mojo/edk/embedder/embedder.cc80
-rw-r--r--chromium/mojo/edk/embedder/embedder.h90
-rw-r--r--chromium/mojo/edk/embedder/incoming_broker_client_invitation.cc50
-rw-r--r--chromium/mojo/edk/embedder/incoming_broker_client_invitation.h58
-rw-r--r--chromium/mojo/edk/embedder/named_platform_channel_pair.cc101
-rw-r--r--chromium/mojo/edk/embedder/named_platform_channel_pair.h78
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle.h16
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_posix.h29
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_utils.h56
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_utils_fuchsia.cc28
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc141
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_utils_win.cc95
-rw-r--r--chromium/mojo/edk/embedder/named_platform_handle_win.h34
-rw-r--r--chromium/mojo/edk/embedder/outgoing_broker_client_invitation.cc65
-rw-r--r--chromium/mojo/edk/embedder/outgoing_broker_client_invitation.h93
-rw-r--r--chromium/mojo/edk/embedder/peer_connection.cc31
-rw-r--r--chromium/mojo/edk/embedder/peer_connection.h54
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_pair.cc40
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_pair.h118
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_pair_fuchsia.cc96
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_pair_posix.cc173
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc257
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_pair_win.cc122
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_utils_posix.cc250
-rw-r--r--chromium/mojo/edk/embedder/platform_channel_utils_posix.h79
-rw-r--r--chromium/mojo/edk/embedder/platform_handle.cc109
-rw-r--r--chromium/mojo/edk/embedder/platform_handle.h126
-rw-r--r--chromium/mojo/edk/embedder/platform_handle_utils.cc149
-rw-r--r--chromium/mojo/edk/embedder/platform_handle_utils.h63
-rw-r--r--chromium/mojo/edk/embedder/platform_handle_utils_fuchsia.cc24
-rw-r--r--chromium/mojo/edk/embedder/platform_handle_utils_posix.cc25
-rw-r--r--chromium/mojo/edk/embedder/platform_handle_utils_win.cc29
-rw-r--r--chromium/mojo/edk/embedder/scoped_platform_handle.h65
-rw-r--r--chromium/mojo/edk/embedder/transport_protocol.h47
-rw-r--r--chromium/mojo/edk/system/BUILD.gn76
-rw-r--r--chromium/mojo/edk/system/scoped_process_handle.cc45
-rw-r--r--chromium/mojo/edk/system/trap_unittest.cc1868
-rw-r--r--chromium/mojo/public/c/system/README.md300
-rw-r--r--chromium/mojo/public/c/system/core.h1
-rw-r--r--chromium/mojo/public/c/system/functions.h8
-rw-r--r--chromium/mojo/public/c/system/invitation.h45
-rw-r--r--chromium/mojo/public/c/system/macros.h15
-rw-r--r--chromium/mojo/public/c/system/quota.h126
-rw-r--r--chromium/mojo/public/c/system/thunks.cc289
-rw-r--r--chromium/mojo/public/c/system/thunks.h15
-rw-r--r--chromium/mojo/public/c/system/trap.h68
-rw-r--r--chromium/mojo/public/c/system/types.h13
-rw-r--r--chromium/mojo/public/cpp/base/BUILD.gn4
-rw-r--r--chromium/mojo/public/cpp/base/file_info.typemap5
-rw-r--r--chromium/mojo/public/cpp/base/file_info_mojom_traits.cc28
-rw-r--r--chromium/mojo/public/cpp/base/file_info_mojom_traits.h49
-rw-r--r--chromium/mojo/public/cpp/base/file_mojom_traits.cc2
-rw-r--r--chromium/mojo/public/cpp/base/file_mojom_traits.h1
-rw-r--r--chromium/mojo/public/cpp/base/file_unittest.cc20
-rw-r--r--chromium/mojo/public/cpp/base/logfont_win.typemap14
-rw-r--r--chromium/mojo/public/cpp/base/logfont_win_mojom_traits.cc39
-rw-r--r--chromium/mojo/public/cpp/base/logfont_win_mojom_traits.h30
-rw-r--r--chromium/mojo/public/cpp/base/time.typemap5
-rw-r--r--chromium/mojo/public/cpp/base/time_mojom_traits.h6
-rw-r--r--chromium/mojo/public/cpp/bindings/BUILD.gn14
-rw-r--r--chromium/mojo/public/cpp/bindings/README.md180
-rw-r--r--chromium/mojo/public/cpp/bindings/connector.h7
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_endpoint_client.h1
-rw-r--r--chromium/mojo/public/cpp/bindings/interface_ptr.h12
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/connector.cc20
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc48
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h3
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc4
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h5
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message.cc8
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/message_dumper.cc96
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc25
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/multiplex_router.h2
-rw-r--r--chromium/mojo/public/cpp/bindings/lib/unserialized_message_context.cc1
-rw-r--r--chromium/mojo/public/cpp/bindings/message.h15
-rw-r--r--chromium/mojo/public/cpp/bindings/message_dumper.h43
-rw-r--r--chromium/mojo/public/cpp/bindings/sync_call_restrictions.h16
-rw-r--r--chromium/mojo/public/cpp/bindings/tests/BUILD.gn6
-rw-r--r--chromium/mojo/public/cpp/platform/BUILD.gn13
-rw-r--r--chromium/mojo/public/cpp/platform/DEPS1
-rw-r--r--chromium/mojo/public/cpp/platform/README.md75
-rw-r--r--chromium/mojo/public/cpp/platform/named_platform_channel.cc17
-rw-r--r--chromium/mojo/public/cpp/platform/named_platform_channel.h6
-rw-r--r--chromium/mojo/public/cpp/platform/named_platform_channel_win.cc1
-rw-r--r--chromium/mojo/public/cpp/platform/platform_channel.cc49
-rw-r--r--chromium/mojo/public/cpp/platform/platform_channel.h17
-rw-r--r--chromium/mojo/public/cpp/platform/platform_handle.cc147
-rw-r--r--chromium/mojo/public/cpp/platform/platform_handle.h90
-rw-r--r--chromium/mojo/public/cpp/platform/socket_utils_posix.cc194
-rw-r--r--chromium/mojo/public/cpp/platform/socket_utils_posix.h80
-rw-r--r--chromium/mojo/public/cpp/system/BUILD.gn4
-rw-r--r--chromium/mojo/public/cpp/system/README.md166
-rw-r--r--chromium/mojo/public/cpp/system/handle_signals_state.h5
-rw-r--r--chromium/mojo/public/cpp/system/invitation.cc286
-rw-r--r--chromium/mojo/public/cpp/system/invitation.h186
-rw-r--r--chromium/mojo/public/cpp/system/isolated_connection.cc41
-rw-r--r--chromium/mojo/public/cpp/system/isolated_connection.h60
-rw-r--r--chromium/mojo/public/cpp/system/platform_handle.cc81
-rw-r--r--chromium/mojo/public/cpp/system/platform_handle.h19
-rw-r--r--chromium/mojo/public/cpp/system/simple_watcher.cc29
-rw-r--r--chromium/mojo/public/cpp/system/tests/BUILD.gn7
-rw-r--r--chromium/mojo/public/cpp/system/wait.cc36
-rw-r--r--chromium/mojo/public/cpp/system/wait_set.cc35
-rw-r--r--chromium/mojo/public/java/BUILD.gn3
-rw-r--r--chromium/mojo/public/java/system/BUILD.gn (renamed from chromium/mojo/android/BUILD.gn)83
-rw-r--r--chromium/mojo/public/java/system/DEPS (renamed from chromium/mojo/android/DEPS)0
-rw-r--r--chromium/mojo/public/java/system/base_run_loop.cc (renamed from chromium/mojo/android/system/base_run_loop.cc)3
-rw-r--r--chromium/mojo/public/java/system/core_impl.cc (renamed from chromium/mojo/android/system/core_impl.cc)0
-rw-r--r--chromium/mojo/public/java/system/javatests/AndroidManifest.xml (renamed from chromium/mojo/android/javatests/AndroidManifest.xml)0
-rw-r--r--chromium/mojo/public/java/system/javatests/DEPS3
-rw-r--r--chromium/mojo/public/java/system/javatests/apk/.empty (renamed from chromium/mojo/android/javatests/apk/.empty)0
-rw-r--r--chromium/mojo/public/java/system/javatests/init_library.cc (renamed from chromium/mojo/android/javatests/init_library.cc)4
-rw-r--r--chromium/mojo/public/java/system/javatests/mojo_test_rule.cc (renamed from chromium/mojo/android/javatests/mojo_test_rule.cc)6
-rw-r--r--chromium/mojo/public/java/system/javatests/validation_test_util.cc (renamed from chromium/mojo/android/javatests/validation_test_util.cc)4
-rw-r--r--chromium/mojo/public/java/system/watcher_impl.cc (renamed from chromium/mojo/android/system/watcher_impl.cc)4
-rw-r--r--chromium/mojo/public/js/lib/unicode.js16
-rw-r--r--chromium/mojo/public/mojom/base/file.mojom1
-rw-r--r--chromium/mojo/public/mojom/base/file_info.mojom13
-rw-r--r--chromium/mojo/public/mojom/base/logfont_win.mojom6
-rw-r--r--chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni1
-rw-r--r--chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni6
-rw-r--r--chromium/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl16
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/externs/interface_definition.tmpl20
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/externs/module.externs.tmpl17
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/fuzzing.tmpl4
-rw-r--r--chromium/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl4
-rw-r--r--chromium/mojo/public/tools/bindings/mojom.gni2
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py23
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py18
-rw-r--r--chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py5
-rw-r--r--chromium/mojo/public/tools/fuzzers/BUILD.gn7
-rw-r--r--chromium/mojo/public/tools/fuzzers/DEPS2
-rw-r--r--chromium/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc4
-rw-r--r--chromium/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc4
-rw-r--r--chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc4
269 files changed, 8645 insertions, 8708 deletions
diff --git a/chromium/mojo/BUILD.gn b/chromium/mojo/BUILD.gn
index b0ad79f3e8d..f6cd5b6c6ca 100644
--- a/chromium/mojo/BUILD.gn
+++ b/chromium/mojo/BUILD.gn
@@ -17,7 +17,7 @@ group("mojo") {
}
if (is_android) {
- deps += [ "//mojo/android" ]
+ deps += [ "//mojo/public/java/system" ]
}
deps += [ "//services/service_manager:all" ]
@@ -35,8 +35,8 @@ group("tests") {
test("mojo_unittests") {
deps = [
- "//mojo/edk/system:test_sources",
- "//mojo/edk/test:run_all_unittests",
+ "//mojo/core:test_sources",
+ "//mojo/core/test:run_all_unittests",
"//mojo/public/cpp/base:tests",
"//mojo/public/cpp/bindings/tests",
"//mojo/public/cpp/platform/tests",
@@ -46,22 +46,23 @@ test("mojo_unittests") {
test("mojo_perftests") {
deps = [
- "//mojo/edk/test:run_all_perftests",
- "//mojo/edk/test:test_support",
+ "//mojo/core/test:run_all_perftests",
+ "//mojo/core/test:test_support",
"//mojo/public/c/system/tests:perftests",
"//mojo/public/cpp/bindings/tests:perftests",
]
if (!is_ios) {
sources = [
- "//mojo/edk/system/message_pipe_perftest.cc",
+ "//mojo/core/message_pipe_perftest.cc",
]
deps += [
"//base",
"//base/test:test_support",
- "//mojo/edk",
- "//mojo/edk/system:test_utils",
+ "//mojo/core:embedder_internal",
+ "//mojo/core:test_utils",
+ "//mojo/core/embedder",
"//testing/gtest",
]
}
diff --git a/chromium/mojo/README.md b/chromium/mojo/README.md
index 20852f12bde..46d14fa4c3b 100644
--- a/chromium/mojo/README.md
+++ b/chromium/mojo/README.md
@@ -19,42 +19,73 @@ out [Converting Legacy Chrome IPC To Mojo](/ipc/README.md).
## System Overview
-Mojo is a layered collection of runtime libraries providing a platform-agnostic
+Mojo is a collection of runtime libraries providing a platform-agnostic
abstraction of common IPC primitives, a message IDL format, and a bindings
library with code generation for multiple target languages to facilitate
convenient message passing across arbitrary inter- and intra-process boundaries.
-The documentation here is segmented according to the different isolated layers
-and libraries comprising the system. The basic hierarchy of features is as
-follows:
+The documentation here is segmented according to the different libraries
+comprising Mojo. The basic hierarchy of features is as follows:
-![Mojo Library Layering: EDK on bottom, different language bindings on top, public system support APIs in the middle](https://docs.google.com/drawings/d/1RwhzKblXUZw-zhy_KDVobAYprYSqxZzopXTUsbwzDPw/pub?w=570&h=324)
+![Mojo Library Layering: Core on bottom, language bindings on top, public system support APIs in the middle](https://docs.google.com/drawings/d/1RwhzKblXUZw-zhy_KDVobAYprYSqxZzopXTUsbwzDPw/pub?w=570&h=324)
-## Embedder Development Kit (EDK)
-Every process to be interconnected via Mojo IPC is called a **Mojo embedder**
-and needs to embed the
-[**Embedder Development Kit (EDK)**](/mojo/edk/embedder/README.md) library. The
-EDK exposes the means for an embedder to physically connect one process to another
-using any supported native IPC primitive (*e.g.,* a UNIX domain socket or
-Windows named pipe) on the host platform.
+## Mojo Core
+In order to use any of the more interesting high-level support libraries like
+the System APIs or Bindings APIs, a process must first initialize Mojo Core.
+This is a one-time initialization which remains active for the remainder of the
+process's lifetime. There are two ways to initialize Mojo Core: via the Embedder
+API, or through a dynamically linked library.
-Details regarding where and how an application process actually embeds and
-configures the EDK are generaly hidden from the rest of the application code,
-and applications instead use the public System and Bindings APIs to get things
-done within processes that embed Mojo.
+### Embedding
+Many processes to be interconnected via Mojo are **embedders**, meaning that
+they statically link against the `//mojo/core/embedder` target and initialize
+Mojo support within each process by calling `mojo::core::Init()`. See
+[**Mojo Core Embedder API**](/mojo/core/embedder/README.md) for more details.
+
+This is a reasonable option when you can guarantee that all interconnected
+process binaries are linking against precisely the same revision of Mojo Core.
+To support other scenarios, use dynamic linking.
+
+## Dynamic Linking
+On some platforms, it's also possible for applications to rely on a
+dynamically-linked Mojo Core library (`libmojo_core.so` or `mojo_core.dll`)
+instead of statically linking against Mojo Core.
+
+In order to take advantage of this mechanism, the corresponding library must be
+present in either:
+
+ - The working directory of the application
+ - A directory named by the `MOJO_CORE_LIBRARY_PATH` environment variable
+ - A directory named explicitly by the application at runtime
+
+Instead of calling `mojo::core::Init()` as embedders do, an application using
+dynamic Mojo Core instead calls `MojoInitialize()` from the C System API. This
+call will attempt to locate (see above) and load a Mojo Core library to support
+subsequent Mojo API usage within the process.
+
+Note that the Mojo Core shared library presents a stable, forward-compatible C
+ABI which can support all current and future versions of the higher-level,
+public (and not binary-stable) System and Bindings APIs.
## C System API
-Once the EDK is initialized within a process, the public
+Once Mojo is initialized within a process, the public
[**C System API**](/mojo/public/c/system/README.md) is usable on any thread for
the remainder of the process's lifetime. This is a lightweight API with a
-relatively small (and eventually stable) ABI. Typically this API is not used
-directly, but it is the foundation upon which all remaining upper layers are
-built. It exposes the fundamental capabilities to create and interact with
-various types of Mojo handles including **message pipes**, **data pipes**, and
-**shared buffers**.
+relatively small, stable, forward-compatible ABI, comprising the total public
+API surface of the Mojo Core library.
-## High-Level System APIs
+This API is rarely used directly, but it is the foundation upon which all
+higher-level Mojo APIs are built. It exposes the fundamental capabilities to
+create and interact Mojo primitives like **message pipes**, **data pipes**, and
+**shared buffers**, as well as APIs to help bootstrap connections among
+processes.
+## Platform Support API
+Mojo provides a small collection of abstractions around platform-specific IPC
+primitives to facilitate bootstrapping Mojo IPC between two processes. See the
+[Platform API](/mojo/public/cpp/platform/README.md) documentation for details.
+
+## High-Level System APIs
There is a relatively small, higher-level system API for each supported
language, built upon the low-level C API. Like the C API, direct usage of these
system APIs is rare compared to the bindings APIs, but it is sometimes desirable
diff --git a/chromium/mojo/android/javatests/DEPS b/chromium/mojo/android/javatests/DEPS
deleted file mode 100644
index 78cf465ca0c..00000000000
--- a/chromium/mojo/android/javatests/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- # out should be allowed by default, but bots are failing on this.
- "+out",
-]
diff --git a/chromium/mojo/core/BUILD.gn b/chromium/mojo/core/BUILD.gn
new file mode 100644
index 00000000000..49a537bcb74
--- /dev/null
+++ b/chromium/mojo/core/BUILD.gn
@@ -0,0 +1,325 @@
+# Copyright 2018 The Chromium 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/config/nacl/config.gni")
+import("//testing/test.gni")
+
+component("embedder_internal") {
+ output_name = "mojo_core_embedder_internal"
+ public_deps = [
+ ":impl_for_embedder",
+ ]
+ visibility = [
+ ":test_sources",
+ "//mojo:*",
+ "//mojo/core/embedder",
+ ]
+}
+
+# Bits of the EDK library which do not depend on public API linkage. It is
+# not allowed for this target or any of its transitive dependencies to depend
+# on anything under //mojo/public beyond strict C type definitions.
+#
+# This is templated because it's consumed by both the ":embedder_internal"
+# component library as well as the ":mojo_core" shared library. In the former
+# case we want to export symbols, but in the latter case we don't. The template
+# stamps out two nearly identical targets which differ only in what symbols they
+# export.
+template("core_impl_source_set") {
+ source_set(target_name) {
+ if (invoker.for_shared_library) {
+ visibility = [ ":shared_library" ]
+ } else {
+ visibility = [ ":embedder_internal" ]
+ }
+
+ public = [
+ "channel.h",
+ "configuration.h",
+ "connection_params.h",
+ "core.h",
+ "data_pipe_consumer_dispatcher.h",
+ "data_pipe_control_message.h",
+ "data_pipe_producer_dispatcher.h",
+ "dispatcher.h",
+ "embedder/configuration.h",
+ "embedder/process_error_callback.h",
+ "entrypoints.h",
+ "handle_signals_state.h",
+ "handle_table.h",
+ "invitation_dispatcher.h",
+ "message_pipe_dispatcher.h",
+ "node_controller.h",
+ "options_validation.h",
+ "platform_handle_dispatcher.h",
+ "platform_handle_utils.h",
+ "platform_shared_memory_mapping.h",
+ "request_context.h",
+ "scoped_process_handle.h",
+ "shared_buffer_dispatcher.h",
+ "user_message_impl.h",
+ ]
+
+ sources = [
+ "atomic_flag.h",
+ "broker.h",
+ "broker_win.cc",
+ "channel.cc",
+ "channel_win.cc",
+ "configuration.cc",
+ "connection_params.cc",
+ "core.cc",
+ "data_pipe_consumer_dispatcher.cc",
+ "data_pipe_control_message.cc",
+ "data_pipe_producer_dispatcher.cc",
+ "dispatcher.cc",
+ "entrypoints.cc",
+ "handle_table.cc",
+ "invitation_dispatcher.cc",
+ "message_pipe_dispatcher.cc",
+ "node_channel.cc",
+ "node_channel.h",
+ "node_controller.cc",
+ "platform_handle_dispatcher.cc",
+ "platform_handle_in_transit.cc",
+ "platform_handle_in_transit.h",
+ "platform_handle_utils.cc",
+ "platform_shared_memory_mapping.cc",
+ "request_context.cc",
+ "scoped_process_handle.cc",
+ "shared_buffer_dispatcher.cc",
+ "user_message_impl.cc",
+ "watch.cc",
+ "watch.h",
+ "watcher_dispatcher.cc",
+ "watcher_dispatcher.h",
+ "watcher_set.cc",
+ "watcher_set.h",
+ ]
+
+ public_deps = [
+ "//base",
+ "//mojo/core/ports",
+ "//mojo/public/c/system:headers",
+ "//mojo/public/cpp/platform",
+ ]
+
+ if (is_fuchsia) {
+ sources += [ "channel_fuchsia.cc" ]
+
+ public_deps += [ "//third_party/fuchsia-sdk:fdio" ]
+ }
+
+ if (is_posix) {
+ if (!is_nacl || is_nacl_nonsfi) {
+ sources += [
+ "broker_posix.cc",
+ "channel_posix.cc",
+ ]
+ }
+ }
+
+ if (is_mac && !is_ios) {
+ sources += [
+ "mach_port_relay.cc",
+ "mach_port_relay.h",
+ ]
+ }
+
+ if (!is_nacl || is_nacl_nonsfi) {
+ sources += [
+ "broker_host.cc",
+ "broker_host.h",
+ ]
+ }
+
+ defines = []
+ if (invoker.for_shared_library) {
+ defines += [ "MOJO_CORE_SHARED_LIBRARY" ]
+ } else {
+ defines += [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
+ }
+
+ deps = []
+ if (is_android) {
+ deps += [ "//third_party/ashmem" ]
+ }
+ if (!is_nacl) {
+ deps += [ "//crypto" ]
+ }
+
+ if (is_win) {
+ cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()),
+ # which is uninteresting.
+ }
+
+ # Use target_os == "chromeos" instead of is_chromeos because we need to
+ # build NaCl targets (i.e. IRT) for ChromeOS the same as the rest of ChromeOS.
+ if (is_android || target_os == "chromeos") {
+ defines += [ "MOJO_CORE_LEGACY_PROTOCOL" ]
+ }
+ }
+}
+
+core_impl_source_set("impl_for_embedder") {
+ for_shared_library = false
+}
+
+if (is_chromeos || is_linux || is_android || is_win) {
+ core_impl_source_set("impl_for_shared_library") {
+ for_shared_library = true
+ }
+
+ shared_library("shared_library") {
+ output_name = "mojo_core"
+ sources = [
+ "mojo_core.cc",
+ ]
+ defines = [ "MOJO_CORE_SHARED_LIBRARY" ]
+ deps = [
+ ":impl_for_shared_library",
+ "//mojo/public/c/system:headers",
+ ]
+ if (is_win) {
+ inputs = [
+ "mojo_core.def",
+ ]
+ ldflags = [ "/DEF:" + rebase_path("mojo_core.def", root_build_dir) ]
+ } else {
+ configs += [ ":export_only_thunks_api" ]
+ }
+ }
+
+ if (is_chromeos) {
+ if (target_cpu == "arm" || target_cpu == "arm64") {
+ android32_toolchain = "android_clang_arm"
+ android64_toolchain = "android_clang_arm64"
+ } else {
+ android32_toolchain = "android_clang_x86"
+ android64_toolchain = "android_clang_x64"
+ }
+
+ group("shared_libraries_for_arc") {
+ deps = [
+ ":shared_library_arc32",
+ ":shared_library_arc64",
+ ]
+ }
+
+ copy("shared_library_arc32") {
+ sources = [
+ "${root_out_dir}/${android32_toolchain}/libmojo_core.so",
+ ]
+ outputs = [
+ "${root_out_dir}/libmojo_core_arc32.so",
+ ]
+ deps = [
+ ":shared_library(//build/toolchain/android:${android32_toolchain})",
+ ]
+ }
+
+ copy("shared_library_arc64") {
+ sources = [
+ "${root_out_dir}/${android64_toolchain}/libmojo_core.so",
+ ]
+ outputs = [
+ "${root_out_dir}/libmojo_core_arc64.so",
+ ]
+ deps = [
+ ":shared_library(//build/toolchain/android:${android64_toolchain})",
+ ]
+ }
+ }
+
+ config("export_only_thunks_api") {
+ ldflags = [ "-Wl,--version-script=" +
+ rebase_path("//mojo/core/export_only_thunks_api.lst",
+ root_build_dir) ]
+ }
+
+ if (is_chromeos || is_linux || is_win) {
+ test("mojo_core_unittests") {
+ sources = [
+ "mojo_core_unittest.cc",
+ "run_all_core_unittests.cc",
+ ]
+
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ "//mojo/public/c/system",
+ "//testing/gtest",
+ ]
+
+ data_deps = [
+ ":shared_library",
+ ]
+ }
+ }
+}
+
+source_set("test_utils") {
+ testonly = true
+
+ sources = [
+ "test_utils.cc",
+ "test_utils.h",
+ ]
+
+ public_deps = [
+ "//mojo/public/c/system",
+ "//mojo/public/cpp/system",
+ ]
+
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/test:test_support",
+ "//testing/gtest:gtest",
+ ]
+}
+
+source_set("test_sources") {
+ testonly = true
+ sources = [
+ "channel_unittest.cc",
+ "core_test_base.cc",
+ "core_test_base.h",
+ "core_unittest.cc",
+ "embedder_unittest.cc",
+ "handle_table_unittest.cc",
+ "message_pipe_unittest.cc",
+ "message_unittest.cc",
+ "options_validation_unittest.cc",
+ "platform_handle_dispatcher_unittest.cc",
+ "quota_unittest.cc",
+ "shared_buffer_dispatcher_unittest.cc",
+ "shared_buffer_unittest.cc",
+ "signals_unittest.cc",
+ "trap_unittest.cc",
+ ]
+
+ if (!is_ios) {
+ sources += [
+ "data_pipe_unittest.cc",
+ "invitation_unittest.cc",
+ "multiprocess_message_pipe_unittest.cc",
+ "platform_wrapper_unittest.cc",
+ ]
+ }
+
+ deps = [
+ ":test_utils",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core:embedder_internal",
+ "//mojo/core/embedder",
+ "//mojo/core/ports:tests",
+ "//mojo/core/test:run_all_unittests",
+ "//mojo/core/test:test_support",
+ "//mojo/public/cpp/system",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/mojo/edk/DEPS b/chromium/mojo/core/DEPS
index 4cc26fb9900..4cc26fb9900 100644
--- a/chromium/mojo/edk/DEPS
+++ b/chromium/mojo/core/DEPS
diff --git a/chromium/mojo/edk/system/OWNERS b/chromium/mojo/core/OWNERS
index 42444bcd16d..42444bcd16d 100644
--- a/chromium/mojo/edk/system/OWNERS
+++ b/chromium/mojo/core/OWNERS
diff --git a/chromium/mojo/edk/system/atomic_flag.h b/chromium/mojo/core/atomic_flag.h
index 6bdcfaaddd9..075b837ab1b 100644
--- a/chromium/mojo/edk/system/atomic_flag.h
+++ b/chromium/mojo/core/atomic_flag.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_
-#define MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_
+#ifndef MOJO_CORE_ATOMIC_FLAG_H_
+#define MOJO_CORE_ATOMIC_FLAG_H_
#include "base/atomicops.h"
#include "base/macros.h"
namespace mojo {
-namespace edk {
+namespace core {
// AtomicFlag is a boolean flag that can be set and tested atomically. It is
// intended to be used to fast-path checks where the common case would normally
@@ -35,13 +35,9 @@ class AtomicFlag {
AtomicFlag() : flag_(0) {}
~AtomicFlag() {}
- void Set(bool value) {
- base::subtle::Release_Store(&flag_, value ? 1 : 0);
- }
+ void Set(bool value) { base::subtle::Release_Store(&flag_, value ? 1 : 0); }
- bool Get() const {
- return base::subtle::Acquire_Load(&flag_) ? true : false;
- }
+ bool Get() const { return base::subtle::Acquire_Load(&flag_) ? true : false; }
operator const bool() const { return Get(); }
@@ -51,7 +47,7 @@ class AtomicFlag {
DISALLOW_COPY_AND_ASSIGN(AtomicFlag);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_
+#endif // MOJO_CORE_ATOMIC_FLAG_H_
diff --git a/chromium/mojo/edk/system/broker.h b/chromium/mojo/core/broker.h
index 6961f641e0c..41e0b896649 100644
--- a/chromium/mojo/edk/system/broker.h
+++ b/chromium/mojo/core/broker.h
@@ -2,31 +2,32 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_BROKER_H_
-#define MOJO_EDK_SYSTEM_BROKER_H_
+#ifndef MOJO_CORE_BROKER_H_
+#define MOJO_CORE_BROKER_H_
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/writable_shared_memory_region.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
// The Broker is a channel to the broker process, which allows synchronous IPCs
// to fulfill shared memory allocation requests on some platforms.
class Broker {
public:
// Note: This is blocking, and will wait for the first message over
- // |platform_handle|.
- explicit Broker(ScopedInternalPlatformHandle platform_handle);
+ // the endpoint handle in |handle|.
+ explicit Broker(PlatformHandle handle);
~Broker();
// Returns the platform handle that should be used to establish a NodeChannel
// to the process which is inviting us to join its network. This is the first
// handle read off the Broker channel upon construction.
- ScopedInternalPlatformHandle GetInviterInternalPlatformHandle();
+ PlatformChannelEndpoint GetInviterEndpoint();
// Request a shared buffer from the broker process. Blocks the current thread.
base::WritableSharedMemoryRegion GetWritableSharedMemoryRegion(
@@ -34,11 +35,11 @@ class Broker {
private:
// Handle to the broker process, used for synchronous IPCs.
- ScopedInternalPlatformHandle sync_channel_;
+ PlatformHandle sync_channel_;
- // Handle to the inviter process which is recieved in the first first message
- // over |sync_channel_|.
- ScopedInternalPlatformHandle inviter_channel_;
+ // Channel endpoint connected to the inviter process. Recieved in the first
+ // first message over |sync_channel_|.
+ PlatformChannelEndpoint inviter_endpoint_;
// Lock to only allow one sync message at a time. This avoids having to deal
// with message ordering since we can only have one request at a time
@@ -48,7 +49,7 @@ class Broker {
DISALLOW_COPY_AND_ASSIGN(Broker);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_BROKER_H_
+#endif // MOJO_CORE_BROKER_H_
diff --git a/chromium/mojo/edk/system/broker_host.cc b/chromium/mojo/core/broker_host.cc
index 8966e239654..875cc2fe490 100644
--- a/chromium/mojo/edk/system/broker_host.cc
+++ b/chromium/mojo/core/broker_host.cc
@@ -2,7 +2,7 @@
// 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 "mojo/core/broker_host.h"
#include <utility>
@@ -11,17 +11,18 @@
#include "base/memory/ref_counted.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/named_platform_channel_pair.h"
-#include "mojo/edk/embedder/named_platform_handle.h"
-#include "mojo/edk/embedder/platform_handle_utils.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/broker_messages.h"
+#include "mojo/core/broker_messages.h"
+#include "mojo/core/platform_handle_utils.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
namespace mojo {
-namespace edk {
+namespace core {
BrokerHost::BrokerHost(base::ProcessHandle client_process,
- ScopedInternalPlatformHandle platform_handle,
+ ConnectionParams connection_params,
const ProcessErrorCallback& process_error_callback)
: process_error_callback_(process_error_callback)
#if defined(OS_WIN)
@@ -29,14 +30,13 @@ BrokerHost::BrokerHost(base::ProcessHandle client_process,
client_process_(ScopedProcessHandle::CloneFrom(client_process))
#endif
{
- CHECK(platform_handle.is_valid());
+ CHECK(connection_params.endpoint().is_valid() ||
+ connection_params.server_endpoint().is_valid());
base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
- channel_ = Channel::Create(
- this,
- ConnectionParams(TransportProtocol::kLegacy, std::move(platform_handle)),
- base::ThreadTaskRunnerHandle::Get());
+ channel_ = Channel::Create(this, std::move(connection_params),
+ base::ThreadTaskRunnerHandle::Get());
channel_->Start();
}
@@ -49,21 +49,20 @@ BrokerHost::~BrokerHost() {
}
bool BrokerHost::PrepareHandlesForClient(
- std::vector<ScopedInternalPlatformHandle>* handles) {
+ std::vector<PlatformHandleInTransit>* handles) {
#if defined(OS_WIN)
- if (!Channel::Message::RewriteHandles(base::GetCurrentProcessHandle(),
- client_process_.get(), 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;
+ bool handles_ok = true;
+ for (auto& handle : *handles) {
+ if (!handle.TransferToProcess(client_process_.Clone()))
+ handles_ok = false;
}
-#endif
+ return handles_ok;
+#else
return true;
+#endif
}
-bool BrokerHost::SendChannel(ScopedInternalPlatformHandle handle) {
+bool BrokerHost::SendChannel(PlatformHandle handle) {
CHECK(handle.is_valid());
CHECK(channel_);
@@ -76,8 +75,8 @@ bool BrokerHost::SendChannel(ScopedInternalPlatformHandle handle) {
Channel::MessagePtr message =
CreateBrokerMessage(BrokerMessageType::INIT, 1, nullptr);
#endif
- std::vector<ScopedInternalPlatformHandle> handles(1);
- handles[0] = std::move(handle);
+ std::vector<PlatformHandleInTransit> handles(1);
+ handles[0] = PlatformHandleInTransit(std::move(handle));
// This may legitimately fail on Windows if the client process is in another
// session, e.g., is an elevated process.
@@ -108,18 +107,21 @@ void BrokerHost::OnBufferRequest(uint32_t num_bytes) {
base::subtle::PlatformSharedMemoryRegion region =
base::subtle::PlatformSharedMemoryRegion::CreateWritable(num_bytes);
- std::vector<ScopedInternalPlatformHandle> handles(2);
+ std::vector<PlatformHandleInTransit> handles(2);
if (region.IsValid()) {
- ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
- region.PassPlatformHandle(), &handles[0], &handles[1]);
+ PlatformHandle h[2];
+ ExtractPlatformHandlesFromSharedMemoryRegionHandle(
+ region.PassPlatformHandle(), &h[0], &h[1]);
+ handles[0] = PlatformHandleInTransit(std::move(h[0]));
+ handles[1] = PlatformHandleInTransit(std::move(h[1]));
#if !defined(OS_POSIX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) || \
(defined(OS_MACOSX) && !defined(OS_IOS))
// Non-POSIX systems, as well as Android, Fuchsia, and non-iOS Mac, only use
// a single handle to represent a writable region.
- DCHECK(!handles[1].is_valid());
+ DCHECK(!handles[1].handle().is_valid());
handles.resize(1);
#else
- DCHECK(handles[1].is_valid());
+ DCHECK(handles[1].handle().is_valid());
#endif
}
@@ -137,10 +139,9 @@ void BrokerHost::OnBufferRequest(uint32_t num_bytes) {
channel_->Write(std::move(message));
}
-void BrokerHost::OnChannelMessage(
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) {
+void BrokerHost::OnChannelMessage(const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) {
if (payload_size < sizeof(BrokerMessageHeader))
return;
@@ -175,5 +176,5 @@ void BrokerHost::WillDestroyCurrentMessageLoop() {
delete this;
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/broker_host.h b/chromium/mojo/core/broker_host.h
index 1681bdca6c2..3ff36eaa9fd 100644
--- a/chromium/mojo/edk/system/broker_host.h
+++ b/chromium/mojo/core/broker_host.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_BROKER_HOST_H_
-#define MOJO_EDK_SYSTEM_BROKER_HOST_H_
+#ifndef MOJO_CORE_BROKER_HOST_H_
+#define MOJO_CORE_BROKER_HOST_H_
#include <stdint.h>
#include <vector>
@@ -12,13 +12,16 @@
#include "base/message_loop/message_loop_current.h"
#include "base/process/process_handle.h"
#include "base/strings/string_piece.h"
-#include "mojo/edk/embedder/process_error_callback.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/scoped_process_handle.h"
+#include "build/build_config.h"
+#include "mojo/core/channel.h"
+#include "mojo/core/connection_params.h"
+#include "mojo/core/embedder/process_error_callback.h"
+#include "mojo/core/platform_handle_in_transit.h"
+#include "mojo/core/scoped_process_handle.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
// The BrokerHost is a channel to a broker client process, servicing synchronous
// IPCs issued by the client.
@@ -26,11 +29,11 @@ class BrokerHost : public Channel::Delegate,
public base::MessageLoopCurrent::DestructionObserver {
public:
BrokerHost(base::ProcessHandle client_process,
- ScopedInternalPlatformHandle handle,
+ ConnectionParams connection_params,
const ProcessErrorCallback& process_error_callback);
// Send |handle| to the client, to be used to establish a NodeChannel to us.
- bool SendChannel(ScopedInternalPlatformHandle handle);
+ bool SendChannel(PlatformHandle handle);
#if defined(OS_WIN)
// Sends a named channel to the client. Like above, but for named pipes.
@@ -40,14 +43,12 @@ class BrokerHost : public Channel::Delegate,
private:
~BrokerHost() override;
- bool PrepareHandlesForClient(
- std::vector<ScopedInternalPlatformHandle>* handles);
+ bool PrepareHandlesForClient(std::vector<PlatformHandleInTransit>* handles);
// Channel::Delegate:
- void OnChannelMessage(
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) override;
+ void OnChannelMessage(const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) override;
void OnChannelError(Channel::Error error) override;
// base::MessageLoopCurrent::DestructionObserver:
@@ -66,7 +67,7 @@ class BrokerHost : public Channel::Delegate,
DISALLOW_COPY_AND_ASSIGN(BrokerHost);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_BROKER_HOST_H_
+#endif // MOJO_CORE_BROKER_HOST_H_
diff --git a/chromium/mojo/edk/system/broker_messages.h b/chromium/mojo/core/broker_messages.h
index 88cab4e4ad6..3bad6f5d9d3 100644
--- a/chromium/mojo/edk/system/broker_messages.h
+++ b/chromium/mojo/core/broker_messages.h
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_BROKER_MESSAGES_H_
-#define MOJO_EDK_SYSTEM_BROKER_MESSAGES_H_
+#ifndef MOJO_CORE_BROKER_MESSAGES_H_
+#define MOJO_CORE_BROKER_MESSAGES_H_
-#include "mojo/edk/system/channel.h"
+#include "build/build_config.h"
+#include "mojo/core/channel.h"
namespace mojo {
-namespace edk {
+namespace core {
#pragma pack(push, 1)
@@ -90,7 +91,7 @@ inline Channel::MessagePtr CreateBrokerMessage(
return message;
}
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_BROKER_MESSAGES_H_
+#endif // MOJO_CORE_BROKER_MESSAGES_H_
diff --git a/chromium/mojo/edk/system/broker_posix.cc b/chromium/mojo/core/broker_posix.cc
index 4b5c15c0fbc..a2501af5f55 100644
--- a/chromium/mojo/edk/system/broker_posix.cc
+++ b/chromium/mojo/core/broker_posix.cc
@@ -2,39 +2,39 @@
// 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.h"
+#include "mojo/core/broker.h"
#include <fcntl.h>
#include <unistd.h>
#include <utility>
+#include <vector>
#include "base/logging.h"
#include "base/memory/platform_shared_memory_region.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_channel_utils_posix.h"
-#include "mojo/edk/embedder/platform_handle_utils.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/broker_messages.h"
-#include "mojo/edk/system/channel.h"
+#include "mojo/core/broker_messages.h"
+#include "mojo/core/channel.h"
+#include "mojo/core/platform_handle_utils.h"
+#include "mojo/public/cpp/platform/socket_utils_posix.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
Channel::MessagePtr WaitForBrokerMessage(
- const ScopedInternalPlatformHandle& platform_handle,
+ int socket_fd,
BrokerMessageType expected_type,
size_t expected_num_handles,
size_t expected_data_size,
- std::vector<ScopedInternalPlatformHandle>* incoming_handles) {
+ std::vector<PlatformHandle>* incoming_handles) {
Channel::MessagePtr message(new Channel::Message(
sizeof(BrokerMessageHeader) + expected_data_size, expected_num_handles));
- base::circular_deque<ScopedInternalPlatformHandle> incoming_platform_handles;
- ssize_t read_result = PlatformChannelRecvmsg(
- platform_handle, const_cast<void*>(message->data()),
- message->data_num_bytes(), &incoming_platform_handles, true /* block */);
+ std::vector<base::ScopedFD> incoming_fds;
+ ssize_t read_result =
+ SocketRecvmsg(socket_fd, const_cast<void*>(message->data()),
+ message->data_num_bytes(), &incoming_fds, true /* block */);
bool error = false;
if (read_result < 0) {
PLOG(ERROR) << "Recvmsg error";
@@ -42,7 +42,7 @@ Channel::MessagePtr WaitForBrokerMessage(
} else if (static_cast<size_t>(read_result) != message->data_num_bytes()) {
LOG(ERROR) << "Invalid node channel message";
error = true;
- } else if (incoming_platform_handles.size() != expected_num_handles) {
+ } else if (incoming_fds.size() != expected_num_handles) {
LOG(ERROR) << "Received unexpected number of handles";
error = true;
}
@@ -57,37 +57,38 @@ Channel::MessagePtr WaitForBrokerMessage(
return nullptr;
}
- incoming_handles->resize(incoming_platform_handles.size());
- std::move(incoming_platform_handles.begin(), incoming_platform_handles.end(),
- incoming_handles->begin());
+ incoming_handles->reserve(incoming_fds.size());
+ for (size_t i = 0; i < incoming_fds.size(); ++i)
+ incoming_handles->emplace_back(std::move(incoming_fds[i]));
return message;
}
} // namespace
-Broker::Broker(ScopedInternalPlatformHandle platform_handle)
- : sync_channel_(std::move(platform_handle)) {
+Broker::Broker(PlatformHandle handle) : sync_channel_(std::move(handle)) {
CHECK(sync_channel_.is_valid());
+ int fd = sync_channel_.GetFD().get();
// Mark the channel as blocking.
- int flags = fcntl(sync_channel_.get().handle, F_GETFL);
+ int flags = fcntl(fd, F_GETFL);
PCHECK(flags != -1);
- flags = fcntl(sync_channel_.get().handle, F_SETFL, flags & ~O_NONBLOCK);
+ flags = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
PCHECK(flags != -1);
// Wait for the first message, which should contain a handle.
- std::vector<ScopedInternalPlatformHandle> incoming_platform_handles;
- if (WaitForBrokerMessage(sync_channel_, BrokerMessageType::INIT, 1, 0,
+ std::vector<PlatformHandle> incoming_platform_handles;
+ if (WaitForBrokerMessage(fd, BrokerMessageType::INIT, 1, 0,
&incoming_platform_handles)) {
- inviter_channel_ = std::move(incoming_platform_handles[0]);
+ inviter_endpoint_ =
+ PlatformChannelEndpoint(std::move(incoming_platform_handles[0]));
}
}
Broker::~Broker() = default;
-ScopedInternalPlatformHandle Broker::GetInviterInternalPlatformHandle() {
- return std::move(inviter_channel_);
+PlatformChannelEndpoint Broker::GetInviterEndpoint() {
+ return std::move(inviter_endpoint_);
}
base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
@@ -98,8 +99,9 @@ base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
Channel::MessagePtr out_message = CreateBrokerMessage(
BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request);
buffer_request->size = num_bytes;
- ssize_t write_result = PlatformChannelWrite(
- sync_channel_, out_message->data(), out_message->data_num_bytes());
+ ssize_t write_result =
+ SocketWrite(sync_channel_.GetFD().get(), out_message->data(),
+ out_message->data_num_bytes());
if (write_result < 0) {
PLOG(ERROR) << "Error sending sync broker message";
return base::WritableSharedMemoryRegion();
@@ -118,22 +120,21 @@ base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
constexpr size_t kNumExpectedHandles = 2;
#endif
- std::vector<ScopedInternalPlatformHandle> incoming_platform_handles;
+ std::vector<PlatformHandle> handles;
Channel::MessagePtr message = WaitForBrokerMessage(
- sync_channel_, BrokerMessageType::BUFFER_RESPONSE, kNumExpectedHandles,
- sizeof(BufferResponseData), &incoming_platform_handles);
+ sync_channel_.GetFD().get(), BrokerMessageType::BUFFER_RESPONSE,
+ kNumExpectedHandles, sizeof(BufferResponseData), &handles);
if (message) {
const BufferResponseData* data;
if (!GetBrokerMessageData(message.get(), &data))
return base::WritableSharedMemoryRegion();
- if (incoming_platform_handles.size() == 1)
- incoming_platform_handles.emplace_back();
+ if (handles.size() == 1)
+ handles.emplace_back();
return base::WritableSharedMemoryRegion::Deserialize(
base::subtle::PlatformSharedMemoryRegion::Take(
- CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
- std::move(incoming_platform_handles[0]),
- std::move(incoming_platform_handles[1])),
+ CreateSharedMemoryRegionHandleFromPlatformHandles(
+ std::move(handles[0]), std::move(handles[1])),
base::subtle::PlatformSharedMemoryRegion::Mode::kWritable,
num_bytes,
base::UnguessableToken::Deserialize(data->guid_high,
@@ -143,5 +144,5 @@ base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
return base::WritableSharedMemoryRegion();
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/broker_win.cc b/chromium/mojo/core/broker_win.cc
index a2dea366c0c..3ebc8839ce0 100644
--- a/chromium/mojo/edk/system/broker_win.cc
+++ b/chromium/mojo/core/broker_win.cc
@@ -11,17 +11,14 @@
#include "base/memory/platform_shared_memory_region.h"
#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_utils.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/broker.h"
-#include "mojo/edk/system/broker_messages.h"
-#include "mojo/edk/system/channel.h"
+#include "mojo/core/broker.h"
+#include "mojo/core/broker_messages.h"
+#include "mojo/core/channel.h"
+#include "mojo/core/platform_handle_utils.h"
+#include "mojo/public/cpp/platform/named_platform_channel.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -30,27 +27,27 @@ const size_t kMaxBrokerMessageSize = 256;
bool TakeHandlesFromBrokerMessage(Channel::Message* message,
size_t num_handles,
- ScopedInternalPlatformHandle* out_handles) {
+ PlatformHandle* out_handles) {
if (message->num_handles() != num_handles) {
DLOG(ERROR) << "Received unexpected number of handles in broker message";
return false;
}
- std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
DCHECK_EQ(handles.size(), num_handles);
DCHECK(out_handles);
for (size_t i = 0; i < num_handles; ++i)
- out_handles[i] = std::move(handles[i]);
+ out_handles[i] = handles[i].TakeHandle();
return true;
}
-Channel::MessagePtr WaitForBrokerMessage(InternalPlatformHandle platform_handle,
+Channel::MessagePtr WaitForBrokerMessage(HANDLE pipe_handle,
BrokerMessageType expected_type) {
char buffer[kMaxBrokerMessageSize];
DWORD bytes_read = 0;
- BOOL result = ::ReadFile(platform_handle.handle, buffer,
- kMaxBrokerMessageSize, &bytes_read, nullptr);
+ BOOL result = ::ReadFile(pipe_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
@@ -86,18 +83,20 @@ Channel::MessagePtr WaitForBrokerMessage(InternalPlatformHandle platform_handle,
} // namespace
-Broker::Broker(ScopedInternalPlatformHandle handle)
- : sync_channel_(std::move(handle)) {
+Broker::Broker(PlatformHandle handle) : sync_channel_(std::move(handle)) {
CHECK(sync_channel_.is_valid());
- Channel::MessagePtr message =
- WaitForBrokerMessage(sync_channel_.get(), BrokerMessageType::INIT);
+ Channel::MessagePtr message = WaitForBrokerMessage(
+ sync_channel_.GetHandle().Get(), BrokerMessageType::INIT);
// If we fail to read a message (broken pipe), just return early. The inviter
// handle will be null and callers must handle this gracefully.
if (!message)
return;
- if (!TakeHandlesFromBrokerMessage(message.get(), 1, &inviter_channel_)) {
+ PlatformHandle endpoint_handle;
+ if (TakeHandlesFromBrokerMessage(message.get(), 1, &endpoint_handle)) {
+ inviter_endpoint_ = PlatformChannelEndpoint(std::move(endpoint_handle));
+ } else {
// If the message has no handles, we expect it to carry pipe name instead.
const BrokerMessageHeader* header =
static_cast<const BrokerMessageHeader*>(message->payload());
@@ -110,15 +109,15 @@ Broker::Broker(ScopedInternalPlatformHandle handle)
const base::char16* name_data =
reinterpret_cast<const base::char16*>(data + 1);
CHECK(data->pipe_name_length);
- inviter_channel_ = CreateClientHandle(NamedPlatformHandle(
- base::StringPiece16(name_data, data->pipe_name_length)));
+ inviter_endpoint_ = NamedPlatformChannel::ConnectToServer(
+ base::StringPiece16(name_data, data->pipe_name_length).as_string());
}
}
Broker::~Broker() {}
-ScopedInternalPlatformHandle Broker::GetInviterInternalPlatformHandle() {
- return std::move(inviter_channel_);
+PlatformChannelEndpoint Broker::GetInviterEndpoint() {
+ return std::move(inviter_endpoint_);
}
base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
@@ -129,26 +128,27 @@ base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request);
buffer_request->size = base::checked_cast<uint32_t>(num_bytes);
DWORD bytes_written = 0;
- BOOL result = ::WriteFile(sync_channel_.get().handle, out_message->data(),
- static_cast<DWORD>(out_message->data_num_bytes()),
- &bytes_written, nullptr);
+ BOOL result =
+ ::WriteFile(sync_channel_.GetHandle().Get(), out_message->data(),
+ static_cast<DWORD>(out_message->data_num_bytes()),
+ &bytes_written, nullptr);
if (!result ||
static_cast<size_t>(bytes_written) != out_message->data_num_bytes()) {
PLOG(ERROR) << "Error sending sync broker message";
return base::WritableSharedMemoryRegion();
}
- ScopedInternalPlatformHandle handle;
+ PlatformHandle handle;
Channel::MessagePtr response = WaitForBrokerMessage(
- sync_channel_.get(), BrokerMessageType::BUFFER_RESPONSE);
+ sync_channel_.GetHandle().Get(), BrokerMessageType::BUFFER_RESPONSE);
if (response && TakeHandlesFromBrokerMessage(response.get(), 1, &handle)) {
BufferResponseData* data;
if (!GetBrokerMessageData(response.get(), &data))
return base::WritableSharedMemoryRegion();
return base::WritableSharedMemoryRegion::Deserialize(
base::subtle::PlatformSharedMemoryRegion::Take(
- CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
- std::move(handle), ScopedInternalPlatformHandle()),
+ CreateSharedMemoryRegionHandleFromPlatformHandles(std::move(handle),
+ PlatformHandle()),
base::subtle::PlatformSharedMemoryRegion::Mode::kWritable,
num_bytes,
base::UnguessableToken::Deserialize(data->guid_high,
@@ -158,5 +158,5 @@ base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
return base::WritableSharedMemoryRegion();
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/channel.cc b/chromium/mojo/core/channel.cc
index 0005193ca3d..85d2a629be3 100644
--- a/chromium/mojo/edk/system/channel.cc
+++ b/chromium/mojo/core/channel.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/channel.h"
+#include "mojo/core/channel.h"
#include <stddef.h>
#include <string.h>
@@ -16,9 +16,8 @@
#include "base/numerics/safe_math.h"
#include "base/process/process_handle.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/core.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/core.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include "base/mac/mach_logging.h"
@@ -27,7 +26,7 @@
#endif
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -70,7 +69,7 @@ Channel::Message::Message(size_t payload_size,
Channel::Message::Message(size_t capacity,
size_t payload_size,
size_t max_handles)
-#if defined(MOJO_EDK_LEGACY_PROTOCOL)
+#if defined(MOJO_CORE_LEGACY_PROTOCOL)
: Message(capacity, payload_size, max_handles, MessageType::NORMAL_LEGACY) {
}
#else
@@ -151,8 +150,8 @@ Channel::Message::Message(size_t capacity,
mach_ports_header_->num_ports = 0;
// Initialize all handles to invalid values.
for (size_t i = 0; i < max_handles_; ++i) {
- mach_ports_header_->entries[i] =
- {0, static_cast<uint32_t>(MACH_PORT_NULL)};
+ mach_ports_header_->entries[i] = {0,
+ static_cast<uint32_t>(MACH_PORT_NULL)};
}
#endif
}
@@ -163,8 +162,10 @@ Channel::Message::~Message() {
}
// static
-Channel::MessagePtr Channel::Message::Deserialize(const void* data,
- size_t data_num_bytes) {
+Channel::MessagePtr Channel::Message::Deserialize(
+ const void* data,
+ size_t data_num_bytes,
+ base::ProcessHandle from_process) {
if (data_num_bytes < sizeof(LegacyHeader))
return nullptr;
@@ -250,10 +251,17 @@ Channel::MessagePtr Channel::Message::Deserialize(const void* data,
}
#if defined(OS_WIN)
- std::vector<ScopedInternalPlatformHandle> handles(num_handles);
+ std::vector<PlatformHandleInTransit> handles(num_handles);
for (size_t i = 0; i < num_handles; i++) {
- handles[i] = ScopedInternalPlatformHandle(InternalPlatformHandle(
- base::win::Uint32ToHandle(message->handles_[i].handle)));
+ HANDLE handle = base::win::Uint32ToHandle(message->handles_[i].handle);
+ if (from_process == base::kNullProcessHandle) {
+ handles[i] = PlatformHandleInTransit(
+ PlatformHandle(base::win::ScopedHandle(handle)));
+ } else {
+ handles[i] = PlatformHandleInTransit(
+ PlatformHandleInTransit::TakeIncomingRemoteHandle(handle,
+ from_process));
+ }
}
message->SetHandles(std::move(handles));
#endif
@@ -343,10 +351,8 @@ bool Channel::Message::has_mach_ports() const {
return false;
for (const auto& handle : handle_vector_) {
- if (handle.get().type == InternalPlatformHandle::Type::MACH ||
- handle.get().type == InternalPlatformHandle::Type::MACH_NAME) {
+ if (handle.is_mach_port_name() || handle.handle().is_mach_port())
return true;
- }
}
return false;
}
@@ -365,8 +371,17 @@ Channel::Message::Header* Channel::Message::header() const {
return reinterpret_cast<Header*>(data_);
}
+void Channel::Message::SetHandles(std::vector<PlatformHandle> new_handles) {
+ std::vector<PlatformHandleInTransit> handles;
+ handles.reserve(new_handles.size());
+ for (auto& h : new_handles) {
+ handles.emplace_back(PlatformHandleInTransit(std::move(h)));
+ }
+ SetHandles(std::move(handles));
+}
+
void Channel::Message::SetHandles(
- std::vector<ScopedInternalPlatformHandle> new_handles) {
+ std::vector<PlatformHandleInTransit> new_handles) {
if (is_legacy_message()) {
// Old semantics for ChromeOS and Android
if (legacy_header()->num_handles == 0) {
@@ -388,39 +403,46 @@ void Channel::Message::SetHandles(
std::swap(handle_vector_, new_handles);
#if defined(OS_WIN)
memset(handles_, 0, extra_header_size());
- for (size_t i = 0; i < handle_vector_.size(); i++)
- handles_[i].handle =
- base::win::HandleToUint32(handle_vector_[i].get().handle);
+ for (size_t i = 0; i < handle_vector_.size(); i++) {
+ HANDLE handle = handle_vector_[i].remote_handle();
+ if (handle == INVALID_HANDLE_VALUE)
+ handle = handle_vector_[i].handle().GetHandle().Get();
+ handles_[i].handle = base::win::HandleToUint32(handle);
+ }
#endif // defined(OS_WIN)
#if defined(OS_MACOSX) && !defined(OS_IOS)
size_t mach_port_index = 0;
if (mach_ports_header_) {
for (size_t i = 0; i < max_handles_; ++i) {
- mach_ports_header_->entries[i] =
- {0, static_cast<uint32_t>(MACH_PORT_NULL)};
+ mach_ports_header_->entries[i] = {0,
+ static_cast<uint32_t>(MACH_PORT_NULL)};
}
for (size_t i = 0; i < handle_vector_.size(); i++) {
- if (handle_vector_[i].get().type == InternalPlatformHandle::Type::MACH ||
- handle_vector_[i].get().type ==
- InternalPlatformHandle::Type::MACH_NAME) {
- mach_port_t port = handle_vector_[i].get().port;
- mach_ports_header_->entries[mach_port_index].index = i;
- mach_ports_header_->entries[mach_port_index].mach_port = port;
- mach_port_index++;
+ if (!handle_vector_[i].is_mach_port_name() &&
+ !handle_vector_[i].handle().is_mach_port()) {
+ DCHECK(handle_vector_[i].handle().is_valid_fd());
+ continue;
}
+
+ mach_port_t port = handle_vector_[i].is_mach_port_name()
+ ? handle_vector_[i].mach_port_name()
+ : handle_vector_[i].handle().GetMachPort().get();
+ mach_ports_header_->entries[mach_port_index].index = i;
+ mach_ports_header_->entries[mach_port_index].mach_port = port;
+ mach_port_index++;
}
mach_ports_header_->num_ports = static_cast<uint16_t>(mach_port_index);
}
#endif
}
-std::vector<ScopedInternalPlatformHandle> Channel::Message::TakeHandles() {
+std::vector<PlatformHandleInTransit> Channel::Message::TakeHandles() {
#if defined(OS_MACOSX) && !defined(OS_IOS)
if (mach_ports_header_) {
for (size_t i = 0; i < max_handles_; ++i) {
- mach_ports_header_->entries[i] =
- {0, static_cast<uint32_t>(MACH_PORT_NULL)};
+ mach_ports_header_->entries[i] = {0,
+ static_cast<uint32_t>(MACH_PORT_NULL)};
}
mach_ports_header_->num_ports = 0;
}
@@ -432,74 +454,30 @@ std::vector<ScopedInternalPlatformHandle> Channel::Message::TakeHandles() {
return std::move(handle_vector_);
}
-std::vector<ScopedInternalPlatformHandle>
+std::vector<PlatformHandleInTransit>
Channel::Message::TakeHandlesForTransport() {
#if defined(OS_WIN)
// Not necessary on Windows.
NOTREACHED();
- return std::vector<ScopedInternalPlatformHandle>();
+ return std::vector<PlatformHandleInTransit>();
#elif defined(OS_MACOSX) && !defined(OS_IOS)
- for (auto it = handle_vector_.begin(); it != handle_vector_.end();) {
- if (it->get().type == InternalPlatformHandle::Type::MACH ||
- it->get().type == InternalPlatformHandle::Type::MACH_NAME) {
- // For Mach port names, we can can just leak them. They're not real
- // ports anyways. For real ports, they're leaked because this is a child
- // process and the remote process will take ownership.
- // TODO(wez): Removing Mach ports here because they are delivered
- // out-of-band seems strange; could this be properly hidden inside the
- // Mac-specific Channel impl?
- ignore_result(it->release());
- it = handle_vector_.erase(it);
+ std::vector<PlatformHandleInTransit> non_mach_handles;
+ for (auto& handle : handle_vector_) {
+ if (handle.is_mach_port_name() || handle.handle().is_mach_port()) {
+ // Ownership is effectively transferred to the receiving process
+ // out-of-band via MachPortRelay.
+ handle.CompleteTransit();
} else {
- ++it;
+ non_mach_handles.emplace_back(std::move(handle));
}
}
- return std::move(handle_vector_);
+ handle_vector_.clear();
+ return non_mach_handles;
#else
return std::move(handle_vector_);
#endif
}
-#if defined(OS_WIN)
-// static
-bool Channel::Message::RewriteHandles(
- base::ProcessHandle from_process,
- base::ProcessHandle to_process,
- std::vector<ScopedInternalPlatformHandle>* handles) {
- bool success = true;
- for (size_t i = 0; i < handles->size(); ++i) {
- if (!(*handles)[i].is_valid()) {
- DLOG(ERROR) << "Refusing to duplicate invalid handle.";
- continue;
- }
- DCHECK_EQ((*handles)[i].get().owning_process, from_process);
- BOOL result =
- DuplicateHandle(from_process, (*handles)[i].get().handle, to_process,
- &(*handles)[i].get().handle, 0, FALSE,
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
- if (result) {
- if (to_process == base::GetCurrentProcessHandle()) {
- (*handles)[i].get().owning_process = to_process;
- } else {
- // If this handle is bound for an external process, make sure it owns
- // its own copy of the target process handle.
- (*handles)[i].get().owning_process =
- ScopedProcessHandle::CloneFrom(to_process).release();
- }
- } else {
- success = false;
-
- // If handle duplication fails, the source handle will already be closed
- // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with
- // an invalid handle.
- (*handles)[i].get().handle = INVALID_HANDLE_VALUE;
- (*handles)[i].get().owning_process = base::GetCurrentProcessHandle();
- }
- }
- return success;
-}
-#endif
-
// Helper class for managing a Channel's read buffer allocations. This maintains
// a single contiguous buffer with the layout:
//
@@ -525,8 +503,8 @@ class Channel::ReadBuffer {
public:
ReadBuffer() {
size_ = kReadBufferSize;
- data_ = static_cast<char*>(base::AlignedAlloc(size_,
- kChannelMessageAlignment));
+ data_ =
+ static_cast<char*>(base::AlignedAlloc(size_, kChannelMessageAlignment));
}
~ReadBuffer() {
@@ -622,18 +600,16 @@ class Channel::ReadBuffer {
};
Channel::Channel(Delegate* delegate)
- : delegate_(delegate), read_buffer_(new ReadBuffer) {
-}
+ : delegate_(delegate), read_buffer_(new ReadBuffer) {}
-Channel::~Channel() {
-}
+Channel::~Channel() {}
void Channel::ShutDown() {
- delegate_ = nullptr;
ShutDownImpl();
+ delegate_ = nullptr;
}
-char* Channel::GetReadBuffer(size_t *buffer_capacity) {
+char* Channel::GetReadBuffer(size_t* buffer_capacity) {
DCHECK(read_buffer_);
size_t required_capacity = *buffer_capacity;
if (!required_capacity)
@@ -643,8 +619,8 @@ char* Channel::GetReadBuffer(size_t *buffer_capacity) {
return read_buffer_->Reserve(required_capacity);
}
-bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) {
- bool did_dispatch_message = false;
+bool Channel::OnReadComplete(size_t bytes_read, size_t* next_read_size_hint) {
+ bool did_consume_message = false;
read_buffer_->Claim(bytes_read);
while (read_buffer_->num_occupied_bytes() >= sizeof(Message::LegacyHeader)) {
// Ensure the occupied data is properly aligned. If it isn't, a SIGBUS could
@@ -708,10 +684,12 @@ bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) {
const uint16_t num_handles =
header ? header->num_handles : legacy_header->num_handles;
- std::vector<ScopedInternalPlatformHandle> handles;
+ std::vector<PlatformHandle> handles;
+ bool deferred = false;
if (num_handles > 0) {
- if (!GetReadInternalPlatformHandles(num_handles, extra_header,
- extra_header_size, &handles)) {
+ if (!GetReadPlatformHandles(payload, payload_size, num_handles,
+ extra_header, extra_header_size, &handles,
+ &deferred)) {
return false;
}
@@ -724,20 +702,23 @@ bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) {
// We've got a complete message! Dispatch it and try another.
if (legacy_header->message_type != Message::MessageType::NORMAL_LEGACY &&
legacy_header->message_type != Message::MessageType::NORMAL) {
+ DCHECK(!deferred);
if (!OnControlMessage(legacy_header->message_type, payload, payload_size,
std::move(handles))) {
return false;
}
- did_dispatch_message = true;
+ did_consume_message = true;
+ } else if (deferred) {
+ did_consume_message = true;
} else if (delegate_) {
delegate_->OnChannelMessage(payload, payload_size, std::move(handles));
- did_dispatch_message = true;
+ did_consume_message = true;
}
read_buffer_->Discard(legacy_header->num_bytes);
}
- *next_read_size_hint = did_dispatch_message ? 0 : kReadBufferSize;
+ *next_read_size_hint = did_consume_message ? 0 : kReadBufferSize;
return true;
}
@@ -746,13 +727,12 @@ void Channel::OnError(Error error) {
delegate_->OnChannelError(error);
}
-bool Channel::OnControlMessage(
- Message::MessageType message_type,
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) {
+bool Channel::OnControlMessage(Message::MessageType message_type,
+ const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) {
return false;
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/channel.h b/chromium/mojo/core/channel.h
index ef9669cc39a..17108e9f027 100644
--- a/chromium/mojo/edk/system/channel.h
+++ b/chromium/mojo/core/channel.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_CHANNEL_H_
-#define MOJO_EDK_SYSTEM_CHANNEL_H_
+#ifndef MOJO_CORE_CHANNEL_H_
+#define MOJO_CORE_CHANNEL_H_
#include <vector>
@@ -12,11 +12,13 @@
#include "base/process/process_handle.h"
#include "base/task_runner.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/connection_params.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/core/connection_params.h"
+#include "mojo/core/platform_handle_in_transit.h"
+#include "mojo/core/scoped_process_handle.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
const size_t kChannelMessageAlignment = 8;
@@ -39,8 +41,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
enum class MessageType : uint16_t {
// An old format normal message, that uses the LegacyHeader.
// Only used on Android and ChromeOS.
- // TODO(jcivelli): remove legacy support when Arc++ has updated to Mojo
- // with normal versioned messages. crbug.com/695645
+ // TODO(https://crbug.com/695645): remove legacy support when Arc++ has
+ // updated to Mojo with normal versioned messages.
NORMAL_LEGACY = 0,
#if defined(OS_MACOSX)
// A control message containing handles to echo back.
@@ -88,7 +90,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
#if defined(OS_MACOSX) && !defined(OS_IOS)
struct MachPortsEntry {
- // Index of Mach port in the original vector of InternalPlatformHandles.
+ // Index of Mach port in the original vector of PlatformHandleInTransits.
uint16_t index;
// Mach port name.
@@ -141,8 +143,12 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
MessageType message_type);
~Message();
- // Constructs a Message from serialized message data.
- static MessagePtr Deserialize(const void* data, size_t data_num_bytes);
+ // Constructs a Message from serialized message data, optionally coming from
+ // a known remote process.
+ static MessagePtr Deserialize(
+ const void* data,
+ size_t data_num_bytes,
+ base::ProcessHandle from_process = base::kNullProcessHandle);
const void* data() const { return data_; }
size_t data_num_bytes() const { return size_; }
@@ -179,25 +185,14 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Note: SetHandles() and TakeHandles() invalidate any previous value of
// handles().
- void SetHandles(std::vector<ScopedInternalPlatformHandle> new_handles);
- std::vector<ScopedInternalPlatformHandle> TakeHandles();
+ void SetHandles(std::vector<PlatformHandle> new_handles);
+ void SetHandles(std::vector<PlatformHandleInTransit> new_handles);
+ std::vector<PlatformHandleInTransit> TakeHandles();
// Version of TakeHandles that returns a vector of platform handles suitable
// for transfer over an underlying OS mechanism. i.e. file descriptors over
// a unix domain socket. Any handle that cannot be transferred this way,
// such as Mach ports, will be removed.
- std::vector<ScopedInternalPlatformHandle> TakeHandlesForTransport();
-
-#if defined(OS_WIN)
- // Prepares the handles in this message for use in a different process.
- // Upon calling this the handles should belong to |from_process|; after the
- // call they'll belong to |to_process|. The source handles are always
- // closed by this call. Returns false iff one or more handles failed
- // duplication.
- static bool RewriteHandles(
- base::ProcessHandle from_process,
- base::ProcessHandle to_process,
- std::vector<ScopedInternalPlatformHandle>* handles);
-#endif
+ std::vector<PlatformHandleInTransit> TakeHandlesForTransport();
void SetVersionForTest(uint16_t version_number);
@@ -216,7 +211,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Maximum number of handles which may be attached to this message.
size_t max_handles_ = 0;
- std::vector<ScopedInternalPlatformHandle> handle_vector_;
+ std::vector<PlatformHandleInTransit> handle_vector_;
#if defined(OS_WIN)
// On Windows, handles are serialised into the extra header section.
@@ -253,10 +248,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Notify of a received message. |payload| is not owned and must not be
// retained; it will be null if |payload_size| is 0. |handles| are
// transferred to the callee.
- virtual void OnChannelMessage(
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) = 0;
+ virtual void OnChannelMessage(const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) = 0;
// Notify that an error has occured and the Channel will cease operation.
virtual void OnChannelError(Error error) = 0;
@@ -278,6 +272,14 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Delegate methods will no longer be invoked after this call.
void ShutDown();
+ // Sets the process handle of the remote endpoint to which this Channel is
+ // connected. If called at all, must be called only once, and before Start().
+ void set_remote_process(ScopedProcessHandle remote_process) {
+ DCHECK(!remote_process_.is_valid());
+ remote_process_ = std::move(remote_process);
+ }
+ const ScopedProcessHandle& remote_process() const { return remote_process_; }
+
// Begin processing I/O events. Delegate methods must only be invoked after
// this call.
virtual void Start() = 0;
@@ -298,6 +300,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
explicit Channel(Delegate* delegate);
virtual ~Channel();
+ Delegate* delegate() const { return delegate_; }
+
// Called by the implementation when it wants somewhere to stick data.
// |*buffer_capacity| may be set by the caller to indicate the desired buffer
// size. If 0, a sane default size will be used instead.
@@ -327,19 +331,24 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// insufficient number of handles to be available when this call is made, but
// this is not necessarily an error condition. In such cases this returns
// |true| but |*handles| will also be reset to null.
- virtual bool GetReadInternalPlatformHandles(
- size_t num_handles,
- const void* extra_header,
- size_t extra_header_size,
- std::vector<ScopedInternalPlatformHandle>* handles) = 0;
+ //
+ // If the implementation sets |*deferred| to |true|, it assumes responsibility
+ // for dispatching the message eventually. It must copy |payload| to retain
+ // it for later transmission.
+ virtual bool GetReadPlatformHandles(const void* payload,
+ size_t payload_size,
+ size_t num_handles,
+ const void* extra_header,
+ size_t extra_header_size,
+ std::vector<PlatformHandle>* handles,
+ bool* deferred) = 0;
// Handles a received control message. Returns |true| if the message is
// accepted, or |false| otherwise.
- virtual bool OnControlMessage(
- Message::MessageType message_type,
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles);
+ virtual bool OnControlMessage(Message::MessageType message_type,
+ const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles);
private:
friend class base::RefCountedThreadSafe<Channel>;
@@ -349,10 +358,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
Delegate* delegate_;
const std::unique_ptr<ReadBuffer> read_buffer_;
+ // Handle to the process on the other end of this Channel, iff known.
+ ScopedProcessHandle remote_process_;
+
DISALLOW_COPY_AND_ASSIGN(Channel);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_CHANNEL_H_
+#endif // MOJO_CORE_CHANNEL_H_
diff --git a/chromium/mojo/edk/system/channel_fuchsia.cc b/chromium/mojo/core/channel_fuchsia.cc
index 364792cc32b..4386b200b81 100644
--- a/chromium/mojo/edk/system/channel_fuchsia.cc
+++ b/chromium/mojo/core/channel_fuchsia.cc
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/channel.h"
+#include "mojo/core/channel.h"
-#include <fdio/limits.h>
-#include <fdio/util.h>
+#include <lib/fdio/limits.h>
+#include <lib/fdio/util.h>
+#include <lib/zx/channel.h>
+#include <lib/zx/handle.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
@@ -14,30 +16,30 @@
#include "base/bind.h"
#include "base/containers/circular_deque.h"
#include "base/files/scoped_file.h"
-#include "base/fuchsia/scoped_zx_handle.h"
+#include "base/fuchsia/fuchsia_logging.h"
#include "base/location.h"
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_pump_for_io.h"
+#include "base/stl_util.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
+#include "mojo/core/platform_handle_in_transit.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
const size_t kMaxBatchReadCapacity = 256 * 1024;
-bool UnwrapInternalPlatformHandle(
- ScopedInternalPlatformHandle handle,
- Channel::Message::HandleInfoEntry* info_out,
- std::vector<ScopedInternalPlatformHandle>* handles_out) {
- DCHECK(handle.get().is_valid());
+bool UnwrapPlatformHandle(PlatformHandleInTransit handle,
+ Channel::Message::HandleInfoEntry* info_out,
+ std::vector<PlatformHandleInTransit>* handles_out) {
+ DCHECK(handle.handle().is_valid());
- if (!handle.get().is_valid_fd()) {
+ if (!handle.handle().is_valid_fd()) {
*info_out = {0u, 0u};
handles_out->emplace_back(std::move(handle));
return true;
@@ -51,20 +53,21 @@ bool UnwrapInternalPlatformHandle(
// already been dup()d into another FD) we may need to clone.
zx_handle_t handles[FDIO_MAX_HANDLES] = {};
uint32_t info[FDIO_MAX_HANDLES] = {};
- zx_status_t result = fdio_transfer_fd(handle.get().as_fd(), 0, handles, info);
+ zx_status_t result =
+ fdio_transfer_fd(handle.handle().GetFD().get(), 0, handles, info);
if (result > 0) {
// On success, the fd in |handle| has been transferred and is no longer
- // valid. Release from the ScopedInternalPlatformHandle to avoid close()ing
+ // valid. Release from the PlatformHandle to avoid close()ing an invalid
// an invalid handle.
- ignore_result(handle.release());
+ handle.CompleteTransit();
} else if (result == ZX_ERR_UNAVAILABLE) {
// No luck, try cloning instead.
- result = fdio_clone_fd(handle.get().as_fd(), 0, handles, info);
+ result = fdio_clone_fd(handle.handle().GetFD().get(), 0, handles, info);
}
if (result <= 0) {
- DLOG(ERROR) << "fdio_transfer_fd(" << handle.get().as_fd()
- << "): " << zx_status_get_string(result);
+ ZX_DLOG(ERROR, result) << "fdio_transfer_fd("
+ << handle.handle().GetFD().get() << ")";
return false;
}
DCHECK_LE(result, FDIO_MAX_HANDLES);
@@ -75,23 +78,22 @@ bool UnwrapInternalPlatformHandle(
for (int i = 0; i < result; ++i) {
DCHECK_EQ(PA_HND_TYPE(info[0]), PA_HND_TYPE(info[i]));
DCHECK_EQ(0u, PA_HND_SUBTYPE(info[i]));
- handles_out->emplace_back(InternalPlatformHandle::ForHandle(handles[i]));
+ handles_out->emplace_back(
+ PlatformHandleInTransit(PlatformHandle(zx::handle(handles[i]))));
}
return true;
}
-ScopedInternalPlatformHandle WrapInternalPlatformHandles(
- Channel::Message::HandleInfoEntry info,
- base::circular_deque<base::ScopedZxHandle>* handles) {
- ScopedInternalPlatformHandle out_handle;
+PlatformHandle WrapPlatformHandles(Channel::Message::HandleInfoEntry info,
+ base::circular_deque<zx::handle>* handles) {
+ PlatformHandle out_handle;
if (!info.type) {
- out_handle.reset(
- InternalPlatformHandle::ForHandle(handles->front().release()));
+ out_handle = PlatformHandle(std::move(handles->front()));
handles->pop_front();
} else {
if (info.count > FDIO_MAX_HANDLES)
- return ScopedInternalPlatformHandle();
+ return PlatformHandle();
// Fetch the required number of handles from |handles| and set up type info.
zx_handle_t fd_handles[FDIO_MAX_HANDLES] = {};
@@ -106,8 +108,8 @@ ScopedInternalPlatformHandle WrapInternalPlatformHandles(
zx_status_t result =
fdio_create_fd(fd_handles, fd_infos, info.count, out_fd.receive());
if (result != ZX_OK) {
- DLOG(ERROR) << "fdio_create_fd: " << zx_status_get_string(result);
- return ScopedInternalPlatformHandle();
+ ZX_DLOG(ERROR, result) << "fdio_create_fd";
+ return PlatformHandle();
}
// The handles are owned by FDIO now, so |release()| them before removing
@@ -117,7 +119,7 @@ ScopedInternalPlatformHandle WrapInternalPlatformHandles(
handles->pop_front();
}
- out_handle.reset(InternalPlatformHandle::ForFd(out_fd.release()));
+ out_handle = PlatformHandle(std::move(out_fd));
}
return out_handle;
}
@@ -157,9 +159,9 @@ class MessageView {
offset_ += num_bytes;
}
- std::vector<ScopedInternalPlatformHandle> TakeHandles() {
+ std::vector<PlatformHandleInTransit> TakeHandles() {
if (handles_.empty())
- return std::vector<ScopedInternalPlatformHandle>();
+ return std::vector<PlatformHandleInTransit>();
// We can only pass Fuchsia handles via IPC, so unwrap any FDIO file-
// descriptors in |handles_| into the underlying handles, and serialize the
@@ -168,12 +170,12 @@ class MessageView {
message_->mutable_extra_header());
memset(handles_info, 0, message_->extra_header_size());
- std::vector<ScopedInternalPlatformHandle> in_handles = std::move(handles_);
+ std::vector<PlatformHandleInTransit> in_handles = std::move(handles_);
handles_.reserve(in_handles.size());
for (size_t i = 0; i < in_handles.size(); i++) {
- if (!UnwrapInternalPlatformHandle(std::move(in_handles[i]),
- &handles_info[i], &handles_))
- return std::vector<ScopedInternalPlatformHandle>();
+ if (!UnwrapPlatformHandle(std::move(in_handles[i]), &handles_info[i],
+ &handles_))
+ return std::vector<PlatformHandleInTransit>();
}
return std::move(handles_);
}
@@ -181,7 +183,7 @@ class MessageView {
private:
Channel::MessagePtr message_;
size_t offset_;
- std::vector<ScopedInternalPlatformHandle> handles_;
+ std::vector<PlatformHandleInTransit> handles_;
DISALLOW_COPY_AND_ASSIGN(MessageView);
};
@@ -195,7 +197,8 @@ class ChannelFuchsia : public Channel,
scoped_refptr<base::TaskRunner> io_task_runner)
: Channel(delegate),
self_(this),
- handle_(connection_params.TakeChannelHandle()),
+ handle_(
+ connection_params.TakeEndpoint().TakePlatformHandle().TakeHandle()),
io_task_runner_(io_task_runner) {
CHECK(handle_.is_valid());
}
@@ -238,11 +241,13 @@ class ChannelFuchsia : public Channel,
leak_handle_ = true;
}
- bool GetReadInternalPlatformHandles(
- size_t num_handles,
- const void* extra_header,
- size_t extra_header_size,
- std::vector<ScopedInternalPlatformHandle>* handles) override {
+ bool GetReadPlatformHandles(const void* payload,
+ size_t payload_size,
+ size_t num_handles,
+ const void* extra_header,
+ size_t extra_header_size,
+ std::vector<PlatformHandle>* handles,
+ bool* deferred) override {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (num_handles > std::numeric_limits<uint16_t>::max())
return false;
@@ -273,16 +278,13 @@ class ChannelFuchsia : public Channel,
handles->reserve(num_handles);
for (size_t i = 0; i < num_handles; ++i) {
handles->emplace_back(
- WrapInternalPlatformHandles(handles_info[i], &incoming_handles_)
- .release());
+ WrapPlatformHandles(handles_info[i], &incoming_handles_));
}
return true;
}
private:
- ~ChannelFuchsia() override {
- DCHECK(!read_watch_);
- }
+ ~ChannelFuchsia() override { DCHECK(!read_watch_); }
void StartOnIOThread() {
DCHECK(!read_watch_);
@@ -292,7 +294,7 @@ class ChannelFuchsia : public Channel,
read_watch_.reset(
new base::MessagePumpForIO::ZxHandleWatchController(FROM_HERE));
base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
- handle_.get().as_handle(), true /* persistent */,
+ handle_.get(), true /* persistent */,
ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, read_watch_.get(), this);
}
@@ -318,7 +320,7 @@ class ChannelFuchsia : public Channel,
// base::MessagePumpForIO::ZxHandleWatcher:
void OnZxHandleSignalled(zx_handle_t handle, zx_signals_t signals) override {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
- CHECK_EQ(handle, handle_.get().as_handle());
+ CHECK_EQ(handle, handle_.get());
DCHECK((ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED) & signals);
// We always try to read message(s), even if ZX_CHANNEL_PEER_CLOSED, since
@@ -338,12 +340,12 @@ class ChannelFuchsia : public Channel,
uint32_t handles_read = 0;
zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES] = {};
- zx_status_t read_result = zx_channel_read(
- handle_.get().as_handle(), 0, buffer, handles, buffer_capacity,
- arraysize(handles), &bytes_read, &handles_read);
+ zx_status_t read_result =
+ handle_.read(0, buffer, buffer_capacity, &bytes_read, handles,
+ base::size(handles), &handles_read);
if (read_result == ZX_OK) {
for (size_t i = 0; i < handles_read; ++i) {
- incoming_handles_.push_back(base::ScopedZxHandle(handles[i]));
+ incoming_handles_.emplace_back(handles[i]);
}
total_bytes_read += bytes_read;
if (!OnReadComplete(bytes_read, &next_read_size)) {
@@ -352,13 +354,13 @@ class ChannelFuchsia : public Channel,
break;
}
} else if (read_result == ZX_ERR_BUFFER_TOO_SMALL) {
- DCHECK_LE(handles_read, arraysize(handles));
+ DCHECK_LE(handles_read, base::size(handles));
next_read_size = bytes_read;
} else if (read_result == ZX_ERR_SHOULD_WAIT) {
break;
} else {
- DLOG_IF(ERROR, read_result != ZX_ERR_PEER_CLOSED)
- << "zx_channel_read: " << zx_status_get_string(read_result);
+ ZX_DLOG_IF(ERROR, read_result != ZX_ERR_PEER_CLOSED, read_result)
+ << "zx_channel_read";
read_error = true;
break;
}
@@ -381,35 +383,34 @@ class ChannelFuchsia : public Channel,
do {
message_view.advance_data_offset(write_bytes);
- std::vector<ScopedInternalPlatformHandle> outgoing_handles =
+ std::vector<PlatformHandleInTransit> outgoing_handles =
message_view.TakeHandles();
zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES] = {};
size_t handles_count = outgoing_handles.size();
- DCHECK_LE(handles_count, arraysize(handles));
+ DCHECK_LE(handles_count, base::size(handles));
for (size_t i = 0; i < handles_count; ++i) {
- DCHECK(outgoing_handles[i].is_valid());
- handles[i] = outgoing_handles[i].get().as_handle();
+ DCHECK(outgoing_handles[i].handle().is_valid());
+ handles[i] = outgoing_handles[i].handle().GetHandle().get();
}
write_bytes = std::min(message_view.data_num_bytes(),
static_cast<size_t>(ZX_CHANNEL_MAX_MSG_BYTES));
- zx_status_t result =
- zx_channel_write(handle_.get().as_handle(), 0, message_view.data(),
- write_bytes, handles, handles_count);
+ zx_status_t result = handle_.write(0, message_view.data(), write_bytes,
+ handles, handles_count);
+ // zx_channel_write() consumes |handles| whether or not it succeeds, so
+ // release() our copies now, to avoid them being double-closed.
+ for (auto& outgoing_handle : outgoing_handles)
+ outgoing_handle.CompleteTransit();
+
if (result != ZX_OK) {
// TODO(fuchsia): Handle ZX_ERR_SHOULD_WAIT flow-control errors, once
- // the platform starts generating them. See crbug.com/754084.
- DLOG_IF(ERROR, result != ZX_ERR_PEER_CLOSED)
- << "WriteNoLock(zx_channel_write): "
- << zx_status_get_string(result);
+ // the platform starts generating them. See https://crbug.com/754084.
+ ZX_DLOG_IF(ERROR, result != ZX_ERR_PEER_CLOSED, result)
+ << "WriteNoLock(zx_channel_write)";
return false;
}
- // |handles| have been transferred to the peer process, so release()
- // them, to avoid them being double-closed.
- for (auto& outgoing_handle : outgoing_handles)
- ignore_result(outgoing_handle.release());
} while (write_bytes < message_view.data_num_bytes());
return true;
@@ -436,12 +437,12 @@ class ChannelFuchsia : public Channel,
// Keeps the Channel alive at least until explicit shutdown on the IO thread.
scoped_refptr<Channel> self_;
- ScopedInternalPlatformHandle handle_;
+ zx::channel handle_;
scoped_refptr<base::TaskRunner> io_task_runner_;
// These members are only used on the IO thread.
std::unique_ptr<base::MessagePumpForIO::ZxHandleWatchController> read_watch_;
- base::circular_deque<base::ScopedZxHandle> incoming_handles_;
+ base::circular_deque<zx::handle> incoming_handles_;
bool leak_handle_ = false;
base::Lock write_lock_;
@@ -461,5 +462,5 @@ scoped_refptr<Channel> Channel::Create(
std::move(io_task_runner));
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/channel_posix.cc b/chromium/mojo/core/channel_posix.cc
index 42d78d533f1..dc7f3a22aad 100644
--- a/chromium/mojo/edk/system/channel_posix.cc
+++ b/chromium/mojo/core/channel_posix.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/channel.h"
+#include "mojo/core/channel.h"
#include <errno.h>
#include <sys/socket.h>
@@ -20,15 +20,20 @@
#include "base/message_loop/message_pump_for_io.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
-#include "mojo/edk/embedder/platform_channel_utils_posix.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "build/build_config.h"
+#include "mojo/core/core.h"
+#include "mojo/public/cpp/platform/socket_utils_posix.h"
#if !defined(OS_NACL)
#include <sys/uio.h>
#endif
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include "mojo/core/mach_port_relay.h"
+#endif
+
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -69,39 +74,52 @@ class MessageView {
offset_ += num_bytes;
}
- std::vector<ScopedInternalPlatformHandle> TakeHandles() {
+ std::vector<PlatformHandleInTransit> TakeHandles() {
return std::move(handles_);
}
Channel::MessagePtr TakeMessage() { return std::move(message_); }
- void SetHandles(std::vector<ScopedInternalPlatformHandle> handles) {
+ void SetHandles(std::vector<PlatformHandleInTransit> handles) {
handles_ = std::move(handles);
}
private:
Channel::MessagePtr message_;
size_t offset_;
- std::vector<ScopedInternalPlatformHandle> handles_;
+ std::vector<PlatformHandleInTransit> handles_;
DISALLOW_COPY_AND_ASSIGN(MessageView);
};
class ChannelPosix : public Channel,
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ public MachPortRelay::Observer,
+#endif
public base::MessageLoopCurrent::DestructionObserver,
public base::MessagePumpForIO::FdWatcher {
public:
ChannelPosix(Delegate* delegate,
ConnectionParams connection_params,
scoped_refptr<base::TaskRunner> io_task_runner)
- : Channel(delegate),
- self_(this),
- handle_(connection_params.TakeChannelHandle()),
- io_task_runner_(io_task_runner)
- {
- CHECK(handle_.is_valid());
+ : Channel(delegate), self_(this), io_task_runner_(io_task_runner) {
+ if (connection_params.server_endpoint().is_valid())
+ server_ = connection_params.TakeServerEndpoint();
+ else
+ socket_ = connection_params.TakeEndpoint().TakePlatformHandle().TakeFD();
+
+ CHECK(server_.is_valid() || socket_.is_valid());
}
void Start() override {
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ auto* relay = Core::Get()->GetMachPortRelay();
+ if (relay) {
+ // We should only have a relay if we know the remote process handle,
+ // because that means we're in the broker process.
+ relay->AddObserver(this);
+ }
+#endif
+
if (io_task_runner_->RunsTasksInCurrentSequence()) {
StartOnIOThread();
} else {
@@ -117,6 +135,30 @@ class ChannelPosix : public Channel,
}
void Write(MessagePtr message) override {
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ // If this message has Mach ports and we have a MachPortRelay, use the relay
+ // to rewrite the ports as receive rights from which the send right can be
+ // read. See |MachPortRelay::SendPortsToProcess()|.
+ //
+ // Note that if we don't have a relay, the receiving process must, and they
+ // must also have the ability to extract a send right from the ports that
+ // are already attached.
+ MachPortRelay* relay = Core::Get()->GetMachPortRelay();
+ if (relay && remote_process().is_valid() && message->has_mach_ports()) {
+ if (relay->port_provider()->TaskForPid(remote_process().get()) ==
+ MACH_PORT_NULL) {
+ // We also need to have a task port for the remote process before we can
+ // send it any other ports. If we don't have one yet, queue the message
+ // until OnProcessReady() is invoked.
+ base::AutoLock lock(task_port_wait_lock_);
+ pending_outgoing_with_mach_ports_.emplace_back(std::move(message));
+ return;
+ }
+
+ relay->SendPortsToProcess(message.get(), remote_process().get());
+ }
+#endif
+
bool write_error = false;
{
base::AutoLock lock(write_lock_);
@@ -143,11 +185,13 @@ class ChannelPosix : public Channel,
leak_handle_ = true;
}
- bool GetReadInternalPlatformHandles(
- size_t num_handles,
- const void* extra_header,
- size_t extra_header_size,
- std::vector<ScopedInternalPlatformHandle>* handles) override {
+ bool GetReadPlatformHandles(const void* payload,
+ size_t payload_size,
+ size_t num_handles,
+ const void* extra_header,
+ size_t extra_header_size,
+ std::vector<PlatformHandle>* handles,
+ bool* deferred) override {
if (num_handles > std::numeric_limits<uint16_t>::max())
return false;
#if defined(OS_MACOSX) && !defined(OS_IOS)
@@ -164,37 +208,75 @@ class ChannelPosix : public Channel,
size_t num_mach_ports = mach_ports_header->num_ports;
if (num_mach_ports > num_handles)
return false;
- if (incoming_platform_handles_.size() + num_mach_ports < num_handles)
+ if (incoming_fds_.size() + num_mach_ports < num_handles)
return true;
- handles->resize(num_handles);
+ std::vector<PlatformHandleInTransit> handles_in_transit(num_handles);
const MachPortsEntry* mach_ports = mach_ports_header->entries;
+
+ // If we know the remote process handle, we assume all incoming Mach ports
+ // are send right references owned by the remote process. Otherwise they're
+ // receive ports we can use to read a send right.
+ const bool extract_send_rights = remote_process().is_valid();
for (size_t i = 0, mach_port_index = 0; i < num_handles; ++i) {
if (mach_port_index < num_mach_ports &&
mach_ports[mach_port_index].index == i) {
- handles->at(i).reset(InternalPlatformHandle(
- static_cast<mach_port_t>(mach_ports[mach_port_index].mach_port)));
- DCHECK_EQ(handles->at(i).get().type,
- InternalPlatformHandle::Type::MACH);
- // These are actually just Mach port names until they're resolved from
- // the remote process.
- handles->at(i).get().type = InternalPlatformHandle::Type::MACH_NAME;
+ mach_port_t port_name =
+ static_cast<mach_port_t>(mach_ports[mach_port_index].mach_port);
+ if (extract_send_rights) {
+ handles_in_transit[i] =
+ PlatformHandleInTransit::CreateForMachPortName(port_name);
+ } else {
+ handles_in_transit[i] = PlatformHandleInTransit(
+ PlatformHandle(MachPortRelay::ReceiveSendRight(
+ base::mac::ScopedMachReceiveRight(port_name))));
+ }
mach_port_index++;
} else {
- if (incoming_platform_handles_.empty())
+ if (incoming_fds_.empty())
return false;
- handles->at(i) = std::move(incoming_platform_handles_.front());
- incoming_platform_handles_.pop_front();
+ handles_in_transit[i] = PlatformHandleInTransit(
+ PlatformHandle(std::move(incoming_fds_.front())));
+ incoming_fds_.pop_front();
}
}
+ if (extract_send_rights && num_mach_ports) {
+ MachPortRelay* relay = Core::Get()->GetMachPortRelay();
+ DCHECK(relay);
+ // Extracting send rights requires that we have a task port for the
+ // remote process, which we may not yet have.
+ if (relay->port_provider()->TaskForPid(remote_process().get()) !=
+ MACH_PORT_NULL) {
+ // We do have a task port, so extract the send rights immediately.
+ for (auto& handle : handles_in_transit) {
+ if (handle.is_mach_port_name()) {
+ handle = PlatformHandleInTransit(PlatformHandle(relay->ExtractPort(
+ handle.mach_port_name(), remote_process().get())));
+ }
+ }
+ } else {
+ // No task port, we have to defer this message.
+ *deferred = true;
+ base::AutoLock lock(task_port_wait_lock_);
+ std::vector<uint8_t> data(payload_size);
+ memcpy(data.data(), payload, payload_size);
+ pending_incoming_with_mach_ports_.emplace_back(
+ std::move(data), std::move(handles_in_transit));
+ return true;
+ }
+ }
+
+ handles->resize(handles_in_transit.size());
+ for (size_t i = 0; i < handles->size(); ++i)
+ handles->at(i) = handles_in_transit[i].TakeHandle();
#else
- if (incoming_platform_handles_.size() < num_handles)
+ if (incoming_fds_.size() < num_handles)
return true;
handles->resize(num_handles);
for (size_t i = 0; i < num_handles; ++i) {
- handles->at(i) = std::move(incoming_platform_handles_.front());
- incoming_platform_handles_.pop_front();
+ handles->at(i) = PlatformHandle(std::move(incoming_fds_.front()));
+ incoming_fds_.pop_front();
}
#endif
@@ -213,15 +295,15 @@ class ChannelPosix : public Channel,
read_watcher_.reset(
new base::MessagePumpForIO::FdWatchController(FROM_HERE));
base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
- if (handle_.get().needs_connection) {
+ if (server_.is_valid()) {
base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- handle_.get().handle, false /* persistent */,
+ server_.platform_handle().GetFD().get(), false /* persistent */,
base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this);
} else {
write_watcher_.reset(
new base::MessagePumpForIO::FdWatchController(FROM_HERE));
base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- handle_.get().handle, true /* persistent */,
+ socket_.get(), true /* persistent */,
base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this);
base::AutoLock lock(write_lock_);
FlushOutgoingMessagesNoLock();
@@ -241,7 +323,7 @@ class ChannelPosix : public Channel,
if (io_task_runner_->RunsTasksInCurrentSequence()) {
pending_write_ = true;
base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- handle_.get().handle, false /* persistent */,
+ socket_.get(), false /* persistent */,
base::MessagePumpForIO::WATCH_WRITE, write_watcher_.get(), this);
} else {
io_task_runner_->PostTask(
@@ -255,17 +337,81 @@ class ChannelPosix : public Channel,
read_watcher_.reset();
write_watcher_.reset();
- if (leak_handle_)
- ignore_result(handle_.release());
- handle_.reset();
+ if (leak_handle_) {
+ ignore_result(socket_.release());
+ server_.TakePlatformHandle().release();
+ } else {
+ socket_.reset();
+ ignore_result(server_.TakePlatformHandle());
+ }
#if defined(OS_MACOSX)
- handles_to_close_.clear();
+ fds_to_close_.clear();
+#endif
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ auto* relay = Core::Get()->GetMachPortRelay();
+ if (relay)
+ relay->RemoveObserver(this);
#endif
// May destroy the |this| if it was the last reference.
self_ = nullptr;
}
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ // MachPortRelay::Observer:
+ void OnProcessReady(base::ProcessHandle process) override {
+ if (process != remote_process().get())
+ return;
+
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &ChannelPosix::FlushPendingMessagesWithMachPortsOnIOThread, this));
+ }
+
+ void FlushPendingMessagesWithMachPortsOnIOThread() {
+ // We have a task port for the remote process. Now we can send or accept
+ // any pending messages with Mach ports.
+ std::vector<RawIncomingMessage> incoming;
+ std::vector<MessagePtr> outgoing;
+ {
+ base::AutoLock lock(task_port_wait_lock_);
+ if (reject_incoming_messages_with_mach_ports_)
+ return;
+ std::swap(pending_incoming_with_mach_ports_, incoming);
+ std::swap(pending_outgoing_with_mach_ports_, outgoing);
+ }
+
+ DCHECK(remote_process().is_valid());
+ base::ProcessHandle process = remote_process().get();
+ MachPortRelay* relay = Core::Get()->GetMachPortRelay();
+ DCHECK(relay);
+ for (auto& message : incoming) {
+ Channel::Delegate* d = delegate();
+ if (!d)
+ break;
+ std::vector<PlatformHandle> handles(message.handles.size());
+ for (size_t i = 0; i < message.handles.size(); ++i) {
+ if (message.handles[i].is_mach_port_name()) {
+ handles[i] = PlatformHandle(
+ relay->ExtractPort(message.handles[i].mach_port_name(), process));
+ } else {
+ DCHECK(!message.handles[i].owning_process().is_valid());
+ handles[i] = message.handles[i].TakeHandle();
+ }
+ }
+ d->OnChannelMessage(message.data.data(), message.data.size(),
+ std::move(handles));
+ }
+
+ for (auto& message : outgoing) {
+ relay->SendPortsToProcess(message.get(), process);
+ Write(std::move(message));
+ }
+ }
+#endif
+
// base::MessageLoopCurrent::DestructionObserver:
void WillDestroyCurrentMessageLoop() override {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
@@ -275,25 +421,25 @@ class ChannelPosix : public Channel,
// base::MessagePumpForIO::FdWatcher:
void OnFileCanReadWithoutBlocking(int fd) override {
- CHECK_EQ(fd, handle_.get().handle);
- if (handle_.get().needs_connection) {
+ if (server_.is_valid()) {
+ CHECK_EQ(fd, server_.platform_handle().GetFD().get());
#if !defined(OS_NACL)
read_watcher_.reset();
base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
- ScopedInternalPlatformHandle accept_fd;
- ServerAcceptConnection(handle_, &accept_fd);
- if (!accept_fd.is_valid()) {
+ AcceptSocketConnection(server_.platform_handle().GetFD().get(), &socket_);
+ ignore_result(server_.TakePlatformHandle());
+ if (!socket_.is_valid()) {
OnError(Error::kConnectionFailed);
return;
}
- handle_ = std::move(accept_fd);
StartOnIOThread();
#else
NOTREACHED();
#endif
return;
}
+ CHECK_EQ(fd, socket_.get());
bool validation_error = false;
bool read_error = false;
@@ -306,8 +452,11 @@ class ChannelPosix : public Channel,
char* buffer = GetReadBuffer(&buffer_capacity);
DCHECK_GT(buffer_capacity, 0u);
- ssize_t read_result = PlatformChannelRecvmsg(
- handle_, buffer, buffer_capacity, &incoming_platform_handles_);
+ std::vector<base::ScopedFD> incoming_fds;
+ ssize_t read_result =
+ SocketRecvmsg(socket_.get(), buffer, buffer_capacity, &incoming_fds);
+ for (auto& fd : incoming_fds)
+ incoming_fds_.emplace_back(std::move(fd));
if (read_result > 0) {
bytes_read = static_cast<size_t>(read_result);
@@ -350,7 +499,7 @@ 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) {
+ if (server_.is_valid()) {
outgoing_messages_.emplace_front(std::move(message_view));
return true;
}
@@ -359,13 +508,15 @@ class ChannelPosix : public Channel,
message_view.advance_data_offset(bytes_written);
ssize_t result;
- std::vector<ScopedInternalPlatformHandle> handles =
- message_view.TakeHandles();
+ std::vector<PlatformHandleInTransit> handles = message_view.TakeHandles();
if (!handles.empty()) {
iovec iov = {const_cast<void*>(message_view.data()),
message_view.data_num_bytes()};
+ std::vector<base::ScopedFD> fds(handles.size());
+ for (size_t i = 0; i < handles.size(); ++i)
+ fds[i] = handles[i].TakeHandle().TakeFD();
// TODO: Handle lots of handles.
- result = PlatformChannelSendmsgWithHandles(handle_, &iov, 1, handles);
+ result = SendmsgWithHandles(socket_.get(), &iov, 1, fds);
if (result >= 0) {
#if defined(OS_MACOSX)
// There is a bug on OSX which makes it dangerous to close
@@ -376,25 +527,29 @@ class ChannelPosix : public Channel,
// letting us know that it is now safe to close the file
// descriptor. For more information, see:
// http://crbug.com/298276
- std::vector<int> fds;
- for (auto& handle : handles)
- fds.push_back(handle.get().handle);
- {
- base::AutoLock l(handles_to_close_lock_);
- for (auto& handle : handles)
- handles_to_close_.emplace_back(std::move(handle));
- }
MessagePtr fds_message(
new Channel::Message(sizeof(fds[0]) * fds.size(), 0,
Message::MessageType::HANDLES_SENT));
memcpy(fds_message->mutable_payload(), fds.data(),
sizeof(fds[0]) * fds.size());
outgoing_messages_.emplace_back(std::move(fds_message), 0);
+ {
+ base::AutoLock l(fds_to_close_lock_);
+ for (auto& fd : fds)
+ fds_to_close_.emplace_back(std::move(fd));
+ }
#endif // defined(OS_MACOSX)
+ } else {
+ // Message transmission failed, so pull the FDs back into |handles|
+ // so they can be held by the Message again.
+ for (size_t i = 0; i < fds.size(); ++i) {
+ handles[i] =
+ PlatformHandleInTransit(PlatformHandle(std::move(fds[i])));
+ }
}
} else {
- result = PlatformChannelWrite(handle_, message_view.data(),
- message_view.data_num_bytes());
+ result = SocketWrite(socket_.get(), message_view.data(),
+ message_view.data_num_bytes());
}
if (result < 0) {
@@ -459,11 +614,10 @@ class ChannelPosix : public Channel,
}
#if defined(OS_MACOSX)
- bool OnControlMessage(
- Message::MessageType message_type,
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) override {
+ bool OnControlMessage(Message::MessageType message_type,
+ const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) override {
switch (message_type) {
case Message::MessageType::HANDLES_SENT: {
if (payload_size == 0)
@@ -494,37 +648,35 @@ class ChannelPosix : public Channel,
}
// Closes handles referenced by |fds|. Returns false if |num_fds| is 0, or if
- // |fds| does not match a sequence of handles in |handles_to_close_|.
+ // |fds| does not match a sequence of handles in |fds_to_close_|.
bool CloseHandles(const int* fds, size_t num_fds) {
- base::AutoLock l(handles_to_close_lock_);
+ base::AutoLock l(fds_to_close_lock_);
if (!num_fds)
return false;
- auto start =
- std::find_if(handles_to_close_.begin(), handles_to_close_.end(),
- [&fds](const ScopedInternalPlatformHandle& handle) {
- return handle.get().handle == fds[0];
- });
- if (start == handles_to_close_.end())
+ auto start = std::find_if(
+ fds_to_close_.begin(), fds_to_close_.end(),
+ [&fds](const base::ScopedFD& fd) { return fd.get() == fds[0]; });
+ if (start == fds_to_close_.end())
return false;
auto it = start;
size_t i = 0;
// The FDs in the message should match a sequence of handles in
- // |handles_to_close_|.
- // TODO(wez): Consider making handles_to_close_ a circular_deque<>
+ // |fds_to_close_|.
+ // TODO(wez): Consider making |fds_to_close_| a circular_deque<>
// for greater efficiency? Or assign a unique Id to each FD-containing
// message, and map that to a vector of FDs to close, to avoid the
// need for this traversal? Id could even be the first FD in the message.
- for (; i < num_fds && it != handles_to_close_.end(); i++, ++it) {
- if (it->get().handle != fds[i])
+ for (; i < num_fds && it != fds_to_close_.end(); i++, ++it) {
+ if (it->get() != fds[i])
return false;
}
if (i != num_fds)
return false;
- // Close the FDs by erase()ing their ScopedInternalPlatformHandles.
- handles_to_close_.erase(start, it);
+ // Close the FDs by erase()ing their ScopedFDs.
+ fds_to_close_.erase(start, it);
return true;
}
#endif // defined(OS_MACOSX)
@@ -549,14 +701,21 @@ class ChannelPosix : public Channel,
// Keeps the Channel alive at least until explicit shutdown on the IO thread.
scoped_refptr<Channel> self_;
- ScopedInternalPlatformHandle handle_;
+ // We may be initialized with a server socket, in which case this will be
+ // valid until it accepts an incoming connection.
+ PlatformChannelServerEndpoint server_;
+
+ // The socket over which to communicate. May be passed in at construction time
+ // or accepted over |server_|.
+ base::ScopedFD socket_;
+
scoped_refptr<base::TaskRunner> io_task_runner_;
// These watchers must only be accessed on the IO thread.
std::unique_ptr<base::MessagePumpForIO::FdWatchController> read_watcher_;
std::unique_ptr<base::MessagePumpForIO::FdWatchController> write_watcher_;
- base::circular_deque<ScopedInternalPlatformHandle> incoming_platform_handles_;
+ base::circular_deque<base::ScopedFD> incoming_fds_;
// Protects |pending_write_| and |outgoing_messages_|.
base::Lock write_lock_;
@@ -567,9 +726,29 @@ class ChannelPosix : public Channel,
bool leak_handle_ = false;
#if defined(OS_MACOSX)
- base::Lock handles_to_close_lock_;
- std::vector<ScopedInternalPlatformHandle> handles_to_close_;
-#endif
+ base::Lock fds_to_close_lock_;
+ std::vector<base::ScopedFD> fds_to_close_;
+#if !defined(OS_IOS)
+ // Guards access to the send/receive queues below. These are messages that
+ // can't be fully accepted from or dispatched to the Channel user yet because
+ // we're still waiting on a task port for the remote process.
+ struct RawIncomingMessage {
+ RawIncomingMessage(std::vector<uint8_t> data,
+ std::vector<PlatformHandleInTransit> handles)
+ : data(std::move(data)), handles(std::move(handles)) {}
+ RawIncomingMessage(RawIncomingMessage&&) = default;
+ ~RawIncomingMessage() = default;
+
+ std::vector<uint8_t> data;
+ std::vector<PlatformHandleInTransit> handles;
+ };
+
+ base::Lock task_port_wait_lock_;
+ bool reject_incoming_messages_with_mach_ports_ = false;
+ std::vector<MessagePtr> pending_outgoing_with_mach_ports_;
+ std::vector<RawIncomingMessage> pending_incoming_with_mach_ports_;
+#endif // !defined(OS_IOS)
+#endif // defined(OS_MACOSX)
DISALLOW_COPY_AND_ASSIGN(ChannelPosix);
};
@@ -585,5 +764,5 @@ scoped_refptr<Channel> Channel::Create(
io_task_runner);
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/channel_unittest.cc b/chromium/mojo/core/channel_unittest.cc
index 90ff9b3728f..e53cc0ffbc1 100644
--- a/chromium/mojo/edk/system/channel_unittest.cc
+++ b/chromium/mojo/core/channel_unittest.cc
@@ -2,18 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/channel.h"
+#include "mojo/core/channel.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/core/platform_handle_utils.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
class TestChannel : public Channel {
@@ -28,11 +29,14 @@ class TestChannel : public Channel {
return OnReadComplete(bytes_read, next_read_size_hint);
}
- MOCK_METHOD4(GetReadInternalPlatformHandles,
- bool(size_t num_handles,
+ MOCK_METHOD7(GetReadPlatformHandles,
+ bool(const void* payload,
+ size_t payload_size,
+ size_t num_handles,
const void* extra_header,
size_t extra_header_size,
- std::vector<ScopedInternalPlatformHandle>* handles));
+ std::vector<PlatformHandle>* handles,
+ bool* deferred));
MOCK_METHOD0(Start, void());
MOCK_METHOD0(ShutDownImpl, void());
MOCK_METHOD0(LeakHandle, void());
@@ -53,10 +57,9 @@ class MockChannelDelegate : public Channel::Delegate {
const void* GetReceivedPayload() const { return payload_.get(); }
protected:
- void OnChannelMessage(
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) override {
+ void OnChannelMessage(const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) override {
payload_.reset(new char[payload_size]);
memcpy(payload_.get(), payload, payload_size);
payload_size_ = payload_size;
@@ -181,7 +184,7 @@ TEST(ChannelTest, OnReadNonLegacyMessage) {
class ChannelTestShutdownAndWriteDelegate : public Channel::Delegate {
public:
ChannelTestShutdownAndWriteDelegate(
- ScopedInternalPlatformHandle handle,
+ PlatformChannelEndpoint endpoint,
scoped_refptr<base::TaskRunner> task_runner,
scoped_refptr<Channel> client_channel,
std::unique_ptr<base::Thread> client_thread,
@@ -189,18 +192,16 @@ class ChannelTestShutdownAndWriteDelegate : public Channel::Delegate {
: quit_closure_(std::move(quit_closure)),
client_channel_(std::move(client_channel)),
client_thread_(std::move(client_thread)) {
- channel_ = Channel::Create(
- this, ConnectionParams(TransportProtocol::kLegacy, std::move(handle)),
- std::move(task_runner));
+ channel_ = Channel::Create(this, ConnectionParams(std::move(endpoint)),
+ std::move(task_runner));
channel_->Start();
}
~ChannelTestShutdownAndWriteDelegate() override { channel_->ShutDown(); }
// Channel::Delegate implementation
- void OnChannelMessage(
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) override {
+ void OnChannelMessage(const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) override {
++message_count_;
// If |client_channel_| exists then close it and its thread.
@@ -240,7 +241,7 @@ class ChannelTestShutdownAndWriteDelegate : public Channel::Delegate {
TEST(ChannelTest, PeerShutdownDuringRead) {
base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
- PlatformChannelPair channel_pair;
+ PlatformChannel channel;
// Create a "client" Channel with one end of the pipe, and Start() it.
std::unique_ptr<base::Thread> client_thread =
@@ -249,9 +250,7 @@ TEST(ChannelTest, PeerShutdownDuringRead) {
base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
scoped_refptr<Channel> client_channel =
- Channel::Create(nullptr,
- ConnectionParams(TransportProtocol::kLegacy,
- channel_pair.PassClientHandle()),
+ Channel::Create(nullptr, ConnectionParams(channel.TakeRemoteEndpoint()),
client_thread->task_runner());
client_channel->Start();
@@ -267,7 +266,7 @@ TEST(ChannelTest, PeerShutdownDuringRead) {
// is received.
base::RunLoop run_loop;
ChannelTestShutdownAndWriteDelegate server_delegate(
- channel_pair.PassServerHandle(), message_loop.task_runner(),
+ channel.TakeLocalEndpoint(), message_loop.task_runner(),
std::move(client_channel), std::move(client_thread),
run_loop.QuitClosure());
@@ -275,5 +274,5 @@ TEST(ChannelTest, PeerShutdownDuringRead) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/channel_win.cc b/chromium/mojo/core/channel_win.cc
index 123e295f9db..30a14867beb 100644
--- a/chromium/mojo/edk/system/channel_win.cc
+++ b/chromium/mojo/core/channel_win.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/channel.h"
+#include "mojo/core/channel.h"
#include <stdint.h>
#include <windows.h>
@@ -18,13 +18,14 @@
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_pump_for_io.h"
+#include "base/process/process_handle.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
+#include "base/win/scoped_handle.h"
#include "base/win/win_util.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -33,13 +34,20 @@ class ChannelWin : public Channel,
public base::MessagePumpForIO::IOHandler {
public:
ChannelWin(Delegate* delegate,
- ScopedInternalPlatformHandle handle,
+ ConnectionParams connection_params,
scoped_refptr<base::TaskRunner> io_task_runner)
- : Channel(delegate),
- self_(this),
- handle_(std::move(handle)),
- io_task_runner_(io_task_runner) {
- CHECK(handle_.is_valid());
+ : Channel(delegate), self_(this), io_task_runner_(io_task_runner) {
+ if (connection_params.server_endpoint().is_valid()) {
+ handle_ = connection_params.TakeServerEndpoint()
+ .TakePlatformHandle()
+ .TakeHandle();
+ needs_connection_ = true;
+ } else {
+ handle_ =
+ connection_params.TakeEndpoint().TakePlatformHandle().TakeHandle();
+ }
+
+ CHECK(handle_.IsValid());
}
void Start() override {
@@ -54,6 +62,17 @@ class ChannelWin : public Channel,
}
void Write(MessagePtr message) override {
+ if (remote_process().is_valid()) {
+ // If we know the remote process handle, we transfer all outgoing handles
+ // to the process now rewriting them in the message.
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
+ for (auto& handle : handles) {
+ if (handle.handle().is_valid())
+ handle.TransferToProcess(remote_process().Clone());
+ }
+ message->SetHandles(std::move(handles));
+ }
+
bool write_error = false;
{
base::AutoLock lock(write_lock_);
@@ -79,11 +98,13 @@ class ChannelWin : public Channel,
leak_handle_ = true;
}
- bool GetReadInternalPlatformHandles(
- size_t num_handles,
- const void* extra_header,
- size_t extra_header_size,
- std::vector<ScopedInternalPlatformHandle>* handles) override {
+ bool GetReadPlatformHandles(const void* payload,
+ size_t payload_size,
+ size_t num_handles,
+ const void* extra_header,
+ size_t extra_header_size,
+ std::vector<PlatformHandle>* handles,
+ bool* deferred) override {
DCHECK(extra_header);
if (num_handles > std::numeric_limits<uint16_t>::max())
return false;
@@ -95,8 +116,17 @@ class ChannelWin : public Channel,
const HandleEntry* extra_header_handles =
reinterpret_cast<const HandleEntry*>(extra_header);
for (size_t i = 0; i < num_handles; i++) {
- handles->emplace_back(ScopedInternalPlatformHandle(InternalPlatformHandle(
- base::win::Uint32ToHandle(extra_header_handles[i].handle))));
+ HANDLE handle_value =
+ base::win::Uint32ToHandle(extra_header_handles[i].handle);
+ if (remote_process().is_valid()) {
+ // If we know the remote process's handle, we assume it doesn't know
+ // ours; that means any handle values still belong to that process, and
+ // we need to transfer them to this process.
+ handle_value = PlatformHandleInTransit::TakeIncomingRemoteHandle(
+ handle_value, remote_process().get())
+ .ReleaseHandle();
+ }
+ handles->emplace_back(base::win::ScopedHandle(std::move(handle_value)));
}
return true;
}
@@ -107,12 +137,11 @@ class ChannelWin : public Channel,
void StartOnIOThread() {
base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
- base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(
- handle_.get().handle, this);
+ base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(handle_.Get(),
+ this);
- if (handle_.get().needs_connection) {
- BOOL ok = ConnectNamedPipe(handle_.get().handle,
- &connect_context_.overlapped);
+ if (needs_connection_) {
+ BOOL ok = ::ConnectNamedPipe(handle_.Get(), &connect_context_.overlapped);
if (ok) {
PLOG(ERROR) << "Unexpected success while waiting for pipe connection";
OnError(Error::kConnectionFailed);
@@ -152,13 +181,14 @@ class ChannelWin : public Channel,
void ShutDownOnIOThread() {
base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
- // BUG(crbug.com/583525): This function is expected to be called once, and
- // |handle_| should be valid at this point.
- CHECK(handle_.is_valid());
- CancelIo(handle_.get().handle);
+ // TODO(https://crbug.com/583525): This function is expected to be called
+ // once, and |handle_| should be valid at this point.
+ CHECK(handle_.IsValid());
+ CancelIo(handle_.Get());
if (leak_handle_)
- ignore_result(handle_.release());
- handle_.reset();
+ ignore_result(handle_.Take());
+ else
+ handle_.Close();
// Allow |this| to be destroyed as soon as no IO is pending.
self_ = nullptr;
@@ -236,13 +266,9 @@ class ChannelWin : public Channel,
outgoing_messages_.pop_front();
// Invalidate all the scoped handles so we don't attempt to close them.
- // Note that we don't simply release these objects because they also own
- // an internal process handle (in |owning_process|) which *does* need to
- // be closed.
- std::vector<ScopedInternalPlatformHandle> handles =
- message->TakeHandles();
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
for (auto& handle : handles)
- handle.get().handle = INVALID_HANDLE_VALUE;
+ handle.CompleteTransit();
// Overlapped WriteFile() to a pipe should always fully complete.
if (message->data_num_bytes() != bytes_written)
@@ -261,12 +287,9 @@ class ChannelWin : public Channel,
char* buffer = GetReadBuffer(&buffer_capacity);
DCHECK_GT(buffer_capacity, 0u);
- BOOL ok = ReadFile(handle_.get().handle,
- buffer,
- static_cast<DWORD>(buffer_capacity),
- NULL,
- &read_context_.overlapped);
-
+ BOOL ok =
+ ::ReadFile(handle_.Get(), buffer, static_cast<DWORD>(buffer_capacity),
+ NULL, &read_context_.overlapped);
if (ok || GetLastError() == ERROR_IO_PENDING) {
is_read_pending_ = true;
AddRef();
@@ -279,10 +302,9 @@ class ChannelWin : 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(const Channel::MessagePtr& message) {
- BOOL ok = WriteFile(handle_.get().handle, message->data(),
+ BOOL ok = WriteFile(handle_.Get(), message->data(),
static_cast<DWORD>(message->data_num_bytes()), NULL,
&write_context_.overlapped);
-
if (ok || GetLastError() == ERROR_IO_PENDING) {
is_write_pending_ = true;
AddRef();
@@ -315,7 +337,12 @@ class ChannelWin : public Channel,
// Keeps the Channel alive at least until explicit shutdown on the IO thread.
scoped_refptr<Channel> self_;
- ScopedInternalPlatformHandle handle_;
+ // The pipe handle this Channel uses for communication.
+ base::win::ScopedHandle handle_;
+
+ // Indicates whether |handle_| must wait for a connection.
+ bool needs_connection_ = false;
+
const scoped_refptr<base::TaskRunner> io_task_runner_;
base::MessagePumpForIO::IOContext connect_context_;
@@ -343,9 +370,8 @@ scoped_refptr<Channel> Channel::Create(
Delegate* delegate,
ConnectionParams connection_params,
scoped_refptr<base::TaskRunner> io_task_runner) {
- return new ChannelWin(delegate, connection_params.TakeChannelHandle(),
- io_task_runner);
+ return new ChannelWin(delegate, std::move(connection_params), io_task_runner);
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/configuration.cc b/chromium/mojo/core/configuration.cc
index f9a5d106ae8..b65612cea4b 100644
--- a/chromium/mojo/edk/system/configuration.cc
+++ b/chromium/mojo/core/configuration.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/configuration.h"
+#include "mojo/core/configuration.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace internal {
Configuration g_configuration;
} // namespace internal
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/configuration.h b/chromium/mojo/core/configuration.h
index 489d20ba2ff..4ba3eeb3cb3 100644
--- a/chromium/mojo/edk/system/configuration.h
+++ b/chromium/mojo/core/configuration.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_CONFIGURATION_H_
-#define MOJO_EDK_SYSTEM_CONFIGURATION_H_
+#ifndef MOJO_CORE_CONFIGURATION_H_
+#define MOJO_CORE_CONFIGURATION_H_
-#include "mojo/edk/embedder/configuration.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/embedder/configuration.h"
+#include "mojo/core/system_impl_export.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace internal {
MOJO_SYSTEM_IMPL_EXPORT extern Configuration g_configuration;
@@ -19,7 +19,7 @@ MOJO_SYSTEM_IMPL_EXPORT inline const Configuration& GetConfiguration() {
return internal::g_configuration;
}
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_CONFIGURATION_H_
+#endif // MOJO_CORE_CONFIGURATION_H_
diff --git a/chromium/mojo/core/connection_params.cc b/chromium/mojo/core/connection_params.cc
new file mode 100644
index 00000000000..444c1a1f3b5
--- /dev/null
+++ b/chromium/mojo/core/connection_params.cc
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium 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/core/connection_params.h"
+
+#include <utility>
+
+#include "base/logging.h"
+
+namespace mojo {
+namespace core {
+
+ConnectionParams::ConnectionParams() = default;
+
+ConnectionParams::ConnectionParams(PlatformChannelEndpoint endpoint)
+ : endpoint_(std::move(endpoint)) {}
+
+ConnectionParams::ConnectionParams(
+ PlatformChannelServerEndpoint server_endpoint)
+ : server_endpoint_(std::move(server_endpoint)) {}
+
+ConnectionParams::ConnectionParams(ConnectionParams&&) = default;
+
+ConnectionParams::~ConnectionParams() = default;
+
+ConnectionParams& ConnectionParams::operator=(ConnectionParams&& params) =
+ default;
+
+} // namespace core
+} // namespace mojo
diff --git a/chromium/mojo/core/connection_params.h b/chromium/mojo/core/connection_params.h
new file mode 100644
index 00000000000..77b41905633
--- /dev/null
+++ b/chromium/mojo/core/connection_params.h
@@ -0,0 +1,49 @@
+// Copyright 2017 The Chromium 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_CORE_CONNECTION_PARAMS_H_
+#define MOJO_CORE_CONNECTION_PARAMS_H_
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "mojo/core/system_impl_export.h"
+#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
+
+namespace mojo {
+namespace core {
+
+// A set of parameters used when establishing a connection to another process.
+class MOJO_SYSTEM_IMPL_EXPORT ConnectionParams {
+ public:
+ ConnectionParams();
+ explicit ConnectionParams(PlatformChannelEndpoint endpoint);
+ explicit ConnectionParams(PlatformChannelServerEndpoint server_endpoint);
+ ConnectionParams(ConnectionParams&&);
+ ~ConnectionParams();
+
+ ConnectionParams& operator=(ConnectionParams&&);
+
+ const PlatformChannelEndpoint& endpoint() const { return endpoint_; }
+ const PlatformChannelServerEndpoint& server_endpoint() const {
+ return server_endpoint_;
+ }
+
+ PlatformChannelEndpoint TakeEndpoint() { return std::move(endpoint_); }
+
+ PlatformChannelServerEndpoint TakeServerEndpoint() {
+ return std::move(server_endpoint_);
+ }
+
+ private:
+ PlatformChannelEndpoint endpoint_;
+ PlatformChannelServerEndpoint server_endpoint_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectionParams);
+};
+
+} // namespace core
+} // namespace mojo
+
+#endif // MOJO_CORE_CONNECTION_PARAMS_H_
diff --git a/chromium/mojo/edk/system/core.cc b/chromium/mojo/core/core.cc
index 58bc403cd50..8422ec247a4 100644
--- a/chromium/mojo/edk/system/core.cc
+++ b/chromium/mojo/core/core.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/core.h"
+#include "mojo/core/core.h"
#include <string.h>
@@ -23,27 +23,27 @@
#include "base/time/time.h"
#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_handle_utils.h"
-#include "mojo/edk/embedder/process_error_callback.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
-#include "mojo/edk/system/data_pipe_producer_dispatcher.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/invitation_dispatcher.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-#include "mojo/edk/system/platform_handle_dispatcher.h"
-#include "mojo/edk/system/platform_shared_memory_mapping.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/name.h"
-#include "mojo/edk/system/ports/node.h"
-#include "mojo/edk/system/request_context.h"
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
-#include "mojo/edk/system/user_message_impl.h"
-#include "mojo/edk/system/watcher_dispatcher.h"
+#include "mojo/core/channel.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/data_pipe_consumer_dispatcher.h"
+#include "mojo/core/data_pipe_producer_dispatcher.h"
+#include "mojo/core/embedder/process_error_callback.h"
+#include "mojo/core/handle_signals_state.h"
+#include "mojo/core/invitation_dispatcher.h"
+#include "mojo/core/message_pipe_dispatcher.h"
+#include "mojo/core/platform_handle_dispatcher.h"
+#include "mojo/core/platform_handle_utils.h"
+#include "mojo/core/platform_shared_memory_mapping.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/name.h"
+#include "mojo/core/ports/node.h"
+#include "mojo/core/request_context.h"
+#include "mojo/core/shared_buffer_dispatcher.h"
+#include "mojo/core/user_message_impl.h"
+#include "mojo/core/watcher_dispatcher.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -54,6 +54,10 @@ const uint32_t kMaxHandlesPerMessage = 1024 * 1024;
// pipes too; for now we just use a constant. This only affects bootstrap pipes.
const uint64_t kUnknownPipeIdForDebug = 0x7f7f7f7f7f7f7f7fUL;
+// The pipe name which must be used for the sole pipe attachment on any isolated
+// invitation.
+constexpr base::StringPiece kIsolatedInvitationPipeName = {"\0\0\0\0", 4};
+
void InvokeProcessErrorCallbackOnTaskRunner(
scoped_refptr<base::TaskRunner> task_runner,
MojoProcessErrorHandler handler,
@@ -80,13 +84,13 @@ void InvokeProcessErrorCallbackOnTaskRunner(
handler, context, error, flags));
}
-// Helper class which is bound to the lifetime of a ProcessErrorCallback
-// generated by the |MojoSendInvitation()| API. When the last reference to the
-// error callback is lost within the EDK, which will happen shortly after a
-// connection to the process is lost, that obviously guarantees that no more
-// invocations of the callback will occur. At that point, the corresponding
-// instance of this object (owned by the callback -- see Core::SendInvitation)
-// will be destroyed.
+// Helper class which is bound to the lifetime of a
+// ProcessErrorCallback generated by the |MojoSendInvitation()|
+// API. When the last reference to the error callback is lost within the EDK,
+// which will happen shortly after a connection to the process is lost, that
+// obviously guarantees that no more invocations of the callback will occur. At
+// that point, the corresponding instance of this object (owned by the callback
+// -- see Core::SendInvitation) will be destroyed.
class ProcessDisconnectHandler {
public:
ProcessDisconnectHandler(scoped_refptr<base::TaskRunner> task_runner,
@@ -135,8 +139,8 @@ Core::~Core() {
scoped_refptr<base::TaskRunner> io_task_runner =
node_controller_->io_task_runner();
io_task_runner->PostTask(FROM_HERE,
- base::Bind(&Core::PassNodeControllerToIOThread,
- base::Passed(&node_controller_)));
+ base::BindOnce(&Core::PassNodeControllerToIOThread,
+ base::Passed(&node_controller_)));
}
base::trace_event::MemoryDumpManager::GetInstance()
->UnregisterAndDeleteDumpProviderSoon(std::move(handles_));
@@ -201,15 +205,12 @@ void Core::AcceptBrokerClientInvitation(ConnectionParams connection_params) {
std::move(connection_params));
}
-uint64_t Core::ConnectToPeer(ConnectionParams connection_params,
- const ports::PortRef& port) {
- RequestContext request_context;
- return GetNodeController()->ConnectToPeer(std::move(connection_params), port);
-}
-
-void Core::ClosePeerConnection(uint64_t peer_connection_id) {
+void Core::ConnectIsolated(ConnectionParams connection_params,
+ const ports::PortRef& port,
+ base::StringPiece connection_name) {
RequestContext request_context;
- GetNodeController()->ClosePeerConnection(peer_connection_id);
+ GetNodeController()->ConnectIsolated(std::move(connection_params), port,
+ connection_name);
}
void Core::SetMachPortProvider(base::PortProvider* port_provider) {
@@ -218,6 +219,12 @@ void Core::SetMachPortProvider(base::PortProvider* port_provider) {
#endif
}
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+MachPortRelay* Core::GetMachPortRelay() {
+ return GetNodeController()->GetMachPortRelay();
+}
+#endif
+
MojoHandle Core::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
base::AutoLock lock(handles_->GetLock());
return handles_->AddDispatcher(dispatcher);
@@ -263,36 +270,6 @@ void Core::ReleaseDispatchersForTransit(
handles_->CancelTransit(dispatchers);
}
-MojoResult Core::CreateInternalPlatformHandleWrapper(
- ScopedInternalPlatformHandle platform_handle,
- MojoHandle* wrapper_handle) {
- MojoHandle h = AddDispatcher(
- PlatformHandleDispatcher::Create(std::move(platform_handle)));
- if (h == MOJO_HANDLE_INVALID)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- *wrapper_handle = h;
- return MOJO_RESULT_OK;
-}
-
-MojoResult Core::PassWrappedInternalPlatformHandle(
- MojoHandle wrapper_handle,
- ScopedInternalPlatformHandle* platform_handle) {
- base::AutoLock lock(handles_->GetLock());
- scoped_refptr<Dispatcher> d;
- MojoResult result = handles_->GetAndRemoveDispatcher(wrapper_handle, &d);
- if (result != MOJO_RESULT_OK)
- return result;
- if (d->GetType() == Dispatcher::Type::PLATFORM_HANDLE) {
- PlatformHandleDispatcher* phd =
- static_cast<PlatformHandleDispatcher*>(d.get());
- *platform_handle = phd->PassInternalPlatformHandle();
- } else {
- result = MOJO_RESULT_INVALID_ARGUMENT;
- }
- d->Close();
- return result;
-}
-
void Core::RequestShutdown(const base::Closure& callback) {
GetNodeController()->RequestShutdown(callback);
}
@@ -338,7 +315,7 @@ MojoResult Core::QueryHandleSignalsState(
MojoResult Core::CreateTrap(MojoTrapEventHandler handler,
const MojoCreateTrapOptions* options,
MojoHandle* trap_handle) {
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
RequestContext request_context;
@@ -356,7 +333,7 @@ MojoResult Core::AddTrigger(MojoHandle trap_handle,
MojoTriggerCondition condition,
uintptr_t context,
const MojoAddTriggerOptions* options) {
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
RequestContext request_context;
@@ -375,7 +352,7 @@ MojoResult Core::AddTrigger(MojoHandle trap_handle,
MojoResult Core::RemoveTrigger(MojoHandle trap_handle,
uintptr_t context,
const MojoRemoveTriggerOptions* options) {
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
RequestContext request_context;
@@ -387,26 +364,23 @@ MojoResult Core::RemoveTrigger(MojoHandle trap_handle,
MojoResult Core::ArmTrap(MojoHandle trap_handle,
const MojoArmTrapOptions* options,
- uint32_t* num_ready_triggers,
- uintptr_t* ready_triggers,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states) {
- if (options && options->struct_size != sizeof(*options))
+ uint32_t* num_blocking_events,
+ MojoTrapEvent* blocking_events) {
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
RequestContext request_context;
scoped_refptr<Dispatcher> watcher = GetDispatcher(trap_handle);
if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER)
return MOJO_RESULT_INVALID_ARGUMENT;
- return watcher->Arm(num_ready_triggers, ready_triggers, ready_results,
- ready_signals_states);
+ return watcher->Arm(num_blocking_events, blocking_events);
}
MojoResult Core::CreateMessage(const MojoCreateMessageOptions* options,
MojoMessageHandle* message_handle) {
if (!message_handle)
return MOJO_RESULT_INVALID_ARGUMENT;
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
*message_handle = reinterpret_cast<MojoMessageHandle>(
UserMessageImpl::CreateEventForNewMessage().release());
@@ -426,7 +400,7 @@ MojoResult Core::SerializeMessage(MojoMessageHandle message_handle,
const MojoSerializeMessageOptions* options) {
if (!message_handle)
return MOJO_RESULT_INVALID_ARGUMENT;
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
RequestContext request_context;
return reinterpret_cast<ports::UserMessageEvent*>(message_handle)
@@ -443,7 +417,7 @@ MojoResult Core::AppendMessageData(MojoMessageHandle message_handle,
uint32_t* buffer_size) {
if (!message_handle || (num_handles && !handles))
return MOJO_RESULT_INVALID_ARGUMENT;
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
RequestContext request_context;
@@ -476,7 +450,7 @@ MojoResult Core::GetMessageData(MojoMessageHandle message_handle,
uint32_t* num_handles) {
if (!message_handle || (num_handles && *num_handles && !handles))
return MOJO_RESULT_INVALID_ARGUMENT;
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle)
@@ -525,7 +499,7 @@ MojoResult Core::SetMessageContext(
const MojoSetMessageContextOptions* options) {
if (!message_handle)
return MOJO_RESULT_INVALID_ARGUMENT;
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle)
->GetMessage<UserMessageImpl>();
@@ -537,7 +511,7 @@ MojoResult Core::GetMessageContext(MojoMessageHandle message_handle,
uintptr_t* context) {
if (!message_handle)
return MOJO_RESULT_INVALID_ARGUMENT;
- if (options && options->struct_size != sizeof(*options))
+ if (options && options->struct_size < sizeof(*options))
return MOJO_RESULT_INVALID_ARGUMENT;
auto* message = reinterpret_cast<ports::UserMessageEvent*>(message_handle)
@@ -681,7 +655,7 @@ MojoResult Core::CreateDataPipe(const MojoCreateDataPipeOptions* options,
MojoHandle* data_pipe_producer_handle,
MojoHandle* data_pipe_consumer_handle) {
RequestContext request_context;
- if (options && options->struct_size != sizeof(MojoCreateDataPipeOptions))
+ if (options && options->struct_size < sizeof(MojoCreateDataPipeOptions))
return MOJO_RESULT_INVALID_ARGUMENT;
MojoCreateDataPipeOptions create_options;
@@ -708,7 +682,7 @@ MojoResult Core::CreateDataPipe(const MojoCreateDataPipeOptions* options,
// consumer of this pipe, and it would be impossible to support such access
// control on Android anyway.
auto writable_region_handle = ring_buffer_region.PassPlatformHandle();
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
(!defined(OS_MACOSX) || defined(OS_IOS))
// This isn't strictly necessary, but it does make the handle configuration
// consistent with regular UnsafeSharedMemoryRegions.
@@ -1011,30 +985,54 @@ MojoResult Core::GetBufferInfo(MojoHandle buffer_handle,
return dispatcher->GetBufferInfo(info);
}
-MojoResult Core::WrapInternalPlatformHandle(
+MojoResult Core::WrapPlatformHandle(
const MojoPlatformHandle* platform_handle,
const MojoWrapPlatformHandleOptions* options,
MojoHandle* mojo_handle) {
- ScopedInternalPlatformHandle handle;
- MojoResult result = MojoPlatformHandleToScopedInternalPlatformHandle(
- platform_handle, &handle);
- if (result != MOJO_RESULT_OK)
- return result;
+ if (!platform_handle ||
+ platform_handle->struct_size < sizeof(*platform_handle)) {
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
- return CreateInternalPlatformHandleWrapper(std::move(handle), mojo_handle);
+ auto handle = PlatformHandle::FromMojoPlatformHandle(platform_handle);
+ MojoHandle h =
+ AddDispatcher(PlatformHandleDispatcher::Create(std::move(handle)));
+ if (h == MOJO_HANDLE_INVALID)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+ *mojo_handle = h;
+ return MOJO_RESULT_OK;
}
-MojoResult Core::UnwrapInternalPlatformHandle(
+MojoResult Core::UnwrapPlatformHandle(
MojoHandle mojo_handle,
const MojoUnwrapPlatformHandleOptions* options,
MojoPlatformHandle* platform_handle) {
- ScopedInternalPlatformHandle handle;
- MojoResult result = PassWrappedInternalPlatformHandle(mojo_handle, &handle);
- if (result != MOJO_RESULT_OK)
- return result;
+ if (!platform_handle ||
+ platform_handle->struct_size < sizeof(*platform_handle)) {
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
- return ScopedInternalPlatformHandleToMojoPlatformHandle(std::move(handle),
- platform_handle);
+ scoped_refptr<Dispatcher> dispatcher;
+ {
+ base::AutoLock lock(handles_->GetLock());
+ dispatcher = handles_->GetDispatcher(mojo_handle);
+ if (dispatcher->GetType() != Dispatcher::Type::PLATFORM_HANDLE)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ MojoResult result =
+ handles_->GetAndRemoveDispatcher(mojo_handle, &dispatcher);
+ if (result != MOJO_RESULT_OK)
+ return result;
+ }
+
+ PlatformHandleDispatcher* phd =
+ static_cast<PlatformHandleDispatcher*>(dispatcher.get());
+ PlatformHandle handle = phd->TakePlatformHandle();
+ phd->Close();
+
+ PlatformHandle::ToMojoPlatformHandle(std::move(handle), platform_handle);
+ return MOJO_RESULT_OK;
}
MojoResult Core::WrapPlatformSharedMemoryRegion(
@@ -1047,7 +1045,7 @@ MojoResult Core::WrapPlatformSharedMemoryRegion(
MojoHandle* mojo_handle) {
DCHECK(size);
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
(!defined(OS_MACOSX) || defined(OS_IOS))
if (access_mode == MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE) {
if (num_platform_handles != 2)
@@ -1058,12 +1056,11 @@ MojoResult Core::WrapPlatformSharedMemoryRegion(
return MOJO_RESULT_INVALID_ARGUMENT;
#endif
- ScopedInternalPlatformHandle handles[2];
+ PlatformHandle handles[2];
bool handles_ok = true;
for (size_t i = 0; i < num_platform_handles; ++i) {
- MojoResult result = MojoPlatformHandleToScopedInternalPlatformHandle(
- &platform_handles[i], &handles[i]);
- if (result != MOJO_RESULT_OK)
+ handles[i] = PlatformHandle::FromMojoPlatformHandle(&platform_handles[i]);
+ if (!handles[i].is_valid())
handles_ok = false;
}
if (!handles_ok)
@@ -1089,7 +1086,7 @@ MojoResult Core::WrapPlatformSharedMemoryRegion(
base::subtle::PlatformSharedMemoryRegion region =
base::subtle::PlatformSharedMemoryRegion::Take(
- CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
+ CreateSharedMemoryRegionHandleFromPlatformHandles(
std::move(handles[0]), std::move(handles[1])),
mode, size, token);
if (!region.IsValid())
@@ -1161,34 +1158,32 @@ MojoResult Core::UnwrapPlatformSharedMemoryRegion(
return MOJO_RESULT_INVALID_ARGUMENT;
}
- ScopedInternalPlatformHandle handle;
- ScopedInternalPlatformHandle read_only_handle;
- ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
+ PlatformHandle handle;
+ PlatformHandle read_only_handle;
+ ExtractPlatformHandlesFromSharedMemoryRegionHandle(
region.PassPlatformHandle(), &handle, &read_only_handle);
const uint32_t available_handle_storage_slots = *num_platform_handles;
if (available_handle_storage_slots < 1)
return MOJO_RESULT_RESOURCE_EXHAUSTED;
*num_platform_handles = 1;
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
(!defined(OS_MACOSX) || defined(OS_IOS))
if (region.GetMode() ==
base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
if (available_handle_storage_slots < 2)
return MOJO_RESULT_INVALID_ARGUMENT;
- if (ScopedInternalPlatformHandleToMojoPlatformHandle(
- std::move(read_only_handle), &platform_handles[1]) !=
- MOJO_RESULT_OK) {
+ PlatformHandle::ToMojoPlatformHandle(std::move(read_only_handle),
+ &platform_handles[1]);
+ if (platform_handles[1].type == MOJO_PLATFORM_HANDLE_TYPE_INVALID)
return MOJO_RESULT_INVALID_ARGUMENT;
- }
*num_platform_handles = 2;
}
#endif
- if (ScopedInternalPlatformHandleToMojoPlatformHandle(
- std::move(handle), &platform_handles[0]) != MOJO_RESULT_OK) {
+ PlatformHandle::ToMojoPlatformHandle(std::move(handle), &platform_handles[0]);
+ if (platform_handles[0].type == MOJO_PLATFORM_HANDLE_TYPE_INVALID)
return MOJO_RESULT_INVALID_ARGUMENT;
- }
return MOJO_RESULT_OK;
}
@@ -1267,7 +1262,8 @@ MojoResult Core::ExtractMessagePipeFromInvitation(
auto* invitation_dispatcher =
static_cast<InvitationDispatcher*>(dispatcher.get());
// First attempt to extract from the invitation object itself. This is for
- // cases where this creation was created in-process.
+ // cases where this invitation was created in-process or is an accepted
+ // isolated invitation.
MojoResult extract_result = invitation_dispatcher->ExtractMessagePipe(
name_string, message_pipe_handle);
if (extract_result == MOJO_RESULT_OK ||
@@ -1336,16 +1332,23 @@ MojoResult Core::SendInvitation(
auto* invitation_dispatcher =
static_cast<InvitationDispatcher*>(dispatcher.get());
- ScopedInternalPlatformHandle endpoint_handle;
- MojoResult result = MojoPlatformHandleToScopedInternalPlatformHandle(
- &transport_endpoint->platform_handles[0], &endpoint_handle);
- if (result != MOJO_RESULT_OK || !endpoint_handle.is_valid())
+ auto endpoint = PlatformHandle::FromMojoPlatformHandle(
+ &transport_endpoint->platform_handles[0]);
+ if (!endpoint.is_valid())
return MOJO_RESULT_INVALID_ARGUMENT;
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_FUCHSIA))
- if (transport_endpoint->type == MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER)
- endpoint_handle.get().needs_connection = true;
+ ConnectionParams connection_params;
+#if defined(OS_WIN) || defined(OS_POSIX)
+ if (transport_endpoint->type ==
+ MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
+ connection_params =
+ ConnectionParams(PlatformChannelServerEndpoint(std::move(endpoint)));
+ }
#endif
+ if (!connection_params.server_endpoint().is_valid()) {
+ connection_params =
+ ConnectionParams(PlatformChannelEndpoint(std::move(endpoint)));
+ }
// At this point everything else has been validated, so we can take ownership
// of the dispatcher.
@@ -1357,15 +1360,13 @@ MojoResult Core::SendInvitation(
if (result != MOJO_RESULT_OK) {
// Release ownership of the endpoint platform handle, per the API
// contract. The caller retains ownership on failure.
- ignore_result(endpoint_handle.release());
+ connection_params.TakeEndpoint().TakePlatformHandle().release();
+ connection_params.TakeServerEndpoint().TakePlatformHandle().release();
return result;
}
DCHECK_EQ(removed_dispatcher.get(), invitation_dispatcher);
}
- ConnectionParams connection_params(TransportProtocol::kLegacy,
- std::move(endpoint_handle));
-
std::vector<std::pair<std::string, ports::PortRef>> attached_ports;
InvitationDispatcher::PortMapping attached_port_map =
invitation_dispatcher->TakeAttachedPorts();
@@ -1373,10 +1374,22 @@ MojoResult Core::SendInvitation(
for (auto& entry : attached_port_map)
attached_ports.emplace_back(entry.first, std::move(entry.second));
+ bool is_isolated =
+ options && (options->flags & MOJO_SEND_INVITATION_FLAG_ISOLATED);
RequestContext request_context;
- GetNodeController()->SendBrokerClientInvitation(
- target_process, std::move(connection_params), attached_ports,
- process_error_callback);
+ if (is_isolated) {
+ DCHECK_EQ(attached_ports.size(), 1u);
+ DCHECK_EQ(attached_ports[0].first, kIsolatedInvitationPipeName);
+ base::StringPiece connection_name(options->isolated_connection_name,
+ options->isolated_connection_name_length);
+ GetNodeController()->ConnectIsolated(std::move(connection_params),
+ attached_ports[0].second,
+ connection_name);
+ } else {
+ GetNodeController()->SendBrokerClientInvitation(
+ target_process, std::move(connection_params), attached_ports,
+ process_error_callback);
+ }
return MOJO_RESULT_OK;
}
@@ -1404,32 +1417,83 @@ MojoResult Core::AcceptInvitation(
if (!invitation_handle)
return MOJO_RESULT_INVALID_ARGUMENT;
- *invitation_handle = AddDispatcher(new InvitationDispatcher);
+ auto dispatcher = base::MakeRefCounted<InvitationDispatcher>();
+ *invitation_handle = AddDispatcher(dispatcher);
if (*invitation_handle == MOJO_HANDLE_INVALID)
return MOJO_RESULT_RESOURCE_EXHAUSTED;
- ScopedInternalPlatformHandle endpoint_handle;
- MojoResult result = MojoPlatformHandleToScopedInternalPlatformHandle(
- &transport_endpoint->platform_handles[0], &endpoint_handle);
- if (result != MOJO_RESULT_OK) {
+ auto endpoint = PlatformHandle::FromMojoPlatformHandle(
+ &transport_endpoint->platform_handles[0]);
+ if (!endpoint.is_valid()) {
Close(*invitation_handle);
*invitation_handle = MOJO_HANDLE_INVALID;
return MOJO_RESULT_INVALID_ARGUMENT;
}
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_FUCHSIA))
- if (transport_endpoint->type == MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER)
- endpoint_handle.get().needs_connection = true;
+ ConnectionParams connection_params;
+#if defined(OS_WIN) || defined(OS_POSIX)
+ if (transport_endpoint->type ==
+ MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
+ connection_params =
+ ConnectionParams(PlatformChannelServerEndpoint(std::move(endpoint)));
+ }
#endif
+ if (!connection_params.server_endpoint().is_valid()) {
+ connection_params =
+ ConnectionParams(PlatformChannelEndpoint(std::move(endpoint)));
+ }
+ bool is_isolated =
+ options && (options->flags & MOJO_ACCEPT_INVITATION_FLAG_ISOLATED);
+ NodeController* const node_controller = GetNodeController();
RequestContext request_context;
- ConnectionParams connection_params(TransportProtocol::kLegacy,
- std::move(endpoint_handle));
- GetNodeController()->AcceptBrokerClientInvitation(
- std::move(connection_params));
+ if (is_isolated) {
+ // For an isolated invitation, we simply mint a new port pair here and send
+ // one name to the remote endpoint while stashing the other in the accepted
+ // invitation object for later extraction.
+ ports::PortRef local_port;
+ ports::PortRef remote_port;
+ node_controller->node()->CreatePortPair(&local_port, &remote_port);
+ node_controller->ConnectIsolated(std::move(connection_params), remote_port,
+ base::StringPiece());
+ MojoResult result =
+ dispatcher->AttachMessagePipe(kIsolatedInvitationPipeName, local_port);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ } else {
+ node_controller->AcceptBrokerClientInvitation(std::move(connection_params));
+ }
+
return MOJO_RESULT_OK;
}
+MojoResult Core::SetQuota(MojoHandle handle,
+ MojoQuotaType type,
+ uint64_t limit,
+ const MojoSetQuotaOptions* options) {
+ RequestContext request_context;
+ if (options && options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ auto dispatcher = GetDispatcher(handle);
+ if (!dispatcher)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ return dispatcher->SetQuota(type, limit);
+}
+
+MojoResult Core::QueryQuota(MojoHandle handle,
+ MojoQuotaType type,
+ const MojoQueryQuotaOptions* options,
+ uint64_t* limit,
+ uint64_t* usage) {
+ RequestContext request_context;
+ if (options && options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ auto dispatcher = GetDispatcher(handle);
+ if (!dispatcher)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ return dispatcher->QueryQuota(type, limit, usage);
+}
+
void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
base::AutoLock lock(handles_->GetLock());
handles_->GetActiveHandlesForTest(handles);
@@ -1445,5 +1509,5 @@ void Core::PassNodeControllerToIOThread(
node_controller.release()->DestroyOnIOThreadShutdown();
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/core.h b/chromium/mojo/core/core.h
index 9401189c809..2840bc5e680 100644
--- a/chromium/mojo/edk/system/core.h
+++ b/chromium/mojo/core/core.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_CORE_H_
-#define MOJO_EDK_SYSTEM_CORE_H_
+#ifndef MOJO_CORE_CORE_H_
+#define MOJO_CORE_CORE_H_
#include <memory>
#include <string>
@@ -15,17 +15,18 @@
#include "base/memory/shared_memory_handle.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/handle_table.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "build/build_config.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/handle_signals_state.h"
+#include "mojo/core/handle_table.h"
+#include "mojo/core/node_controller.h"
+#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/invitation.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/c/system/platform_handle.h"
+#include "mojo/public/c/system/quota.h"
#include "mojo/public/c/system/trap.h"
#include "mojo/public/c/system/types.h"
@@ -34,8 +35,9 @@ class PortProvider;
}
namespace mojo {
-namespace edk {
+namespace core {
+class MachPortRelay;
class PlatformSharedMemoryMapping;
// |Core| is an object that implements the Mojo system calls. All public methods
@@ -86,9 +88,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
const std::vector<std::pair<std::string, ports::PortRef>>& attached_ports,
const ProcessErrorCallback& process_error_callback);
- // Accepts a broker client invitation via |connection_params|. The other end
- // of the connection medium in |connection_params| must have been used by some
- // other process to send an OutgoingBrokerClientInvitation.
+ // Accepts an invitation via |connection_params|. The other end of the
+ // connection medium in |connection_params| must have been used by some other
+ // process to send an invitation.
void AcceptBrokerClientInvitation(ConnectionParams connection_params);
// Extracts a named message pipe endpoint from the broker client invitation
@@ -102,15 +104,21 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// channel. |port| is a port to be merged with the remote peer's port, which
// it will provide via the same API.
//
- // Returns an ID which can be later used to close the connection via
- // ClosePeerConnection().
- uint64_t ConnectToPeer(ConnectionParams connection_params,
- const ports::PortRef& port);
- void ClosePeerConnection(uint64_t peer_connection_id);
+ // |connection_name| if non-empty guarantees that no other isolated
+ // connections exist in the calling process using the same name. This is
+ // useful for invitation endpoints that use a named server accepting multiple
+ // connections.
+ void ConnectIsolated(ConnectionParams connection_params,
+ const ports::PortRef& port,
+ base::StringPiece connection_name);
// Sets the mach port provider for this process.
void SetMachPortProvider(base::PortProvider* port_provider);
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ MachPortRelay* GetMachPortRelay();
+#endif
+
MojoHandle AddDispatcher(scoped_refptr<Dispatcher> dispatcher);
// Adds new dispatchers for non-message-pipe handles received in a message.
@@ -139,15 +147,6 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
bool in_transit);
- // See "mojo/edk/embedder/embedder.h" for more information on these functions.
- MojoResult CreateInternalPlatformHandleWrapper(
- ScopedInternalPlatformHandle platform_handle,
- MojoHandle* wrapper_handle);
-
- MojoResult PassWrappedInternalPlatformHandle(
- MojoHandle wrapper_handle,
- ScopedInternalPlatformHandle* platform_handle);
-
// Requests that the EDK tear itself down. |callback| will be called once
// the shutdown process is complete. Note that |callback| is always called
// asynchronously on the calling thread if said thread is running a message
@@ -160,9 +159,9 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// The following methods are essentially implementations of the Mojo Core
// functions of the Mojo API, with the C interface translated to C++ by
- // "mojo/edk/embedder/entrypoints.cc". The best way to understand the contract
- // of these methods is to look at the header files defining the corresponding
- // API functions, referenced below.
+ // "mojo/core/embedder/entrypoints.cc". The best way to understand the
+ // contract of these methods is to look at the header files defining the
+ // corresponding API functions, referenced below.
// These methods correspond to the API functions defined in
// "mojo/public/c/system/functions.h":
@@ -184,10 +183,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
const MojoRemoveTriggerOptions* options);
MojoResult ArmTrap(MojoHandle trap_handle,
const MojoArmTrapOptions* options,
- uint32_t* num_ready_triggers,
- uintptr_t* ready_triggers,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states);
+ uint32_t* num_blocking_events,
+ MojoTrapEvent* blocking_events);
MojoResult CreateMessage(const MojoCreateMessageOptions* options,
MojoMessageHandle* message_handle);
MojoResult DestroyMessage(MojoMessageHandle message_handle);
@@ -283,11 +280,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// These methods correspond to the API functions defined in
// "mojo/public/c/system/platform_handle.h".
- MojoResult WrapInternalPlatformHandle(
- const MojoPlatformHandle* platform_handle,
- const MojoWrapPlatformHandleOptions* options,
- MojoHandle* mojo_handle);
- MojoResult UnwrapInternalPlatformHandle(
+ MojoResult WrapPlatformHandle(const MojoPlatformHandle* platform_handle,
+ const MojoWrapPlatformHandleOptions* options,
+ MojoHandle* mojo_handle);
+ MojoResult UnwrapPlatformHandle(
MojoHandle mojo_handle,
const MojoUnwrapPlatformHandleOptions* options,
MojoPlatformHandle* platform_handle);
@@ -335,6 +331,17 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
const MojoAcceptInvitationOptions* options,
MojoHandle* invitation_handle);
+ // Quota API.
+ MojoResult SetQuota(MojoHandle handle,
+ MojoQuotaType type,
+ uint64_t limit,
+ const MojoSetQuotaOptions* options);
+ MojoResult QueryQuota(MojoHandle handle,
+ MojoQuotaType type,
+ const MojoQueryQuotaOptions* options,
+ uint64_t* limit,
+ uint64_t* usage);
+
void GetActiveHandlesForTest(std::vector<MojoHandle>* handles);
private:
@@ -372,7 +379,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
DISALLOW_COPY_AND_ASSIGN(Core);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_CORE_H_
+#endif // MOJO_CORE_CORE_H_
diff --git a/chromium/mojo/edk/system/core_test_base.cc b/chromium/mojo/core/core_test_base.cc
index a025a9bbf3b..3be60c5b73f 100644
--- a/chromium/mojo/edk/system/core_test_base.cc
+++ b/chromium/mojo/core/core_test_base.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/core_test_base.h"
+#include "mojo/core/core_test_base.h"
#include <stddef.h>
#include <stdint.h>
@@ -12,13 +12,13 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/user_message_impl.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/core.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/user_message_impl.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace test {
namespace {
@@ -105,11 +105,9 @@ class MockDispatcher : public Dispatcher {
// CoreTestBase ----------------------------------------------------------------
-CoreTestBase::CoreTestBase() {
-}
+CoreTestBase::CoreTestBase() {}
-CoreTestBase::~CoreTestBase() {
-}
+CoreTestBase::~CoreTestBase() {}
MojoHandle CoreTestBase::CreateMockHandle(CoreTestBase::MockHandleInfo* info) {
scoped_refptr<MockDispatcher> dispatcher = MockDispatcher::Create(info);
@@ -135,8 +133,7 @@ CoreTestBase_MockHandleInfo::CoreTestBase_MockHandleInfo()
begin_read_data_call_count_(0),
end_read_data_call_count_(0) {}
-CoreTestBase_MockHandleInfo::~CoreTestBase_MockHandleInfo() {
-}
+CoreTestBase_MockHandleInfo::~CoreTestBase_MockHandleInfo() {}
unsigned CoreTestBase_MockHandleInfo::GetCtorCallCount() const {
base::AutoLock locker(lock_);
@@ -249,5 +246,5 @@ void CoreTestBase_MockHandleInfo::IncrementEndReadDataCallCount() {
}
} // namespace test
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/core_test_base.h b/chromium/mojo/core/core_test_base.h
index 84718be2944..5d37d252c2e 100644
--- a/chromium/mojo/edk/system/core_test_base.h
+++ b/chromium/mojo/core/core_test_base.h
@@ -2,19 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_
-#define MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_
+#ifndef MOJO_CORE_CORE_TEST_BASE_H_
+#define MOJO_CORE_CORE_TEST_BASE_H_
#include <stddef.h>
#include "base/macros.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/system/test_utils.h"
+#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/types.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
class Core;
@@ -87,7 +87,7 @@ class CoreTestBase_MockHandleInfo {
};
} // namespace test
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_
+#endif // MOJO_CORE_CORE_TEST_BASE_H_
diff --git a/chromium/mojo/edk/system/core_unittest.cc b/chromium/mojo/core/core_unittest.cc
index a35208b7a46..8846051ad03 100644
--- a/chromium/mojo/edk/system/core_unittest.cc
+++ b/chromium/mojo/core/core_unittest.cc
@@ -2,15 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/core.h"
+#include "mojo/core/core.h"
#include <stdint.h>
#include <limits>
#include "base/bind.h"
-#include "mojo/edk/system/core_test_base.h"
-#include "mojo/edk/system/test_utils.h"
+#include "build/build_config.h"
+#include "mojo/core/core_test_base.h"
+#include "mojo/core/test_utils.h"
#include "mojo/public/cpp/system/wait.h"
#if defined(OS_WIN)
@@ -18,14 +19,15 @@
#endif
namespace mojo {
-namespace edk {
+namespace core {
namespace {
const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u};
const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u};
const MojoHandleSignals kAllSignals =
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE;
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE |
+ MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED;
using CoreTest = test::CoreTestBase;
@@ -208,14 +210,12 @@ TEST_F(CoreTest, MessagePipe) {
// Check that |h[1]| is no longer writable (and will never be).
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss[1].satisfiable_signals);
+ EXPECT_FALSE(hss[1].satisfiable_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
// Check that |h[1]| is still readable (for the moment).
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss[1].satisfiable_signals);
+ EXPECT_TRUE(hss[1].satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
// Discard a message from |h[1]|.
ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h[1], nullptr, &message));
@@ -225,7 +225,7 @@ TEST_F(CoreTest, MessagePipe) {
hss[1] = kFullMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[1], &hss[1]));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[1].satisfiable_signals);
+ EXPECT_FALSE(hss[1].satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
// Try writing to |h[1]|.
ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message));
@@ -455,5 +455,5 @@ TEST_F(CoreTest, DataPipe) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/chromium/mojo/core/data_pipe_consumer_dispatcher.cc
index 78d6d129e86..68e2f7e24d6 100644
--- a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc
+++ b/chromium/mojo/core/data_pipe_consumer_dispatcher.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
+#include "mojo/core/data_pipe_consumer_dispatcher.h"
#include <stddef.h>
#include <stdint.h>
@@ -14,16 +14,16 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/platform_handle_utils.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/data_pipe_control_message.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/edk/system/request_context.h"
-#include "mojo/edk/system/user_message_impl.h"
+#include "mojo/core/core.h"
+#include "mojo/core/data_pipe_control_message.h"
+#include "mojo/core/node_controller.h"
+#include "mojo/core/platform_handle_utils.h"
+#include "mojo/core/request_context.h"
+#include "mojo/core/user_message_impl.h"
#include "mojo/public/c/system/data_pipe.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -299,7 +299,7 @@ void DataPipeConsumerDispatcher::StartSerialize(uint32_t* num_bytes,
bool DataPipeConsumerDispatcher::EndSerialize(
void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* platform_handles) {
+ PlatformHandle* platform_handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
memcpy(&state->options, &options_, sizeof(MojoCreateDataPipeOptions));
memset(state->padding, 0, sizeof(state->padding));
@@ -320,13 +320,14 @@ bool DataPipeConsumerDispatcher::EndSerialize(
ports[0] = control_port_.name();
- ScopedInternalPlatformHandle ignored_handle;
- ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
- region_handle.PassPlatformHandle(), &platform_handles[0],
- &ignored_handle);
- if (!platform_handles[0].is_valid() || ignored_handle.is_valid())
+ PlatformHandle handle;
+ PlatformHandle ignored_handle;
+ ExtractPlatformHandlesFromSharedMemoryRegionHandle(
+ region_handle.PassPlatformHandle(), &handle, &ignored_handle);
+ if (!handle.is_valid() || ignored_handle.is_valid())
return false;
+ platform_handles[0] = std::move(handle);
return true;
}
@@ -361,7 +362,7 @@ DataPipeConsumerDispatcher::Deserialize(const void* data,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* handles,
+ PlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles != 1 ||
num_bytes != sizeof(SerializedState)) {
@@ -379,11 +380,8 @@ DataPipeConsumerDispatcher::Deserialize(const void* data,
if (node_controller->node()->GetPort(ports[0], &port) != ports::OK)
return nullptr;
- ScopedInternalPlatformHandle buffer_handle;
- std::swap(buffer_handle, handles[0]);
- auto region_handle =
- CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
- std::move(buffer_handle), ScopedInternalPlatformHandle());
+ auto region_handle = CreateSharedMemoryRegionHandleFromPlatformHandles(
+ std::move(handles[0]), PlatformHandle());
auto region = base::subtle::PlatformSharedMemoryRegion::Take(
std::move(region_handle),
base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
@@ -592,5 +590,5 @@ void DataPipeConsumerDispatcher::UpdateSignalsStateNoLock() {
}
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h b/chromium/mojo/core/data_pipe_consumer_dispatcher.h
index 48a63f1ba4a..982d3f055a0 100644
--- a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h
+++ b/chromium/mojo/core/data_pipe_consumer_dispatcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_
+#ifndef MOJO_CORE_DATA_PIPE_CONSUMER_DISPATCHER_H_
+#define MOJO_CORE_DATA_PIPE_CONSUMER_DISPATCHER_H_
#include <stddef.h>
#include <stdint.h>
@@ -15,14 +15,13 @@
#include "base/memory/shared_memory_mapping.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/ports/port_ref.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/edk/system/watcher_set.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/ports/port_ref.h"
+#include "mojo/core/system_impl_export.h"
+#include "mojo/core/watcher_set.h"
namespace mojo {
-namespace edk {
+namespace core {
class NodeController;
@@ -58,7 +57,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) override;
+ PlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
@@ -68,7 +67,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* handles,
+ PlatformHandle* handles,
size_t num_handles);
private:
@@ -123,7 +122,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
DISALLOW_COPY_AND_ASSIGN(DataPipeConsumerDispatcher);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_
+#endif // MOJO_CORE_DATA_PIPE_CONSUMER_DISPATCHER_H_
diff --git a/chromium/mojo/edk/system/data_pipe_control_message.cc b/chromium/mojo/core/data_pipe_control_message.cc
index 6bb0785d71e..cd782e5bc12 100644
--- a/chromium/mojo/edk/system/data_pipe_control_message.cc
+++ b/chromium/mojo/core/data_pipe_control_message.cc
@@ -2,15 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/data_pipe_control_message.h"
+#include "mojo/core/data_pipe_control_message.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/user_message_impl.h"
+#include "mojo/core/node_controller.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/user_message_impl.h"
namespace mojo {
-namespace edk {
+namespace core {
void SendDataPipeControlMessage(NodeController* node_controller,
const ports::PortRef& port,
@@ -34,5 +33,5 @@ void SendDataPipeControlMessage(NodeController* node_controller,
}
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/data_pipe_control_message.h b/chromium/mojo/core/data_pipe_control_message.h
index ec84ea3c559..3493e2b8b7b 100644
--- a/chromium/mojo/edk/system/data_pipe_control_message.h
+++ b/chromium/mojo/core/data_pipe_control_message.h
@@ -2,19 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_DATA_PIPE_CONTROL_MESSAGE_H_
-#define MOJO_EDK_SYSTEM_DATA_PIPE_CONTROL_MESSAGE_H_
+#ifndef MOJO_CORE_DATA_PIPE_CONTROL_MESSAGE_H_
+#define MOJO_CORE_DATA_PIPE_CONTROL_MESSAGE_H_
#include <stdint.h>
#include <memory>
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/ports/port_ref.h"
+#include "mojo/core/ports/port_ref.h"
#include "mojo/public/c/system/macros.h"
namespace mojo {
-namespace edk {
+namespace core {
class NodeController;
@@ -37,7 +36,7 @@ void SendDataPipeControlMessage(NodeController* node_controller,
DataPipeCommand command,
uint32_t num_bytes);
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_DATA_PIPE_CONTROL_MESSAGE_H_
+#endif // MOJO_CORE_DATA_PIPE_CONTROL_MESSAGE_H_
diff --git a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc b/chromium/mojo/core/data_pipe_producer_dispatcher.cc
index caa76d959ef..e6256f8f0d9 100644
--- a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc
+++ b/chromium/mojo/core/data_pipe_producer_dispatcher.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/data_pipe_producer_dispatcher.h"
+#include "mojo/core/data_pipe_producer_dispatcher.h"
#include <stddef.h>
#include <stdint.h>
@@ -12,17 +12,17 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/platform_handle_utils.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/data_pipe_control_message.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/edk/system/request_context.h"
-#include "mojo/edk/system/user_message_impl.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/core.h"
+#include "mojo/core/data_pipe_control_message.h"
+#include "mojo/core/node_controller.h"
+#include "mojo/core/platform_handle_utils.h"
+#include "mojo/core/request_context.h"
+#include "mojo/core/user_message_impl.h"
#include "mojo/public/c/system/data_pipe.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -258,7 +258,7 @@ void DataPipeProducerDispatcher::StartSerialize(uint32_t* num_bytes,
bool DataPipeProducerDispatcher::EndSerialize(
void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* platform_handles) {
+ PlatformHandle* platform_handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
memcpy(&state->options, &options_, sizeof(MojoCreateDataPipeOptions));
memset(state->padding, 0, sizeof(state->padding));
@@ -279,13 +279,14 @@ bool DataPipeProducerDispatcher::EndSerialize(
ports[0] = control_port_.name();
- ScopedInternalPlatformHandle ignored_handle;
- ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
- region_handle.PassPlatformHandle(), &platform_handles[0],
- &ignored_handle);
- if (!platform_handles[0].is_valid() || ignored_handle.is_valid())
+ PlatformHandle handle;
+ PlatformHandle ignored_handle;
+ ExtractPlatformHandlesFromSharedMemoryRegionHandle(
+ region_handle.PassPlatformHandle(), &handle, &ignored_handle);
+ if (!handle.is_valid() || ignored_handle.is_valid())
return false;
+ platform_handles[0] = std::move(handle);
return true;
}
@@ -322,7 +323,7 @@ DataPipeProducerDispatcher::Deserialize(const void* data,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* handles,
+ PlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles != 1 ||
num_bytes != sizeof(SerializedState)) {
@@ -340,11 +341,8 @@ DataPipeProducerDispatcher::Deserialize(const void* data,
if (node_controller->node()->GetPort(ports[0], &port) != ports::OK)
return nullptr;
- ScopedInternalPlatformHandle buffer_handle;
- std::swap(buffer_handle, handles[0]);
- auto region_handle =
- CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
- std::move(buffer_handle), ScopedInternalPlatformHandle());
+ auto region_handle = CreateSharedMemoryRegionHandleFromPlatformHandles(
+ std::move(handles[0]), PlatformHandle());
auto region = base::subtle::PlatformSharedMemoryRegion::Take(
std::move(region_handle),
base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
@@ -536,5 +534,5 @@ void DataPipeProducerDispatcher::UpdateSignalsStateNoLock() {
}
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h b/chromium/mojo/core/data_pipe_producer_dispatcher.h
index 4ee72c8e426..15cd1c9b0de 100644
--- a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h
+++ b/chromium/mojo/core/data_pipe_producer_dispatcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_
+#ifndef MOJO_CORE_DATA_PIPE_PRODUCER_DISPATCHER_H_
+#define MOJO_CORE_DATA_PIPE_PRODUCER_DISPATCHER_H_
#include <stddef.h>
#include <stdint.h>
@@ -15,14 +15,13 @@
#include "base/memory/shared_memory_mapping.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/ports/port_ref.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/edk/system/watcher_set.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/ports/port_ref.h"
+#include "mojo/core/system_impl_export.h"
+#include "mojo/core/watcher_set.h"
namespace mojo {
-namespace edk {
+namespace core {
class NodeController;
@@ -57,7 +56,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) override;
+ PlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
@@ -67,7 +66,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* handles,
+ PlatformHandle* handles,
size_t num_handles);
private:
@@ -114,7 +113,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
DISALLOW_COPY_AND_ASSIGN(DataPipeProducerDispatcher);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_
+#endif // MOJO_CORE_DATA_PIPE_PRODUCER_DISPATCHER_H_
diff --git a/chromium/mojo/edk/system/data_pipe_unittest.cc b/chromium/mojo/core/data_pipe_unittest.cc
index dbee3ed8b45..b2f32a4c29a 100644
--- a/chromium/mojo/edk/system/data_pipe_unittest.cc
+++ b/chromium/mojo/core/data_pipe_unittest.cc
@@ -13,10 +13,10 @@
#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"
-#include "mojo/edk/test/mojo_test_base.h"
+#include "build/build_config.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/c/system/message_pipe.h"
@@ -25,7 +25,7 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
const uint32_t kSizeOfOptions =
@@ -2043,5 +2043,5 @@ TEST_F(DataPipeTest, StatusChangeInTransit) {
#endif // !defined(OS_IOS)
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/dispatcher.cc b/chromium/mojo/core/dispatcher.cc
index 6d9f875a1c0..a110dbdc8e4 100644
--- a/chromium/mojo/edk/system/dispatcher.cc
+++ b/chromium/mojo/core/dispatcher.cc
@@ -2,19 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/dispatcher.h"
+#include "mojo/core/dispatcher.h"
#include "base/logging.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
-#include "mojo/edk/system/data_pipe_producer_dispatcher.h"
-#include "mojo/edk/system/message_pipe_dispatcher.h"
-#include "mojo/edk/system/platform_handle_dispatcher.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/data_pipe_consumer_dispatcher.h"
+#include "mojo/core/data_pipe_producer_dispatcher.h"
+#include "mojo/core/message_pipe_dispatcher.h"
+#include "mojo/core/platform_handle_dispatcher.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/shared_buffer_dispatcher.h"
namespace mojo {
-namespace edk {
+namespace core {
Dispatcher::DispatcherInTransit::DispatcherInTransit() {}
@@ -34,10 +34,8 @@ MojoResult Dispatcher::CancelWatch(uintptr_t context) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
-MojoResult Dispatcher::Arm(uint32_t* num_ready_contexts,
- uintptr_t* ready_contexts,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states) {
+MojoResult Dispatcher::Arm(uint32_t* num_blocking_events,
+ MojoTrapEvent* blocking_events) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
@@ -108,6 +106,16 @@ MojoResult Dispatcher::ExtractMessagePipe(base::StringPiece name,
return MOJO_RESULT_INVALID_ARGUMENT;
}
+MojoResult Dispatcher::SetQuota(MojoQuotaType type, uint64_t limit) {
+ return MOJO_RESULT_INVALID_ARGUMENT;
+}
+
+MojoResult Dispatcher::QueryQuota(MojoQuotaType type,
+ uint64_t* limit,
+ uint64_t* usage) {
+ return MOJO_RESULT_INVALID_ARGUMENT;
+}
+
HandleSignalsState Dispatcher::GetHandleSignalsState() const {
return HandleSignalsState();
}
@@ -133,7 +141,7 @@ void Dispatcher::StartSerialize(uint32_t* num_bytes,
bool Dispatcher::EndSerialize(void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) {
+ PlatformHandle* handles) {
LOG(ERROR) << "Attempting to serialize a non-transferrable dispatcher.";
return true;
}
@@ -153,7 +161,7 @@ scoped_refptr<Dispatcher> Dispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* platform_handles,
+ PlatformHandle* platform_handles,
size_t num_platform_handles) {
switch (type) {
case Type::MESSAGE_PIPE:
@@ -186,5 +194,5 @@ Dispatcher::Dispatcher() {}
Dispatcher::~Dispatcher() {}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/dispatcher.h b/chromium/mojo/core/dispatcher.h
index 3776be2e812..58cd7a7a39d 100644
--- a/chromium/mojo/edk/system/dispatcher.h
+++ b/chromium/mojo/core/dispatcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_DISPATCHER_H_
+#ifndef MOJO_CORE_DISPATCHER_H_
+#define MOJO_CORE_DISPATCHER_H_
#include <stddef.h>
#include <stdint.h>
@@ -16,21 +16,21 @@
#include "base/memory/ref_counted.h"
#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/ports/name.h"
-#include "mojo/edk/system/ports/port_ref.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/edk/system/watch.h"
+#include "mojo/core/handle_signals_state.h"
+#include "mojo/core/ports/name.h"
+#include "mojo/core/ports/port_ref.h"
+#include "mojo/core/system_impl_export.h"
+#include "mojo/core/watch.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/message_pipe.h"
+#include "mojo/public/c/system/quota.h"
#include "mojo/public/c/system/trap.h"
#include "mojo/public/c/system/types.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
class UserMessageEvent;
@@ -80,10 +80,8 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
MojoTriggerCondition condition,
uintptr_t context);
virtual MojoResult CancelWatch(uintptr_t context);
- virtual MojoResult Arm(uint32_t* num_ready_contexts,
- uintptr_t* ready_contexts,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states);
+ virtual MojoResult Arm(uint32_t* num_blocking_events,
+ MojoTrapEvent* blocking_events);
///////////// Message pipe API /////////////
@@ -136,6 +134,12 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
virtual MojoResult ExtractMessagePipe(base::StringPiece name,
MojoHandle* message_pipe_handle);
+ // Quota API.
+ virtual MojoResult SetQuota(MojoQuotaType type, uint64_t limit);
+ virtual MojoResult QueryQuota(MojoQuotaType type,
+ uint64_t* limit,
+ uint64_t* usage);
+
///////////// General-purpose API for all handle types /////////
// Gets the current handle signals state. (The default implementation simply
@@ -177,13 +181,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
// will close.
//
// NOTE: Transit MAY still fail after this call returns. Implementations
- // should not assume InternalPlatformHandle ownership has transferred until
+ // should not assume PlatformHandle ownership has transferred until
// CompleteTransitAndClose() is called. In other words, if CancelTransit() is
- // called, the implementation should retain its InternalPlatformHandles in
- // working condition.
+ // called, the implementation should retain its PlatformHandles in working
+ // condition.
virtual bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* handles);
+ PlatformHandle* handles);
// Does whatever is necessary to begin transit of the dispatcher. This
// should return |true| if transit is OK, or false if the underlying resource
@@ -200,14 +204,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
virtual void CancelTransit();
// Deserializes a specific dispatcher type from an incoming message.
- static scoped_refptr<Dispatcher> Deserialize(
- Type type,
- const void* bytes,
- size_t num_bytes,
- const ports::PortName* ports,
- size_t num_ports,
- ScopedInternalPlatformHandle* platform_handles,
- size_t platform_handle_count);
+ static scoped_refptr<Dispatcher> Deserialize(Type type,
+ const void* bytes,
+ size_t num_bytes,
+ const ports::PortName* ports,
+ size_t num_ports,
+ PlatformHandle* platform_handles,
+ size_t platform_handle_count);
protected:
friend class base::RefCountedThreadSafe<Dispatcher>;
@@ -224,7 +227,7 @@ MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out,
return out << static_cast<int>(type);
}
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_DISPATCHER_H_
+#endif // MOJO_CORE_DISPATCHER_H_
diff --git a/chromium/mojo/core/embedder/BUILD.gn b/chromium/mojo/core/embedder/BUILD.gn
new file mode 100644
index 00000000000..47f1c390166
--- /dev/null
+++ b/chromium/mojo/core/embedder/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+component("embedder") {
+ output_name = "mojo_core_embedder"
+
+ public = [
+ "configuration.h",
+ "embedder.h",
+ "scoped_ipc_support.h",
+ ]
+
+ sources = [
+ "embedder.cc",
+ "scoped_ipc_support.cc",
+ ]
+
+ defines = [ "IS_MOJO_CORE_EMBEDDER_IMPL" ]
+
+ public_deps = [
+ "//base",
+ ]
+
+ deps = [
+ "//mojo/core:embedder_internal",
+ "//mojo/public/c/system",
+ ]
+}
diff --git a/chromium/mojo/core/embedder/README.md b/chromium/mojo/core/embedder/README.md
new file mode 100644
index 00000000000..7183a6374db
--- /dev/null
+++ b/chromium/mojo/core/embedder/README.md
@@ -0,0 +1,86 @@
+# Mojo Core Embedder API
+This document is a subset of the [Mojo documentation](/mojo/README.md).
+
+[TOC]
+
+## Overview
+
+The Mojo Core Embedder API enables process to initialize and use Mojo for IPC,
+using an implementation of Mojo Core that is statically linked into the
+application. See the note about dynamic linking
+[here](/mojo/README.md#Mojo-Core) for more information about an alternative
+approach to Mojo Core initialization.
+
+**NOTE:** Unless you are introducing a new binary entry point into the system
+(*e.g.,* a new executable with a new `main()` definition), you probably don't
+need to know anything about the Embedder API. Most processes defined in the
+Chrome repo today already fully initialize Mojo Core so that all other public
+Mojo APIs just work out of the box.
+
+## Basic Initialization
+
+As an embedder, initializing Mojo Core requires a single call to
+`mojo::core::Init`:
+
+```
+#include "mojo/core/embedder/embedder.h"
+
+int main(int argc, char** argv) {
+ mojo::core::Init();
+
+ // Now you can create message pipes, write messages, etc
+
+ return 0;
+}
+```
+
+This enables local API calls to work, so message pipes *etc* can be created and
+used. In some cases (particuarly many unit testing scenarios) this is
+sufficient, but to support any actual multiprocess communication (e.g. sending
+or accepting Mojo invitations), a second IPC initialization step is required.
+
+## IPC Initialization
+
+Internal Mojo IPC implementation requires a background `TaskRunner` on which it
+can watch for inbound I/O from other processes. This is configured using a
+`ScopedIPCSupport` object, which keeps IPC support alive through the extent of
+its lifetime.
+
+Typically an application will create a dedicated background thread and give its
+`TaskRunner` to Mojo. Note that in Chromium, we use the existing "IO thread" in
+the browser process and content child processes. In general, any thread used
+for Mojo IPC support must be running a `base::MessageLoop::TYPE_IO` loop.
+
+```
+#include "base/threading/thread.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/embedder/scoped_ipc_support.h"
+
+int main(int argc, char** argv) {
+ mojo::core::Init();
+
+ base::Thread ipc_thread("ipc!");
+ ipc_thread.StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+
+ // As long as this object is alive, all Mojo API surface relevant to IPC
+ // connections is usable, and message pipes which span a process boundary will
+ // continue to function.
+ mojo::core::ScopedIPCSupport ipc_support(
+ ipc_thread.task_runner(),
+ mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
+
+ return 0;
+}
+```
+
+This process is now fully prepared to use Mojo IPC!
+
+Note that all existing process types in Chromium already perform this setup
+very early during startup.
+
+## Connecting Two Processes
+
+Once IPC is initialized, you can bootstrap connections to other processes by
+using the public
+[Invitations API](/mojo/public/cpp/system/README.md#Invitations).
diff --git a/chromium/mojo/edk/embedder/configuration.h b/chromium/mojo/core/embedder/configuration.h
index d02b9995e60..f4621dcd174 100644
--- a/chromium/mojo/edk/embedder/configuration.h
+++ b/chromium/mojo/core/embedder/configuration.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_EMBEDDER_CONFIGURATION_H_
-#define MOJO_EDK_EMBEDDER_CONFIGURATION_H_
+#ifndef MOJO_CORE_EMBEDDER_CONFIGURATION_H_
+#define MOJO_CORE_EMBEDDER_CONFIGURATION_H_
#include <stddef.h>
#include <stdint.h>
namespace mojo {
-namespace edk {
+namespace core {
// A set of configuration parameters that the Mojo system uses internally. The
// configuration used can be overridden from the default by passing a
-// Configuration into |mojo::edk::Init()|. See embedder.h.
+// Configuration into |mojo::core::Init()|. See embedder.h.
//
// NOTE: Please ensure that this type remains a simple aggregate of POD fields.
struct Configuration {
@@ -41,7 +41,7 @@ struct Configuration {
size_t max_shared_memory_num_bytes = 1024 * 1024 * 1024;
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_EMBEDDER_CONFIGURATION_H_
+#endif // MOJO_CORE_EMBEDDER_CONFIGURATION_H_
diff --git a/chromium/mojo/core/embedder/embedder.cc b/chromium/mojo/core/embedder/embedder.cc
new file mode 100644
index 00000000000..4044de083ee
--- /dev/null
+++ b/chromium/mojo/core/embedder/embedder.cc
@@ -0,0 +1,50 @@
+// 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/core/embedder/embedder.h"
+
+#include <stdint.h>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/task_runner.h"
+#include "build/build_config.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/core.h"
+#include "mojo/core/entrypoints.h"
+#include "mojo/core/node_controller.h"
+#include "mojo/public/c/system/thunks.h"
+
+namespace mojo {
+namespace core {
+
+void Init(const Configuration& configuration) {
+ internal::g_configuration = configuration;
+ InitializeCore();
+ MojoEmbedderSetSystemThunks(&GetSystemThunks());
+}
+
+void Init() {
+ Init(Configuration());
+}
+
+void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback) {
+ Core::Get()->SetDefaultProcessErrorCallback(callback);
+}
+
+scoped_refptr<base::TaskRunner> GetIOTaskRunner() {
+ return Core::Get()->GetNodeController()->io_task_runner();
+}
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+void SetMachPortProvider(base::PortProvider* port_provider) {
+ DCHECK(port_provider);
+ Core::Get()->SetMachPortProvider(port_provider);
+}
+#endif
+
+} // namespace core
+} // namespace mojo
diff --git a/chromium/mojo/core/embedder/embedder.h b/chromium/mojo/core/embedder/embedder.h
new file mode 100644
index 00000000000..feb7ca1be4b
--- /dev/null
+++ b/chromium/mojo/core/embedder/embedder.h
@@ -0,0 +1,65 @@
+// 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_CORE_EMBEDDER_EMBEDDER_H_
+#define MOJO_CORE_EMBEDDER_EMBEDDER_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory_handle.h"
+#include "base/process/process_handle.h"
+#include "base/task_runner.h"
+#include "build/build_config.h"
+#include "mojo/core/embedder/configuration.h"
+
+namespace base {
+class PortProvider;
+}
+
+namespace mojo {
+namespace core {
+
+using ProcessErrorCallback = base::Callback<void(const std::string& error)>;
+
+// Basic configuration/initialization ------------------------------------------
+
+// Must be called first, or just after setting configuration parameters, to
+// initialize the (global, singleton) system state. There is no corresponding
+// shutdown operation: once the embedder is initialized, public Mojo C API calls
+// remain available for the remainder of the process's lifetime.
+COMPONENT_EXPORT(MOJO_CORE_EMBEDDER)
+void Init(const Configuration& configuration);
+
+// Like above but uses a default Configuration.
+COMPONENT_EXPORT(MOJO_CORE_EMBEDDER) void Init();
+
+// Sets a default callback to invoke when an internal error is reported but
+// cannot be associated with a specific child process. Calling this is optional.
+COMPONENT_EXPORT(MOJO_CORE_EMBEDDER)
+void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback);
+
+// Initialialization/shutdown for interprocess communication (IPC) -------------
+
+// Retrieves the TaskRunner used for IPC I/O, as set by ScopedIPCSupport.
+COMPONENT_EXPORT(MOJO_CORE_EMBEDDER)
+scoped_refptr<base::TaskRunner> GetIOTaskRunner();
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+// Set the |base::PortProvider| for this process. Can be called on any thread,
+// but must be set in the root process before any Mach ports can be transferred.
+//
+// If called at all, this must be called while a ScopedIPCSupport exists.
+COMPONENT_EXPORT(MOJO_CORE_EMBEDDER)
+void SetMachPortProvider(base::PortProvider* port_provider);
+#endif
+
+} // namespace core
+} // namespace mojo
+
+#endif // MOJO_CORE_EMBEDDER_EMBEDDER_H_
diff --git a/chromium/mojo/edk/embedder/process_error_callback.h b/chromium/mojo/core/embedder/process_error_callback.h
index 53234def1f4..f60ce899906 100644
--- a/chromium/mojo/edk/embedder/process_error_callback.h
+++ b/chromium/mojo/core/embedder/process_error_callback.h
@@ -2,20 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_EMBEDDER_PROCESS_ERROR_CALLBACK_H_
-#define MOJO_EDK_EMBEDDER_PROCESS_ERROR_CALLBACK_H_
+#ifndef MOJO_CORE_EMBEDDER_PROCESS_ERROR_CALLBACK_H_
+#define MOJO_CORE_EMBEDDER_PROCESS_ERROR_CALLBACK_H_
#include <string>
#include "base/callback.h"
namespace mojo {
-namespace edk {
+namespace core {
using ProcessErrorCallback =
base::RepeatingCallback<void(const std::string& error)>;
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_EMBEDDER_PROCESS_ERROR_CALLBACK_H_
+#endif // MOJO_CORE_EMBEDDER_PROCESS_ERROR_CALLBACK_H_
diff --git a/chromium/mojo/edk/embedder/scoped_ipc_support.cc b/chromium/mojo/core/embedder/scoped_ipc_support.cc
index a0231726d8f..71174f535ea 100644
--- a/chromium/mojo/edk/embedder/scoped_ipc_support.cc
+++ b/chromium/mojo/core/embedder/scoped_ipc_support.cc
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/embedder/scoped_ipc_support.h"
+#include "mojo/core/embedder/scoped_ipc_support.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
-#include "mojo/edk/system/core.h"
+#include "mojo/core/core.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -23,7 +23,8 @@ void ShutdownIPCSupport(const base::Closure& callback) {
ScopedIPCSupport::ScopedIPCSupport(
scoped_refptr<base::TaskRunner> io_thread_task_runner,
- ShutdownPolicy shutdown_policy) : shutdown_policy_(shutdown_policy) {
+ ShutdownPolicy shutdown_policy)
+ : shutdown_policy_(shutdown_policy) {
Core::Get()->SetIOTaskRunner(io_thread_task_runner);
}
@@ -39,9 +40,9 @@ ScopedIPCSupport::~ScopedIPCSupport() {
ShutdownIPCSupport(base::Bind(&base::WaitableEvent::Signal,
base::Unretained(&shutdown_event)));
- base::ThreadRestrictions::ScopedAllowWait allow_io;
+ base::ScopedAllowBaseSyncPrimitives allow_io;
shutdown_event.Wait();
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/scoped_ipc_support.h b/chromium/mojo/core/embedder/scoped_ipc_support.h
index 83611b76b51..8afcd00d541 100644
--- a/chromium/mojo/edk/embedder/scoped_ipc_support.h
+++ b/chromium/mojo/core/embedder/scoped_ipc_support.h
@@ -2,23 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_
-#define MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_
+#ifndef MOJO_CORE_EMBEDDER_SCOPED_IPC_SUPPORT_H_
+#define MOJO_CORE_EMBEDDER_SCOPED_IPC_SUPPORT_H_
+#include "base/component_export.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/system_impl_export.h"
namespace base {
class TaskRunner;
}
namespace mojo {
-namespace edk {
+namespace core {
// A simple class that initialized Mojo IPC support on construction and shuts
// down IPC support on destruction, optionally blocking the destructor on clean
// IPC shutdown completion.
-class MOJO_SYSTEM_IMPL_EXPORT ScopedIPCSupport {
+class COMPONENT_EXPORT(MOJO_CORE_EMBEDDER) ScopedIPCSupport {
public:
// ShutdownPolicy is a type for specifying the desired Mojo IPC support
// shutdown behavior used during ScopedIPCSupport destruction.
@@ -32,7 +32,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ScopedIPCSupport {
// In order to facilitate efficient and reliable transfer of Mojo message pipe
// endpoints across process boundaries, the underlying model for a message
// pipe is actually a self-collapsing cycle of "ports." See
- // //mojo/edk/system/ports for gritty implementation details.
+ // //mojo/core/ports for gritty implementation details.
//
// Ports are essentially globally unique identifiers used for system-wide
// message routing. Every message pipe consists of at least two such ports:
@@ -112,7 +112,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ScopedIPCSupport {
DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_
+#endif // MOJO_CORE_EMBEDDER_SCOPED_IPC_SUPPORT_H_
diff --git a/chromium/mojo/edk/embedder/embedder_unittest.cc b/chromium/mojo/core/embedder_unittest.cc
index e0e3c194fd8..f336f4c8f70 100644
--- a/chromium/mojo/edk/embedder/embedder_unittest.cc
+++ b/chromium/mojo/core/embedder_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include <stddef.h>
#include <stdint.h>
@@ -22,29 +22,26 @@
#include "base/memory/writable_shared_memory_region.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
-#include "base/process/process_handle.h"
+#include "base/rand_util.h"
#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/named_platform_handle.h"
-#include "mojo/edk/embedder/named_platform_handle_utils.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
-#include "mojo/edk/embedder/peer_connection.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/test/mojo_test_base.h"
+#include "mojo/core/core.h"
+#include "mojo/core/shared_buffer_dispatcher.h"
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/core.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/message_pipe.h"
+#include "mojo/public/cpp/system/platform_handle.h"
#include "mojo/public/cpp/system/wait.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
template <typename T>
@@ -170,37 +167,6 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) {
ASSERT_EQ(MOJO_RESULT_OK, MojoClose(h1));
}
-TEST_F(EmbedderTest, PipeSetup_LaunchDeath) {
- PlatformChannelPair pair;
-
- OutgoingBrokerClientInvitation invitation;
- ScopedMessagePipeHandle parent_mp = invitation.AttachMessagePipe("unused");
- invitation.Send(
- base::GetCurrentProcessHandle(),
- ConnectionParams(TransportProtocol::kLegacy, pair.PassServerHandle()));
-
- // Close the remote end, simulating child death before the child extracts the
- // attached message pipe.
- ignore_result(pair.PassClientHandle());
-
- EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(parent_mp.get().value(),
- MOJO_HANDLE_SIGNAL_PEER_CLOSED));
-}
-
-TEST_F(EmbedderTest, PipeSetup_LaunchFailure) {
- PlatformChannelPair pair;
-
- auto invitation = std::make_unique<OutgoingBrokerClientInvitation>();
- ScopedMessagePipeHandle parent_mp = invitation->AttachMessagePipe("unused");
-
- // Ensure that if an OutgoingBrokerClientInvitation goes away before Send() is
- // called, any message pipes attachde to it detect peer closure.
- invitation.reset();
-
- EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(parent_mp.get().value(),
- MOJO_HANDLE_SIGNAL_PEER_CLOSED));
-}
-
// The sequence of messages sent is:
// server_mp client_mp mp0 mp1 mp2 mp3
// 1. "hello"
@@ -255,7 +221,8 @@ TEST_F(EmbedderTest, MultiprocessChannels) {
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
WaitForSignals(mp2, MOJO_HANDLE_SIGNAL_READABLE, &state));
ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals);
+ ASSERT_FALSE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_FALSE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp2));
});
@@ -298,7 +265,8 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessChannelsClient,
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
WaitForSignals(mp1, MOJO_HANDLE_SIGNAL_READABLE, &state));
ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals);
+ ASSERT_FALSE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_FALSE(state.satisfiable_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp1));
}
@@ -375,17 +343,15 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessSharedMemoryClient,
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(sb1));
}
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
enum class HandleType {
POSIX,
MACH,
- MACH_NULL,
};
const HandleType kTestHandleTypes[] = {
- HandleType::MACH, HandleType::MACH_NULL, HandleType::POSIX,
- HandleType::POSIX, HandleType::MACH,
+ HandleType::MACH, HandleType::POSIX, HandleType::POSIX, HandleType::MACH,
};
// Test that we can mix file descriptors and mach port handles.
@@ -393,22 +359,17 @@ TEST_F(EmbedderTest, MultiprocessMixMachAndFds) {
const size_t kShmSize = 1234;
RunTestClient("MultiprocessMixMachAndFdsClient", [&](MojoHandle server_mp) {
// 1. Create fds or Mach objects and mojo handles from them.
- MojoHandle platform_handles[arraysize(kTestHandleTypes)];
- for (size_t i = 0; i < arraysize(kTestHandleTypes); i++) {
+ MojoHandle platform_handles[base::size(kTestHandleTypes)];
+ for (size_t i = 0; i < base::size(kTestHandleTypes); i++) {
const auto type = kTestHandleTypes[i];
- ScopedInternalPlatformHandle scoped_handle;
+ PlatformHandle scoped_handle;
if (type == HandleType::POSIX) {
// The easiest source of fds is opening /dev/null.
base::File file(base::FilePath("/dev/null"),
base::File::FLAG_OPEN | base::File::FLAG_WRITE);
ASSERT_TRUE(file.IsValid());
- scoped_handle.reset(InternalPlatformHandle(file.TakePlatformFile()));
- EXPECT_EQ(InternalPlatformHandle::Type::POSIX,
- scoped_handle.get().type);
- } else if (type == HandleType::MACH_NULL) {
- scoped_handle.reset(
- InternalPlatformHandle(static_cast<mach_port_t>(MACH_PORT_NULL)));
- EXPECT_EQ(InternalPlatformHandle::Type::MACH, scoped_handle.get().type);
+ scoped_handle = PlatformHandle(base::ScopedFD(file.TakePlatformFile()));
+ ASSERT_TRUE(scoped_handle.is_valid_fd());
} else {
auto shared_memory = base::UnsafeSharedMemoryRegion::Create(kShmSize);
ASSERT_TRUE(shared_memory.IsValid());
@@ -416,17 +377,16 @@ TEST_F(EmbedderTest, MultiprocessMixMachAndFds) {
base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
std::move(shared_memory))
.PassPlatformHandle();
- scoped_handle.reset(InternalPlatformHandle(shm_handle.release()));
- EXPECT_EQ(InternalPlatformHandle::Type::MACH, scoped_handle.get().type);
+ scoped_handle = PlatformHandle(std::move(shm_handle));
+ ASSERT_TRUE(scoped_handle.is_valid_mach_port());
}
- ASSERT_EQ(MOJO_RESULT_OK,
- CreateInternalPlatformHandleWrapper(std::move(scoped_handle),
- platform_handles + i));
+ platform_handles[i] =
+ WrapPlatformHandle(std::move(scoped_handle)).release().value();
}
// 2. Send all the handles to the child.
WriteMessageWithHandles(server_mp, "hello", platform_handles,
- arraysize(kTestHandleTypes));
+ base::size(kTestHandleTypes));
// 3. Read a message from |server_mp|.
EXPECT_EQ("bye", ReadMessage(server_mp));
@@ -436,7 +396,7 @@ TEST_F(EmbedderTest, MultiprocessMixMachAndFds) {
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessMixMachAndFdsClient,
EmbedderTest,
client_mp) {
- const int kNumHandles = arraysize(kTestHandleTypes);
+ const int kNumHandles = base::size(kTestHandleTypes);
MojoHandle platform_handles[kNumHandles];
// 1. Read from |client_mp|, which should have a message containing
@@ -447,20 +407,12 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessMixMachAndFdsClient,
// 2. Extract each handle, and verify the type.
for (int i = 0; i < kNumHandles; i++) {
const auto type = kTestHandleTypes[i];
- ScopedInternalPlatformHandle scoped_handle;
- ASSERT_EQ(MOJO_RESULT_OK, PassWrappedInternalPlatformHandle(
- platform_handles[i], &scoped_handle));
+ PlatformHandle scoped_handle =
+ UnwrapPlatformHandle(ScopedHandle(Handle(platform_handles[i])));
if (type == HandleType::POSIX) {
- EXPECT_NE(0, scoped_handle.get().handle);
- EXPECT_EQ(InternalPlatformHandle::Type::POSIX, scoped_handle.get().type);
- } else if (type == HandleType::MACH_NULL) {
- EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL),
- scoped_handle.get().port);
- EXPECT_EQ(InternalPlatformHandle::Type::MACH, scoped_handle.get().type);
+ EXPECT_TRUE(scoped_handle.is_valid_fd());
} else {
- EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL),
- scoped_handle.get().port);
- EXPECT_EQ(InternalPlatformHandle::Type::MACH, scoped_handle.get().type);
+ EXPECT_TRUE(scoped_handle.is_valid_mach_port());
}
}
@@ -468,115 +420,10 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessMixMachAndFdsClient,
WriteMessage(client_mp, "bye");
}
-#endif // defined(OS_MACOSX) && !defined(OS_IOS)
-
-// TODO(vtl): Test immediate write & close.
-// TODO(vtl): Test broken-connection cases.
-
-#endif // !defined(OS_IOS)
-
-#if !defined(OS_FUCHSIA)
-// TODO(fuchsia): Implement NamedPlatformHandles (crbug.com/754038).
-
-NamedPlatformHandle GenerateChannelName() {
-#if defined(OS_POSIX)
- base::FilePath temp_dir;
- CHECK(base::PathService::Get(base::DIR_TEMP, &temp_dir));
- return NamedPlatformHandle(
- temp_dir.AppendASCII(GenerateRandomToken()).value());
-#else
- return NamedPlatformHandle(GenerateRandomToken());
-#endif
-}
-
-void CreateClientHandleOnIoThread(const NamedPlatformHandle& named_handle,
- ScopedInternalPlatformHandle* output) {
- *output = CreateClientHandle(named_handle);
-}
-
-TEST_F(EmbedderTest, ClosePendingPeerConnection) {
- NamedPlatformHandle named_handle = GenerateChannelName();
- std::string peer_token = GenerateRandomToken();
-
- auto peer_connection = std::make_unique<PeerConnection>();
- ScopedMessagePipeHandle server_pipe =
- peer_connection->Connect(ConnectionParams(
- TransportProtocol::kLegacy, CreateServerHandle(named_handle)));
- peer_connection.reset();
- EXPECT_EQ(MOJO_RESULT_OK,
- Wait(server_pipe.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED));
- base::MessageLoop message_loop;
- base::RunLoop run_loop;
- ScopedInternalPlatformHandle client_handle;
- // Closing the channel involves posting a task to the IO thread to do the
- // work. By the time the local message pipe has been observerd as closed,
- // that task will have been posted. Therefore, a task to create the client
- // connection should be handled after the channel is closed.
- GetIOTaskRunner()->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&CreateClientHandleOnIoThread, named_handle, &client_handle),
- run_loop.QuitClosure());
- run_loop.Run();
- EXPECT_FALSE(client_handle.is_valid());
-}
-
-#endif // !defined(OS_FUCHSIA)
-
-#if !defined(OS_IOS)
-
-TEST_F(EmbedderTest, ClosePipeToConnectedPeer) {
- set_launch_type(LaunchType::PEER);
- auto& controller = StartClient("ClosePipeToConnectedPeerClient");
- MojoHandle server_mp = controller.pipe();
- // 1. Write a message to |server_mp| (attaching nothing).
- WriteMessage(server_mp, "hello");
-
- // 2. Read a message from |server_mp|.
- EXPECT_EQ("world!", ReadMessage(server_mp));
-
- controller.ClosePeerConnection();
-
- EXPECT_EQ(MOJO_RESULT_OK,
- WaitForSignals(server_mp, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
-
- EXPECT_EQ(0, controller.WaitForShutdown());
-}
-
-DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ClosePipeToConnectedPeerClient,
- EmbedderTest,
- client_mp) {
- // 1. Read the first message from |client_mp|.
- EXPECT_EQ("hello", ReadMessage(client_mp));
-
- // 2. Write a message to |client_mp| (attaching nothing).
- WriteMessage(client_mp, "world!");
-
- ASSERT_EQ(MOJO_RESULT_OK,
- WaitForSignals(client_mp, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
-}
-
-TEST_F(EmbedderTest, ClosePipeToConnectingPeer) {
- set_launch_type(LaunchType::PEER);
- auto& controller = StartClient("ClosePipeToConnectingPeerClient");
- controller.ClosePeerConnection();
-
- MojoHandle server_mp = controller.pipe();
-
- EXPECT_EQ(MOJO_RESULT_OK,
- WaitForSignals(server_mp, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
-
- EXPECT_EQ(0, controller.WaitForShutdown());
-}
-
-DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ClosePipeToConnectingPeerClient,
- EmbedderTest,
- client_mp) {
- ASSERT_EQ(MOJO_RESULT_OK,
- WaitForSignals(client_mp, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
-}
+#endif // defined(OS_MACOSX)
#endif // !defined(OS_IOS)
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/entrypoints.cc b/chromium/mojo/core/entrypoints.cc
index c57a02341ec..42e74171922 100644
--- a/chromium/mojo/edk/embedder/entrypoints.cc
+++ b/chromium/mojo/core/entrypoints.cc
@@ -2,20 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/embedder/entrypoints.h"
+#include "mojo/core/entrypoints.h"
#include <stdint.h>
-#include "mojo/edk/system/core.h"
+#include "mojo/core/core.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/c/system/platform_handle.h"
+#include "mojo/public/c/system/quota.h"
namespace {
-mojo::edk::Core* g_core;
+mojo::core::Core* g_core;
extern "C" {
@@ -237,28 +238,24 @@ MojoResult MojoRemoveTriggerImpl(MojoHandle trap_handle,
MojoResult MojoArmTrapImpl(MojoHandle trap_handle,
const MojoArmTrapOptions* options,
- uint32_t* num_ready_triggers,
- uintptr_t* ready_triggers,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states) {
- return g_core->ArmTrap(trap_handle, options, num_ready_triggers,
- ready_triggers, ready_results, ready_signals_states);
+ uint32_t* num_blocking_events,
+ MojoTrapEvent* blocking_events) {
+ return g_core->ArmTrap(trap_handle, options, num_blocking_events,
+ blocking_events);
}
MojoResult MojoWrapPlatformHandleImpl(
const MojoPlatformHandle* platform_handle,
const MojoWrapPlatformHandleOptions* options,
MojoHandle* mojo_handle) {
- return g_core->WrapInternalPlatformHandle(platform_handle, options,
- mojo_handle);
+ return g_core->WrapPlatformHandle(platform_handle, options, mojo_handle);
}
MojoResult MojoUnwrapPlatformHandleImpl(
MojoHandle mojo_handle,
const MojoUnwrapPlatformHandleOptions* options,
MojoPlatformHandle* platform_handle) {
- return g_core->UnwrapInternalPlatformHandle(mojo_handle, options,
- platform_handle);
+ return g_core->UnwrapPlatformHandle(mojo_handle, options, platform_handle);
}
MojoResult MojoWrapPlatformSharedMemoryRegionImpl(
@@ -332,6 +329,22 @@ MojoResult MojoAcceptInvitationImpl(
invitation_handle);
}
+MojoResult MojoSetQuotaImpl(MojoHandle handle,
+ MojoQuotaType type,
+ uint64_t limit,
+ const MojoSetQuotaOptions* options) {
+ return g_core->SetQuota(handle, type, limit, options);
+}
+
+MojoResult MojoQueryQuotaImpl(MojoHandle handle,
+ MojoQuotaType type,
+ const MojoQueryQuotaOptions* options,
+ uint64_t* current_limit,
+ uint64_t* current_usage) {
+ return g_core->QueryQuota(handle, type, options, current_limit,
+ current_usage);
+}
+
} // extern "C"
MojoSystemThunks g_thunks = {sizeof(MojoSystemThunks),
@@ -375,12 +388,14 @@ MojoSystemThunks g_thunks = {sizeof(MojoSystemThunks),
MojoAttachMessagePipeToInvitationImpl,
MojoExtractMessagePipeFromInvitationImpl,
MojoSendInvitationImpl,
- MojoAcceptInvitationImpl};
+ MojoAcceptInvitationImpl,
+ MojoSetQuotaImpl,
+ MojoQueryQuotaImpl};
} // namespace
namespace mojo {
-namespace edk {
+namespace core {
// static
Core* Core::Get() {
@@ -395,5 +410,5 @@ const MojoSystemThunks& GetSystemThunks() {
return g_thunks;
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/entrypoints.h b/chromium/mojo/core/entrypoints.h
index 63299a627ce..e18366b74dd 100644
--- a/chromium/mojo/edk/embedder/entrypoints.h
+++ b/chromium/mojo/core/entrypoints.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_EMBEDDER_ENTRYPOINTS_H_
-#define MOJO_EDK_EMBEDDER_ENTRYPOINTS_H_
+#ifndef MOJO_CORE_ENTRYPOINTS_H_
+#define MOJO_CORE_ENTRYPOINTS_H_
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/thunks.h"
namespace mojo {
-namespace edk {
+namespace core {
// Initializes the global Core object.
MOJO_SYSTEM_IMPL_EXPORT void InitializeCore();
@@ -19,7 +19,7 @@ MOJO_SYSTEM_IMPL_EXPORT void InitializeCore();
// application loading.
MOJO_SYSTEM_IMPL_EXPORT const MojoSystemThunks& GetSystemThunks();
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_EMBEDDER_ENTRYPOINTS_H_
+#endif // MOJO_CORE_ENTRYPOINTS_H_
diff --git a/chromium/mojo/edk/export_only_thunks_api.lst b/chromium/mojo/core/export_only_thunks_api.lst
index 11e436bd3a3..11e436bd3a3 100644
--- a/chromium/mojo/edk/export_only_thunks_api.lst
+++ b/chromium/mojo/core/export_only_thunks_api.lst
diff --git a/chromium/mojo/edk/system/handle_signals_state.h b/chromium/mojo/core/handle_signals_state.h
index c8c5b5ea4a0..7cd7d8db692 100644
--- a/chromium/mojo/edk/system/handle_signals_state.h
+++ b/chromium/mojo/core/handle_signals_state.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_
-#define MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_
+#ifndef MOJO_CORE_HANDLE_SIGNALS_STATE_H_
+#define MOJO_CORE_HANDLE_SIGNALS_STATE_H_
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/types.h"
namespace mojo {
-namespace edk {
+namespace core {
// A convenience wrapper around the MojoHandleSignalsState struct.
//
@@ -71,6 +71,11 @@ struct MOJO_SYSTEM_IMPL_EXPORT HandleSignalsState final
return satisfies_any(MOJO_HANDLE_SIGNAL_PEER_REMOTE);
}
+ // Indicates whether the handle has exceeded some quota limit.
+ bool quota_exceeded() const {
+ return satisfies_any(MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+ }
+
// The handle will never be |readable()| again.
bool never_readable() const {
return !can_satisfy_any(MOJO_HANDLE_SIGNAL_READABLE);
@@ -100,7 +105,7 @@ struct MOJO_SYSTEM_IMPL_EXPORT HandleSignalsState final
static_assert(sizeof(HandleSignalsState) == sizeof(MojoHandleSignalsState),
"HandleSignalsState should add no overhead");
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_
+#endif // MOJO_CORE_HANDLE_SIGNALS_STATE_H_
diff --git a/chromium/mojo/edk/system/handle_table.cc b/chromium/mojo/core/handle_table.cc
index a9fcc651414..62419a92363 100644
--- a/chromium/mojo/edk/system/handle_table.cc
+++ b/chromium/mojo/core/handle_table.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/handle_table.h"
+#include "mojo/core/handle_table.h"
#include <stdint.h>
@@ -11,7 +11,7 @@
#include "base/trace_event/memory_dump_manager.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -40,11 +40,9 @@ const char* GetNameForDispatcherType(Dispatcher::Type type) {
} // namespace
-HandleTable::HandleTable() {
-}
+HandleTable::HandleTable() {}
-HandleTable::~HandleTable() {
-}
+HandleTable::~HandleTable() {}
base::Lock& HandleTable::GetLock() {
return lock_;
@@ -171,6 +169,7 @@ bool HandleTable::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
handle_count[Dispatcher::Type::SHARED_BUFFER];
handle_count[Dispatcher::Type::WATCHER];
handle_count[Dispatcher::Type::PLATFORM_HANDLE];
+ handle_count[Dispatcher::Type::INVITATION];
// Count the number of each dispatcher type.
{
@@ -201,5 +200,5 @@ HandleTable::Entry::Entry(const Entry& other) = default;
HandleTable::Entry::~Entry() {}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/handle_table.h b/chromium/mojo/core/handle_table.h
index f8206cfa21c..234bdac239e 100644
--- a/chromium/mojo/edk/system/handle_table.h
+++ b/chromium/mojo/core/handle_table.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_HANDLE_TABLE_H_
-#define MOJO_EDK_SYSTEM_HANDLE_TABLE_H_
+#ifndef MOJO_CORE_HANDLE_TABLE_H_
+#define MOJO_CORE_HANDLE_TABLE_H_
#include <stdint.h>
@@ -14,12 +14,12 @@
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/trace_event/memory_dump_provider.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/types.h"
namespace mojo {
-namespace edk {
+namespace core {
class MOJO_SYSTEM_IMPL_EXPORT HandleTable
: public base::trace_event::MemoryDumpProvider {
@@ -55,7 +55,7 @@ class MOJO_SYSTEM_IMPL_EXPORT HandleTable
void CancelTransit(
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers);
- void GetActiveHandlesForTest(std::vector<MojoHandle> *handles);
+ void GetActiveHandlesForTest(std::vector<MojoHandle>* handles);
private:
FRIEND_TEST_ALL_PREFIXES(HandleTableTest, OnMemoryDump);
@@ -65,13 +65,13 @@ class MOJO_SYSTEM_IMPL_EXPORT HandleTable
base::trace_event::ProcessMemoryDump* pmd) override;
struct Entry {
- Entry();
- explicit Entry(scoped_refptr<Dispatcher> dispatcher);
- Entry(const Entry& other);
- ~Entry();
+ Entry();
+ explicit Entry(scoped_refptr<Dispatcher> dispatcher);
+ Entry(const Entry& other);
+ ~Entry();
- scoped_refptr<Dispatcher> dispatcher;
- bool busy = false;
+ scoped_refptr<Dispatcher> dispatcher;
+ bool busy = false;
};
using HandleMap = base::hash_map<MojoHandle, Entry>;
@@ -84,7 +84,7 @@ class MOJO_SYSTEM_IMPL_EXPORT HandleTable
DISALLOW_COPY_AND_ASSIGN(HandleTable);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_HANDLE_TABLE_H_
+#endif // MOJO_CORE_HANDLE_TABLE_H_
diff --git a/chromium/mojo/edk/system/handle_table_unittest.cc b/chromium/mojo/core/handle_table_unittest.cc
index 32f6425586b..493f71e021d 100644
--- a/chromium/mojo/edk/system/handle_table_unittest.cc
+++ b/chromium/mojo/core/handle_table_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/handle_table.h"
+#include "mojo/core/handle_table.h"
#include <memory>
@@ -11,7 +11,7 @@
#include "base/trace_event/memory_dump_request_args.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event_argument.h"
-#include "mojo/edk/system/dispatcher.h"
+#include "mojo/core/dispatcher.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -22,7 +22,7 @@ using testing::Contains;
using testing::ByRef;
namespace mojo {
-namespace edk {
+namespace core {
namespace {
class FakeMessagePipeDispatcher : public Dispatcher {
@@ -56,19 +56,18 @@ TEST(HandleTableTest, OnMemoryDump) {
{
base::AutoLock auto_lock(ht.GetLock());
- scoped_refptr<mojo::edk::Dispatcher> dispatcher(
- new FakeMessagePipeDispatcher);
+ scoped_refptr<Dispatcher> dispatcher(new FakeMessagePipeDispatcher);
ht.AddDispatcher(dispatcher);
}
base::trace_event::MemoryDumpArgs args = {
base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
- base::trace_event::ProcessMemoryDump pmd(nullptr, args);
+ base::trace_event::ProcessMemoryDump pmd(args);
ht.OnMemoryDump(args, &pmd);
CheckNameAndValue(&pmd, "mojo/message_pipe", 1);
CheckNameAndValue(&pmd, "mojo/data_pipe_consumer", 0);
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/invitation_dispatcher.cc b/chromium/mojo/core/invitation_dispatcher.cc
index aa684bc0409..82d33871025 100644
--- a/chromium/mojo/edk/system/invitation_dispatcher.cc
+++ b/chromium/mojo/core/invitation_dispatcher.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/invitation_dispatcher.h"
+#include "mojo/core/invitation_dispatcher.h"
-#include "mojo/edk/system/core.h"
+#include "mojo/core/core.h"
namespace mojo {
-namespace edk {
+namespace core {
InvitationDispatcher::InvitationDispatcher() = default;
@@ -74,5 +74,5 @@ InvitationDispatcher::~InvitationDispatcher() {
DCHECK(is_closed_);
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/invitation_dispatcher.h b/chromium/mojo/core/invitation_dispatcher.h
index 21c530be02a..c856e1f7da2 100644
--- a/chromium/mojo/edk/system/invitation_dispatcher.h
+++ b/chromium/mojo/core/invitation_dispatcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_INVITATION_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_INVITATION_DISPATCHER_H_
+#ifndef MOJO_CORE_INVITATION_DISPATCHER_H_
+#define MOJO_CORE_INVITATION_DISPATCHER_H_
#include <stdint.h>
@@ -11,13 +11,12 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/ports/port_ref.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/ports/port_ref.h"
+#include "mojo/core/system_impl_export.h"
namespace mojo {
-namespace edk {
+namespace core {
class MOJO_SYSTEM_IMPL_EXPORT InvitationDispatcher : public Dispatcher {
public:
@@ -44,7 +43,7 @@ class MOJO_SYSTEM_IMPL_EXPORT InvitationDispatcher : public Dispatcher {
DISALLOW_COPY_AND_ASSIGN(InvitationDispatcher);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_INVITATION_DISPATCHER_H
+#endif // MOJO_CORE_INVITATION_DISPATCHER_H
diff --git a/chromium/mojo/edk/system/invitation_unittest.cc b/chromium/mojo/core/invitation_unittest.cc
index ddb86ae0659..791bb085539 100644
--- a/chromium/mojo/edk/system/invitation_unittest.cc
+++ b/chromium/mojo/core/invitation_unittest.cc
@@ -20,14 +20,14 @@
#include "base/test/scoped_task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
-#include "mojo/edk/test/mojo_test_base.h"
+#include "mojo/core/test/mojo_test_base.h"
#include "mojo/public/c/system/invitation.h"
#include "mojo/public/cpp/platform/named_platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
enum class TransportType {
@@ -35,6 +35,8 @@ enum class TransportType {
kChannelServer,
};
+const char kSecondaryChannelHandleSwitch[] = "test-secondary-channel-handle";
+
class InvitationTest : public test::MojoTestBase {
public:
InvitationTest() = default;
@@ -46,8 +48,22 @@ class InvitationTest : public test::MojoTestBase {
MojoHandle* primordial_pipes,
size_t num_primordial_pipes,
TransportType transport_type,
+ MojoSendInvitationFlags send_flags,
MojoProcessErrorHandler error_handler = nullptr,
- uintptr_t error_handler_context = 0);
+ uintptr_t error_handler_context = 0,
+ base::CommandLine* custom_command_line = nullptr,
+ base::LaunchOptions* custom_launch_options = nullptr);
+
+ static void SendInvitationToClient(
+ PlatformHandle endpoint_handle,
+ base::ProcessHandle process,
+ MojoHandle* primordial_pipes,
+ size_t num_primordial_pipes,
+ TransportType transport_type,
+ MojoSendInvitationFlags flags,
+ MojoProcessErrorHandler error_handler,
+ uintptr_t error_handler_context,
+ base::StringPiece isolated_invitation_name);
private:
base::test::ScopedTaskEnvironment task_environment_;
@@ -55,6 +71,26 @@ class InvitationTest : public test::MojoTestBase {
DISALLOW_COPY_AND_ASSIGN(InvitationTest);
};
+void PrepareToPassRemoteEndpoint(PlatformChannel* channel,
+ base::LaunchOptions* options,
+ base::CommandLine* command_line,
+ base::StringPiece switch_name = {}) {
+ std::string value;
+#if defined(OS_FUCHSIA)
+ channel->PrepareToPassRemoteEndpoint(&options->handles_to_transfer, &value);
+#elif defined(OS_POSIX)
+ channel->PrepareToPassRemoteEndpoint(&options->fds_to_remap, &value);
+#elif defined(OS_WIN)
+ channel->PrepareToPassRemoteEndpoint(&options->handles_to_inherit, &value);
+#else
+#error "Platform not yet supported."
+#endif
+
+ if (switch_name.empty())
+ switch_name = PlatformChannel::kHandleSwitch;
+ command_line->AppendSwitchASCII(switch_name.as_string(), value);
+}
+
TEST_F(InvitationTest, Create) {
MojoHandle invitation;
EXPECT_EQ(MOJO_RESULT_OK, MojoCreateInvitation(nullptr, &invitation));
@@ -108,7 +144,7 @@ TEST_F(InvitationTest, InvalidArguments) {
PlatformChannel channel;
MojoPlatformHandle endpoint_handle;
endpoint_handle.struct_size = sizeof(endpoint_handle);
- PlatformHandleToMojoPlatformHandle(
+ PlatformHandle::ToMojoPlatformHandle(
channel.TakeLocalEndpoint().TakePlatformHandle(), &endpoint_handle);
ASSERT_NE(endpoint_handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
@@ -246,30 +282,30 @@ base::Process InvitationTest::LaunchChildTestClient(
MojoHandle* primordial_pipes,
size_t num_primordial_pipes,
TransportType transport_type,
+ MojoSendInvitationFlags send_flags,
MojoProcessErrorHandler error_handler,
- uintptr_t error_handler_context) {
- base::CommandLine command_line(
- base::GetMultiProcessTestChildBaseCommandLine());
+ uintptr_t error_handler_context,
+ base::CommandLine* custom_command_line,
+ base::LaunchOptions* custom_launch_options) {
+ base::CommandLine default_command_line =
+ base::GetMultiProcessTestChildBaseCommandLine();
+ base::CommandLine& command_line =
+ custom_command_line ? *custom_command_line : default_command_line;
+
+ base::LaunchOptions default_launch_options;
+ base::LaunchOptions& launch_options =
+ custom_launch_options ? *custom_launch_options : default_launch_options;
+#if defined(OS_WIN)
+ launch_options.start_hidden = true;
+#endif
- base::LaunchOptions launch_options;
base::Optional<PlatformChannel> channel;
base::Optional<NamedPlatformChannel> named_channel;
PlatformHandle local_endpoint_handle;
if (transport_type == TransportType::kChannel) {
channel.emplace();
-#if defined(OS_FUCHSIA)
- channel->PrepareToPassRemoteEndpoint(&launch_options.handles_to_transfer,
- &command_line);
-#elif defined(OS_POSIX)
- channel->PrepareToPassRemoteEndpoint(&launch_options.fds_to_remap,
- &command_line);
-#elif defined(OS_WIN)
- launch_options.start_hidden = true;
- channel->PrepareToPassRemoteEndpoint(&launch_options.handles_to_inherit,
- &command_line);
-#else
-#error "Platform not yet supported."
-#endif
+ PrepareToPassRemoteEndpoint(&channel.value(), &launch_options,
+ &command_line);
local_endpoint_handle = channel->TakeLocalEndpoint().TakePlatformHandle();
} else {
#if defined(OS_FUCHSIA)
@@ -287,10 +323,33 @@ base::Process InvitationTest::LaunchChildTestClient(
#endif
}
- MojoPlatformHandle endpoint_handle;
- PlatformHandleToMojoPlatformHandle(std::move(local_endpoint_handle),
- &endpoint_handle);
- CHECK_NE(endpoint_handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
+ base::Process child_process = base::SpawnMultiProcessTestChild(
+ test_client_name, command_line, launch_options);
+ if (channel)
+ channel->RemoteProcessLaunchAttempted();
+
+ SendInvitationToClient(std::move(local_endpoint_handle),
+ child_process.Handle(), primordial_pipes,
+ num_primordial_pipes, transport_type, send_flags,
+ error_handler, error_handler_context, "");
+
+ return child_process;
+}
+
+// static
+void InvitationTest::SendInvitationToClient(
+ PlatformHandle endpoint_handle,
+ base::ProcessHandle process,
+ MojoHandle* primordial_pipes,
+ size_t num_primordial_pipes,
+ TransportType transport_type,
+ MojoSendInvitationFlags flags,
+ MojoProcessErrorHandler error_handler,
+ uintptr_t error_handler_context,
+ base::StringPiece isolated_invitation_name) {
+ MojoPlatformHandle handle;
+ PlatformHandle::ToMojoPlatformHandle(std::move(endpoint_handle), &handle);
+ CHECK_NE(handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
MojoHandle invitation;
CHECK_EQ(MOJO_RESULT_OK, MojoCreateInvitation(nullptr, &invitation));
@@ -300,18 +359,13 @@ base::Process InvitationTest::LaunchChildTestClient(
&primordial_pipes[name]));
}
- base::Process child_process = base::SpawnMultiProcessTestChild(
- test_client_name, command_line, launch_options);
- if (channel)
- channel->RemoteProcessLaunched();
-
MojoPlatformProcessHandle process_handle;
process_handle.struct_size = sizeof(process_handle);
#if defined(OS_WIN)
- process_handle.value = static_cast<uint64_t>(
- reinterpret_cast<uintptr_t>(child_process.Handle()));
+ process_handle.value =
+ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(process));
#else
- process_handle.value = static_cast<uint64_t>(child_process.Handle());
+ process_handle.value = static_cast<uint64_t>(process);
#endif
MojoInvitationTransportEndpoint transport_endpoint;
@@ -321,26 +375,40 @@ base::Process InvitationTest::LaunchChildTestClient(
else
transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER;
transport_endpoint.num_platform_handles = 1;
- transport_endpoint.platform_handles = &endpoint_handle;
+ transport_endpoint.platform_handles = &handle;
+
+ MojoSendInvitationOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = flags;
+ if (flags & MOJO_SEND_INVITATION_FLAG_ISOLATED) {
+ options.isolated_connection_name = isolated_invitation_name.data();
+ options.isolated_connection_name_length =
+ static_cast<uint32_t>(isolated_invitation_name.size());
+ }
CHECK_EQ(MOJO_RESULT_OK,
MojoSendInvitation(invitation, &process_handle, &transport_endpoint,
- error_handler, error_handler_context, nullptr));
- return child_process;
+ error_handler, error_handler_context, &options));
}
class TestClientBase : public InvitationTest {
public:
- static MojoHandle AcceptInvitation() {
+ static MojoHandle AcceptInvitation(MojoAcceptInvitationFlags flags,
+ base::StringPiece switch_name = {}) {
const auto& command_line = *base::CommandLine::ForCurrentProcess();
PlatformChannelEndpoint channel_endpoint =
NamedPlatformChannel::ConnectToServer(command_line);
if (!channel_endpoint.is_valid()) {
- channel_endpoint =
- PlatformChannel::RecoverPassedEndpointFromCommandLine(command_line);
+ if (switch_name.empty()) {
+ channel_endpoint =
+ PlatformChannel::RecoverPassedEndpointFromCommandLine(command_line);
+ } else {
+ channel_endpoint = PlatformChannel::RecoverPassedEndpointFromString(
+ command_line.GetSwitchValueASCII(switch_name));
+ }
}
MojoPlatformHandle endpoint_handle;
- PlatformHandleToMojoPlatformHandle(channel_endpoint.TakePlatformHandle(),
- &endpoint_handle);
+ PlatformHandle::ToMojoPlatformHandle(channel_endpoint.TakePlatformHandle(),
+ &endpoint_handle);
CHECK_NE(endpoint_handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
MojoInvitationTransportEndpoint transport_endpoint;
@@ -349,9 +417,12 @@ class TestClientBase : public InvitationTest {
transport_endpoint.num_platform_handles = 1;
transport_endpoint.platform_handles = &endpoint_handle;
+ MojoAcceptInvitationOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = flags;
MojoHandle invitation;
CHECK_EQ(MOJO_RESULT_OK,
- MojoAcceptInvitation(&transport_endpoint, nullptr, &invitation));
+ MojoAcceptInvitation(&transport_endpoint, &options, &invitation));
return invitation;
}
@@ -378,7 +449,8 @@ const std::string kTestMessage4 = "i shove the messages down the pipe";
TEST_F(InvitationTest, SendInvitation) {
MojoHandle primordial_pipe;
base::Process child_process = LaunchChildTestClient(
- "SendInvitationClient", &primordial_pipe, 1, TransportType::kChannel);
+ "SendInvitationClient", &primordial_pipe, 1, TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_NONE);
WriteMessage(primordial_pipe, kTestMessage1);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -395,7 +467,7 @@ TEST_F(InvitationTest, SendInvitation) {
DEFINE_TEST_CLIENT(SendInvitationClient) {
MojoHandle primordial_pipe;
- MojoHandle invitation = AcceptInvitation();
+ MojoHandle invitation = AcceptInvitation(MOJO_ACCEPT_INVITATION_FLAG_NONE);
const uint32_t pipe_name = 0;
ASSERT_EQ(MOJO_RESULT_OK,
MojoExtractMessagePipeFromInvitation(invitation, &pipe_name, 4,
@@ -413,7 +485,8 @@ DEFINE_TEST_CLIENT(SendInvitationClient) {
TEST_F(InvitationTest, SendInvitationMultiplePipes) {
MojoHandle pipes[2];
base::Process child_process = LaunchChildTestClient(
- "SendInvitationMultiplePipesClient", pipes, 2, TransportType::kChannel);
+ "SendInvitationMultiplePipesClient", pipes, 2, TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_NONE);
WriteMessage(pipes[0], kTestMessage1);
WriteMessage(pipes[1], kTestMessage2);
@@ -436,7 +509,7 @@ TEST_F(InvitationTest, SendInvitationMultiplePipes) {
DEFINE_TEST_CLIENT(SendInvitationMultiplePipesClient) {
MojoHandle pipes[2];
- MojoHandle invitation = AcceptInvitation();
+ MojoHandle invitation = AcceptInvitation(MOJO_ACCEPT_INVITATION_FLAG_NONE);
const uint32_t pipe_names[] = {0, 1};
ASSERT_EQ(MOJO_RESULT_OK,
MojoExtractMessagePipeFromInvitation(invitation, &pipe_names[0], 4,
@@ -458,9 +531,9 @@ DEFINE_TEST_CLIENT(SendInvitationMultiplePipesClient) {
#if !defined(OS_FUCHSIA)
TEST_F(InvitationTest, SendInvitationWithServer) {
MojoHandle primordial_pipe;
- base::Process child_process =
- LaunchChildTestClient("SendInvitationWithServerClient", &primordial_pipe,
- 1, TransportType::kChannelServer);
+ base::Process child_process = LaunchChildTestClient(
+ "SendInvitationWithServerClient", &primordial_pipe, 1,
+ TransportType::kChannelServer, MOJO_SEND_INVITATION_FLAG_NONE);
WriteMessage(primordial_pipe, kTestMessage1);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -477,7 +550,7 @@ TEST_F(InvitationTest, SendInvitationWithServer) {
DEFINE_TEST_CLIENT(SendInvitationWithServerClient) {
MojoHandle primordial_pipe;
- MojoHandle invitation = AcceptInvitation();
+ MojoHandle invitation = AcceptInvitation(MOJO_ACCEPT_INVITATION_FLAG_NONE);
const uint32_t pipe_name = 0;
ASSERT_EQ(MOJO_RESULT_OK,
MojoExtractMessagePipeFromInvitation(invitation, &pipe_name, 4,
@@ -554,7 +627,8 @@ TEST_F(InvitationTest, ProcessErrors) {
MojoHandle pipe;
base::Process child_process = LaunchChildTestClient(
"ProcessErrorsClient", &pipe, 1, TransportType::kChannel,
- &TestProcessErrorHandler, reinterpret_cast<uintptr_t>(&process_state));
+ MOJO_SEND_INVITATION_FLAG_NONE, &TestProcessErrorHandler,
+ reinterpret_cast<uintptr_t>(&process_state));
MojoMessageHandle message;
WaitForSignals(pipe, MOJO_HANDLE_SIGNAL_READABLE);
@@ -590,7 +664,7 @@ TEST_F(InvitationTest, ProcessErrors) {
DEFINE_TEST_CLIENT(ProcessErrorsClient) {
MojoHandle pipe;
- MojoHandle invitation = AcceptInvitation();
+ MojoHandle invitation = AcceptInvitation(MOJO_ACCEPT_INVITATION_FLAG_NONE);
const uint32_t pipe_name = 0;
ASSERT_EQ(MOJO_RESULT_OK, MojoExtractMessagePipeFromInvitation(
invitation, &pipe_name, 4, nullptr, &pipe));
@@ -605,6 +679,196 @@ DEFINE_TEST_CLIENT(ProcessErrorsClient) {
EXPECT_EQ(kDisconnectMessage, ReadMessage(pipe));
}
+TEST_F(InvitationTest, SendIsolatedInvitation) {
+ MojoHandle primordial_pipe;
+ base::Process child_process = LaunchChildTestClient(
+ "SendIsolatedInvitationClient", &primordial_pipe, 1,
+ TransportType::kChannel, MOJO_SEND_INVITATION_FLAG_ISOLATED);
+
+ WriteMessage(primordial_pipe, kTestMessage1);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE));
+ EXPECT_EQ(kTestMessage3, ReadMessage(primordial_pipe));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+
+ int wait_result = -1;
+ base::WaitForMultiprocessTestChildExit(
+ child_process, TestTimeouts::action_timeout(), &wait_result);
+ child_process.Close();
+ EXPECT_EQ(0, wait_result);
+}
+
+DEFINE_TEST_CLIENT(SendIsolatedInvitationClient) {
+ MojoHandle primordial_pipe;
+ MojoHandle invitation =
+ AcceptInvitation(MOJO_ACCEPT_INVITATION_FLAG_ISOLATED);
+ const uint32_t pipe_name = 0;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoExtractMessagePipeFromInvitation(invitation, &pipe_name, 4,
+ nullptr, &primordial_pipe));
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_EQ(kTestMessage1, ReadMessage(primordial_pipe));
+ WriteMessage(primordial_pipe, kTestMessage3);
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+}
+
+TEST_F(InvitationTest, SendMultipleIsolatedInvitations) {
+ // We send a secondary transport to the client process so we can send a second
+ // isolated invitation.
+ base::CommandLine command_line =
+ base::GetMultiProcessTestChildBaseCommandLine();
+ PlatformChannel secondary_transport;
+ base::LaunchOptions options;
+ PrepareToPassRemoteEndpoint(&secondary_transport, &options, &command_line,
+ kSecondaryChannelHandleSwitch);
+
+ MojoHandle primordial_pipe;
+ base::Process child_process = LaunchChildTestClient(
+ "SendMultipleIsolatedInvitationsClient", &primordial_pipe, 1,
+ TransportType::kChannel, MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0,
+ &command_line, &options);
+ secondary_transport.RemoteProcessLaunchAttempted();
+
+ WriteMessage(primordial_pipe, kTestMessage1);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE));
+ EXPECT_EQ(kTestMessage3, ReadMessage(primordial_pipe));
+
+ // Send another invitation over our seconary pipe. This should trample the
+ // original connection, breaking the first pipe.
+ MojoHandle new_pipe;
+ SendInvitationToClient(
+ secondary_transport.TakeLocalEndpoint().TakePlatformHandle(),
+ child_process.Handle(), &new_pipe, 1, TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, "");
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+
+ // And the new pipe should be working.
+ WriteMessage(new_pipe, kTestMessage1);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(new_pipe, MOJO_HANDLE_SIGNAL_READABLE));
+ EXPECT_EQ(kTestMessage3, ReadMessage(new_pipe));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(new_pipe));
+
+ int wait_result = -1;
+ base::WaitForMultiprocessTestChildExit(
+ child_process, TestTimeouts::action_timeout(), &wait_result);
+ child_process.Close();
+ EXPECT_EQ(0, wait_result);
+}
+
+DEFINE_TEST_CLIENT(SendMultipleIsolatedInvitationsClient) {
+ MojoHandle primordial_pipe;
+ MojoHandle invitation =
+ AcceptInvitation(MOJO_ACCEPT_INVITATION_FLAG_ISOLATED);
+ const uint32_t pipe_name = 0;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoExtractMessagePipeFromInvitation(invitation, &pipe_name, 4,
+ nullptr, &primordial_pipe));
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_EQ(kTestMessage1, ReadMessage(primordial_pipe));
+ WriteMessage(primordial_pipe, kTestMessage3);
+
+ // The above pipe should get closed once we accept a new invitation.
+ invitation = AcceptInvitation(MOJO_ACCEPT_INVITATION_FLAG_ISOLATED,
+ kSecondaryChannelHandleSwitch);
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+ primordial_pipe = MOJO_HANDLE_INVALID;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoExtractMessagePipeFromInvitation(invitation, &pipe_name, 4,
+ nullptr, &primordial_pipe));
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_EQ(kTestMessage1, ReadMessage(primordial_pipe));
+ WriteMessage(primordial_pipe, kTestMessage3);
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+}
+
+TEST_F(InvitationTest, SendIsolatedInvitationWithDuplicateName) {
+ PlatformChannel channel1;
+ PlatformChannel channel2;
+ MojoHandle pipe0, pipe1;
+ const char kConnectionName[] = "there can be only one!";
+ SendInvitationToClient(
+ channel1.TakeLocalEndpoint().TakePlatformHandle(),
+ base::kNullProcessHandle, &pipe0, 1, TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, kConnectionName);
+
+ // Send another invitation with the same connection name. |pipe0| should be
+ // disconnected as the first invitation's connection is torn down.
+ SendInvitationToClient(
+ channel2.TakeLocalEndpoint().TakePlatformHandle(),
+ base::kNullProcessHandle, &pipe1, 1, TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, kConnectionName);
+
+ WaitForSignals(pipe0, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+}
+
+TEST_F(InvitationTest, SendIsolatedInvitationToSelf) {
+ PlatformChannel channel;
+ MojoHandle pipe0, pipe1;
+ SendInvitationToClient(channel.TakeLocalEndpoint().TakePlatformHandle(),
+ base::kNullProcessHandle, &pipe0, 1,
+ TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, "");
+ SendInvitationToClient(channel.TakeRemoteEndpoint().TakePlatformHandle(),
+ base::kNullProcessHandle, &pipe1, 1,
+ TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_ISOLATED, nullptr, 0, "");
+
+ WriteMessage(pipe0, kTestMessage1);
+ EXPECT_EQ(kTestMessage1, ReadMessage(pipe1));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe0));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe1));
+}
+
+TEST_F(InvitationTest, BrokenInvitationTransportBreaksAttachedPipe) {
+ MojoHandle primordial_pipe;
+ base::Process child_process = LaunchChildTestClient(
+ "BrokenTransportClient", &primordial_pipe, 1, TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_NONE);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+
+ int wait_result = -1;
+ base::WaitForMultiprocessTestChildExit(
+ child_process, TestTimeouts::action_timeout(), &wait_result);
+ child_process.Close();
+ EXPECT_EQ(0, wait_result);
+}
+
+TEST_F(InvitationTest, BrokenIsolatedInvitationTransportBreaksAttachedPipe) {
+ MojoHandle primordial_pipe;
+ base::Process child_process = LaunchChildTestClient(
+ "BrokenTransportClient", &primordial_pipe, 1, TransportType::kChannel,
+ MOJO_SEND_INVITATION_FLAG_ISOLATED);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+
+ int wait_result = -1;
+ base::WaitForMultiprocessTestChildExit(
+ child_process, TestTimeouts::action_timeout(), &wait_result);
+ child_process.Close();
+ EXPECT_EQ(0, wait_result);
+}
+
+DEFINE_TEST_CLIENT(BrokenTransportClient) {
+ // No-op. Exit immediately without accepting any invitation.
+}
+
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/mach_port_relay.cc b/chromium/mojo/core/mach_port_relay.cc
index b3380a86d29..7d7a42510e4 100644
--- a/chromium/mojo/edk/system/mach_port_relay.cc
+++ b/chromium/mojo/core/mach_port_relay.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/mach_port_relay.h"
+#include "mojo/core/mach_port_relay.h"
#include <mach/mach.h>
@@ -13,10 +13,9 @@
#include "base/mac/scoped_mach_port.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -65,37 +64,24 @@ void ReportChildError(ChildUMAError error) {
} // namespace
// static
-void MachPortRelay::ReceivePorts(
- std::vector<ScopedInternalPlatformHandle>* handles) {
- DCHECK(handles);
-
- for (auto& handle : *handles) {
- DCHECK(handle.get().type != InternalPlatformHandle::Type::MACH);
- if (handle.get().type != InternalPlatformHandle::Type::MACH_NAME)
- continue;
-
- handle.get().type = InternalPlatformHandle::Type::MACH;
-
- // MACH_PORT_NULL doesn't need translation.
- if (handle.get().port == MACH_PORT_NULL)
- continue;
-
- // TODO(wez): Wrapping handle.get().port in this way causes it to be
- // Free()d via mach_port_mod_refs() - should InternalPlatformHandle also do
- // that if the handle never reaches here, or should this code not be
- // wrapping it?
- base::mac::ScopedMachReceiveRight message_port(handle.get().port);
- base::mac::ScopedMachSendRight received_port(
- base::ReceiveMachPort(message_port.get()));
- handle.get().port = received_port.release();
- if (!handle.is_valid()) {
- ReportChildError(ChildUMAError::ERROR_RECEIVE_MACH_MESSAGE);
- DLOG(ERROR) << "Error receiving mach port";
- continue;
- }
-
- ReportChildError(ChildUMAError::SUCCESS);
+base::mac::ScopedMachSendRight MachPortRelay::ReceiveSendRight(
+ base::mac::ScopedMachReceiveRight port) {
+ // MACH_PORT_NULL doesn't need translation.
+ if (!port.is_valid())
+ return base::mac::ScopedMachSendRight();
+
+ // Take ownership of the receive right. We only need it to read this single
+ // send right, then it can be closed.
+ base::mac::ScopedMachSendRight received_port(
+ base::ReceiveMachPort(port.get()));
+ if (!received_port.is_valid()) {
+ ReportChildError(ChildUMAError::ERROR_RECEIVE_MACH_MESSAGE);
+ DLOG(ERROR) << "Error receiving mach port";
+ return base::mac::ScopedMachSendRight();
}
+
+ ReportChildError(ChildUMAError::SUCCESS);
+ return received_port;
}
MachPortRelay::MachPortRelay(base::PortProvider* port_provider)
@@ -113,40 +99,29 @@ void MachPortRelay::SendPortsToProcess(Channel::Message* message,
DCHECK(message);
mach_port_t task_port = port_provider_->TaskForPid(process);
- std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
// Message should have handles, otherwise there's no point in calling this
// function.
DCHECK(!handles.empty());
for (auto& handle : handles) {
- DCHECK(handle.get().type != InternalPlatformHandle::Type::MACH_NAME);
- if (handle.get().type != InternalPlatformHandle::Type::MACH)
+ if (!handle.handle().is_valid_mach_port())
continue;
- if (!handle.is_valid()) {
- handle.get().type = InternalPlatformHandle::Type::MACH_NAME;
- continue;
- }
-
if (task_port == MACH_PORT_NULL) {
// Callers check the port provider for the task port before calling this
// function, in order to queue pending messages. Therefore, if this fails,
// it should be considered a genuine, bona fide, electrified, six-car
// error.
ReportBrokerError(BrokerUMAError::ERROR_TASK_FOR_PID);
-
- // For MACH_PORT_NULL, use Type::MACH to indicate that no extraction is
- // necessary.
- // TODO(wez): But we're not setting Type::Mach... is the comment above
- // out of date?
- handle.get().port = MACH_PORT_NULL;
+ handle = PlatformHandleInTransit(
+ PlatformHandle(base::mac::ScopedMachSendRight()));
continue;
}
mach_port_name_t intermediate_port;
base::MachCreateError error_code;
intermediate_port = base::CreateIntermediateMachPort(
- task_port, base::mac::ScopedMachSendRight(handle.get().port),
- &error_code);
+ task_port, handle.TakeHandle().TakeMachPort(), &error_code);
if (intermediate_port == MACH_PORT_NULL) {
BrokerUMAError uma_error;
switch (error_code) {
@@ -164,48 +139,44 @@ void MachPortRelay::SendPortsToProcess(Channel::Message* message,
break;
}
ReportBrokerError(uma_error);
- handle.get().port = MACH_PORT_NULL;
+ handle = PlatformHandleInTransit(
+ PlatformHandle(base::mac::ScopedMachSendRight()));
continue;
}
+ handle = PlatformHandleInTransit::CreateForMachPortName(intermediate_port);
ReportBrokerError(BrokerUMAError::SUCCESS);
- handle.get().port = intermediate_port;
- handle.get().type = InternalPlatformHandle::Type::MACH_NAME;
}
message->SetHandles(std::move(handles));
}
-void MachPortRelay::ExtractPort(ScopedInternalPlatformHandle* handle,
- base::ProcessHandle process) {
- DCHECK_EQ(handle->get().type, InternalPlatformHandle::Type::MACH_NAME);
- handle->get().type = InternalPlatformHandle::Type::MACH;
-
+base::mac::ScopedMachSendRight MachPortRelay::ExtractPort(
+ mach_port_t port_name,
+ base::ProcessHandle process) {
// No extraction necessary for MACH_PORT_NULL.
- if (!handle->is_valid())
- return;
+ if (port_name == MACH_PORT_NULL)
+ return base::mac::ScopedMachSendRight();
mach_port_t task_port = port_provider_->TaskForPid(process);
if (task_port == MACH_PORT_NULL) {
ReportBrokerError(BrokerUMAError::ERROR_TASK_FOR_PID);
- handle->get().port = MACH_PORT_NULL;
- return;
+ return base::mac::ScopedMachSendRight();
}
mach_port_t extracted_right = MACH_PORT_NULL;
mach_msg_type_name_t extracted_right_type;
- kern_return_t kr = mach_port_extract_right(
- task_port, handle->get().port, MACH_MSG_TYPE_MOVE_SEND, &extracted_right,
- &extracted_right_type);
+ kern_return_t kr =
+ mach_port_extract_right(task_port, port_name, MACH_MSG_TYPE_MOVE_SEND,
+ &extracted_right, &extracted_right_type);
if (kr != KERN_SUCCESS) {
ReportBrokerError(BrokerUMAError::ERROR_EXTRACT_SOURCE_RIGHT);
- handle->get().port = MACH_PORT_NULL;
- return;
+ return base::mac::ScopedMachSendRight();
}
ReportBrokerError(BrokerUMAError::SUCCESS);
DCHECK_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND),
extracted_right_type);
- handle->get().port = extracted_right;
+ return base::mac::ScopedMachSendRight(extracted_right);
}
void MachPortRelay::AddObserver(Observer* observer) {
@@ -225,5 +196,5 @@ void MachPortRelay::OnReceivedTaskPort(base::ProcessHandle process) {
observer->OnProcessReady(process);
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/mach_port_relay.h b/chromium/mojo/core/mach_port_relay.h
index b8d232f20c3..4cb6de4bd64 100644
--- a/chromium/mojo/edk/system/mach_port_relay.h
+++ b/chromium/mojo/core/mach_port_relay.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_MACH_PORT_RELAY_H_
-#define MOJO_EDK_SYSTEM_MACH_PORT_RELAY_H_
+#ifndef MOJO_CORE_MACH_PORT_RELAY_H_
+#define MOJO_CORE_MACH_PORT_RELAY_H_
#include <set>
#include <vector>
@@ -11,11 +11,10 @@
#include "base/macros.h"
#include "base/process/port_provider_mac.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/channel.h"
+#include "mojo/core/channel.h"
namespace mojo {
-namespace edk {
+namespace core {
// The MachPortRelay is used by a privileged process, usually the root process,
// to manipulate Mach ports in a child process. Ports can be added to and
@@ -34,17 +33,17 @@ class MachPortRelay : public base::PortProvider::Observer {
};
// Used by a child process to receive Mach ports from a sender (privileged)
- // process. Each Mach port in |handles| is interpreted as an intermediate Mach
+ // process. The Mach port in |port| is interpreted as an intermediate Mach
// port. It replaces each Mach port with the final Mach port received from the
// intermediate port. This method takes ownership of the intermediate Mach
- // port and gives ownership of the final Mach port to the caller. Any handles
- // that are not Mach ports will remain unchanged, and the number and ordering
- // of handles is preserved.
- // On failure, the Mach port is replaced with MACH_PORT_NULL.
+ // port and gives ownership of the final Mach port to the caller.
+ //
+ // On failure, returns a null send right.
//
// See SendPortsToProcess() for the definition of intermediate and final Mach
// ports.
- static void ReceivePorts(std::vector<ScopedInternalPlatformHandle>* handles);
+ static base::mac::ScopedMachSendRight ReceiveSendRight(
+ base::mac::ScopedMachReceiveRight port);
explicit MachPortRelay(base::PortProvider* port_provider);
~MachPortRelay() override;
@@ -55,16 +54,17 @@ class MachPortRelay : public base::PortProvider::Observer {
// this intermediate port and the message is modified to refer to the name of
// the intermediate port. The Mach port received over the intermediate port in
// the child is referred to as the final Mach port.
- // Ports that cannot be brokered are replaced with MACH_PORT_NULL.
+ //
+ // All ports in |message|'s set of handles are reset by this call, and all
+ // port names in the message's header are replaced with the new receive right
+ // ports.
void SendPortsToProcess(Channel::Message* message,
base::ProcessHandle process);
- // Given a InternalPlatformHandle of Type::MACH_NAME, extracts the Mach port,
- // and updates the contents of the InternalPlatformHandle to have Type::MACH
- // and have the actual Mach port. On failure, replaces the contents with
- // Type::MACH and MACH_PORT_NULL.
- void ExtractPort(ScopedInternalPlatformHandle* handle,
- base::ProcessHandle process);
+ // Given the name of a Mach send right within |process|, extracts an owned
+ // send right ref and returns it. May return a null port on failure.
+ base::mac::ScopedMachSendRight ExtractPort(mach_port_t port_name,
+ base::ProcessHandle process);
// Observer interface.
void AddObserver(Observer* observer);
@@ -84,7 +84,7 @@ class MachPortRelay : public base::PortProvider::Observer {
DISALLOW_COPY_AND_ASSIGN(MachPortRelay);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_MACH_PORT_RELAY_H_
+#endif // MOJO_CORE_MACH_PORT_RELAY_H_
diff --git a/chromium/mojo/edk/system/message_pipe_dispatcher.cc b/chromium/mojo/core/message_pipe_dispatcher.cc
index 219ad4ccab8..00fc12e2aa0 100644
--- a/chromium/mojo/edk/system/message_pipe_dispatcher.cc
+++ b/chromium/mojo/core/message_pipe_dispatcher.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/message_pipe_dispatcher.h"
+#include "mojo/core/message_pipe_dispatcher.h"
#include <limits>
#include <memory>
@@ -10,15 +10,15 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/message_filter.h"
-#include "mojo/edk/system/request_context.h"
-#include "mojo/edk/system/user_message_impl.h"
+#include "mojo/core/core.h"
+#include "mojo/core/node_controller.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/message_filter.h"
+#include "mojo/core/request_context.h"
+#include "mojo/core/user_message_impl.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -193,6 +193,56 @@ MojoResult MessagePipeDispatcher::ReadMessage(
return MOJO_RESULT_OK;
}
+MojoResult MessagePipeDispatcher::SetQuota(MojoQuotaType type, uint64_t limit) {
+ switch (type) {
+ case MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH:
+ if (limit == MOJO_QUOTA_LIMIT_NONE)
+ receive_queue_length_limit_.reset();
+ else
+ receive_queue_length_limit_ = limit;
+ break;
+
+ case MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE:
+ if (limit == MOJO_QUOTA_LIMIT_NONE)
+ receive_queue_memory_size_limit_.reset();
+ else
+ receive_queue_memory_size_limit_ = limit;
+ break;
+
+ default:
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+
+ return MOJO_RESULT_OK;
+}
+
+MojoResult MessagePipeDispatcher::QueryQuota(MojoQuotaType type,
+ uint64_t* limit,
+ uint64_t* usage) {
+ ports::PortStatus port_status;
+ if (node_controller_->node()->GetStatus(port_, &port_status) != ports::OK) {
+ CHECK(in_transit_ || port_transferred_ || port_closed_);
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+
+ switch (type) {
+ case MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH:
+ *limit = receive_queue_length_limit_.value_or(MOJO_QUOTA_LIMIT_NONE);
+ *usage = port_status.queued_message_count;
+ break;
+
+ case MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE:
+ *limit = receive_queue_memory_size_limit_.value_or(MOJO_QUOTA_LIMIT_NONE);
+ *usage = port_status.queued_num_bytes;
+ break;
+
+ default:
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+
+ return MOJO_RESULT_OK;
+}
+
HandleSignalsState MessagePipeDispatcher::GetHandleSignalsState() const {
base::AutoLock lock(signal_lock_);
return GetHandleSignalsStateNoLock();
@@ -223,10 +273,9 @@ void MessagePipeDispatcher::StartSerialize(uint32_t* num_bytes,
*num_handles = 0;
}
-bool MessagePipeDispatcher::EndSerialize(
- void* destination,
- ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) {
+bool MessagePipeDispatcher::EndSerialize(void* destination,
+ ports::PortName* ports,
+ PlatformHandle* handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
state->pipe_id = pipe_id_;
state->endpoint = static_cast<int8_t>(endpoint_);
@@ -266,7 +315,7 @@ scoped_refptr<Dispatcher> MessagePipeDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* handles,
+ PlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles || num_bytes != sizeof(SerializedState))
return nullptr;
@@ -329,7 +378,15 @@ HandleSignalsState MessagePipeDispatcher::GetHandleSignalsStateNoLock() const {
} else {
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
}
- rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
+ if (receive_queue_length_limit_ &&
+ port_status.queued_message_count > *receive_queue_length_limit_) {
+ rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED;
+ } else if (receive_queue_memory_size_limit_ &&
+ port_status.queued_num_bytes > *receive_queue_memory_size_limit_) {
+ rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED;
+ }
+ rv.satisfiable_signals |=
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED;
return rv;
}
@@ -365,5 +422,5 @@ void MessagePipeDispatcher::OnPortStatusChanged() {
watchers_.NotifyState(GetHandleSignalsStateNoLock());
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/message_pipe_dispatcher.h b/chromium/mojo/core/message_pipe_dispatcher.h
index 64ad3d70a05..4fef7080997 100644
--- a/chromium/mojo/edk/system/message_pipe_dispatcher.h
+++ b/chromium/mojo/core/message_pipe_dispatcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
+#ifndef MOJO_CORE_MESSAGE_PIPE_DISPATCHER_H_
+#define MOJO_CORE_MESSAGE_PIPE_DISPATCHER_H_
#include <stdint.h>
@@ -11,13 +11,14 @@
#include <queue>
#include "base/macros.h"
-#include "mojo/edk/system/atomic_flag.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/ports/port_ref.h"
-#include "mojo/edk/system/watcher_set.h"
+#include "base/optional.h"
+#include "mojo/core/atomic_flag.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/ports/port_ref.h"
+#include "mojo/core/watcher_set.h"
namespace mojo {
-namespace edk {
+namespace core {
class NodeController;
@@ -51,6 +52,10 @@ class MessagePipeDispatcher : public Dispatcher {
std::unique_ptr<ports::UserMessageEvent> message) override;
MojoResult ReadMessage(
std::unique_ptr<ports::UserMessageEvent>* message) override;
+ MojoResult SetQuota(MojoQuotaType type, uint64_t limit) override;
+ MojoResult QueryQuota(MojoQuotaType type,
+ uint64_t* limit,
+ uint64_t* usage) override;
HandleSignalsState GetHandleSignalsState() const override;
MojoResult AddWatcherRef(const scoped_refptr<WatcherDispatcher>& watcher,
uintptr_t context) override;
@@ -61,18 +66,17 @@ class MessagePipeDispatcher : public Dispatcher {
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) override;
+ PlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
- static scoped_refptr<Dispatcher> Deserialize(
- const void* data,
- size_t num_bytes,
- const ports::PortName* ports,
- size_t num_ports,
- ScopedInternalPlatformHandle* handles,
- size_t num_handles);
+ static scoped_refptr<Dispatcher> Deserialize(const void* data,
+ size_t num_bytes,
+ const ports::PortName* ports,
+ size_t num_ports,
+ PlatformHandle* handles,
+ size_t num_handles);
private:
class PortObserverThunk;
@@ -100,11 +104,13 @@ class MessagePipeDispatcher : public Dispatcher {
bool port_transferred_ = false;
AtomicFlag port_closed_;
WatcherSet watchers_;
+ base::Optional<uint64_t> receive_queue_length_limit_;
+ base::Optional<uint64_t> receive_queue_memory_size_limit_;
DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
+#endif // MOJO_CORE_MESSAGE_PIPE_DISPATCHER_H_
diff --git a/chromium/mojo/edk/system/message_pipe_perftest.cc b/chromium/mojo/core/message_pipe_perftest.cc
index 70c00920f44..93c833a559b 100644
--- a/chromium/mojo/edk/system/message_pipe_perftest.cc
+++ b/chromium/mojo/core/message_pipe_perftest.cc
@@ -15,18 +15,17 @@
#include "base/strings/stringprintf.h"
#include "base/test/perf_time_logger.h"
#include "base/threading/thread.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/test/mojo_test_base.h"
-#include "mojo/edk/test/test_utils.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/handle_signals_state.h"
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/core/test/test_utils.h"
+#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
class MessagePipePerfTest : public test::MojoTestBase {
@@ -158,5 +157,5 @@ TEST_F(MessagePipePerfTest, MultiprocessPingPong) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/message_pipe_unittest.cc b/chromium/mojo/core/message_pipe_unittest.cc
index 2cdc58edd3a..20c71ff4549 100644
--- a/chromium/mojo/edk/system/message_pipe_unittest.cc
+++ b/chromium/mojo/core/message_pipe_unittest.cc
@@ -12,19 +12,21 @@
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/test/mojo_test_base.h"
+#include "build/build_config.h"
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/core/test_utils.h"
#include "mojo/public/c/system/core.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/message_pipe.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
const MojoHandleSignals kAllSignals =
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE;
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE |
+ MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED;
static const char kHelloWorld[] = "hello world";
@@ -278,29 +280,23 @@ TEST_F(MessagePipeTest, BasicWaiting) {
hss = MojoHandleSignalsState();
ASSERT_EQ(MOJO_RESULT_OK,
WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss));
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
+ ASSERT_TRUE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+ ASSERT_TRUE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_CLOSED);
- // Port 1 should not be writable.
+ // Port 1 should not be writable now or ever again.
hss = MojoHandleSignalsState();
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_WRITABLE, &hss));
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
+ ASSERT_FALSE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
+ ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
// But it should still be readable.
hss = MojoHandleSignalsState();
ASSERT_EQ(MOJO_RESULT_OK,
WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- hss.satisfiable_signals);
+ ASSERT_TRUE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_TRUE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
// Read from port 1.
buffer[0] = 0;
@@ -313,7 +309,8 @@ TEST_F(MessagePipeTest, BasicWaiting) {
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &hss));
ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
+ ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
}
#if !defined(OS_IOS)
@@ -555,5 +552,5 @@ TEST_F(MessagePipeTest, ClosePipesStressTest) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/message_unittest.cc b/chromium/mojo/core/message_unittest.cc
index b493bad3166..ce44f221441 100644
--- a/chromium/mojo/edk/system/message_unittest.cc
+++ b/chromium/mojo/core/message_unittest.cc
@@ -11,16 +11,15 @@
#include "base/numerics/safe_math.h"
#include "base/rand_util.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/system/user_message_impl.h"
-#include "mojo/edk/test/mojo_test_base.h"
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/core/user_message_impl.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/buffer.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
using MessageTest = test::MojoTestBase;
@@ -815,11 +814,15 @@ TEST_F(MessageTest, ExtendPayloadWithHandlesAttached) {
MojoHandle handles[5];
CreateMessagePipe(&handles[0], &handles[1]);
- PlatformChannelPair channel;
- ASSERT_EQ(MOJO_RESULT_OK, CreateInternalPlatformHandleWrapper(
- channel.PassServerHandle(), &handles[2]));
- ASSERT_EQ(MOJO_RESULT_OK, CreateInternalPlatformHandleWrapper(
- channel.PassClientHandle(), &handles[3]));
+ PlatformChannel channel;
+ handles[2] =
+ WrapPlatformHandle(channel.TakeLocalEndpoint().TakePlatformHandle())
+ .release()
+ .value();
+ handles[3] =
+ WrapPlatformHandle(channel.TakeRemoteEndpoint().TakePlatformHandle())
+ .release()
+ .value();
handles[4] = SharedBufferHandle::Create(64).release().value();
MojoMessageHandle message;
@@ -864,11 +867,15 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndIgnoreMessage, MessageTest, h) {
TEST_F(MessageTest, ExtendPayloadWithHandlesAttachedViaExtension) {
MojoHandle handles[5];
CreateMessagePipe(&handles[0], &handles[4]);
- PlatformChannelPair channel;
- ASSERT_EQ(MOJO_RESULT_OK, CreateInternalPlatformHandleWrapper(
- channel.PassServerHandle(), &handles[1]));
- ASSERT_EQ(MOJO_RESULT_OK, CreateInternalPlatformHandleWrapper(
- channel.PassClientHandle(), &handles[2]));
+ PlatformChannel channel;
+ handles[1] =
+ WrapPlatformHandle(channel.TakeLocalEndpoint().TakePlatformHandle())
+ .release()
+ .value();
+ handles[2] =
+ WrapPlatformHandle(channel.TakeRemoteEndpoint().TakePlatformHandle())
+ .release()
+ .value();
handles[3] = SharedBufferHandle::Create(64).release().value();
MojoMessageHandle message;
@@ -945,5 +952,5 @@ TEST_F(MessageTest, PartiallySerializedMessagesDontLeakHandles) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/mojo_core.cc b/chromium/mojo/core/mojo_core.cc
index b0c652750bf..9823b201709 100644
--- a/chromium/mojo/edk/mojo_core.cc
+++ b/chromium/mojo/core/mojo_core.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "base/time/time.h"
-#include "mojo/edk/embedder/entrypoints.h"
-#include "mojo/edk/system/core.h"
+#include "mojo/core/core.h"
+#include "mojo/core/entrypoints.h"
#include "mojo/public/c/system/core.h"
#include "mojo/public/c/system/thunks.h"
@@ -13,7 +13,7 @@ extern "C" {
namespace {
MojoResult InitializeImpl(const struct MojoInitializeOptions* options) {
- mojo::edk::InitializeCore();
+ mojo::core::InitializeCore();
return MOJO_RESULT_OK;
}
@@ -29,7 +29,7 @@ MojoSystemThunks g_thunks = {0};
EXPORT_FROM_MOJO_CORE void MojoGetSystemThunks(MojoSystemThunks* thunks) {
if (!g_thunks.size) {
- g_thunks = mojo::edk::GetSystemThunks();
+ g_thunks = mojo::core::GetSystemThunks();
g_thunks.Initialize = InitializeImpl;
}
diff --git a/chromium/mojo/core/mojo_core.def b/chromium/mojo/core/mojo_core.def
new file mode 100644
index 00000000000..59c73515990
--- /dev/null
+++ b/chromium/mojo/core/mojo_core.def
@@ -0,0 +1,10 @@
+; Copyright 2018 The Chromium Authors. All rights reserved.
+; Use of this source code is governed by a BSD-style license that can be
+; found in the LICENSE file.
+
+; Ensure that we export only MojoGetSystemThunks from the mojo_core library.
+
+LIBRARY "mojo_core.dll"
+
+EXPORTS
+ MojoGetSystemThunks
diff --git a/chromium/mojo/edk/mojo_core_unittest.cc b/chromium/mojo/core/mojo_core_unittest.cc
index 8428e09859b..8428e09859b 100644
--- a/chromium/mojo/edk/mojo_core_unittest.cc
+++ b/chromium/mojo/core/mojo_core_unittest.cc
diff --git a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/chromium/mojo/core/multiprocess_message_pipe_unittest.cc
index 946a21a53b2..b69af363535 100644
--- a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc
+++ b/chromium/mojo/core/multiprocess_message_pipe_unittest.cc
@@ -22,22 +22,21 @@
#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/test_utils.h"
-#include "mojo/edk/test/mojo_test_base.h"
-#include "mojo/edk/test/test_utils.h"
+#include "mojo/core/handle_signals_state.h"
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/core/test/test_utils.h"
+#include "mojo/core/test_utils.h"
#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/message_pipe.h"
+#include "mojo/public/cpp/system/platform_handle.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "mojo/public/cpp/system/wait.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
// Temporary helpers to avoid tons of churn as old APIs are removed. These
@@ -249,8 +248,8 @@ TEST_P(MultiprocessMessagePipeTestWithPeerSupport, QueueMessages) {
HandleSignalsState hss;
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
+ ASSERT_FALSE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
});
EXPECT_EQ(static_cast<int>(kNumMessages % 100), exit_code);
}
@@ -266,9 +265,6 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer,
// pipe before we do.
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE);
// It should have a shared buffer.
std::string read_buffer(100, '\0');
@@ -305,9 +301,6 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer,
MOJO_RESULT_OK);
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE);
read_buffer = std::string(100, '\0');
num_bytes = static_cast<uint32_t>(read_buffer.size());
@@ -397,12 +390,12 @@ TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) {
hss = HandleSignalsState();
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
+ ASSERT_FALSE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
});
}
-DEFINE_TEST_CLIENT_WITH_PIPE(CheckInternalPlatformHandleFile,
+DEFINE_TEST_CLIENT_WITH_PIPE(CheckPlatformHandleFile,
MultiprocessMessagePipeTest,
h) {
HandleSignalsState hss;
@@ -410,9 +403,6 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckInternalPlatformHandleFile,
MOJO_RESULT_OK);
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE);
std::string read_buffer(100, '\0');
uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
@@ -431,13 +421,10 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckInternalPlatformHandleFile,
CHECK_GT(num_handles, 0);
for (int i = 0; i < num_handles; ++i) {
- ScopedInternalPlatformHandle h;
- CHECK_EQ(PassWrappedInternalPlatformHandle(handles[i], &h), MOJO_RESULT_OK);
+ PlatformHandle h = UnwrapPlatformHandle(ScopedHandle(Handle(handles[i])));
CHECK(h.is_valid());
- MojoClose(handles[i]);
- base::ScopedFILE fp(
- test::FILEFromInternalPlatformHandle(std::move(h), "r"));
+ base::ScopedFILE fp = test::FILEFromPlatformHandle(std::move(h), "r");
CHECK(fp);
std::string fread_buffer(100, '\0');
size_t bytes_read =
@@ -453,12 +440,11 @@ class MultiprocessMessagePipeTestWithPipeCount
: public MultiprocessMessagePipeTest,
public testing::WithParamInterface<size_t> {};
-TEST_P(MultiprocessMessagePipeTestWithPipeCount,
- InternalPlatformHandlePassing) {
+TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- RunTestClient("CheckInternalPlatformHandleFile", [&](MojoHandle h) {
+ RunTestClient("CheckPlatformHandleFile", [&](MojoHandle h) {
std::vector<MojoHandle> handles;
size_t pipe_count = GetParam();
@@ -470,13 +456,10 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount,
CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size());
fflush(fp.get());
rewind(fp.get());
- MojoHandle handle;
- ASSERT_EQ(CreateInternalPlatformHandleWrapper(
- ScopedInternalPlatformHandle(
- test::InternalPlatformHandleFromFILE(std::move(fp))),
- &handle),
- MOJO_RESULT_OK);
- handles.push_back(handle);
+ ScopedHandle handle =
+ WrapPlatformHandle(test::PlatformHandleFromFILE(std::move(fp)));
+ ASSERT_TRUE(handle.is_valid());
+ handles.push_back(handle.release().value());
}
char message[128];
@@ -492,8 +475,8 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount,
HandleSignalsState hss;
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
- ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
+ ASSERT_FALSE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
});
}
@@ -517,9 +500,6 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe, MultiprocessMessagePipeTest, h) {
// pipe before we do.
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE);
// It should have a message pipe.
MojoHandle handles[10];
@@ -534,9 +514,6 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe, MultiprocessMessagePipeTest, h) {
MOJO_RESULT_OK);
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE);
std::string read_buffer(100, '\0');
uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
@@ -637,7 +614,8 @@ DEFINE_TEST_CLIENT_WITH_PIPE(DataPipeConsumer, MultiprocessMessagePipeTest, h) {
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
CHECK_EQ(hss.satisfiable_signals,
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE);
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE |
+ MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
// It should have a message pipe.
MojoHandle handles[10];
@@ -654,7 +632,8 @@ DEFINE_TEST_CLIENT_WITH_PIPE(DataPipeConsumer, MultiprocessMessagePipeTest, h) {
CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
CHECK_EQ(hss.satisfiable_signals,
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE);
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE |
+ MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
std::string read_buffer(100, '\0');
uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
@@ -1348,58 +1327,6 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(BadMessageClient,
EXPECT_EQ("bye", ReadMessage(parent));
}
-void OnProcessError(std::string* out_error, const std::string& error) {
- *out_error = error;
-}
-
-TEST_F(MultiprocessMessagePipeTest, NotifyBadMessage) {
- const std::string kFirstErrorMessage = "everything is terrible!";
- const std::string kSecondErrorMessage = "not the bits you're looking for";
-
- std::string first_process_error;
- std::string second_process_error;
-
- set_process_error_callback(base::Bind(&OnProcessError, &first_process_error));
- RunTestClient("BadMessageClient", [&](MojoHandle child1) {
- set_process_error_callback(
- base::Bind(&OnProcessError, &second_process_error));
- RunTestClient("BadMessageClient", [&](MojoHandle child2) {
- MojoHandle a, b, c, d;
- CreateMessagePipe(&a, &b);
- CreateMessagePipe(&c, &d);
- WriteMessageWithHandles(child1, "hi", &b, 1);
- WriteMessageWithHandles(child2, "hi", &d, 1);
-
- // Read a message from the pipe we sent to child1 and flag it as bad.
- ASSERT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_READABLE));
- MojoMessageHandle message;
- ASSERT_EQ(MOJO_RESULT_OK, ::MojoReadMessage(a, nullptr, &message));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoNotifyBadMessage(
- message, kFirstErrorMessage.data(),
- static_cast<uint32_t>(kFirstErrorMessage.size()), nullptr));
- EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
-
- // Read a message from the pipe we sent to child2 and flag it as bad.
- ASSERT_EQ(MOJO_RESULT_OK, WaitForSignals(c, MOJO_HANDLE_SIGNAL_READABLE));
- ASSERT_EQ(MOJO_RESULT_OK, ::MojoReadMessage(c, nullptr, &message));
- EXPECT_EQ(
- MOJO_RESULT_OK,
- MojoNotifyBadMessage(
- message, kSecondErrorMessage.data(),
- static_cast<uint32_t>(kSecondErrorMessage.size()), nullptr));
- EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
-
- WriteMessage(child2, "bye");
- });
-
- WriteMessage(child1, "bye");
- });
-
- // The error messages should match the processes which triggered them.
- 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,
@@ -1408,5 +1335,5 @@ INSTANTIATE_TEST_CASE_P(
test::MojoTestBase::LaunchType::NAMED_CHILD,
test::MojoTestBase::LaunchType::NAMED_PEER));
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/node_channel.cc b/chromium/mojo/core/node_channel.cc
index f2e4ade4298..ebcb8812e1e 100644
--- a/chromium/mojo/edk/system/node_channel.cc
+++ b/chromium/mojo/core/node_channel.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/node_channel.h"
+#include "mojo/core/node_channel.h"
#include <cstring>
#include <limits>
@@ -12,16 +12,13 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/request_context.h"
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-#include "mojo/edk/system/mach_port_relay.h"
-#endif
+#include "mojo/core/channel.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/core.h"
+#include "mojo/core/request_context.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -194,12 +191,6 @@ void NodeChannel::GetEventMessageData(Channel::Message* message,
}
void NodeChannel::Start() {
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- MachPortRelay* relay = delegate_->GetMachPortRelay();
- if (relay)
- relay->AddObserver(this);
-#endif
-
base::AutoLock lock(channel_lock_);
// ShutDown() may have already been called, in which case |channel_| is null.
if (channel_)
@@ -207,12 +198,6 @@ void NodeChannel::Start() {
}
void NodeChannel::ShutDown() {
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- MachPortRelay* relay = delegate_->GetMachPortRelay();
- if (relay)
- relay->RemoveObserver(this);
-#endif
-
base::AutoLock lock(channel_lock_);
if (channel_) {
channel_->ShutDown();
@@ -234,6 +219,11 @@ void NodeChannel::NotifyBadMessage(const std::string& error) {
void NodeChannel::SetRemoteProcessHandle(ScopedProcessHandle process_handle) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ {
+ base::AutoLock lock(channel_lock_);
+ if (channel_)
+ channel_->set_remote_process(process_handle.Clone());
+ }
base::AutoLock lock(remote_process_handle_lock_);
DCHECK(!remote_process_handle_.is_valid());
CHECK_NE(remote_process_handle_.get(), base::GetCurrentProcessHandle());
@@ -292,10 +282,9 @@ void NodeChannel::AcceptPeer(const ports::NodeName& sender_name,
void NodeChannel::AddBrokerClient(const ports::NodeName& client_name,
ScopedProcessHandle process_handle) {
AddBrokerClientData* data;
- std::vector<ScopedInternalPlatformHandle> handles;
+ std::vector<PlatformHandle> handles;
#if defined(OS_WIN)
- handles.emplace_back(ScopedInternalPlatformHandle(
- InternalPlatformHandle(process_handle.release())));
+ handles.emplace_back(base::win::ScopedHandle(process_handle.release()));
#endif
Channel::MessagePtr message =
CreateMessage(MessageType::ADD_BROKER_CLIENT, sizeof(AddBrokerClientData),
@@ -309,13 +298,12 @@ void NodeChannel::AddBrokerClient(const ports::NodeName& client_name,
WriteChannelMessage(std::move(message));
}
-void NodeChannel::BrokerClientAdded(
- const ports::NodeName& client_name,
- ScopedInternalPlatformHandle broker_channel) {
+void NodeChannel::BrokerClientAdded(const ports::NodeName& client_name,
+ PlatformHandle broker_channel) {
BrokerClientAddedData* data;
- std::vector<ScopedInternalPlatformHandle> handles;
+ std::vector<PlatformHandle> handles;
if (broker_channel.is_valid())
- handles.push_back(std::move(broker_channel));
+ handles.emplace_back(std::move(broker_channel));
Channel::MessagePtr message =
CreateMessage(MessageType::BROKER_CLIENT_ADDED,
sizeof(BrokerClientAddedData), handles.size(), &data);
@@ -324,13 +312,12 @@ void NodeChannel::BrokerClientAdded(
WriteChannelMessage(std::move(message));
}
-void NodeChannel::AcceptBrokerClient(
- const ports::NodeName& broker_name,
- ScopedInternalPlatformHandle broker_channel) {
+void NodeChannel::AcceptBrokerClient(const ports::NodeName& broker_name,
+ PlatformHandle broker_channel) {
AcceptBrokerClientData* data;
- std::vector<ScopedInternalPlatformHandle> handles;
+ std::vector<PlatformHandle> handles;
if (broker_channel.is_valid())
- handles.push_back(std::move(broker_channel));
+ handles.emplace_back(std::move(broker_channel));
Channel::MessagePtr message =
CreateMessage(MessageType::ACCEPT_BROKER_CLIENT,
sizeof(AcceptBrokerClientData), handles.size(), &data);
@@ -342,9 +329,9 @@ void NodeChannel::AcceptBrokerClient(
void NodeChannel::RequestPortMerge(const ports::PortName& connector_port_name,
const std::string& token) {
RequestPortMergeData* data;
- Channel::MessagePtr message = CreateMessage(
- MessageType::REQUEST_PORT_MERGE,
- sizeof(RequestPortMergeData) + token.size(), 0, &data);
+ Channel::MessagePtr message =
+ CreateMessage(MessageType::REQUEST_PORT_MERGE,
+ sizeof(RequestPortMergeData) + token.size(), 0, &data);
data->connector_port_name = connector_port_name;
memcpy(data + 1, token.data(), token.size());
WriteChannelMessage(std::move(message));
@@ -359,11 +346,11 @@ void NodeChannel::RequestIntroduction(const ports::NodeName& name) {
}
void NodeChannel::Introduce(const ports::NodeName& name,
- ScopedInternalPlatformHandle channel_handle) {
+ PlatformHandle channel_handle) {
IntroductionData* data;
- std::vector<ScopedInternalPlatformHandle> handles;
+ std::vector<PlatformHandle> handles;
if (channel_handle.is_valid())
- handles.push_back(std::move(channel_handle));
+ handles.emplace_back(std::move(channel_handle));
Channel::MessagePtr message = CreateMessage(
MessageType::INTRODUCE, sizeof(IntroductionData), handles.size(), &data);
message->SetHandles(std::move(handles));
@@ -409,9 +396,9 @@ void NodeChannel::RelayEventMessage(const ports::NodeName& destination,
// above stated assumption. We should not leak handles in cases where we
// outlive the broker, as we may continue existing and eventually accept a new
// broker invitation.
- std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
for (auto& handle : handles)
- ignore_result(handle.release());
+ handle.TakeHandle().release();
#else
DCHECK(message->has_mach_ports());
@@ -421,7 +408,7 @@ void NodeChannel::RelayEventMessage(const ports::NodeName& destination,
// moves them back to the relayed message. This is necessary because the
// message may contain fds which need to be attached to the outer message so
// that they can be transferred to the broker.
- std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
size_t num_bytes = sizeof(RelayEventMessageData) + message->data_num_bytes();
RelayEventMessageData* data;
Channel::MessagePtr relay_message = CreateMessage(
@@ -469,10 +456,9 @@ NodeChannel::~NodeChannel() {
ShutDown();
}
-void NodeChannel::OnChannelMessage(
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) {
+void NodeChannel::OnChannelMessage(const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
RequestContext request_context(RequestContext::Source::SYSTEM);
@@ -482,41 +468,6 @@ void NodeChannel::OnChannelMessage(
// to drop it here in response to, e.g., a malformed message.
scoped_refptr<NodeChannel> keepalive = this;
-#if defined(OS_WIN)
- // If we receive handles from a known process, rewrite them to our own
- // process. This can occur when a privileged node receives handles directly
- // from a privileged descendant.
- {
- base::AutoLock lock(remote_process_handle_lock_);
- if (!handles.empty() && remote_process_handle_.is_valid()) {
- // Note that we explicitly mark the handles as being owned by the sending
- // process before rewriting them, in order to accommodate RewriteHandles'
- // internal sanity checks.
- for (auto& handle : handles)
- handle.get().owning_process = remote_process_handle_.get();
- if (!Channel::Message::RewriteHandles(remote_process_handle_.get(),
- base::GetCurrentProcessHandle(),
- &handles)) {
- DLOG(ERROR) << "Received one or more invalid handles.";
- }
- } else if (!handles.empty()) {
- // Handles received by an unknown process must already be owned by us.
- for (auto& handle : handles)
- handle.get().owning_process = base::GetCurrentProcessHandle();
- }
- }
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
- // If we're not the root, receive any mach ports from the message. If we're
- // the root, the only message containing mach ports should be a
- // RELAY_EVENT_MESSAGE.
- {
- MachPortRelay* relay = delegate_->GetMachPortRelay();
- if (!handles.empty() && !relay)
- MachPortRelay::ReceivePorts(&handles);
- }
-#endif // defined(OS_WIN)
-
-
if (payload_size <= sizeof(Header)) {
delegate_->OnChannelError(remote_node_name_, this);
return;
@@ -553,7 +504,7 @@ void NodeChannel::OnChannelMessage(
break;
}
delegate_->OnAddBrokerClient(remote_node_name_, data->client_name,
- handles.at(0).release().handle);
+ handles[0].ReleaseHandle());
#else
if (!handles.empty()) {
DLOG(ERROR) << "Dropping invalid AddBrokerClient message.";
@@ -575,7 +526,7 @@ void NodeChannel::OnChannelMessage(
break;
}
delegate_->OnBrokerClientAdded(remote_node_name_, data->client_name,
- std::move(handles.at(0)));
+ std::move(handles[0]));
return;
}
break;
@@ -584,14 +535,14 @@ void NodeChannel::OnChannelMessage(
case MessageType::ACCEPT_BROKER_CLIENT: {
const AcceptBrokerClientData* data;
if (GetMessagePayload(payload, payload_size, &data)) {
- ScopedInternalPlatformHandle broker_channel;
+ PlatformHandle broker_channel;
if (handles.size() > 1) {
DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message.";
break;
}
- if (handles.size() == 1) {
- broker_channel = std::move(handles.at(0));
- }
+ if (handles.size() == 1)
+ broker_channel = std::move(handles[0]);
+
delegate_->OnAcceptBrokerClient(remote_node_name_, data->broker_name,
std::move(broker_channel));
return;
@@ -639,10 +590,10 @@ void NodeChannel::OnChannelMessage(
DLOG(ERROR) << "Dropping invalid introduction message.";
break;
}
- ScopedInternalPlatformHandle channel_handle;
- if (handles.size() == 1) {
- channel_handle = std::move(handles.at(0));
- }
+ PlatformHandle channel_handle;
+ if (handles.size() == 1)
+ channel_handle = std::move(handles[0]);
+
delegate_->OnIntroduce(remote_node_name_, data->name,
std::move(channel_handle));
return;
@@ -668,29 +619,15 @@ void NodeChannel::OnChannelMessage(
const void* message_start = data + 1;
Channel::MessagePtr message = Channel::Message::Deserialize(
- message_start, payload_size - sizeof(Header) - sizeof(*data));
+ message_start, payload_size - sizeof(Header) - sizeof(*data),
+ from_process);
if (!message) {
DLOG(ERROR) << "Dropping invalid relay message.";
break;
}
- #if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
message->SetHandles(std::move(handles));
- MachPortRelay* relay = delegate_->GetMachPortRelay();
- if (!relay) {
- LOG(ERROR) << "Receiving mach ports without a port relay from "
- << remote_node_name_ << ". Dropping message.";
- break;
- }
- {
- base::AutoLock lock(pending_mach_messages_lock_);
- if (relay->port_provider()->TaskForPid(from_process) ==
- MACH_PORT_NULL) {
- pending_relay_messages_.push(
- std::make_pair(data->destination, std::move(message)));
- return;
- }
- }
- #endif
+#endif
delegate_->OnRelayEventMessage(remote_node_name_, from_process,
data->destination, std::move(message));
return;
@@ -776,105 +713,7 @@ void NodeChannel::OnChannelError(Channel::Error error) {
delegate_->OnChannelError(node_name, this);
}
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-void NodeChannel::OnProcessReady(base::ProcessHandle process) {
- io_task_runner_->PostTask(FROM_HERE, base::Bind(
- &NodeChannel::ProcessPendingMessagesWithMachPorts, this));
-}
-
-void NodeChannel::ProcessPendingMessagesWithMachPorts() {
- MachPortRelay* relay = delegate_->GetMachPortRelay();
- DCHECK(relay);
-
- base::ProcessHandle remote_process_handle;
- {
- base::AutoLock lock(remote_process_handle_lock_);
- remote_process_handle = remote_process_handle_.get();
- }
- PendingMessageQueue pending_writes;
- PendingRelayMessageQueue pending_relays;
- {
- base::AutoLock lock(pending_mach_messages_lock_);
- pending_writes.swap(pending_write_messages_);
- pending_relays.swap(pending_relay_messages_);
- }
-
- while (!pending_writes.empty()) {
- Channel::MessagePtr message = std::move(pending_writes.front());
- pending_writes.pop();
- relay->SendPortsToProcess(message.get(), remote_process_handle);
-
- base::AutoLock lock(channel_lock_);
- if (!channel_) {
- DLOG(ERROR) << "Dropping message on closed channel.";
- break;
- } else {
- channel_->Write(std::move(message));
- }
- }
-
- // Ensure this NodeChannel stays alive while flushing relay messages.
- scoped_refptr<NodeChannel> keepalive = this;
-
- while (!pending_relays.empty()) {
- ports::NodeName destination = pending_relays.front().first;
- Channel::MessagePtr message = std::move(pending_relays.front().second);
- pending_relays.pop();
- delegate_->OnRelayEventMessage(remote_node_name_, remote_process_handle,
- destination, std::move(message));
- }
-}
-#endif
-
void NodeChannel::WriteChannelMessage(Channel::MessagePtr message) {
-#if defined(OS_WIN)
- // Map handles to the destination process. Note: only messages from a
- // privileged node should contain handles on Windows. If an unprivileged
- // node needs to send handles, it should do so via RelayEventMessage which
- // stashes the handles in the message in such a way that they go undetected
- // here (they'll be unpacked and duplicated by the broker).
-
- if (message->has_handles()) {
- base::AutoLock lock(remote_process_handle_lock_);
-
- // Rewrite outgoing handles if we have a handle to the destination process.
- if (remote_process_handle_.is_valid()) {
- std::vector<ScopedInternalPlatformHandle> handles =
- message->TakeHandles();
- if (!Channel::Message::RewriteHandles(base::GetCurrentProcessHandle(),
- remote_process_handle_.get(),
- &handles)) {
- DLOG(ERROR) << "Failed to duplicate one or more outgoing handles.";
- }
- message->SetHandles(std::move(handles));
- }
- }
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
- // On OSX, we need to transfer mach ports to the destination process before
- // transferring the message itself.
- if (message->has_mach_ports()) {
- MachPortRelay* relay = delegate_->GetMachPortRelay();
- if (relay) {
- base::AutoLock lock(remote_process_handle_lock_);
- DCHECK(remote_process_handle_.is_valid());
- {
- base::AutoLock lock(pending_mach_messages_lock_);
- if (relay->port_provider()->TaskForPid(remote_process_handle_.get()) ==
- MACH_PORT_NULL) {
- // It is also possible for TaskForPid() to return MACH_PORT_NULL when
- // the process has started, then died. In that case, the queued
- // message will never be processed. But that's fine since we're about
- // to die anyway.
- pending_write_messages_.push(std::move(message));
- return;
- }
- }
-
- relay->SendPortsToProcess(message.get(), remote_process_handle_.get());
- }
- }
-#endif
-
// Force a crash if this process attempts to send a message larger than the
// maximum allowed size. This is more useful than killing a Channel when we
// *receive* an oversized message, as we should consider oversized message
@@ -888,5 +727,5 @@ void NodeChannel::WriteChannelMessage(Channel::MessagePtr message) {
channel_->Write(std::move(message));
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/node_channel.h b/chromium/mojo/core/node_channel.h
index 95fd6ed6410..5573305013f 100644
--- a/chromium/mojo/edk/system/node_channel.h
+++ b/chromium/mojo/core/node_channel.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_NODE_CHANNEL_H_
-#define MOJO_EDK_SYSTEM_NODE_CHANNEL_H_
+#ifndef MOJO_CORE_NODE_CHANNEL_H_
+#define MOJO_CORE_NODE_CHANNEL_H_
#include <utility>
#include <vector>
@@ -16,27 +16,18 @@
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/connection_params.h"
-#include "mojo/edk/embedder/process_error_callback.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/ports/name.h"
-#include "mojo/edk/system/scoped_process_handle.h"
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-#include "mojo/edk/system/mach_port_relay.h"
-#endif
+#include "mojo/core/channel.h"
+#include "mojo/core/connection_params.h"
+#include "mojo/core/embedder/process_error_callback.h"
+#include "mojo/core/ports/name.h"
+#include "mojo/core/scoped_process_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
// Wraps a Channel to send and receive Node control messages.
class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
- public Channel::Delegate
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- , public MachPortRelay::Observer
-#endif
- {
+ public Channel::Delegate {
public:
class Delegate {
public:
@@ -50,14 +41,12 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
virtual void OnAddBrokerClient(const ports::NodeName& from_node,
const ports::NodeName& client_name,
base::ProcessHandle process_handle) = 0;
- virtual void OnBrokerClientAdded(
- const ports::NodeName& from_node,
- const ports::NodeName& client_name,
- ScopedInternalPlatformHandle broker_channel) = 0;
- virtual void OnAcceptBrokerClient(
- const ports::NodeName& from_node,
- const ports::NodeName& broker_name,
- ScopedInternalPlatformHandle broker_channel) = 0;
+ virtual void OnBrokerClientAdded(const ports::NodeName& from_node,
+ const ports::NodeName& client_name,
+ PlatformHandle broker_channel) = 0;
+ virtual void OnAcceptBrokerClient(const ports::NodeName& from_node,
+ const ports::NodeName& broker_name,
+ PlatformHandle broker_channel) = 0;
virtual void OnEventMessage(const ports::NodeName& from_node,
Channel::MessagePtr message) = 0;
virtual void OnRequestPortMerge(const ports::NodeName& from_node,
@@ -67,7 +56,7 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
const ports::NodeName& name) = 0;
virtual void OnIntroduce(const ports::NodeName& from_node,
const ports::NodeName& name,
- ScopedInternalPlatformHandle channel_handle) = 0;
+ PlatformHandle channel_handle) = 0;
virtual void OnBroadcast(const ports::NodeName& from_node,
Channel::MessagePtr message) = 0;
#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
@@ -85,10 +74,6 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
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;
-#endif
};
static scoped_refptr<NodeChannel> Create(
@@ -135,14 +120,13 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
void AddBrokerClient(const ports::NodeName& client_name,
ScopedProcessHandle process_handle);
void BrokerClientAdded(const ports::NodeName& client_name,
- ScopedInternalPlatformHandle broker_channel);
+ PlatformHandle broker_channel);
void AcceptBrokerClient(const ports::NodeName& broker_name,
- ScopedInternalPlatformHandle broker_channel);
+ PlatformHandle broker_channel);
void RequestPortMerge(const ports::PortName& connector_port_name,
const std::string& token);
void RequestIntroduction(const ports::NodeName& name);
- void Introduce(const ports::NodeName& name,
- ScopedInternalPlatformHandle channel_handle);
+ void Introduce(const ports::NodeName& name, PlatformHandle channel_handle);
void SendChannelMessage(Channel::MessagePtr message);
void Broadcast(Channel::MessagePtr message);
@@ -175,19 +159,11 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
~NodeChannel() override;
// Channel::Delegate:
- void OnChannelMessage(
- const void* payload,
- size_t payload_size,
- std::vector<ScopedInternalPlatformHandle> handles) override;
+ void OnChannelMessage(const void* payload,
+ size_t payload_size,
+ std::vector<PlatformHandle> handles) override;
void OnChannelError(Channel::Error error) override;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- // MachPortRelay::Observer:
- void OnProcessReady(base::ProcessHandle process) override;
-
- void ProcessPendingMessagesWithMachPorts();
-#endif
-
void WriteChannelMessage(Channel::MessagePtr message);
Delegate* const delegate_;
@@ -203,16 +179,10 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
base::Lock remote_process_handle_lock_;
ScopedProcessHandle remote_process_handle_;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- base::Lock pending_mach_messages_lock_;
- PendingMessageQueue pending_write_messages_;
- PendingRelayMessageQueue pending_relay_messages_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(NodeChannel);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_NODE_CHANNEL_H_
+#endif // MOJO_CORE_NODE_CHANNEL_H_
diff --git a/chromium/mojo/edk/system/node_controller.cc b/chromium/mojo/core/node_controller.cc
index ee602c46340..fc65c4d5b6d 100644
--- a/chromium/mojo/edk/system/node_controller.cc
+++ b/chromium/mojo/core/node_controller.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/node_controller.h"
+#include "mojo/core/node_controller.h"
#include <algorithm>
#include <limits>
@@ -19,18 +19,21 @@
#include "base/rand_util.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.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/configuration.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/request_context.h"
-#include "mojo/edk/system/user_message_impl.h"
+#include "mojo/core/broker.h"
+#include "mojo/core/broker_host.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/core.h"
+#include "mojo/core/request_context.h"
+#include "mojo/core/user_message_impl.h"
+#include "mojo/public/cpp/platform/named_platform_channel.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
-#include "mojo/edk/system/mach_port_relay.h"
+#include "mojo/core/mach_port_relay.h"
#endif
#if !defined(OS_NACL)
@@ -38,16 +41,20 @@
#endif
namespace mojo {
-namespace edk {
+namespace core {
namespace {
#if defined(OS_NACL)
template <typename T>
-void GenerateRandomName(T* out) { base::RandBytes(out, sizeof(T)); }
+void GenerateRandomName(T* out) {
+ base::RandBytes(out, sizeof(T));
+}
#else
template <typename T>
-void GenerateRandomName(T* out) { crypto::RandBytes(out, sizeof(T)); }
+void GenerateRandomName(T* out) {
+ crypto::RandBytes(out, sizeof(T));
+}
#endif
ports::NodeName GetRandomNodeName() {
@@ -150,8 +157,7 @@ NodeController::NodeController(Core* core)
}
#if defined(OS_MACOSX) && !defined(OS_IOS)
-void NodeController::CreateMachPortRelay(
- base::PortProvider* port_provider) {
+void NodeController::CreateMachPortRelay(base::PortProvider* port_provider) {
base::AutoLock lock(mach_port_relay_lock_);
DCHECK(!mach_port_relay_);
mach_port_relay_.reset(new MachPortRelay(port_provider));
@@ -201,12 +207,13 @@ void NodeController::AcceptBrokerClientInvitation(
#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA)
// Use the bootstrap channel for the broker and receive the node's channel
// synchronously as the first message from the broker.
+ DCHECK(connection_params.endpoint().is_valid());
base::ElapsedTimer timer;
- broker_.reset(new Broker(connection_params.TakeChannelHandle()));
- ScopedInternalPlatformHandle platform_handle =
- broker_->GetInviterInternalPlatformHandle();
+ broker_ = std::make_unique<Broker>(
+ connection_params.TakeEndpoint().TakePlatformHandle());
+ PlatformChannelEndpoint endpoint = broker_->GetInviterEndpoint();
- if (!platform_handle.is_valid()) {
+ if (!endpoint.is_valid()) {
// Most likely the inviter's side of the channel has already been closed and
// the broker was unable to negotiate a NodeChannel pipe. In this case we
// can cancel our connection to our inviter.
@@ -214,8 +221,7 @@ void NodeController::AcceptBrokerClientInvitation(
CancelPendingPortMerges();
return;
}
- connection_params = ConnectionParams(connection_params.protocol(),
- std::move(platform_handle));
+ connection_params = ConnectionParams(std::move(endpoint));
#endif
io_task_runner_->PostTask(
@@ -224,24 +230,14 @@ void NodeController::AcceptBrokerClientInvitation(
base::Unretained(this), std::move(connection_params)));
}
-uint64_t NodeController::ConnectToPeer(ConnectionParams connection_params,
- const ports::PortRef& port) {
- uint64_t id = 0;
- {
- base::AutoLock lock(peers_lock_);
- id = next_peer_connection_id_++;
- }
- io_task_runner_->PostTask(FROM_HERE,
- base::Bind(&NodeController::ConnectToPeerOnIOThread,
- base::Unretained(this), id,
- base::Passed(&connection_params), port));
- return id;
-}
-
-void NodeController::ClosePeerConnection(uint64_t peer_connection_id) {
+void NodeController::ConnectIsolated(ConnectionParams connection_params,
+ const ports::PortRef& port,
+ base::StringPiece connection_name) {
io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&NodeController::ClosePeerConnectionOnIOThread,
- base::Unretained(this), peer_connection_id));
+ FROM_HERE,
+ base::BindOnce(&NodeController::ConnectIsolatedOnIOThread,
+ base::Unretained(this), base::Passed(&connection_params),
+ port, connection_name.as_string()));
}
void NodeController::SetPortObserver(const ports::PortRef& port,
@@ -330,32 +326,34 @@ void NodeController::SendBrokerClientInvitationOnIOThread(
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
#if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_FUCHSIA)
- PlatformChannelPair node_channel;
- ScopedInternalPlatformHandle server_handle = node_channel.PassServerHandle();
+ PlatformChannel node_channel;
+ ConnectionParams node_connection_params(node_channel.TakeLocalEndpoint());
// BrokerHost owns itself.
- BrokerHost* broker_host = new BrokerHost(
- target_process.get(), connection_params.TakeChannelHandle(),
- process_error_callback);
- bool channel_ok = broker_host->SendChannel(node_channel.PassClientHandle());
+ BrokerHost* broker_host =
+ new BrokerHost(target_process.get(), std::move(connection_params),
+ process_error_callback);
+ bool channel_ok = broker_host->SendChannel(
+ node_channel.TakeRemoteEndpoint().TakePlatformHandle());
#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);
+ NamedPlatformChannel::Options options;
+ NamedPlatformChannel named_channel(options);
+ node_connection_params =
+ ConnectionParams(named_channel.TakeServerEndpoint());
+ broker_host->SendNamedChannel(named_channel.GetServerName());
}
#else
CHECK(channel_ok);
#endif // defined(OS_WIN)
- scoped_refptr<NodeChannel> channel = NodeChannel::Create(
- this,
- ConnectionParams(connection_params.protocol(), std::move(server_handle)),
- io_task_runner_, process_error_callback);
+ scoped_refptr<NodeChannel> channel =
+ NodeChannel::Create(this, std::move(node_connection_params),
+ io_task_runner_, process_error_callback);
-#else // !defined(OS_MACOSX) && !defined(OS_NACL)
+#else // !defined(OS_MACOSX) && !defined(OS_NACL)
scoped_refptr<NodeChannel> channel =
NodeChannel::Create(this, std::move(connection_params), io_task_runner_,
process_error_callback);
@@ -397,19 +395,38 @@ void NodeController::AcceptBrokerClientInvitationOnIOThread(
bootstrap_inviter_channel_->Start();
}
-void NodeController::ConnectToPeerOnIOThread(uint64_t peer_connection_id,
- ConnectionParams connection_params,
- ports::PortRef port) {
+void NodeController::ConnectIsolatedOnIOThread(
+ ConnectionParams connection_params,
+ ports::PortRef port,
+ const std::string& connection_name) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
scoped_refptr<NodeChannel> channel = NodeChannel::Create(
this, std::move(connection_params), io_task_runner_, {});
+ RequestContext request_context;
ports::NodeName token;
GenerateRandomName(&token);
- peer_connections_.emplace(token,
- PeerConnection{channel, port, peer_connection_id});
- peer_connections_by_id_.emplace(peer_connection_id, token);
+ pending_isolated_connections_.emplace(
+ token, IsolatedConnection{channel, port, connection_name});
+ if (!connection_name.empty()) {
+ // If a connection already exists with this name, drop it.
+ auto it = named_isolated_connections_.find(connection_name);
+ if (it != named_isolated_connections_.end()) {
+ ports::NodeName connection_node = it->second;
+ if (connection_node != name_) {
+ DropPeer(connection_node, nullptr);
+ } else {
+ auto pending_it = pending_isolated_connections_.find(connection_node);
+ if (pending_it != pending_isolated_connections_.end()) {
+ node_->ClosePort(pending_it->second.local_port);
+ pending_isolated_connections_.erase(pending_it);
+ }
+ named_isolated_connections_.erase(it);
+ }
+ }
+ named_isolated_connections_.emplace(connection_name, token);
+ }
channel->SetRemoteNodeName(token);
channel->Start();
@@ -417,19 +434,6 @@ void NodeController::ConnectToPeerOnIOThread(uint64_t peer_connection_id,
channel->AcceptPeer(name_, token, port.name());
}
-void NodeController::ClosePeerConnectionOnIOThread(
- uint64_t peer_connection_id) {
- RequestContext request_context(RequestContext::Source::SYSTEM);
- auto peer = peer_connections_by_id_.find(peer_connection_id);
- // The connection may already be closed.
- if (peer == peer_connections_by_id_.end())
- return;
-
- // |peer| may be removed so make a copy of |name|.
- ports::NodeName name = peer->second;
- DropPeer(name, nullptr);
-}
-
scoped_refptr<NodeChannel> NodeController::GetPeerChannel(
const ports::NodeName& name) {
base::AutoLock lock(peers_lock_);
@@ -536,8 +540,8 @@ void NodeController::DropPeer(const ports::NodeName& name,
bool is_inviter;
{
base::AutoLock lock(inviter_lock_);
- is_inviter =
- (name == inviter_name_ || channel == bootstrap_inviter_channel_);
+ is_inviter = (name == inviter_name_ ||
+ (channel && channel == bootstrap_inviter_channel_));
}
// If the error comes from the inviter channel, we also need to cancel any
@@ -546,11 +550,13 @@ void NodeController::DropPeer(const ports::NodeName& name,
if (is_inviter)
CancelPendingPortMerges();
- auto peer = peer_connections_.find(name);
- if (peer != peer_connections_.end()) {
- peer_connections_by_id_.erase(peer->second.connection_id);
- ports_to_close.push_back(peer->second.local_port);
- peer_connections_.erase(peer);
+ auto connection_it = pending_isolated_connections_.find(name);
+ if (connection_it != pending_isolated_connections_.end()) {
+ IsolatedConnection& connection = connection_it->second;
+ ports_to_close.push_back(connection.local_port);
+ if (!connection.name.empty())
+ named_isolated_connections_.erase(connection.name);
+ pending_isolated_connections_.erase(connection_it);
}
for (const auto& port : ports_to_close)
@@ -668,7 +674,8 @@ void NodeController::DropAllPeers() {
peers_.clear();
pending_invitations_.clear();
pending_peer_messages_.clear();
- peer_connections_.clear();
+ pending_isolated_connections_.clear();
+ named_isolated_connections_.clear();
}
for (const auto& peer : all_peers)
@@ -799,7 +806,7 @@ void NodeController::OnAcceptInvitation(const ports::NodeName& from_node,
if (!inviter) {
// Yes, we're the broker. We can initialize the client directly.
- channel->AcceptBrokerClient(name_, ScopedInternalPlatformHandle());
+ channel->AcceptBrokerClient(name_, PlatformHandle());
} else {
// We aren't the broker, so wait for a broker connection.
base::AutoLock lock(broker_lock_);
@@ -825,9 +832,8 @@ void NodeController::OnAddBrokerClient(const ports::NodeName& from_node,
return;
}
- PlatformChannelPair broker_channel;
- ConnectionParams connection_params(TransportProtocol::kLegacy,
- broker_channel.PassServerHandle());
+ PlatformChannel broker_channel;
+ ConnectionParams connection_params(broker_channel.TakeLocalEndpoint());
scoped_refptr<NodeChannel> client =
NodeChannel::Create(this, std::move(connection_params), io_task_runner_,
ProcessErrorCallback());
@@ -847,13 +853,13 @@ void NodeController::OnAddBrokerClient(const ports::NodeName& from_node,
DVLOG(1) << "Broker " << name_ << " accepting client " << client_name
<< " from peer " << from_node;
- sender->BrokerClientAdded(client_name, broker_channel.PassClientHandle());
+ sender->BrokerClientAdded(
+ client_name, broker_channel.TakeRemoteEndpoint().TakePlatformHandle());
}
-void NodeController::OnBrokerClientAdded(
- const ports::NodeName& from_node,
- const ports::NodeName& client_name,
- ScopedInternalPlatformHandle broker_channel) {
+void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node,
+ const ports::NodeName& client_name,
+ PlatformHandle broker_channel) {
scoped_refptr<NodeChannel> client = GetPeerChannel(client_name);
if (!client) {
DLOG(ERROR) << "BrokerClientAdded for unknown client " << client_name;
@@ -871,10 +877,9 @@ void NodeController::OnBrokerClientAdded(
client->AcceptBrokerClient(from_node, std::move(broker_channel));
}
-void NodeController::OnAcceptBrokerClient(
- const ports::NodeName& from_node,
- const ports::NodeName& broker_name,
- ScopedInternalPlatformHandle broker_channel) {
+void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node,
+ const ports::NodeName& broker_name,
+ PlatformHandle broker_channel) {
DCHECK(!GetConfiguration().is_broker_process);
// This node should already have an inviter in bootstrap mode.
@@ -910,7 +915,7 @@ void NodeController::OnAcceptBrokerClient(
DCHECK(broker_channel.is_valid());
broker = NodeChannel::Create(
this,
- ConnectionParams(TransportProtocol::kLegacy, std::move(broker_channel)),
+ ConnectionParams(PlatformChannelEndpoint(std::move(broker_channel))),
io_task_runner_, ProcessErrorCallback());
AddPeer(broker_name, broker, true /* start_channel */);
}
@@ -1028,17 +1033,19 @@ void NodeController::OnRequestIntroduction(const ports::NodeName& from_node,
scoped_refptr<NodeChannel> new_friend = GetPeerChannel(name);
if (!new_friend) {
// We don't know who they're talking about!
- requestor->Introduce(name, ScopedInternalPlatformHandle());
+ requestor->Introduce(name, PlatformHandle());
} else {
- PlatformChannelPair new_channel;
- requestor->Introduce(name, new_channel.PassServerHandle());
- new_friend->Introduce(from_node, new_channel.PassClientHandle());
+ PlatformChannel new_channel;
+ requestor->Introduce(name,
+ new_channel.TakeLocalEndpoint().TakePlatformHandle());
+ new_friend->Introduce(
+ from_node, new_channel.TakeRemoteEndpoint().TakePlatformHandle());
}
}
void NodeController::OnIntroduce(const ports::NodeName& from_node,
const ports::NodeName& name,
- ScopedInternalPlatformHandle channel_handle) {
+ PlatformHandle channel_handle) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (!channel_handle.is_valid()) {
@@ -1052,7 +1059,7 @@ void NodeController::OnIntroduce(const ports::NodeName& from_node,
scoped_refptr<NodeChannel> channel = NodeChannel::Create(
this,
- ConnectionParams(TransportProtocol::kLegacy, std::move(channel_handle)),
+ ConnectionParams(PlatformChannelEndpoint(std::move(channel_handle))),
io_task_runner_, ProcessErrorCallback());
DVLOG(1) << "Adding new peer " << name << " via broker introduction.";
@@ -1093,6 +1100,8 @@ void NodeController::OnRelayEventMessage(const ports::NodeName& from_node,
base::ProcessHandle from_process,
const ports::NodeName& destination,
Channel::MessagePtr message) {
+ // The broker should always know which process this came from.
+ DCHECK(from_process != base::kNullProcessHandle);
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (GetBrokerChannel()) {
@@ -1102,45 +1111,6 @@ void NodeController::OnRelayEventMessage(const ports::NodeName& from_node,
return;
}
- // The broker should always know which process this came from.
- DCHECK(from_process != base::kNullProcessHandle);
-
-#if defined(OS_WIN)
- // Rewrite the handles to this (the broker) process. If the message is
- // destined for another client process, the handles will be rewritten to that
- // process before going out (see NodeChannel::WriteChannelMessage).
- //
- // TODO: We could avoid double-duplication.
- //
- // Note that we explicitly mark the handles as being owned by the sending
- // process before rewriting them, in order to accommodate RewriteHandles'
- // internal sanity checks.
- std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
- for (auto& handle : handles)
- handle.get().owning_process = from_process;
- if (!Channel::Message::RewriteHandles(
- from_process, base::GetCurrentProcessHandle(), &handles)) {
- DLOG(ERROR) << "Failed to relay one or more handles.";
- }
- message->SetHandles(std::move(handles));
-#else
- std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
- for (auto& handle : handles) {
- if (handle.get().type == InternalPlatformHandle::Type::MACH_NAME) {
- MachPortRelay* relay = GetMachPortRelay();
- if (!relay) {
- handle.get().type = InternalPlatformHandle::Type::MACH;
- handle.get().port = MACH_PORT_NULL;
- DLOG(ERROR) << "Receiving Mach ports without a port relay from "
- << from_node << ".";
- continue;
- }
- relay->ExtractPort(&handle, from_process);
- }
- }
- message->SetHandles(std::move(handles));
-#endif // defined(OS_WIN)
-
if (destination == name_) {
// Great, we can deliver this message locally.
OnEventMessage(from_node, std::move(message));
@@ -1173,30 +1143,29 @@ void NodeController::OnAcceptPeer(const ports::NodeName& from_node,
const ports::PortName& port_name) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
- auto it = peer_connections_.find(from_node);
- if (it == peer_connections_.end()) {
+ auto it = pending_isolated_connections_.find(from_node);
+ if (it == pending_isolated_connections_.end()) {
DLOG(ERROR) << "Received unexpected AcceptPeer message from " << from_node;
DropPeer(from_node, nullptr);
return;
}
- scoped_refptr<NodeChannel> channel = std::move(it->second.channel);
- ports::PortRef local_port = it->second.local_port;
- uint64_t peer_connection_id = it->second.connection_id;
- peer_connections_.erase(it);
+ IsolatedConnection& connection = it->second;
+ scoped_refptr<NodeChannel> channel = std::move(connection.channel);
+ ports::PortRef local_port = connection.local_port;
+ if (!connection.name.empty())
+ named_isolated_connections_[connection.name] = peer_name;
+ pending_isolated_connections_.erase(it);
DCHECK(channel);
- if (name_ == peer_name) {
- // 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.
- peer_connections_by_id_.erase(peer_connection_id);
- } else {
- peer_connections_by_id_[peer_connection_id] = peer_name;
- peer_connections_.emplace(
- peer_name, PeerConnection{nullptr, local_port, peer_connection_id});
- DVLOG(1) << "Node " << name_ << " accepted peer " << peer_name;
-
+ if (name_ != peer_name) {
+ // It's possible (e.g. in tests) that we may "connect" to ourself, in which
+ // case we skip this |AddPeer()| call and go straight to merging ports.
+ // Note that we explicitly drop any prior connection to the same peer so
+ // that new isolated connections can replace old ones.
+ DropPeer(peer_name, nullptr);
AddPeer(peer_name, channel, false /* start_channel */);
+ DVLOG(1) << "Node " << name_ << " accepted peer " << peer_name;
}
// We need to choose one side to initiate the port merge. It doesn't matter
@@ -1262,7 +1231,7 @@ void NodeController::AttemptShutdownIfRequested() {
if (shutdown_callback_.is_null())
return;
if (!node_->CanShutdownCleanly(
- ports::Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)) {
+ ports::Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)) {
DVLOG(2) << "Unable to cleanly shut down node " << name_;
return;
}
@@ -1277,29 +1246,27 @@ void NodeController::AttemptShutdownIfRequested() {
callback.Run();
}
-NodeController::PeerConnection::PeerConnection() = default;
+NodeController::IsolatedConnection::IsolatedConnection() = default;
-NodeController::PeerConnection::PeerConnection(
- const PeerConnection& other) = default;
+NodeController::IsolatedConnection::IsolatedConnection(
+ const IsolatedConnection& other) = default;
-NodeController::PeerConnection::PeerConnection(
- PeerConnection&& other) = default;
+NodeController::IsolatedConnection::IsolatedConnection(
+ IsolatedConnection&& other) = default;
-NodeController::PeerConnection::PeerConnection(
+NodeController::IsolatedConnection::IsolatedConnection(
scoped_refptr<NodeChannel> channel,
const ports::PortRef& local_port,
- uint64_t connection_id)
- : channel(std::move(channel)),
- local_port(local_port),
- connection_id(connection_id) {}
+ base::StringPiece name)
+ : channel(std::move(channel)), local_port(local_port), name(name) {}
-NodeController::PeerConnection::~PeerConnection() = default;
+NodeController::IsolatedConnection::~IsolatedConnection() = default;
-NodeController::PeerConnection& NodeController::PeerConnection::
-operator=(const PeerConnection& other) = default;
+NodeController::IsolatedConnection& NodeController::IsolatedConnection::
+operator=(const IsolatedConnection& other) = default;
-NodeController::PeerConnection& NodeController::PeerConnection::
-operator=(PeerConnection&& other) = default;
+NodeController::IsolatedConnection& NodeController::IsolatedConnection::
+operator=(IsolatedConnection&& other) = default;
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/node_controller.h b/chromium/mojo/core/node_controller.h
index e6ccd428aa8..fac39df9e42 100644
--- a/chromium/mojo/edk/system/node_controller.h
+++ b/chromium/mojo/core/node_controller.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_NODE_CONTROLLER_H_
-#define MOJO_EDK_SYSTEM_NODE_CONTROLLER_H_
+#ifndef MOJO_CORE_NODE_CONTROLLER_H_
+#define MOJO_CORE_NODE_CONTROLLER_H_
#include <map>
#include <memory>
@@ -21,22 +21,22 @@
#include "base/memory/writable_shared_memory_region.h"
#include "base/task_runner.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/atomic_flag.h"
-#include "mojo/edk/system/node_channel.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/name.h"
-#include "mojo/edk/system/ports/node.h"
-#include "mojo/edk/system/ports/node_delegate.h"
-#include "mojo/edk/system/scoped_process_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/atomic_flag.h"
+#include "mojo/core/node_channel.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/name.h"
+#include "mojo/core/ports/node.h"
+#include "mojo/core/ports/node_delegate.h"
+#include "mojo/core/scoped_process_handle.h"
+#include "mojo/core/system_impl_export.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
namespace base {
class PortProvider;
}
namespace mojo {
-namespace edk {
+namespace core {
class Broker;
class Core;
@@ -87,13 +87,10 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
void AcceptBrokerClientInvitation(ConnectionParams connection_params);
// Connects this node to a peer node. On success, |port| will be merged with
- // the corresponding port in the peer node. Returns an ID that can be used to
- // later close the connection with a call to ClosePeerConnection().
- uint64_t ConnectToPeer(ConnectionParams connection_params,
- const ports::PortRef& port);
-
- // Close a connection to a peer associated with |peer_connection_id|.
- void ClosePeerConnection(uint64_t peer_connection_id);
+ // the corresponding port in the peer node.
+ void ConnectIsolated(ConnectionParams connection_params,
+ const ports::PortRef& port,
+ base::StringPiece connection_name);
// Sets a port's observer. If |observer| is null the port's current observer
// is removed.
@@ -136,27 +133,27 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
private:
friend Core;
- using NodeMap = std::unordered_map<ports::NodeName,
- scoped_refptr<NodeChannel>>;
+ using NodeMap =
+ std::unordered_map<ports::NodeName, scoped_refptr<NodeChannel>>;
using OutgoingMessageQueue = base::queue<Channel::MessagePtr>;
using PortMap = std::map<std::string, ports::PortRef>;
- struct PeerConnection {
- PeerConnection();
- PeerConnection(const PeerConnection& other);
- PeerConnection(PeerConnection&& other);
- PeerConnection(scoped_refptr<NodeChannel> channel,
- const ports::PortRef& local_port,
- uint64_t connection_id);
- ~PeerConnection();
+ struct IsolatedConnection {
+ IsolatedConnection();
+ IsolatedConnection(const IsolatedConnection& other);
+ IsolatedConnection(IsolatedConnection&& other);
+ IsolatedConnection(scoped_refptr<NodeChannel> channel,
+ const ports::PortRef& local_port,
+ base::StringPiece name);
+ ~IsolatedConnection();
- PeerConnection& operator=(const PeerConnection& other);
- PeerConnection& operator=(PeerConnection&& other);
+ IsolatedConnection& operator=(const IsolatedConnection& other);
+ IsolatedConnection& operator=(IsolatedConnection&& other);
// NOTE: |channel| is null once the connection is fully established.
scoped_refptr<NodeChannel> channel;
ports::PortRef local_port;
- uint64_t connection_id;
+ std::string name;
};
void SendBrokerClientInvitationOnIOThread(
@@ -167,10 +164,9 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
void AcceptBrokerClientInvitationOnIOThread(
ConnectionParams connection_params);
- void ConnectToPeerOnIOThread(uint64_t peer_connection_id,
- ConnectionParams connection_params,
- ports::PortRef port);
- void ClosePeerConnectionOnIOThread(uint64_t peer_connection_id);
+ void ConnectIsolatedOnIOThread(ConnectionParams connection_params,
+ ports::PortRef port,
+ const std::string& connection_name);
scoped_refptr<NodeChannel> GetPeerChannel(const ports::NodeName& name);
scoped_refptr<NodeChannel> GetInviterChannel();
@@ -199,14 +195,12 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
void OnAddBrokerClient(const ports::NodeName& from_node,
const ports::NodeName& client_name,
base::ProcessHandle process_handle) override;
- void OnBrokerClientAdded(
- const ports::NodeName& from_node,
- const ports::NodeName& client_name,
- ScopedInternalPlatformHandle broker_channel) override;
- void OnAcceptBrokerClient(
- const ports::NodeName& from_node,
- const ports::NodeName& broker_name,
- ScopedInternalPlatformHandle broker_channel) override;
+ void OnBrokerClientAdded(const ports::NodeName& from_node,
+ const ports::NodeName& client_name,
+ PlatformHandle broker_channel) override;
+ void OnAcceptBrokerClient(const ports::NodeName& from_node,
+ const ports::NodeName& broker_name,
+ PlatformHandle broker_channel) override;
void OnEventMessage(const ports::NodeName& from_node,
Channel::MessagePtr message) override;
void OnRequestPortMerge(const ports::NodeName& from_node,
@@ -216,7 +210,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
const ports::NodeName& name) override;
void OnIntroduce(const ports::NodeName& from_node,
const ports::NodeName& name,
- ScopedInternalPlatformHandle channel_handle) override;
+ PlatformHandle channel_handle) override;
void OnBroadcast(const ports::NodeName& from_node,
Channel::MessagePtr message) override;
#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
@@ -234,8 +228,9 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
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;
+ MachPortRelay* GetMachPortRelay();
#endif
// Cancels all pending port merges. These are merges which are supposed to
@@ -259,15 +254,12 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
const std::unique_ptr<ports::Node> node_;
scoped_refptr<base::TaskRunner> io_task_runner_;
- // Guards |peers_|, |pending_peer_messages_|, and |next_peer_connection_id_|.
+ // Guards |peers_| and |pending_peer_messages_|.
base::Lock peers_lock_;
// Channels to known peers, including inviter and invitees, if any.
NodeMap peers_;
- // A unique ID generator for peer connections.
- uint64_t next_peer_connection_id_ = 1;
-
// Outgoing message queues for peers we've heard of but can't yet talk to.
std::unordered_map<ports::NodeName, OutgoingMessageQueue>
pending_peer_messages_;
@@ -327,10 +319,8 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
// Channels to invitees during handshake.
NodeMap pending_invitations_;
- std::map<ports::NodeName, PeerConnection> peer_connections_;
-
- // Maps from peer token to node name, pending or not.
- std::unordered_map<uint64_t, ports::NodeName> peer_connections_by_id_;
+ std::map<ports::NodeName, IsolatedConnection> pending_isolated_connections_;
+ std::map<std::string, ports::NodeName> named_isolated_connections_;
// Indicates whether this object should delete itself on IO thread shutdown.
// Must only be accessed from the IO thread.
@@ -350,7 +340,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
DISALLOW_COPY_AND_ASSIGN(NodeController);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_NODE_CONTROLLER_H_
+#endif // MOJO_CORE_NODE_CONTROLLER_H_
diff --git a/chromium/mojo/edk/system/options_validation.h b/chromium/mojo/core/options_validation.h
index e1b337d5f74..ae4120800ae 100644
--- a/chromium/mojo/edk/system/options_validation.h
+++ b/chromium/mojo/core/options_validation.h
@@ -8,8 +8,8 @@
// but any |flags| specified must be known to the system (otherwise, an error of
// |MOJO_RESULT_UNIMPLEMENTED| should be returned).
-#ifndef MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_
-#define MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_
+#ifndef MOJO_CORE_OPTIONS_VALIDATION_H_
+#define MOJO_CORE_OPTIONS_VALIDATION_H_
#include <stddef.h>
#include <stdint.h>
@@ -18,11 +18,11 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/types.h"
namespace mojo {
-namespace edk {
+namespace core {
template <class Options>
class UserOptionsReader {
@@ -91,7 +91,7 @@ class UserOptionsReader {
#define OPTIONS_STRUCT_HAS_MEMBER(Options, member, reader) \
reader.HasMember(offsetof(Options, member), sizeof(reader.options().member))
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_
+#endif // MOJO_CORE_OPTIONS_VALIDATION_H_
diff --git a/chromium/mojo/edk/system/options_validation_unittest.cc b/chromium/mojo/core/options_validation_unittest.cc
index a01a92cfb10..52e0032a898 100644
--- a/chromium/mojo/edk/system/options_validation_unittest.cc
+++ b/chromium/mojo/core/options_validation_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/options_validation.h"
+#include "mojo/core/options_validation.h"
#include <stddef.h>
#include <stdint.h>
@@ -11,7 +11,7 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
// Declare a test options struct just as we do in actual public headers.
@@ -130,5 +130,5 @@ TEST(OptionsValidationTest, InvalidDeath) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/platform_handle_dispatcher.cc b/chromium/mojo/core/platform_handle_dispatcher.cc
index 19b1ed3fb19..7029b965369 100644
--- a/chromium/mojo/edk/system/platform_handle_dispatcher.cc
+++ b/chromium/mojo/core/platform_handle_dispatcher.cc
@@ -2,22 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/platform_handle_dispatcher.h"
+#include "mojo/core/platform_handle_dispatcher.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
// static
scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Create(
- ScopedInternalPlatformHandle platform_handle) {
+ PlatformHandle platform_handle) {
return new PlatformHandleDispatcher(std::move(platform_handle));
}
-ScopedInternalPlatformHandle
-PlatformHandleDispatcher::PassInternalPlatformHandle() {
+PlatformHandle PlatformHandleDispatcher::TakePlatformHandle() {
return std::move(platform_handle_);
}
@@ -42,14 +40,13 @@ void PlatformHandleDispatcher::StartSerialize(uint32_t* num_bytes,
*num_handles = 1;
}
-bool PlatformHandleDispatcher::EndSerialize(
- void* destination,
- ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) {
+bool PlatformHandleDispatcher::EndSerialize(void* destination,
+ ports::PortName* ports,
+ PlatformHandle* handles) {
base::AutoLock lock(lock_);
if (is_closed_)
return false;
- handles[0] = ScopedInternalPlatformHandle(platform_handle_.get());
+ handles[0] = std::move(platform_handle_);
return true;
}
@@ -63,12 +60,8 @@ bool PlatformHandleDispatcher::BeginTransit() {
void PlatformHandleDispatcher::CompleteTransitAndClose() {
base::AutoLock lock(lock_);
-
in_transit_ = false;
is_closed_ = true;
-
- // The system has taken ownership of our handle.
- ignore_result(platform_handle_.release());
}
void PlatformHandleDispatcher::CancelTransit() {
@@ -82,7 +75,7 @@ scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* handles,
+ PlatformHandle* handles,
size_t num_handles) {
if (num_bytes || num_ports || num_handles != 1)
return nullptr;
@@ -91,7 +84,7 @@ scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize(
}
PlatformHandleDispatcher::PlatformHandleDispatcher(
- ScopedInternalPlatformHandle platform_handle)
+ PlatformHandle platform_handle)
: platform_handle_(std::move(platform_handle)) {}
PlatformHandleDispatcher::~PlatformHandleDispatcher() {
@@ -99,5 +92,5 @@ PlatformHandleDispatcher::~PlatformHandleDispatcher() {
DCHECK(!platform_handle_.is_valid());
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/platform_handle_dispatcher.h b/chromium/mojo/core/platform_handle_dispatcher.h
index 8a377e47fa7..8d9627c393e 100644
--- a/chromium/mojo/edk/system/platform_handle_dispatcher.h
+++ b/chromium/mojo/core/platform_handle_dispatcher.h
@@ -2,25 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_
+#ifndef MOJO_CORE_PLATFORM_HANDLE_DISPATCHER_H_
+#define MOJO_CORE_PLATFORM_HANDLE_DISPATCHER_H_
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/system_impl_export.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher {
public:
static scoped_refptr<PlatformHandleDispatcher> Create(
- ScopedInternalPlatformHandle platform_handle);
+ PlatformHandle platform_handle);
- ScopedInternalPlatformHandle PassInternalPlatformHandle();
+ PlatformHandle TakePlatformHandle();
// Dispatcher:
Type GetType() const override;
@@ -30,7 +30,7 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher {
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) override;
+ PlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
@@ -40,22 +40,22 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher {
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* handles,
+ PlatformHandle* handles,
size_t num_handles);
private:
- PlatformHandleDispatcher(ScopedInternalPlatformHandle platform_handle);
+ PlatformHandleDispatcher(PlatformHandle platform_handle);
~PlatformHandleDispatcher() override;
base::Lock lock_;
bool in_transit_ = false;
bool is_closed_ = false;
- ScopedInternalPlatformHandle platform_handle_;
+ PlatformHandle platform_handle_;
DISALLOW_COPY_AND_ASSIGN(PlatformHandleDispatcher);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_
+#endif // MOJO_CORE_PLATFORM_HANDLE_DISPATCHER_H_
diff --git a/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/chromium/mojo/core/platform_handle_dispatcher_unittest.cc
index 0313b8fdccf..8e3ad81f3d8 100644
--- a/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc
+++ b/chromium/mojo/core/platform_handle_dispatcher_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/platform_handle_dispatcher.h"
+#include "mojo/core/platform_handle_dispatcher.h"
#include <stdio.h>
#include <utility>
@@ -12,12 +12,12 @@
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/test/test_utils.h"
+#include "mojo/core/test/test_utils.h"
+#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
TEST(PlatformHandleDispatcherTest, Basic) {
@@ -33,8 +33,7 @@ TEST(PlatformHandleDispatcherTest, Basic) {
EXPECT_EQ(sizeof(kHelloWorld),
fwrite(kHelloWorld, 1, sizeof(kHelloWorld), fp.get()));
- ScopedInternalPlatformHandle h(
- test::InternalPlatformHandleFromFILE(std::move(fp)));
+ PlatformHandle h = test::PlatformHandleFromFILE(std::move(fp));
EXPECT_FALSE(fp);
ASSERT_TRUE(h.is_valid());
@@ -43,10 +42,10 @@ TEST(PlatformHandleDispatcherTest, Basic) {
EXPECT_FALSE(h.is_valid());
EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, dispatcher->GetType());
- h = dispatcher->PassInternalPlatformHandle();
+ h = dispatcher->TakePlatformHandle();
EXPECT_TRUE(h.is_valid());
- fp = test::FILEFromInternalPlatformHandle(std::move(h), "rb");
+ fp = test::FILEFromPlatformHandle(std::move(h), "rb");
EXPECT_FALSE(h.is_valid());
EXPECT_TRUE(fp);
@@ -57,8 +56,8 @@ TEST(PlatformHandleDispatcherTest, Basic) {
EXPECT_STREQ(kHelloWorld, read_buffer);
// Try getting the handle again. (It should fail cleanly.)
- h = dispatcher->PassInternalPlatformHandle();
- EXPECT_FALSE(h.is_valid());
+ auto internal_handle = dispatcher->TakePlatformHandle();
+ EXPECT_FALSE(internal_handle.is_valid());
EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
}
@@ -76,7 +75,7 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
scoped_refptr<PlatformHandleDispatcher> dispatcher =
PlatformHandleDispatcher::Create(
- test::InternalPlatformHandleFromFILE(std::move(fp)));
+ test::PlatformHandleFromFILE(std::move(fp)));
uint32_t num_bytes = 0;
uint32_t num_ports = 0;
@@ -88,15 +87,14 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
EXPECT_EQ(0u, num_ports);
EXPECT_EQ(1u, num_handles);
- ScopedInternalPlatformHandle received_handle;
+ PlatformHandle received_handle;
EXPECT_TRUE(dispatcher->EndSerialize(nullptr, nullptr, &received_handle));
dispatcher->CompleteTransitAndClose();
EXPECT_TRUE(received_handle.is_valid());
- ScopedInternalPlatformHandle handle =
- dispatcher->PassInternalPlatformHandle();
+ PlatformHandle handle = dispatcher->TakePlatformHandle();
EXPECT_FALSE(handle.is_valid());
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher->Close());
@@ -110,8 +108,7 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
EXPECT_FALSE(received_handle.is_valid());
EXPECT_TRUE(dispatcher->GetType() == Dispatcher::Type::PLATFORM_HANDLE);
- fp = test::FILEFromInternalPlatformHandle(
- dispatcher->PassInternalPlatformHandle(), "rb");
+ fp = test::FILEFromPlatformHandle(dispatcher->TakePlatformHandle(), "rb");
EXPECT_TRUE(fp);
rewind(fp.get());
@@ -124,5 +121,5 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/core/platform_handle_in_transit.cc b/chromium/mojo/core/platform_handle_in_transit.cc
new file mode 100644
index 00000000000..7b82f27c34b
--- /dev/null
+++ b/chromium/mojo/core/platform_handle_in_transit.cc
@@ -0,0 +1,156 @@
+// Copyright 2018 The Chromium 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/core/platform_handle_in_transit.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/process/process_handle.h"
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+
+#include "base/win/scoped_handle.h"
+#endif
+
+namespace mojo {
+namespace core {
+
+namespace {
+
+#if defined(OS_WIN)
+HANDLE TransferHandle(HANDLE handle,
+ base::ProcessHandle from_process,
+ base::ProcessHandle to_process) {
+ BOOL result =
+ ::DuplicateHandle(from_process, handle, to_process, &handle, 0, FALSE,
+ DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+ if (result) {
+ return handle;
+ } else {
+ DPLOG(ERROR) << "DuplicateHandle failed";
+ return INVALID_HANDLE_VALUE;
+ }
+}
+
+void CloseHandleInProcess(HANDLE handle, const ScopedProcessHandle& process) {
+ DCHECK_NE(handle, INVALID_HANDLE_VALUE);
+ DCHECK(process.is_valid());
+
+ // The handle lives in |process|, so we close it there using a special
+ // incantation of |DuplicateHandle()|.
+ //
+ // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251 for
+ // this usage of |DuplicateHandle()|, particularly where it says "to close a
+ // handle from the source process...". Note that although the documentation
+ // says that the target *handle* address must be NULL, it seems that the
+ // target process handle being NULL is what really matters here.
+ BOOL result = ::DuplicateHandle(process.get(), handle, NULL, &handle, 0,
+ FALSE, DUPLICATE_CLOSE_SOURCE);
+ if (!result) {
+ DPLOG(ERROR) << "DuplicateHandle failed";
+ }
+}
+#endif
+
+} // namespace
+
+PlatformHandleInTransit::PlatformHandleInTransit() = default;
+
+PlatformHandleInTransit::PlatformHandleInTransit(PlatformHandle handle)
+ : handle_(std::move(handle)) {}
+
+PlatformHandleInTransit::PlatformHandleInTransit(
+ PlatformHandleInTransit&& other) {
+ *this = std::move(other);
+}
+
+PlatformHandleInTransit::~PlatformHandleInTransit() {
+#if defined(OS_WIN)
+ if (!owning_process_.is_valid()) {
+ DCHECK_EQ(remote_handle_, INVALID_HANDLE_VALUE);
+ return;
+ }
+
+ CloseHandleInProcess(remote_handle_, owning_process_);
+#endif
+}
+
+PlatformHandleInTransit& PlatformHandleInTransit::operator=(
+ PlatformHandleInTransit&& other) {
+#if defined(OS_WIN)
+ if (owning_process_.is_valid()) {
+ DCHECK_NE(remote_handle_, INVALID_HANDLE_VALUE);
+ CloseHandleInProcess(remote_handle_, owning_process_);
+ }
+
+ remote_handle_ = INVALID_HANDLE_VALUE;
+ std::swap(remote_handle_, other.remote_handle_);
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ mach_port_name_ = MACH_PORT_NULL;
+ std::swap(mach_port_name_, other.mach_port_name_);
+#endif
+ handle_ = std::move(other.handle_);
+ owning_process_ = std::move(other.owning_process_);
+ return *this;
+}
+
+PlatformHandle PlatformHandleInTransit::TakeHandle() {
+ DCHECK(!owning_process_.is_valid());
+ return std::move(handle_);
+}
+
+void PlatformHandleInTransit::CompleteTransit() {
+#if defined(OS_WIN)
+ remote_handle_ = INVALID_HANDLE_VALUE;
+#endif
+ handle_.release();
+ owning_process_ = ScopedProcessHandle();
+}
+
+bool PlatformHandleInTransit::TransferToProcess(
+ ScopedProcessHandle target_process) {
+ DCHECK(target_process.is_valid());
+ DCHECK(!owning_process_.is_valid());
+ DCHECK(handle_.is_valid());
+#if defined(OS_WIN)
+ remote_handle_ =
+ TransferHandle(handle_.ReleaseHandle(), base::GetCurrentProcessHandle(),
+ target_process.get());
+ if (remote_handle_ == INVALID_HANDLE_VALUE)
+ return false;
+#endif
+ owning_process_ = std::move(target_process);
+ return true;
+}
+
+#if defined(OS_WIN)
+// static
+PlatformHandle PlatformHandleInTransit::TakeIncomingRemoteHandle(
+ HANDLE handle,
+ base::ProcessHandle owning_process) {
+ return PlatformHandle(base::win::ScopedHandle(
+ TransferHandle(handle, owning_process, base::GetCurrentProcessHandle())));
+}
+#endif
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+// static
+PlatformHandleInTransit PlatformHandleInTransit::CreateForMachPortName(
+ mach_port_t name) {
+ if (name == MACH_PORT_NULL) {
+ return PlatformHandleInTransit(
+ PlatformHandle(base::mac::ScopedMachSendRight()));
+ }
+
+ PlatformHandleInTransit handle;
+ handle.mach_port_name_ = name;
+ return handle;
+}
+#endif
+
+} // namespace core
+} // namespace mojo
diff --git a/chromium/mojo/core/platform_handle_in_transit.h b/chromium/mojo/core/platform_handle_in_transit.h
new file mode 100644
index 00000000000..b75a01fbb01
--- /dev/null
+++ b/chromium/mojo/core/platform_handle_in_transit.h
@@ -0,0 +1,107 @@
+// Copyright 2018 The Chromium 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_CORE_PLATFORM_HANDLE_IN_TRANSIT_H_
+#define MOJO_CORE_PLATFORM_HANDLE_IN_TRANSIT_H_
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "mojo/core/scoped_process_handle.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include <mach/mach.h>
+#endif
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+namespace mojo {
+namespace core {
+
+// Owns a PlatformHandle which may actually belong to another process. On
+// Windows and (sometimes) Mac, handles in a message object may take on values
+// which only have meaning in the context of a remote process.
+//
+// This class provides a safe way of scoping the lifetime of such handles so
+// that they don't leak when transmission can't be completed.
+class PlatformHandleInTransit {
+ public:
+ PlatformHandleInTransit();
+ explicit PlatformHandleInTransit(PlatformHandle handle);
+ PlatformHandleInTransit(PlatformHandleInTransit&&);
+ ~PlatformHandleInTransit();
+
+ PlatformHandleInTransit& operator=(PlatformHandleInTransit&&);
+
+ // Accessor for the owned handle. Must be owned by the calling process.
+ const PlatformHandle& handle() const {
+ DCHECK(!owning_process_.is_valid());
+ return handle_;
+ }
+
+ // Returns the process which owns this handle. If this is invalid, the handle
+ // is owned by the current process.
+ const ScopedProcessHandle& owning_process() const { return owning_process_; }
+
+ // Takes ownership of the held handle as-is. The handle must belong to the
+ // current process.
+ PlatformHandle TakeHandle();
+
+ // Discards the handle owned by this object. The implication is that its
+ // value has been successfully communicated to the owning process and the
+ // calling process is no longer responsible for managing the handle's
+ // lifetime.
+ void CompleteTransit();
+
+ // Transfers ownership of this (local) handle to |target_process|.
+ bool TransferToProcess(ScopedProcessHandle target_process);
+
+#if defined(OS_WIN)
+ HANDLE remote_handle() const { return remote_handle_; }
+
+ // Returns a new local handle, with ownership of |handle| being transferred
+ // from |owning_process| to the caller.
+ static PlatformHandle TakeIncomingRemoteHandle(
+ HANDLE handle,
+ base::ProcessHandle owning_process);
+#endif
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ // Creates a special wrapper holding an unowned Mach port name. This may refer
+ // to a send or receive right in a remote task (process), and is used for
+ // cases where message must retain such an object as one of its attached
+ // handles. We're OK for now with leaking in any scenario where a lack of
+ // strict ownership could cause leakage. See https://crbug.com/855930 for more
+ // details.
+ static PlatformHandleInTransit CreateForMachPortName(mach_port_t name);
+
+ bool is_mach_port_name() const { return mach_port_name_ != MACH_PORT_NULL; }
+ mach_port_t mach_port_name() const { return mach_port_name_; }
+#endif
+
+ private:
+#if defined(OS_WIN)
+ // We don't use a ScopedHandle (or, by extension, PlatformHandle) here because
+ // the handle verifier expects all handle values to be owned by this process.
+ // On Windows we use |handle_| for locally owned handles and |remote_handle_|
+ // otherwise. On all other platforms we use |handle_| regardless of ownership.
+ HANDLE remote_handle_ = INVALID_HANDLE_VALUE;
+#endif
+
+ PlatformHandle handle_;
+ ScopedProcessHandle owning_process_;
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ mach_port_t mach_port_name_ = MACH_PORT_NULL;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformHandleInTransit);
+};
+
+} // namespace core
+} // namespace mojo
+
+#endif // MOJO_CORE_PLATFORM_HANDLE_IN_TRANSIT_H_
diff --git a/chromium/mojo/core/platform_handle_utils.cc b/chromium/mojo/core/platform_handle_utils.cc
new file mode 100644
index 00000000000..edd0cff0639
--- /dev/null
+++ b/chromium/mojo/core/platform_handle_utils.cc
@@ -0,0 +1,67 @@
+// Copyright 2018 The Chromium 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/core/platform_handle_utils.h"
+
+#include "build/build_config.h"
+
+#if defined(OS_FUCHSIA)
+#include <lib/zx/vmo.h>
+#elif defined(OS_POSIX)
+#include "base/files/scoped_file.h"
+#elif defined(OS_WIN)
+#include "base/win/scoped_handle.h"
+#endif
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include "base/mac/scoped_mach_port.h"
+#endif
+
+namespace mojo {
+namespace core {
+
+void ExtractPlatformHandlesFromSharedMemoryRegionHandle(
+ base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle handle,
+ PlatformHandle* extracted_handle,
+ PlatformHandle* extracted_readonly_handle) {
+#if defined(OS_WIN)
+ *extracted_handle = PlatformHandle(base::win::ScopedHandle(handle.Take()));
+#elif defined(OS_FUCHSIA)
+ *extracted_handle = PlatformHandle(std::move(handle));
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ // This is a Mach port. Same code as above and below, but separated for
+ // clarity.
+ *extracted_handle = PlatformHandle(std::move(handle));
+#elif defined(OS_ANDROID)
+ // This is a file descriptor. Same code as above, but separated for clarity.
+ *extracted_handle = PlatformHandle(std::move(handle));
+#else
+ *extracted_handle = PlatformHandle(std::move(handle.fd));
+ *extracted_readonly_handle = PlatformHandle(std::move(handle.readonly_fd));
+#endif
+}
+
+base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle
+CreateSharedMemoryRegionHandleFromPlatformHandles(
+ PlatformHandle handle,
+ PlatformHandle readonly_handle) {
+#if defined(OS_WIN)
+ DCHECK(!readonly_handle.is_valid());
+ return handle.TakeHandle();
+#elif defined(OS_FUCHSIA)
+ DCHECK(!readonly_handle.is_valid());
+ return zx::vmo(handle.TakeHandle());
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ DCHECK(!readonly_handle.is_valid());
+ return handle.TakeMachPort();
+#elif defined(OS_ANDROID)
+ DCHECK(!readonly_handle.is_valid());
+ return handle.TakeFD();
+#else
+ return base::subtle::ScopedFDPair(handle.TakeFD(), readonly_handle.TakeFD());
+#endif
+}
+
+} // namespace core
+} // namespace mojo
diff --git a/chromium/mojo/core/platform_handle_utils.h b/chromium/mojo/core/platform_handle_utils.h
new file mode 100644
index 00000000000..b18275b5a4d
--- /dev/null
+++ b/chromium/mojo/core/platform_handle_utils.h
@@ -0,0 +1,35 @@
+// 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_CORE_PLATFORM_HANDLE_UTILS_H_
+#define MOJO_CORE_PLATFORM_HANDLE_UTILS_H_
+
+#include "base/memory/platform_shared_memory_region.h"
+#include "mojo/core/system_impl_export.h"
+#include "mojo/public/c/system/platform_handle.h"
+#include "mojo/public/c/system/types.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
+
+namespace mojo {
+namespace core {
+
+// Converts a base shared memory platform handle into one (maybe two on POSIX)
+// PlatformHandle(s).
+MOJO_SYSTEM_IMPL_EXPORT void ExtractPlatformHandlesFromSharedMemoryRegionHandle(
+ base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle handle,
+ PlatformHandle* extracted_handle,
+ PlatformHandle* extracted_readonly_handle);
+
+// Converts one (maybe two on POSIX) PlatformHandle(s) to a base shared memory
+// platform handle.
+MOJO_SYSTEM_IMPL_EXPORT
+base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle
+CreateSharedMemoryRegionHandleFromPlatformHandles(
+ PlatformHandle handle,
+ PlatformHandle readonly_handle);
+
+} // namespace core
+} // namespace mojo
+
+#endif // MOJO_CORE_PLATFORM_HANDLE_UTILS_H_
diff --git a/chromium/mojo/edk/system/platform_shared_memory_mapping.cc b/chromium/mojo/core/platform_shared_memory_mapping.cc
index 80f14f6546c..6b8d67201f3 100644
--- a/chromium/mojo/edk/system/platform_shared_memory_mapping.cc
+++ b/chromium/mojo/core/platform_shared_memory_mapping.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/platform_shared_memory_mapping.h"
+#include "mojo/core/platform_shared_memory_mapping.h"
#include <utility>
@@ -19,7 +19,7 @@
#endif
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -100,5 +100,5 @@ size_t PlatformSharedMemoryMapping::GetLength() const {
return length_;
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/platform_shared_memory_mapping.h b/chromium/mojo/core/platform_shared_memory_mapping.h
index 764fe4f4c1e..b7c43ace9e0 100644
--- a/chromium/mojo/edk/system/platform_shared_memory_mapping.h
+++ b/chromium/mojo/core/platform_shared_memory_mapping.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PLATFORM_SHARED_MEMORY_MAPPING_H_
-#define MOJO_EDK_SYSTEM_PLATFORM_SHARED_MEMORY_MAPPING_H_
+#ifndef MOJO_CORE_PLATFORM_SHARED_MEMORY_MAPPING_H_
+#define MOJO_CORE_PLATFORM_SHARED_MEMORY_MAPPING_H_
#include <stddef.h>
@@ -13,10 +13,10 @@
#include "base/macros.h"
#include "base/memory/platform_shared_memory_region.h"
#include "base/memory/shared_memory_mapping.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/system_impl_export.h"
namespace mojo {
-namespace edk {
+namespace core {
// A mapping of a |base::subtle::PlatformSharedMemoryRegion|, created
// exclusively by |SharedBufferDispatcher::MapBuffer()|. Automatically maps
@@ -54,7 +54,7 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedMemoryMapping {
DISALLOW_COPY_AND_ASSIGN(PlatformSharedMemoryMapping);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PLATFORM_SHARED_MEMORY_MAPPING_H_
+#endif // MOJO_CORE_PLATFORM_SHARED_MEMORY_MAPPING_H_
diff --git a/chromium/mojo/edk/system/platform_wrapper_unittest.cc b/chromium/mojo/core/platform_wrapper_unittest.cc
index f7770ba711c..e795b949201 100644
--- a/chromium/mojo/edk/system/platform_wrapper_unittest.cc
+++ b/chromium/mojo/core/platform_wrapper_unittest.cc
@@ -14,7 +14,7 @@
#include "base/memory/shared_memory.h"
#include "base/process/process_handle.h"
#include "build/build_config.h"
-#include "mojo/edk/test/mojo_test_base.h"
+#include "mojo/core/test/mojo_test_base.h"
#include "mojo/public/c/system/platform_handle.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,7 +38,7 @@
#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE SIMPLE_PLATFORM_HANDLE_TYPE
#endif
-uint64_t InternalPlatformHandleValueFromPlatformFile(base::PlatformFile file) {
+uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) {
#if defined(OS_WIN)
return reinterpret_cast<uint64_t>(file);
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
@@ -46,7 +46,7 @@ uint64_t InternalPlatformHandleValueFromPlatformFile(base::PlatformFile file) {
#endif
}
-base::PlatformFile PlatformFileFromInternalPlatformHandleValue(uint64_t value) {
+base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) {
#if defined(OS_WIN)
return reinterpret_cast<base::PlatformFile>(value);
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
@@ -55,12 +55,12 @@ base::PlatformFile PlatformFileFromInternalPlatformHandleValue(uint64_t value) {
}
namespace mojo {
-namespace edk {
+namespace core {
namespace {
using PlatformWrapperTest = test::MojoTestBase;
-TEST_F(PlatformWrapperTest, WrapInternalPlatformHandle) {
+TEST_F(PlatformWrapperTest, WrapPlatformHandle) {
// Create a temporary file and write a message to it.
base::FilePath temp_file_path;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
@@ -81,7 +81,7 @@ TEST_F(PlatformWrapperTest, WrapInternalPlatformHandle) {
os_file.struct_size = sizeof(MojoPlatformHandle);
os_file.type = SIMPLE_PLATFORM_HANDLE_TYPE;
os_file.value =
- InternalPlatformHandleValueFromPlatformFile(file.TakePlatformFile());
+ PlatformHandleValueFromPlatformFile(file.TakePlatformFile());
EXPECT_EQ(MOJO_RESULT_OK,
MojoWrapPlatformHandle(&os_file, nullptr, &wrapped_handle));
@@ -101,8 +101,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadPlatformFile, PlatformWrapperTest, h) {
ASSERT_EQ(MOJO_RESULT_OK, MojoUnwrapPlatformHandle(wrapped_handle, nullptr,
&platform_handle));
EXPECT_EQ(SIMPLE_PLATFORM_HANDLE_TYPE, platform_handle.type);
- base::File file(
- PlatformFileFromInternalPlatformHandleValue(platform_handle.value));
+ base::File file(PlatformFileFromPlatformHandleValue(platform_handle.value));
// Expect to read the same message from the file.
std::vector<char> data(message.size());
@@ -246,5 +245,5 @@ TEST_F(PlatformWrapperTest, InvalidArgument) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/BUILD.gn b/chromium/mojo/core/ports/BUILD.gn
index 1a5ba79279c..68dce3f8eb6 100644
--- a/chromium/mojo/edk/system/ports/BUILD.gn
+++ b/chromium/mojo/core/ports/BUILD.gn
@@ -5,7 +5,7 @@
import("//testing/test.gni")
component("ports") {
- output_name = "mojo_edk_ports"
+ output_name = "mojo_core_ports"
sources = [
"event.cc",
@@ -29,7 +29,7 @@ component("ports") {
"user_message.h",
]
- defines = [ "IS_MOJO_EDK_PORTS_IMPL" ]
+ defines = [ "IS_MOJO_CORE_PORTS_IMPL" ]
public_deps = [
"//base",
diff --git a/chromium/mojo/edk/system/ports/event.cc b/chromium/mojo/core/ports/event.cc
index 1c5abaf8e3b..f3cf74edbdd 100644
--- a/chromium/mojo/edk/system/ports/event.cc
+++ b/chromium/mojo/core/ports/event.cc
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/event.h"
+#include "mojo/core/ports/event.h"
#include <stdint.h>
#include <string.h>
#include "base/numerics/safe_math.h"
-#include "mojo/edk/system/ports/user_message.h"
+#include "mojo/core/ports/user_message.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
namespace {
@@ -189,6 +189,12 @@ UserMessageEvent::UserMessageEvent(const PortName& port_name,
uint64_t sequence_num)
: Event(Type::kUserMessage, port_name), sequence_num_(sequence_num) {}
+size_t UserMessageEvent::GetSizeIfSerialized() const {
+ if (!message_)
+ return 0;
+ return message_->GetSizeIfSerialized();
+}
+
size_t UserMessageEvent::GetSerializedDataSize() const {
DCHECK_EQ(ports_.size(), port_descriptors_.size());
base::CheckedNumeric<size_t> size = sizeof(UserMessageEventData);
@@ -373,5 +379,5 @@ void MergePortEvent::SerializeData(void* buffer) const {
}
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/event.h b/chromium/mojo/core/ports/event.h
index ab8a4d80113..e278896b04f 100644
--- a/chromium/mojo/edk/system/ports/event.h
+++ b/chromium/mojo/core/ports/event.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_EVENT_H_
-#define MOJO_EDK_SYSTEM_PORTS_EVENT_H_
+#ifndef MOJO_CORE_PORTS_EVENT_H_
+#define MOJO_CORE_PORTS_EVENT_H_
#include <stdint.h>
@@ -12,11 +12,11 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "mojo/edk/system/ports/name.h"
-#include "mojo/edk/system/ports/user_message.h"
+#include "mojo/core/ports/name.h"
+#include "mojo/core/ports/user_message.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
class Event;
@@ -25,7 +25,7 @@ using ScopedEvent = std::unique_ptr<Event>;
// A Event is the fundamental unit of operation and communication within and
// between Nodes.
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) Event {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) Event {
public:
enum Type : uint32_t {
// A user message event contains arbitrary user-specified payload data
@@ -103,7 +103,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) Event {
DISALLOW_COPY_AND_ASSIGN(Event);
};
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) UserMessageEvent : public Event {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) UserMessageEvent : public Event {
public:
explicit UserMessageEvent(size_t num_ports);
~UserMessageEvent() override;
@@ -139,6 +139,8 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) UserMessageEvent : public Event {
const void* buffer,
size_t num_bytes);
+ size_t GetSizeIfSerialized() const;
+
private:
UserMessageEvent(const PortName& port_name, uint64_t sequence_num);
@@ -153,7 +155,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) UserMessageEvent : public Event {
DISALLOW_COPY_AND_ASSIGN(UserMessageEvent);
};
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) PortAcceptedEvent : public Event {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) PortAcceptedEvent : public Event {
public:
explicit PortAcceptedEvent(const PortName& port_name);
~PortAcceptedEvent() override;
@@ -169,7 +171,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) PortAcceptedEvent : public Event {
DISALLOW_COPY_AND_ASSIGN(PortAcceptedEvent);
};
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveProxyEvent : public Event {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) ObserveProxyEvent : public Event {
public:
ObserveProxyEvent(const PortName& port_name,
const NodeName& proxy_node_name,
@@ -204,7 +206,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveProxyEvent : public Event {
DISALLOW_COPY_AND_ASSIGN(ObserveProxyEvent);
};
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveProxyAckEvent : public Event {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) ObserveProxyAckEvent : public Event {
public:
ObserveProxyAckEvent(const PortName& port_name, uint64_t last_sequence_num);
~ObserveProxyAckEvent() override;
@@ -225,7 +227,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveProxyAckEvent : public Event {
DISALLOW_COPY_AND_ASSIGN(ObserveProxyAckEvent);
};
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveClosureEvent : public Event {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) ObserveClosureEvent : public Event {
public:
ObserveClosureEvent(const PortName& port_name, uint64_t last_sequence_num);
~ObserveClosureEvent() override;
@@ -249,7 +251,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) ObserveClosureEvent : public Event {
DISALLOW_COPY_AND_ASSIGN(ObserveClosureEvent);
};
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) MergePortEvent : public Event {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) MergePortEvent : public Event {
public:
MergePortEvent(const PortName& port_name,
const PortName& new_port_name,
@@ -276,7 +278,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) MergePortEvent : public Event {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_EVENT_H_
+#endif // MOJO_CORE_PORTS_EVENT_H_
diff --git a/chromium/mojo/edk/system/ports/message_filter.h b/chromium/mojo/core/ports/message_filter.h
index 1b1f2ce2167..f09903ffca4 100644
--- a/chromium/mojo/edk/system/ports/message_filter.h
+++ b/chromium/mojo/core/ports/message_filter.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_MESSAGE_FILTER_H_
-#define MOJO_EDK_SYSTEM_PORTS_MESSAGE_FILTER_H_
+#ifndef MOJO_CORE_PORTS_MESSAGE_FILTER_H_
+#define MOJO_CORE_PORTS_MESSAGE_FILTER_H_
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
class UserMessageEvent;
@@ -23,7 +23,7 @@ class MessageFilter {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_MESSAGE_FILTER_H_
+#endif // MOJO_CORE_PORTS_MESSAGE_FILTER_H_
diff --git a/chromium/mojo/edk/system/ports/message_queue.cc b/chromium/mojo/core/ports/message_queue.cc
index 859636243d1..074b35a46da 100644
--- a/chromium/mojo/edk/system/ports/message_queue.cc
+++ b/chromium/mojo/core/ports/message_queue.cc
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/message_queue.h"
+#include "mojo/core/ports/message_queue.h"
#include <algorithm>
#include "base/logging.h"
-#include "mojo/edk/system/ports/message_filter.h"
+#include "mojo/core/ports/message_filter.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
// Used by std::{push,pop}_heap functions
@@ -50,6 +50,7 @@ void MessageQueue::GetNextMessage(std::unique_ptr<UserMessageEvent>* message,
std::pop_heap(heap_.begin(), heap_.end());
*message = std::move(heap_.back());
+ total_queued_bytes_ -= (*message)->GetSizeIfSerialized();
heap_.pop_back();
next_sequence_num_++;
@@ -59,6 +60,7 @@ void MessageQueue::AcceptMessage(std::unique_ptr<UserMessageEvent> message,
bool* has_next_message) {
// TODO: Handle sequence number roll-over.
+ total_queued_bytes_ += message->GetSizeIfSerialized();
heap_.emplace_back(std::move(message));
std::push_heap(heap_.begin(), heap_.end());
@@ -72,8 +74,9 @@ void MessageQueue::AcceptMessage(std::unique_ptr<UserMessageEvent> message,
void MessageQueue::TakeAllMessages(
std::vector<std::unique_ptr<UserMessageEvent>>* messages) {
*messages = std::move(heap_);
+ total_queued_bytes_ = 0;
}
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/message_queue.h b/chromium/mojo/core/ports/message_queue.h
index 829d217213e..1d34222c5eb 100644
--- a/chromium/mojo/edk/system/ports/message_queue.h
+++ b/chromium/mojo/core/ports/message_queue.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_MESSAGE_QUEUE_H_
-#define MOJO_EDK_SYSTEM_PORTS_MESSAGE_QUEUE_H_
+#ifndef MOJO_CORE_PORTS_MESSAGE_QUEUE_H_
+#define MOJO_CORE_PORTS_MESSAGE_QUEUE_H_
#include <stdint.h>
@@ -13,10 +13,10 @@
#include "base/component_export.h"
#include "base/macros.h"
-#include "mojo/edk/system/ports/event.h"
+#include "mojo/core/ports/event.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
constexpr uint64_t kInitialSequenceNum = 1;
@@ -28,7 +28,7 @@ class MessageFilter;
// known sequence number and can indicate whether the next sequential message is
// available. Thus the queue enforces message ordering for the consumer without
// enforcing it for the producer (see AcceptMessage() below.)
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) MessageQueue {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) MessageQueue {
public:
explicit MessageQueue();
explicit MessageQueue(uint64_t next_sequence_num);
@@ -62,16 +62,25 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) MessageQueue {
void TakeAllMessages(
std::vector<std::unique_ptr<UserMessageEvent>>* messages);
+ // The number of messages queued here, regardless of whether the next expected
+ // message has arrived yet.
+ size_t queued_message_count() const { return heap_.size(); }
+
+ // The aggregate memory size in bytes of all messages queued here, regardless
+ // of whether the next expected message has arrived yet.
+ size_t queued_num_bytes() const { return total_queued_bytes_; }
+
private:
std::vector<std::unique_ptr<UserMessageEvent>> heap_;
uint64_t next_sequence_num_;
bool signalable_ = true;
+ size_t total_queued_bytes_ = 0;
DISALLOW_COPY_AND_ASSIGN(MessageQueue);
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_MESSAGE_QUEUE_H_
+#endif // MOJO_CORE_PORTS_MESSAGE_QUEUE_H_
diff --git a/chromium/mojo/edk/system/ports/name.cc b/chromium/mojo/core/ports/name.cc
index fe03b4ba704..332a0a0826d 100644
--- a/chromium/mojo/edk/system/ports/name.cc
+++ b/chromium/mojo/core/ports/name.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/name.h"
+#include "mojo/core/ports/name.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
const PortName kInvalidPortName = {0, 0};
@@ -22,5 +22,5 @@ std::ostream& operator<<(std::ostream& stream, const Name& name) {
}
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/name.h b/chromium/mojo/core/ports/name.h
index 80d7ffc38d5..415ba65a958 100644
--- a/chromium/mojo/edk/system/ports/name.h
+++ b/chromium/mojo/core/ports/name.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_NAME_H_
-#define MOJO_EDK_SYSTEM_PORTS_NAME_H_
+#ifndef MOJO_CORE_PORTS_NAME_H_
+#define MOJO_CORE_PORTS_NAME_H_
#include <stdint.h>
@@ -14,10 +14,10 @@
#include "base/hash.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
-struct COMPONENT_EXPORT(MOJO_EDK_PORTS) Name {
+struct COMPONENT_EXPORT(MOJO_CORE_PORTS) Name {
Name(uint64_t v1, uint64_t v2) : v1(v1), v2(v2) {}
uint64_t v1, v2;
};
@@ -34,43 +34,43 @@ inline bool operator<(const Name& a, const Name& b) {
return std::tie(a.v1, a.v2) < std::tie(b.v1, b.v2);
}
-COMPONENT_EXPORT(MOJO_EDK_PORTS)
+COMPONENT_EXPORT(MOJO_CORE_PORTS)
std::ostream& operator<<(std::ostream& stream, const Name& name);
-struct COMPONENT_EXPORT(MOJO_EDK_PORTS) PortName : Name {
+struct COMPONENT_EXPORT(MOJO_CORE_PORTS) PortName : Name {
PortName() : Name(0, 0) {}
PortName(uint64_t v1, uint64_t v2) : Name(v1, v2) {}
};
-extern COMPONENT_EXPORT(MOJO_EDK_PORTS) const PortName kInvalidPortName;
+extern COMPONENT_EXPORT(MOJO_CORE_PORTS) const PortName kInvalidPortName;
-struct COMPONENT_EXPORT(MOJO_EDK_PORTS) NodeName : Name {
+struct COMPONENT_EXPORT(MOJO_CORE_PORTS) NodeName : Name {
NodeName() : Name(0, 0) {}
NodeName(uint64_t v1, uint64_t v2) : Name(v1, v2) {}
};
-extern COMPONENT_EXPORT(MOJO_EDK_PORTS) const NodeName kInvalidNodeName;
+extern COMPONENT_EXPORT(MOJO_CORE_PORTS) const NodeName kInvalidNodeName;
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
namespace std {
template <>
-struct COMPONENT_EXPORT(MOJO_EDK_PORTS) hash<mojo::edk::ports::PortName> {
- std::size_t operator()(const mojo::edk::ports::PortName& name) const {
+struct COMPONENT_EXPORT(MOJO_CORE_PORTS) hash<mojo::core::ports::PortName> {
+ std::size_t operator()(const mojo::core::ports::PortName& name) const {
return base::HashInts64(name.v1, name.v2);
}
};
template <>
-struct COMPONENT_EXPORT(MOJO_EDK_PORTS) hash<mojo::edk::ports::NodeName> {
- std::size_t operator()(const mojo::edk::ports::NodeName& name) const {
+struct COMPONENT_EXPORT(MOJO_CORE_PORTS) hash<mojo::core::ports::NodeName> {
+ std::size_t operator()(const mojo::core::ports::NodeName& name) const {
return base::HashInts64(name.v1, name.v2);
}
};
} // namespace std
-#endif // MOJO_EDK_SYSTEM_PORTS_NAME_H_
+#endif // MOJO_CORE_PORTS_NAME_H_
diff --git a/chromium/mojo/edk/system/ports/name_unittest.cc b/chromium/mojo/core/ports/name_unittest.cc
index 7e4d82b7651..520295c5807 100644
--- a/chromium/mojo/edk/system/ports/name_unittest.cc
+++ b/chromium/mojo/core/ports/name_unittest.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/name.h"
+#include "mojo/core/ports/name.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
namespace test {
@@ -71,5 +71,5 @@ TEST(NameTest, NodeNameChecks) {
} // namespace test
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/node.cc b/chromium/mojo/core/ports/node.cc
index 78365e4d856..7ed191c7886 100644
--- a/chromium/mojo/edk/system/ports/node.cc
+++ b/chromium/mojo/core/ports/node.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/node.h"
+#include "mojo/core/ports/node.h"
#include <string.h>
@@ -18,9 +18,9 @@
#include "base/synchronization/lock.h"
#include "base/threading/thread_local.h"
#include "build/build_config.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/node_delegate.h"
-#include "mojo/edk/system/ports/port_locker.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/node_delegate.h"
+#include "mojo/core/ports/port_locker.h"
#if !defined(OS_NACL)
#include "crypto/random.h"
@@ -29,7 +29,7 @@
#endif
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
namespace {
@@ -305,6 +305,9 @@ int Node::GetStatus(const PortRef& port_ref, PortStatus* port_status) {
port_status->receiving_messages = CanAcceptMoreMessages(port);
port_status->peer_closed = port->peer_closed;
port_status->peer_remote = port->peer_node_name != name_;
+ port_status->queued_message_count =
+ port->message_queue.queued_message_count();
+ port_status->queued_num_bytes = port->message_queue.queued_num_bytes();
return OK;
}
@@ -1381,5 +1384,5 @@ void Node::DelegateHolder::EnsureSafeDelegateAccess() const {
#endif
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/node.h b/chromium/mojo/core/ports/node.h
index ec4bbbcd439..a9576bf2660 100644
--- a/chromium/mojo/edk/system/ports/node.h
+++ b/chromium/mojo/core/ports/node.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_NODE_H_
-#define MOJO_EDK_SYSTEM_PORTS_NODE_H_
+#ifndef MOJO_CORE_PORTS_NODE_H_
+#define MOJO_CORE_PORTS_NODE_H_
#include <stddef.h>
#include <stdint.h>
@@ -15,14 +15,14 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/name.h"
-#include "mojo/edk/system/ports/port.h"
-#include "mojo/edk/system/ports/port_ref.h"
-#include "mojo/edk/system/ports/user_data.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/name.h"
+#include "mojo/core/ports/port.h"
+#include "mojo/core/ports/port_ref.h"
+#include "mojo/core/ports/user_data.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
enum : int {
@@ -41,6 +41,8 @@ struct PortStatus {
bool receiving_messages;
bool peer_closed;
bool peer_remote;
+ size_t queued_message_count;
+ size_t queued_num_bytes;
};
class MessageFilter;
@@ -62,7 +64,7 @@ class NodeDelegate;
// by Nodes to coordinate Port behavior and lifetime within and across Nodes.
// See Event documentation for description of different types of events used by
// a Node to coordinate behavior.
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) Node {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) Node {
public:
enum class ShutdownPolicy {
DONT_ALLOW_LOCAL_PORTS,
@@ -242,7 +244,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) Node {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_NODE_H_
+#endif // MOJO_CORE_PORTS_NODE_H_
diff --git a/chromium/mojo/edk/system/ports/node_delegate.h b/chromium/mojo/core/ports/node_delegate.h
index 3c7550a608e..afe1c4cd975 100644
--- a/chromium/mojo/edk/system/ports/node_delegate.h
+++ b/chromium/mojo/core/ports/node_delegate.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_NODE_DELEGATE_H_
-#define MOJO_EDK_SYSTEM_PORTS_NODE_DELEGATE_H_
+#ifndef MOJO_CORE_PORTS_NODE_DELEGATE_H_
+#define MOJO_CORE_PORTS_NODE_DELEGATE_H_
#include <stddef.h>
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/name.h"
-#include "mojo/edk/system/ports/port_ref.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/name.h"
+#include "mojo/core/ports/port_ref.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
class NodeDelegate {
@@ -32,7 +32,7 @@ class NodeDelegate {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_NODE_DELEGATE_H_
+#endif // MOJO_CORE_PORTS_NODE_DELEGATE_H_
diff --git a/chromium/mojo/edk/system/ports/port.cc b/chromium/mojo/core/ports/port.cc
index e4403aed788..71869790218 100644
--- a/chromium/mojo/edk/system/ports/port.cc
+++ b/chromium/mojo/core/ports/port.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/port.h"
+#include "mojo/core/ports/port.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
Port::Port(uint64_t next_sequence_num_to_send,
@@ -20,5 +20,5 @@ Port::Port(uint64_t next_sequence_num_to_send,
Port::~Port() {}
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/port.h b/chromium/mojo/core/ports/port.h
index e10bfebe41d..d1a825e2c62 100644
--- a/chromium/mojo/edk/system/ports/port.h
+++ b/chromium/mojo/core/ports/port.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_PORT_H_
-#define MOJO_EDK_SYSTEM_PORTS_PORT_H_
+#ifndef MOJO_CORE_PORTS_PORT_H_
+#define MOJO_CORE_PORTS_PORT_H_
#include <memory>
#include <queue>
@@ -13,12 +13,12 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/message_queue.h"
-#include "mojo/edk/system/ports/user_data.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/message_queue.h"
+#include "mojo/core/ports/user_data.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
class PortLocker;
@@ -169,7 +169,7 @@ class Port : public base::RefCountedThreadSafe<Port> {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_PORT_H_
+#endif // MOJO_CORE_PORTS_PORT_H_
diff --git a/chromium/mojo/edk/system/ports/port_locker.cc b/chromium/mojo/core/ports/port_locker.cc
index e84d0d00b23..880492332dd 100644
--- a/chromium/mojo/edk/system/ports/port_locker.cc
+++ b/chromium/mojo/core/ports/port_locker.cc
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/port_locker.h"
+#include "mojo/core/ports/port_locker.h"
#include <algorithm>
-#include "mojo/edk/system/ports/port.h"
+#include "mojo/core/ports/port.h"
#if DCHECK_IS_ON()
#include "base/threading/thread_local.h"
#endif
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
namespace {
@@ -70,5 +70,5 @@ SinglePortLocker::SinglePortLocker(const PortRef* port_ref)
SinglePortLocker::~SinglePortLocker() = default;
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/port_locker.h b/chromium/mojo/core/ports/port_locker.h
index 38782068b0e..0da26545635 100644
--- a/chromium/mojo/edk/system/ports/port_locker.h
+++ b/chromium/mojo/core/ports/port_locker.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_PORT_LOCKER_H_
-#define MOJO_EDK_SYSTEM_PORTS_PORT_LOCKER_H_
+#ifndef MOJO_CORE_PORTS_PORT_LOCKER_H_
+#define MOJO_CORE_PORTS_PORT_LOCKER_H_
#include <stdint.h>
#include "base/macros.h"
-#include "mojo/edk/system/ports/port_ref.h"
+#include "mojo/core/ports/port_ref.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
class Port;
@@ -80,7 +80,7 @@ class SinglePortLocker {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_PORT_LOCKER_H_
+#endif // MOJO_CORE_PORTS_PORT_LOCKER_H_
diff --git a/chromium/mojo/edk/system/ports/port_ref.cc b/chromium/mojo/core/ports/port_ref.cc
index 66e48c2ecbe..a3d312bc399 100644
--- a/chromium/mojo/edk/system/ports/port_ref.cc
+++ b/chromium/mojo/core/ports/port_ref.cc
@@ -2,19 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/port_ref.h"
+#include "mojo/core/ports/port_ref.h"
-#include "mojo/edk/system/ports/port.h"
+#include "mojo/core/ports/port.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
-PortRef::~PortRef() {
-}
+PortRef::~PortRef() {}
-PortRef::PortRef() {
-}
+PortRef::PortRef() {}
PortRef::PortRef(const PortName& name, scoped_refptr<Port> port)
: name_(name), port_(std::move(port)) {}
@@ -28,5 +26,5 @@ PortRef& PortRef::operator=(const PortRef& other) = default;
PortRef& PortRef::operator=(PortRef&& other) = default;
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/port_ref.h b/chromium/mojo/core/ports/port_ref.h
index 9bafe38f474..b63d6cfcd00 100644
--- a/chromium/mojo/edk/system/ports/port_ref.h
+++ b/chromium/mojo/core/ports/port_ref.h
@@ -2,22 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_PORT_REF_H_
-#define MOJO_EDK_SYSTEM_PORTS_PORT_REF_H_
+#ifndef MOJO_CORE_PORTS_PORT_REF_H_
+#define MOJO_CORE_PORTS_PORT_REF_H_
#include "base/component_export.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/system/ports/name.h"
+#include "mojo/core/ports/name.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
class Port;
class PortLocker;
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) PortRef {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) PortRef {
public:
~PortRef();
PortRef();
@@ -43,7 +43,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) PortRef {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_PORT_REF_H_
+#endif // MOJO_CORE_PORTS_PORT_REF_H_
diff --git a/chromium/mojo/edk/system/ports/ports_unittest.cc b/chromium/mojo/core/ports/ports_unittest.cc
index f04ac49f609..3d18bb680fa 100644
--- a/chromium/mojo/edk/system/ports/ports_unittest.cc
+++ b/chromium/mojo/core/ports/ports_unittest.cc
@@ -22,14 +22,14 @@
#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/node.h"
-#include "mojo/edk/system/ports/node_delegate.h"
-#include "mojo/edk/system/ports/user_message.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/node.h"
+#include "mojo/core/ports/node_delegate.h"
+#include "mojo/core/ports/user_message.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
namespace test {
@@ -1640,5 +1640,5 @@ TEST_F(PortsTest, RetransmitUserMessageEvents) {
} // namespace test
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/user_data.h b/chromium/mojo/core/ports/user_data.h
index 73e7d17b328..e18d9b79d5f 100644
--- a/chromium/mojo/edk/system/ports/user_data.h
+++ b/chromium/mojo/core/ports/user_data.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_USER_DATA_H_
-#define MOJO_EDK_SYSTEM_PORTS_USER_DATA_H_
+#ifndef MOJO_CORE_PORTS_USER_DATA_H_
+#define MOJO_CORE_PORTS_USER_DATA_H_
#include "base/memory/ref_counted.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
class UserData : public base::RefCountedThreadSafe<UserData> {
@@ -19,7 +19,7 @@ class UserData : public base::RefCountedThreadSafe<UserData> {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_USER_DATA_H_
+#endif // MOJO_CORE_PORTS_USER_DATA_H_
diff --git a/chromium/mojo/edk/system/ports/user_message.cc b/chromium/mojo/core/ports/user_message.cc
index 1976dcb8130..aa16376c9c5 100644
--- a/chromium/mojo/edk/system/ports/user_message.cc
+++ b/chromium/mojo/core/ports/user_message.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/ports/user_message.h"
+#include "mojo/core/ports/user_message.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
UserMessage::UserMessage(const TypeInfo* type_info) : type_info_(type_info) {}
@@ -16,6 +16,10 @@ bool UserMessage::WillBeRoutedExternally() {
return true;
}
+size_t UserMessage::GetSizeIfSerialized() const {
+ return 0;
+}
+
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/ports/user_message.h b/chromium/mojo/core/ports/user_message.h
index b4414b2de21..34d26887202 100644
--- a/chromium/mojo/edk/system/ports/user_message.h
+++ b/chromium/mojo/core/ports/user_message.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_PORTS_USER_MESSAGE_H_
-#define MOJO_EDK_SYSTEM_PORTS_USER_MESSAGE_H_
+#ifndef MOJO_CORE_PORTS_USER_MESSAGE_H_
+#define MOJO_CORE_PORTS_USER_MESSAGE_H_
#include "base/component_export.h"
#include "base/macros.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace ports {
// Base type to use for any embedder-defined user message implementation. This
@@ -22,7 +22,7 @@ namespace ports {
// |kUserMessageTypeInfo| and pass its address down to the UserMessage
// constructor. The type of a UserMessage can then be dynamically inspected by
// comparing |type_info()| to any subclass's |&kUserMessageTypeInfo|.
-class COMPONENT_EXPORT(MOJO_EDK_PORTS) UserMessage {
+class COMPONENT_EXPORT(MOJO_CORE_PORTS) UserMessage {
public:
struct TypeInfo {};
@@ -39,6 +39,10 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) UserMessage {
// message event will be destroyed without further routing.
virtual bool WillBeRoutedExternally();
+ // Returns the size in bytes of this message iff it's serialized. Zero
+ // otherwise.
+ virtual size_t GetSizeIfSerialized() const;
+
private:
const TypeInfo* const type_info_;
@@ -46,7 +50,7 @@ class COMPONENT_EXPORT(MOJO_EDK_PORTS) UserMessage {
};
} // namespace ports
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_PORTS_USER_MESSAGE_H_
+#endif // MOJO_CORE_PORTS_USER_MESSAGE_H_
diff --git a/chromium/mojo/core/quota_unittest.cc b/chromium/mojo/core/quota_unittest.cc
new file mode 100644
index 00000000000..bc26baf151a
--- /dev/null
+++ b/chromium/mojo/core/quota_unittest.cc
@@ -0,0 +1,314 @@
+// Copyright 2018 The Chromium 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 <string>
+
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/public/c/system/quota.h"
+
+namespace mojo {
+namespace core {
+namespace {
+
+using QuotaTest = test::MojoTestBase;
+
+void QuotaExceededEventHandler(const MojoTrapEvent* event) {
+ // Always treat trigger context as the address of a bool to set to |true|.
+ if (event->result == MOJO_RESULT_OK)
+ *reinterpret_cast<bool*>(event->trigger_context) = true;
+}
+
+TEST_F(QuotaTest, InvalidArguments) {
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSetQuota(MOJO_HANDLE_INVALID,
+ MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, 2, nullptr));
+
+ const MojoQuotaType kInvalidQuotaType = 0xfffffffful;
+ MojoHandle message_pipe0, message_pipe1;
+ CreateMessagePipe(&message_pipe0, &message_pipe1);
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSetQuota(message_pipe0, kInvalidQuotaType, 0, nullptr));
+
+ const MojoSetQuotaOptions kInvalidSetQuotaOptions = {0};
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSetQuota(message_pipe0, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, 0,
+ &kInvalidSetQuotaOptions));
+
+ uint64_t limit = 0;
+ uint64_t usage = 0;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoQueryQuota(message_pipe0, kInvalidQuotaType, nullptr, &limit,
+ &usage));
+
+ const MojoQueryQuotaOptions kInvalidQueryQuotaOptions = {0};
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoQueryQuota(message_pipe0, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH,
+ &kInvalidQueryQuotaOptions, &limit, &usage));
+
+ MojoClose(message_pipe0);
+ MojoClose(message_pipe1);
+
+ MojoHandle producer, consumer;
+ CreateDataPipe(&producer, &consumer, 1);
+ EXPECT_EQ(
+ MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSetQuota(producer, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, 0, nullptr));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSetQuota(producer, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE, 0,
+ nullptr));
+ EXPECT_EQ(
+ MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSetQuota(consumer, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, 0, nullptr));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSetQuota(consumer, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE, 0,
+ nullptr));
+ MojoClose(producer);
+ MojoClose(consumer);
+}
+
+TEST_F(QuotaTest, BasicReceiveQueueLength) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ uint64_t limit = 0;
+ uint64_t usage = 0;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(a, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, nullptr,
+ &limit, &usage));
+ EXPECT_EQ(MOJO_QUOTA_LIMIT_NONE, limit);
+ EXPECT_EQ(0u, usage);
+
+ const uint64_t kTestLimit = 42;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoSetQuota(a, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, kTestLimit,
+ nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(a, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, nullptr,
+ &limit, &usage));
+ EXPECT_EQ(kTestLimit, limit);
+ EXPECT_EQ(0u, usage);
+
+ const std::string kTestMessage = "doot";
+ WriteMessage(b, kTestMessage);
+ WaitForSignals(a, MOJO_HANDLE_SIGNAL_READABLE);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(a, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, nullptr,
+ &limit, &usage));
+ EXPECT_EQ(kTestLimit, limit);
+ EXPECT_EQ(1u, usage);
+}
+
+TEST_F(QuotaTest, BasicReceiveQueueMemorySize) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ uint64_t limit = 0;
+ uint64_t usage = 0;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(a, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE,
+ nullptr, &limit, &usage));
+ EXPECT_EQ(MOJO_QUOTA_LIMIT_NONE, limit);
+ EXPECT_EQ(0u, usage);
+
+ const uint64_t kTestLimit = 42;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoSetQuota(a, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE,
+ kTestLimit, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(a, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE,
+ nullptr, &limit, &usage));
+ EXPECT_EQ(kTestLimit, limit);
+ EXPECT_EQ(0u, usage);
+
+ const std::string kTestMessage = "doot";
+ WriteMessage(b, kTestMessage);
+ WaitForSignals(a, MOJO_HANDLE_SIGNAL_READABLE);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(a, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE,
+ nullptr, &limit, &usage));
+ EXPECT_EQ(kTestLimit, limit);
+ EXPECT_EQ(usage, kTestMessage.size());
+
+ MojoClose(a);
+ MojoClose(b);
+}
+
+TEST_F(QuotaTest, ReceiveQueueLengthLimitExceeded) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ const uint64_t kMaxMessages = 1;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoSetQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, kMaxMessages,
+ nullptr));
+
+ MojoHandleSignalsState signals;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_FALSE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ const std::string kTestMessage = "this message is lit, fam";
+ WriteMessage(a, kTestMessage);
+ WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE);
+
+ uint64_t limit = 0;
+ uint64_t usage = 0;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, nullptr,
+ &limit, &usage));
+ EXPECT_EQ(kMaxMessages, limit);
+ EXPECT_EQ(1u, usage);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_FALSE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ // Push the endpoint over quota and ensure that it signals accordingly.
+ WriteMessage(a, kTestMessage);
+ WaitForSignals(b, MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_TRUE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, nullptr,
+ &limit, &usage));
+ EXPECT_EQ(kMaxMessages, limit);
+ EXPECT_EQ(2u, usage);
+
+ // Read a message and wait for QUOTA_EXCEEDED to go back low.
+ EXPECT_EQ(kTestMessage, ReadMessage(b));
+ WaitForSignals(b, MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_FALSE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, nullptr,
+ &limit, &usage));
+ EXPECT_EQ(kMaxMessages, limit);
+ EXPECT_EQ(1u, usage);
+
+ MojoClose(a);
+ MojoClose(b);
+}
+
+TEST_F(QuotaTest, ReceiveQueueMemorySizeLimitExceeded) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ const uint64_t kMaxMessageBytes = 6;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoSetQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE,
+ kMaxMessageBytes, nullptr));
+
+ MojoHandleSignalsState signals;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_FALSE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ const std::string kTestMessage = "four";
+ WriteMessage(a, kTestMessage);
+ WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE);
+
+ uint64_t limit = 0;
+ uint64_t usage = 0;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE,
+ nullptr, &limit, &usage));
+ EXPECT_EQ(kMaxMessageBytes, limit);
+ EXPECT_EQ(kTestMessage.size(), usage);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_FALSE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ // Push the endpoint over quota and ensure that it signals accordingly.
+ WriteMessage(a, kTestMessage);
+ WaitForSignals(b, MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_TRUE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE,
+ nullptr, &limit, &usage));
+ EXPECT_EQ(kMaxMessageBytes, limit);
+ EXPECT_EQ(kTestMessage.size() * 2, usage);
+
+ // Read a message and wait for QUOTA_EXCEEDED to go back low.
+ EXPECT_EQ(kTestMessage, ReadMessage(b));
+ WaitForSignals(b, MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_FALSE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE,
+ nullptr, &limit, &usage));
+ EXPECT_EQ(kMaxMessageBytes, limit);
+ EXPECT_EQ(kTestMessage.size(), usage);
+
+ MojoClose(a);
+ MojoClose(b);
+}
+
+TEST_F(QuotaTest, TrapQuotaExceeded) {
+ // Simple sanity check to verify that QUOTA_EXCEEDED signals can be trapped
+ // like any other signals.
+
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ const uint64_t kMaxMessages = 42;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoSetQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, kMaxMessages,
+ nullptr));
+
+ bool signal_event_fired = false;
+ MojoHandle quota_trap;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoCreateTrap(&QuotaExceededEventHandler, nullptr, &quota_trap));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(quota_trap, b, MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ reinterpret_cast<uintptr_t>(&signal_event_fired),
+ nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(quota_trap, nullptr, nullptr, nullptr));
+
+ const std::string kTestMessage("sup");
+ for (uint64_t i = 0; i < kMaxMessages; ++i)
+ WriteMessage(a, kTestMessage);
+
+ // We're at quota but not yet over.
+ MojoHandleSignalsState signals;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_FALSE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+ EXPECT_FALSE(signal_event_fired);
+
+ // Push over quota. The event handler should be invoked before this returns.
+ WriteMessage(a, kTestMessage);
+ EXPECT_TRUE(signal_event_fired);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &signals));
+ EXPECT_TRUE(signals.satisfied_signals & MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+
+ uint64_t limit = 0;
+ uint64_t usage = 0;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoQueryQuota(b, MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH, nullptr,
+ &limit, &usage));
+ EXPECT_EQ(kMaxMessages, limit);
+ EXPECT_EQ(kMaxMessages + 1, usage);
+
+ MojoClose(quota_trap);
+ MojoClose(a);
+ MojoClose(b);
+}
+
+} // namespace
+} // namespace core
+} // namespace mojo
diff --git a/chromium/mojo/edk/system/request_context.cc b/chromium/mojo/core/request_context.cc
index 4de4343fa2b..0a481af7291 100644
--- a/chromium/mojo/edk/system/request_context.cc
+++ b/chromium/mojo/core/request_context.cc
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/request_context.h"
+#include "mojo/core/request_context.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/threading/thread_local.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -55,8 +55,14 @@ RequestContext::~RequestContext() {
static const HandleSignalsState closed_state = {0, 0};
// Establish a new RequestContext to capture and run any new notifications
- // triggered by the callback invocation.
- RequestContext inner_context(source_);
+ // triggered by the callback invocation. Note that while it would be safe
+ // to inherit |source_| from the perspective of Mojo core re-entrancy,
+ // upper application layers may use the flag as a signal to allow
+ // synchronous event dispatch and in turn shoot themselves in the foot
+ // with e.g. mutually recursive event handlers. We avoid that by
+ // treating all nested trap events as if they originated from a local API
+ // call even if this is a system RequestContext.
+ RequestContext inner_context(Source::LOCAL_API_CALL);
watch->InvokeCallback(MOJO_RESULT_CANCELLED, closed_state, flags);
}
@@ -106,5 +112,5 @@ RequestContext::WatchNotifyFinalizer::WatchNotifyFinalizer(
RequestContext::WatchNotifyFinalizer::~WatchNotifyFinalizer() {}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/request_context.h b/chromium/mojo/core/request_context.h
index d1f43bdfbd1..89988f27d30 100644
--- a/chromium/mojo/edk/system/request_context.h
+++ b/chromium/mojo/core/request_context.h
@@ -2,21 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_REQUEST_CONTEXT_H_
-#define MOJO_EDK_SYSTEM_REQUEST_CONTEXT_H_
+#ifndef MOJO_CORE_REQUEST_CONTEXT_H_
+#define MOJO_CORE_REQUEST_CONTEXT_H_
#include "base/containers/stack_container.h"
#include "base/macros.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/edk/system/watch.h"
+#include "mojo/core/handle_signals_state.h"
+#include "mojo/core/system_impl_export.h"
+#include "mojo/core/watch.h"
namespace base {
-template<typename T> class ThreadLocalPointer;
+template <typename T>
+class ThreadLocalPointer;
}
namespace mojo {
-namespace edk {
+namespace core {
// A RequestContext is a thread-local object which exists for the duration of
// a single system API call. It is constructed immediately upon EDK entry and
@@ -101,7 +102,7 @@ class MOJO_SYSTEM_IMPL_EXPORT RequestContext {
DISALLOW_COPY_AND_ASSIGN(RequestContext);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_REQUEST_CONTEXT_H_
+#endif // MOJO_CORE_REQUEST_CONTEXT_H_
diff --git a/chromium/mojo/edk/run_all_core_unittests.cc b/chromium/mojo/core/run_all_core_unittests.cc
index 92dcafc9619..92dcafc9619 100644
--- a/chromium/mojo/edk/run_all_core_unittests.cc
+++ b/chromium/mojo/core/run_all_core_unittests.cc
diff --git a/chromium/mojo/core/scoped_process_handle.cc b/chromium/mojo/core/scoped_process_handle.cc
new file mode 100644
index 00000000000..65dfcf78aa6
--- /dev/null
+++ b/chromium/mojo/core/scoped_process_handle.cc
@@ -0,0 +1,90 @@
+// Copyright 2018 The Chromium 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/core/scoped_process_handle.h"
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+namespace mojo {
+namespace core {
+
+namespace {
+
+base::ProcessHandle GetCurrentProcessHandle() {
+#if defined(OS_NACL_NONSFI)
+ // Doesn't really matter, it's not going to be used for anything interesting
+ // under NaCl.
+ return 1;
+#else
+ return base::GetCurrentProcessHandle();
+#endif
+}
+
+} // namespace
+
+ScopedProcessHandle::ScopedProcessHandle() = default;
+
+ScopedProcessHandle::ScopedProcessHandle(base::ProcessHandle handle)
+ : handle_(handle) {
+ DCHECK_NE(handle, GetCurrentProcessHandle());
+}
+
+ScopedProcessHandle::ScopedProcessHandle(ScopedProcessHandle&&) = default;
+
+ScopedProcessHandle::~ScopedProcessHandle() = default;
+
+// static
+ScopedProcessHandle ScopedProcessHandle::CloneFrom(base::ProcessHandle handle) {
+ DCHECK_NE(handle, GetCurrentProcessHandle());
+ if (handle == base::kNullProcessHandle)
+ return ScopedProcessHandle();
+
+#if defined(OS_WIN)
+ BOOL ok = ::DuplicateHandle(GetCurrentProcessHandle(), handle,
+ GetCurrentProcessHandle(), &handle, 0, FALSE,
+ DUPLICATE_SAME_ACCESS);
+ DCHECK(ok);
+#endif
+ return ScopedProcessHandle(handle);
+}
+
+ScopedProcessHandle& ScopedProcessHandle::operator=(ScopedProcessHandle&&) =
+ default;
+
+bool ScopedProcessHandle::is_valid() const {
+#if defined(OS_WIN)
+ return handle_.IsValid();
+#else
+ return handle_ != base::kNullProcessHandle;
+#endif
+}
+
+base::ProcessHandle ScopedProcessHandle::get() const {
+#if defined(OS_WIN)
+ return handle_.Get();
+#else
+ return handle_;
+#endif
+}
+
+base::ProcessHandle ScopedProcessHandle::release() {
+#if defined(OS_WIN)
+ return handle_.Take();
+#else
+ return handle_;
+#endif
+}
+
+ScopedProcessHandle ScopedProcessHandle::Clone() const {
+ if (is_valid())
+ return CloneFrom(get());
+ return ScopedProcessHandle();
+}
+
+} // namespace core
+} // namespace mojo
diff --git a/chromium/mojo/edk/system/scoped_process_handle.h b/chromium/mojo/core/scoped_process_handle.h
index dbefdfe0593..4677145d9f9 100644
--- a/chromium/mojo/edk/system/scoped_process_handle.h
+++ b/chromium/mojo/core/scoped_process_handle.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_SCOPED_PROCESS_HANDLE_H_
-#define MOJO_EDK_SYSTEM_SCOPED_PROCESS_HANDLE_H_
+#ifndef MOJO_CORE_SCOPED_PROCESS_HANDLE_H_
+#define MOJO_CORE_SCOPED_PROCESS_HANDLE_H_
#include "base/macros.h"
#include "base/process/process_handle.h"
@@ -14,7 +14,7 @@
#endif
namespace mojo {
-namespace edk {
+namespace core {
// Wraps a |base::ProcessHandle| with additional scoped lifetime semantics on
// applicable platforms. For platforms where process handles aren't ownable
@@ -23,6 +23,10 @@ namespace edk {
// This essentially exists to support passing around process handles internally
// in a generic way while also supporting Windows process handle ownership
// semantics.
+//
+// A ScopedProcessHandle will never refer to the current process, and
+// constructing a ScopedProcessHandle over the current process's handle is
+// considered an error.
class ScopedProcessHandle {
public:
ScopedProcessHandle();
@@ -39,29 +43,9 @@ class ScopedProcessHandle {
ScopedProcessHandle& operator=(ScopedProcessHandle&&);
- bool is_valid() const {
-#if defined(OS_WIN)
- return handle_.IsValid();
-#else
- return handle_ != base::kNullProcessHandle;
-#endif
- }
-
- base::ProcessHandle get() const {
-#if defined(OS_WIN)
- return handle_.Get();
-#else
- return handle_;
-#endif
- }
-
- base::ProcessHandle release() {
-#if defined(OS_WIN)
- return handle_.Take();
-#else
- return handle_;
-#endif
- }
+ bool is_valid() const;
+ base::ProcessHandle get() const;
+ base::ProcessHandle release();
ScopedProcessHandle Clone() const;
@@ -75,7 +59,7 @@ class ScopedProcessHandle {
DISALLOW_COPY_AND_ASSIGN(ScopedProcessHandle);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_SCOPED_PROCESS_HANDLE_H_
+#endif // MOJO_CORE_SCOPED_PROCESS_HANDLE_H_
diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher.cc b/chromium/mojo/core/shared_buffer_dispatcher.cc
index 73b2c03d624..8a0026ab0e3 100644
--- a/chromium/mojo/edk/system/shared_buffer_dispatcher.cc
+++ b/chromium/mojo/core/shared_buffer_dispatcher.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
+#include "mojo/core/shared_buffer_dispatcher.h"
#include <stddef.h>
#include <stdint.h>
@@ -14,15 +14,15 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_handle_utils.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/edk/system/options_validation.h"
-#include "mojo/edk/system/platform_shared_memory_mapping.h"
+#include "mojo/core/configuration.h"
+#include "mojo/core/node_controller.h"
+#include "mojo/core/options_validation.h"
+#include "mojo/core/platform_handle_utils.h"
+#include "mojo/core/platform_shared_memory_mapping.h"
#include "mojo/public/c/system/platform_handle.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -122,7 +122,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* platform_handles,
+ PlatformHandle* platform_handles,
size_t num_platform_handles) {
if (num_bytes != sizeof(SerializedState)) {
LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)";
@@ -140,8 +140,8 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
if (num_ports)
return nullptr;
- ScopedInternalPlatformHandle handles[2];
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+ PlatformHandle handles[2];
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
(!defined(OS_MACOSX) || defined(OS_IOS))
if (serialized_state->access_mode ==
MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE) {
@@ -176,9 +176,10 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
LOG(ERROR) << "Invalid serialized shared buffer access mode.";
return nullptr;
}
+
auto region = base::subtle::PlatformSharedMemoryRegion::Take(
- CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
- std::move(handles[0]), std::move(handles[1])),
+ CreateSharedMemoryRegionHandleFromPlatformHandles(std::move(handles[0]),
+ std::move(handles[1])),
mode, static_cast<size_t>(serialized_state->num_bytes), guid);
if (!region.IsValid()) {
LOG(ERROR)
@@ -250,7 +251,7 @@ MojoResult SharedBufferDispatcher::DuplicateBufferHandle(
} else if (region_.GetMode() ==
base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
auto handle = region_.PassPlatformHandle();
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
(!defined(OS_MACOSX) || defined(OS_IOS))
// On POSIX systems excluding Android, Fuchsia, and OSX, we explicitly
// wipe out the secondary (read-only) FD from the platform handle to
@@ -311,7 +312,7 @@ void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes,
*num_bytes = sizeof(SerializedState);
*num_ports = 0;
*num_platform_handles = 1;
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
(!defined(OS_MACOSX) || defined(OS_IOS))
if (region_.GetMode() ==
base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
@@ -320,10 +321,9 @@ void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes,
#endif
}
-bool SharedBufferDispatcher::EndSerialize(
- void* destination,
- ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) {
+bool SharedBufferDispatcher::EndSerialize(void* destination,
+ ports::PortName* ports,
+ PlatformHandle* handles) {
SerializedState* serialized_state =
static_cast<SerializedState*>(destination);
base::AutoLock lock(lock_);
@@ -352,19 +352,25 @@ bool SharedBufferDispatcher::EndSerialize(
serialized_state->padding = 0;
auto region = std::move(region_);
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
(!defined(OS_MACOSX) || defined(OS_IOS))
if (region.GetMode() ==
base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
- ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
- region.PassPlatformHandle(), &handles[0], &handles[1]);
+ PlatformHandle platform_handles[2];
+ ExtractPlatformHandlesFromSharedMemoryRegionHandle(
+ region.PassPlatformHandle(), &platform_handles[0],
+ &platform_handles[1]);
+ handles[0] = std::move(platform_handles[0]);
+ handles[1] = std::move(platform_handles[1]);
return true;
}
#endif
- ScopedInternalPlatformHandle ignored_handle;
- ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
- region.PassPlatformHandle(), &handles[0], &ignored_handle);
+ PlatformHandle platform_handle;
+ PlatformHandle ignored_handle;
+ ExtractPlatformHandlesFromSharedMemoryRegionHandle(
+ region.PassPlatformHandle(), &platform_handle, &ignored_handle);
+ handles[0] = std::move(platform_handle);
return true;
}
@@ -435,5 +441,5 @@ MojoResult SharedBufferDispatcher::ValidateDuplicateOptions(
return MOJO_RESULT_OK;
}
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher.h b/chromium/mojo/core/shared_buffer_dispatcher.h
index 30c0dd6f60e..cbdb3533f96 100644
--- a/chromium/mojo/edk/system/shared_buffer_dispatcher.h
+++ b/chromium/mojo/core/shared_buffer_dispatcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
+#ifndef MOJO_CORE_SHARED_BUFFER_DISPATCHER_H_
+#define MOJO_CORE_SHARED_BUFFER_DISPATCHER_H_
#include <stddef.h>
#include <stdint.h>
@@ -12,13 +12,12 @@
#include "base/macros.h"
#include "base/memory/platform_shared_memory_region.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/system_impl_export.h"
namespace mojo {
-namespace edk {
+namespace core {
class NodeController;
class PlatformSharedMemoryMapping;
@@ -60,7 +59,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedInternalPlatformHandle* platform_handles,
+ PlatformHandle* platform_handles,
size_t num_handles);
// Passes the underlying PlatformSharedMemoryRegion. This dispatcher must be
@@ -88,7 +87,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
uint32_t* num_platform_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedInternalPlatformHandle* handles) override;
+ PlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
@@ -119,7 +118,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcher);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
+#endif // MOJO_CORE_SHARED_BUFFER_DISPATCHER_H_
diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/chromium/mojo/core/shared_buffer_dispatcher_unittest.cc
index 768c7aa7475..22cbb44a4ab 100644
--- a/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc
+++ b/chromium/mojo/core/shared_buffer_dispatcher_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
+#include "mojo/core/shared_buffer_dispatcher.h"
#include <stddef.h>
#include <stdint.h>
@@ -13,12 +13,12 @@
#include "base/memory/platform_shared_memory_region.h"
#include "base/memory/ref_counted.h"
#include "base/memory/writable_shared_memory_region.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/platform_shared_memory_mapping.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/platform_shared_memory_mapping.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
// NOTE(vtl): There's currently not much to test for in
@@ -37,9 +37,8 @@ void RevalidateCreateOptions(
// Nothing to check for flags.
MojoCreateSharedBufferOptions revalidated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- SharedBufferDispatcher::ValidateCreateOptions(
- &validated_options, &revalidated_options));
+ EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
+ &validated_options, &revalidated_options));
EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
EXPECT_EQ(validated_options.flags, revalidated_options.flags);
}
@@ -76,9 +75,8 @@ TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsValid) {
flags // |flags|.
};
MojoCreateSharedBufferOptions validated_options = {};
- EXPECT_EQ(MOJO_RESULT_OK,
- SharedBufferDispatcher::ValidateCreateOptions(
- &options, &validated_options))
+ EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
+ &options, &validated_options))
<< capacity;
RevalidateCreateOptions(validated_options);
EXPECT_EQ(options.flags, validated_options.flags);
@@ -95,8 +93,7 @@ TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) {
};
MojoCreateSharedBufferOptions unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- SharedBufferDispatcher::ValidateCreateOptions(
- &options, &unused));
+ SharedBufferDispatcher::ValidateCreateOptions(&options, &unused));
}
// Unknown |flags|.
@@ -107,8 +104,7 @@ TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) {
};
MojoCreateSharedBufferOptions unused;
EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- SharedBufferDispatcher::ValidateCreateOptions(
- &options, &unused));
+ SharedBufferDispatcher::ValidateCreateOptions(&options, &unused));
}
}
@@ -195,8 +191,8 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) {
// Duplicate |dispatcher1| and then close it.
scoped_refptr<Dispatcher> dispatcher2;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle(
- nullptr, &dispatcher2));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ dispatcher1->DuplicateBufferHandle(nullptr, &dispatcher2));
ASSERT_TRUE(dispatcher2);
EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType());
@@ -340,5 +336,5 @@ TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) {
}
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/shared_buffer_unittest.cc b/chromium/mojo/core/shared_buffer_unittest.cc
index 2e09b60059d..58a0b88376c 100644
--- a/chromium/mojo/edk/system/shared_buffer_unittest.cc
+++ b/chromium/mojo/core/shared_buffer_unittest.cc
@@ -10,14 +10,15 @@
#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/strings/string_piece.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/shared_buffer_dispatcher.h"
-#include "mojo/edk/test/mojo_test_base.h"
+#include "build/build_config.h"
+#include "mojo/core/core.h"
+#include "mojo/core/shared_buffer_dispatcher.h"
+#include "mojo/core/test/mojo_test_base.h"
#include "mojo/public/c/system/types.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
using SharedBufferTest = test::MojoTestBase;
@@ -318,5 +319,5 @@ TEST_F(SharedBufferTest, MAYBE_CreateAndPassFromChildReadOnlyBuffer) {
#endif // !defined(OS_IOS)
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/signals_unittest.cc b/chromium/mojo/core/signals_unittest.cc
index 34f2105ea94..2519763250c 100644
--- a/chromium/mojo/edk/system/signals_unittest.cc
+++ b/chromium/mojo/core/signals_unittest.cc
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/test/mojo_test_base.h"
+#include "build/build_config.h"
+#include "mojo/core/test/mojo_test_base.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/functions.h"
@@ -11,7 +12,7 @@
#include "mojo/public/c/system/types.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
using SignalsTest = test::MojoTestBase;
@@ -36,13 +37,17 @@ TEST_F(SignalsTest, QueryMessagePipeSignals) {
EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE,
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED |
+ MOJO_HANDLE_SIGNAL_PEER_REMOTE |
+ MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED,
state.satisfiable_signals);
EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE,
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED |
+ MOJO_HANDLE_SIGNAL_PEER_REMOTE |
+ MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED,
state.satisfiable_signals);
WriteMessage(a, "ok");
@@ -52,7 +57,9 @@ TEST_F(SignalsTest, QueryMessagePipeSignals) {
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
state.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE,
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED |
+ MOJO_HANDLE_SIGNAL_PEER_REMOTE |
+ MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED,
state.satisfiable_signals);
EXPECT_EQ("ok", ReadMessage(b));
@@ -60,7 +67,9 @@ TEST_F(SignalsTest, QueryMessagePipeSignals) {
EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE,
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED |
+ MOJO_HANDLE_SIGNAL_PEER_REMOTE |
+ MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED,
state.satisfiable_signals);
EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
@@ -69,7 +78,8 @@ TEST_F(SignalsTest, QueryMessagePipeSignals) {
EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED,
+ state.satisfiable_signals);
}
TEST_F(SignalsTest, LocalPeers) {
@@ -208,5 +218,5 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(RemotePeersClient, SignalsTest, h) {
#endif // !defined(OS_IOS)
} // namespace
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/system_impl_export.h b/chromium/mojo/core/system_impl_export.h
index 5bbf0057b0d..b55acbc26cc 100644
--- a/chromium/mojo/edk/system/system_impl_export.h
+++ b/chromium/mojo/core/system_impl_export.h
@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_
-#define MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_
+#ifndef MOJO_CORE_SYSTEM_IMPL_EXPORT_H_
+#define MOJO_CORE_SYSTEM_IMPL_EXPORT_H_
+#if defined(MOJO_CORE_SHARED_LIBRARY)
+#define MOJO_SYSTEM_IMPL_EXPORT
+#else
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
@@ -25,5 +28,6 @@
#else // defined(COMPONENT_BUILD)
#define MOJO_SYSTEM_IMPL_EXPORT
#endif
+#endif
-#endif // MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_
+#endif // MOJO_CORE_SYSTEM_IMPL_EXPORT_H_
diff --git a/chromium/mojo/edk/test/BUILD.gn b/chromium/mojo/core/test/BUILD.gn
index 71491d304f8..6fad6fec711 100644
--- a/chromium/mojo/edk/test/BUILD.gn
+++ b/chromium/mojo/core/test/BUILD.gn
@@ -18,16 +18,14 @@ static_library("test_support") {
]
}
- if (is_fuchsia) {
- sources += [ "test_utils_fuchsia.cc" ]
- } else if (is_posix) {
- sources += [ "test_utils_posix.cc" ]
+ if (is_fuchsia || is_posix) {
+ sources += [ "test_utils.cc" ]
}
public_deps = [
"//base",
"//base/test:test_support",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//mojo/public/cpp/system",
"//testing/gtest",
]
@@ -44,7 +42,7 @@ source_set("run_all_unittests") {
":test_support_impl",
"//base",
"//base/test:test_support",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//mojo/public/c/test_support",
"//testing/gtest",
]
@@ -60,8 +58,8 @@ source_set("run_all_perftests") {
":test_support_impl",
"//base",
"//base/test:test_support",
- "//mojo/edk",
- "//mojo/edk/test:test_support",
+ "//mojo/core/embedder",
+ "//mojo/core/test:test_support",
"//mojo/public/c/test_support",
]
diff --git a/chromium/mojo/edk/system/test_utils.cc b/chromium/mojo/core/test_utils.cc
index 4a39cf73dae..33ce9ea0155 100644
--- a/chromium/mojo/edk/system/test_utils.cc
+++ b/chromium/mojo/core/test_utils.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/test_utils.h"
+#include "mojo/core/test_utils.h"
#include <stdint.h>
@@ -14,7 +14,7 @@
#include "build/build_config.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace test {
MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds) {
@@ -54,11 +54,9 @@ void Sleep(MojoDeadline deadline) {
base::TimeDelta::FromMicroseconds(static_cast<int64_t>(deadline)));
}
-Stopwatch::Stopwatch() {
-}
+Stopwatch::Stopwatch() {}
-Stopwatch::~Stopwatch() {
-}
+Stopwatch::~Stopwatch() {}
void Stopwatch::Start() {
start_time_ = base::TimeTicks::Now();
@@ -72,5 +70,5 @@ MojoDeadline Stopwatch::Elapsed() {
}
} // namespace test
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/test_utils.h b/chromium/mojo/core/test_utils.h
index 1c90dc1717c..98ac51e182d 100644
--- a/chromium/mojo/edk/system/test_utils.h
+++ b/chromium/mojo/core/test_utils.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_TEST_UTILS_H_
-#define MOJO_EDK_SYSTEM_TEST_UTILS_H_
+#ifndef MOJO_CORE_TEST_UTILS_H_
+#define MOJO_CORE_TEST_UTILS_H_
#include "base/macros.h"
#include "base/time/time.h"
@@ -11,7 +11,7 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace test {
MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds);
@@ -53,7 +53,7 @@ class Stopwatch {
};
} // namespace test
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_TEST_UTILS_H_
+#endif // MOJO_CORE_TEST_UTILS_H_
diff --git a/chromium/mojo/core/trap_unittest.cc b/chromium/mojo/core/trap_unittest.cc
new file mode 100644
index 00000000000..555726f4da6
--- /dev/null
+++ b/chromium/mojo/core/trap_unittest.cc
@@ -0,0 +1,1763 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <set>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/rand_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/bind_test_util.h"
+#include "base/threading/platform_thread.h"
+#include "base/threading/simple_thread.h"
+#include "base/time/time.h"
+#include "mojo/core/test/mojo_test_base.h"
+#include "mojo/public/c/system/data_pipe.h"
+#include "mojo/public/c/system/trap.h"
+#include "mojo/public/c/system/types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace core {
+namespace {
+
+using TrapTest = test::MojoTestBase;
+
+class TriggerHelper {
+ public:
+ using ContextCallback = base::RepeatingCallback<void(const MojoTrapEvent&)>;
+
+ TriggerHelper() {}
+ ~TriggerHelper() {}
+
+ MojoResult CreateTrap(MojoHandle* handle) {
+ return MojoCreateTrap(&Notify, nullptr, handle);
+ }
+
+ template <typename Handler>
+ uintptr_t CreateContext(Handler handler) {
+ return CreateContextWithCancel(handler, [] {});
+ }
+
+ template <typename Handler, typename CancelHandler>
+ uintptr_t CreateContextWithCancel(Handler handler,
+ CancelHandler cancel_handler) {
+ auto* context =
+ new NotificationContext(base::BindLambdaForTesting(handler));
+ context->SetCancelCallback(
+ base::BindOnce(base::BindLambdaForTesting([cancel_handler, context] {
+ cancel_handler();
+ delete context;
+ })));
+ return reinterpret_cast<uintptr_t>(context);
+ }
+
+ private:
+ class NotificationContext {
+ public:
+ explicit NotificationContext(const ContextCallback& callback)
+ : callback_(callback) {}
+
+ ~NotificationContext() {}
+
+ void SetCancelCallback(base::OnceClosure cancel_callback) {
+ cancel_callback_ = std::move(cancel_callback);
+ }
+
+ void Notify(const MojoTrapEvent& event) {
+ if (event.result == MOJO_RESULT_CANCELLED && cancel_callback_)
+ std::move(cancel_callback_).Run();
+ else
+ callback_.Run(event);
+ }
+
+ private:
+ const ContextCallback callback_;
+ base::OnceClosure cancel_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationContext);
+ };
+
+ static void Notify(const MojoTrapEvent* event) {
+ reinterpret_cast<NotificationContext*>(event->trigger_context)
+ ->Notify(*event);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(TriggerHelper);
+};
+
+class ThreadedRunner : public base::SimpleThread {
+ public:
+ explicit ThreadedRunner(base::OnceClosure callback)
+ : SimpleThread("ThreadedRunner"), callback_(std::move(callback)) {}
+ ~ThreadedRunner() override {}
+
+ void Run() override { std::move(callback_).Run(); }
+
+ private:
+ base::OnceClosure callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadedRunner);
+};
+
+void ExpectNoNotification(const MojoTrapEvent* event) {
+ NOTREACHED();
+}
+
+void ExpectOnlyCancel(const MojoTrapEvent* event) {
+ EXPECT_EQ(event->result, MOJO_RESULT_CANCELLED);
+}
+
+TEST_F(TrapTest, InvalidArguments) {
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoCreateTrap(&ExpectNoNotification, nullptr, nullptr));
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &t));
+
+ // Try to add triggers for handles which don't raise trappable signals.
+ EXPECT_EQ(
+ MOJO_RESULT_INVALID_ARGUMENT,
+ MojoAddTrigger(t, t, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, 0, nullptr));
+ MojoHandle buffer_handle = CreateBuffer(42);
+ EXPECT_EQ(
+ MOJO_RESULT_INVALID_ARGUMENT,
+ MojoAddTrigger(t, buffer_handle, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, 0, nullptr));
+
+ // Try to remove a trigger on a non-trap handle.
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoRemoveTrigger(buffer_handle, 0, nullptr));
+
+ // Try to arm an invalid or non-trap handle.
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoArmTrap(MOJO_HANDLE_INVALID, nullptr, nullptr, nullptr));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoArmTrap(buffer_handle, nullptr, nullptr, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(buffer_handle));
+
+ // Try to arm with a non-null count but a null output buffer.
+ uint32_t num_blocking_events = 1;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoArmTrap(t, nullptr, &num_blocking_events, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+}
+
+TEST_F(TrapTest, TrapMessagePipeReadable) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ int num_expected_notifications = 1;
+ const uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_GT(num_expected_notifications, 0);
+ num_expected_notifications -= 1;
+
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ const char kMessage1[] = "hey hey hey hey";
+ const char kMessage2[] = "i said hey";
+ const char kMessage3[] = "what's goin' on?";
+
+ // Writing to |b| multiple times should notify exactly once.
+ WriteMessage(b, kMessage1);
+ WriteMessage(b, kMessage2);
+ wait.Wait();
+
+ // This also shouldn't fire a notification; the trap is still disarmed.
+ WriteMessage(b, kMessage3);
+
+ // Arming should fail with relevant information.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(readable_a_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+
+ // Flush the three messages from above.
+ EXPECT_EQ(kMessage1, ReadMessage(a));
+ EXPECT_EQ(kMessage2, ReadMessage(a));
+ EXPECT_EQ(kMessage3, ReadMessage(a));
+
+ // Now we can rearm the trap.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+}
+
+TEST_F(TrapTest, CloseWatchedMessagePipeHandle) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ const uintptr_t readable_a_context = helper.CreateContextWithCancel(
+ [](const MojoTrapEvent&) {}, [&] { wait.Signal(); });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+
+ // Test that closing a watched handle fires an appropriate notification, even
+ // when the trap is unarmed.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+}
+
+TEST_F(TrapTest, CloseWatchedMessagePipeHandlePeer) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ const uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, event.result);
+ wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+
+ // Test that closing a watched handle's peer with an armed trap fires an
+ // appropriate notification.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ wait.Wait();
+
+ // And now arming should fail with correct information about |a|'s state.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(readable_a_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, blocking_events[0].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+ EXPECT_FALSE(blocking_events[0].signals_state.satisfiable_signals &
+ MOJO_HANDLE_SIGNAL_READABLE);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+}
+
+TEST_F(TrapTest, TrapDataPipeConsumerReadable) {
+ constexpr size_t kTestPipeCapacity = 64;
+ MojoHandle producer, consumer;
+ CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ int num_expected_notifications = 1;
+ const uintptr_t readable_consumer_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_GT(num_expected_notifications, 0);
+ num_expected_notifications -= 1;
+
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, consumer, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_consumer_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ const char kMessage1[] = "hey hey hey hey";
+ const char kMessage2[] = "i said hey";
+ const char kMessage3[] = "what's goin' on?";
+
+ // Writing to |producer| multiple times should notify exactly once.
+ WriteData(producer, kMessage1);
+ WriteData(producer, kMessage2);
+ wait.Wait();
+
+ // This also shouldn't fire a notification; the trap is still disarmed.
+ WriteData(producer, kMessage3);
+
+ // Arming should fail with relevant information.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(readable_consumer_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+
+ // Flush the three messages from above.
+ EXPECT_EQ(kMessage1, ReadData(consumer, sizeof(kMessage1) - 1));
+ EXPECT_EQ(kMessage2, ReadData(consumer, sizeof(kMessage2) - 1));
+ EXPECT_EQ(kMessage3, ReadData(consumer, sizeof(kMessage3) - 1));
+
+ // Now we can rearm the trap.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
+}
+
+TEST_F(TrapTest, TrapDataPipeConsumerNewDataReadable) {
+ constexpr size_t kTestPipeCapacity = 64;
+ MojoHandle producer, consumer;
+ CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ int num_new_data_notifications = 0;
+ const uintptr_t new_data_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ num_new_data_notifications += 1;
+
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, consumer, MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ new_data_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ const char kMessage1[] = "hey hey hey hey";
+ const char kMessage2[] = "i said hey";
+ const char kMessage3[] = "what's goin' on?";
+
+ // Writing to |producer| multiple times should notify exactly once.
+ WriteData(producer, kMessage1);
+ WriteData(producer, kMessage2);
+ wait.Wait();
+
+ // This also shouldn't fire a notification; the trap is still disarmed.
+ WriteData(producer, kMessage3);
+
+ // Arming should fail with relevant information.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(new_data_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+
+ // Attempt to read more data than is available. Should fail but clear the
+ // NEW_DATA_READABLE signal.
+ char large_buffer[512];
+ uint32_t large_read_size = 512;
+ MojoReadDataOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = MOJO_READ_DATA_FLAG_ALL_OR_NONE;
+ EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
+ MojoReadData(consumer, &options, large_buffer, &large_read_size));
+
+ // Attempt to arm again. Should succeed.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Write more data. Should notify.
+ wait.Reset();
+ WriteData(producer, kMessage1);
+ wait.Wait();
+
+ // Reading some data should clear NEW_DATA_READABLE again so we can rearm.
+ EXPECT_EQ(kMessage1, ReadData(consumer, sizeof(kMessage1) - 1));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ EXPECT_EQ(2, num_new_data_notifications);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
+}
+
+TEST_F(TrapTest, TrapDataPipeProducerWritable) {
+ constexpr size_t kTestPipeCapacity = 8;
+ MojoHandle producer, consumer;
+ CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
+
+ // Half the capacity of the data pipe.
+ const char kTestData[] = "aaaa";
+ static_assert((sizeof(kTestData) - 1) * 2 == kTestPipeCapacity,
+ "Invalid test data for this test.");
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ int num_expected_notifications = 1;
+ const uintptr_t writable_producer_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_GT(num_expected_notifications, 0);
+ num_expected_notifications -= 1;
+
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, producer, MOJO_HANDLE_SIGNAL_WRITABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ writable_producer_context, nullptr));
+
+ // The producer is already writable, so arming should fail with relevant
+ // information.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(writable_producer_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+
+ // Write some data, but don't fill the pipe yet. Arming should fail again.
+ WriteData(producer, kTestData);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(writable_producer_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+
+ // Write more data, filling the pipe to capacity. Arming should succeed now.
+ WriteData(producer, kTestData);
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Now read from the pipe, making the producer writable again. Should notify.
+ EXPECT_EQ(kTestData, ReadData(consumer, sizeof(kTestData) - 1));
+ wait.Wait();
+
+ // Arming should fail again.
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(writable_producer_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+
+ // Fill the pipe once more and arm the trap. Should succeed.
+ WriteData(producer, kTestData);
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
+};
+
+TEST_F(TrapTest, CloseWatchedDataPipeConsumerHandle) {
+ constexpr size_t kTestPipeCapacity = 8;
+ MojoHandle producer, consumer;
+ CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ const uintptr_t readable_consumer_context = helper.CreateContextWithCancel(
+ [](const MojoTrapEvent&) {}, [&] { wait.Signal(); });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, consumer, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_consumer_context, nullptr));
+
+ // Closing the consumer should fire a cancellation notification.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+}
+
+TEST_F(TrapTest, CloseWatchedDataPipeConsumerHandlePeer) {
+ constexpr size_t kTestPipeCapacity = 8;
+ MojoHandle producer, consumer;
+ CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ const uintptr_t readable_consumer_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, event.result);
+ wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, consumer, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_consumer_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Closing the producer should fire a notification for an unsatisfiable
+ // condition.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
+ wait.Wait();
+
+ // Now attempt to rearm and expect appropriate error feedback.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(readable_consumer_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, blocking_events[0].result);
+ EXPECT_FALSE(blocking_events[0].signals_state.satisfiable_signals &
+ MOJO_HANDLE_SIGNAL_READABLE);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
+}
+
+TEST_F(TrapTest, CloseWatchedDataPipeProducerHandle) {
+ constexpr size_t kTestPipeCapacity = 8;
+ MojoHandle producer, consumer;
+ CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ const uintptr_t writable_producer_context = helper.CreateContextWithCancel(
+ [](const MojoTrapEvent&) {}, [&] { wait.Signal(); });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, producer, MOJO_HANDLE_SIGNAL_WRITABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ writable_producer_context, nullptr));
+
+ // Closing the consumer should fire a cancellation notification.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+}
+
+TEST_F(TrapTest, CloseWatchedDataPipeProducerHandlePeer) {
+ constexpr size_t kTestPipeCapacity = 8;
+ MojoHandle producer, consumer;
+ CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
+
+ const char kTestMessageFullCapacity[] = "xxxxxxxx";
+ static_assert(sizeof(kTestMessageFullCapacity) - 1 == kTestPipeCapacity,
+ "Invalid test message size for this test.");
+
+ // Make the pipe unwritable initially.
+ WriteData(producer, kTestMessageFullCapacity);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ const uintptr_t writable_producer_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, event.result);
+ wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, producer, MOJO_HANDLE_SIGNAL_WRITABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ writable_producer_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Closing the consumer should fire a notification for an unsatisfiable
+ // condition, as the full data pipe can never be read from again and is
+ // therefore permanently full and unwritable.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
+ wait.Wait();
+
+ // Now attempt to rearm and expect appropriate error feedback.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(writable_producer_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, blocking_events[0].result);
+ EXPECT_FALSE(blocking_events[0].signals_state.satisfiable_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
+}
+
+TEST_F(TrapTest, ArmWithNoTriggers) {
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &t));
+ EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoArmTrap(t, nullptr, nullptr, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+}
+
+TEST_F(TrapTest, DuplicateTriggerContext) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &t));
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, 0, nullptr));
+ EXPECT_EQ(
+ MOJO_RESULT_ALREADY_EXISTS,
+ MojoAddTrigger(t, b, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, 0, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+}
+
+TEST_F(TrapTest, RemoveUnknownTrigger) {
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &t));
+ EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoRemoveTrigger(t, 1234, nullptr));
+}
+
+TEST_F(TrapTest, ArmWithTriggerConditionAlreadySatisfied) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &t));
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_WRITABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, 0, nullptr));
+
+ // |a| is always writable, so we can never arm this trap.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(0u, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+}
+
+TEST_F(TrapTest, ArmWithTriggerConditionAlreadyUnsatisfiable) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &t));
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, 0, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+
+ // |b| is closed and never wrote any messages, so |a| won't be readable again.
+ // MojoArmTrap() should fail, incidcating as much.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = kMaxBlockingEvents;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(0u, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, blocking_events[0].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+ EXPECT_FALSE(blocking_events[0].signals_state.satisfiable_signals &
+ MOJO_HANDLE_SIGNAL_READABLE);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+}
+
+TEST_F(TrapTest, MultipleTriggers) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ base::WaitableEvent a_wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ base::WaitableEvent b_wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ int num_a_notifications = 0;
+ int num_b_notifications = 0;
+ uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ num_a_notifications += 1;
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ a_wait.Signal();
+ });
+ uintptr_t readable_b_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ num_b_notifications += 1;
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ b_wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ // Add two independent triggers to trap |a| or |b| readability.
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, b, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_b_context, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ const char kMessage1[] = "things are happening";
+ const char kMessage2[] = "ok. ok. ok. ok.";
+ const char kMessage3[] = "plz wake up";
+
+ // Writing to |b| should signal |a|'s watch.
+ WriteMessage(b, kMessage1);
+ a_wait.Wait();
+ a_wait.Reset();
+
+ // Subsequent messages on |b| should not trigger another notification.
+ WriteMessage(b, kMessage2);
+ WriteMessage(b, kMessage3);
+
+ // Messages on |a| also shouldn't trigger |b|'s notification, since the
+ // trap should be disarmed by now.
+ WriteMessage(a, kMessage1);
+ WriteMessage(a, kMessage2);
+ WriteMessage(a, kMessage3);
+
+ // Arming should fail. Since we only ask for at most one context's information
+ // that's all we should get back. Which one we get is unspecified.
+ constexpr size_t kMaxBlockingEvents = 3;
+ uint32_t num_blocking_events = 1;
+ MojoTrapEvent blocking_events[kMaxBlockingEvents] = {
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])},
+ {sizeof(blocking_events[0])}};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_TRUE(blocking_events[0].trigger_context == readable_a_context ||
+ blocking_events[0].trigger_context == readable_b_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+
+ // Now try arming again, verifying that both contexts are returned.
+ num_blocking_events = kMaxBlockingEvents;
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(2u, num_blocking_events);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[1].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+ EXPECT_TRUE(blocking_events[1].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+ EXPECT_TRUE((blocking_events[0].trigger_context == readable_a_context &&
+ blocking_events[1].trigger_context == readable_b_context) ||
+ (blocking_events[0].trigger_context == readable_b_context &&
+ blocking_events[1].trigger_context == readable_a_context));
+
+ // Flush out the test messages so we should be able to successfully rearm.
+ EXPECT_EQ(kMessage1, ReadMessage(a));
+ EXPECT_EQ(kMessage2, ReadMessage(a));
+ EXPECT_EQ(kMessage3, ReadMessage(a));
+ EXPECT_EQ(kMessage1, ReadMessage(b));
+ EXPECT_EQ(kMessage2, ReadMessage(b));
+ EXPECT_EQ(kMessage3, ReadMessage(b));
+
+ // Add a trigger whose condition is always satisfied so we can't arm. Arming
+ // should fail with only this new watch's information.
+ uintptr_t writable_c_context =
+ helper.CreateContext([](const MojoTrapEvent&) { NOTREACHED(); });
+ MojoHandle c, d;
+ CreateMessagePipe(&c, &d);
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, c, MOJO_HANDLE_SIGNAL_WRITABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ writable_c_context, nullptr));
+ num_blocking_events = kMaxBlockingEvents;
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_events[0]));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(writable_c_context, blocking_events[0].trigger_context);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_events[0].result);
+ EXPECT_TRUE(blocking_events[0].signals_state.satisfied_signals &
+ MOJO_HANDLE_SIGNAL_WRITABLE);
+
+ // Remove the new trigger and arming should succeed once again.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoRemoveTrigger(t, writable_c_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
+}
+
+TEST_F(TrapTest, ActivateOtherTriggerFromEventHandler) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ static const char kTestMessageToA[] = "hello a";
+ static const char kTestMessageToB[] = "hello b";
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ TriggerHelper helper;
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ("hello a", ReadMessage(a));
+
+ // Re-arm the trap and signal |b|.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+ WriteMessage(a, kTestMessageToB);
+ });
+
+ uintptr_t readable_b_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToB, ReadMessage(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+ wait.Signal();
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, b, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_b_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Send a message to |a|. The relevant trigger should be notified and the
+ // event handler should send a message to |b|, in turn notifying the other
+ // trigger. The second event handler will signal |wait|.
+ WriteMessage(b, kTestMessageToA);
+ wait.Wait();
+}
+
+TEST_F(TrapTest, ActivateSameTriggerFromEventHandler) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ static const char kTestMessageToA[] = "hello a";
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ TriggerHelper helper;
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ int expected_notifications = 10;
+ uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ("hello a", ReadMessage(a));
+
+ EXPECT_GT(expected_notifications, 0);
+ expected_notifications -= 1;
+ if (expected_notifications == 0) {
+ wait.Signal();
+ return;
+ } else {
+ // Re-arm the trap and signal |a| again.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+ WriteMessage(b, kTestMessageToA);
+ }
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Send a message to |a|. When the trigger above is activated, the event
+ // handler will rearm the trap and send another message to |a|. This will
+ // happen until |expected_notifications| reaches 0.
+ WriteMessage(b, kTestMessageToA);
+ wait.Wait();
+}
+
+TEST_F(TrapTest, ImplicitRemoveOtherTriggerWithinEventHandler) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ MojoHandle c, d;
+ CreateMessagePipe(&c, &d);
+
+ static const char kTestMessageToA[] = "hi a";
+ static const char kTestMessageToC[] = "hi c";
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ TriggerHelper helper;
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ uintptr_t readable_a_context = helper.CreateContextWithCancel(
+ [](const MojoTrapEvent&) { NOTREACHED(); }, [&] { wait.Signal(); });
+
+ uintptr_t readable_c_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToC, ReadMessage(c));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Must result in exactly ONE notification from the above trigger, for
+ // CANCELLED only. Because we cannot dispatch notifications until the
+ // stack unwinds, and because we must never dispatch non-cancellation
+ // notifications for a handle once it's been closed, we must be certain
+ // that cancellation due to closure preemptively invalidates any
+ // pending non-cancellation notifications queued on the current
+ // RequestContext, such as the one resulting from the WriteMessage here.
+ WriteMessage(b, kTestMessageToA);
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+
+ // Rearming should be fine since |a|'s trigger should already be
+ // implicitly removed (even though the notification will not have
+ // been invoked yet.)
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Nothing interesting should happen as a result of this.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, c, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_c_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ WriteMessage(d, kTestMessageToC);
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
+}
+
+TEST_F(TrapTest, ExplicitRemoveOtherTriggerWithinEventHandler) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ MojoHandle c, d;
+ CreateMessagePipe(&c, &d);
+
+ static const char kTestMessageToA[] = "hi a";
+ static const char kTestMessageToC[] = "hi c";
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ TriggerHelper helper;
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ uintptr_t readable_a_context =
+ helper.CreateContext([](const MojoTrapEvent&) { NOTREACHED(); });
+
+ uintptr_t readable_c_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToC, ReadMessage(c));
+
+ // Now rearm the trap.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Should result in no notifications from the above trigger, because the
+ // trigger will have been removed by the time the event handler can
+ // execute.
+ WriteMessage(b, kTestMessageToA);
+ WriteMessage(b, kTestMessageToA);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoRemoveTrigger(t, readable_a_context, nullptr));
+
+ // Rearming should be fine now.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // Nothing interesting should happen as a result of these.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+
+ wait.Signal();
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, c, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_c_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ WriteMessage(d, kTestMessageToC);
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
+}
+
+TEST_F(TrapTest, NestedCancellation) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ MojoHandle c, d;
+ CreateMessagePipe(&c, &d);
+
+ static const char kTestMessageToA[] = "hey a";
+ static const char kTestMessageToC[] = "hey c";
+ static const char kTestMessageToD[] = "hey d";
+
+ // This is a tricky test. It establishes a trigger on |b| using one trap and
+ // triggers on |c| and |d| using another trap.
+ //
+ // A message is written to |d| to activate |c|'s trigger, and the resuling
+ // event handler invocation does the folllowing:
+ // 1. Writes to |a| to eventually activate |b|'s trigger.
+ // 2. Rearms |c|'s trap.
+ // 3. Writes to |d| to eventually activate |c|'s trigger again.
+ //
+ // Meanwhile, |b|'s event handler removes |c|'s trigger altogether before
+ // writing to |c| to activate |d|'s trigger.
+ //
+ // The net result should be that |c|'s trigger only gets activated once (from
+ // the first write to |d| above) and everyone else gets notified as expected.
+
+ MojoHandle b_trap;
+ MojoHandle cd_trap;
+ TriggerHelper helper;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&b_trap));
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&cd_trap));
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ uintptr_t readable_d_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToD, ReadMessage(d));
+ wait.Signal();
+ });
+
+ int num_expected_c_notifications = 1;
+ uintptr_t readable_c_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_GT(num_expected_c_notifications--, 0);
+
+ // Trigger an eventual |readable_b_context| notification.
+ WriteMessage(a, kTestMessageToA);
+
+ EXPECT_EQ(kTestMessageToC, ReadMessage(c));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoArmTrap(cd_trap, nullptr, nullptr, nullptr));
+
+ // Trigger another eventual |readable_c_context| notification.
+ WriteMessage(d, kTestMessageToC);
+ });
+
+ uintptr_t readable_b_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoRemoveTrigger(cd_trap, readable_c_context, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoArmTrap(cd_trap, nullptr, nullptr, nullptr));
+
+ WriteMessage(c, kTestMessageToD);
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(b_trap, b, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_b_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(cd_trap, c, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_c_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(cd_trap, d, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_d_context, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(b_trap, nullptr, nullptr, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(cd_trap, nullptr, nullptr, nullptr));
+
+ WriteMessage(d, kTestMessageToC);
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(cd_trap));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b_trap));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
+}
+
+TEST_F(TrapTest, RemoveSelfWithinEventHandler) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ static const char kTestMessageToA[] = "hey a";
+
+ MojoHandle t;
+ TriggerHelper helper;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ static uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+
+ // There should be no problem removing this trigger from its own
+ // notification invocation.
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoRemoveTrigger(t, readable_a_context, nullptr));
+ EXPECT_EQ(kTestMessageToA, ReadMessage(a));
+
+ // Arming should fail because there are no longer any registered
+ // triggers on the trap.
+ EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
+ MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // And closing |a| should be fine (and should not invoke this
+ // notification with MOJO_RESULT_CANCELLED) for the same reason.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+
+ wait.Signal();
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ WriteMessage(b, kTestMessageToA);
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+}
+
+TEST_F(TrapTest, CloseTrapWithinEventHandler) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ static const char kTestMessageToA1[] = "hey a";
+ static const char kTestMessageToA2[] = "hey a again";
+
+ MojoHandle t;
+ TriggerHelper helper;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToA1, ReadMessage(a));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // There should be no problem closing this trap from its own
+ // notification callback.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+
+ // And these should not trigger more notifications, because |t| has been
+ // closed already.
+ WriteMessage(b, kTestMessageToA2);
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+
+ wait.Signal();
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ WriteMessage(b, kTestMessageToA1);
+ wait.Wait();
+}
+
+TEST_F(TrapTest, CloseTrapAfterImplicitTriggerRemoval) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ static const char kTestMessageToA[] = "hey a";
+
+ MojoHandle t;
+ TriggerHelper helper;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToA, ReadMessage(a));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // This will cue up a notification for |MOJO_RESULT_CANCELLED|...
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+
+ // ...but it should never fire because we close the trap here.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+
+ wait.Signal();
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ WriteMessage(b, kTestMessageToA);
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+}
+
+TEST_F(TrapTest, OtherThreadRemovesTriggerDuringEventHandler) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ static const char kTestMessageToA[] = "hey a";
+
+ MojoHandle t;
+ TriggerHelper helper;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ base::WaitableEvent wait_for_notification(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ base::WaitableEvent wait_for_cancellation(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ static bool callback_done = false;
+ uintptr_t readable_a_context = helper.CreateContextWithCancel(
+ [&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToA, ReadMessage(a));
+
+ wait_for_notification.Signal();
+
+ // Give the other thread sufficient time to race with the completion
+ // of this callback. There should be no race, since the cancellation
+ // notification must be mutually exclusive to this notification.
+ base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
+
+ callback_done = true;
+ },
+ [&] {
+ EXPECT_TRUE(callback_done);
+ wait_for_cancellation.Signal();
+ });
+
+ ThreadedRunner runner(base::BindOnce(base::BindLambdaForTesting([&] {
+ wait_for_notification.Wait();
+
+ // Cancel the watch while the notification is still running.
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoRemoveTrigger(t, readable_a_context, nullptr));
+
+ wait_for_cancellation.Wait();
+
+ EXPECT_TRUE(callback_done);
+ })));
+ runner.Start();
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ WriteMessage(b, kTestMessageToA);
+ runner.Join();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+}
+
+TEST_F(TrapTest, TriggersRemoveEachOtherWithinEventHandlers) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ static const char kTestMessageToA[] = "hey a";
+ static const char kTestMessageToB[] = "hey b";
+
+ base::WaitableEvent wait_for_a_to_notify(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ base::WaitableEvent wait_for_b_to_notify(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ base::WaitableEvent wait_for_a_to_cancel(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ base::WaitableEvent wait_for_b_to_cancel(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ MojoHandle a_trap;
+ MojoHandle b_trap;
+ TriggerHelper helper;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&a_trap));
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&b_trap));
+
+ // We set up two traps, one triggered on |a| readability and one triggered on
+ // |b| readability. Each removes the other's trigger from within its own event
+ // handler. This should be safe, i.e., it should not deadlock in spite of the
+ // fact that we also guarantee mutually exclusive event handler invocation
+ // (including cancellations) on any given trap.
+ bool a_cancelled = false;
+ bool b_cancelled = false;
+ static uintptr_t readable_b_context;
+ uintptr_t readable_a_context = helper.CreateContextWithCancel(
+ [&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToA, ReadMessage(a));
+ wait_for_a_to_notify.Signal();
+ wait_for_b_to_notify.Wait();
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoRemoveTrigger(b_trap, readable_b_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b_trap));
+ },
+ [&] {
+ a_cancelled = true;
+ wait_for_a_to_cancel.Signal();
+ wait_for_b_to_cancel.Wait();
+ });
+
+ readable_b_context = helper.CreateContextWithCancel(
+ [&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ EXPECT_EQ(kTestMessageToB, ReadMessage(b));
+ wait_for_b_to_notify.Signal();
+ wait_for_a_to_notify.Wait();
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoRemoveTrigger(a_trap, readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a_trap));
+ },
+ [&] {
+ b_cancelled = true;
+ wait_for_b_to_cancel.Signal();
+ wait_for_a_to_cancel.Wait();
+ });
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(a_trap, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(a_trap, nullptr, nullptr, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(b_trap, b, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_b_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(b_trap, nullptr, nullptr, nullptr));
+
+ ThreadedRunner runner(base::BindOnce(
+ [](MojoHandle b) { WriteMessage(b, kTestMessageToA); }, b));
+ runner.Start();
+
+ WriteMessage(a, kTestMessageToB);
+
+ wait_for_a_to_cancel.Wait();
+ wait_for_b_to_cancel.Wait();
+ runner.Join();
+
+ EXPECT_TRUE(a_cancelled);
+ EXPECT_TRUE(b_cancelled);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+}
+
+TEST_F(TrapTest, AlwaysCancel) {
+ // Basic sanity check to ensure that all possible ways to remove a trigger
+ // result in a final MOJO_RESULT_CANCELLED notification.
+
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ MojoHandle t;
+ TriggerHelper helper;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ auto ignore_event = [](const MojoTrapEvent&) {};
+ auto signal_wait = [&] { wait.Signal(); };
+
+ // Cancel via |MojoRemoveTrigger()|.
+ uintptr_t context = helper.CreateContextWithCancel(ignore_event, signal_wait);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, context,
+ nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoRemoveTrigger(t, context, nullptr));
+ wait.Wait();
+ wait.Reset();
+
+ // Cancel by closing the trigger's watched handle.
+ context = helper.CreateContextWithCancel(ignore_event, signal_wait);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, context,
+ nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+ wait.Wait();
+ wait.Reset();
+
+ // Cancel by closing the trap handle.
+ context = helper.CreateContextWithCancel(ignore_event, signal_wait);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, b, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, context,
+ nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+}
+
+TEST_F(TrapTest, ArmFailureCirculation) {
+ // Sanity check to ensure that all ready trigger events will eventually be
+ // returned over a finite number of calls to MojoArmTrap().
+
+ constexpr size_t kNumTestPipes = 100;
+ constexpr size_t kNumTestHandles = kNumTestPipes * 2;
+ MojoHandle handles[kNumTestHandles];
+
+ // Create a bunch of pipes and make sure they're all readable.
+ for (size_t i = 0; i < kNumTestPipes; ++i) {
+ CreateMessagePipe(&handles[i], &handles[i + kNumTestPipes]);
+ WriteMessage(handles[i], "hey");
+ WriteMessage(handles[i + kNumTestPipes], "hay");
+ WaitForSignals(handles[i], MOJO_HANDLE_SIGNAL_READABLE);
+ WaitForSignals(handles[i + kNumTestPipes], MOJO_HANDLE_SIGNAL_READABLE);
+ }
+
+ // Create a trap and watch all of them for readability.
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &t));
+ for (size_t i = 0; i < kNumTestHandles; ++i) {
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoAddTrigger(t, handles[i], MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, i, nullptr));
+ }
+
+ // Keep trying to arm |t| until every trigger gets an entry in
+ // |ready_contexts|. If MojoArmTrap() is well-behaved, this should terminate
+ // eventually.
+ std::set<uintptr_t> ready_contexts;
+ while (ready_contexts.size() < kNumTestHandles) {
+ uint32_t num_blocking_events = 1;
+ MojoTrapEvent blocking_event = {sizeof(blocking_event)};
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoArmTrap(t, nullptr, &num_blocking_events, &blocking_event));
+ EXPECT_EQ(1u, num_blocking_events);
+ EXPECT_EQ(MOJO_RESULT_OK, blocking_event.result);
+ ready_contexts.insert(blocking_event.trigger_context);
+ }
+
+ for (size_t i = 0; i < kNumTestHandles; ++i)
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[i]));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+}
+
+TEST_F(TrapTest, TriggerOnUnsatisfiedSignals) {
+ MojoHandle a, b;
+ CreateMessagePipe(&a, &b);
+
+ base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ TriggerHelper helper;
+ const uintptr_t readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ wait.Signal();
+ });
+
+ MojoHandle t;
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ const char kMessage[] = "this is not a message";
+
+ WriteMessage(b, kMessage);
+ wait.Wait();
+
+ // Now we know |a| is readable. Remove the trigger and add a new one to watch
+ // for a not-readable state.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ const uintptr_t not_readable_a_context =
+ helper.CreateContext([&](const MojoTrapEvent& event) {
+ EXPECT_EQ(MOJO_RESULT_OK, event.result);
+ wait.Signal();
+ });
+ EXPECT_EQ(MOJO_RESULT_OK, helper.CreateTrap(&t));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED,
+ not_readable_a_context, nullptr));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(t, nullptr, nullptr, nullptr));
+
+ // This should not block, because the event should be signaled by
+ // |not_readable_a_context| when we read the only available message off of
+ // |a|.
+ wait.Reset();
+ EXPECT_EQ(kMessage, ReadMessage(a));
+ wait.Wait();
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(t));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+}
+
+base::Closure g_do_random_thing_callback;
+
+void ReadAllMessages(const MojoTrapEvent* event) {
+ if (event->result == MOJO_RESULT_OK) {
+ MojoHandle handle = static_cast<MojoHandle>(event->trigger_context);
+ MojoMessageHandle message;
+ while (MojoReadMessage(handle, nullptr, &message) == MOJO_RESULT_OK)
+ MojoDestroyMessage(message);
+ }
+
+ constexpr size_t kNumRandomThingsToDoOnNotify = 5;
+ for (size_t i = 0; i < kNumRandomThingsToDoOnNotify; ++i)
+ g_do_random_thing_callback.Run();
+}
+
+MojoHandle RandomHandle(MojoHandle* handles, size_t size) {
+ return handles[base::RandInt(0, static_cast<int>(size) - 1)];
+}
+
+void DoRandomThing(MojoHandle* traps,
+ size_t num_traps,
+ MojoHandle* watched_handles,
+ size_t num_watched_handles) {
+ switch (base::RandInt(0, 10)) {
+ case 0:
+ MojoClose(RandomHandle(traps, num_traps));
+ break;
+ case 1:
+ MojoClose(RandomHandle(watched_handles, num_watched_handles));
+ break;
+ case 2:
+ case 3:
+ case 4: {
+ MojoMessageHandle message;
+ ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoSetMessageContext(message, 1, nullptr, nullptr, nullptr));
+ MojoWriteMessage(RandomHandle(watched_handles, num_watched_handles),
+ message, nullptr);
+ break;
+ }
+ case 5:
+ case 6: {
+ MojoHandle t = RandomHandle(traps, num_traps);
+ MojoHandle h = RandomHandle(watched_handles, num_watched_handles);
+ MojoAddTrigger(t, h, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ static_cast<uintptr_t>(h), nullptr);
+ break;
+ }
+ case 7:
+ case 8: {
+ uint32_t num_blocking_events = 1;
+ MojoTrapEvent blocking_event = {sizeof(blocking_event)};
+ if (MojoArmTrap(RandomHandle(traps, num_traps), nullptr,
+ &num_blocking_events,
+ &blocking_event) == MOJO_RESULT_FAILED_PRECONDITION &&
+ blocking_event.result == MOJO_RESULT_OK) {
+ ReadAllMessages(&blocking_event);
+ }
+ break;
+ }
+ case 9:
+ case 10: {
+ MojoHandle t = RandomHandle(traps, num_traps);
+ MojoHandle h = RandomHandle(watched_handles, num_watched_handles);
+ MojoRemoveTrigger(t, static_cast<uintptr_t>(h), nullptr);
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+TEST_F(TrapTest, ConcurrencyStressTest) {
+ // Regression test for https://crbug.com/740044. Exercises racy usage of the
+ // trap API to weed out potential crashes.
+
+ constexpr size_t kNumTraps = 50;
+ constexpr size_t kNumWatchedHandles = 50;
+ static_assert(kNumWatchedHandles % 2 == 0, "Invalid number of test handles.");
+
+ constexpr size_t kNumThreads = 10;
+ static constexpr size_t kNumOperationsPerThread = 400;
+
+ MojoHandle traps[kNumTraps];
+ MojoHandle watched_handles[kNumWatchedHandles];
+ g_do_random_thing_callback = base::BindRepeating(
+ &DoRandomThing, traps, kNumTraps, watched_handles, kNumWatchedHandles);
+
+ for (size_t i = 0; i < kNumTraps; ++i)
+ MojoCreateTrap(&ReadAllMessages, nullptr, &traps[i]);
+ for (size_t i = 0; i < kNumWatchedHandles; i += 2)
+ CreateMessagePipe(&watched_handles[i], &watched_handles[i + 1]);
+
+ std::unique_ptr<ThreadedRunner> threads[kNumThreads];
+ for (size_t i = 0; i < kNumThreads; ++i) {
+ threads[i] = std::make_unique<ThreadedRunner>(base::BindOnce([] {
+ for (size_t i = 0; i < kNumOperationsPerThread; ++i)
+ g_do_random_thing_callback.Run();
+ }));
+ threads[i]->Start();
+ }
+ for (size_t i = 0; i < kNumThreads; ++i)
+ threads[i]->Join();
+ for (size_t i = 0; i < kNumTraps; ++i)
+ MojoClose(traps[i]);
+ for (size_t i = 0; i < kNumWatchedHandles; ++i)
+ MojoClose(watched_handles[i]);
+}
+
+} // namespace
+} // namespace core
+} // namespace mojo
diff --git a/chromium/mojo/edk/system/user_message_impl.cc b/chromium/mojo/core/user_message_impl.cc
index dc36c1f99e7..d4a4da16a23 100644
--- a/chromium/mojo/edk/system/user_message_impl.cc
+++ b/chromium/mojo/core/user_message_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/user_message_impl.h"
+#include "mojo/core/user_message_impl.h"
#include <algorithm>
#include <vector>
@@ -17,16 +17,16 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/trace_event.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/node_channel.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/message_filter.h"
-#include "mojo/edk/system/ports/node.h"
+#include "mojo/core/core.h"
+#include "mojo/core/node_channel.h"
+#include "mojo/core/node_controller.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/message_filter.h"
+#include "mojo/core/ports/node.h"
#include "mojo/public/c/system/types.h"
namespace mojo {
-namespace edk {
+namespace core {
namespace {
@@ -152,7 +152,7 @@ MojoResult CreateOrExtendSerializedEventMessage(
DispatcherHeader* new_dispatcher_headers;
char* new_dispatcher_data;
size_t total_num_dispatchers = num_new_dispatchers;
- std::vector<ScopedInternalPlatformHandle> handles;
+ std::vector<PlatformHandle> handles;
if (original_message) {
DCHECK(original_header);
size_t original_dispatcher_headers_size =
@@ -176,9 +176,12 @@ MojoResult CreateOrExtendSerializedEventMessage(
memcpy(dispatcher_data, original_dispatcher_data,
original_dispatcher_data_size);
new_dispatcher_data = dispatcher_data + original_dispatcher_data_size;
- handles = original_message->TakeHandles();
- if (!handles.empty())
+ auto handles_in_transit = original_message->TakeHandles();
+ if (!handles_in_transit.empty()) {
handles.resize(num_handles);
+ for (size_t i = 0; i < handles_in_transit.size(); ++i)
+ handles[i] = handles_in_transit[i].TakeHandle();
+ }
memcpy(reinterpret_cast<char*>(header) + header_size,
reinterpret_cast<char*>(original_header) + original_header_size,
original_payload_size);
@@ -190,9 +193,8 @@ MojoResult CreateOrExtendSerializedEventMessage(
reinterpret_cast<char*>(new_dispatcher_headers + num_new_dispatchers);
}
- if (handles.empty() && num_new_handles) {
+ if (handles.empty() && num_new_handles)
handles.resize(num_new_handles);
- }
header->num_dispatchers =
base::CheckedNumeric<uint32_t>(total_num_dispatchers).ValueOrDie();
@@ -240,7 +242,7 @@ MojoResult CreateOrExtendSerializedEventMessage(
// retain ownership when message creation fails, so these are not actually
// leaking.
for (auto& handle : handles)
- ignore_result(handle.release());
+ handle.release();
// Leave the original message in place on failure if applicable.
if (original_message)
@@ -582,8 +584,13 @@ MojoResult UserMessageImpl::ExtractSerializedHandles(
dispatcher_headers + header->num_dispatchers);
size_t port_index = 0;
size_t platform_handle_index = 0;
- std::vector<ScopedInternalPlatformHandle> msg_handles =
+ std::vector<PlatformHandleInTransit> handles_in_transit =
channel_message_->TakeHandles();
+ std::vector<PlatformHandle> msg_handles(handles_in_transit.size());
+ for (size_t i = 0; i < handles_in_transit.size(); ++i) {
+ DCHECK(!handles_in_transit[i].owning_process().is_valid());
+ msg_handles[i] = handles_in_transit[i].TakeHandle();
+ }
for (size_t i = 0; i < header->num_dispatchers; ++i) {
const DispatcherHeader& dh = dispatcher_headers[i];
auto type = static_cast<Dispatcher::Type>(dh.type);
@@ -610,7 +617,7 @@ MojoResult UserMessageImpl::ExtractSerializedHandles(
return MOJO_RESULT_ABORTED;
}
- ScopedInternalPlatformHandle* out_handles =
+ PlatformHandle* out_handles =
!msg_handles.empty() ? msg_handles.data() + platform_handle_index
: nullptr;
dispatchers[i].dispatcher = Dispatcher::Deserialize(
@@ -669,5 +676,11 @@ bool UserMessageImpl::WillBeRoutedExternally() {
return result == MOJO_RESULT_OK || result == MOJO_RESULT_FAILED_PRECONDITION;
}
-} // namespace edk
+size_t UserMessageImpl::GetSizeIfSerialized() const {
+ if (!IsSerialized())
+ return 0;
+ return user_payload_size_;
+}
+
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/user_message_impl.h b/chromium/mojo/core/user_message_impl.h
index dc974c31077..c6a15f98c78 100644
--- a/chromium/mojo/edk/system/user_message_impl.h
+++ b/chromium/mojo/core/user_message_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_USER_MESSAGE_IMPL_H_
-#define MOJO_EDK_SYSTEM_USER_MESSAGE_IMPL_H_
+#ifndef MOJO_CORE_USER_MESSAGE_IMPL_H_
+#define MOJO_CORE_USER_MESSAGE_IMPL_H_
#include <memory>
#include <utility>
@@ -11,19 +11,18 @@
#include "base/macros.h"
#include "base/optional.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/channel.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/ports/event.h"
-#include "mojo/edk/system/ports/name.h"
-#include "mojo/edk/system/ports/port_ref.h"
-#include "mojo/edk/system/ports/user_message.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/channel.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/ports/event.h"
+#include "mojo/core/ports/name.h"
+#include "mojo/core/ports/port_ref.h"
+#include "mojo/core/ports/user_message.h"
+#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/c/system/types.h"
namespace mojo {
-namespace edk {
+namespace core {
// UserMessageImpl is the sole implementation of ports::UserMessage used to
// attach message data to any ports::UserMessageEvent.
@@ -170,6 +169,7 @@ class MOJO_SYSTEM_IMPL_EXPORT UserMessageImpl : public ports::UserMessage {
// UserMessage:
bool WillBeRoutedExternally() override;
+ size_t GetSizeIfSerialized() const override;
// The event which owns this serialized message. Not owned.
ports::UserMessageEvent* const message_event_;
@@ -212,7 +212,7 @@ class MOJO_SYSTEM_IMPL_EXPORT UserMessageImpl : public ports::UserMessage {
DISALLOW_COPY_AND_ASSIGN(UserMessageImpl);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_USER_MESSAGE_IMPL_H_
+#endif // MOJO_CORE_USER_MESSAGE_IMPL_H_
diff --git a/chromium/mojo/edk/system/watch.cc b/chromium/mojo/core/watch.cc
index bc1d84337e4..996f0a7ca24 100644
--- a/chromium/mojo/edk/system/watch.cc
+++ b/chromium/mojo/core/watch.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/watch.h"
+#include "mojo/core/watch.h"
-#include "mojo/edk/system/request_context.h"
-#include "mojo/edk/system/watcher_dispatcher.h"
+#include "mojo/core/request_context.h"
+#include "mojo/core/watcher_dispatcher.h"
namespace mojo {
-namespace edk {
+namespace core {
Watch::Watch(const scoped_refptr<WatcherDispatcher>& watcher,
const scoped_refptr<Dispatcher>& dispatcher,
@@ -86,5 +86,5 @@ void Watch::AssertWatcherLockAcquired() const {
}
#endif
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/watch.h b/chromium/mojo/core/watch.h
index 07d6169379a..b2a81658332 100644
--- a/chromium/mojo/edk/system/watch.h
+++ b/chromium/mojo/core/watch.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_WATCH_H_
-#define MOJO_EDK_SYSTEM_WATCH_H_
+#ifndef MOJO_CORE_WATCH_H_
+#define MOJO_CORE_WATCH_H_
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/system/atomic_flag.h"
-#include "mojo/edk/system/handle_signals_state.h"
+#include "mojo/core/atomic_flag.h"
+#include "mojo/core/handle_signals_state.h"
#include "mojo/public/c/system/trap.h"
namespace mojo {
-namespace edk {
+namespace core {
class Dispatcher;
class WatcherDispatcher;
@@ -121,7 +121,7 @@ class Watch : public base::RefCountedThreadSafe<Watch> {
DISALLOW_COPY_AND_ASSIGN(Watch);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_WATCH_H_
+#endif // MOJO_CORE_WATCH_H_
diff --git a/chromium/mojo/edk/system/watcher_dispatcher.cc b/chromium/mojo/core/watcher_dispatcher.cc
index 6e8a44280ef..f2eb2e253d7 100644
--- a/chromium/mojo/edk/system/watcher_dispatcher.cc
+++ b/chromium/mojo/core/watcher_dispatcher.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/watcher_dispatcher.h"
+#include "mojo/core/watcher_dispatcher.h"
#include <algorithm>
#include <limits>
@@ -10,10 +10,10 @@
#include "base/debug/alias.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "mojo/edk/system/watch.h"
+#include "mojo/core/watch.h"
namespace mojo {
-namespace edk {
+namespace core {
WatcherDispatcher::WatcherDispatcher(MojoTrapEventHandler handler)
: handler_(handler) {}
@@ -204,16 +204,11 @@ MojoResult WatcherDispatcher::CancelWatch(uintptr_t context) {
return MOJO_RESULT_OK;
}
-MojoResult WatcherDispatcher::Arm(
- uint32_t* num_ready_contexts,
- uintptr_t* ready_contexts,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states) {
+MojoResult WatcherDispatcher::Arm(uint32_t* num_blocking_events,
+ MojoTrapEvent* blocking_events) {
base::AutoLock lock(lock_);
- if (num_ready_contexts &&
- (!ready_contexts || !ready_results || !ready_signals_states)) {
+ if (num_blocking_events && !blocking_events)
return MOJO_RESULT_INVALID_ARGUMENT;
- }
if (closed_)
return MOJO_RESULT_INVALID_ARGUMENT;
@@ -226,10 +221,10 @@ MojoResult WatcherDispatcher::Arm(
return MOJO_RESULT_OK;
}
- if (num_ready_contexts) {
+ if (num_blocking_events) {
DCHECK_LE(ready_watches_.size(), std::numeric_limits<uint32_t>::max());
- *num_ready_contexts = std::min(
- *num_ready_contexts, static_cast<uint32_t>(ready_watches_.size()));
+ *num_blocking_events = std::min(
+ *num_blocking_events, static_cast<uint32_t>(ready_watches_.size()));
WatchSet::const_iterator next_ready_iter = ready_watches_.begin();
if (last_watch_to_block_arming_) {
@@ -242,11 +237,14 @@ MojoResult WatcherDispatcher::Arm(
next_ready_iter = ready_watches_.begin();
}
- for (size_t i = 0; i < *num_ready_contexts; ++i) {
+ for (size_t i = 0; i < *num_blocking_events; ++i) {
const Watch* const watch = *next_ready_iter;
- ready_contexts[i] = watch->context();
- ready_results[i] = watch->last_known_result();
- ready_signals_states[i] = watch->last_known_signals_state();
+ if (blocking_events[i].struct_size < sizeof(*blocking_events))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ blocking_events[i].flags = MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL;
+ blocking_events[i].trigger_context = watch->context();
+ blocking_events[i].result = watch->last_known_result();
+ blocking_events[i].signals_state = watch->last_known_signals_state();
// Iterate and wrap around.
last_watch_to_block_arming_ = watch;
@@ -261,5 +259,5 @@ MojoResult WatcherDispatcher::Arm(
WatcherDispatcher::~WatcherDispatcher() = default;
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/watcher_dispatcher.h b/chromium/mojo/core/watcher_dispatcher.h
index 3048a58833e..6a8bceda9fd 100644
--- a/chromium/mojo/edk/system/watcher_dispatcher.h
+++ b/chromium/mojo/core/watcher_dispatcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_WATCHER_DISPATCHER_H_
-#define MOJO_EDK_SYSTEM_WATCHER_DISPATCHER_H_
+#ifndef MOJO_CORE_WATCHER_DISPATCHER_H_
+#define MOJO_CORE_WATCHER_DISPATCHER_H_
#include <stdint.h>
@@ -13,13 +13,13 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/system/dispatcher.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/core/dispatcher.h"
+#include "mojo/core/handle_signals_state.h"
+#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/trap.h"
namespace mojo {
-namespace edk {
+namespace core {
class Watch;
@@ -50,10 +50,8 @@ class WatcherDispatcher : public Dispatcher {
MojoTriggerCondition condition,
uintptr_t context) override;
MojoResult CancelWatch(uintptr_t context) override;
- MojoResult Arm(uint32_t* num_ready_contexts,
- uintptr_t* ready_contexts,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states) override;
+ MojoResult Arm(uint32_t* num_blocking_events,
+ MojoTrapEvent* blocking_events) override;
private:
friend class Watch;
@@ -98,7 +96,7 @@ class WatcherDispatcher : public Dispatcher {
DISALLOW_COPY_AND_ASSIGN(WatcherDispatcher);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_WATCHER_DISPATCHER_H_
+#endif // MOJO_CORE_WATCHER_DISPATCHER_H_
diff --git a/chromium/mojo/edk/system/watcher_set.cc b/chromium/mojo/core/watcher_set.cc
index 0355b58795f..98aa1afe7cb 100644
--- a/chromium/mojo/edk/system/watcher_set.cc
+++ b/chromium/mojo/core/watcher_set.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "mojo/edk/system/watcher_set.h"
+#include "mojo/core/watcher_set.h"
#include <utility>
namespace mojo {
-namespace edk {
+namespace core {
WatcherSet::WatcherSet(Dispatcher* owner) : owner_(owner) {}
@@ -78,5 +78,5 @@ WatcherSet::Entry::~Entry() = default;
WatcherSet::Entry& WatcherSet::Entry::operator=(Entry&& other) = default;
-} // namespace edk
+} // namespace core
} // namespace mojo
diff --git a/chromium/mojo/edk/system/watcher_set.h b/chromium/mojo/core/watcher_set.h
index 77ddd88e5ff..6abd43e0999 100644
--- a/chromium/mojo/edk/system/watcher_set.h
+++ b/chromium/mojo/core/watcher_set.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef MOJO_EDK_SYSTEM_WATCHER_SET_H_
-#define MOJO_EDK_SYSTEM_WATCHER_SET_H_
+#ifndef MOJO_CORE_WATCHER_SET_H_
+#define MOJO_CORE_WATCHER_SET_H_
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
-#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/watcher_dispatcher.h"
+#include "mojo/core/handle_signals_state.h"
+#include "mojo/core/watcher_dispatcher.h"
namespace mojo {
-namespace edk {
+namespace core {
// A WatcherSet maintains a set of references to WatcherDispatchers to be
// notified when a handle changes state.
@@ -64,7 +64,7 @@ class WatcherSet {
DISALLOW_COPY_AND_ASSIGN(WatcherSet);
};
-} // namespace edk
+} // namespace core
} // namespace mojo
-#endif // MOJO_EDK_SYSTEM_WATCHER_SET_H_
+#endif // MOJO_CORE_WATCHER_SET_H_
diff --git a/chromium/mojo/edk/BUILD.gn b/chromium/mojo/edk/BUILD.gn
deleted file mode 100644
index 0fbbe1588a3..00000000000
--- a/chromium/mojo/edk/BUILD.gn
+++ /dev/null
@@ -1,304 +0,0 @@
-# Copyright 2018 The Chromium 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/config/nacl/config.gni")
-import("//testing/test.gni")
-
-# Targets should depend on this if directly referencing the |mojo::edk|
-# namespace.
-component("edk") {
- output_name = "mojo_edk"
-
- public = [
- "embedder/embedder.h",
- "embedder/incoming_broker_client_invitation.h",
- "embedder/outgoing_broker_client_invitation.h",
- "embedder/peer_connection.h",
- ]
-
- sources = [
- "embedder/embedder.cc",
- "embedder/incoming_broker_client_invitation.cc",
- "embedder/outgoing_broker_client_invitation.cc",
- "embedder/peer_connection.cc",
- ]
-
- defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
-
- deps = []
- if (!is_nacl) {
- deps += [ "//crypto" ]
- }
-
- public_deps = [
- ":impl_for_edk",
- "//mojo/public/cpp/platform",
- "//mojo/public/cpp/system",
- ]
-}
-
-# Bits of the EDK library which do not depend on public API linkage. It is
-# not allowed for this target or any of its transitive dependencies to depend
-# on anything under //mojo/public beyond strict C type definitions.
-#
-# This is templated because it's consumed by both the ":edk" component library
-# as well as the ":mojo_core" shared library. In the former case we want to
-# export symbols, but in the latter case we don't. The template stamps out two
-# nearly identical targets which differ only in what symbols they export.
-template("core_impl_source_set") {
- source_set(target_name) {
- if (invoker.for_mojo_core) {
- visibility = [ ":mojo_core" ]
- } else {
- visibility = [ ":edk" ]
- }
-
- public = [
- "embedder/configuration.h",
- "embedder/connection_params.h",
- "embedder/entrypoints.h",
- "embedder/named_platform_channel_pair.h",
- "embedder/named_platform_handle.h",
- "embedder/named_platform_handle_utils.h",
- "embedder/platform_channel_pair.h",
- "embedder/platform_handle.h",
- "embedder/platform_handle_utils.h",
- "embedder/process_error_callback.h",
- "embedder/scoped_ipc_support.h",
- "embedder/scoped_platform_handle.h",
- "embedder/transport_protocol.h",
- "system/channel.h",
- "system/configuration.h",
- "system/core.h",
- "system/data_pipe_consumer_dispatcher.h",
- "system/data_pipe_control_message.h",
- "system/data_pipe_producer_dispatcher.h",
- "system/dispatcher.h",
- "system/handle_signals_state.h",
- "system/handle_table.h",
- "system/invitation_dispatcher.h",
- "system/message_pipe_dispatcher.h",
- "system/node_controller.h",
- "system/options_validation.h",
- "system/platform_handle_dispatcher.h",
- "system/platform_shared_memory_mapping.h",
- "system/request_context.h",
- "system/scoped_process_handle.h",
- "system/shared_buffer_dispatcher.h",
- "system/user_message_impl.h",
- ]
-
- if (is_win) {
- public += [ "embedder/named_platform_handle_win.h" ]
- } else if (is_posix || is_fuchsia) {
- public += [ "embedder/named_platform_handle_posix.h" ]
- }
-
- sources = [
- "embedder/connection_params.cc",
- "embedder/entrypoints.cc",
- "embedder/named_platform_handle_utils_win.cc",
- "embedder/platform_channel_pair.cc",
- "embedder/platform_channel_pair_win.cc",
- "embedder/platform_handle.cc",
- "embedder/platform_handle_utils.cc",
- "embedder/platform_handle_utils_win.cc",
- "embedder/scoped_ipc_support.cc",
- "system/atomic_flag.h",
- "system/broker.h",
- "system/broker_win.cc",
- "system/channel.cc",
- "system/channel_win.cc",
- "system/configuration.cc",
- "system/core.cc",
- "system/data_pipe_consumer_dispatcher.cc",
- "system/data_pipe_control_message.cc",
- "system/data_pipe_producer_dispatcher.cc",
- "system/dispatcher.cc",
- "system/handle_table.cc",
- "system/invitation_dispatcher.cc",
- "system/message_pipe_dispatcher.cc",
- "system/node_channel.cc",
- "system/node_channel.h",
- "system/node_controller.cc",
- "system/platform_handle_dispatcher.cc",
- "system/platform_shared_memory_mapping.cc",
- "system/request_context.cc",
- "system/scoped_process_handle.cc",
- "system/shared_buffer_dispatcher.cc",
- "system/user_message_impl.cc",
- "system/watch.cc",
- "system/watch.h",
- "system/watcher_dispatcher.cc",
- "system/watcher_dispatcher.h",
- "system/watcher_set.cc",
- "system/watcher_set.h",
- ]
-
- public_deps = [
- "//base",
- "//mojo/edk/system/ports",
- "//mojo/public/c/system:headers",
- "//mojo/public/cpp/platform",
- ]
-
- if (is_fuchsia) {
- sources += [
- "embedder/named_platform_handle_utils_fuchsia.cc",
- "embedder/platform_channel_pair_fuchsia.cc",
- "embedder/platform_handle_utils_fuchsia.cc",
- "system/channel_fuchsia.cc",
- ]
-
- public_deps += [ "//third_party/fuchsia-sdk:fdio" ]
- }
-
- if (is_posix) {
- sources += [
- "embedder/platform_channel_pair_posix.cc",
- "embedder/platform_handle_utils_posix.cc",
- ]
-
- if (!is_nacl || is_nacl_nonsfi) {
- public += [ "embedder/platform_channel_utils_posix.h" ]
- sources += [
- "embedder/platform_channel_utils_posix.cc",
- "system/broker_posix.cc",
- "system/channel_posix.cc",
- ]
- }
-
- if (!is_nacl) {
- sources += [ "embedder/named_platform_handle_utils_posix.cc" ]
- }
- }
-
- if (is_mac && !is_ios) {
- sources += [
- "system/mach_port_relay.cc",
- "system/mach_port_relay.h",
- ]
- }
-
- if (!is_nacl || is_nacl_nonsfi) {
- sources += [
- "system/broker_host.cc",
- "system/broker_host.h",
- ]
- }
-
- defines = []
- if (!invoker.for_mojo_core) {
- defines += [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
- }
-
- deps = []
- if (is_android) {
- deps += [ "//third_party/ashmem" ]
- }
- if (!is_nacl) {
- sources += [ "embedder/named_platform_channel_pair.cc" ]
- deps += [ "//crypto" ]
- }
-
- if (is_win) {
- cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()),
- # which is uninteresting.
- }
-
- # Use target_os == "chromeos" instead of is_chromeos because we need to
- # build NaCl targets (i.e. IRT) for ChromeOS the same as the rest of ChromeOS.
- if (is_android || target_os == "chromeos") {
- defines += [ "MOJO_EDK_LEGACY_PROTOCOL" ]
- }
- }
-}
-
-core_impl_source_set("impl_for_edk") {
- for_mojo_core = false
-}
-
-if (is_chromeos || is_linux || is_android) {
- core_impl_source_set("impl_for_mojo_core") {
- for_mojo_core = true
- }
-
- shared_library("mojo_core") {
- sources = [
- "mojo_core.cc",
- ]
- deps = [
- ":impl_for_mojo_core",
- "//build/config:exe_and_shlib_deps",
- "//mojo/public/c/system:headers",
- ]
- configs += [ ":export_only_thunks_api" ]
- }
-
- if (is_chromeos) {
- if (target_cpu == "arm" || target_cpu == "arm64") {
- android32_toolchain = "android_clang_arm"
- android64_toolchain = "android_clang_arm64"
- } else {
- android32_toolchain = "android_clang_x86"
- android64_toolchain = "android_clang_x64"
- }
-
- group("mojo_core_for_arc") {
- deps = [
- ":mojo_core_arc32",
- ":mojo_core_arc64",
- ]
- }
-
- copy("mojo_core_arc32") {
- sources = [
- "${root_out_dir}/${android32_toolchain}/libmojo_core.so",
- ]
- outputs = [
- "${root_out_dir}/libmojo_core_arc32.so",
- ]
- deps = [
- ":mojo_core(//build/toolchain/android:${android32_toolchain})",
- ]
- }
-
- copy("mojo_core_arc64") {
- sources = [
- "${root_out_dir}/${android64_toolchain}/libmojo_core.so",
- ]
- outputs = [
- "${root_out_dir}/libmojo_core_arc64.so",
- ]
- deps = [
- ":mojo_core(//build/toolchain/android:${android64_toolchain})",
- ]
- }
- }
-
- config("export_only_thunks_api") {
- ldflags = [ "-Wl,--version-script=" +
- rebase_path("//mojo/edk/export_only_thunks_api.lst") ]
- }
-
- if (is_chromeos || is_linux) {
- test("mojo_core_unittests") {
- sources = [
- "mojo_core_unittest.cc",
- "run_all_core_unittests.cc",
- ]
-
- deps = [
- "//base",
- "//base/test:test_support",
- "//mojo/public/c/system",
- "//testing/gtest",
- ]
-
- data_deps = [
- ":mojo_core",
- ]
- }
- }
-}
diff --git a/chromium/mojo/edk/embedder/BUILD.gn b/chromium/mojo/edk/embedder/BUILD.gn
deleted file mode 100644
index a33988eec4f..00000000000
--- a/chromium/mojo/edk/embedder/BUILD.gn
+++ /dev/null
@@ -1,27 +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.
-
-source_set("embedder_unittests") {
- testonly = true
-
- # TODO: Figure out why this visibility check fails on Android.
- # visibility = [ "//mojo:mojo_unittests" ]
-
- sources = [
- "embedder_unittest.cc",
- ]
-
- if (is_posix) {
- sources += [ "platform_channel_pair_posix_unittest.cc" ]
- }
-
- deps = [
- "//base",
- "//base/test:test_support",
- "//mojo/edk",
- "//mojo/edk/system:test_utils",
- "//mojo/edk/test:test_support",
- "//testing/gtest",
- ]
-}
diff --git a/chromium/mojo/edk/embedder/README.md b/chromium/mojo/edk/embedder/README.md
deleted file mode 100644
index a700f48abe9..00000000000
--- a/chromium/mojo/edk/embedder/README.md
+++ /dev/null
@@ -1,325 +0,0 @@
-# Mojo Embedder Development Kit (EDK)
-This document is a subset of the [Mojo documentation](/mojo/README.md).
-
-[TOC]
-
-## Overview
-
-The Mojo EDK is a (binary-unstable) API which enables a process to use Mojo both
-internally and for IPC to other Mojo-embedding processes.
-
-Using any of the API surface in `//mojo/edk/embedder` requires a direct
-dependency on the GN `//mojo/edk` target. Headers in `mojo/edk/system` are
-reserved for internal use by the EDK only.
-
-**NOTE:** Unless you are introducing a new binary entry point into the system
-(*e.g.,* a new executable with a new `main()` definition), you probably don't
-need to know anything about the EDK API. Most processes defined in the Chrome
-repo today already fully initialize the EDK so that Mojo's other public APIs
-"just work" out of the box.
-
-## Basic Initialization
-
-In order to use Mojo in a given process, it's necessary to call
-`mojo::edk::Init` exactly once:
-
-```
-#include "mojo/edk/embedder/embedder.h"
-
-int main(int argc, char** argv) {
- mojo::edk::Init();
-
- // Now you can create message pipes, write messages, etc
-
- return 0;
-}
-```
-
-As it happens though, Mojo is less useful without some kind of IPC support as
-well, and that's a second initialization step.
-
-## IPC Initialization
-
-You also need to provide the system with a background TaskRunner on which it can
-watch for inbound I/O from any of the various other processes you will later
-connect to it.
-
-Here we'll just create a new background thread for IPC and let Mojo use that.
-Note that in Chromium, we use the existing "IO thread" in the browser process
-and content child processes.
-
-```
-#include "base/threading/thread.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
-
-int main(int argc, char** argv) {
- mojo::edk::Init();
-
- base::Thread ipc_thread("ipc!");
- ipc_thread.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
-
- // As long as this object is alive, all EDK API surface relevant to IPC
- // connections is usable and message pipes which span a process boundary will
- // continue to function.
- mojo::edk::ScopedIPCSupport ipc_support(
- ipc_thread.task_runner(),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN);
-
- return 0;
-}
-```
-
-This process is now fully prepared to use Mojo IPC!
-
-Note that all existing process types in Chromium already perform this setup
-very early during startup.
-
-## Connecting Two Processes
-
-Now suppose you're running a process which has initialized Mojo IPC, and you
-want to launch another process which you know will also initialize Mojo IPC.
-You want to be able to connect Mojo interfaces between these two processes.
-Rejoice, because this section was written just for you.
-
-NOTE: For legacy reasons, some API terminology may refer to concepts of "parent"
-and "child" as a relationship between processes being connected by Mojo. This
-relationship is today completely orthogonal to any notion of process hierarchy
-in the OS, and so use of these APIs is not constrained by an adherence to any
-such hierarchy.
-
-Mojo requires you to bring your own OS pipe to the party, and it will do the
-rest. It also provides a convenient mechanism for creating such pipes, known as
-a `PlatformChannelPair`.
-
-You provide one end of this pipe to the EDK in the local process via
-`OutgoingBrokerClientInvitation` - which can also be used to create cross-
-process message pipes (see the next section) - and you're responsible for
-getting the other end into the remote process.
-
-```
-#include "base/process/process_handle.h"
-#include "base/threading/thread.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
-
-// You write this. It launches a new process, passing the pipe handle
-// encapsulated by |channel| by any means possible (e.g. on Windows or POSIX
-// you may inhert the file descriptor/HANDLE at launch and pass a commandline
-// argument to indicate its numeric value). Returns the handle of the new
-// process.
-base::ProcessHandle LaunchCoolChildProcess(
- mojo::edk::ScopedInternalPlatformHandle channel);
-
-int main(int argc, char** argv) {
- mojo::edk::Init();
-
- base::Thread ipc_thread("ipc!");
- ipc_thread.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
-
- mojo::edk::ScopedIPCSupport ipc_support(
- ipc_thread.task_runner(),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN);
-
- // This is essentially always an OS pipe (domain socket pair, Windows named
- // pipe, etc.)
- mojo::edk::PlatformChannelPair channel;
-
- // This is a scoper which encapsulates the intent to connect to another
- // process. It exists because process connection is inherently asynchronous,
- // things may go wrong, and the lifetime of any associated resources is bound
- // by the lifetime of this object regardless of success or failure.
- mojo::edk::OutgoingBrokerClientInvitation invitation;
-
- base::ProcessHandle child_handle =
- LaunchCoolChildProcess(channel.PassClientHandle());
-
- // At this point it's safe for |invitation| to go out of scope and nothing
- // will break.
- invitation.Send(child_handle, channel.PassServerHandle());
-
- return 0;
-}
-```
-
-The launched process code uses `IncomingBrokerClientInvitation` to get
-connected, and might look something like:
-
-```
-#include "base/threading/thread.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
-
-// You write this. It acquires the ScopedInternalPlatformHandle that was passed by
-// whomever launched this process (i.e. LaunchCoolChildProcess above).
-mojo::edk::ScopedInternalPlatformHandle GetChannelHandle();
-
-int main(int argc, char** argv) {
- mojo::edk::Init();
-
- base::Thread ipc_thread("ipc!");
- ipc_thread.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
-
- mojo::edk::ScopedIPCSupport ipc_support(
- ipc_thread.task_runner(),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN);
-
- mojo::edk::IncomingBrokerClientInvitation::Accept(GetChannelHandle());
-
- return 0;
-}
-```
-
-Now you have IPC initialized between two processes. For some practical examples
-of how this is done, you can dig into the various multiprocess tests in the
-`mojo_unittests` test suite.
-
-## Bootstrapping Cross-Process Message Pipes
-
-Having internal Mojo IPC support initialized is pretty useless if you don't have
-any message pipes spanning the process boundary. Fortunately, this is made
-trivial by the EDK: `OutgoingBrokerClientInvitation` has an
-`AttachMessagePipe` method which synthesizes a new solitary message pipe
-endpoint for your immediate use, and attaches the other end to the invitation
-such that it can later be extracted by name by the invitee from the
-`IncomingBrokerClientInvitation`.
-
-We can modify our existing sample code as follows:
-
-```
-#include "base/command_line.h"
-#include "base/process/process_handle.h"
-#include "base/threading/thread.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-#include "local/foo.mojom.h" // You provide this
-
-base::ProcessHandle LaunchCoolChildProcess(
- const base::CommandLine& command_line,
- mojo::edk::ScopedInternalPlatformHandle channel);
-
-int main(int argc, char** argv) {
- mojo::edk::Init();
-
- base::Thread ipc_thread("ipc!");
- ipc_thread.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
-
- mojo::edk::ScopedIPCSupport ipc_support(
- ipc_thread.task_runner(),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN);
-
- mojo::edk::PlatformChannelPair channel;
-
- mojo::edk::OutgoingBrokerClientInvitation invitation;
-
- // Create a new message pipe with one end being retrievable in the new
- // process. Note that the name chosen for the attachment is arbitrary and
- // scoped to this invitation.
- mojo::ScopedMessagePipeHandle my_pipe =
- invitation.AttachMessagePipe("pretty_cool_pipe");
-
- base::ProcessHandle child_handle =
- LaunchCoolChildProcess(channel.PassClientHandle());
- invitation.Send(
- child_handle,
- mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
- channel.PassServerHandle()));
-
- // We can start using our end of the pipe immediately. Here we assume the
- // other end will eventually be bound to a local::mojom::Foo implementation,
- // so we can start making calls on that interface.
- //
- // Note that this could even be done before the child process is launched and
- // it would still work as expected.
- local::mojom::FooPtr foo;
- foo.Bind(local::mojom::FooPtrInfo(std::move(my_pipe), 0));
- foo->DoSomeStuff(42);
-
- return 0;
-}
-```
-
-and for the launched process:
-
-
-```
-#include "base/run_loop/run_loop.h"
-#include "base/threading/thread.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/incoming_broker_client_invitation.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-#include "local/foo.mojom.h" // You provide this
-
-mojo::edk::ScopedInternalPlatformHandle GetChannelHandle();
-
-class FooImpl : local::mojom::Foo {
- public:
- explicit FooImpl(local::mojom::FooRequest request)
- : binding_(this, std::move(request)) {}
- ~FooImpl() override {}
-
- void DoSomeStuff(int32_t n) override {
- // ...
- }
-
- private:
- mojo::Binding<local::mojom::Foo> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(FooImpl);
-};
-
-int main(int argc, char** argv) {
- mojo::edk::Init();
-
- base::Thread ipc_thread("ipc!");
- ipc_thread.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO));
-
- mojo::edk::ScopedIPCSupport ipc_support(
- ipc_thread.task_runner(),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN);
-
- auto invitation = mojo::edk::IncomingBrokerClientInvitation::Accept(
- mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
- GetChannelHandle()));
-
- mojo::ScopedMessagePipeHandle my_pipe =
- invitation->ExtractMessagePipe("pretty_cool_pipe");
-
- FooImpl impl(local::mojom::FooRequest(std::move(my_pipe)));
-
- // Run forever!
- base::RunLoop().Run();
-
- return 0;
-}
-```
-
-Note that the above samples assume an interface definition in
-`//local/test.mojom` which would look something like:
-
-```
-module local.mojom;
-
-interface Foo {
- DoSomeStuff(int32 n);
-};
-```
-
-Once you've bootstrapped your process connection with a real mojom interface,
-you can avoid any further mucking around with EDK APIs or raw message pipe
-handles, as everything beyond this point - including the passing of other
-interface pipes - can be handled eloquently using
-[public bindings APIs](/mojo/README.md#High_Level-Bindings-APIs).
-
diff --git a/chromium/mojo/edk/embedder/connection_params.cc b/chromium/mojo/edk/embedder/connection_params.cc
deleted file mode 100644
index 8e53d4f5644..00000000000
--- a/chromium/mojo/edk/embedder/connection_params.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium 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/connection_params.h"
-
-#include <utility>
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace edk {
-
-ConnectionParams::ConnectionParams(TransportProtocol protocol,
- ScopedInternalPlatformHandle channel)
- : protocol_(protocol), channel_(std::move(channel)) {
- // TODO(rockot): Support other protocols.
- DCHECK_EQ(TransportProtocol::kLegacy, protocol);
-}
-
-ConnectionParams::ConnectionParams(ConnectionParams&& params) {
- *this = std::move(params);
-}
-
-ConnectionParams& ConnectionParams::operator=(ConnectionParams&& params) =
- default;
-
-ScopedInternalPlatformHandle ConnectionParams::TakeChannelHandle() {
- return std::move(channel_);
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/connection_params.h b/chromium/mojo/edk/embedder/connection_params.h
deleted file mode 100644
index 1a7c9793439..00000000000
--- a/chromium/mojo/edk/embedder/connection_params.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 The Chromium 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_CONNECTION_PARAMS_H_
-#define MOJO_EDK_EMBEDDER_CONNECTION_PARAMS_H_
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/embedder/transport_protocol.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace edk {
-
-// A set of parameters used when establishing a connection to another process.
-class MOJO_SYSTEM_IMPL_EXPORT ConnectionParams {
- public:
- // Configures an OS pipe-based connection of type |type| to the remote process
- // using the given transport |protocol|.
- ConnectionParams(TransportProtocol protocol,
- ScopedInternalPlatformHandle channel);
-
- ConnectionParams(ConnectionParams&& params);
- ConnectionParams& operator=(ConnectionParams&& params);
-
- TransportProtocol protocol() const { return protocol_; }
-
- ScopedInternalPlatformHandle TakeChannelHandle();
-
- private:
- TransportProtocol protocol_;
- ScopedInternalPlatformHandle channel_;
-
- DISALLOW_COPY_AND_ASSIGN(ConnectionParams);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_CONNECTION_PARAMS_H_
diff --git a/chromium/mojo/edk/embedder/embedder.cc b/chromium/mojo/edk/embedder/embedder.cc
deleted file mode 100644
index a4a896cbe09..00000000000
--- a/chromium/mojo/edk/embedder/embedder.cc
+++ /dev/null
@@ -1,80 +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/embedder/embedder.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task_runner.h"
-#include "mojo/edk/embedder/entrypoints.h"
-#include "mojo/edk/system/configuration.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/public/c/system/thunks.h"
-
-#if !defined(OS_NACL)
-#include "crypto/random.h"
-#endif
-
-namespace mojo {
-namespace edk {
-
-void Init(const Configuration& configuration) {
- internal::g_configuration = configuration;
- InitializeCore();
- MojoEmbedderSetSystemThunks(&GetSystemThunks());
-}
-
-void Init() {
- Init(Configuration());
-}
-
-void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback) {
- Core::Get()->SetDefaultProcessErrorCallback(callback);
-}
-
-std::string GenerateRandomToken() {
- char random_bytes[16];
-#if defined(OS_NACL)
- // Not secure. For NaCl only!
- base::RandBytes(random_bytes, 16);
-#else
- crypto::RandBytes(random_bytes, 16);
-#endif
- return base::HexEncode(random_bytes, 16);
-}
-
-MojoResult CreateInternalPlatformHandleWrapper(
- ScopedInternalPlatformHandle platform_handle,
- MojoHandle* platform_handle_wrapper_handle) {
- return Core::Get()->CreateInternalPlatformHandleWrapper(
- std::move(platform_handle), platform_handle_wrapper_handle);
-}
-
-MojoResult PassWrappedInternalPlatformHandle(
- MojoHandle platform_handle_wrapper_handle,
- ScopedInternalPlatformHandle* platform_handle) {
- return Core::Get()->PassWrappedInternalPlatformHandle(
- platform_handle_wrapper_handle, platform_handle);
-}
-
-scoped_refptr<base::TaskRunner> GetIOTaskRunner() {
- return Core::Get()->GetNodeController()->io_task_runner();
-}
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-void SetMachPortProvider(base::PortProvider* port_provider) {
- DCHECK(port_provider);
- Core::Get()->SetMachPortProvider(port_provider);
-}
-#endif
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/embedder.h b/chromium/mojo/edk/embedder/embedder.h
deleted file mode 100644
index 4e0766f3360..00000000000
--- a/chromium/mojo/edk/embedder/embedder.h
+++ /dev/null
@@ -1,90 +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_EMBEDDER_EMBEDDER_H_
-#define MOJO_EDK_EMBEDDER_EMBEDDER_H_
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory_handle.h"
-#include "base/process/process_handle.h"
-#include "base/task_runner.h"
-#include "mojo/edk/embedder/configuration.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace base {
-class PortProvider;
-}
-
-namespace mojo {
-namespace edk {
-
-using ProcessErrorCallback = base::Callback<void(const std::string& error)>;
-
-// Basic configuration/initialization ------------------------------------------
-
-// Must be called first, or just after setting configuration parameters, to
-// initialize the (global, singleton) system state. There is no corresponding
-// shutdown operation: once the EDK is initialized, public Mojo C API calls
-// remain available for the remainder of the process's lifetime.
-MOJO_SYSTEM_IMPL_EXPORT void Init(const Configuration& configuration);
-
-// Like above but uses a default Configuration.
-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. Calling this is optional.
-MOJO_SYSTEM_IMPL_EXPORT void SetDefaultProcessErrorCallback(
- const ProcessErrorCallback& callback);
-
-// Generates a random ASCII token string for use with various APIs that expect
-// a globally unique token string. May be called at any time on any thread.
-MOJO_SYSTEM_IMPL_EXPORT std::string GenerateRandomToken();
-
-// Basic functions -------------------------------------------------------------
-//
-// The functions in this section are available once |Init()| has been called and
-// provide the embedder with some extra capabilities not exposed by public Mojo
-// C APIs.
-
-// Creates a |MojoHandle| that wraps the given |InternalPlatformHandle| (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
-// failure, which is different from what you'd expect from a Mojo API, but it
-// makes for a more convenient embedder API.
-MOJO_SYSTEM_IMPL_EXPORT MojoResult CreateInternalPlatformHandleWrapper(
- ScopedInternalPlatformHandle platform_handle,
- MojoHandle* platform_handle_wrapper_handle);
-
-// Retrieves the |InternalPlatformHandle| that was wrapped into a |MojoHandle|
-// (using |CreateInternalPlatformHandleWrapper()| above). Note that the
-// |MojoHandle| is closed on success.
-MOJO_SYSTEM_IMPL_EXPORT MojoResult PassWrappedInternalPlatformHandle(
- MojoHandle platform_handle_wrapper_handle,
- ScopedInternalPlatformHandle* platform_handle);
-
-// Initialialization/shutdown for interprocess communication (IPC) -------------
-
-// Retrieves the TaskRunner used for IPC I/O, as set by ScopedIPCSupport.
-MOJO_SYSTEM_IMPL_EXPORT scoped_refptr<base::TaskRunner> GetIOTaskRunner();
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-// Set the |base::PortProvider| for this process. Can be called on any thread,
-// but must be set in the root process before any Mach ports can be transferred.
-//
-// If called at all, this must be called while a ScopedIPCSupport exists.
-MOJO_SYSTEM_IMPL_EXPORT void SetMachPortProvider(
- base::PortProvider* port_provider);
-#endif
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_EMBEDDER_H_
diff --git a/chromium/mojo/edk/embedder/incoming_broker_client_invitation.cc b/chromium/mojo/edk/embedder/incoming_broker_client_invitation.cc
deleted file mode 100644
index ed201a53656..00000000000
--- a/chromium/mojo/edk/embedder/incoming_broker_client_invitation.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2017 The Chromium 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/incoming_broker_client_invitation.h"
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/core.h"
-
-namespace mojo {
-namespace edk {
-
-IncomingBrokerClientInvitation::~IncomingBrokerClientInvitation() = default;
-
-// static
-std::unique_ptr<IncomingBrokerClientInvitation>
-IncomingBrokerClientInvitation::Accept(ConnectionParams params) {
- return base::WrapUnique(
- new IncomingBrokerClientInvitation(std::move(params)));
-}
-
-// static
-std::unique_ptr<IncomingBrokerClientInvitation>
-IncomingBrokerClientInvitation::AcceptFromCommandLine(
- TransportProtocol protocol) {
- ScopedInternalPlatformHandle platform_channel =
- PlatformChannelPair::PassClientHandleFromParentProcess(
- *base::CommandLine::ForCurrentProcess());
- DCHECK(platform_channel.is_valid());
- return base::WrapUnique(new IncomingBrokerClientInvitation(
- ConnectionParams(protocol, std::move(platform_channel))));
-}
-
-ScopedMessagePipeHandle IncomingBrokerClientInvitation::ExtractMessagePipe(
- const std::string& name) {
- return ScopedMessagePipeHandle(
- MessagePipeHandle(Core::Get()->ExtractMessagePipeFromInvitation(name)));
-}
-
-IncomingBrokerClientInvitation::IncomingBrokerClientInvitation(
- ConnectionParams params) {
- Core::Get()->AcceptBrokerClientInvitation(std::move(params));
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/incoming_broker_client_invitation.h b/chromium/mojo/edk/embedder/incoming_broker_client_invitation.h
deleted file mode 100644
index 79193ea5564..00000000000
--- a/chromium/mojo/edk/embedder/incoming_broker_client_invitation.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2017 The Chromium 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_INCOMING_BROKER_CLIENT_INVITATION_H_
-#define MOJO_EDK_EMBEDDER_INCOMING_BROKER_CLIENT_INVITATION_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "mojo/edk/embedder/connection_params.h"
-#include "mojo/edk/embedder/transport_protocol.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-
-namespace mojo {
-namespace edk {
-
-// Mojo embedders may use this to accept a broker client invitation from another
-// embedder in the system.
-class MOJO_SYSTEM_IMPL_EXPORT IncomingBrokerClientInvitation {
- public:
- ~IncomingBrokerClientInvitation();
-
- // Accepts an incoming invitation received via the connection medium in
- // |params|.
- static std::unique_ptr<IncomingBrokerClientInvitation> Accept(
- ConnectionParams params);
-
- // Accepts an incoming invitation from the command line. The command line is
- // expected to have a |PlatformChannelPair::kMojoPlatformChannelHandleSwitch|
- // switch whose value is an integer platform handle identifier (e.g. FD or
- // HANDLE) in the calling process. The handle should correspond to one end of
- // an OS pipe whose other end was used by another process to send an
- // OutgoingBrokerClientInvitation.
- static std::unique_ptr<IncomingBrokerClientInvitation> AcceptFromCommandLine(
- TransportProtocol protocol);
-
- // Extracts a named message pipe from the accepted invitation. Must be called
- // after Accept() or AcceptFromCommandLine().
- //
- // Note that while this returns a usable pipe handle immediately, extraction
- // and internal pipe connection is an asynchronous process. Therefore this
- // method always returns a valid handle even if no such pipe was attached; in
- // such cases where there was no attached pipe named |name|, the returned pipe
- // handle will imminently signal peer closure.
- ScopedMessagePipeHandle ExtractMessagePipe(const std::string& name);
-
- private:
- explicit IncomingBrokerClientInvitation(ConnectionParams params);
-
- DISALLOW_COPY_AND_ASSIGN(IncomingBrokerClientInvitation);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_INCOMING_BROKER_CLIENT_INVITATION_H_
diff --git a/chromium/mojo/edk/embedder/named_platform_channel_pair.cc b/chromium/mojo/edk/embedder/named_platform_channel_pair.cc
deleted file mode 100644
index 63c45b837d1..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_channel_pair.cc
+++ /dev/null
@@ -1,101 +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/embedder/named_platform_channel_pair.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#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"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace mojo {
-namespace edk {
-
-namespace {
-
-const char kMojoNamedPlatformChannelPipeSwitch[] =
- "mojo-named-platform-channel-pipe";
-
-#if defined(OS_WIN)
-std::wstring GeneratePipeName(
- const NamedPlatformChannelPair::Options& options) {
- return base::StringPrintf(L"%u.%u.%I64u", GetCurrentProcessId(),
- GetCurrentThreadId(), base::RandUint64());
-}
-#else
-std::string GeneratePipeName(const NamedPlatformChannelPair::Options& options) {
- return options.socket_dir
- .AppendASCII(base::NumberToString(base::RandUint64()))
- .value();
-}
-#endif
-
-} // namespace
-
-NamedPlatformChannelPair::NamedPlatformChannelPair(
- const NamedPlatformChannelPair::Options& options)
- : pipe_handle_(GeneratePipeName(options)) {
- CreateServerHandleOptions server_handle_options;
-#if defined(OS_WIN)
- server_handle_options.security_descriptor = options.security_descriptor;
- server_handle_options.enforce_uniqueness = true;
-#endif
- server_handle_ = CreateServerHandle(pipe_handle_, server_handle_options);
- PCHECK(server_handle_.is_valid());
-}
-
-NamedPlatformChannelPair::~NamedPlatformChannelPair() {}
-
-ScopedInternalPlatformHandle NamedPlatformChannelPair::PassServerHandle() {
- return std::move(server_handle_);
-}
-
-// static
-ScopedInternalPlatformHandle
-NamedPlatformChannelPair::PassClientHandleFromParentProcess(
- const base::CommandLine& command_line) {
- // 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));
-
- if (!handle.is_valid())
- return ScopedInternalPlatformHandle();
-
- return CreateClientHandle(handle);
-}
-
-void NamedPlatformChannelPair::PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line) const {
- DCHECK(command_line);
-
- // Log a warning if the command line already has the switch, but "clobber" it
- // anyway, since it's reasonably likely that all the switches were just copied
- // from the parent.
- LOG_IF(WARNING, command_line->HasSwitch(kMojoNamedPlatformChannelPipeSwitch))
- << "Child command line already has switch --"
- << kMojoNamedPlatformChannelPipeSwitch << "="
- << command_line->GetSwitchValueNative(
- 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_handle_.name);
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/named_platform_channel_pair.h b/chromium/mojo/edk/embedder/named_platform_channel_pair.h
deleted file mode 100644
index f49400d2d56..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_channel_pair.h
+++ /dev/null
@@ -1,78 +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_EDK_EMBEDDER_NAMED_PLATFORM_CHANNEL_PAIR_H_
-#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_CHANNEL_PAIR_H_
-
-#include <string>
-
-#include "base/files/file_path.h"
-#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"
-
-namespace base {
-class CommandLine;
-}
-
-namespace mojo {
-namespace edk {
-
-// This is used to create a named bidirectional pipe to connect new child
-// processes. The resulting server handle should be passed to the EDK, and the
-// child end passed as a pipe name on the command line to the child process. The
-// child process can then retrieve the pipe name from the command line and
-// resolve it into a client handle.
-class MOJO_SYSTEM_IMPL_EXPORT NamedPlatformChannelPair {
- public:
- struct Options {
-#if defined(OS_WIN)
- // If non-empty, a security descriptor to use when creating the pipe. If
- // empty, a default security descriptor will be used. See
- // kDefaultSecurityDescriptor in named_platform_handle_utils_win.cc.
- base::string16 security_descriptor;
-#else
- // On POSIX, every new NamedPlatformChannelPair creates a new server socket
- // with a random name. This controls the directory where that happens.
- base::FilePath socket_dir;
-#endif
- };
-
- NamedPlatformChannelPair(const Options& options = {});
- ~NamedPlatformChannelPair();
-
- // Note: It is NOT acceptable to use this handle as a generic pipe channel. It
- // MUST be passed to OutgoingBrokerClientInvitation::Send() only.
- ScopedInternalPlatformHandle PassServerHandle();
-
- // To be called in the child process, after the parent process called
- // |PrepareToPassClientHandleToChildProcess()| and launched the child (using
- // the provided data), to create a client handle connected to the server
- // handle (in the parent process).
- static ScopedInternalPlatformHandle PassClientHandleFromParentProcess(
- const base::CommandLine& command_line);
-
- // Prepares to pass the client channel to a new child process, to be launched
- // using |LaunchProcess()| (from base/launch.h). Modifies |*command_line| and
- // |*handle_passing_info| as needed.
- // Note: For Windows, this method only works on Vista and later.
- void PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line) const;
-
- const NamedPlatformHandle& handle() const { return pipe_handle_; }
-
- private:
- NamedPlatformHandle pipe_handle_;
- ScopedInternalPlatformHandle server_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(NamedPlatformChannelPair);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_CHANNEL_PAIR_H_
diff --git a/chromium/mojo/edk/embedder/named_platform_handle.h b/chromium/mojo/edk/embedder/named_platform_handle.h
deleted file mode 100644
index e212792aef7..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_handle.h
+++ /dev/null
@@ -1,16 +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_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_
-#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include "mojo/edk/embedder/named_platform_handle_win.h"
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
-#include "mojo/edk/embedder/named_platform_handle_posix.h"
-#endif
-
-#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_
diff --git a/chromium/mojo/edk/embedder/named_platform_handle_posix.h b/chromium/mojo/edk/embedder/named_platform_handle_posix.h
deleted file mode 100644
index 3c7e0a1e5ec..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_handle_posix.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 The Chromium 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_POSIX_H_
-#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_POSIX_H_
-
-#include <string>
-
-#include "base/strings/string_piece.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace edk {
-
-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;
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_POSIX_H_
diff --git a/chromium/mojo/edk/embedder/named_platform_handle_utils.h b/chromium/mojo/edk/embedder/named_platform_handle_utils.h
deleted file mode 100644
index 21f9a3d1886..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_handle_utils.h
+++ /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.
-
-#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"
-
-#if defined(OS_WIN)
-#include "base/strings/string16.h"
-#endif
-
-namespace mojo {
-namespace edk {
-
-struct NamedPlatformHandle;
-
-#if defined(OS_POSIX)
-
-// The maximum length of the name of a unix domain 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;
-
-#endif
-
-struct CreateServerHandleOptions {
-#if defined(OS_WIN)
- // If true, creating a server handle will fail if another pipe with the same
- // name exists.
- bool enforce_uniqueness = true;
-
- // If non-empty, a security descriptor to use when creating the pipe. If
- // empty, a default security descriptor will be used. See
- // kDefaultSecurityDescriptor in named_platform_handle_utils_win.cc.
- base::string16 security_descriptor;
-#endif
-};
-
-// Creates a client platform handle from |handle|. This may block until |handle|
-// is ready to receive connections.
-MOJO_SYSTEM_IMPL_EXPORT ScopedInternalPlatformHandle
-CreateClientHandle(const NamedPlatformHandle& handle);
-
-// Creates a server platform handle from |handle|.
-MOJO_SYSTEM_IMPL_EXPORT ScopedInternalPlatformHandle
-CreateServerHandle(const NamedPlatformHandle& handle,
- const CreateServerHandleOptions& options = {});
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_UTILS_H_
diff --git a/chromium/mojo/edk/embedder/named_platform_handle_utils_fuchsia.cc b/chromium/mojo/edk/embedder/named_platform_handle_utils_fuchsia.cc
deleted file mode 100644
index f9539e78d76..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_handle_utils_fuchsia.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The Chromium 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 "mojo/edk/embedder/named_platform_handle.h"
-
-namespace mojo {
-namespace edk {
-
-ScopedInternalPlatformHandle CreateClientHandle(
- const NamedPlatformHandle& named_handle) {
- // TODO(fuchsia): Implement, or remove dependencies (crbug.com/754038).
- NOTREACHED();
- return ScopedInternalPlatformHandle();
-}
-
-ScopedInternalPlatformHandle CreateServerHandle(
- const NamedPlatformHandle& named_handle,
- const CreateServerHandleOptions& options) {
- // TODO(fuchsia): Implement, or remove dependencies (crbug.com/754038).
- NOTREACHED();
- return ScopedInternalPlatformHandle();
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc b/chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc
deleted file mode 100644
index 6a8c58b726a..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_handle_utils_posix.cc
+++ /dev/null
@@ -1,141 +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/embedder/named_platform_handle_utils.h"
-
-#include <errno.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "mojo/edk/embedder/named_platform_handle.h"
-
-namespace mojo {
-namespace edk {
-namespace {
-
-// 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 ScopedInternalPlatformHandle containing the
-// socket. Otherwise, this returns an invalid ScopedInternalPlatformHandle.
-ScopedInternalPlatformHandle CreateUnixDomainSocket(bool needs_connection) {
- // Create the unix domain socket.
- InternalPlatformHandle socket_handle(socket(AF_UNIX, SOCK_STREAM, 0));
- socket_handle.needs_connection = needs_connection;
- ScopedInternalPlatformHandle handle(socket_handle);
- if (!handle.is_valid()) {
- PLOG(ERROR) << "Failed to create AF_UNIX socket.";
- return ScopedInternalPlatformHandle();
- }
-
- // Now set it as non-blocking.
- if (!base::SetNonBlocking(handle.get().handle)) {
- PLOG(ERROR) << "base::SetNonBlocking() failed " << handle.get().handle;
- return ScopedInternalPlatformHandle();
- }
- return handle;
-}
-
-} // namespace
-
-ScopedInternalPlatformHandle CreateClientHandle(
- const NamedPlatformHandle& named_handle) {
- if (!named_handle.is_valid())
- return ScopedInternalPlatformHandle();
-
- struct sockaddr_un unix_addr;
- size_t unix_addr_len;
- if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len))
- return ScopedInternalPlatformHandle();
-
- ScopedInternalPlatformHandle handle = CreateUnixDomainSocket(false);
- if (!handle.is_valid())
- return ScopedInternalPlatformHandle();
-
- if (HANDLE_EINTR(connect(handle.get().handle,
- reinterpret_cast<sockaddr*>(&unix_addr),
- unix_addr_len)) < 0) {
- PLOG(ERROR) << "connect " << named_handle.name;
- return ScopedInternalPlatformHandle();
- }
-
- return handle;
-}
-
-ScopedInternalPlatformHandle CreateServerHandle(
- const NamedPlatformHandle& named_handle,
- const CreateServerHandleOptions& options) {
- if (!named_handle.is_valid())
- return ScopedInternalPlatformHandle();
-
- // 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 ScopedInternalPlatformHandle();
- }
-
- // Delete any old FS instances.
- if (unlink(named_handle.name.c_str()) < 0 && errno != ENOENT) {
- PLOG(ERROR) << "unlink " << named_handle.name;
- return ScopedInternalPlatformHandle();
- }
-
- struct sockaddr_un unix_addr;
- size_t unix_addr_len;
- if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len))
- return ScopedInternalPlatformHandle();
-
- ScopedInternalPlatformHandle handle = CreateUnixDomainSocket(true);
- if (!handle.is_valid())
- return ScopedInternalPlatformHandle();
-
- // Bind the socket.
- if (bind(handle.get().handle, reinterpret_cast<const sockaddr*>(&unix_addr),
- unix_addr_len) < 0) {
- PLOG(ERROR) << "bind " << named_handle.name;
- return ScopedInternalPlatformHandle();
- }
-
- // 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 ScopedInternalPlatformHandle();
- }
- 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
deleted file mode 100644
index 21125a3c034..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_handle_utils_win.cc
+++ /dev/null
@@ -1,95 +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/embedder/named_platform_handle_utils.h"
-
-#include <sddl.h>
-#include <windows.h>
-
-#include <memory>
-
-#include "base/logging.h"
-#include "base/win/windows_version.h"
-#include "mojo/edk/embedder/named_platform_handle.h"
-
-namespace mojo {
-namespace edk {
-namespace {
-
-// A DACL to grant:
-// GA = Generic All
-// access to:
-// SY = LOCAL_SYSTEM
-// BA = BUILTIN_ADMINISTRATORS
-// OW = OWNER_RIGHTS
-constexpr base::char16 kDefaultSecurityDescriptor[] =
- L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;OW)";
-
-} // namespace
-
-ScopedInternalPlatformHandle CreateClientHandle(
- const NamedPlatformHandle& named_handle) {
- if (!named_handle.is_valid())
- return ScopedInternalPlatformHandle();
-
- base::string16 pipe_name = named_handle.pipe_name();
-
- // Note: This may block.
- if (!WaitNamedPipeW(pipe_name.c_str(), NMPWAIT_USE_DEFAULT_WAIT))
- return ScopedInternalPlatformHandle();
-
- 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;
- ScopedInternalPlatformHandle handle(
- InternalPlatformHandle(CreateFileW(pipe_name.c_str(), kDesiredAccess,
- 0, // No sharing.
- nullptr, OPEN_EXISTING, kFlags,
- nullptr))); // No template file.
- // The server may have stopped accepting a connection between the
- // WaitNamedPipe() and CreateFile(). If this occurs, an invalid handle is
- // returned.
- DPLOG_IF(ERROR, !handle.is_valid())
- << "Named pipe " << named_handle.pipe_name()
- << " could not be opened after WaitNamedPipe succeeded";
- return handle;
-}
-
-ScopedInternalPlatformHandle CreateServerHandle(
- const NamedPlatformHandle& named_handle,
- const CreateServerHandleOptions& options) {
- if (!named_handle.is_valid())
- return ScopedInternalPlatformHandle();
-
- PSECURITY_DESCRIPTOR security_desc = nullptr;
- ULONG security_desc_len = 0;
- PCHECK(ConvertStringSecurityDescriptorToSecurityDescriptor(
- options.security_descriptor.empty() ? kDefaultSecurityDescriptor
- : options.security_descriptor.c_str(),
- SDDL_REVISION_1, &security_desc, &security_desc_len));
- std::unique_ptr<void, decltype(::LocalFree)*> p(security_desc, ::LocalFree);
- SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES),
- security_desc, FALSE};
-
- const DWORD kOpenMode = options.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;
- InternalPlatformHandle handle(
- CreateNamedPipeW(named_handle.pipe_name().c_str(), kOpenMode, kPipeMode,
- options.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 ScopedInternalPlatformHandle(handle);
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/named_platform_handle_win.h b/chromium/mojo/edk/embedder/named_platform_handle_win.h
deleted file mode 100644
index febeb68989e..00000000000
--- a/chromium/mojo/edk/embedder/named_platform_handle_win.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2018 The Chromium 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_WIN_H_
-#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_WIN_H_
-
-#include "base/strings/string16.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/utf_string_conversions.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace edk {
-
-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;
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_WIN_H_
diff --git a/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.cc b/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.cc
deleted file mode 100644
index 6c9ae1ed398..00000000000
--- a/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2017 The Chromium 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/outgoing_broker_client_invitation.h"
-
-#include "base/logging.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/node_controller.h"
-#include "mojo/edk/system/ports/port_ref.h"
-#include "mojo/edk/system/request_context.h"
-
-namespace mojo {
-namespace edk {
-
-OutgoingBrokerClientInvitation::OutgoingBrokerClientInvitation() = default;
-
-OutgoingBrokerClientInvitation::~OutgoingBrokerClientInvitation() {
- RequestContext request_context;
- for (auto& entry : attached_ports_)
- Core::Get()->GetNodeController()->ClosePort(entry.second);
-}
-
-ScopedMessagePipeHandle OutgoingBrokerClientInvitation::AttachMessagePipe(
- const std::string& name) {
- DCHECK(!sent_);
- ports::PortRef port;
- ScopedMessagePipeHandle pipe = ScopedMessagePipeHandle(
- MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(&port)));
- attached_ports_.emplace_back(name, port);
- return pipe;
-}
-
-ScopedMessagePipeHandle
-OutgoingBrokerClientInvitation::ExtractInProcessMessagePipe(
- const std::string& name) {
- // NOTE: Efficiency is not really important here. This is not used in normal
- // production code and is in practice only called when |attached_ports_| has
- // a single entry.
- for (auto it = attached_ports_.begin(); it != attached_ports_.end(); ++it) {
- if (it->first == name) {
- ScopedMessagePipeHandle pipe = ScopedMessagePipeHandle(
- MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(it->second)));
- attached_ports_.erase(it);
- return pipe;
- }
- }
-
- NOTREACHED();
- return ScopedMessagePipeHandle();
-}
-
-void OutgoingBrokerClientInvitation::Send(
- base::ProcessHandle target_process,
- ConnectionParams params,
- const ProcessErrorCallback& error_callback) {
- DCHECK(!sent_);
- sent_ = true;
- Core::Get()->SendBrokerClientInvitation(target_process, std::move(params),
- attached_ports_, error_callback);
- attached_ports_.clear();
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.h b/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.h
deleted file mode 100644
index aadf3f8e632..00000000000
--- a/chromium/mojo/edk/embedder/outgoing_broker_client_invitation.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2017 The Chromium 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_OUTGOING_BROKER_CLIENT_INVITATION_H_
-#define MOJO_EDK_EMBEDDER_OUTGOING_BROKER_CLIENT_INVITATION_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/process/process_handle.h"
-#include "mojo/edk/embedder/connection_params.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-
-namespace mojo {
-namespace edk {
-
-namespace ports {
-class PortRef;
-}
-
-// Any Mojo embedder which is either the broker process itself or an existing
-// broker client can use a OutgoingBrokerClientInvitation to invite a new
-// process into broker's group of connected processes.
-//
-// In order to use OutgoingBrokerClientInvitation, you must have a valid process
-// handle to the target process, as well as a valid ConnectionParams
-// corresponding to some ConnectionParams in the target process.
-//
-// It is the embedder's responsibility get a corresponding ConnectionParams into
-// the target process somehow (for example, by using file descriptor inheritance
-// at process launch to give it the other end of a socket pair) and ensure that
-// the target process constructs a corresponding IncomingBrokerClientInvitation
-// object for that ConnectionParams.
-//
-// New message pipes may be attached to a OutgoingBrokerClientInvitation by
-// calling AttachMessagePipe().
-//
-// The invitation is sent by calling Send(), and once the invitation is sent
-// there is no further need to keep the OutgoingBrokerClientInvitation object
-// alive.
-class MOJO_SYSTEM_IMPL_EXPORT OutgoingBrokerClientInvitation {
- public:
- OutgoingBrokerClientInvitation();
- ~OutgoingBrokerClientInvitation();
-
- // Attaches a new message pipe to this invitation. The returned message pipe
- // handle can be used immediately in the calling process. The other end can be
- // obtained by the eventual receiver of this invitation, i.e., the target of
- // Send().
- //
- // NOTE: This must not be called after Send().
- ScopedMessagePipeHandle AttachMessagePipe(const std::string& name);
-
- // Sends the invitation to the target process. |target_process| must be a
- // valid handle and |params| must correspond to some other ConnectionParams
- // (e.g. the other half of a socket pair) in the target process.
- void Send(
- base::ProcessHandle target_process,
- ConnectionParams params,
- const ProcessErrorCallback& error_callback = ProcessErrorCallback());
-
- // Extracts an attached message pipe endpoint by name. For use only when this
- // invitation will NOT be sent to a remote process (i.e. Send() will never be
- // be called) after all, and the caller wishes to retrieve the message pipe
- // endpoint that would have been received.
- //
- // TODO(rockot): Remove this. It's only here to support content single-process
- // mode and the NaCl broker, both of which could be implemented without this
- // after some refactoring.
- ScopedMessagePipeHandle ExtractInProcessMessagePipe(const std::string& name);
-
- private:
- // List of named ports attached to this invitation. Each port is the peer of
- // some corresponding message pipe handle returned by AttachMessagePipe.
- std::vector<std::pair<std::string, ports::PortRef>> attached_ports_;
-
- // Indicates whether the invitation has been sent yet.
- bool sent_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(OutgoingBrokerClientInvitation);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_OUTGOING_BROKER_CLIENT_INVITATION_H_
diff --git a/chromium/mojo/edk/embedder/peer_connection.cc b/chromium/mojo/edk/embedder/peer_connection.cc
deleted file mode 100644
index 85344114e90..00000000000
--- a/chromium/mojo/edk/embedder/peer_connection.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 The Chromium 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/peer_connection.h"
-
-#include "mojo/edk/system/core.h"
-
-namespace mojo {
-namespace edk {
-
-PeerConnection::PeerConnection() = default;
-
-PeerConnection::~PeerConnection() {
- if (is_connected_)
- Core::Get()->ClosePeerConnection(connection_id_);
-}
-
-ScopedMessagePipeHandle PeerConnection::Connect(ConnectionParams params) {
- DCHECK(!is_connected_);
- is_connected_ = true;
-
- ports::PortRef peer_port;
- auto pipe = ScopedMessagePipeHandle(
- MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(&peer_port)));
- connection_id_ = Core::Get()->ConnectToPeer(std::move(params), peer_port);
- return pipe;
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/peer_connection.h b/chromium/mojo/edk/embedder/peer_connection.h
deleted file mode 100644
index f17fc48f262..00000000000
--- a/chromium/mojo/edk/embedder/peer_connection.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2017 The Chromium 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_PEER_CONNECTION_H_
-#define MOJO_EDK_EMBEDDER_PEER_CONNECTION_H_
-
-#include "base/macros.h"
-#include "mojo/edk/embedder/connection_params.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-
-namespace mojo {
-namespace edk {
-
-// Used to connect to a peer process.
-//
-// NOTE: This should ONLY be used if there is no common ancestor for the
-// processes being connected. Peer connections have limited capabilities with
-// respect to Mojo IPC when compared to standard broker client connections (see
-// OutgoingBrokerClientInvitation and IncomingBrokerClientInvitation), and in
-// particular it's undefined behavior to attempt to forward any resources
-// (message pipes or other system handles) received from a peer process over to
-// any other process to which you're connected.
-//
-// Both processes must construct a PeerConnection with each one corresponding to
-// one end of some shared connection medium (e.g. a platform channel.)
-//
-// Each PeerConnection gets an implicit cross-process message pipe, the local
-// endpoint of which may be acquired by a one-time call to TakeMessagePipe().
-//
-// Once established, the connection to the remote peer will remain valid as long
-// as each process keeps its respective PeerConnection object alive.
-class MOJO_SYSTEM_IMPL_EXPORT PeerConnection {
- public:
- // Constructs a disconnected connection.
- PeerConnection();
- ~PeerConnection();
-
- // Connects to the peer and returns a primordial message pipe handle which
- // will be connected to a corresponding peer pipe in the remote process.
- ScopedMessagePipeHandle Connect(ConnectionParams params);
-
- private:
- bool is_connected_ = false;
- uint64_t connection_id_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(PeerConnection);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PEER_CONNECTION_H_
diff --git a/chromium/mojo/edk/embedder/platform_channel_pair.cc b/chromium/mojo/edk/embedder/platform_channel_pair.cc
deleted file mode 100644
index 2bb008cdb7b..00000000000
--- a/chromium/mojo/edk/embedder/platform_channel_pair.cc
+++ /dev/null
@@ -1,40 +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/embedder/platform_channel_pair.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-
-namespace mojo {
-namespace edk {
-
-const char PlatformChannelPair::kMojoPlatformChannelHandleSwitch[] =
- "mojo-platform-channel-handle";
-
-PlatformChannelPair::~PlatformChannelPair() {
-}
-
-ScopedInternalPlatformHandle PlatformChannelPair::PassServerHandle() {
- return std::move(server_handle_);
-}
-
-ScopedInternalPlatformHandle PlatformChannelPair::PassClientHandle() {
- return std::move(client_handle_);
-}
-
-void PlatformChannelPair::ChildProcessLaunched() {
- DCHECK(client_handle_.is_valid());
-#if defined(OS_FUCHSIA)
- // The |client_handle_| is transferred, not cloned, to the child.
- ignore_result(client_handle_.release());
-#else
- client_handle_.reset();
-#endif
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_channel_pair.h b/chromium/mojo/edk/embedder/platform_channel_pair.h
deleted file mode 100644
index 09f6d75afa5..00000000000
--- a/chromium/mojo/edk/embedder/platform_channel_pair.h
+++ /dev/null
@@ -1,118 +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_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/process/launch.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace base {
-class CommandLine;
-}
-
-namespace mojo {
-namespace edk {
-
-// It would be nice to refactor base/process/launch.h to have a more platform-
-// independent way of representing handles that are passed to child processes.
-#if defined(OS_WIN)
-using HandlePassingInformation = base::HandlesToInheritVector;
-#elif defined(OS_FUCHSIA)
-using HandlePassingInformation = base::HandlesToTransferVector;
-#elif defined(OS_POSIX)
-using HandlePassingInformation = base::FileHandleMappingVector;
-#else
-#error "Unsupported."
-#endif
-
-// This is used to create a pair of |InternalPlatformHandle|s that are connected
-// by a suitable (platform-specific) bidirectional "pipe" (e.g., socket on
-// POSIX, named pipe on Windows). The resulting handles can then be used in the
-// same process (e.g., in tests) or between processes. (The "server" handle is
-// the one that will be used in the process that created the pair, whereas the
-// "client" handle is the one that will be used in a different process.)
-//
-// This class provides facilities for passing the client handle to a child
-// process. The parent should call |PrepareToPassClientHandlelToChildProcess()|
-// to get the data needed to do this, spawn the child using that data, and then
-// call |ChildProcessLaunched()|. Note that on Windows this facility (will) only
-// work on Vista and later (TODO(vtl)).
-//
-// Note: |PlatformChannelPair()|, |PassClientHandleFromParentProcess()| and
-// |PrepareToPassClientHandleToChildProcess()| have platform-specific
-// implementations.
-//
-// Note: On POSIX platforms, to write to the "pipe", use
-// |PlatformChannel{Write,Writev}()| (from platform_channel_utils_posix.h)
-// instead of |write()|, |writev()|, etc. Otherwise, you have to worry about
-// platform differences in suppressing |SIGPIPE|.
-class MOJO_SYSTEM_IMPL_EXPORT PlatformChannelPair {
- public:
- static const char kMojoPlatformChannelHandleSwitch[];
-
- // If |client_is_blocking| is true, then the client handle only supports
- // blocking reads and writes. The default is nonblocking.
- PlatformChannelPair(bool client_is_blocking = false);
- ~PlatformChannelPair();
-
- ScopedInternalPlatformHandle PassServerHandle();
-
- // For in-process use (e.g., in tests or to pass over another channel).
- ScopedInternalPlatformHandle PassClientHandle();
-
- // To be called in the child process, after the parent process called
- // |PrepareToPassClientHandleToChildProcess()| and launched the child (using
- // the provided data), to create a client handle connected to the server
- // handle (in the parent process).
- // TODO(jcivelli): remove the command_line param. http://crbug.com/670106
- static ScopedInternalPlatformHandle PassClientHandleFromParentProcess(
- const base::CommandLine& command_line);
-
- // Like above, but gets the handle from the passed in string.
- static ScopedInternalPlatformHandle
- PassClientHandleFromParentProcessFromString(const std::string& value);
-
- // Prepares to pass the client channel to a new child process, to be launched
- // using |LaunchProcess()| (from base/launch.h). Modifies |*command_line| and
- // |*handle_passing_info| as needed.
- // Note: For Windows, this method only works on Vista and later.
- void PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line,
- HandlePassingInformation* handle_passing_info) const;
-
- // Like above, but returns a string instead of changing the command line.
- std::string PrepareToPassClientHandleToChildProcessAsString(
- HandlePassingInformation* handle_passing_info) const;
-
-#if defined(OS_FUCHSIA)
- // Like above, but accepts a caller-supplied client |handle|.
- // TODO(wez): Consider incorporating this call into other platform
- // implementations.
- static void PrepareToPassHandleToChildProcess(
- const InternalPlatformHandle& handle,
- base::CommandLine* command_line,
- HandlePassingInformation* handle_passing_info);
-#endif
-
- // To be called once the child process has been successfully launched, to do
- // any cleanup necessary.
- void ChildProcessLaunched();
-
- private:
- ScopedInternalPlatformHandle server_handle_;
- ScopedInternalPlatformHandle client_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformChannelPair);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_
diff --git a/chromium/mojo/edk/embedder/platform_channel_pair_fuchsia.cc b/chromium/mojo/edk/embedder/platform_channel_pair_fuchsia.cc
deleted file mode 100644
index 17f6b1c6955..00000000000
--- a/chromium/mojo/edk/embedder/platform_channel_pair_fuchsia.cc
+++ /dev/null
@@ -1,96 +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/embedder/platform_channel_pair.h"
-
-#include <zircon/process.h>
-#include <zircon/processargs.h>
-#include <zircon/syscalls.h>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "mojo/edk/embedder/platform_handle.h"
-
-namespace mojo {
-namespace edk {
-
-namespace {
-
-std::string PrepareToPassHandleToChildProcessAsString(
- const InternalPlatformHandle& handle,
- HandlePassingInformation* handle_passing_info) {
- DCHECK(handle.is_valid());
-
- const uint32_t id = PA_HND(PA_USER0, 0);
- handle_passing_info->push_back({id, handle.as_handle()});
-
- return base::UintToString(id);
-}
-
-} // namespace
-
-PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) {
- zx_handle_t handles[2] = {};
- zx_status_t result = zx_channel_create(0, &handles[0], &handles[1]);
- CHECK_EQ(ZX_OK, result);
-
- server_handle_.reset(InternalPlatformHandle::ForHandle(handles[0]));
- DCHECK(server_handle_.is_valid());
- client_handle_.reset(InternalPlatformHandle::ForHandle(handles[1]));
- DCHECK(client_handle_.is_valid());
-}
-
-// static
-ScopedInternalPlatformHandle
-PlatformChannelPair::PassClientHandleFromParentProcess(
- const base::CommandLine& command_line) {
- std::string handle_string =
- command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
- return PassClientHandleFromParentProcessFromString(handle_string);
-}
-
-ScopedInternalPlatformHandle
-PlatformChannelPair::PassClientHandleFromParentProcessFromString(
- const std::string& value) {
- unsigned int id = 0;
- if (value.empty() || !base::StringToUint(value, &id)) {
- LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
- return ScopedInternalPlatformHandle();
- }
- return ScopedInternalPlatformHandle(InternalPlatformHandle::ForHandle(
- zx_get_startup_handle(base::checked_cast<uint32_t>(id))));
-}
-
-void PlatformChannelPair::PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line,
- HandlePassingInformation* handle_passing_info) const {
- return PrepareToPassHandleToChildProcess(client_handle_.get(), command_line,
- handle_passing_info);
-}
-
-// static
-void PlatformChannelPair::PrepareToPassHandleToChildProcess(
- const InternalPlatformHandle& handle,
- base::CommandLine* command_line,
- HandlePassingInformation* handle_passing_info) {
- DCHECK(command_line);
-
- // Log a warning if the command line already has the switch, but "clobber" it
- // anyway, since it's reasonably likely that all the switches were just copied
- // from the parent.
- LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch))
- << "Child command line already has switch --"
- << kMojoPlatformChannelHandleSwitch << "="
- << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
- // (Any existing switch won't actually be removed from the command line, but
- // the last one appended takes precedence.)
- command_line->AppendSwitchASCII(
- kMojoPlatformChannelHandleSwitch,
- PrepareToPassHandleToChildProcessAsString(handle, handle_passing_info));
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_channel_pair_posix.cc b/chromium/mojo/edk/embedder/platform_channel_pair_posix.cc
deleted file mode 100644
index 5b206658626..00000000000
--- a/chromium/mojo/edk/embedder/platform_channel_pair_posix.cc
+++ /dev/null
@@ -1,173 +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/embedder/platform_channel_pair.h"
-
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <limits>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/posix/global_descriptors.h"
-#include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_handle.h"
-
-#if !defined(OS_NACL_SFI)
-#include <sys/socket.h>
-#else
-#include "native_client/src/public/imc_syscalls.h"
-#endif
-
-#if !defined(SO_PEEK_OFF)
-#define SO_PEEK_OFF 42
-#endif
-
-namespace mojo {
-namespace edk {
-
-namespace {
-
-#if defined(OS_ANDROID)
-enum {
- // Leave room for any other descriptors defined in content for example.
- // TODO(jcivelli): consider changing base::GlobalDescriptors to generate a
- // key when setting the file descriptor (http://crbug.com/676442).
- kAndroidClientHandleDescriptor =
- base::GlobalDescriptors::kBaseDescriptor + 10000,
-};
-#else
-bool IsTargetDescriptorUsed(
- const base::FileHandleMappingVector& file_handle_mapping,
- int target_fd) {
- for (size_t i = 0; i < file_handle_mapping.size(); i++) {
- if (file_handle_mapping[i].second == target_fd)
- return true;
- }
- return false;
-}
-#endif
-
-} // namespace
-
-PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) {
- // Create the Unix domain socket.
- int fds[2];
- // TODO(vtl): Maybe fail gracefully if |socketpair()| fails.
-
-#if defined(OS_NACL_SFI)
- PCHECK(imc_socketpair(fds) == 0);
-#else
- PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
-
- // Set the ends to nonblocking.
- PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0);
- if (!client_is_blocking)
- PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0);
-
-#if defined(OS_MACOSX)
- // This turns off |SIGPIPE| when writing to a closed socket (causing it to
- // fail with |EPIPE| instead). On Linux, we have to use |send...()| with
- // |MSG_NOSIGNAL| -- which is not supported on Mac -- instead.
- int no_sigpipe = 1;
- PCHECK(setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
- sizeof(no_sigpipe)) == 0);
- PCHECK(setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
- sizeof(no_sigpipe)) == 0);
-#endif // defined(OS_MACOSX)
-#endif // defined(OS_NACL_SFI)
-
- server_handle_.reset(InternalPlatformHandle(fds[0]));
- DCHECK(server_handle_.is_valid());
- client_handle_.reset(InternalPlatformHandle(fds[1]));
- DCHECK(client_handle_.is_valid());
-}
-
-// static
-ScopedInternalPlatformHandle
-PlatformChannelPair::PassClientHandleFromParentProcess(
- const base::CommandLine& command_line) {
- std::string client_fd_string =
- command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
- return PassClientHandleFromParentProcessFromString(client_fd_string);
-}
-
-ScopedInternalPlatformHandle
-PlatformChannelPair::PassClientHandleFromParentProcessFromString(
- const std::string& value) {
- int client_fd = -1;
-#if defined(OS_ANDROID)
- base::GlobalDescriptors::Key key = -1;
- if (value.empty() || !base::StringToUint(value, &key)) {
- LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
- return ScopedInternalPlatformHandle();
- }
- client_fd = base::GlobalDescriptors::GetInstance()->Get(key);
-#else
- if (value.empty() ||
- !base::StringToInt(value, &client_fd) ||
- client_fd < base::GlobalDescriptors::kBaseDescriptor) {
- LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
- return ScopedInternalPlatformHandle();
- }
-#endif
- return ScopedInternalPlatformHandle(InternalPlatformHandle(client_fd));
-}
-
-void PlatformChannelPair::PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line,
- base::FileHandleMappingVector* handle_passing_info) const {
- DCHECK(command_line);
-
- // Log a warning if the command line already has the switch, but "clobber" it
- // anyway, since it's reasonably likely that all the switches were just copied
- // from the parent.
- LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch))
- << "Child command line already has switch --"
- << kMojoPlatformChannelHandleSwitch << "="
- << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
- // (Any existing switch won't actually be removed from the command line, but
- // the last one appended takes precedence.)
- command_line->AppendSwitchASCII(
- kMojoPlatformChannelHandleSwitch,
- PrepareToPassClientHandleToChildProcessAsString(handle_passing_info));
-}
-
-std::string
-PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString(
- HandlePassingInformation* handle_passing_info) const {
-#if defined(OS_ANDROID)
- int fd = client_handle_.get().handle;
- handle_passing_info->push_back(
- std::pair<int, int>(fd, kAndroidClientHandleDescriptor));
- return base::UintToString(kAndroidClientHandleDescriptor);
-#else
- DCHECK(handle_passing_info);
- // This is an arbitrary sanity check. (Note that this guarantees that the loop
- // below will terminate sanely.)
- CHECK_LT(handle_passing_info->size(), 1000u);
-
- DCHECK(client_handle_.is_valid());
-
- // Find a suitable FD to map our client handle to in the child process.
- // This has quadratic time complexity in the size of |*handle_passing_info|,
- // but |*handle_passing_info| should be very small (usually/often empty).
- int target_fd = base::GlobalDescriptors::kBaseDescriptor;
- while (IsTargetDescriptorUsed(*handle_passing_info, target_fd))
- target_fd++;
-
- handle_passing_info->push_back(
- std::pair<int, int>(client_handle_.get().handle, target_fd));
- return base::IntToString(target_fd);
-#endif
-}
-
-} // 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
deleted file mode 100644
index 9955b2103db..00000000000
--- a/chromium/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc
+++ /dev/null
@@ -1,257 +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/embedder/platform_channel_pair.h"
-
-#include <errno.h>
-#include <poll.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <utility>
-#include <vector>
-
-#include "base/containers/circular_deque.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "mojo/edk/embedder/platform_channel_utils_posix.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace edk {
-namespace {
-
-void WaitReadable(InternalPlatformHandle h) {
- struct pollfd pfds = {};
- pfds.fd = h.handle;
- pfds.events = POLLIN;
- CHECK_EQ(poll(&pfds, 1, -1), 1);
-}
-
-class PlatformChannelPairPosixTest : public testing::Test {
- public:
- PlatformChannelPairPosixTest() {}
- ~PlatformChannelPairPosixTest() override {}
-
- void SetUp() override {
- // Make sure |SIGPIPE| isn't being ignored.
- struct sigaction action = {};
- action.sa_handler = SIG_DFL;
- ASSERT_EQ(0, sigaction(SIGPIPE, &action, &old_action_));
- }
-
- void TearDown() override {
- // Restore the |SIGPIPE| handler.
- ASSERT_EQ(0, sigaction(SIGPIPE, &old_action_, nullptr));
- }
-
- private:
- struct sigaction old_action_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformChannelPairPosixTest);
-};
-
-TEST_F(PlatformChannelPairPosixTest, NoSigPipe) {
- PlatformChannelPair channel_pair;
- ScopedInternalPlatformHandle server_handle = channel_pair.PassServerHandle();
- ScopedInternalPlatformHandle client_handle = channel_pair.PassClientHandle();
-
- // Write to the client.
- static const char kHello[] = "hello";
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- write(client_handle.get().handle, kHello, sizeof(kHello)));
-
- // Close the client.
- client_handle.reset();
-
- // Read from the server; this should be okay.
- char buffer[100] = {};
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- read(server_handle.get().handle, buffer, sizeof(buffer)));
- EXPECT_STREQ(kHello, buffer);
-
- // Try reading again.
- ssize_t result = read(server_handle.get().handle, buffer, sizeof(buffer));
- // We should probably get zero (for "end of file"), but -1 would also be okay.
- EXPECT_TRUE(result == 0 || result == -1);
- if (result == -1)
- PLOG(WARNING) << "read (expected 0 for EOF)";
-
- // Test our replacement for |write()|/|send()|.
- result = PlatformChannelWrite(server_handle, kHello, sizeof(kHello));
- EXPECT_EQ(-1, result);
- if (errno != EPIPE)
- PLOG(WARNING) << "write (expected EPIPE)";
-
- // Test our replacement for |writev()|/|sendv()|.
- struct iovec iov[2] = {{const_cast<char*>(kHello), sizeof(kHello)},
- {const_cast<char*>(kHello), sizeof(kHello)}};
- result = PlatformChannelWritev(server_handle, iov, 2);
- EXPECT_EQ(-1, result);
- if (errno != EPIPE)
- PLOG(WARNING) << "write (expected EPIPE)";
-}
-
-TEST_F(PlatformChannelPairPosixTest, SendReceiveData) {
- PlatformChannelPair channel_pair;
- ScopedInternalPlatformHandle server_handle = channel_pair.PassServerHandle();
- ScopedInternalPlatformHandle client_handle = channel_pair.PassClientHandle();
-
- for (size_t i = 0; i < 10; i++) {
- std::string send_string(1 << i, 'A' + i);
-
- EXPECT_EQ(static_cast<ssize_t>(send_string.size()),
- PlatformChannelWrite(server_handle, send_string.data(),
- send_string.size()));
-
- WaitReadable(client_handle.get());
-
- char buf[10000] = {};
- base::circular_deque<ScopedInternalPlatformHandle> received_handles;
- ssize_t result = PlatformChannelRecvmsg(client_handle, buf, sizeof(buf),
- &received_handles);
- EXPECT_EQ(static_cast<ssize_t>(send_string.size()), result);
- EXPECT_EQ(send_string, std::string(buf, static_cast<size_t>(result)));
- EXPECT_TRUE(received_handles.empty());
- }
-}
-
-TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- static const char kHello[] = "hello";
-
- PlatformChannelPair channel_pair;
- ScopedInternalPlatformHandle server_handle = channel_pair.PassServerHandle();
- ScopedInternalPlatformHandle client_handle = channel_pair.PassClientHandle();
-
-// Reduce the number of FDs opened on OS X to avoid test flake.
-#if defined(OS_MACOSX)
- const size_t kNumHandlesToSend = kPlatformChannelMaxNumHandles / 2;
-#else
- const size_t kNumHandlesToSend = kPlatformChannelMaxNumHandles;
-#endif
-
- for (size_t i = 1; i < kNumHandlesToSend; i++) {
- // Make |i| files, with the j-th file consisting of j copies of the digit
- // |c|.
- const char c = '0' + (i % 10);
- std::vector<ScopedInternalPlatformHandle> platform_handles;
- for (size_t j = 1; j <= i; j++) {
- base::FilePath unused;
- base::ScopedFILE fp(
- 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(
- test::InternalPlatformHandleFromFILE(std::move(fp)));
- ASSERT_TRUE(platform_handles.back().is_valid());
- }
-
- // Send the FDs (+ "hello").
- struct iovec iov = {const_cast<char*>(kHello), sizeof(kHello)};
- // We assume that the |sendmsg()| actually sends all the data.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- PlatformChannelSendmsgWithHandles(server_handle, &iov, 1,
- std::move(platform_handles)));
-
- WaitReadable(client_handle.get());
-
- char buf[10000] = {};
- base::circular_deque<ScopedInternalPlatformHandle> received_handles;
- // We assume that the |recvmsg()| actually reads all the data.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- PlatformChannelRecvmsg(client_handle, buf, sizeof(buf),
- &received_handles));
- EXPECT_STREQ(kHello, buf);
- EXPECT_EQ(i, received_handles.size());
-
- for (size_t j = 0; j < received_handles.size(); j++) {
- base::ScopedFILE fp(test::FILEFromInternalPlatformHandle(
- std::move(received_handles.front()), "rb"));
- received_handles.pop_front();
- ASSERT_TRUE(fp);
- rewind(fp.get());
- char read_buf[kNumHandlesToSend];
- size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get());
- EXPECT_EQ(j + 1, bytes_read);
- EXPECT_EQ(std::string(j + 1, c), std::string(read_buf, bytes_read));
- }
- }
-}
-
-TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- static const char kHello[] = "hello";
-
- PlatformChannelPair channel_pair;
- ScopedInternalPlatformHandle server_handle = channel_pair.PassServerHandle();
- ScopedInternalPlatformHandle client_handle = channel_pair.PassClientHandle();
-
- const std::string file_contents("hello world");
-
- {
- base::FilePath unused;
- base::ScopedFILE fp(
- base::CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused));
- ASSERT_TRUE(fp);
- ASSERT_EQ(file_contents.size(),
- fwrite(file_contents.data(), 1, file_contents.size(), fp.get()));
- std::vector<ScopedInternalPlatformHandle> platform_handles(1);
- platform_handles[0] = test::InternalPlatformHandleFromFILE(std::move(fp));
- ASSERT_TRUE(platform_handles.back().is_valid());
-
- // Send the FD (+ "hello").
- struct iovec iov = {const_cast<char*>(kHello), sizeof(kHello)};
- // We assume that the |sendmsg()| actually sends all the data.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- PlatformChannelSendmsgWithHandles(server_handle, &iov, 1,
- std::move(platform_handles)));
- }
-
- WaitReadable(client_handle.get());
-
- // Start with an invalid handle in the vector.
- base::circular_deque<ScopedInternalPlatformHandle> received_handles;
- received_handles.push_back(ScopedInternalPlatformHandle());
-
- char buf[100] = {};
- // We assume that the |recvmsg()| actually reads all the data.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
- PlatformChannelRecvmsg(client_handle, buf, sizeof(buf),
- &received_handles));
- EXPECT_STREQ(kHello, buf);
- ASSERT_EQ(2u, received_handles.size());
- EXPECT_FALSE(received_handles[0].is_valid());
- EXPECT_TRUE(received_handles[1].is_valid());
-
- {
- base::ScopedFILE fp(test::FILEFromInternalPlatformHandle(
- std::move(received_handles[1]), "rb"));
- ASSERT_TRUE(fp);
- rewind(fp.get());
- char read_buf[100];
- size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get());
- EXPECT_EQ(file_contents.size(), bytes_read);
- EXPECT_EQ(file_contents, std::string(read_buf, bytes_read));
- }
-}
-
-} // namespace
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_channel_pair_win.cc b/chromium/mojo/edk/embedder/platform_channel_pair_win.cc
deleted file mode 100644
index 7981cc6c013..00000000000
--- a/chromium/mojo/edk/embedder/platform_channel_pair_win.cc
+++ /dev/null
@@ -1,122 +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/embedder/platform_channel_pair.h"
-
-#include <windows.h>
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "mojo/edk/embedder/platform_handle.h"
-
-namespace mojo {
-namespace edk {
-
-namespace {
-
-std::wstring GeneratePipeName() {
- return base::StringPrintf(L"\\\\.\\pipe\\mojo.%u.%u.%I64u",
- GetCurrentProcessId(), GetCurrentThreadId(),
- base::RandUint64());
-}
-
-} // namespace
-
-PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) {
- std::wstring pipe_name = GeneratePipeName();
-
- DWORD kOpenMode =
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE;
- const DWORD kPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE;
- server_handle_.reset(InternalPlatformHandle(
- CreateNamedPipeW(pipe_name.c_str(), kOpenMode, kPipeMode,
- 1, // Max instances.
- 4096, // Out buffer size.
- 4096, // In buffer size.
- 5000, // Timeout in milliseconds.
- nullptr))); // Default security descriptor.
- PCHECK(server_handle_.is_valid());
-
- const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE;
- // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate
- // the client.
- DWORD kFlags = SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS;
- if (!client_is_blocking)
- kFlags |= FILE_FLAG_OVERLAPPED;
- // Allow the handle to be inherited by child processes.
- SECURITY_ATTRIBUTES security_attributes = {
- sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE};
- client_handle_.reset(InternalPlatformHandle(
- CreateFileW(pipe_name.c_str(), kDesiredAccess,
- 0, // No sharing.
- &security_attributes, OPEN_EXISTING, kFlags,
- nullptr))); // No template file.
- PCHECK(client_handle_.is_valid());
-
- // Since a client has connected, ConnectNamedPipe() should return zero and
- // GetLastError() should return ERROR_PIPE_CONNECTED.
- CHECK(!ConnectNamedPipe(server_handle_.get().handle, nullptr));
- PCHECK(GetLastError() == ERROR_PIPE_CONNECTED);
-}
-
-// static
-ScopedInternalPlatformHandle
-PlatformChannelPair::PassClientHandleFromParentProcess(
- const base::CommandLine& command_line) {
- std::string client_handle_string =
- command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
- return PassClientHandleFromParentProcessFromString(client_handle_string);
-}
-
-ScopedInternalPlatformHandle
-PlatformChannelPair::PassClientHandleFromParentProcessFromString(
- const std::string& value) {
- int client_handle_value = 0;
- if (value.empty() ||
- !base::StringToInt(value, &client_handle_value)) {
- LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
- return ScopedInternalPlatformHandle();
- }
-
- return ScopedInternalPlatformHandle(
- InternalPlatformHandle(LongToHandle(client_handle_value)));
-}
-
-void PlatformChannelPair::PrepareToPassClientHandleToChildProcess(
- base::CommandLine* command_line,
- base::HandlesToInheritVector* handle_passing_info) const {
- DCHECK(command_line);
-
- // Log a warning if the command line already has the switch, but "clobber" it
- // anyway, since it's reasonably likely that all the switches were just copied
- // from the parent.
- LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch))
- << "Child command line already has switch --"
- << kMojoPlatformChannelHandleSwitch << "="
- << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
- // (Any existing switch won't actually be removed from the command line, but
- // the last one appended takes precedence.)
- command_line->AppendSwitchASCII(
- kMojoPlatformChannelHandleSwitch,
- PrepareToPassClientHandleToChildProcessAsString(handle_passing_info));
-}
-
-std::string
-PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString(
- HandlePassingInformation* handle_passing_info) const {
- DCHECK(handle_passing_info);
- DCHECK(client_handle_.is_valid());
-
- handle_passing_info->push_back(client_handle_.get().handle);
-
- return base::IntToString(HandleToLong(client_handle_.get().handle));
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_channel_utils_posix.cc b/chromium/mojo/edk/embedder/platform_channel_utils_posix.cc
deleted file mode 100644
index 8ac67dc2bce..00000000000
--- a/chromium/mojo/edk/embedder/platform_channel_utils_posix.cc
+++ /dev/null
@@ -1,250 +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/embedder/platform_channel_utils_posix.h"
-
-#include <stddef.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include <utility>
-
-#include "base/containers/queue.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "build/build_config.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-
-#if !defined(OS_NACL)
-#include <sys/uio.h>
-#endif
-
-#if !defined(SO_PEEK_OFF)
-#define SO_PEEK_OFF 42
-#endif
-
-namespace mojo {
-namespace edk {
-namespace {
-
-#if !defined(OS_NACL)
-bool IsRecoverableError() {
- return errno == ECONNABORTED || errno == EMFILE || errno == ENFILE ||
- errno == ENOMEM || errno == ENOBUFS;
-}
-
-bool GetPeerEuid(InternalPlatformHandle handle, uid_t* peer_euid) {
- DCHECK(peer_euid);
-#if defined(OS_MACOSX) || defined(OS_OPENBSD) || defined(OS_FREEBSD)
- uid_t socket_euid;
- gid_t socket_gid;
- if (getpeereid(handle.handle, &socket_euid, &socket_gid) < 0) {
- PLOG(ERROR) << "getpeereid " << handle.handle;
- return false;
- }
- *peer_euid = socket_euid;
- return true;
-#else
- struct ucred cred;
- socklen_t cred_len = sizeof(cred);
- if (getsockopt(handle.handle, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) <
- 0) {
- PLOG(ERROR) << "getsockopt " << handle.handle;
- return false;
- }
- if (static_cast<unsigned>(cred_len) < sizeof(cred)) {
- NOTREACHED() << "Truncated ucred from SO_PEERCRED?";
- return false;
- }
- *peer_euid = cred.uid;
- return true;
-#endif
-}
-
-bool IsPeerAuthorized(InternalPlatformHandle 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
-// |write()|/|writev().) On Mac, |SIGPIPE| is suppressed by setting the
-// |SO_NOSIGPIPE| option on the socket.
-//
-// Performance notes:
-// - On Linux, we have to use |send()|/|sendmsg()| rather than
-// |write()|/|writev()| in order to suppress |SIGPIPE|. This is okay, since
-// |send()| is (slightly) faster than |write()| (!), while |sendmsg()| is
-// quite comparable to |writev()|.
-// - On Mac, we may use |write()|/|writev()|. Here, |write()| is considerably
-// faster than |send()|, whereas |sendmsg()| is quite comparable to
-// |writev()|.
-// - On both platforms, an appropriate |sendmsg()|/|writev()| is considerably
-// faster than two |send()|s/|write()|s.
-// - Relative numbers (minimum real times from 10 runs) for one |write()| of
-// 1032 bytes, one |send()| of 1032 bytes, one |writev()| of 32+1000 bytes,
-// one |sendmsg()| of 32+1000 bytes, two |write()|s of 32 and 1000 bytes, two
-// |send()|s of 32 and 1000 bytes:
-// - Linux: 0.81 s, 0.77 s, 0.87 s, 0.89 s, 1.31 s, 1.22 s
-// - Mac: 2.21 s, 2.91 s, 2.98 s, 3.08 s, 3.59 s, 4.74 s
-
-// Flags to use with calling |send()| or |sendmsg()| (see above).
-#if defined(OS_MACOSX) || defined(OS_FUCHSIA)
-const int kSendFlags = 0;
-#else
-const int kSendFlags = MSG_NOSIGNAL;
-#endif
-
-ssize_t PlatformChannelWrite(const ScopedInternalPlatformHandle& h,
- const void* bytes,
- size_t num_bytes) {
- DCHECK(h.is_valid());
- DCHECK(bytes);
- DCHECK_GT(num_bytes, 0u);
-
-#if defined(OS_MACOSX) || defined(OS_NACL_NONSFI)
- // send() is not available under NaCl-nonsfi.
- return HANDLE_EINTR(write(h.get().handle, bytes, num_bytes));
-#else
- return send(h.get().handle, bytes, num_bytes, kSendFlags);
-#endif
-}
-
-ssize_t PlatformChannelWritev(const ScopedInternalPlatformHandle& h,
- struct iovec* iov,
- size_t num_iov) {
- DCHECK(h.is_valid());
- DCHECK(iov);
- DCHECK_GT(num_iov, 0u);
-
-#if defined(OS_MACOSX)
- return HANDLE_EINTR(writev(h.get().handle, iov, static_cast<int>(num_iov)));
-#else
- struct msghdr msg = {};
- msg.msg_iov = iov;
- msg.msg_iovlen = num_iov;
- return HANDLE_EINTR(sendmsg(h.get().handle, &msg, kSendFlags));
-#endif
-}
-
-ssize_t PlatformChannelSendmsgWithHandles(
- const ScopedInternalPlatformHandle& h,
- struct iovec* iov,
- size_t num_iov,
- const std::vector<ScopedInternalPlatformHandle>& platform_handles) {
- DCHECK(iov);
- DCHECK_GT(num_iov, 0u);
- DCHECK(!platform_handles.empty());
- DCHECK_LE(platform_handles.size(), kPlatformChannelMaxNumHandles);
-
- char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))];
- struct msghdr msg = {};
- msg.msg_iov = iov;
- msg.msg_iovlen = num_iov;
- msg.msg_control = cmsg_buf;
- msg.msg_controllen = CMSG_LEN(platform_handles.size() * sizeof(int));
- struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(platform_handles.size() * sizeof(int));
- for (size_t i = 0; i < platform_handles.size(); i++) {
- DCHECK(platform_handles[i].is_valid());
- reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] =
- platform_handles[i].get().handle;
- }
-
- return HANDLE_EINTR(sendmsg(h.get().handle, &msg, kSendFlags));
-}
-
-ssize_t PlatformChannelRecvmsg(
- const ScopedInternalPlatformHandle& h,
- void* buf,
- size_t num_bytes,
- base::circular_deque<ScopedInternalPlatformHandle>* platform_handles,
- bool block) {
- DCHECK(buf);
- DCHECK_GT(num_bytes, 0u);
- DCHECK(platform_handles);
-
- struct iovec iov = {buf, num_bytes};
- char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))];
- struct msghdr msg = {};
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = cmsg_buf;
- msg.msg_controllen = sizeof(cmsg_buf);
-
- ssize_t result =
- HANDLE_EINTR(recvmsg(h.get().handle, &msg, block ? 0 : MSG_DONTWAIT));
- if (result < 0)
- return result;
-
- // Success; no control messages.
- if (msg.msg_controllen == 0)
- return result;
-
- DCHECK(!(msg.msg_flags & MSG_CTRUNC));
-
- for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- size_t payload_length = cmsg->cmsg_len - CMSG_LEN(0);
- DCHECK_EQ(payload_length % sizeof(int), 0u);
- size_t num_fds = payload_length / sizeof(int);
- const int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
- for (size_t i = 0; i < num_fds; i++) {
- platform_handles->push_back(
- ScopedInternalPlatformHandle(InternalPlatformHandle(fds[i])));
- DCHECK(platform_handles->back().is_valid());
- }
- }
- }
-
- return result;
-}
-
-bool ServerAcceptConnection(const ScopedInternalPlatformHandle& server_handle,
- ScopedInternalPlatformHandle* connection_handle,
- bool check_peer_user) {
- DCHECK(server_handle.is_valid());
- connection_handle->reset();
-#if defined(OS_NACL)
- NOTREACHED();
- return false;
-#else
- ScopedInternalPlatformHandle accept_handle(InternalPlatformHandle(
- HANDLE_EINTR(accept(server_handle.get().handle, NULL, 0))));
- if (!accept_handle.is_valid())
- return IsRecoverableError();
-
- // Verify that the IPC channel peer is running as the same user.
- if (check_peer_user && !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
deleted file mode 100644
index e5a4b0096a7..00000000000
--- a/chromium/mojo/edk/embedder/platform_channel_utils_posix.h
+++ /dev/null
@@ -1,79 +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_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
-
-#include <stddef.h>
-#include <sys/types.h> // For |ssize_t|.
-
-#include <vector>
-
-#include "base/containers/circular_deque.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-struct iovec; // Declared in <sys/uio.h>.
-
-namespace mojo {
-namespace edk {
-class ScopedInternalPlatformHandle;
-
-// The maximum number of handles that can be sent "at once" using
-// |PlatformChannelSendmsgWithHandles()|. This must be less than the Linux
-// kernel's SCM_MAX_FD which is 253.
-const size_t kPlatformChannelMaxNumHandles = 128;
-
-// Use these to write to a socket created using |PlatformChannelPair| (or
-// equivalent). These are like |write()| and |writev()|, but handle |EINTR| and
-// never raise |SIGPIPE|. (Note: On Mac, the suppression of |SIGPIPE| is set up
-// by |PlatformChannelPair|.)
-MOJO_SYSTEM_IMPL_EXPORT ssize_t
-PlatformChannelWrite(const ScopedInternalPlatformHandle& h,
- const void* bytes,
- size_t num_bytes);
-MOJO_SYSTEM_IMPL_EXPORT ssize_t
-PlatformChannelWritev(const ScopedInternalPlatformHandle& h,
- struct iovec* iov,
- size_t num_iov);
-
-// Writes data, and the given set of |InternalPlatformHandle|s (i.e., file
-// descriptors) over the Unix domain socket given by |h| (e.g., created using
-// |PlatformChannelPair()|). All the handles must be valid, and there must be at
-// least one and at most |kPlatformChannelMaxNumHandles| handles. The return
-// value is as for |sendmsg()|, namely -1 on failure and otherwise the number of
-// bytes of data sent on success (note that this may not be all the data
-// specified by |iov|). (The handles are not closed, regardless of success or
-// failure.)
-MOJO_SYSTEM_IMPL_EXPORT ssize_t PlatformChannelSendmsgWithHandles(
- const ScopedInternalPlatformHandle& h,
- struct iovec* iov,
- size_t num_iov,
- const std::vector<ScopedInternalPlatformHandle>& platform_handles);
-
-// Wrapper around |recvmsg()|, which will extract any attached file descriptors
-// (in the control message) to |InternalPlatformHandle|s (and append them to
-// |platform_handles|). (This also handles |EINTR|.)
-MOJO_SYSTEM_IMPL_EXPORT ssize_t PlatformChannelRecvmsg(
- const ScopedInternalPlatformHandle& h,
- void* buf,
- size_t num_bytes,
- base::circular_deque<ScopedInternalPlatformHandle>* 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. If |check_peer_user| is True, the
-// connection will be rejected if the peer is running as a different user.
-MOJO_SYSTEM_IMPL_EXPORT bool ServerAcceptConnection(
- const ScopedInternalPlatformHandle& server_handle,
- ScopedInternalPlatformHandle* connection_handle,
- bool check_peer_user = true);
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
diff --git a/chromium/mojo/edk/embedder/platform_handle.cc b/chromium/mojo/edk/embedder/platform_handle.cc
deleted file mode 100644
index fce7177348a..00000000000
--- a/chromium/mojo/edk/embedder/platform_handle.cc
+++ /dev/null
@@ -1,109 +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/edk/embedder/platform_handle.h"
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#elif defined(OS_FUCHSIA)
-#include <unistd.h>
-#include <zircon/status.h>
-#include <zircon/syscalls.h>
-#elif defined(OS_POSIX)
-#include <unistd.h>
-#endif
-
-#include "base/logging.h"
-
-#if defined(OS_WIN)
-#include "base/optional.h"
-#include "mojo/edk/system/scoped_process_handle.h"
-#endif
-
-namespace mojo {
-namespace edk {
-
-void InternalPlatformHandle::CloseIfNecessary() {
-#if defined(OS_WIN)
- // Take local ownership of the process handle in |owning_process| if it's
- // a handle to a remote process. We do this before the generic handle validity
- // test below because even if the platform handle has been taken by someone
- // else, we may still own a remote process handle and it needs to be closed
- // before we return.
- base::Optional<ScopedProcessHandle> remote_process_handle;
- if (owning_process != base::GetCurrentProcessHandle()) {
- remote_process_handle.emplace(owning_process);
- owning_process = base::GetCurrentProcessHandle();
- }
-#endif
-
- if (!is_valid())
- return;
-
-#if defined(OS_WIN)
- if (remote_process_handle) {
- // This handle may have been duplicated to a new target process but not yet
- // sent there. In this case CloseHandle should NOT be called. From MSDN
- // documentation for DuplicateHandle[1]:
- //
- // Normally the target process closes a duplicated handle when that
- // process is finished using the handle. To close a duplicated handle
- // from the source process, call DuplicateHandle with the following
- // parameters:
- //
- // * Set hSourceProcessHandle to the target process from the
- // call that created the handle.
- // * Set hSourceHandle to the duplicated handle to close.
- // * Set lpTargetHandle [sic] to NULL. (N.B.: This appears to be a
- // documentation bug; what matters is that hTargetProcessHandle is
- // NULL.)
- // * Set dwOptions to DUPLICATE_CLOSE_SOURCE.
- //
- // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251
- //
- // NOTE: It's possible for this operation to fail if the owning process
- // was terminated or is in the process of being terminated. Either way,
- // there is nothing we can reasonably do about failure, so we ignore it.
- ::DuplicateHandle(remote_process_handle->get(), handle, NULL, &handle, 0,
- FALSE, DUPLICATE_CLOSE_SOURCE);
- return;
- }
-
- bool success = !!CloseHandle(handle);
- DPCHECK(success);
- handle = INVALID_HANDLE_VALUE;
-#elif defined(OS_FUCHSIA)
- if (handle != ZX_HANDLE_INVALID) {
- zx_status_t result = zx_handle_close(handle);
- DCHECK_EQ(ZX_OK, result) << "CloseIfNecessary(zx_handle_close): "
- << zx_status_get_string(result);
- handle = ZX_HANDLE_INVALID;
- }
- if (fd >= 0) {
- bool success = (close(fd) == 0);
- DPCHECK(success);
- fd = -1;
- }
-#elif defined(OS_POSIX)
- if (type == Type::POSIX) {
- bool success = (close(handle) == 0);
- DPCHECK(success);
- handle = -1;
- }
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- else if (type == Type::MACH) {
- kern_return_t rv = mach_port_deallocate(mach_task_self(), port);
- DPCHECK(rv == KERN_SUCCESS);
- port = MACH_PORT_NULL;
- }
-#endif // defined(OS_MACOSX) && !defined(OS_IOS)
-#else
-#error "Platform not yet supported."
-#endif // defined(OS_WIN)
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_handle.h b/chromium/mojo/edk/embedder/platform_handle.h
deleted file mode 100644
index 302412261ce..00000000000
--- a/chromium/mojo/edk/embedder/platform_handle.h
+++ /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.
-
-#ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_
-
-#include "build/build_config.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-
-#include "base/process/process_handle.h"
-#elif defined(OS_FUCHSIA)
-#include <fdio/limits.h>
-#include <zircon/syscalls.h>
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
-#include <mach/mach.h>
-#endif
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace edk {
-
-#if defined(OS_WIN)
-struct MOJO_SYSTEM_IMPL_EXPORT InternalPlatformHandle {
- InternalPlatformHandle() : InternalPlatformHandle(INVALID_HANDLE_VALUE) {}
- explicit InternalPlatformHandle(HANDLE handle)
- : handle(handle), owning_process(base::GetCurrentProcessHandle()) {}
-
- void CloseIfNecessary();
-
- bool is_valid() const { return handle != INVALID_HANDLE_VALUE; }
-
- HANDLE handle;
-
- // A Windows HANDLE may be duplicated to another process but not yet sent to
- // that process. This tracks the handle's owning process and this process
- // handle (if not null, i.e., the current process) is *owned* by this
- // InternalPlatformHandle.
- base::ProcessHandle owning_process;
-
- // A Windows HANDLE may be an unconnected named pipe. In this case, we need to
- // wait for a connection before communicating on the pipe.
- bool needs_connection = false;
-};
-#elif defined(OS_FUCHSIA)
-// TODO(fuchsia): Find a clean way to share this with the POSIX version.
-// |zx_handle_t| is a typedef of |int|, so we only allow InternalPlatformHandle
-// to be created via explicit For<type>() creator functions.
-struct MOJO_SYSTEM_IMPL_EXPORT InternalPlatformHandle {
- public:
- static InternalPlatformHandle ForHandle(zx_handle_t handle) {
- InternalPlatformHandle platform_handle;
- platform_handle.handle = handle;
- return platform_handle;
- }
- static InternalPlatformHandle ForFd(int fd) {
- InternalPlatformHandle platform_handle;
- DCHECK_LT(fd, FDIO_MAX_FD);
- platform_handle.fd = fd;
- return platform_handle;
- }
-
- void CloseIfNecessary();
- bool is_valid() const { return is_valid_fd() || is_valid_handle(); }
- bool is_valid_handle() const { return handle != ZX_HANDLE_INVALID && fd < 0; }
- zx_handle_t as_handle() const { return handle; }
- bool is_valid_fd() const { return fd >= 0 && handle == ZX_HANDLE_INVALID; }
- int as_fd() const { return fd; }
-
- private:
- zx_handle_t handle = ZX_HANDLE_INVALID;
- int fd = -1;
-};
-#elif defined(OS_POSIX)
-struct MOJO_SYSTEM_IMPL_EXPORT InternalPlatformHandle {
- InternalPlatformHandle() {}
- explicit InternalPlatformHandle(int handle) : handle(handle) {}
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- explicit InternalPlatformHandle(mach_port_t port)
- : type(Type::MACH), port(port) {}
-#endif
-
- void CloseIfNecessary();
-
- bool is_valid() const {
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- if (type == Type::MACH || type == Type::MACH_NAME)
- return port != MACH_PORT_NULL;
-#endif
- return handle != -1;
- }
-
- enum class Type {
- POSIX,
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- MACH,
- // MACH_NAME isn't a real Mach port. But rather the "name" of one that can
- // be resolved to a real port later. This distinction is needed so that the
- // "port" doesn't try to be closed if CloseIfNecessary() is called. Having
- // this also allows us to do checks in other places.
- MACH_NAME,
-#endif
- };
- Type type = Type::POSIX;
-
- 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
-};
-#else
-#error "Platform not yet supported."
-#endif
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_
diff --git a/chromium/mojo/edk/embedder/platform_handle_utils.cc b/chromium/mojo/edk/embedder/platform_handle_utils.cc
deleted file mode 100644
index e3c0cfd6b6f..00000000000
--- a/chromium/mojo/edk/embedder/platform_handle_utils.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2018 The Chromium 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/platform_handle_utils.h"
-
-#include "build/build_config.h"
-
-namespace mojo {
-namespace edk {
-
-MojoResult MojoPlatformHandleToScopedInternalPlatformHandle(
- const MojoPlatformHandle* platform_handle,
- ScopedInternalPlatformHandle* out_handle) {
- if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (platform_handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
- out_handle->reset();
- return MOJO_RESULT_OK;
- }
-
- InternalPlatformHandle handle;
- switch (platform_handle->type) {
-#if defined(OS_FUCHSIA)
- case MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE:
- handle = InternalPlatformHandle::ForHandle(platform_handle->value);
- break;
- case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR:
- handle = InternalPlatformHandle::ForFd(platform_handle->value);
- break;
-
-#elif defined(OS_POSIX)
- case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR:
- handle.handle = static_cast<int>(platform_handle->value);
- break;
-#endif
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- case MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT:
- handle.type = InternalPlatformHandle::Type::MACH;
- handle.port = static_cast<mach_port_t>(platform_handle->value);
- break;
-#endif
-
-#if defined(OS_WIN)
- case MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE:
- handle.handle = reinterpret_cast<HANDLE>(platform_handle->value);
- break;
-#endif
-
- default:
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-
- out_handle->reset(handle);
- return MOJO_RESULT_OK;
-}
-
-MojoResult ScopedInternalPlatformHandleToMojoPlatformHandle(
- ScopedInternalPlatformHandle handle,
- MojoPlatformHandle* platform_handle) {
- if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (!handle.is_valid()) {
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
- return MOJO_RESULT_OK;
- }
-
-#if defined(OS_FUCHSIA)
- if (handle.get().is_valid_fd()) {
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
- platform_handle->value = handle.release().as_fd();
- } else {
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE;
- platform_handle->value = handle.release().as_handle();
- }
-#elif defined(OS_POSIX)
- switch (handle.get().type) {
- case InternalPlatformHandle::Type::POSIX:
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
- platform_handle->value = static_cast<uint64_t>(handle.release().handle);
- break;
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- case InternalPlatformHandle::Type::MACH:
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
- platform_handle->value = static_cast<uint64_t>(handle.release().port);
- break;
-#endif // defined(OS_MACOSX) && !defined(OS_IOS)
-
- default:
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-#elif defined(OS_WIN)
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
- platform_handle->value = reinterpret_cast<uint64_t>(handle.release().handle);
-#endif // defined(OS_WIN)
-
- return MOJO_RESULT_OK;
-}
-
-void ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
- base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle handle,
- ScopedInternalPlatformHandle* extracted_handle,
- ScopedInternalPlatformHandle* extracted_readonly_handle) {
-#if defined(OS_WIN)
- extracted_handle->reset(InternalPlatformHandle(handle.Take()));
-#elif defined(OS_FUCHSIA)
- extracted_handle->reset(InternalPlatformHandle::ForHandle(handle.release()));
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
- // This is a Mach port. Same code as below, but separated for clarity.
- extracted_handle->reset(InternalPlatformHandle(handle.release()));
-#elif defined(OS_ANDROID)
- // This is a file descriptor. Same code as above, but separated for clarity.
- extracted_handle->reset(InternalPlatformHandle(handle.release()));
-#else
- extracted_handle->reset(InternalPlatformHandle(handle.fd.release()));
- extracted_readonly_handle->reset(
- InternalPlatformHandle(handle.readonly_fd.release()));
-#endif
-}
-
-base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle
-CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
- ScopedInternalPlatformHandle handle,
- ScopedInternalPlatformHandle readonly_handle) {
-#if defined(OS_WIN)
- DCHECK(!readonly_handle.is_valid());
- return base::win::ScopedHandle(handle.release().handle);
-#elif defined(OS_FUCHSIA)
- DCHECK(!readonly_handle.is_valid());
- return base::ScopedZxHandle(handle.release().as_handle());
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
- DCHECK(!readonly_handle.is_valid());
- return base::mac::ScopedMachSendRight(handle.release().port);
-#elif defined(OS_ANDROID)
- DCHECK(!readonly_handle.is_valid());
- return base::ScopedFD(handle.release().handle);
-#else
- return base::subtle::ScopedFDPair(
- base::ScopedFD(handle.release().handle),
- base::ScopedFD(readonly_handle.release().handle));
-#endif
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_handle_utils.h b/chromium/mojo/edk/embedder/platform_handle_utils.h
deleted file mode 100644
index 2bdfb3f1572..00000000000
--- a/chromium/mojo/edk/embedder/platform_handle_utils.h
+++ /dev/null
@@ -1,63 +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_EMBEDDER_PLATFORM_HANDLE_UTILS_H_
-#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_
-
-#include "base/memory/platform_shared_memory_region.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/platform_handle.h"
-#include "mojo/public/c/system/types.h"
-#include "mojo/public/cpp/platform/platform_handle.h"
-
-namespace mojo {
-namespace edk {
-
-// Closes all the |InternalPlatformHandle|s in the given container.
-template <typename InternalPlatformHandleContainer>
-MOJO_SYSTEM_IMPL_EXPORT inline void CloseAllInternalPlatformHandles(
- InternalPlatformHandleContainer* platform_handles) {
- for (typename InternalPlatformHandleContainer::iterator it =
- platform_handles->begin();
- it != platform_handles->end(); ++it)
- it->CloseIfNecessary();
-}
-
-MOJO_SYSTEM_IMPL_EXPORT MojoResult
-MojoPlatformHandleToScopedInternalPlatformHandle(
- const MojoPlatformHandle* platform_handle,
- ScopedInternalPlatformHandle* out_handle);
-
-MOJO_SYSTEM_IMPL_EXPORT MojoResult
-ScopedInternalPlatformHandleToMojoPlatformHandle(
- ScopedInternalPlatformHandle handle,
- MojoPlatformHandle* platform_handle);
-
-// Duplicates the given |InternalPlatformHandle| (which must be valid). (Returns
-// an invalid |ScopedInternalPlatformHandle| on failure.)
-MOJO_SYSTEM_IMPL_EXPORT ScopedInternalPlatformHandle
-DuplicatePlatformHandle(InternalPlatformHandle platform_handle);
-
-// Converts a base shared memory platform handle into one (maybe two on POSIX)
-// EDK ScopedInternalPlatformHandles.
-MOJO_SYSTEM_IMPL_EXPORT void
-ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
- base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle handle,
- ScopedInternalPlatformHandle* extracted_handle,
- ScopedInternalPlatformHandle* extracted_readonly_handle);
-
-// Converts one (maybe two on POSIX) EDK ScopedInternalPlatformHandles to a base
-// shared memory platform handle.
-MOJO_SYSTEM_IMPL_EXPORT
-base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle
-CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
- ScopedInternalPlatformHandle handle,
- ScopedInternalPlatformHandle readonly_handle);
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_
diff --git a/chromium/mojo/edk/embedder/platform_handle_utils_fuchsia.cc b/chromium/mojo/edk/embedder/platform_handle_utils_fuchsia.cc
deleted file mode 100644
index a904a08b6c3..00000000000
--- a/chromium/mojo/edk/embedder/platform_handle_utils_fuchsia.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium 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/platform_handle_utils.h"
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace edk {
-
-ScopedInternalPlatformHandle DuplicatePlatformHandle(
- InternalPlatformHandle platform_handle) {
- DCHECK(platform_handle.is_valid());
- zx_handle_t duped;
- // zx_handle_duplicate won't touch |duped| in case of failure.
- zx_status_t result = zx_handle_duplicate(platform_handle.as_handle(),
- ZX_RIGHT_SAME_RIGHTS, &duped);
- DLOG_IF(ERROR, result != ZX_OK) << "zx_duplicate_handle failed: " << result;
- return ScopedInternalPlatformHandle(InternalPlatformHandle::ForHandle(duped));
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_handle_utils_posix.cc b/chromium/mojo/edk/embedder/platform_handle_utils_posix.cc
deleted file mode 100644
index a29b79f8713..00000000000
--- a/chromium/mojo/edk/embedder/platform_handle_utils_posix.cc
+++ /dev/null
@@ -1,25 +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/embedder/platform_handle_utils.h"
-
-#include <unistd.h>
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace edk {
-
-ScopedInternalPlatformHandle DuplicatePlatformHandle(
- InternalPlatformHandle platform_handle) {
- DCHECK(platform_handle.is_valid());
- // Note that |dup()| returns -1 on error (which is exactly the value we use
- // for invalid |InternalPlatformHandle| FDs).
- InternalPlatformHandle duped(dup(platform_handle.handle));
- duped.needs_connection = platform_handle.needs_connection;
- return ScopedInternalPlatformHandle(duped);
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/platform_handle_utils_win.cc b/chromium/mojo/edk/embedder/platform_handle_utils_win.cc
deleted file mode 100644
index 4622e925fb1..00000000000
--- a/chromium/mojo/edk/embedder/platform_handle_utils_win.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/edk/embedder/platform_handle_utils.h"
-
-#include <windows.h>
-
-#include "base/logging.h"
-
-namespace mojo {
-namespace edk {
-
-ScopedInternalPlatformHandle DuplicatePlatformHandle(
- InternalPlatformHandle platform_handle) {
- DCHECK(platform_handle.is_valid());
-
- HANDLE new_handle;
- CHECK_NE(platform_handle.handle, INVALID_HANDLE_VALUE);
- if (!DuplicateHandle(GetCurrentProcess(), platform_handle.handle,
- GetCurrentProcess(), &new_handle, 0, TRUE,
- DUPLICATE_SAME_ACCESS))
- return ScopedInternalPlatformHandle();
- DCHECK_NE(new_handle, INVALID_HANDLE_VALUE);
- return ScopedInternalPlatformHandle(InternalPlatformHandle(new_handle));
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/embedder/scoped_platform_handle.h b/chromium/mojo/edk/embedder/scoped_platform_handle.h
deleted file mode 100644
index 67ffdb07b88..00000000000
--- a/chromium/mojo/edk/embedder/scoped_platform_handle.h
+++ /dev/null
@@ -1,65 +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_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_
-#define MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/macros.h"
-
-namespace mojo {
-namespace edk {
-
-class MOJO_SYSTEM_IMPL_EXPORT ScopedInternalPlatformHandle {
- public:
- ScopedInternalPlatformHandle() {}
- explicit ScopedInternalPlatformHandle(InternalPlatformHandle handle)
- : handle_(handle) {}
- ~ScopedInternalPlatformHandle() { handle_.CloseIfNecessary(); }
-
- // Move-only constructor and operator=.
- ScopedInternalPlatformHandle(ScopedInternalPlatformHandle&& other)
- : handle_(other.release()) {}
-
- ScopedInternalPlatformHandle& operator=(
- ScopedInternalPlatformHandle&& other) {
- reset(other.release());
- return *this;
- }
-
- const InternalPlatformHandle& get() const { return handle_; }
- InternalPlatformHandle& get() { return handle_; }
-
- void swap(ScopedInternalPlatformHandle& other) {
- InternalPlatformHandle temp = handle_;
- handle_ = other.handle_;
- other.handle_ = temp;
- }
-
- InternalPlatformHandle release() WARN_UNUSED_RESULT {
- InternalPlatformHandle rv = handle_;
- handle_ = InternalPlatformHandle();
- return rv;
- }
-
- void reset(InternalPlatformHandle handle = InternalPlatformHandle()) {
- handle_.CloseIfNecessary();
- handle_ = handle;
- }
-
- bool is_valid() const { return handle_.is_valid(); }
-
- private:
- InternalPlatformHandle handle_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedInternalPlatformHandle);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_
diff --git a/chromium/mojo/edk/embedder/transport_protocol.h b/chromium/mojo/edk/embedder/transport_protocol.h
deleted file mode 100644
index 67d8ee94f92..00000000000
--- a/chromium/mojo/edk/embedder/transport_protocol.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2017 The Chromium 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_TRANSPORT_PROTOCOL_H_
-#define MOJO_EDK_EMBEDDER_TRANSPORT_PROTOCOL_H_
-
-#include <stdint.h>
-
-namespace mojo {
-namespace edk {
-
-// Selects the transport protocol to use when connecting to the remote
-// process.
-//
-// New code should generally prefer to use |kAutomatic| to allow the protocol
-// to be negotiated by the two processes involved in the connection. As noted
-// below, this is not possible when either one of the two processes only
-// supports the legacy protocol. In such cases both ends of the connection
-// must be aware and explicitly use |kLegacy|, which is the default for now.
-enum class TransportProtocol : int32_t {
- // Legacy transport protocol. Should only be used when connecting to
- // embedders which may not support at least |kVersion0|. Deprecated.
- kLegacy = -2,
-
- // Automatically negotiate the transport protocol. This will ultimately
- // select the highest protocol version supported by all of the calling
- // process, the broker process (if any), and the target process.
- //
- // This may only be used when connecting to embedders which support at least
- // |kVersion0|. Otherwise the deprecated |kLegacy| protocol must be used.
- kAutomatic = -1,
-
- // Protocol version 0. This is NOT backwards compatible with the legacy
- // protocol. If this is used to establish a connection, the remote embedder
- // (and the broker, if applicable) must also support at least version 0.
- kVersion0 = 0,
-
- // The maximum version supported by the current process. This must be
- // updated if a new version is added.
- kMaxSupportedVersion = kVersion0,
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_TRANSPORT_PROTOCOL_H_
diff --git a/chromium/mojo/edk/system/BUILD.gn b/chromium/mojo/edk/system/BUILD.gn
deleted file mode 100644
index 235f32e31e1..00000000000
--- a/chromium/mojo/edk/system/BUILD.gn
+++ /dev/null
@@ -1,76 +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/config/nacl/config.gni")
-import("../../../mojo/public/tools/bindings/mojom.gni")
-
-if (is_android) {
- import("//build/config/android/config.gni")
- import("//build/config/android/rules.gni")
-}
-
-source_set("test_utils") {
- testonly = true
-
- sources = [
- "test_utils.cc",
- "test_utils.h",
- ]
-
- public_deps = [
- "//mojo/public/c/system",
- "//mojo/public/cpp/system",
- ]
-
- deps = [
- "//base",
- "//base/test:test_support",
- "//mojo/edk/test:test_support",
- "//testing/gtest:gtest",
- ]
-}
-
-source_set("test_sources") {
- testonly = true
- sources = [
- "channel_unittest.cc",
- "core_test_base.cc",
- "core_test_base.h",
- "core_unittest.cc",
- "handle_table_unittest.cc",
- "message_pipe_unittest.cc",
- "message_unittest.cc",
- "options_validation_unittest.cc",
- "platform_handle_dispatcher_unittest.cc",
- "shared_buffer_dispatcher_unittest.cc",
- "shared_buffer_unittest.cc",
- "signals_unittest.cc",
- "trap_unittest.cc",
- ]
-
- if (!is_ios) {
- sources += [
- "data_pipe_unittest.cc",
- "invitation_unittest.cc",
- "multiprocess_message_pipe_unittest.cc",
- "platform_wrapper_unittest.cc",
- ]
- }
-
- deps = [
- ":test_utils",
- "//base",
- "//base/test:test_support",
- "//mojo/edk",
- "//mojo/edk/embedder:embedder_unittests",
- "//mojo/edk/system/ports:tests",
- "//mojo/edk/test:run_all_unittests",
- "//mojo/edk/test:test_support",
- "//mojo/public/cpp/system",
- "//testing/gmock",
- "//testing/gtest",
- ]
-
- allow_circular_includes_from = [ "//mojo/edk/embedder:embedder_unittests" ]
-}
diff --git a/chromium/mojo/edk/system/scoped_process_handle.cc b/chromium/mojo/edk/system/scoped_process_handle.cc
deleted file mode 100644
index 43d719df410..00000000000
--- a/chromium/mojo/edk/system/scoped_process_handle.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Chromium 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/scoped_process_handle.h"
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace mojo {
-namespace edk {
-
-ScopedProcessHandle::ScopedProcessHandle() = default;
-
-ScopedProcessHandle::ScopedProcessHandle(base::ProcessHandle handle)
- : handle_(handle) {}
-
-ScopedProcessHandle::ScopedProcessHandle(ScopedProcessHandle&&) = default;
-
-ScopedProcessHandle::~ScopedProcessHandle() = default;
-
-// static
-ScopedProcessHandle ScopedProcessHandle::CloneFrom(base::ProcessHandle handle) {
-#if defined(OS_WIN)
- BOOL ok = ::DuplicateHandle(base::GetCurrentProcessHandle(), handle,
- base::GetCurrentProcessHandle(), &handle, 0,
- FALSE, DUPLICATE_SAME_ACCESS);
- DCHECK(ok);
-#endif
- return ScopedProcessHandle(handle);
-}
-
-ScopedProcessHandle& ScopedProcessHandle::operator=(ScopedProcessHandle&&) =
- default;
-
-ScopedProcessHandle ScopedProcessHandle::Clone() const {
- DCHECK(is_valid());
- return CloneFrom(get());
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/system/trap_unittest.cc b/chromium/mojo/edk/system/trap_unittest.cc
deleted file mode 100644
index 011f988020e..00000000000
--- a/chromium/mojo/edk/system/trap_unittest.cc
+++ /dev/null
@@ -1,1868 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <set>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/rand_util.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "mojo/edk/test/mojo_test_base.h"
-#include "mojo/public/c/system/data_pipe.h"
-#include "mojo/public/c/system/trap.h"
-#include "mojo/public/c/system/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace edk {
-namespace {
-
-// TODO(https://crbug.com/819046): These are temporary wrappers to reduce
-// changes necessary during the API rename. Remove them.
-
-MojoResult MojoWatch(MojoHandle trap_handle,
- MojoHandle handle,
- MojoHandleSignals signals,
- MojoTriggerCondition condition,
- uintptr_t context) {
- return MojoAddTrigger(trap_handle, handle, signals, condition, context,
- nullptr);
-}
-
-MojoResult MojoCancelWatch(MojoHandle trap_handle, uintptr_t context) {
- return MojoRemoveTrigger(trap_handle, context, nullptr);
-}
-
-MojoResult MojoArmWatcher(MojoHandle trap_handle,
- uint32_t* num_ready_contexts,
- uintptr_t* ready_contexts,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals) {
- return MojoArmTrap(trap_handle, nullptr, num_ready_contexts, ready_contexts,
- ready_results, ready_signals);
-}
-
-using WatcherTest = test::MojoTestBase;
-
-class WatchHelper {
- public:
- using ContextCallback =
- base::Callback<void(MojoResult, MojoHandleSignalsState)>;
-
- WatchHelper() {}
- ~WatchHelper() {}
-
- MojoResult CreateWatcher(MojoHandle* handle) {
- return MojoCreateTrap(&Notify, nullptr, handle);
- }
-
- uintptr_t CreateContext(const ContextCallback& callback) {
- return CreateContextWithCancel(callback, base::Closure());
- }
-
- uintptr_t CreateContextWithCancel(const ContextCallback& callback,
- const base::Closure& cancel_callback) {
- auto context = std::make_unique<NotificationContext>(callback);
- NotificationContext* raw_context = context.get();
- raw_context->SetCancelCallback(base::Bind(
- [](std::unique_ptr<NotificationContext> context,
- const base::Closure& cancel_callback) {
- if (cancel_callback)
- cancel_callback.Run();
- },
- base::Passed(&context), cancel_callback));
- return reinterpret_cast<uintptr_t>(raw_context);
- }
-
- private:
- class NotificationContext {
- public:
- explicit NotificationContext(const ContextCallback& callback)
- : callback_(callback) {}
-
- ~NotificationContext() {}
-
- void SetCancelCallback(const base::Closure& cancel_callback) {
- cancel_callback_ = cancel_callback;
- }
-
- void Notify(MojoResult result, MojoHandleSignalsState state) {
- if (result == MOJO_RESULT_CANCELLED)
- cancel_callback_.Run();
- else
- callback_.Run(result, state);
- }
-
- private:
- const ContextCallback callback_;
- base::Closure cancel_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(NotificationContext);
- };
-
- static void Notify(const MojoTrapEvent* event) {
- reinterpret_cast<NotificationContext*>(event->trigger_context)
- ->Notify(event->result, event->signals_state);
- }
-
- DISALLOW_COPY_AND_ASSIGN(WatchHelper);
-};
-
-class ThreadedRunner : public base::SimpleThread {
- public:
- explicit ThreadedRunner(const base::Closure& callback)
- : SimpleThread("ThreadedRunner"), callback_(callback) {}
- ~ThreadedRunner() override {}
-
- void Run() override { callback_.Run(); }
-
- private:
- const base::Closure callback_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadedRunner);
-};
-
-void ExpectNoNotification(const MojoTrapEvent* event) {
- NOTREACHED();
-}
-
-void ExpectOnlyCancel(const MojoTrapEvent* event) {
- EXPECT_EQ(event->result, MOJO_RESULT_CANCELLED);
-}
-
-TEST_F(WatcherTest, InvalidArguments) {
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoCreateTrap(&ExpectNoNotification, nullptr, nullptr));
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &w));
-
- // Try to watch unwatchable handles.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoWatch(w, w, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, 0));
- MojoHandle buffer_handle = CreateBuffer(42);
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoWatch(w, buffer_handle, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, 0));
-
- // Try to cancel a watch on an invalid watcher handle.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCancelWatch(buffer_handle, 0));
-
- // Try to arm an invalid handle.
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- MojoArmWatcher(MOJO_HANDLE_INVALID, nullptr, nullptr, nullptr, nullptr));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoArmWatcher(buffer_handle, nullptr, nullptr, nullptr, nullptr));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(buffer_handle));
-
- // Try to arm with a non-null count but at least one null output buffer.
- uint32_t num_ready_contexts = 1;
- uintptr_t ready_context;
- MojoResult ready_result;
- MojoHandleSignalsState ready_state;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoArmWatcher(w, &num_ready_contexts, nullptr, &ready_result,
- &ready_state));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoArmWatcher(w, &num_ready_contexts, &ready_context, nullptr,
- &ready_state));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoArmWatcher(w, &num_ready_contexts, &ready_context,
- &ready_result, nullptr));
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-}
-
-TEST_F(WatcherTest, WatchMessagePipeReadable) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- int num_expected_notifications = 1;
- const uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, int* expected_count, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_GT(*expected_count, 0);
- *expected_count -= 1;
-
- EXPECT_EQ(MOJO_RESULT_OK, result);
- event->Signal();
- },
- &event, &num_expected_notifications));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- const char kMessage1[] = "hey hey hey hey";
- const char kMessage2[] = "i said hey";
- const char kMessage3[] = "what's goin' on?";
-
- // Writing to |b| multiple times should notify exactly once.
- WriteMessage(b, kMessage1);
- WriteMessage(b, kMessage2);
- event.Wait();
-
- // This also shouldn't fire a notification; the watcher is still disarmed.
- WriteMessage(b, kMessage3);
-
- // Arming should fail with relevant information.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(readable_a_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
-
- // Flush the three messages from above.
- EXPECT_EQ(kMessage1, ReadMessage(a));
- EXPECT_EQ(kMessage2, ReadMessage(a));
- EXPECT_EQ(kMessage3, ReadMessage(a));
-
- // Now we can rearm the watcher.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
-}
-
-TEST_F(WatcherTest, CloseWatchedMessagePipeHandle) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- const uintptr_t readable_a_context = helper.CreateContextWithCancel(
- WatchHelper::ContextCallback(),
- base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
-
- // Test that closing a watched handle fires an appropriate notification, even
- // when the watcher is unarmed.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-}
-
-TEST_F(WatcherTest, CloseWatchedMessagePipeHandlePeer) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- const uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- event->Signal();
- },
- &event));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
-
- // Test that closing a watched handle's peer with an armed watcher fires an
- // appropriate notification.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- event.Wait();
-
- // And now arming should fail with correct information about |a|'s state.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(readable_a_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]);
- EXPECT_TRUE(ready_states[0].satisfied_signals &
- MOJO_HANDLE_SIGNAL_PEER_CLOSED);
- EXPECT_FALSE(ready_states[0].satisfiable_signals &
- MOJO_HANDLE_SIGNAL_READABLE);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
-}
-
-TEST_F(WatcherTest, WatchDataPipeConsumerReadable) {
- constexpr size_t kTestPipeCapacity = 64;
- MojoHandle producer, consumer;
- CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- int num_expected_notifications = 1;
- const uintptr_t readable_consumer_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, int* expected_count, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_GT(*expected_count, 0);
- *expected_count -= 1;
-
- EXPECT_EQ(MOJO_RESULT_OK, result);
- event->Signal();
- },
- &event, &num_expected_notifications));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED,
- readable_consumer_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- const char kMessage1[] = "hey hey hey hey";
- const char kMessage2[] = "i said hey";
- const char kMessage3[] = "what's goin' on?";
-
- // Writing to |producer| multiple times should notify exactly once.
- WriteData(producer, kMessage1);
- WriteData(producer, kMessage2);
- event.Wait();
-
- // This also shouldn't fire a notification; the watcher is still disarmed.
- WriteData(producer, kMessage3);
-
- // Arming should fail with relevant information.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(readable_consumer_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
-
- // Flush the three messages from above.
- EXPECT_EQ(kMessage1, ReadData(consumer, sizeof(kMessage1) - 1));
- EXPECT_EQ(kMessage2, ReadData(consumer, sizeof(kMessage2) - 1));
- EXPECT_EQ(kMessage3, ReadData(consumer, sizeof(kMessage3) - 1));
-
- // Now we can rearm the watcher.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
-}
-
-TEST_F(WatcherTest, WatchDataPipeConsumerNewDataReadable) {
- constexpr size_t kTestPipeCapacity = 64;
- MojoHandle producer, consumer;
- CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- int num_new_data_notifications = 0;
- const uintptr_t new_data_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, int* notification_count, MojoResult result,
- MojoHandleSignalsState state) {
- *notification_count += 1;
-
- EXPECT_EQ(MOJO_RESULT_OK, result);
- event->Signal();
- },
- &event, &num_new_data_notifications));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, new_data_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- const char kMessage1[] = "hey hey hey hey";
- const char kMessage2[] = "i said hey";
- const char kMessage3[] = "what's goin' on?";
-
- // Writing to |producer| multiple times should notify exactly once.
- WriteData(producer, kMessage1);
- WriteData(producer, kMessage2);
- event.Wait();
-
- // This also shouldn't fire a notification; the watcher is still disarmed.
- WriteData(producer, kMessage3);
-
- // Arming should fail with relevant information.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(new_data_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
-
- // Attempt to read more data than is available. Should fail but clear the
- // NEW_DATA_READABLE signal.
- char large_buffer[512];
- uint32_t large_read_size = 512;
- MojoReadDataOptions options;
- options.struct_size = sizeof(options);
- options.flags = MOJO_READ_DATA_FLAG_ALL_OR_NONE;
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- MojoReadData(consumer, &options, large_buffer, &large_read_size));
-
- // Attempt to arm again. Should succeed.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Write more data. Should notify.
- event.Reset();
- WriteData(producer, kMessage1);
- event.Wait();
-
- // Reading some data should clear NEW_DATA_READABLE again so we can rearm.
- EXPECT_EQ(kMessage1, ReadData(consumer, sizeof(kMessage1) - 1));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- EXPECT_EQ(2, num_new_data_notifications);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
-}
-
-TEST_F(WatcherTest, WatchDataPipeProducerWritable) {
- constexpr size_t kTestPipeCapacity = 8;
- MojoHandle producer, consumer;
- CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
-
- // Half the capacity of the data pipe.
- const char kTestData[] = "aaaa";
- static_assert((sizeof(kTestData) - 1) * 2 == kTestPipeCapacity,
- "Invalid test data for this test.");
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- int num_expected_notifications = 1;
- const uintptr_t writable_producer_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, int* expected_count, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_GT(*expected_count, 0);
- *expected_count -= 1;
-
- EXPECT_EQ(MOJO_RESULT_OK, result);
- event->Signal();
- },
- &event, &num_expected_notifications));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_WATCH_CONDITION_SATISFIED,
- writable_producer_context));
-
- // The producer is already writable, so arming should fail with relevant
- // information.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(writable_producer_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
- EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
-
- // Write some data, but don't fill the pipe yet. Arming should fail again.
- WriteData(producer, kTestData);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(writable_producer_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
- EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
-
- // Write more data, filling the pipe to capacity. Arming should succeed now.
- WriteData(producer, kTestData);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Now read from the pipe, making the producer writable again. Should notify.
- EXPECT_EQ(kTestData, ReadData(consumer, sizeof(kTestData) - 1));
- event.Wait();
-
- // Arming should fail again.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(writable_producer_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
- EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
-
- // Fill the pipe once more and arm the watcher. Should succeed.
- WriteData(producer, kTestData);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
-};
-
-TEST_F(WatcherTest, CloseWatchedDataPipeConsumerHandle) {
- constexpr size_t kTestPipeCapacity = 8;
- MojoHandle producer, consumer;
- CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- const uintptr_t readable_consumer_context = helper.CreateContextWithCancel(
- WatchHelper::ContextCallback(),
- base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED,
- readable_consumer_context));
-
- // Closing the consumer should fire a cancellation notification.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-}
-
-TEST_F(WatcherTest, CloseWatcherDataPipeConsumerHandlePeer) {
- constexpr size_t kTestPipeCapacity = 8;
- MojoHandle producer, consumer;
- CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- const uintptr_t readable_consumer_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- event->Signal();
- },
- &event));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED,
- readable_consumer_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Closing the producer should fire a notification for an unsatisfiable watch.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
- event.Wait();
-
- // Now attempt to rearm and expect appropriate error feedback.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(readable_consumer_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]);
- EXPECT_FALSE(ready_states[0].satisfiable_signals &
- MOJO_HANDLE_SIGNAL_READABLE);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
-}
-
-TEST_F(WatcherTest, CloseWatchedDataPipeProducerHandle) {
- constexpr size_t kTestPipeCapacity = 8;
- MojoHandle producer, consumer;
- CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- const uintptr_t writable_producer_context = helper.CreateContextWithCancel(
- WatchHelper::ContextCallback(),
- base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_WATCH_CONDITION_SATISFIED,
- writable_producer_context));
-
- // Closing the consumer should fire a cancellation notification.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-}
-
-TEST_F(WatcherTest, CloseWatchedDataPipeProducerHandlePeer) {
- constexpr size_t kTestPipeCapacity = 8;
- MojoHandle producer, consumer;
- CreateDataPipe(&producer, &consumer, kTestPipeCapacity);
-
- const char kTestMessageFullCapacity[] = "xxxxxxxx";
- static_assert(sizeof(kTestMessageFullCapacity) - 1 == kTestPipeCapacity,
- "Invalid test message size for this test.");
-
- // Make the pipe unwritable initially.
- WriteData(producer, kTestMessageFullCapacity);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- const uintptr_t writable_producer_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- event->Signal();
- },
- &event));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_WATCH_CONDITION_SATISFIED,
- writable_producer_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Closing the consumer should fire a notification for an unsatisfiable watch,
- // as the full data pipe can never be read from again and is therefore
- // permanently full and unwritable.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer));
- event.Wait();
-
- // Now attempt to rearm and expect appropriate error feedback.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(writable_producer_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]);
- EXPECT_FALSE(ready_states[0].satisfiable_signals &
- MOJO_HANDLE_SIGNAL_WRITABLE);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer));
-}
-
-TEST_F(WatcherTest, ArmWithNoWatches) {
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &w));
- EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-}
-
-TEST_F(WatcherTest, WatchDuplicateContext) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, 0));
- EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, 0));
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
-}
-
-TEST_F(WatcherTest, CancelUnknownWatch) {
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectNoNotification, nullptr, &w));
- EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoCancelWatch(w, 1234));
-}
-
-TEST_F(WatcherTest, ArmWithWatchAlreadySatisfied) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_WATCH_CONDITION_SATISFIED, 0));
-
- // |a| is always writable, so we can never arm this watcher.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(0u, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
- EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
-}
-
-TEST_F(WatcherTest, ArmWithWatchAlreadyUnsatisfiable) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, 0));
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
-
- // |b| is closed and never wrote any messages, so |a| won't be readable again.
- // MojoArmWatcher() should fail, incidcating as much.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = kMaxReadyContexts;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(0u, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]);
- EXPECT_TRUE(ready_states[0].satisfied_signals &
- MOJO_HANDLE_SIGNAL_PEER_CLOSED);
- EXPECT_FALSE(ready_states[0].satisfiable_signals &
- MOJO_HANDLE_SIGNAL_READABLE);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
-}
-
-TEST_F(WatcherTest, MultipleWatches) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- base::WaitableEvent a_event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- base::WaitableEvent b_event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- int num_a_notifications = 0;
- int num_b_notifications = 0;
- auto notify_callback =
- base::Bind([](base::WaitableEvent* event, int* notification_count,
- MojoResult result, MojoHandleSignalsState state) {
- *notification_count += 1;
- EXPECT_EQ(MOJO_RESULT_OK, result);
- event->Signal();
- });
- uintptr_t readable_a_context = helper.CreateContext(
- base::Bind(notify_callback, &a_event, &num_a_notifications));
- uintptr_t readable_b_context = helper.CreateContext(
- base::Bind(notify_callback, &b_event, &num_b_notifications));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- // Add two independent watch contexts to watch for |a| or |b| readability.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_b_context));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- const char kMessage1[] = "things are happening";
- const char kMessage2[] = "ok. ok. ok. ok.";
- const char kMessage3[] = "plz wake up";
-
- // Writing to |b| should signal |a|'s watch.
- WriteMessage(b, kMessage1);
- a_event.Wait();
- a_event.Reset();
-
- // Subsequent messages on |b| should not trigger another notification.
- WriteMessage(b, kMessage2);
- WriteMessage(b, kMessage3);
-
- // Messages on |a| also shouldn't trigger |b|'s notification, since the
- // watcher should be disarmed by now.
- WriteMessage(a, kMessage1);
- WriteMessage(a, kMessage2);
- WriteMessage(a, kMessage3);
-
- // Arming should fail. Since we only ask for at most one context's information
- // that's all we should get back. Which one we get is unspecified.
- constexpr size_t kMaxReadyContexts = 10;
- uint32_t num_ready_contexts = 1;
- uintptr_t ready_contexts[kMaxReadyContexts];
- MojoResult ready_results[kMaxReadyContexts];
- MojoHandleSignalsState ready_states[kMaxReadyContexts];
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_TRUE(ready_contexts[0] == readable_a_context ||
- ready_contexts[0] == readable_b_context);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
- EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
-
- // Now try arming again, verifying that both contexts are returned.
- num_ready_contexts = kMaxReadyContexts;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(2u, num_ready_contexts);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[1]);
- EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
- EXPECT_TRUE(ready_states[1].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
- EXPECT_TRUE((ready_contexts[0] == readable_a_context &&
- ready_contexts[1] == readable_b_context) ||
- (ready_contexts[0] == readable_b_context &&
- ready_contexts[1] == readable_a_context));
-
- // Flush out the test messages so we should be able to successfully rearm.
- EXPECT_EQ(kMessage1, ReadMessage(a));
- EXPECT_EQ(kMessage2, ReadMessage(a));
- EXPECT_EQ(kMessage3, ReadMessage(a));
- EXPECT_EQ(kMessage1, ReadMessage(b));
- EXPECT_EQ(kMessage2, ReadMessage(b));
- EXPECT_EQ(kMessage3, ReadMessage(b));
-
- // Add a watch which is always satisfied, so we can't arm. Arming should fail
- // with only this new watch's information.
- uintptr_t writable_c_context = helper.CreateContext(base::Bind(
- [](MojoResult result, MojoHandleSignalsState state) { NOTREACHED(); }));
- MojoHandle c, d;
- CreateMessagePipe(&c, &d);
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, c, MOJO_HANDLE_SIGNAL_WRITABLE,
- MOJO_WATCH_CONDITION_SATISFIED, writable_c_context));
- num_ready_contexts = kMaxReadyContexts;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(writable_c_context, ready_contexts[0]);
- EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
- EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
-
- // Cancel the new watch and arming should succeed once again.
- EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, writable_c_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
-}
-
-TEST_F(WatcherTest, NotifyOtherFromNotificationCallback) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- static const char kTestMessageToA[] = "hello a";
- static const char kTestMessageToB[] = "hello b";
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- WatchHelper helper;
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](MojoHandle w, MojoHandle a, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ("hello a", ReadMessage(a));
-
- // Re-arm the watcher and signal |b|.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
- WriteMessage(a, kTestMessageToB);
- },
- w, a));
-
- uintptr_t readable_b_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoHandle w, MojoHandle b,
- MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToB, ReadMessage(b));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
- event->Signal();
- },
- &event, w, b));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_b_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Send a message to |a|. The relevant watch context should be notified, and
- // should in turn send a message to |b|, waking up the other context. The
- // second context signals |event|.
- WriteMessage(b, kTestMessageToA);
- event.Wait();
-}
-
-TEST_F(WatcherTest, NotifySelfFromNotificationCallback) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- static const char kTestMessageToA[] = "hello a";
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- WatchHelper helper;
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- int expected_notifications = 10;
- uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](int* expected_count, MojoHandle w, MojoHandle a, MojoHandle b,
- base::WaitableEvent* event, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ("hello a", ReadMessage(a));
-
- EXPECT_GT(*expected_count, 0);
- *expected_count -= 1;
- if (*expected_count == 0) {
- event->Signal();
- return;
- } else {
- // Re-arm the watcher and signal |a| again.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
- WriteMessage(b, kTestMessageToA);
- }
- },
- &expected_notifications, w, a, b, &event));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Send a message to |a|. When the watch above is notified, it will rearm and
- // send another message to |a|. This will happen until
- // |expected_notifications| reaches 0.
- WriteMessage(b, kTestMessageToA);
- event.Wait();
-}
-
-TEST_F(WatcherTest, ImplicitCancelOtherFromNotificationCallback) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- MojoHandle c, d;
- CreateMessagePipe(&c, &d);
-
- static const char kTestMessageToA[] = "hi a";
- static const char kTestMessageToC[] = "hi c";
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- WatchHelper helper;
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- uintptr_t readable_a_context = helper.CreateContextWithCancel(
- base::Bind([](MojoResult result, MojoHandleSignalsState state) {
- NOTREACHED();
- }),
- base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event));
-
- uintptr_t readable_c_context = helper.CreateContext(base::Bind(
- [](MojoHandle w, MojoHandle a, MojoHandle b, MojoHandle c,
- MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToC, ReadMessage(c));
-
- // Now rearm the watcher.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Must result in exactly ONE notification on the above context, for
- // CANCELLED only. Because we cannot dispatch notifications until the
- // stack unwinds, and because we must never dispatch non-cancellation
- // notifications for a handle once it's been closed, we must be certain
- // that cancellation due to closure preemptively invalidates any
- // pending non-cancellation notifications queued on the current
- // RequestContext, such as the one resulting from the WriteMessage here.
- WriteMessage(b, kTestMessageToA);
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
-
- // Rearming should be fine since |a|'s watch should already be
- // implicitly cancelled (even though the notification will not have
- // been invoked yet.)
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Nothing interesting should happen as a result of this.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- },
- w, a, b, c));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_c_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- WriteMessage(d, kTestMessageToC);
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
-}
-
-TEST_F(WatcherTest, ExplicitCancelOtherFromNotificationCallback) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- MojoHandle c, d;
- CreateMessagePipe(&c, &d);
-
- static const char kTestMessageToA[] = "hi a";
- static const char kTestMessageToC[] = "hi c";
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- WatchHelper helper;
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](MojoResult result, MojoHandleSignalsState state) { NOTREACHED(); }));
-
- uintptr_t readable_c_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, uintptr_t readable_a_context, MojoHandle w,
- MojoHandle a, MojoHandle b, MojoHandle c, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToC, ReadMessage(c));
-
- // Now rearm the watcher.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Should result in no notifications on the above context, because the
- // watch will have been cancelled by the time the notification callback
- // can execute.
- WriteMessage(b, kTestMessageToA);
- WriteMessage(b, kTestMessageToA);
- EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context));
-
- // Rearming should be fine now.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // Nothing interesting should happen as a result of these.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
-
- event->Signal();
- },
- &event, readable_a_context, w, a, b, c));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_c_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- WriteMessage(d, kTestMessageToC);
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
-}
-
-TEST_F(WatcherTest, NestedCancellation) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- MojoHandle c, d;
- CreateMessagePipe(&c, &d);
-
- static const char kTestMessageToA[] = "hey a";
- static const char kTestMessageToC[] = "hey c";
- static const char kTestMessageToD[] = "hey d";
-
- // This is a tricky test. It establishes a watch on |b| using one watcher and
- // watches on |c| and |d| using another watcher.
- //
- // A message is written to |d| to wake up |c|'s watch, and the notification
- // handler for that event does the following:
- // 1. Writes to |a| to eventually wake up |b|'s watcher.
- // 2. Rearms |c|'s watcher.
- // 3. Writes to |d| to eventually wake up |c|'s watcher again.
- //
- // Meanwhile, |b|'s watch notification handler cancels |c|'s watch altogether
- // before writing to |c| to wake up |d|.
- //
- // The net result should be that |c|'s context only gets notified once (from
- // the first write to |d| above) and everyone else gets notified as expected.
-
- MojoHandle b_watcher;
- MojoHandle cd_watcher;
- WatchHelper helper;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&b_watcher));
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&cd_watcher));
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- uintptr_t readable_d_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoHandle d, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToD, ReadMessage(d));
- event->Signal();
- },
- &event, d));
-
- static int num_expected_c_notifications = 1;
- uintptr_t readable_c_context = helper.CreateContext(base::Bind(
- [](MojoHandle cd_watcher, MojoHandle a, MojoHandle c, MojoHandle d,
- MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_GT(num_expected_c_notifications--, 0);
-
- // Trigger an eventual |readable_b_context| notification.
- WriteMessage(a, kTestMessageToA);
-
- EXPECT_EQ(kTestMessageToC, ReadMessage(c));
- EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(cd_watcher, nullptr, nullptr,
- nullptr, nullptr));
-
- // Trigger another eventual |readable_c_context| notification.
- WriteMessage(d, kTestMessageToC);
- },
- cd_watcher, a, c, d));
-
- uintptr_t readable_b_context = helper.CreateContext(base::Bind(
- [](MojoHandle cd_watcher, uintptr_t readable_c_context, MojoHandle c,
- MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoCancelWatch(cd_watcher, readable_c_context));
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(cd_watcher, nullptr, nullptr,
- nullptr, nullptr));
-
- WriteMessage(c, kTestMessageToD);
- },
- cd_watcher, readable_c_context, c));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_b_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(cd_watcher, c, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_c_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(cd_watcher, d, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_d_context));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(b_watcher, nullptr, nullptr, nullptr, nullptr));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(cd_watcher, nullptr, nullptr, nullptr, nullptr));
-
- WriteMessage(d, kTestMessageToC);
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(cd_watcher));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b_watcher));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
-}
-
-TEST_F(WatcherTest, CancelSelfInNotificationCallback) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- static const char kTestMessageToA[] = "hey a";
-
- MojoHandle w;
- WatchHelper helper;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- static uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoHandle w, MojoHandle a,
- MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
-
- // There should be no problem cancelling this watch from its own
- // notification invocation.
- EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context));
- EXPECT_EQ(kTestMessageToA, ReadMessage(a));
-
- // Arming should fail because there are no longer any registered
- // watches on the watcher.
- EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // And closing |a| should be fine (and should not invoke this
- // notification with MOJO_RESULT_CANCELLED) for the same reason.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
-
- event->Signal();
- },
- &event, w, a));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- WriteMessage(b, kTestMessageToA);
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-}
-
-TEST_F(WatcherTest, CloseWatcherInNotificationCallback) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- static const char kTestMessageToA1[] = "hey a";
- static const char kTestMessageToA2[] = "hey a again";
-
- MojoHandle w;
- WatchHelper helper;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoHandle w, MojoHandle a, MojoHandle b,
- MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToA1, ReadMessage(a));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // There should be no problem closing this watcher from its own
- // notification callback.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-
- // And these should not trigger more notifications, because |w| has been
- // closed already.
- WriteMessage(b, kTestMessageToA2);
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
-
- event->Signal();
- },
- &event, w, a, b));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- WriteMessage(b, kTestMessageToA1);
- event.Wait();
-}
-
-TEST_F(WatcherTest, CloseWatcherAfterImplicitCancel) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- static const char kTestMessageToA[] = "hey a";
-
- MojoHandle w;
- WatchHelper helper;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoHandle w, MojoHandle a,
- MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToA, ReadMessage(a));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // This will cue up a notification for |MOJO_RESULT_CANCELLED|...
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
-
- // ...but it should never fire because we close the watcher here.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-
- event->Signal();
- },
- &event, w, a));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- WriteMessage(b, kTestMessageToA);
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
-}
-
-TEST_F(WatcherTest, OtherThreadCancelDuringNotification) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- static const char kTestMessageToA[] = "hey a";
-
- MojoHandle w;
- WatchHelper helper;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- base::WaitableEvent wait_for_notification(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- base::WaitableEvent wait_for_cancellation(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- static bool callback_done = false;
- uintptr_t readable_a_context = helper.CreateContextWithCancel(
- base::Bind(
- [](base::WaitableEvent* wait_for_notification, MojoHandle w,
- MojoHandle a, MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToA, ReadMessage(a));
-
- wait_for_notification->Signal();
-
- // Give the other thread sufficient time to race with the completion
- // of this callback. There should be no race, since the cancellation
- // notification must be mutually exclusive to this notification.
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
-
- callback_done = true;
- },
- &wait_for_notification, w, a),
- base::Bind(
- [](base::WaitableEvent* wait_for_cancellation) {
- EXPECT_TRUE(callback_done);
- wait_for_cancellation->Signal();
- },
- &wait_for_cancellation));
-
- ThreadedRunner runner(base::Bind(
- [](base::WaitableEvent* wait_for_notification,
- base::WaitableEvent* wait_for_cancellation, MojoHandle w,
- uintptr_t readable_a_context) {
- wait_for_notification->Wait();
-
- // Cancel the watch while the notification is still running.
- EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context));
-
- wait_for_cancellation->Wait();
-
- EXPECT_TRUE(callback_done);
- },
- &wait_for_notification, &wait_for_cancellation, w, readable_a_context));
- runner.Start();
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- WriteMessage(b, kTestMessageToA);
- runner.Join();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-}
-
-TEST_F(WatcherTest, WatchesCancelEachOtherFromNotifications) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- static const char kTestMessageToA[] = "hey a";
- static const char kTestMessageToB[] = "hey b";
-
- base::WaitableEvent wait_for_a_to_notify(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- base::WaitableEvent wait_for_b_to_notify(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- base::WaitableEvent wait_for_a_to_cancel(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- base::WaitableEvent wait_for_b_to_cancel(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- MojoHandle a_watcher;
- MojoHandle b_watcher;
- WatchHelper helper;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&a_watcher));
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&b_watcher));
-
- // We set up two watchers, one on |a| and one on |b|. They cancel each other
- // from within their respective watch notifications. This should be safe,
- // i.e., it should not deadlock, in spite of the fact that we also guarantee
- // mutually exclusive notification execution (including cancellations) on any
- // given watch.
- bool a_cancelled = false;
- bool b_cancelled = false;
- static uintptr_t readable_b_context;
- uintptr_t readable_a_context = helper.CreateContextWithCancel(
- base::Bind(
- [](base::WaitableEvent* wait_for_a_to_notify,
- base::WaitableEvent* wait_for_b_to_notify, MojoHandle b_watcher,
- MojoHandle a, MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToA, ReadMessage(a));
- wait_for_a_to_notify->Signal();
- wait_for_b_to_notify->Wait();
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoCancelWatch(b_watcher, readable_b_context));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b_watcher));
- },
- &wait_for_a_to_notify, &wait_for_b_to_notify, b_watcher, a),
- base::Bind(
- [](base::WaitableEvent* wait_for_a_to_cancel,
- base::WaitableEvent* wait_for_b_to_cancel, bool* a_cancelled) {
- *a_cancelled = true;
- wait_for_a_to_cancel->Signal();
- wait_for_b_to_cancel->Wait();
- },
- &wait_for_a_to_cancel, &wait_for_b_to_cancel, &a_cancelled));
-
- readable_b_context = helper.CreateContextWithCancel(
- base::Bind(
- [](base::WaitableEvent* wait_for_a_to_notify,
- base::WaitableEvent* wait_for_b_to_notify,
- uintptr_t readable_a_context, MojoHandle a_watcher, MojoHandle b,
- MojoResult result, MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- EXPECT_EQ(kTestMessageToB, ReadMessage(b));
- wait_for_b_to_notify->Signal();
- wait_for_a_to_notify->Wait();
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoCancelWatch(a_watcher, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a_watcher));
- },
- &wait_for_a_to_notify, &wait_for_b_to_notify, readable_a_context,
- a_watcher, b),
- base::Bind(
- [](base::WaitableEvent* wait_for_a_to_cancel,
- base::WaitableEvent* wait_for_b_to_cancel, bool* b_cancelled) {
- *b_cancelled = true;
- wait_for_b_to_cancel->Signal();
- wait_for_a_to_cancel->Wait();
- },
- &wait_for_a_to_cancel, &wait_for_b_to_cancel, &b_cancelled));
-
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(a_watcher, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(a_watcher, nullptr, nullptr, nullptr, nullptr));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_b_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(b_watcher, nullptr, nullptr, nullptr, nullptr));
-
- ThreadedRunner runner(
- base::Bind([](MojoHandle b) { WriteMessage(b, kTestMessageToA); }, b));
- runner.Start();
-
- WriteMessage(a, kTestMessageToB);
-
- wait_for_a_to_cancel.Wait();
- wait_for_b_to_cancel.Wait();
- runner.Join();
-
- EXPECT_TRUE(a_cancelled);
- EXPECT_TRUE(b_cancelled);
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
-}
-
-TEST_F(WatcherTest, AlwaysCancel) {
- // Basic sanity check to ensure that all possible ways to cancel a watch
- // result in a final MOJO_RESULT_CANCELLED notification.
-
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- MojoHandle w;
- WatchHelper helper;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- const base::Closure signal_event =
- base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event));
-
- // Cancel via |MojoCancelWatch()|.
- uintptr_t context = helper.CreateContextWithCancel(
- WatchHelper::ContextCallback(), signal_event);
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, context));
- EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, context));
- event.Wait();
- event.Reset();
-
- // Cancel by closing the watched handle.
- context = helper.CreateContextWithCancel(WatchHelper::ContextCallback(),
- signal_event);
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, context));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- event.Wait();
- event.Reset();
-
- // Cancel by closing the watcher handle.
- context = helper.CreateContextWithCancel(WatchHelper::ContextCallback(),
- signal_event);
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, context));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
-}
-
-TEST_F(WatcherTest, ArmFailureCirculation) {
- // Sanity check to ensure that all ready handles will eventually be returned
- // over a finite number of calls to MojoArmWatcher().
-
- constexpr size_t kNumTestPipes = 100;
- constexpr size_t kNumTestHandles = kNumTestPipes * 2;
- MojoHandle handles[kNumTestHandles];
-
- // Create a bunch of pipes and make sure they're all readable.
- for (size_t i = 0; i < kNumTestPipes; ++i) {
- CreateMessagePipe(&handles[i], &handles[i + kNumTestPipes]);
- WriteMessage(handles[i], "hey");
- WriteMessage(handles[i + kNumTestPipes], "hay");
- WaitForSignals(handles[i], MOJO_HANDLE_SIGNAL_READABLE);
- WaitForSignals(handles[i + kNumTestPipes], MOJO_HANDLE_SIGNAL_READABLE);
- }
-
- // Create a watcher and watch all of them.
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateTrap(&ExpectOnlyCancel, nullptr, &w));
- for (size_t i = 0; i < kNumTestHandles; ++i) {
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, handles[i], MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, i));
- }
-
- // Keep trying to arm |w| until every watch gets an entry in |ready_contexts|.
- // If MojoArmWatcher() is well-behaved, this should terminate eventually.
- std::set<uintptr_t> ready_contexts;
- while (ready_contexts.size() < kNumTestHandles) {
- uint32_t num_ready_contexts = 1;
- uintptr_t ready_context;
- MojoResult ready_result;
- MojoHandleSignalsState ready_state;
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- MojoArmWatcher(w, &num_ready_contexts, &ready_context,
- &ready_result, &ready_state));
- EXPECT_EQ(1u, num_ready_contexts);
- EXPECT_EQ(MOJO_RESULT_OK, ready_result);
- ready_contexts.insert(ready_context);
- }
-
- for (size_t i = 0; i < kNumTestHandles; ++i)
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[i]));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
-}
-
-TEST_F(WatcherTest, WatchNotSatisfied) {
- MojoHandle a, b;
- CreateMessagePipe(&a, &b);
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- WatchHelper helper;
- const uintptr_t readable_a_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- event->Signal();
- },
- &event));
-
- MojoHandle w;
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- const char kMessage[] = "this is not a message";
-
- WriteMessage(b, kMessage);
- event.Wait();
-
- // Now we know |a| is readable. Cancel the watch and watch for the
- // not-readable state.
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- const uintptr_t not_readable_a_context = helper.CreateContext(base::Bind(
- [](base::WaitableEvent* event, MojoResult result,
- MojoHandleSignalsState state) {
- EXPECT_EQ(MOJO_RESULT_OK, result);
- event->Signal();
- },
- &event));
- EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_NOT_SATISFIED,
- not_readable_a_context));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr));
-
- // This should not block, because the event should be signaled by
- // |not_readable_a_context| when we read the only available message off of
- // |a|.
- event.Reset();
- EXPECT_EQ(kMessage, ReadMessage(a));
- event.Wait();
-
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
- EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
-}
-
-base::Closure g_do_random_thing_callback;
-
-void ReadAllMessages(const MojoTrapEvent* event) {
- if (event->result == MOJO_RESULT_OK) {
- MojoHandle handle = static_cast<MojoHandle>(event->trigger_context);
- MojoMessageHandle message;
- while (MojoReadMessage(handle, nullptr, &message) == MOJO_RESULT_OK)
- MojoDestroyMessage(message);
- }
-
- constexpr size_t kNumRandomThingsToDoOnNotify = 5;
- for (size_t i = 0; i < kNumRandomThingsToDoOnNotify; ++i)
- g_do_random_thing_callback.Run();
-}
-
-MojoHandle RandomHandle(MojoHandle* handles, size_t size) {
- return handles[base::RandInt(0, static_cast<int>(size) - 1)];
-}
-
-void DoRandomThing(MojoHandle* watchers,
- size_t num_watchers,
- MojoHandle* watched_handles,
- size_t num_watched_handles) {
- switch (base::RandInt(0, 10)) {
- case 0:
- MojoClose(RandomHandle(watchers, num_watchers));
- break;
- case 1:
- MojoClose(RandomHandle(watched_handles, num_watched_handles));
- break;
- case 2:
- case 3:
- case 4: {
- MojoMessageHandle message;
- ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
- ASSERT_EQ(MOJO_RESULT_OK,
- MojoSetMessageContext(message, 1, nullptr, nullptr, nullptr));
- MojoWriteMessage(RandomHandle(watched_handles, num_watched_handles),
- message, nullptr);
- break;
- }
- case 5:
- case 6: {
- MojoHandle w = RandomHandle(watchers, num_watchers);
- MojoHandle h = RandomHandle(watched_handles, num_watched_handles);
- MojoWatch(w, h, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_WATCH_CONDITION_SATISFIED, static_cast<uintptr_t>(h));
- break;
- }
- case 7:
- case 8: {
- uint32_t num_ready_contexts = 1;
- uintptr_t ready_context;
- MojoResult ready_result;
- MojoHandleSignalsState ready_state;
- if (MojoArmWatcher(RandomHandle(watchers, num_watchers),
- &num_ready_contexts, &ready_context, &ready_result,
- &ready_state) == MOJO_RESULT_FAILED_PRECONDITION &&
- ready_result == MOJO_RESULT_OK) {
- MojoTrapEvent event;
- event.struct_size = sizeof(event);
- event.trigger_context = ready_context;
- event.result = ready_result;
- event.signals_state = ready_state;
- event.flags = MOJO_TRAP_EVENT_FLAG_NONE;
- ReadAllMessages(&event);
- }
- break;
- }
- case 9:
- case 10: {
- MojoHandle w = RandomHandle(watchers, num_watchers);
- MojoHandle h = RandomHandle(watched_handles, num_watched_handles);
- MojoCancelWatch(w, static_cast<uintptr_t>(h));
- break;
- }
- default:
- NOTREACHED();
- break;
- }
-}
-
-TEST_F(WatcherTest, ConcurrencyStressTest) {
- // Regression test for https://crbug.com/740044. Exercises racy usage of the
- // watcher API to weed out potential crashes.
-
- constexpr size_t kNumWatchers = 50;
- constexpr size_t kNumWatchedHandles = 50;
- static_assert(kNumWatchedHandles % 2 == 0, "Invalid number of test handles.");
-
- constexpr size_t kNumThreads = 10;
- static constexpr size_t kNumOperationsPerThread = 400;
-
- MojoHandle watchers[kNumWatchers];
- MojoHandle watched_handles[kNumWatchedHandles];
- g_do_random_thing_callback =
- base::Bind(&DoRandomThing, watchers, kNumWatchers, watched_handles,
- kNumWatchedHandles);
-
- for (size_t i = 0; i < kNumWatchers; ++i)
- MojoCreateTrap(&ReadAllMessages, nullptr, &watchers[i]);
- for (size_t i = 0; i < kNumWatchedHandles; i += 2)
- CreateMessagePipe(&watched_handles[i], &watched_handles[i + 1]);
-
- std::unique_ptr<ThreadedRunner> threads[kNumThreads];
- auto runner_callback = base::Bind([]() {
- for (size_t i = 0; i < kNumOperationsPerThread; ++i)
- g_do_random_thing_callback.Run();
- });
- for (size_t i = 0; i < kNumThreads; ++i) {
- threads[i] = std::make_unique<ThreadedRunner>(runner_callback);
- threads[i]->Start();
- }
- for (size_t i = 0; i < kNumThreads; ++i)
- threads[i]->Join();
- for (size_t i = 0; i < kNumWatchers; ++i)
- MojoClose(watchers[i]);
- for (size_t i = 0; i < kNumWatchedHandles; ++i)
- MojoClose(watched_handles[i]);
-}
-
-} // namespace
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/public/c/system/README.md b/chromium/mojo/public/c/system/README.md
index f31375e903a..ec88e3e6674 100644
--- a/chromium/mojo/public/c/system/README.md
+++ b/chromium/mojo/public/c/system/README.md
@@ -4,15 +4,16 @@ This document is a subset of the [Mojo documentation](/mojo/README.md).
[TOC]
## Overview
-The Mojo C System API is a lightweight API (with an eventually-stable ABI) upon
-which all higher layers of the Mojo system are built.
+The Mojo C System API is a lightweight API (with an stable, forward-compatible
+ABI) upon which all higher-level public Mojo APIs are built.
This API exposes the fundamental capabilities to: create, read from, and write
to **message pipes**; create, read from, and write to **data pipes**; create
**shared buffers** and generate sharable handles to them; wrap platform-specific
handle objects (such as **file descriptors**, **Windows handles**, and
**Mach ports**) for seamless transit over message pipes; and efficiently watch
-handles for various types of state transitions.
+handles for various types of state transitions. Finally, there are also APIs to
+bootstrap Mojo IPC between two processes.
This document provides a brief guide to API usage with example code snippets.
For a detailed API references please consult the headers in
@@ -64,11 +65,14 @@ API calls, or by reading messages which contain attached handles.
A `MojoHandle` can represent a message pipe endpoint, a data pipe consumer,
a data pipe producer, a shared buffer reference, a wrapped native platform
-handle such as a POSIX file descriptor or a Windows system handle, or a watcher
-object (see [Signals & Watchers](#Signals-Watchers) below.)
+handle such as a POSIX file descriptor or a Windows system handle, a trap object
+(see [Signals & Traps](#Signals-Traps) below), or a process invitation (see
+[Invitations](#Invitations) below).
-All types of handles except for watchers (which are an inherently local concept)
-can be attached to messages and sent over message pipes.
+Message pipes, data pipes, shared buffers, and platform handles can all be
+attached to messages and sent over message pipes. Traps are an inherently
+process-local concept, and invitations are transmitted using special dedicated
+APIs.
Any `MojoHandle` may be closed by calling `MojoClose`:
@@ -92,12 +96,11 @@ unstructured binary messages with zero or more `MojoHandle` attachments to be
transferred from one end of a pipe to the other. Message pipes work seamlessly
across process boundaries or within a single process.
-The [Embedder Development Kit (EDK)](/mojo/edk/embedder/README.md) provides the
-means to bootstrap one or more primordial cross-process message pipes, and it's
-up to Mojo embedders to expose this capability in some useful way. Once such a
-pipe is established, additional handles -- including other message pipe
-handles -- may be sent to a remote process using that pipe (or in turn, over
-other pipes sent over that pipe, or pipes sent over *that* pipe, and so on...)
+[Invitations](#Invitations) provide the means to bootstrap one or more
+primordial cross-process message pipes between two processes. Once such a pipe
+is established, additional handles -- including other message pipe handles --
+may be sent to a remote process using that pipe (or in turn, over other pipes
+sent over that pipe, or pipes sent over *that* pipe, and so on...)
The public C System API exposes the ability to read and write messages on pipes
and to create new message pipes.
@@ -124,7 +127,7 @@ written to `b` are eventually readable from `a`. If `a` is closed at any point,
will become aware of that.
The state of these conditions can be queried and watched asynchronously as
-described in the [Signals & Watchers](#Signals-Watchers) section below.
+described in the [Signals & Traps](#Signals-Traps) section below.
### Creating Messages
@@ -221,7 +224,7 @@ and not transferred.
In this case since we know `b` is still open, we also know the message will
eventually arrive at `b`. `b` can be queried or watched to become aware of when
the message arrives, but we'll ignore that complexity for now. See
-[Signals & Watchers](#Signals-Watchers) below for more information.
+[Signals & Traps](#Signals-Traps) below for more information.
*** aside
**NOTE**: Although this is an implementation detail and not strictly guaranteed
@@ -528,7 +531,7 @@ over a message pipe first.
Native platform handles to system objects can be wrapped as Mojo handles for
seamless transit over message pipes. Mojo currently supports wrapping POSIX
-file descriptors, Windows handles, and Mach ports.
+file descriptors, Windows handles, Mach ports, and Fuchsia zx_handles.
See [//mojo/public/c/system/platform_handle.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/platform_handle.h)
for detailed platform handle API documentation.
@@ -579,7 +582,7 @@ On OS X, the wrapped platform handle must be a memory-object send right.
On all other POSIX systems, the wrapped platform handle must be a file
descriptor for a shared memory object.
-## Signals & Watchers
+## Signals & Traps
Message pipe and data pipe (producer and consumer) handles can change state in
ways that may be interesting to a Mojo API user. For example, you may wish to
@@ -649,81 +652,72 @@ Finally if we read the last message from `a` its signaling state becomes:
and we know definitively that `a` can never be read from again.
-### Watching Signals
+### Trapping Signals
The ability to query a handle's signaling state can be useful, but it's not
-sufficient to support robust and efficient pipe usage. Mojo watchers empower
-users with the ability to **watch** a handle's signaling state for interesting
-changes and automatically invoke a notification handler in response.
+sufficient to support robust and efficient pipe usage. Mojo traps empower users
+with the ability to **trap** changes in a handle's signaling state and
+automatically invoke a notification handler in response.
-When a watcher is created it must be bound to a function pointer matching
+When a trap is created it must be bound to a function pointer matching
the following signature, defined in
-[//mojo/public/c/system/watcher.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/watcher.h):
+[//mojo/public/c/system/trap.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/trap.h):
``` c
-typedef void (*MojoWatcherNotificationCallback)(
- uintptr_t context,
- MojoResult result,
- MojoHandleSignalsState signals_state,
- MojoWatcherNotificationFlags flags);
+typedef void (*MojoTrapEventHandler)(const struct MojoTrapEvent* event);
```
-The `context` argument corresponds to a specific handle being watched by the
-watcher (read more below), and the remaining arguments provide details regarding
-the specific reason for the notification. It's important to be aware that a
-watcher's registered handler may be called **at any time** and
-**on any thread**.
+The `event` parameter conveys details about why the event handler is being
+invoked. The handler may be called **at any time** and **from any thread**, so
+it is critical that handler implementations account for this.
It's also helpful to understand a bit about the mechanism by which the handler
can be invoked. Essentially, any Mojo C System API call may elicit a handle
state change of some kind. If such a change is relevant to conditions watched by
-a watcher, and that watcher is in a state which allows it raise a corresponding
+a trap, and that trap is in a state which allows it raise a corresponding
notification, its notification handler will be invoked synchronously some time
-before the outermost System API call on the current thread's stack returns.
+before the stack unwinds beyond the outermost System API call on the current
+thread.
Handle state changes can also occur as a result of incoming IPC from an external
process. If a pipe in the current process is connected to an endpoint in another
process and the internal Mojo system receives an incoming message bound for the
-local endpoint, the arrival of that message will trigger a state change on the
-receiving handle and may thus invoke one or more watchers' notification handlers
-as a result.
+local endpoint, the arrival of that message may trigger a state change on the
+receiving handle and may therefore invoke one or more traps' notification
+handlers as a result.
-The `MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM` flag on the notification
-handler's `flags` argument is used to indicate whether the handler was invoked
-due to such an internal system IPC event (if the flag is set), or if it was
-invoked synchronously due to some local API call (if the flag is unset.)
-This distinction can be useful to make in certain cases to *e.g.* avoid
-accidental reentrancy in user code.
+The `MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL` flag on the `flags` field of `event`
+is used to indicate whether the handler was invoked due to such an internal
+system IPC event (if the flag is unset), or if it was invoked synchronously due
+to some local API call (if the flag is set.) This distinction can be useful to
+make in certain cases to *e.g.* avoid accidental reentrancy in user code.
-### Creating a Watcher
+### Creating a Trap
-Creating a watcher is simple:
+Creating a trap is simple:
``` c
-void OnNotification(uintptr_t context,
- MojoResult result,
- MojoHandleSignalsState signals_state,
- MojoWatcherNotificationFlags flags) {
+void OnNotification(const struct MojoTrapEvent* event) {
// ...
}
-MojoHandle w;
-MojoResult result = MojoCreateWatcher(&OnNotification, &w);
+MojoHandle t;
+MojoResult result = MojoCreateTrap(&OnNotification, NULL, &t);
```
-Like all other `MojoHandle` types, watchers may be destroyed by closing them
-with `MojoClose`. Unlike other `MojoHandle` types, watcher handles are **not**
+Like all other `MojoHandle` types, traps may be destroyed by closing them with
+`MojoClose`. Unlike most other `MojoHandle` types, trap handles are **not**
transferrable across message pipes.
-In order for a watcher to be useful, it has to watch at least one handle.
+In order for a trap to be useful, it has have at least one **trigger** attached
+to it.
-### Adding a Handle to a Watcher
+### Adding a Trigger to a Trap
-Any given watcher can watch any given (message or data pipe) handle for some set
+Any given trap can watch any given (message or data pipe) handle for some set
of signaling conditions. A handle may be watched simultaneously by multiple
-watchers, and a single watcher can watch multiple different handles
-simultaneously.
+traps, and a single trap can watch multiple different handles simultaneously.
``` c
MojoHandle a, b;
@@ -731,25 +725,27 @@ MojoCreateMessagePipe(NULL, &a, &b);
// Watch handle |a| for readability.
const uintptr_t context = 1234;
-MojoResult result = MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, context);
+MojoResult result = MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ context, NULL);
```
-We've successfully instructed watcher `w` to begin watching pipe handle `a` for
-readability. However, our recently created watcher is still in a **disarmed**
-state, meaning that it will never fire a notification pertaining to this watched
-signaling condition. It must be **armed** before that can happen.
+We've successfully instructed trap `t` to begin watching pipe handle `a` for
+readability. However, our recently created trap is still in a **disarmed**
+state, meaning that it will never fire a notification pertaining to this
+trigger. It must be **armed** before that can happen.
-### Arming a Watcher
+### Arming a Trap
-In order for a watcher to invoke its notification handler in response to a
-relevant signaling state change on a watched handle, it must first be armed. A
-watcher may only be armed if none of its watched handles would elicit a
-notification immediately once armed.
+In order for a trap to invoke its notification handler in response to a relevant
+signaling state change on a watched handle, it must first be armed. A trap may
+only be armed if none of its attached triggers would elicit a notification
+immediately once armed.
In this case `a` is clearly not yet readable, so arming should succeed:
``` c
-MojoResult result = MojoArmWatcher(w, NULL, NULL, NULL, NULL);
+MojoResult result = MojoArmTrap(t, NULL, NULL, NULL);
```
Now we can write to `b` to make `a` readable:
@@ -762,56 +758,58 @@ MojoWriteMessage(b, m, nullptr);
Eventually -- and in practice possibly before `MojoWriteMessage` even
returns -- this will cause `OnNotification` to be invoked on the calling thread
-with the `context` value (*i.e.* 1234) that was given when the handle was added
-to the watcher.
+with the `context` value (*i.e.* 1234) that was given when the trigger was added
+to the trap.
-The `result` parameter will be `MOJO_RESULT_OK` to indicate that the watched
-signaling condition has been *satisfied*. If the watched condition had instead
-become permanently *unsatisfiable* (*e.g.*, if `b` were instead closed), `result`
-would instead indicate `MOJO_RESULT_FAILED_PRECONDITION`.
+The `result` field of the event will be `MOJO_RESULT_OK` to indicate that the
+trigger's condition has been met. If the handle's state had instead changed in
+such a way that the trigger's condition could never be met again (*e.g.* if `b`
+were instead closed), `result` would instead indicate
+`MOJO_RESULT_FAILED_PRECONDITION`.
-**NOTE:** Immediately before a watcher decides to invoke its notification
-handler, it automatically disarms itself to prevent another state change from
-eliciting another notification. Therefore a watcher must be repeatedly rearmed
-in order to continue dispatching signaling notifications.
+**NOTE:** Immediately before a trigger decides to invoke its event handler, it
+automatically disarms itself to prevent another state change from eliciting
+another notification. Therefore a trap must be repeatedly rearmed in order to
+continue dispatching events.
-As noted above, arming a watcher may fail if any of the watched conditions for
-a handle are already partially satisfied or fully unsatisfiable. In that case
-the caller may provide buffers for `MojoArmWatcher` to store information about
-a subset of the relevant watches which caused it to fail:
+As noted above, arming a watcher may fail if any of its triggers would be
+activated immediately. In that case, the caller may provide buffers to
+`MojoArmTrap` to receive information about a subset of the triggers which caused
+it to fail:
``` c
-// Provide some storage for information about watches that are already ready.
-uint32_t num_ready_contexts = 4;
-uintptr_t ready_contexts[4];
-MojoResult ready_results[4];
-struct MojoHandleSignalsStates ready_states[4];
-MojoResult result = MojoArmWatcher(w, &num_ready_contexts, ready_contexts,
- ready_results, ready_states);
+// Provide some storage for information about triggers that would have been
+// activated immediately.
+uint32_t num_blocking_events = 2;
+MojoTrapEvent blocking_events[2] = {{sizeof(MojoTrapEvent)},
+ {sizeof(MojoTrapEvent)}};
+MojoResult result = MojoArmTrap(t, NULL, &num_blocking_events,
+ &blocking_events);
```
-Because `a` is still readable this operation will fail with
-`MOJO_RESULT_FAILED_PRECONDITION`. The input value of `num_ready_contexts`
-informs `MojoArmWatcher` that it may store information regarding up to 4 watches
-which currently prevent arming. In this case of course there is only one active
-watch, so upon return we will see:
+Because `a` is still readable this operation will now fail with
+`MOJO_RESULT_FAILED_PRECONDITION`. The input value of `num_blocking_events`
+informs `MojoArmTrap` that it may store information regarding up to 2 triggers
+which have prevented arming. In this case of course there is only one active
+trigger, so upon return we will see:
-* `num_ready_contexts` is `1`.
-* `ready_contexts[0]` is `1234`.
-* `ready_results[0]` is `MOJO_RESULT_OK`
-* `ready_states[0]` is the last known signaling state of handle `a`.
+* `num_blocking_events` is `1`.
+* `blocking_events[0].trigger_context` is `1234`.
+* `blocking_events[0].result` is `MOJO_RESULT_OK`
+* `blocking_events[0].signals_state` is the last known signaling state of handle
+ `a`.
-In other words the stored information mirrors what would have been the
-notification handler's arguments if the watcher were allowed to arm and thus
-notify immediately.
+In other words the stored information mirrors what would have been the resulting
+event structure if the trap were allowed to arm and then notify immediately.
-### Cancelling a Watch
+### Removing a Trigger
-There are three ways a watch can be cancelled:
+There are three ways a trigger can be removed:
-* The watched handle is closed
-* The watcher handle is closed (in which case all of its watches are cancelled.)
-* `MojoCancelWatch` is explicitly called for a given `context`.
+* The handle being watched by the trigger is closed
+* The trap handle is closed, in which case all of its attached triggers are
+ implicitly removed.
+* `MojoRemoveTrigger` is called for a given `context`.
In the above example this means any of the following operations will cancel the
watch on `a`:
@@ -820,25 +818,24 @@ watch on `a`:
// Close the watched handle...
MojoClose(a);
-// OR close the watcher handle...
-MojoClose(w);
+// OR close the trap handle...
+MojoClose(t);
-// OR explicitly cancel.
-MojoResult result = MojoCancelWatch(w, 1234);
+// OR explicitly remove it.
+MojoResult result = MojoRemoveTrigger(t, 1234, NULL);
```
-In every case the watcher's notification handler is invoked for the cancelled
-watch(es) regardless of whether or not the watcher is or was armed at the time.
-The notification handler receives a `result` of `MOJO_RESULT_CANCELLED` for
-these notifications, and this is guaranteed to be the final notification for any
-given watch context.
+In every case the trap's event handler is invoked for the cancelled trigger(es)
+regardless of whether or not the trap was armed at the time. The event handler
+receives a `result` of `MOJO_RESULT_CANCELLED` for each of these invocations,
+and this is guaranteed to be the final event for any given trigger context.
-### Practical Watch Context Usage
+### Practical Trigger Context Usage
-It is common and probably wise to treat a watch's `context` value as an opaque
+It is common and probably wise to treat a trigger's `context` value as an opaque
pointer to some thread-safe state associated in some way with the handle being
-watched. Here's a small example which uses a single watcher to watch both ends
-of a message pipe and accumulate a count of messages received at each end.
+watched. Here's a small example which uses a single trap to watch both ends of a
+message pipe and accumulate a count of messages received at each end.
``` c
// NOTE: For the sake of simplicity this example code is not in fact
@@ -846,45 +843,43 @@ of a message pipe and accumulate a count of messages received at each end.
// no external process connections, this is fine.
struct WatchedHandleState {
- MojoHandle watcher;
+ MojoHandle trap;
MojoHandle handle;
int message_count;
};
-void OnNotification(uintptr_t context,
- MojoResult result,
- MojoHandleSignalsState signals_state,
- MojoWatcherNotificationFlags flags) {
- struct WatchedHandleState* state = (struct WatchedHandleState*)(context);
+void OnNotification(const struct MojoTrapEvent* event) {
+ struct WatchedHandleState* state =
+ (struct WatchedHandleState*)(event->trigger_context);
MojoResult rv;
- if (result == MOJO_RESULT_CANCELLED) {
- // Cancellation is always the last notification and is guaranteed to
- // eventually happen for every context, assuming no handles are leaked. We
- // treat this as an opportunity to free the WatchedHandleState.
+ if (event->result == MOJO_RESULT_CANCELLED) {
+ // Cancellation is always the last event and is guaranteed to happen for
+ // every context, assuming no handles are leaked. We treat this as an
+ // opportunity to free the WatchedHandleState.
free(state);
return;
}
if (result == MOJO_RESULT_FAILED_PRECONDITION) {
// No longer readable, i.e. the other handle must have been closed. Better
- // cancel. Note that we could also just call MojoClose(state->watcher) here
- // since we know |context| is its only registered watch.
- MojoCancelWatch(state->watcher, context);
+ // cancel. Note that we could also just call MojoClose(state->trap) here
+ // since we know there's only one attached trigger.
+ MojoRemoveTrigger(state->trap, event->trigger_context, NULL);
return;
}
- // This is the only handle watched by the watcher, so as long as we can't arm
+ // This is the only handle watched by the trap, so as long as we can't arm
// the watcher we know something's up with this handle. Try to read messages
// until we can successfully arm again or something goes terribly wrong.
- while (MojoArmWatcher(state->watcher, NULL, NULL, NULL, NULL) ==
+ while (MojoArmTrap(state->trap, NULL NULL, NULL) ==
MOJO_RESULT_FAILED_PRECONDITION) {
rv = MojoReadMessageNew(state->handle, NULL, NULL, NULL,
MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
if (rv == MOJO_RESULT_OK) {
state->message_count++;
} else if (rv == MOJO_RESULT_FAILED_PRECONDITION) {
- MojoCancelWatch(state->watcher, context);
+ MojoRemoveTrigger(state->trap, event->trigger_context, NULL);
return;
}
}
@@ -893,25 +888,29 @@ void OnNotification(uintptr_t context,
MojoHandle a, b;
MojoCreateMessagePipe(NULL, &a, &b);
-MojoHandle a_watcher, b_watcher;
-MojoCreateWatcher(&OnNotification, &a_watcher);
-MojoCreateWatcher(&OnNotification, &b_watcher)
+MojoHandle a_trap, b_trap;
+MojoCreateTrap(&OnNotification, NULL, &a_trap);
+MojoCreateTrap(&OnNotification, NULL, &b_trap)
struct WatchedHandleState* a_state = malloc(sizeof(struct WatchedHandleState));
-a_state->watcher = a_watcher;
+a_state->trap = a_trap;
a_state->handle = a;
a_state->message_count = 0;
struct WatchedHandleState* b_state = malloc(sizeof(struct WatchedHandleState));
-b_state->watcher = b_watcher;
+b_state->trap = b_trap;
b_state->handle = b;
b_state->message_count = 0;
-MojoWatch(a_watcher, a, MOJO_HANDLE_SIGNAL_READABLE, (uintptr_t)a_state);
-MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, (uintptr_t)b_state);
+MojoAddTrigger(a_trap, a, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, (uintptr_t)a_state,
+ NULL);
+MojoAddTrigger(b_trap, b, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, (uintptr_t)b_state,
+ NULL);
-MojoArmWatcher(a_watcher, NULL, NULL, NULL, NULL);
-MojoArmWatcher(b_watcher, NULL, NULL, NULL, NULL);
+MojoArmTrap(a_trap, NULL, NULL, NULL);
+MojoArmTrap(b_trap, NULL, NULL, NULL);
```
Now any writes to `a` will increment `message_count` in `b_state`, and any
@@ -920,3 +919,12 @@ writes to `b` will increment `message_count` in `a_state`.
If either `a` or `b` is closed, both watches will be cancelled - one because
watch cancellation is implicit in handle closure, and the other because its
watcher will eventually detect that the handle is no longer readable.
+
+## Invitations
+
+TODO.
+
+For now see the
+[C header](https://cs.chromium.org/src/mojo/public/c/system/invitation.h) and
+the documentation for the equivalent
+[C++ API](/mojo/public/cpp/system/README.md#Invitations).
diff --git a/chromium/mojo/public/c/system/core.h b/chromium/mojo/public/c/system/core.h
index 5d29a0f485b..2e8fd39d3fa 100644
--- a/chromium/mojo/public/c/system/core.h
+++ b/chromium/mojo/public/c/system/core.h
@@ -16,6 +16,7 @@
#include "mojo/public/c/system/macros.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/c/system/platform_handle.h"
+#include "mojo/public/c/system/quota.h"
#include "mojo/public/c/system/system_export.h"
#include "mojo/public/c/system/trap.h"
#include "mojo/public/c/system/types.h"
diff --git a/chromium/mojo/public/c/system/functions.h b/chromium/mojo/public/c/system/functions.h
index f59ee577342..9f90c38962e 100644
--- a/chromium/mojo/public/c/system/functions.h
+++ b/chromium/mojo/public/c/system/functions.h
@@ -21,8 +21,8 @@ extern "C" {
// Initializes Mojo in the calling application.
//
-// With the exception of EDK embedders, applications using Mojo APIs must call
-// this function before any others.
+// With the exception of Mojo Core embedders, applications using Mojo APIs must
+// call this function before any others.
//
// |options| may be null.
//
@@ -30,8 +30,8 @@ extern "C" {
// |MOJO_RESULT_OK| if Mojo intiailization was successful.
// |MOJO_RESULT_INVALID_ARGUMENT| if |options| was null or invalid.
// |MOJO_RESULT_FAILED_PRECONDITION| if |MojoInitialize()| was already called
-// once or if the application already explicitly initialized a Mojo EDK
-// environment.
+// once or if the application already explicitly initialized a Mojo Core
+// environment as an embedder.
MOJO_SYSTEM_EXPORT MojoResult
MojoInitialize(const struct MojoInitializeOptions* options);
diff --git a/chromium/mojo/public/c/system/invitation.h b/chromium/mojo/public/c/system/invitation.h
index 233b93740fa..eb1a4a80e8e 100644
--- a/chromium/mojo/public/c/system/invitation.h
+++ b/chromium/mojo/public/c/system/invitation.h
@@ -43,15 +43,13 @@ struct MOJO_ALIGNAS(8) MojoProcessErrorDetails {
// An error message corresponding to the reason why the connection was
// terminated. This is an information message which may be useful to
// developers.
- const char* error_message;
+ MOJO_POINTER_FIELD(const char*, error_message);
// See |MojoProcessErrorFlags|.
MojoProcessErrorFlags flags;
};
-MOJO_STATIC_ASSERT_FOR_32_BIT(sizeof(MojoProcessErrorDetails) == 16,
- "MojoProcessErrorDetails has wrong size.");
-MOJO_STATIC_ASSERT_FOR_64_BIT(sizeof(MojoProcessErrorDetails) == 24,
- "MojoProcessErrorDetails has wrong size.");
+MOJO_STATIC_ASSERT(sizeof(MojoProcessErrorDetails) == 24,
+ "MojoProcessErrorDetails has wrong size.");
// An opaque process handle value which must be provided when sending an
// invitation to another process via a platform transport. See
@@ -110,14 +108,10 @@ struct MOJO_ALIGNAS(8) MojoInvitationTransportEndpoint {
// - On Fuchsua, this is a single channel Fuchsia handle
// - On other POSIX systems, this is a single Unix domain socket file
// descriptor.
- const struct MojoPlatformHandle* platform_handles;
+ MOJO_POINTER_FIELD(const struct MojoPlatformHandle*, platform_handles);
};
-MOJO_STATIC_ASSERT_FOR_32_BIT(
- sizeof(MojoInvitationTransportEndpoint) == 16,
- "MojoInvitationTransportEndpoint has wrong size.");
-MOJO_STATIC_ASSERT_FOR_64_BIT(
- sizeof(MojoInvitationTransportEndpoint) == 24,
- "MojoInvitationTransportEndpoint has wrong size.");
+MOJO_STATIC_ASSERT(sizeof(MojoInvitationTransportEndpoint) == 24,
+ "MojoInvitationTransportEndpoint has wrong size.");
// Flags passed to |MojoCreateInvitation()| via |MojoCreateInvitationOptions|.
typedef uint32_t MojoCreateInvitationFlags;
@@ -181,6 +175,17 @@ typedef uint32_t MojoSendInvitationFlags;
// No flags. Default behavior.
#define MOJO_SEND_INVITATION_FLAG_NONE ((MojoSendInvitationFlags)0)
+// Send an isolated invitation to the receiver. Isolated invitations only
+// establish communication between the sender and the receiver. Accepting an
+// isolated invitation does not make IPC possible between the sender and any
+// other members of the receiver's process graph, nor does it make IPC possible
+// between the receiver and any other members of the sender's process graph.
+//
+// Invitations sent with this flag set must be accepted with the corresponding
+// |MOJO_ACCEPT_INVITATION_FLAG_ISOLATED| flag set, and may only have a single
+// message pipe attached with a name of exactly four zero-bytes ("\0\0\0\0").
+#define MOJO_SEND_INVITATION_FLAG_ISOLATED ((MojoSendInvitationFlags)1)
+
// Options passed to |MojoSendInvitation()|.
struct MOJO_ALIGNAS(8) MojoSendInvitationOptions {
// The size of this structure, used for versioning.
@@ -188,8 +193,16 @@ struct MOJO_ALIGNAS(8) MojoSendInvitationOptions {
// See |MojoSendInvitationFlags|.
MojoSendInvitationFlags flags;
+
+ // If |flags| includes |MOJO_SEND_INVITATION_FLAG_ISOLATED| then these fields
+ // specify a name identifying the established isolated connection. There are
+ // no restrictions on the value given. If |isolated_connection_name_length| is
+ // non-zero, the system ensures that only one isolated process connection can
+ // exist for the given name at any time.
+ MOJO_POINTER_FIELD(const char*, isolated_connection_name);
+ uint32_t isolated_connection_name_length;
};
-MOJO_STATIC_ASSERT(sizeof(MojoSendInvitationOptions) == 8,
+MOJO_STATIC_ASSERT(sizeof(MojoSendInvitationOptions) == 24,
"MojoSendInvitationOptions has wrong size");
// Flags passed to |MojoAcceptInvitation()| via |MojoAcceptInvitationOptions|.
@@ -198,6 +211,10 @@ typedef uint32_t MojoAcceptInvitationFlags;
// No flags. Default behavior.
#define MOJO_ACCEPT_INVITATION_FLAG_NONE ((MojoAcceptInvitationFlags)0)
+// Accept an isoalted invitation from the sender. See
+// |MOJO_SEND_INVITATION_FLAG_ISOLATED| for details.
+#define MOJO_ACCEPT_INVITATION_FLAG_ISOLATED ((MojoAcceptInvitationFlags)1)
+
// Options passed to |MojoAcceptInvitation()|.
struct MOJO_ALIGNAS(8) MojoAcceptInvitationOptions {
// The size of this structure, used for versioning.
@@ -229,7 +246,7 @@ typedef void (*MojoProcessErrorHandler)(
// An invitation is used to invite another process to join this process's
// IPC network. The caller must already be a member of a Mojo network, either
// either by itself having been previously invited, or by being the Mojo broker
-// process initialized via private Mojo APIs (i.e. the EDK).
+// process initialized via the Mojo Core Embedder API.
//
// Invitations can have message pipes attached to them, and these message pipes
// are used to bootstrap Mojo IPC between the inviter and the invitee. See
diff --git a/chromium/mojo/public/c/system/macros.h b/chromium/mojo/public/c/system/macros.h
index 2c297bb76ff..6de4a913de7 100644
--- a/chromium/mojo/public/c/system/macros.h
+++ b/chromium/mojo/public/c/system/macros.h
@@ -13,16 +13,19 @@
// MOJO_STATIC_ASSERT(sizeof(Foo) == 12, "Foo has invalid size");
#if defined(__cplusplus)
#define MOJO_STATIC_ASSERT(expr, msg) static_assert(expr, msg)
-#define MOJO_STATIC_ASSERT_FOR_32_BIT(expr, msg) \
- static_assert(sizeof(void*) != 4 || (expr), msg)
-#define MOJO_STATIC_ASSERT_FOR_64_BIT(expr, msg) \
- static_assert(sizeof(void*) != 8 || (expr), msg)
#else
#define MOJO_STATIC_ASSERT(expr, msg)
-#define MOJO_STATIC_ASSERT_FOR_32_BIT(expr, msg)
-#define MOJO_STATIC_ASSERT_FOR_64_BIT(expr, msg)
#endif
+// Defines a pointer-sized struct field of the given type. This ensures that the
+// field has an 8-byte footprint on both 32-bit and 64-bit systems, using an
+// anonymous bitfield of either 32 or 0 bits, depending on pointer size. Weird
+// formatting here courtesy of clang-format.
+#define MOJO_POINTER_FIELD(type, name) \
+ type name; \
+ uint32_t: \
+ (sizeof(void*) == 4 ? 32 : 0)
+
// Like the C++11 |alignof| operator.
#if __cplusplus >= 201103L
#define MOJO_ALIGNOF(type) alignof(type)
diff --git a/chromium/mojo/public/c/system/quota.h b/chromium/mojo/public/c/system/quota.h
new file mode 100644
index 00000000000..0e4ad3cb722
--- /dev/null
+++ b/chromium/mojo/public/c/system/quota.h
@@ -0,0 +1,126 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_QUOTA_H_
+#define MOJO_PUBLIC_C_SYSTEM_QUOTA_H_
+
+#include <stdint.h>
+
+#include "mojo/public/c/system/macros.h"
+#include "mojo/public/c/system/system_export.h"
+#include "mojo/public/c/system/types.h"
+
+// Flags passed to |MojoSetQuota| via |MojoSetQuotaOptions|.
+typedef uint32_t MojoSetQuotaFlags;
+
+// No flags.
+#define MOJO_SET_QUOTA_FLAG_NONE ((MojoSetQuotaFlags)0)
+
+// Options passed to |MojoSetQuota()|.
+struct MOJO_ALIGNAS(8) MojoSetQuotaOptions {
+ // The size of this structure, used for versioning.
+ uint32_t struct_size;
+
+ // See |MojoSetQuotaFlags| above.
+ MojoSetQuotaFlags flags;
+};
+MOJO_STATIC_ASSERT(sizeof(MojoSetQuotaOptions) == 8,
+ "MojoSetQuotaOptions has wrong size.");
+
+// Flags passed to |MojoQueryQuota| via |MojoQueryQuotaOptions|.
+typedef uint32_t MojoQueryQuotaFlags;
+
+// No flags.
+#define MOJO_QUERY_QUOTA_FLAG_NONE ((MojoQueryQuotaFlags)0)
+
+// Options passed to |MojoQueryQuota()|.
+struct MOJO_ALIGNAS(8) MojoQueryQuotaOptions {
+ // The size of this structure, used for versioning.
+ uint32_t struct_size;
+
+ // See |MojoQueryQuotaFlags| above.
+ MojoQueryQuotaFlags flags;
+};
+MOJO_STATIC_ASSERT(sizeof(MojoQueryQuotaOptions) == 8,
+ "MojoQueryQuotaOptions has wrong size.");
+
+// The maximum value any quota can be set to. Effectively means "no quota".
+#define MOJO_QUOTA_LIMIT_NONE ((uint64_t)0xffffffffffffffff)
+
+// An enumeration of different types of quotas that can be set on a handle.
+typedef uint32_t MojoQuotaType;
+
+// Limits the number of unread messages which can be queued on a message pipe
+// endpoint before raising a |MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED| signal on that
+// endpoint. May only be set on message pipe handles.
+#define MOJO_QUOTA_TYPE_RECEIVE_QUEUE_LENGTH ((MojoQuotaType)0)
+
+// Limits the total size (in bytes) of unread messages which can be queued on a
+// message pipe endpoint before raising a |MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED|
+// signal on that endpoint. May only be set on message pipe handles.
+#define MOJO_QUOTA_TYPE_RECEIVE_QUEUE_MEMORY_SIZE ((MojoQuotaType)1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Sets a quota on a given handle which will cause that handle to raise the
+// |MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED| signal if the quota is exceeded. Signals
+// can be trapped using |MojoCreateTrap()| and related APIs (see trap.h).
+//
+// All quota limits on a handle default to |MOJO_QUOTA_LIMIT_NONE|, meaning that
+// the resource is unlimited.
+//
+// NOTE: A handle's quota is only enforced as long as the handle remains within
+// the process which set the quota.
+//
+// Parameters:
+// |handle|: The handle on which a quota should be set.
+// |type|: The type of quota to set. Certain types of quotas may only be set
+// on certain types of handles. See notes on individual quota type
+// definitions above for meaning and restrictions.
+// |limit|: The limiting value of the quota. The meaning of this is determined
+// by |type|. See notes on individual quota type definitions above.
+// |options|: Additional options; may be null.
+//
+// Returns:
+// |MOJO_RESULT_OK| if the quota was successfully set.
+// |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle value,
+// |type| is not a known quota type, |options| is non-null but
+// |*options| is malformed, or the quota |type| cannot be set on |handle|
+// because the quota does not apply to that type of handle.
+MOJO_SYSTEM_EXPORT MojoResult
+MojoSetQuota(MojoHandle handle,
+ MojoQuotaType type,
+ uint64_t limit,
+ const struct MojoSetQuotaOptions* options);
+
+// Queries a handle for information about a specific quota.
+//
+// Parameters:
+// |handle|: The handle to query.
+// |type|: The type of quota to query.
+// |limit|: Receives the quota's currently set limit if non-null.
+// |usage|: Receives the quota's current usage if non-null.
+//
+// Returns:
+// |MOJO_RESULT_OK| if the quota was successfully queried on |handle|. Upon
+// return, |*limit| contains the quota's current limit if |limit| is
+// non-null, and |*usage| contains the quota's current usage if |usage| is
+// non-null.
+// |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle value or
+// quota |type| does not apply to the type of object referenced by
+// |handle|.
+MOJO_SYSTEM_EXPORT MojoResult
+MojoQueryQuota(MojoHandle handle,
+ MojoQuotaType type,
+ const struct MojoQueryQuotaOptions* options,
+ uint64_t* limit,
+ uint64_t* usage);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // MOJO_PUBLIC_C_SYSTEM_QUOTA_H_
diff --git a/chromium/mojo/public/c/system/thunks.cc b/chromium/mojo/public/c/system/thunks.cc
index 38fc96688dc..cffef2cc50c 100644
--- a/chromium/mojo/public/c/system/thunks.cc
+++ b/chromium/mojo/public/c/system/thunks.cc
@@ -10,11 +10,13 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/protected_memory.h"
+#include "base/memory/protected_memory_cfi.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "mojo/public/c/system/core.h"
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
+#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
#include "base/environment.h"
#include "base/files/file_path.h"
#include "base/optional.h"
@@ -24,10 +26,35 @@
namespace {
-MojoSystemThunks g_thunks = {0};
+typedef void (*MojoGetSystemThunksFunction)(MojoSystemThunks* thunks);
+
+#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
+PROTECTED_MEMORY_SECTION
+base::ProtectedMemory<MojoGetSystemThunksFunction> g_get_thunks;
+#endif
+
+PROTECTED_MEMORY_SECTION base::ProtectedMemory<MojoSystemThunks> g_thunks;
+
+MojoResult NotImplemented(const char* name) {
+ DLOG(ERROR) << "Function 'Mojo" << name
+ << "()' not supported in this version of Mojo Core.";
+ return MOJO_RESULT_UNIMPLEMENTED;
+}
} // namespace
+// Macro to verify that the thunk symbol |name| is actually present in the
+// runtime version of Mojo Core that is currently in use.
+#define FUNCTION_IS_IMPLEMENTED(name) \
+ (reinterpret_cast<uintptr_t>(static_cast<const void*>(&g_thunks->name)) - \
+ reinterpret_cast<uintptr_t>(static_cast<const void*>(&g_thunks)) < \
+ g_thunks->size)
+
+#define INVOKE_THUNK(name, ...) \
+ FUNCTION_IS_IMPLEMENTED(name) \
+ ? base::UnsanitizedCfiCall(g_thunks, &MojoSystemThunks::name)(__VA_ARGS__) \
+ : NotImplemented(#name)
+
namespace mojo {
// NOTE: This is defined within the global mojo namespace so that it can be
@@ -35,42 +62,67 @@ namespace mojo {
// enabled.
class CoreLibraryInitializer {
public:
- typedef void (*MojoGetSystemThunksFunction)(MojoSystemThunks* thunks);
-
- CoreLibraryInitializer() {
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
- auto environment = base::Environment::Create();
-
- base::FilePath library_path;
- std::string library_path_value;
- const char kLibraryPathEnvironmentVar[] = "MOJO_CORE_LIBRARY_PATH";
- if (environment->GetVar(kLibraryPathEnvironmentVar, &library_path_value)) {
- library_path = base::FilePath::FromUTF8Unsafe(library_path_value);
+ CoreLibraryInitializer(const MojoInitializeOptions* options) {
+#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
+ bool application_provided_path = false;
+ base::Optional<base::FilePath> library_path;
+ if (options && options->struct_size >= sizeof(*options) &&
+ options->mojo_core_path) {
+ base::StringPiece utf8_path(options->mojo_core_path,
+ options->mojo_core_path_length);
+ library_path.emplace(base::FilePath::FromUTF8Unsafe(utf8_path));
+ application_provided_path = true;
} else {
+ auto environment = base::Environment::Create();
+ std::string library_path_value;
+ const char kLibraryPathEnvironmentVar[] = "MOJO_CORE_LIBRARY_PATH";
+ if (environment->GetVar(kLibraryPathEnvironmentVar, &library_path_value))
+ library_path = base::FilePath::FromUTF8Unsafe(library_path_value);
+ }
+
+ if (!library_path) {
// Default to looking for the library in the current working directory.
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
const base::FilePath::CharType kDefaultLibraryPathValue[] =
FILE_PATH_LITERAL("./libmojo_core.so");
- library_path = base::FilePath(kDefaultLibraryPathValue);
+#elif defined(OS_WIN)
+ const base::FilePath::CharType kDefaultLibraryPathValue[] =
+ FILE_PATH_LITERAL("mojo_core.dll");
+#endif
+ library_path.emplace(kDefaultLibraryPathValue);
}
base::ScopedAllowBlocking allow_blocking;
- library_.emplace(library_path);
- CHECK(library_->is_valid())
- << "Unable to load the mojo_core library. Make sure the library is in "
- << "the working directory or is correctly pointed to by the "
- << "MOJO_CORE_LIBRARY_PATH environment variable.";
+ library_.emplace(*library_path);
+ if (!application_provided_path) {
+ CHECK(library_->is_valid())
+ << "Unable to load the mojo_core library. Make sure the library is "
+ << "in the working directory or is correctly pointed to by the "
+ << "MOJO_CORE_LIBRARY_PATH environment variable.";
+ } else {
+ CHECK(library_->is_valid())
+ << "Unable to locate mojo_core library. This application expects to "
+ << "find it at " << library_path->value();
+ }
const char kGetThunksFunctionName[] = "MojoGetSystemThunks";
- MojoGetSystemThunksFunction get_thunks =
- reinterpret_cast<MojoGetSystemThunksFunction>(
- library_->GetFunctionPointer(kGetThunksFunctionName));
- CHECK(get_thunks) << "Invalid mojo_core library";
-
- DCHECK_EQ(g_thunks.size, 0u);
- g_thunks.size = sizeof(g_thunks);
- get_thunks(&g_thunks);
+ {
+ auto writer = base::AutoWritableMemory::Create(g_get_thunks);
+ *g_get_thunks = reinterpret_cast<MojoGetSystemThunksFunction>(
+ library_->GetFunctionPointer(kGetThunksFunctionName));
+ }
+ CHECK(*g_get_thunks) << "Invalid mojo_core library: "
+ << library_path->value();
+
+ DCHECK_EQ(g_thunks->size, 0u);
+ {
+ auto writer = base::AutoWritableMemory::Create(g_thunks);
+ g_thunks->size = sizeof(*g_thunks);
+ base::UnsanitizedCfiCall(g_get_thunks)(&*g_thunks);
+ }
- CHECK_GT(g_thunks.size, 0u) << "Invalid mojo_core library";
+ CHECK_GT(g_thunks->size, 0u)
+ << "Invalid mojo_core library: " << library_path->value();
#else // defined(OS_CHROMEOS) || defined(OS_LINUX)
NOTREACHED()
<< "Dynamic mojo_core loading is not supported on this platform.";
@@ -80,7 +132,7 @@ class CoreLibraryInitializer {
~CoreLibraryInitializer() = default;
private:
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
+#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
base::Optional<base::ScopedNativeLibrary> library_;
#endif
@@ -92,117 +144,120 @@ class CoreLibraryInitializer {
extern "C" {
MojoResult MojoInitialize(const struct MojoInitializeOptions* options) {
- static base::NoDestructor<mojo::CoreLibraryInitializer> initializer;
+ static base::NoDestructor<mojo::CoreLibraryInitializer> initializer(options);
ALLOW_UNUSED_LOCAL(initializer);
- DCHECK(g_thunks.Initialize);
+ DCHECK(g_thunks->Initialize);
- return g_thunks.Initialize(options);
+ return INVOKE_THUNK(Initialize, options);
}
MojoTimeTicks MojoGetTimeTicksNow() {
- return g_thunks.GetTimeTicksNow();
+ return INVOKE_THUNK(GetTimeTicksNow);
}
MojoResult MojoClose(MojoHandle handle) {
- return g_thunks.Close(handle);
+ return INVOKE_THUNK(Close, handle);
}
MojoResult MojoQueryHandleSignalsState(
MojoHandle handle,
struct MojoHandleSignalsState* signals_state) {
- return g_thunks.QueryHandleSignalsState(handle, signals_state);
+ return INVOKE_THUNK(QueryHandleSignalsState, handle, signals_state);
}
MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options,
MojoHandle* message_pipe_handle0,
MojoHandle* message_pipe_handle1) {
- return g_thunks.CreateMessagePipe(options, message_pipe_handle0,
- message_pipe_handle1);
+ return INVOKE_THUNK(CreateMessagePipe, options, message_pipe_handle0,
+ message_pipe_handle1);
}
MojoResult MojoWriteMessage(MojoHandle message_pipe_handle,
MojoMessageHandle message_handle,
const MojoWriteMessageOptions* options) {
- return g_thunks.WriteMessage(message_pipe_handle, message_handle, options);
+ return INVOKE_THUNK(WriteMessage, message_pipe_handle, message_handle,
+ options);
}
MojoResult MojoReadMessage(MojoHandle message_pipe_handle,
const MojoReadMessageOptions* options,
MojoMessageHandle* message_handle) {
- return g_thunks.ReadMessage(message_pipe_handle, options, message_handle);
+ return INVOKE_THUNK(ReadMessage, message_pipe_handle, options,
+ message_handle);
}
MojoResult MojoFuseMessagePipes(MojoHandle handle0,
MojoHandle handle1,
const MojoFuseMessagePipesOptions* options) {
- return g_thunks.FuseMessagePipes(handle0, handle1, options);
+ return INVOKE_THUNK(FuseMessagePipes, handle0, handle1, options);
}
MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options,
MojoHandle* data_pipe_producer_handle,
MojoHandle* data_pipe_consumer_handle) {
- return g_thunks.CreateDataPipe(options, data_pipe_producer_handle,
- data_pipe_consumer_handle);
+ return INVOKE_THUNK(CreateDataPipe, options, data_pipe_producer_handle,
+ data_pipe_consumer_handle);
}
MojoResult MojoWriteData(MojoHandle data_pipe_producer_handle,
const void* elements,
uint32_t* num_elements,
const MojoWriteDataOptions* options) {
- return g_thunks.WriteData(data_pipe_producer_handle, elements, num_elements,
- options);
+ return INVOKE_THUNK(WriteData, data_pipe_producer_handle, elements,
+ num_elements, options);
}
MojoResult MojoBeginWriteData(MojoHandle data_pipe_producer_handle,
const MojoBeginWriteDataOptions* options,
void** buffer,
uint32_t* buffer_num_elements) {
- return g_thunks.BeginWriteData(data_pipe_producer_handle, options, buffer,
- buffer_num_elements);
+ return INVOKE_THUNK(BeginWriteData, data_pipe_producer_handle, options,
+ buffer, buffer_num_elements);
}
MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle,
uint32_t num_elements_written,
const MojoEndWriteDataOptions* options) {
- return g_thunks.EndWriteData(data_pipe_producer_handle, num_elements_written,
- options);
+ return INVOKE_THUNK(EndWriteData, data_pipe_producer_handle,
+ num_elements_written, options);
}
MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle,
const MojoReadDataOptions* options,
void* elements,
uint32_t* num_elements) {
- return g_thunks.ReadData(data_pipe_consumer_handle, options, elements,
- num_elements);
+ return INVOKE_THUNK(ReadData, data_pipe_consumer_handle, options, elements,
+ num_elements);
}
MojoResult MojoBeginReadData(MojoHandle data_pipe_consumer_handle,
const MojoBeginReadDataOptions* options,
const void** buffer,
uint32_t* buffer_num_elements) {
- return g_thunks.BeginReadData(data_pipe_consumer_handle, options, buffer,
- buffer_num_elements);
+ return INVOKE_THUNK(BeginReadData, data_pipe_consumer_handle, options, buffer,
+ buffer_num_elements);
}
MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle,
uint32_t num_elements_read,
const MojoEndReadDataOptions* options) {
- return g_thunks.EndReadData(data_pipe_consumer_handle, num_elements_read,
- options);
+ return INVOKE_THUNK(EndReadData, data_pipe_consumer_handle, num_elements_read,
+ options);
}
MojoResult MojoCreateSharedBuffer(uint64_t num_bytes,
const MojoCreateSharedBufferOptions* options,
MojoHandle* shared_buffer_handle) {
- return g_thunks.CreateSharedBuffer(num_bytes, options, shared_buffer_handle);
+ return INVOKE_THUNK(CreateSharedBuffer, num_bytes, options,
+ shared_buffer_handle);
}
MojoResult MojoDuplicateBufferHandle(
MojoHandle buffer_handle,
const MojoDuplicateBufferHandleOptions* options,
MojoHandle* new_buffer_handle) {
- return g_thunks.DuplicateBufferHandle(buffer_handle, options,
- new_buffer_handle);
+ return INVOKE_THUNK(DuplicateBufferHandle, buffer_handle, options,
+ new_buffer_handle);
}
MojoResult MojoMapBuffer(MojoHandle buffer_handle,
@@ -210,23 +265,24 @@ MojoResult MojoMapBuffer(MojoHandle buffer_handle,
uint64_t num_bytes,
const MojoMapBufferOptions* options,
void** buffer) {
- return g_thunks.MapBuffer(buffer_handle, offset, num_bytes, options, buffer);
+ return INVOKE_THUNK(MapBuffer, buffer_handle, offset, num_bytes, options,
+ buffer);
}
MojoResult MojoUnmapBuffer(void* buffer) {
- return g_thunks.UnmapBuffer(buffer);
+ return INVOKE_THUNK(UnmapBuffer, buffer);
}
MojoResult MojoGetBufferInfo(MojoHandle buffer_handle,
const MojoGetBufferInfoOptions* options,
MojoSharedBufferInfo* info) {
- return g_thunks.GetBufferInfo(buffer_handle, options, info);
+ return INVOKE_THUNK(GetBufferInfo, buffer_handle, options, info);
}
MojoResult MojoCreateTrap(MojoTrapEventHandler handler,
const MojoCreateTrapOptions* options,
MojoHandle* trap_handle) {
- return g_thunks.CreateTrap(handler, options, trap_handle);
+ return INVOKE_THUNK(CreateTrap, handler, options, trap_handle);
}
MojoResult MojoAddTrigger(MojoHandle trap_handle,
@@ -235,38 +291,36 @@ MojoResult MojoAddTrigger(MojoHandle trap_handle,
MojoTriggerCondition condition,
uintptr_t context,
const MojoAddTriggerOptions* options) {
- return g_thunks.AddTrigger(trap_handle, handle, signals, condition, context,
- options);
+ return INVOKE_THUNK(AddTrigger, trap_handle, handle, signals, condition,
+ context, options);
}
MojoResult MojoRemoveTrigger(MojoHandle trap_handle,
uintptr_t context,
const MojoRemoveTriggerOptions* options) {
- return g_thunks.RemoveTrigger(trap_handle, context, options);
+ return INVOKE_THUNK(RemoveTrigger, trap_handle, context, options);
}
MojoResult MojoArmTrap(MojoHandle trap_handle,
const MojoArmTrapOptions* options,
- uint32_t* num_ready_triggers,
- uintptr_t* ready_triggers,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states) {
- return g_thunks.ArmTrap(trap_handle, options, num_ready_triggers,
- ready_triggers, ready_results, ready_signals_states);
+ uint32_t* num_blocking_events,
+ MojoTrapEvent* blocking_events) {
+ return INVOKE_THUNK(ArmTrap, trap_handle, options, num_blocking_events,
+ blocking_events);
}
MojoResult MojoCreateMessage(const MojoCreateMessageOptions* options,
MojoMessageHandle* message) {
- return g_thunks.CreateMessage(options, message);
+ return INVOKE_THUNK(CreateMessage, options, message);
}
MojoResult MojoDestroyMessage(MojoMessageHandle message) {
- return g_thunks.DestroyMessage(message);
+ return INVOKE_THUNK(DestroyMessage, message);
}
MojoResult MojoSerializeMessage(MojoMessageHandle message,
const MojoSerializeMessageOptions* options) {
- return g_thunks.SerializeMessage(message, options);
+ return INVOKE_THUNK(SerializeMessage, message, options);
}
MojoResult MojoAppendMessageData(MojoMessageHandle message,
@@ -276,8 +330,8 @@ MojoResult MojoAppendMessageData(MojoMessageHandle message,
const MojoAppendMessageDataOptions* options,
void** buffer,
uint32_t* buffer_size) {
- return g_thunks.AppendMessageData(message, payload_size, handles, num_handles,
- options, buffer, buffer_size);
+ return INVOKE_THUNK(AppendMessageData, message, payload_size, handles,
+ num_handles, options, buffer, buffer_size);
}
MojoResult MojoGetMessageData(MojoMessageHandle message,
@@ -286,8 +340,8 @@ MojoResult MojoGetMessageData(MojoMessageHandle message,
uint32_t* num_bytes,
MojoHandle* handles,
uint32_t* num_handles) {
- return g_thunks.GetMessageData(message, options, buffer, num_bytes, handles,
- num_handles);
+ return INVOKE_THUNK(GetMessageData, message, options, buffer, num_bytes,
+ handles, num_handles);
}
MojoResult MojoSetMessageContext(MojoMessageHandle message,
@@ -295,34 +349,37 @@ MojoResult MojoSetMessageContext(MojoMessageHandle message,
MojoMessageContextSerializer serializer,
MojoMessageContextDestructor destructor,
const MojoSetMessageContextOptions* options) {
- return g_thunks.SetMessageContext(message, context, serializer, destructor,
- options);
+ return INVOKE_THUNK(SetMessageContext, message, context, serializer,
+ destructor, options);
}
MojoResult MojoGetMessageContext(MojoMessageHandle message,
const MojoGetMessageContextOptions* options,
uintptr_t* context) {
- return g_thunks.GetMessageContext(message, options, context);
+ return INVOKE_THUNK(GetMessageContext, message, options, context);
}
MojoResult MojoNotifyBadMessage(MojoMessageHandle message,
const char* error,
uint32_t error_num_bytes,
const MojoNotifyBadMessageOptions* options) {
- return g_thunks.NotifyBadMessage(message, error, error_num_bytes, options);
+ return INVOKE_THUNK(NotifyBadMessage, message, error, error_num_bytes,
+ options);
}
MojoResult MojoWrapPlatformHandle(const MojoPlatformHandle* platform_handle,
const MojoWrapPlatformHandleOptions* options,
MojoHandle* mojo_handle) {
- return g_thunks.WrapPlatformHandle(platform_handle, options, mojo_handle);
+ return INVOKE_THUNK(WrapPlatformHandle, platform_handle, options,
+ mojo_handle);
}
MojoResult MojoUnwrapPlatformHandle(
MojoHandle mojo_handle,
const MojoUnwrapPlatformHandleOptions* options,
MojoPlatformHandle* platform_handle) {
- return g_thunks.UnwrapPlatformHandle(mojo_handle, options, platform_handle);
+ return INVOKE_THUNK(UnwrapPlatformHandle, mojo_handle, options,
+ platform_handle);
}
MojoResult MojoWrapPlatformSharedMemoryRegion(
@@ -333,9 +390,9 @@ MojoResult MojoWrapPlatformSharedMemoryRegion(
MojoPlatformSharedMemoryRegionAccessMode access_mode,
const MojoWrapPlatformSharedMemoryRegionOptions* options,
MojoHandle* mojo_handle) {
- return g_thunks.WrapPlatformSharedMemoryRegion(
- platform_handles, num_platform_handles, num_bytes, guid, access_mode,
- options, mojo_handle);
+ return INVOKE_THUNK(WrapPlatformSharedMemoryRegion, platform_handles,
+ num_platform_handles, num_bytes, guid, access_mode,
+ options, mojo_handle);
}
MojoResult MojoUnwrapPlatformSharedMemoryRegion(
@@ -346,14 +403,14 @@ MojoResult MojoUnwrapPlatformSharedMemoryRegion(
uint64_t* num_bytes,
struct MojoSharedBufferGuid* guid,
MojoPlatformSharedMemoryRegionAccessMode* access_mode) {
- return g_thunks.UnwrapPlatformSharedMemoryRegion(
- mojo_handle, options, platform_handles, num_platform_handles, num_bytes,
- guid, access_mode);
+ return INVOKE_THUNK(UnwrapPlatformSharedMemoryRegion, mojo_handle, options,
+ platform_handles, num_platform_handles, num_bytes, guid,
+ access_mode);
}
MojoResult MojoCreateInvitation(const MojoCreateInvitationOptions* options,
MojoHandle* invitation_handle) {
- return g_thunks.CreateInvitation(options, invitation_handle);
+ return INVOKE_THUNK(CreateInvitation, options, invitation_handle);
}
MojoResult MojoAttachMessagePipeToInvitation(
@@ -362,8 +419,8 @@ MojoResult MojoAttachMessagePipeToInvitation(
uint32_t name_num_bytes,
const MojoAttachMessagePipeToInvitationOptions* options,
MojoHandle* message_pipe_handle) {
- return g_thunks.AttachMessagePipeToInvitation(
- invitation_handle, name, name_num_bytes, options, message_pipe_handle);
+ return INVOKE_THUNK(AttachMessagePipeToInvitation, invitation_handle, name,
+ name_num_bytes, options, message_pipe_handle);
}
MojoResult MojoExtractMessagePipeFromInvitation(
@@ -372,8 +429,8 @@ MojoResult MojoExtractMessagePipeFromInvitation(
uint32_t name_num_bytes,
const MojoExtractMessagePipeFromInvitationOptions* options,
MojoHandle* message_pipe_handle) {
- return g_thunks.ExtractMessagePipeFromInvitation(
- invitation_handle, name, name_num_bytes, options, message_pipe_handle);
+ return INVOKE_THUNK(ExtractMessagePipeFromInvitation, invitation_handle, name,
+ name_num_bytes, options, message_pipe_handle);
}
MojoResult MojoSendInvitation(
@@ -383,31 +440,47 @@ MojoResult MojoSendInvitation(
MojoProcessErrorHandler error_handler,
uintptr_t error_handler_context,
const MojoSendInvitationOptions* options) {
- return g_thunks.SendInvitation(invitation_handle, process_handle,
- transport_endpoint, error_handler,
- error_handler_context, options);
+ return INVOKE_THUNK(SendInvitation, invitation_handle, process_handle,
+ transport_endpoint, error_handler, error_handler_context,
+ options);
}
MojoResult MojoAcceptInvitation(
const MojoInvitationTransportEndpoint* transport_endpoint,
const MojoAcceptInvitationOptions* options,
MojoHandle* invitation_handle) {
- return g_thunks.AcceptInvitation(transport_endpoint, options,
- invitation_handle);
+ return INVOKE_THUNK(AcceptInvitation, transport_endpoint, options,
+ invitation_handle);
+}
+
+MojoResult MojoSetQuota(MojoHandle handle,
+ MojoQuotaType type,
+ uint64_t limit,
+ const MojoSetQuotaOptions* options) {
+ return INVOKE_THUNK(SetQuota, handle, type, limit, options);
+}
+
+MojoResult MojoQueryQuota(MojoHandle handle,
+ MojoQuotaType type,
+ const MojoQueryQuotaOptions* options,
+ uint64_t* limit,
+ uint64_t* usage) {
+ return INVOKE_THUNK(QueryQuota, handle, type, options, limit, usage);
}
} // extern "C"
void MojoEmbedderSetSystemThunks(const MojoSystemThunks* thunks) {
- // Assume embedders will always use matching versions of the EDK and public
- // APIs.
- DCHECK_EQ(thunks->size, sizeof(g_thunks));
-
- // This should only have to check that the |g_thunks.size| is zero, but we
- // have multiple EDK initializations in some test suites still. For now we
- // allow double calls as long as they're the same thunks as before.
- DCHECK(g_thunks.size == 0 || !memcmp(&g_thunks, thunks, sizeof(g_thunks)))
+ // Assume embedders will always use matching versions of the Mojo Core and
+ // public APIs.
+ DCHECK_EQ(thunks->size, sizeof(*g_thunks));
+
+ // This should only have to check that the |g_thunks->size| is zero, but we
+ // have multiple Mojo Core initializations in some test suites still. For now
+ // we allow double calls as long as they're the same thunks as before.
+ DCHECK(g_thunks->size == 0 || !memcmp(&*g_thunks, thunks, sizeof(*g_thunks)))
<< "Cannot set embedder thunks after Mojo API calls have been made.";
- g_thunks = *thunks;
+ auto writer = base::AutoWritableMemory::Create(g_thunks);
+ *g_thunks = *thunks;
}
diff --git a/chromium/mojo/public/c/system/thunks.h b/chromium/mojo/public/c/system/thunks.h
index b1cc6b15702..1e5e2493c7e 100644
--- a/chromium/mojo/public/c/system/thunks.h
+++ b/chromium/mojo/public/c/system/thunks.h
@@ -156,10 +156,8 @@ struct MojoSystemThunks {
const struct MojoRemoveTriggerOptions* options);
MojoResult (*ArmTrap)(MojoHandle trap_handle,
const struct MojoArmTrapOptions* options,
- uint32_t* num_ready_triggers,
- uintptr_t* ready_triggers,
- MojoResult* ready_results,
- MojoHandleSignalsState* ready_signals_states);
+ uint32_t* num_blocking_events,
+ struct MojoTrapEvent* blocking_events);
// Platform handle API.
MojoResult (*WrapPlatformHandle)(
@@ -214,6 +212,15 @@ struct MojoSystemThunks {
const struct MojoInvitationTransportEndpoint* transport_endpoint,
const struct MojoAcceptInvitationOptions* options,
MojoHandle* invitation_handle);
+ MojoResult (*SetQuota)(MojoHandle handle,
+ MojoQuotaType type,
+ uint64_t limit,
+ const struct MojoSetQuotaOptions* options);
+ MojoResult (*QueryQuota)(MojoHandle handle,
+ MojoQuotaType type,
+ const struct MojoQueryQuotaOptions* options,
+ uint64_t* limit,
+ uint64_t* usage);
};
#pragma pack(pop)
diff --git a/chromium/mojo/public/c/system/trap.h b/chromium/mojo/public/c/system/trap.h
index 7c65af31fa2..c5e718ec131 100644
--- a/chromium/mojo/public/c/system/trap.h
+++ b/chromium/mojo/public/c/system/trap.h
@@ -40,7 +40,7 @@ struct MOJO_ALIGNAS(8) MojoTrapEvent {
MojoTrapEventFlags flags;
// The context for the trigger which tripped the trap.
- uintptr_t trigger_context;
+ MOJO_POINTER_FIELD(uintptr_t, trigger_context);
// A result code indicating the cause of the event. May take on any of the
// following values:
@@ -63,6 +63,8 @@ struct MOJO_ALIGNAS(8) MojoTrapEvent {
// time the trap was tripped.
struct MojoHandleSignalsState signals_state;
};
+MOJO_STATIC_ASSERT(sizeof(MojoTrapEvent) == 32,
+ "MojoTrapEvent has wrong size.");
// Value given to |MojoAddTrigger| to configure what condition should cause it
// to trip its trap. May be one of the following values:
@@ -101,6 +103,8 @@ struct MOJO_ALIGNAS(8) MojoCreateTrapOptions {
// Flags. Currently unused.
MojoCreateTrapFlags flags;
};
+MOJO_STATIC_ASSERT(sizeof(MojoCreateTrapOptions) == 8,
+ "MojoCreateTrapOptions has wrong size.");
// Flags passed to |MojoAddTrigger()| via |MojoAddTriggerOptions|.
typedef uint32_t MojoAddTriggerFlags;
@@ -119,6 +123,8 @@ struct MOJO_ALIGNAS(8) MojoAddTriggerOptions {
// Flags. Currently unused.
MojoAddTriggerFlags flags;
};
+MOJO_STATIC_ASSERT(sizeof(MojoAddTriggerOptions) == 8,
+ "MojoAddTriggerOptions has wrong size.");
// Flags passed to |MojoRemoveTrigger()| via |MojoRemoveTriggerOptions|.
typedef uint32_t MojoRemoveTriggerFlags;
@@ -137,6 +143,8 @@ struct MOJO_ALIGNAS(8) MojoRemoveTriggerOptions {
// Flags. Currently unused.
MojoRemoveTriggerFlags flags;
};
+MOJO_STATIC_ASSERT(sizeof(MojoRemoveTriggerOptions) == 8,
+ "MojoRemoveTriggerOptions has wrong size.");
// Flags passed to |MojoArmTrap()| via |MojoArmTrapOptions|.
typedef uint32_t MojoArmTrapFlags;
@@ -155,6 +163,8 @@ struct MOJO_ALIGNAS(8) MojoArmTrapOptions {
// Flags. Currently unused.
MojoArmTrapFlags flags;
};
+MOJO_STATIC_ASSERT(sizeof(MojoArmTrapOptions) == 8,
+ "MojoArmTrapOptions has wrong size.");
#ifdef __cplusplus
extern "C" {
@@ -267,51 +277,43 @@ MojoRemoveTrigger(MojoHandle trap_handle,
//
// Parameters:
// |trap_handle|: The handle of the trap to be armed.
-// |num_ready_triggers|: An address pointing to the number of elements
-// available for storage in the following output buffer parameters.
+// |num_blocking_events|: An address pointing to the number of elements
+// available for storage at the address given by |blocking_events|.
// Optional and only used when |MOJO_RESULT_FAILED_PRECONDITION| is
// returned. See below.
-// |ready_triggers|: An output buffer for contexts of triggers that would have
-// tripped the trap immediately if it were armed. Optional and used only
-// when |MOJO_RESULT_FAILED_PRECONDITION| is returned. See below.
-// |ready_results|: An output buffer for |MojoResult| values corresponding to
-// each trigger in |ready_triggers|. Optional and only used when
-// |MOJO_RESULT_FAILED_PRECONDITION| is returned. See below.
-// |ready_signals_states|: An output buffer for |MojoHandleSignalsState|
-// structures corresponding to the handle observed by each respective
-// trigger in |ready_triggers|. Optional and only used when
+// |blocking_events|: An output buffer for |MojoTrapEvent| structures to be
+// filled in if one or more triggers would have tripped the trap
+// immediately if it were armed. Optional and used only when
// |MOJO_RESULT_FAILED_PRECONDITION| is returned. See below.
//
// Returns:
-// |MOJO_RESULT_OK| if the trap has been successfully armed. All arguments
-// other than |trap_handle| are ignored in this case.
-// |MOJO_RESULT_NOT_FOUND| if the trap does not have any triggers. All
-// arguments other than |trap_handle| are ignored.
+// |MOJO_RESULT_OK| if the trap has been successfully armed.
+// |num_blocking_events| and |blocking_events| are ignored.
+// |MOJO_RESULT_NOT_FOUND| if the trap does not have any triggers.
+// |num_blocking_events| and |blocking_events| are ignored.
// |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a valid trap handle,
-// or if |num_ready_triggers| is non-null and any of the output buffer
-// paramters is null.
+// or if |num_blocking_events| is non-null but |blocking_events| is
+// not.
// |MOJO_RESULT_FAILED_PRECONDITION| if one or more triggers would have
-// tripped the trap immediately upon arming. If |num_handles| is non-null,
-// this assumes there is enough space for |*num_handles| entries in each
-// of the subsequent output buffer parameters.
+// tripped the trap immediately upon arming. If |num_blocking_events| is
+// non-null, this assumes there is enough space for |*num_blocking_events|
+// entries at the non-null address in |blocking_events|.
//
-// At most |*num_handles| entries are populated in the output buffers,
-// with each entry corresponding to one of the triggers which would have
-// tripped the trap. The actual number of entries populated is written to
-// |*num_handles| before returning.
+// At most |*num_blocking_events| entries are populated there, with each
+// entry corresponding to one of the triggers which would have tripped the
+// trap. The actual number of entries populated is written to
+// |*num_blocking_events| before returning.
//
// If there are more ready triggers than available provided storage, the
-// subset presented to thecaller is arbitrary. The runtime makes an effort
-// to circulate triggers returned by consecutive failed |MojoArmTrap()|
-// calls so that callers may avoid handle starvation when observing a
-// large number of active handles with a single trap.
+// subset presented to the caller is arbitrary. The runtime makes an
+// effort to circulate triggers returned by consecutive failed
+// |MojoArmTrap()| calls so that callers may avoid handle starvation when
+// observing a large number of active handles with a single trap.
MOJO_SYSTEM_EXPORT MojoResult
MojoArmTrap(MojoHandle trap_handle,
const struct MojoArmTrapOptions* options,
- uint32_t* num_ready_triggers,
- uintptr_t* ready_triggers,
- MojoResult* ready_results,
- struct MojoHandleSignalsState* ready_signals_states);
+ uint32_t* num_blocking_events,
+ struct MojoTrapEvent* blocking_events);
#ifdef __cplusplus
} // extern "C"
diff --git a/chromium/mojo/public/c/system/types.h b/chromium/mojo/public/c/system/types.h
index 79562634e82..4cf566a5699 100644
--- a/chromium/mojo/public/c/system/types.h
+++ b/chromium/mojo/public/c/system/types.h
@@ -149,7 +149,16 @@ struct MOJO_ALIGNAS(8) MojoInitializeOptions {
// See |MojoInitializeFlags|.
MojoInitializeFlags flags;
+
+ // Address and length of the UTF8-encoded path of a mojo_core shared library
+ // to load. If the |mojo_core_path| is null then |mojo_core_path_length| is
+ // ignored and Mojo will fall back first onto the |MOJO_CORE_LIBRARY_PATH|
+ // environment variable, and then onto the current working directory.
+ MOJO_POINTER_FIELD(const char*, mojo_core_path);
+ uint32_t mojo_core_path_length;
};
+MOJO_STATIC_ASSERT(sizeof(MojoInitializeOptions) == 24,
+ "MojoInitializeOptions has wrong size");
// |MojoHandleSignals|: Used to specify signals that can be watched for on a
// handle (and which can be triggered), e.g., the ability to read or write to
@@ -168,6 +177,8 @@ struct MOJO_ALIGNAS(8) MojoInitializeOptions {
// execution context (e.g. in another process.) Note that this signal is
// maintained with best effort but may at any time be slightly out of sync
// with the actual location of the peer handle.
+// |MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED| - One or more quotas set on the handle
+// is currently exceeded.
typedef uint32_t MojoHandleSignals;
@@ -178,6 +189,7 @@ const MojoHandleSignals MOJO_HANDLE_SIGNAL_WRITABLE = 1 << 1;
const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_CLOSED = 1 << 2;
const MojoHandleSignals MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE = 1 << 3;
const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_REMOTE = 1 << 4;
+const MojoHandleSignals MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED = 1 << 5;
#else
#define MOJO_HANDLE_SIGNAL_NONE ((MojoHandleSignals)0)
#define MOJO_HANDLE_SIGNAL_READABLE ((MojoHandleSignals)1 << 0)
@@ -185,6 +197,7 @@ const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_REMOTE = 1 << 4;
#define MOJO_HANDLE_SIGNAL_PEER_CLOSED ((MojoHandleSignals)1 << 2)
#define MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE ((MojoHandleSignals)1 << 3);
#define MOJO_HANDLE_SIGNAL_PEER_REMOTE ((MojoHandleSignals)1 << 4);
+#define MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED ((MojoHandleSignals)1 << 5);
#endif
// |MojoHandleSignalsState|: Returned by watch notification callbacks and
diff --git a/chromium/mojo/public/cpp/base/BUILD.gn b/chromium/mojo/public/cpp/base/BUILD.gn
index e97ccdab2a4..c57ac0bf1d9 100644
--- a/chromium/mojo/public/cpp/base/BUILD.gn
+++ b/chromium/mojo/public/cpp/base/BUILD.gn
@@ -30,10 +30,14 @@ component("shared_typemap_traits") {
sources = [
"big_buffer_mojom_traits.cc",
"big_buffer_mojom_traits.h",
+ "file_info_mojom_traits.cc",
+ "file_info_mojom_traits.h",
"file_path_mojom_traits.cc",
"file_path_mojom_traits.h",
"shared_memory_mojom_traits.cc",
"shared_memory_mojom_traits.h",
+ "time_mojom_traits.cc",
+ "time_mojom_traits.h",
"values_mojom_traits.cc",
"values_mojom_traits.h",
]
diff --git a/chromium/mojo/public/cpp/base/file_info.typemap b/chromium/mojo/public/cpp/base/file_info.typemap
index f6ef16a586c..4faac8f1c4c 100644
--- a/chromium/mojo/public/cpp/base/file_info.typemap
+++ b/chromium/mojo/public/cpp/base/file_info.typemap
@@ -4,9 +4,10 @@
mojom = "//mojo/public/mojom/base/file_info.mojom"
public_headers = [ "//base/files/file.h" ]
-traits_headers = [ "//ipc/ipc_message_utils.h" ]
+traits_headers = [ "//mojo/public/cpp/base/file_info_mojom_traits.h" ]
public_deps = [
- "//ipc",
+ "//base",
+ "//mojo/public/cpp/base:shared_typemap_traits",
]
type_mappings = [ "mojo_base.mojom.FileInfo=base::File::Info" ]
diff --git a/chromium/mojo/public/cpp/base/file_info_mojom_traits.cc b/chromium/mojo/public/cpp/base/file_info_mojom_traits.cc
new file mode 100644
index 00000000000..64a08029573
--- /dev/null
+++ b/chromium/mojo/public/cpp/base/file_info_mojom_traits.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium 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/base/file_info_mojom_traits.h"
+
+#include "base/logging.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<mojo_base::mojom::FileInfoDataView, base::File::Info>::Read(
+ mojo_base::mojom::FileInfoDataView data,
+ base::File::Info* out) {
+ if (!data.ReadLastModified(&out->last_modified))
+ return false;
+ if (!data.ReadLastAccessed(&out->last_accessed))
+ return false;
+ if (!data.ReadCreationTime(&out->creation_time))
+ return false;
+ out->size = data.size();
+ out->is_directory = data.is_directory();
+ out->is_symbolic_link = data.is_symbolic_link();
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/base/file_info_mojom_traits.h b/chromium/mojo/public/cpp/base/file_info_mojom_traits.h
new file mode 100644
index 00000000000..4049e038d72
--- /dev/null
+++ b/chromium/mojo/public/cpp/base/file_info_mojom_traits.h
@@ -0,0 +1,49 @@
+// Copyright 2018 The Chromium 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_BASE_FILE_INFO_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_FILE_INFO_MOJOM_TRAITS_H_
+
+#include <cstdint>
+
+#include "base/component_export.h"
+#include "base/files/file.h"
+#include "base/macros.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "mojo/public/mojom/base/file_info.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS)
+ StructTraits<mojo_base::mojom::FileInfoDataView, base::File::Info> {
+ static int64_t size(const base::File::Info& info) { return info.size; }
+
+ static bool is_directory(const base::File::Info& info) {
+ return info.is_directory;
+ }
+
+ static bool is_symbolic_link(const base::File::Info& info) {
+ return info.is_symbolic_link;
+ }
+
+ static base::Time last_modified(const base::File::Info& info) {
+ return info.last_modified;
+ }
+
+ static base::Time last_accessed(const base::File::Info& info) {
+ return info.last_accessed;
+ }
+
+ static base::Time creation_time(const base::File::Info& info) {
+ return info.creation_time;
+ }
+
+ static bool Read(mojo_base::mojom::FileInfoDataView data,
+ base::File::Info* out);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BASE_FILE_INFO_MOJOM_TRAITS_H_
diff --git a/chromium/mojo/public/cpp/base/file_mojom_traits.cc b/chromium/mojo/public/cpp/base/file_mojom_traits.cc
index e7fd60590ea..5799b79dd12 100644
--- a/chromium/mojo/public/cpp/base/file_mojom_traits.cc
+++ b/chromium/mojo/public/cpp/base/file_mojom_traits.cc
@@ -23,7 +23,7 @@ bool StructTraits<mojo_base::mojom::FileDataView, base::File>::Read(
MOJO_RESULT_OK) {
return false;
}
- *file = base::File(platform_handle);
+ *file = base::File(platform_handle, data.async());
return true;
}
diff --git a/chromium/mojo/public/cpp/base/file_mojom_traits.h b/chromium/mojo/public/cpp/base/file_mojom_traits.h
index ac2d0d294a9..e4dd2f98759 100644
--- a/chromium/mojo/public/cpp/base/file_mojom_traits.h
+++ b/chromium/mojo/public/cpp/base/file_mojom_traits.h
@@ -19,6 +19,7 @@ struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
static void SetToNull(base::File* file) { *file = base::File(); }
static mojo::ScopedHandle fd(base::File& file);
+ static bool async(base::File& file) { return file.async(); }
static bool Read(mojo_base::mojom::FileDataView data, base::File* file);
};
diff --git a/chromium/mojo/public/cpp/base/file_unittest.cc b/chromium/mojo/public/cpp/base/file_unittest.cc
index fb3cff405e1..e1db729c752 100644
--- a/chromium/mojo/public/cpp/base/file_unittest.cc
+++ b/chromium/mojo/public/cpp/base/file_unittest.cc
@@ -28,6 +28,7 @@ TEST(FileTest, File) {
mojo::test::SerializeAndDeserialize<mojom::File>(&file, &file_out));
std::vector<char> content(test_content.size());
ASSERT_TRUE(file_out.IsValid());
+ ASSERT_FALSE(file_out.async());
ASSERT_EQ(static_cast<int>(test_content.size()),
file_out.Read(0, content.data(),
base::checked_cast<int>(test_content.size())));
@@ -35,6 +36,25 @@ TEST(FileTest, File) {
base::StringPiece(content.data(), test_content.size()));
}
+TEST(FileTest, AsyncFile) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath path = temp_dir.GetPath().AppendASCII("async_test_file.txt");
+
+ base::File write_file(path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+ const base::StringPiece test_content = "test string";
+ write_file.WriteAtCurrentPos(test_content.data(),
+ base::checked_cast<int>(test_content.size()));
+ write_file.Close();
+
+ base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ |
+ base::File::FLAG_ASYNC);
+ base::File file_out;
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::File>(&file, &file_out));
+ ASSERT_TRUE(file_out.async());
+}
+
TEST(FileTest, InvalidFile) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/chromium/mojo/public/cpp/base/logfont_win.typemap b/chromium/mojo/public/cpp/base/logfont_win.typemap
index 43cdc1e2c1d..daaf6fcca6f 100644
--- a/chromium/mojo/public/cpp/base/logfont_win.typemap
+++ b/chromium/mojo/public/cpp/base/logfont_win.typemap
@@ -3,10 +3,16 @@
# found in the LICENSE file.
mojom = "//mojo/public/mojom/base/logfont_win.mojom"
-os_whitelist = [ "win" ]
-public_headers = [ "//base/win/windows_full.h" ]
-traits_headers = [ "//ipc/ipc_message_utils.h" ]
+public_headers = [
+ "//base/win/windows_full.h",
+ "//base/win/windows_types.h",
+]
+traits_headers = [ "//mojo/public/cpp/base/logfont_win_mojom_traits.h" ]
public_deps = [
- "//ipc",
+ "//base",
+]
+sources = [
+ "//mojo/public/cpp/base/logfont_win_mojom_traits.cc",
+ "//mojo/public/cpp/base/logfont_win_mojom_traits.h",
]
type_mappings = [ "mojo_base.mojom.LOGFONT=::LOGFONT" ]
diff --git a/chromium/mojo/public/cpp/base/logfont_win_mojom_traits.cc b/chromium/mojo/public/cpp/base/logfont_win_mojom_traits.cc
new file mode 100644
index 00000000000..3c73701ce99
--- /dev/null
+++ b/chromium/mojo/public/cpp/base/logfont_win_mojom_traits.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium 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/base/logfont_win_mojom_traits.h"
+
+#include <tchar.h>
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+
+namespace mojo {
+
+// static
+base::span<const uint8_t>
+StructTraits<mojo_base::mojom::LOGFONTDataView, ::LOGFONT>::bytes(
+ const ::LOGFONT& input) {
+ return base::make_span(reinterpret_cast<const uint8_t*>(&input),
+ sizeof(::LOGFONT));
+}
+
+// static
+bool StructTraits<mojo_base::mojom::LOGFONTDataView, ::LOGFONT>::Read(
+ mojo_base::mojom::LOGFONTDataView data,
+ ::LOGFONT* out) {
+ ArrayDataView<uint8_t> bytes_view;
+ data.GetBytesDataView(&bytes_view);
+ if (bytes_view.size() != sizeof(::LOGFONT))
+ return false;
+
+ const ::LOGFONT* font = reinterpret_cast<const ::LOGFONT*>(bytes_view.data());
+ if (_tcsnlen(font->lfFaceName, LF_FACESIZE) >= LF_FACESIZE)
+ return false;
+
+ memcpy(out, font, sizeof(::LOGFONT));
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/base/logfont_win_mojom_traits.h b/chromium/mojo/public/cpp/base/logfont_win_mojom_traits.h
new file mode 100644
index 00000000000..09a9fbbeeec
--- /dev/null
+++ b/chromium/mojo/public/cpp/base/logfont_win_mojom_traits.h
@@ -0,0 +1,30 @@
+// Copyright 2018 The Chromium 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_BASE_LOGFONT_WIN_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_LOGFONT_WIN_MOJOM_TRAITS_H_
+
+#include <windows.h>
+
+#include <cstdint>
+
+#include "base/component_export.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/win/windows_types.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "mojo/public/mojom/base/logfont_win.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+ StructTraits<mojo_base::mojom::LOGFONTDataView, ::LOGFONT> {
+ static base::span<const uint8_t> bytes(const ::LOGFONT& input);
+ static bool Read(mojo_base::mojom::LOGFONTDataView data, ::LOGFONT* out);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BASE_LOGFONT_WIN_MOJOM_TRAITS_H_
diff --git a/chromium/mojo/public/cpp/base/time.typemap b/chromium/mojo/public/cpp/base/time.typemap
index b3b2e8b0658..ecd6a27fc7b 100644
--- a/chromium/mojo/public/cpp/base/time.typemap
+++ b/chromium/mojo/public/cpp/base/time.typemap
@@ -5,12 +5,9 @@
mojom = "//mojo/public/mojom/base/time.mojom"
public_headers = [ "//base/time/time.h" ]
traits_headers = [ "//mojo/public/cpp/base/time_mojom_traits.h" ]
-sources = [
- "//mojo/public/cpp/base/time_mojom_traits.cc",
- "//mojo/public/cpp/base/time_mojom_traits.h",
-]
public_deps = [
"//base",
+ "//mojo/public/cpp/base:shared_typemap_traits",
]
type_mappings = [
diff --git a/chromium/mojo/public/cpp/base/time_mojom_traits.h b/chromium/mojo/public/cpp/base/time_mojom_traits.h
index db54476861f..213c6e21696 100644
--- a/chromium/mojo/public/cpp/base/time_mojom_traits.h
+++ b/chromium/mojo/public/cpp/base/time_mojom_traits.h
@@ -12,7 +12,7 @@
namespace mojo {
template <>
-struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS)
StructTraits<mojo_base::mojom::TimeDataView, base::Time> {
static int64_t internal_value(const base::Time& time);
@@ -20,7 +20,7 @@ struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
};
template <>
-struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS)
StructTraits<mojo_base::mojom::TimeDeltaDataView, base::TimeDelta> {
static int64_t microseconds(const base::TimeDelta& delta);
@@ -29,7 +29,7 @@ struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
};
template <>
-struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS)
StructTraits<mojo_base::mojom::TimeTicksDataView, base::TimeTicks> {
static int64_t internal_value(const base::TimeTicks& time);
diff --git a/chromium/mojo/public/cpp/bindings/BUILD.gn b/chromium/mojo/public/cpp/bindings/BUILD.gn
index f268dcc8442..27152835ace 100644
--- a/chromium/mojo/public/cpp/bindings/BUILD.gn
+++ b/chromium/mojo/public/cpp/bindings/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//build/buildflag_header.gni")
+import("//build/config/nacl/config.gni")
+import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
+
declare_args() {
enable_mojo_tracing = false
}
@@ -91,6 +94,10 @@ component("bindings_base") {
"//base",
"//mojo/public/cpp/system",
]
+
+ if (enable_ipc_fuzzer) {
+ all_dependent_configs = [ "//tools/ipc_fuzzer:ipc_fuzzer_config" ]
+ }
}
component("bindings") {
@@ -161,6 +168,13 @@ component("bindings") {
"unique_ptr_impl_ref_traits.h",
]
+ if (enable_ipc_fuzzer && !is_nacl_nonsfi) {
+ sources += [
+ "lib/message_dumper.cc",
+ "message_dumper.h",
+ ]
+ }
+
public_deps = [
":bindings_base",
":struct_traits",
diff --git a/chromium/mojo/public/cpp/bindings/README.md b/chromium/mojo/public/cpp/bindings/README.md
index 3c85a69f77c..89e5d95b157 100644
--- a/chromium/mojo/public/cpp/bindings/README.md
+++ b/chromium/mojo/public/cpp/bindings/README.md
@@ -16,6 +16,9 @@ This document provides a detailed guide to bindings API usage with example code
snippets. For a detailed API references please consult the headers in
[//mojo/public/cpp/bindings](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/README.md).
+For a simplified guide targeted at Chromium developers, see [this
+link](/docs/mojo_guide.md).
+
## Getting Started
When a Mojom IDL file is processed by the bindings generator, C++ code is
@@ -998,9 +1001,182 @@ class TableImpl : public db::mojom::Table {
## Associated Interfaces
-See [this document](https://www.chromium.org/developers/design-documents/mojo/associated-interfaces).
+Associated interfaces are interfaces which:
-TODO: Move the above doc into the repository markdown docs.
+* enable running multiple interfaces over a single message pipe while
+ preserving message ordering.
+* make it possible for the bindings to access a single message pipe from
+ multiple sequences.
+
+### Mojom
+
+A new keyword `associated` is introduced for interface pointer/request
+fields. For example:
+
+``` cpp
+interface Bar {};
+
+struct Qux {
+ associated Bar bar3;
+};
+
+interface Foo {
+ // Uses associated interface pointer.
+ SetBar(associated Bar bar1);
+ // Uses associated interface request.
+ GetBar(associated Bar& bar2);
+ // Passes a struct with associated interface pointer.
+ PassQux(Qux qux);
+ // Uses associated interface pointer in callback.
+ AsyncGetBar() => (associated Bar bar4);
+};
+```
+
+It means the interface impl/client will communicate using the same
+message pipe over which the associated interface pointer/request is
+passed.
+
+### Using associated interfaces in C++
+
+When generating C++ bindings, the associated interface pointer of `Bar` is
+mapped to `BarAssociatedPtrInfo` (which is an alias of
+`mojo::AssociatedInterfacePtrInfo<Bar>`); associated interface request to
+`BarAssociatedRequest` (which is an alias of
+`mojo::AssociatedInterfaceRequest<Bar>`).
+
+``` cpp
+// In mojom:
+interface Foo {
+ ...
+ SetBar(associated Bar bar1);
+ GetBar(associated Bar& bar2);
+ ...
+};
+
+// In C++:
+class Foo {
+ ...
+ virtual void SetBar(BarAssociatedPtrInfo bar1) = 0;
+ virtual void GetBar(BarAssociatedRequest bar2) = 0;
+ ...
+};
+```
+
+#### Passing associated interface requests
+
+Assume you have already got an `InterfacePtr<Foo> foo_ptr`, and you would like
+to call `GetBar()` on it. You can do:
+
+``` cpp
+BarAssociatedPtrInfo bar_ptr_info;
+BarAssociatedRequest bar_request = MakeRequest(&bar_ptr_info);
+foo_ptr->GetBar(std::move(bar_request));
+
+// BarAssociatedPtr is an alias of AssociatedInterfacePtr<Bar>.
+BarAssociatedPtr bar_ptr;
+bar_ptr.Bind(std::move(bar_ptr_info));
+bar_ptr->DoSomething();
+```
+
+First, the code creates an associated interface of type `Bar`. It looks very
+similar to what you would do to setup a non-associated interface. An
+important difference is that one of the two associated endpoints (either
+`bar_request` or `bar_ptr_info`) must be sent over another interface. That is
+how the interface is associated with an existing message pipe.
+
+It should be noted that you cannot call `bar_ptr->DoSomething()` before passing
+`bar_request`. This is required by the FIFO-ness guarantee: at the receiver
+side, when the message of `DoSomething` call arrives, we want to dispatch it to
+the corresponding `AssociatedBinding<Bar>` before processing any subsequent
+messages. If `bar_request` is in a subsequent message, message dispatching gets
+into a deadlock. On the other hand, as soon as `bar_request` is sent, `bar_ptr`
+is usable. There is no need to wait until `bar_request` is bound to an
+implementation at the remote side.
+
+A `MakeRequest` overload which takes an `AssociatedInterfacePtr` pointer
+(instead of an `AssociatedInterfacePtrInfo` pointer) is provided to make the
+code a little shorter. The following code achieves the same purpose:
+
+``` cpp
+BarAssociatedPtr bar_ptr;
+foo_ptr->GetBar(MakeRequest(&bar_ptr));
+bar_ptr->DoSomething();
+```
+
+The implementation of `Foo` looks like this:
+
+``` cpp
+class FooImpl : public Foo {
+ ...
+ void GetBar(BarAssociatedRequest bar2) override {
+ bar_binding_.Bind(std::move(bar2));
+ ...
+ }
+ ...
+
+ Binding<Foo> foo_binding_;
+ AssociatedBinding<Bar> bar_binding_;
+};
+```
+
+In this example, `bar_binding_`'s lifespan is tied to that of `FooImpl`. But you
+don't have to do that. You can, for example, pass `bar2` to another sequence to
+bind to an `AssociatedBinding<Bar>` there.
+
+When the underlying message pipe is disconnected (e.g., `foo_ptr` or
+`foo_binding_` is destroyed), all associated interface endpoints (e.g.,
+`bar_ptr` and `bar_binding_`) will receive a connection error.
+
+#### Passing associated interface pointers
+
+Similarly, assume you have already got an `InterfacePtr<Foo> foo_ptr`, and you
+would like to call `SetBar()` on it. You can do:
+
+``` cpp
+AssociatedBind<Bar> bar_binding(some_bar_impl);
+BarAssociatedPtrInfo bar_ptr_info;
+BarAssociatedRequest bar_request = MakeRequest(&bar_ptr_info);
+foo_ptr->SetBar(std::move(bar_ptr_info));
+bar_binding.Bind(std::move(bar_request));
+```
+
+The following code achieves the same purpose:
+
+``` cpp
+AssociatedBind<Bar> bar_binding(some_bar_impl);
+BarAssociatedPtrInfo bar_ptr_info;
+bar_binding.Bind(&bar_ptr_info);
+foo_ptr->SetBar(std::move(bar_ptr_info));
+```
+
+### Performance considerations
+
+When using associated interfaces on different sequences than the master sequence
+(where the master interface lives):
+
+* Sending messages: send happens directly on the calling sequence. So there
+ isn't sequence hopping.
+* Receiving messages: associated interfaces bound on a different sequence from
+ the master interface incur an extra sequence hop during dispatch.
+
+Therefore, performance-wise associated interfaces are better suited for
+scenarios where message receiving happens on the master sequence.
+
+### Testing
+
+Associated interfaces need to be associated with a master interface before
+they can be used. This means one end of the associated interface must be sent
+over one end of the master interface, or over one end of another associated
+interface which itself already has a master interface.
+
+If you want to test an associated interface endpoint without first
+associating it, you can use `mojo::MakeIsolatedRequest()`. This will create
+working associated interface endpoints which are not actually associated with
+anything else.
+
+### Read more
+
+* [Design: Mojo Associated Interfaces](https://docs.google.com/document/d/1nq3J_HbS-gvVfIoEhcVyxm1uY-9G_7lhD-4Kyxb1WIY/edit)
## Synchronous Calls
diff --git a/chromium/mojo/public/cpp/bindings/connector.h b/chromium/mojo/public/cpp/bindings/connector.h
index b08985b4c1d..fa71604b1b3 100644
--- a/chromium/mojo/public/cpp/bindings/connector.h
+++ b/chromium/mojo/public/cpp/bindings/connector.h
@@ -5,6 +5,7 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_CONNECTOR_H_
#define MOJO_PUBLIC_CPP_BINDINGS_CONNECTOR_H_
+#include <atomic>
#include <memory>
#include <utility>
@@ -234,7 +235,7 @@ class MOJO_CPP_BINDINGS_EXPORT Connector : public MessageReceiver {
std::unique_ptr<SimpleWatcher> handle_watcher_;
base::Optional<HandleSignalTracker> peer_remoteness_tracker_;
- bool error_ = false;
+ std::atomic<bool> error_;
bool drop_writes_ = false;
bool enforce_errors_from_incoming_receiver_ = true;
@@ -270,6 +271,10 @@ class MOJO_CPP_BINDINGS_EXPORT Connector : public MessageReceiver {
// nested dispatch operations.
bool is_dispatching_ = false;
+#if defined(ENABLE_IPC_FUZZER)
+ std::unique_ptr<MessageReceiver> message_dumper_;
+#endif
+
// 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
diff --git a/chromium/mojo/public/cpp/bindings/interface_endpoint_client.h b/chromium/mojo/public/cpp/bindings/interface_endpoint_client.h
index 6842c7c3221..581c91d842b 100644
--- a/chromium/mojo/public/cpp/bindings/interface_endpoint_client.h
+++ b/chromium/mojo/public/cpp/bindings/interface_endpoint_client.h
@@ -113,6 +113,7 @@ class MOJO_CPP_BINDINGS_EXPORT InterfaceEndpointClient
void QueryVersion(const base::Callback<void(uint32_t)>& callback);
void RequireVersion(uint32_t version);
void FlushForTesting();
+ void FlushAsyncForTesting(base::OnceClosure callback);
private:
// Maps from the id of a response to the MessageReceiver that handles the
diff --git a/chromium/mojo/public/cpp/bindings/interface_ptr.h b/chromium/mojo/public/cpp/bindings/interface_ptr.h
index 1de84b7830b..0d7d6ff3811 100644
--- a/chromium/mojo/public/cpp/bindings/interface_ptr.h
+++ b/chromium/mojo/public/cpp/bindings/interface_ptr.h
@@ -48,15 +48,15 @@ class InterfacePtr {
InterfacePtr(decltype(nullptr)) {}
// Takes over the binding of another InterfacePtr.
- InterfacePtr(InterfacePtr&& other) {
+ InterfacePtr(InterfacePtr&& other) noexcept {
internal_state_.Swap(&other.internal_state_);
}
- explicit InterfacePtr(PtrInfoType&& info) { Bind(std::move(info)); }
+ explicit InterfacePtr(PtrInfoType&& info) noexcept { Bind(std::move(info)); }
// Takes over the binding of another InterfacePtr, and closes any message pipe
// already bound to this pointer.
- InterfacePtr& operator=(InterfacePtr&& other) {
+ InterfacePtr& operator=(InterfacePtr&& other) noexcept {
reset();
internal_state_.Swap(&other.internal_state_);
return *this;
@@ -127,6 +127,12 @@ class InterfacePtr {
// stimulus.
void FlushForTesting() { internal_state_.FlushForTesting(); }
+ // Same as |FlushForTesting()| but will call |callback| when the flush is
+ // complete.
+ void FlushAsyncForTesting(base::OnceClosure callback) {
+ internal_state_.FlushAsyncForTesting(std::move(callback));
+ }
+
// Closes the bound message pipe, if any.
void reset() {
State doomed;
diff --git a/chromium/mojo/public/cpp/bindings/lib/connector.cc b/chromium/mojo/public/cpp/bindings/lib/connector.cc
index 27b471f16cf..352c51815fc 100644
--- a/chromium/mojo/public/cpp/bindings/lib/connector.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/connector.cc
@@ -22,6 +22,10 @@
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
#include "mojo/public/cpp/system/wait.h"
+#if defined(ENABLE_IPC_FUZZER)
+#include "mojo/public/cpp/bindings/message_dumper.h"
+#endif
+
namespace mojo {
namespace {
@@ -140,6 +144,7 @@ Connector::Connector(ScopedMessagePipeHandle message_pipe,
scoped_refptr<base::SequencedTaskRunner> runner)
: message_pipe_(std::move(message_pipe)),
task_runner_(std::move(runner)),
+ error_(false),
outgoing_serialization_mode_(g_default_outgoing_serialization_mode),
incoming_serialization_mode_(g_default_incoming_serialization_mode),
nesting_observer_(RunLoopNestingObserver::GetForThread()),
@@ -147,6 +152,11 @@ Connector::Connector(ScopedMessagePipeHandle message_pipe,
if (config == MULTI_THREADED_SEND)
lock_.emplace();
+#if defined(ENABLE_IPC_FUZZER)
+ if (!MessageDumper::GetMessageDumpDirectory().empty())
+ message_dumper_ = std::make_unique<MessageDumper>();
+#endif
+
weak_self_ = weak_factory_.GetWeakPtr();
// Even though we don't have an incoming receiver, we still want to monitor
// the message pipe to know if is closed or encounters an error.
@@ -263,9 +273,6 @@ bool Connector::Accept(Message* message) {
if (!lock_)
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // It shouldn't hurt even if |error_| may be changed by a different sequence
- // at the same time. The outcome is that we may write into |message_pipe_|
- // after encountering an error, which should be fine.
if (error_)
return false;
@@ -274,6 +281,13 @@ bool Connector::Accept(Message* message) {
if (!message_pipe_.is_valid() || drop_writes_)
return true;
+#if defined(ENABLE_IPC_FUZZER)
+ if (message_dumper_ && message->is_serialized()) {
+ bool dump_result = message_dumper_->Accept(message);
+ DCHECK(dump_result);
+ }
+#endif
+
MojoResult rv =
WriteMessageNew(message_pipe_.get(), message->TakeMojoMessage(),
MOJO_WRITE_MESSAGE_FLAG_NONE);
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 9fd7bf41735..5e6c3808e8e 100644
--- a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.cc
@@ -12,6 +12,7 @@
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "mojo/public/cpp/bindings/lib/serialization.h"
#include "mojo/public/cpp/bindings/lib/validation_util.h"
#include "mojo/public/cpp/bindings/message.h"
@@ -39,12 +40,12 @@ bool ValidateControlResponse(Message* message) {
}
using RunCallback =
- base::Callback<void(interface_control::RunResponseMessageParamsPtr)>;
+ base::OnceCallback<void(interface_control::RunResponseMessageParamsPtr)>;
class RunResponseForwardToCallback : public MessageReceiver {
public:
- explicit RunResponseForwardToCallback(const RunCallback& callback)
- : callback_(callback) {}
+ explicit RunResponseForwardToCallback(RunCallback callback)
+ : callback_(std::move(callback)) {}
bool Accept(Message* message) override;
private:
@@ -65,13 +66,13 @@ bool RunResponseForwardToCallback::Accept(Message* message) {
Deserialize<interface_control::RunResponseMessageParamsDataView>(
params, &params_ptr, &context);
- callback_.Run(std::move(params_ptr));
+ std::move(callback_).Run(std::move(params_ptr));
return true;
}
void SendRunMessage(MessageReceiverWithResponder* receiver,
interface_control::RunInputPtr input_ptr,
- const RunCallback& callback) {
+ RunCallback callback) {
auto params_ptr = interface_control::RunMessageParams::New();
params_ptr->input = std::move(input_ptr);
Message message(interface_control::kRunMessageId,
@@ -81,7 +82,7 @@ void SendRunMessage(MessageReceiverWithResponder* receiver,
Serialize<interface_control::RunMessageParamsDataView>(
params_ptr, message.payload_buffer(), &params, &context);
std::unique_ptr<MessageReceiver> responder =
- std::make_unique<RunResponseForwardToCallback>(callback);
+ std::make_unique<RunResponseForwardToCallback>(std::move(callback));
ignore_result(receiver->AcceptWithResponder(&message, std::move(responder)));
}
@@ -115,9 +116,9 @@ void RunVersionCallback(
callback.Run(version);
}
-void RunClosure(const base::Closure& callback,
+void RunClosure(base::OnceClosure callback,
interface_control::RunResponseMessageParamsPtr run_response) {
- callback.Run();
+ std::move(callback).Run();
}
} // namespace
@@ -133,7 +134,7 @@ void ControlMessageProxy::QueryVersion(
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));
+ base::BindOnce(&RunVersionCallback, callback));
}
void ControlMessageProxy::RequireVersion(uint32_t version) {
@@ -145,29 +146,38 @@ void ControlMessageProxy::RequireVersion(uint32_t version) {
}
void ControlMessageProxy::FlushForTesting() {
- if (encountered_error_)
+ base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
+ FlushAsyncForTesting(run_loop.QuitClosure());
+ run_loop.Run();
+}
+
+void ControlMessageProxy::FlushAsyncForTesting(base::OnceClosure callback) {
+ if (encountered_error_) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ std::move(callback));
return;
+ }
auto input_ptr = interface_control::RunInput::New();
input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New());
- base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
- run_loop_quit_closure_ = run_loop.QuitClosure();
+ DCHECK(!pending_flush_callback_);
+ pending_flush_callback_ = std::move(callback);
SendRunMessage(
receiver_, std::move(input_ptr),
- base::Bind(&RunClosure,
- base::Bind(&ControlMessageProxy::RunFlushForTestingClosure,
- base::Unretained(this))));
- run_loop.Run();
+ base::BindOnce(
+ &RunClosure,
+ base::BindOnce(&ControlMessageProxy::RunFlushForTestingClosure,
+ base::Unretained(this))));
}
void ControlMessageProxy::RunFlushForTestingClosure() {
- DCHECK(!run_loop_quit_closure_.is_null());
- base::ResetAndReturn(&run_loop_quit_closure_).Run();
+ DCHECK(!pending_flush_callback_.is_null());
+ std::move(pending_flush_callback_).Run();
}
void ControlMessageProxy::OnConnectionError() {
encountered_error_ = true;
- if (!run_loop_quit_closure_.is_null())
+ if (!pending_flush_callback_.is_null())
RunFlushForTestingClosure();
}
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 2f9314ebf00..f15ba246874 100644
--- a/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h
+++ b/chromium/mojo/public/cpp/bindings/lib/control_message_proxy.h
@@ -29,6 +29,7 @@ class MOJO_CPP_BINDINGS_EXPORT ControlMessageProxy {
void RequireVersion(uint32_t version);
void FlushForTesting();
+ void FlushAsyncForTesting(base::OnceClosure callback);
void OnConnectionError();
private:
@@ -38,7 +39,7 @@ class MOJO_CPP_BINDINGS_EXPORT ControlMessageProxy {
MessageReceiverWithResponder* receiver_;
bool encountered_error_ = false;
- base::Closure run_loop_quit_closure_;
+ base::OnceClosure pending_flush_callback_;
DISALLOW_COPY_AND_ASSIGN(ControlMessageProxy);
};
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 6f119e4c1d6..4e6108d3373 100644
--- a/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -347,6 +347,10 @@ void InterfaceEndpointClient::FlushForTesting() {
control_message_proxy_.FlushForTesting();
}
+void InterfaceEndpointClient::FlushAsyncForTesting(base::OnceClosure callback) {
+ control_message_proxy_.FlushAsyncForTesting(std::move(callback));
+}
+
void InterfaceEndpointClient::InitControllerIfNecessary() {
if (controller_ || handle_.pending_association())
return;
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 2e73564a80c..dcea8661f4f 100644
--- a/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h
+++ b/chromium/mojo/public/cpp/bindings/lib/interface_ptr_state.h
@@ -131,6 +131,11 @@ class InterfacePtrState : public InterfacePtrStateBase {
endpoint_client()->FlushForTesting();
}
+ void FlushAsyncForTesting(base::OnceClosure callback) {
+ ConfigureProxyIfNecessary();
+ endpoint_client()->FlushAsyncForTesting(std::move(callback));
+ }
+
void CloseWithReason(uint32_t custom_reason, const std::string& description) {
ConfigureProxyIfNecessary();
endpoint_client()->CloseWithReason(custom_reason, description);
diff --git a/chromium/mojo/public/cpp/bindings/lib/message.cc b/chromium/mojo/public/cpp/bindings/lib/message.cc
index 44ebf653b26..8972d9efd1d 100644
--- a/chromium/mojo/public/cpp/bindings/lib/message.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/message.cc
@@ -185,6 +185,10 @@ Message::Message(Message&& other)
serialized_(other.serialized_) {
other.transferable_ = false;
other.serialized_ = false;
+#if defined(ENABLE_IPC_FUZZER)
+ interface_name_ = other.interface_name_;
+ method_name_ = other.method_name_;
+#endif
}
Message::Message(std::unique_ptr<internal::UnserializedMessageContext> context)
@@ -262,6 +266,10 @@ Message& Message::operator=(Message&& other) {
other.transferable_ = false;
serialized_ = other.serialized_;
other.serialized_ = false;
+#if defined(ENABLE_IPC_FUZZER)
+ interface_name_ = other.interface_name_;
+ method_name_ = other.method_name_;
+#endif
return *this;
}
diff --git a/chromium/mojo/public/cpp/bindings/lib/message_dumper.cc b/chromium/mojo/public/cpp/bindings/lib/message_dumper.cc
new file mode 100644
index 00000000000..f187e4569b8
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/lib/message_dumper.cc
@@ -0,0 +1,96 @@
+// Copyright 2018 The Chromium 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_dumper.h"
+
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/process/process.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace {
+
+base::FilePath& DumpDirectory() {
+ static base::NoDestructor<base::FilePath> dump_directory;
+ return *dump_directory;
+}
+
+void WriteMessage(uint32_t identifier,
+ const mojo::MessageDumper::MessageEntry& entry) {
+ static uint64_t num = 0;
+
+ if (!entry.interface_name)
+ return;
+
+ base::FilePath message_directory =
+ DumpDirectory()
+ .AppendASCII(entry.interface_name)
+ .AppendASCII(base::NumberToString(identifier));
+
+ if (!base::DirectoryExists(message_directory) &&
+ !base::CreateDirectory(message_directory)) {
+ LOG(ERROR) << "Failed to create" << message_directory.value();
+ return;
+ }
+
+ std::string filename =
+ base::NumberToString(num++) + "." + entry.method_name + ".mojomsg";
+ base::FilePath path = message_directory.AppendASCII(filename);
+ base::File file(path,
+ base::File::FLAG_WRITE | base::File::FLAG_CREATE_ALWAYS);
+
+ file.WriteAtCurrentPos(reinterpret_cast<const char*>(entry.data_bytes.data()),
+ static_cast<int>(entry.data_bytes.size()));
+}
+
+} // namespace
+
+namespace mojo {
+
+MessageDumper::MessageEntry::MessageEntry(const uint8_t* data,
+ uint32_t data_size,
+ const char* interface_name,
+ const char* method_name)
+ : interface_name(interface_name),
+ method_name(method_name),
+ data_bytes(data, data + data_size) {}
+
+MessageDumper::MessageEntry::MessageEntry(const MessageEntry& entry) = default;
+
+MessageDumper::MessageEntry::~MessageEntry() {}
+
+MessageDumper::MessageDumper() : identifier_(base::RandUint64()) {}
+
+MessageDumper::~MessageDumper() {}
+
+bool MessageDumper::Accept(mojo::Message* message) {
+ MessageEntry entry(message->data(), message->data_num_bytes(),
+ message->interface_name(), message->method_name());
+
+ static base::NoDestructor<scoped_refptr<base::TaskRunner>> task_runner(
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+
+ (*task_runner)
+ ->PostTask(FROM_HERE,
+ base::BindOnce(&WriteMessage, identifier_, std::move(entry)));
+ return true;
+}
+
+void MessageDumper::SetMessageDumpDirectory(const base::FilePath& directory) {
+ DumpDirectory() = directory;
+}
+
+const base::FilePath& MessageDumper::GetMessageDumpDirectory() {
+ return DumpDirectory();
+}
+
+} // 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 61833097ef3..6a1c58bce6c 100644
--- a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -338,8 +338,9 @@ MultiplexRouter::MultiplexRouter(
connector_.AllowWokenUpBySyncWatchOnSameThread();
}
connector_.set_incoming_receiver(&filters_);
- connector_.set_connection_error_handler(base::Bind(
- &MultiplexRouter::OnPipeConnectionError, base::Unretained(this)));
+ connector_.set_connection_error_handler(
+ base::BindOnce(&MultiplexRouter::OnPipeConnectionError,
+ base::Unretained(this), false /* force_async_dispatch */));
std::unique_ptr<MessageHeaderValidator> header_validator =
std::make_unique<MessageHeaderValidator>();
@@ -491,7 +492,7 @@ void MultiplexRouter::RaiseError() {
connector_.RaiseError();
} else {
task_runner_->PostTask(FROM_HERE,
- base::Bind(&MultiplexRouter::RaiseError, this));
+ base::BindOnce(&MultiplexRouter::RaiseError, this));
}
}
@@ -506,7 +507,7 @@ void MultiplexRouter::CloseMessagePipe() {
// CloseMessagePipe() above won't trigger connection error handler.
// Explicitly call OnPipeConnectionError() so that associated endpoints will
// get notified.
- OnPipeConnectionError();
+ OnPipeConnectionError(true /* force_async_dispatch */);
}
void MultiplexRouter::PauseIncomingMethodCallProcessing() {
@@ -641,7 +642,7 @@ bool MultiplexRouter::OnPeerAssociatedEndpointClosed(
return true;
}
-void MultiplexRouter::OnPipeConnectionError() {
+void MultiplexRouter::OnPipeConnectionError(bool force_async_dispatch) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
scoped_refptr<MultiplexRouter> protector(this);
@@ -664,10 +665,13 @@ void MultiplexRouter::OnPipeConnectionError() {
UpdateEndpointStateMayRemove(endpoint.get(), PEER_ENDPOINT_CLOSED);
}
- ProcessTasks(connector_.during_sync_handle_watcher_callback()
- ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES
- : ALLOW_DIRECT_CLIENT_CALLS,
- connector_.task_runner());
+ ClientCallBehavior call_behavior = ALLOW_DIRECT_CLIENT_CALLS;
+ if (force_async_dispatch)
+ call_behavior = NO_DIRECT_CLIENT_CALLS;
+ else if (connector_.during_sync_handle_watcher_callback())
+ call_behavior = ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES;
+
+ ProcessTasks(call_behavior, connector_.task_runner());
}
void MultiplexRouter::ProcessTasks(
@@ -879,7 +883,8 @@ void MultiplexRouter::MaybePostToProcessTasks(
posted_to_process_tasks_ = true;
posted_to_task_runner_ = task_runner;
task_runner->PostTask(
- FROM_HERE, base::Bind(&MultiplexRouter::LockAndCallProcessTasks, this));
+ FROM_HERE,
+ base::BindOnce(&MultiplexRouter::LockAndCallProcessTasks, this));
}
void MultiplexRouter::LockAndCallProcessTasks() {
diff --git a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h
index 8c2e7c8b0fc..155e1fe39ab 100644
--- a/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h
+++ b/chromium/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -173,7 +173,7 @@ class MOJO_CPP_BINDINGS_EXPORT MultiplexRouter
InterfaceId id,
const base::Optional<DisconnectReason>& reason) override;
- void OnPipeConnectionError();
+ void OnPipeConnectionError(bool force_async_dispatch);
// Specifies whether we are allowed to directly call into
// InterfaceEndpointClient (given that we are already on the same sequence as
diff --git a/chromium/mojo/public/cpp/bindings/lib/unserialized_message_context.cc b/chromium/mojo/public/cpp/bindings/lib/unserialized_message_context.cc
index 855db4c3cb3..b029f4ef006 100644
--- a/chromium/mojo/public/cpp/bindings/lib/unserialized_message_context.cc
+++ b/chromium/mojo/public/cpp/bindings/lib/unserialized_message_context.cc
@@ -15,6 +15,7 @@ UnserializedMessageContext::UnserializedMessageContext(const Tag* tag,
header_.version = 1;
header_.name = message_name;
header_.flags = message_flags;
+ header_.num_bytes = sizeof(header_);
}
UnserializedMessageContext::~UnserializedMessageContext() = default;
diff --git a/chromium/mojo/public/cpp/bindings/message.h b/chromium/mojo/public/cpp/bindings/message.h
index 4ad1c04c187..7f6e3ea436c 100644
--- a/chromium/mojo/public/cpp/bindings/message.h
+++ b/chromium/mojo/public/cpp/bindings/message.h
@@ -211,6 +211,16 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) Message {
generic_context.release()->template SafeCast<MessageType>());
}
+#if defined(ENABLE_IPC_FUZZER)
+ const char* interface_name() const { return interface_name_; }
+ void set_interface_name(const char* interface_name) {
+ interface_name_ = interface_name;
+ }
+
+ const char* method_name() const { return method_name_; }
+ void set_method_name(const char* method_name) { method_name_ = method_name; }
+#endif
+
private:
ScopedMessageHandle handle_;
@@ -230,6 +240,11 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) Message {
// Indicates whether this Message object is serialized.
bool serialized_ = false;
+#if defined(ENABLE_IPC_FUZZER)
+ const char* interface_name_ = nullptr;
+ const char* method_name_ = nullptr;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(Message);
};
diff --git a/chromium/mojo/public/cpp/bindings/message_dumper.h b/chromium/mojo/public/cpp/bindings/message_dumper.h
new file mode 100644
index 00000000000..44cf384ab0d
--- /dev/null
+++ b/chromium/mojo/public/cpp/bindings/message_dumper.h
@@ -0,0 +1,43 @@
+// Copyright 2018 The Chromium 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_DUMPER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_DUMPER_H_
+
+#include "base/files/file_path.h"
+#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/bindings/message_dumper.h"
+
+namespace mojo {
+
+class MessageDumper : public mojo::MessageReceiver {
+ public:
+ MessageDumper();
+ ~MessageDumper() override;
+
+ bool Accept(mojo::Message* message) override;
+
+ struct MessageEntry {
+ MessageEntry(const uint8_t* data,
+ uint32_t data_size,
+ const char* interface_name,
+ const char* method_name);
+ MessageEntry(const MessageEntry& entry);
+ ~MessageEntry();
+
+ const char* interface_name;
+ const char* method_name;
+ std::vector<uint8_t> data_bytes;
+ };
+
+ static void SetMessageDumpDirectory(const base::FilePath& directory);
+ static const base::FilePath& GetMessageDumpDirectory();
+
+ private:
+ uint32_t identifier_;
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_DUMPER_H_
diff --git a/chromium/mojo/public/cpp/bindings/sync_call_restrictions.h b/chromium/mojo/public/cpp/bindings/sync_call_restrictions.h
index 225782d96d7..e72cb1d3cb1 100644
--- a/chromium/mojo/public/cpp/bindings/sync_call_restrictions.h
+++ b/chromium/mojo/public/cpp/bindings/sync_call_restrictions.h
@@ -37,9 +37,10 @@ namespace prefs {
class PersistentPrefStoreClient;
}
-namespace views {
-class ClipboardMus;
-}
+namespace ui {
+class ClipboardClient;
+class HostContextFactoryPrivate;
+} // namespace ui
namespace viz {
class HostFrameSinkManager;
@@ -94,18 +95,19 @@ class MOJO_CPP_BINDINGS_EXPORT SyncCallRestrictions {
friend class mojo::ScopedAllowSyncCallForTesting;
// For file open and save dialogs created synchronously.
friend class ::ChromeSelectFileDialogFactory;
+ // For synchronous system clipboard access.
+ friend class ui::ClipboardClient;
// For destroying the GL context/surface that draw to a platform window before
// the platform window is destroyed.
friend class viz::HostFrameSinkManager;
// Allow for layout test pixel dumps.
friend class content::BlinkTestController;
+ // For preventing frame swaps of wrong size during resize on Windows.
+ // (https://crbug.com/811945)
+ friend class ui::HostContextFactoryPrivate;
// END ALLOWED USAGE.
// BEGIN USAGE THAT NEEDS TO BE FIXED.
- // In the non-mus case, we called blocking OS functions in the ui::Clipboard
- // implementation which weren't caught by sync call restrictions. Our blocking
- // calls to mus, however, are.
- friend class views::ClipboardMus;
// In ash::Shell::Init() it assumes that NativeDisplayDelegate will be
// synchronous at first. In mushrome ForwardingDisplayDelegate uses a
// synchronous call to get the display snapshots as a workaround.
diff --git a/chromium/mojo/public/cpp/bindings/tests/BUILD.gn b/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
index b54000d3212..82038a186d9 100644
--- a/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/chromium/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -50,7 +50,7 @@ source_set("tests") {
deps = [
":mojo_public_bindings_test_utils",
"//base/test:test_support",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//mojo/public/cpp/test_support:test_utils",
@@ -134,8 +134,8 @@ source_set("perftests") {
deps = [
"//base/test:test_support",
- "//mojo/edk",
- "//mojo/edk/test:test_support",
+ "//mojo/core/embedder",
+ "//mojo/core/test:test_support",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//mojo/public/cpp/test_support:test_utils",
diff --git a/chromium/mojo/public/cpp/platform/BUILD.gn b/chromium/mojo/public/cpp/platform/BUILD.gn
index 3aea9dea5e7..b0aa90ef371 100644
--- a/chromium/mojo/public/cpp/platform/BUILD.gn
+++ b/chromium/mojo/public/cpp/platform/BUILD.gn
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/nacl/config.gni")
+
component("platform") {
output_name = "mojo_cpp_platform"
@@ -22,8 +24,14 @@ component("platform") {
"platform_handle.cc",
]
+ if (is_posix && (!is_nacl || is_nacl_nonsfi)) {
+ public += [ "socket_utils_posix.h" ]
+ sources += [ "socket_utils_posix.cc" ]
+ }
+
public_deps = [
"//base",
+ "//mojo/public/c/system:headers",
]
if (is_posix && (!is_nacl && !is_fuchsia)) {
@@ -32,7 +40,10 @@ component("platform") {
if (is_fuchsia) {
sources += [ "named_platform_channel_fuchsia.cc" ]
- public_deps += [ "//third_party/fuchsia-sdk:fdio" ]
+ public_deps += [
+ "//third_party/fuchsia-sdk:fdio",
+ "//third_party/fuchsia-sdk:zx",
+ ]
}
defines = [ "IS_MOJO_CPP_PLATFORM_IMPL" ]
diff --git a/chromium/mojo/public/cpp/platform/DEPS b/chromium/mojo/public/cpp/platform/DEPS
index aa2ee21388d..375d67bbe6e 100644
--- a/chromium/mojo/public/cpp/platform/DEPS
+++ b/chromium/mojo/public/cpp/platform/DEPS
@@ -2,6 +2,7 @@ include_rules = [
# Mojo platform support must not depend on any other part of the Mojo public
# library.
"-mojo",
+ "+mojo/public/c/system",
"+mojo/public/cpp/platform",
# For some syscalls when building in NaCl toolchains.
diff --git a/chromium/mojo/public/cpp/platform/README.md b/chromium/mojo/public/cpp/platform/README.md
new file mode 100644
index 00000000000..c91e85fa7fa
--- /dev/null
+++ b/chromium/mojo/public/cpp/platform/README.md
@@ -0,0 +1,75 @@
+# Mojo C++ Platform API
+This document is a subset of the [Mojo documentation](/mojo/README.md).
+
+[TOC]
+
+## Overview
+The Mojo C++ Platform API provides a lightweight set of abstractions around
+stable platform primitive APIs like UNIX domain sockets and Windows named pipes.
+This API is primarily useful in conjunction with Mojo
+[Invitations](/mojo/public/cpp/system/README.md#Invitations) to bootstrap Mojo
+IPC between two processes.
+
+## Platform Handles
+The `PlatformHandle` type provides a move-only wrapper around an owned,
+platform-specific primitive handle types. The type of primitive it holds can be
+any of the following:
+
+ * Windows HANDLE (Windows only)
+ * Fuchsia zx_handle_t (Fuchsia only)
+ * Mach send right (OSX only)
+ * POSIX file descriptor (POSIX systems only)
+
+See the
+[header](https://cs.chromium.org/src/mojo/public/cpp/platform/platform_handle.h)
+for more details.
+
+## Platform Channels
+The `PlatformChannel` type abstracts a platform-specific IPC FIFO primitive
+primarily for use with the Mojo
+[Invitations](/mojo/public/cpp/system/README.md#Invitations) API. Constructing
+a `PlatformChannel` instance creates the underlying system primitive with two
+transferrable `PlatformHandle` instances, each thinly wrapped as a
+`PlatformChannelEndpoint` for additional type-safety. One endpoint is designated
+as **local** and the other **remote**, the intention being that the remote
+endpoint will be transferred to another process in the system.
+
+See the
+[header](https://cs.chromium.org/src/mojo/public/cpp/platform/platform_channel.h)
+for more details. See the
+[Invitations](/mojo/public/cpp/system/README.md#Invitations) documentation for
+an example of using `PlatformChannel` with an invitation to bootstrap IPC
+between a process and one of its newly launched child processes.
+
+## Named Platform Channels
+For cases where it is not feasible to transfer a `PlatformHandle` from one
+running process to another, the Platform API also provides
+`NamedPlatformChannel`, which abstracts a named system resource that can
+facilitate communication similarly to `PlatformChannel`.
+
+A `NamedPlatformChannel` upon construction will begin listening on
+platform-specific primitive (a named pipe server on Windows, a domain socket
+server on POSIX, *etc.*). The globally reachable name of the server (*e.g.* the
+socket path) can be specified at construction time via
+`NamedPlatformChannel::Options::server_name`, but if no name is given, a
+suitably random one is generated and used.
+
+``` cpp
+// In one process
+mojo::NamedPlatformChannel::Options options;
+mojo::NamedPlatformChannel named_channel(options);
+OutgoingInvitation::Send(std::move(invitation),
+ named_channel.TakeServerEndpoint());
+SendServerNameToRemoteProcessSomehow(named_channel.GetServerName());
+
+// In the other process
+void OnGotServerName(const mojo::NamedPlatformChannel::ServerName& name) {
+ // Connect to the server.
+ mojo::PlatformChannelEndpoint endpoint =
+ mojo::NamedPlatformChannel::ConnectToServer(name);
+
+ // Proceed normally with invitation acceptance.
+ auto invitation = mojo::IncomingInvitation::Accept(std::move(endpoint));
+ // ...
+}
+```
diff --git a/chromium/mojo/public/cpp/platform/named_platform_channel.cc b/chromium/mojo/public/cpp/platform/named_platform_channel.cc
index e0d12178128..4439710df97 100644
--- a/chromium/mojo/public/cpp/platform/named_platform_channel.cc
+++ b/chromium/mojo/public/cpp/platform/named_platform_channel.cc
@@ -5,6 +5,7 @@
#include "mojo/public/cpp/platform/named_platform_channel.h"
#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
namespace mojo {
@@ -16,8 +17,24 @@ NamedPlatformChannel::NamedPlatformChannel(const Options& options) {
CreateServerEndpoint(options, &server_name_));
}
+NamedPlatformChannel::NamedPlatformChannel(NamedPlatformChannel&& other) =
+ default;
+
NamedPlatformChannel::~NamedPlatformChannel() = default;
+NamedPlatformChannel& NamedPlatformChannel::operator=(
+ NamedPlatformChannel&& other) = default;
+
+// static
+NamedPlatformChannel::ServerName NamedPlatformChannel::ServerNameFromUTF8(
+ base::StringPiece name) {
+#if defined(OS_WIN)
+ return base::UTF8ToUTF16(name);
+#else
+ return name.as_string();
+#endif
+}
+
void NamedPlatformChannel::PassServerNameOnCommandLine(
base::CommandLine* command_line) {
command_line->AppendSwitchNative(kNamedHandleSwitch, server_name_);
diff --git a/chromium/mojo/public/cpp/platform/named_platform_channel.h b/chromium/mojo/public/cpp/platform/named_platform_channel.h
index 4cc32a7d9c0..177136e4e5d 100644
--- a/chromium/mojo/public/cpp/platform/named_platform_channel.h
+++ b/chromium/mojo/public/cpp/platform/named_platform_channel.h
@@ -64,12 +64,18 @@ class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) NamedPlatformChannel {
};
NamedPlatformChannel(const Options& options);
+ NamedPlatformChannel(NamedPlatformChannel&& other);
~NamedPlatformChannel();
+ NamedPlatformChannel& operator=(NamedPlatformChannel&& other);
+
const PlatformChannelServerEndpoint& server_endpoint() const {
return server_endpoint_;
}
+ // Helper to create a ServerName from a UTF8 string regardless of platform.
+ static ServerName ServerNameFromUTF8(base::StringPiece name);
+
// Passes the local server endpoint for the channel. On Windows, this is a
// named pipe server; on POSIX it's a bound, listening domain socket. In each
// case it should accept a single new connection.
diff --git a/chromium/mojo/public/cpp/platform/named_platform_channel_win.cc b/chromium/mojo/public/cpp/platform/named_platform_channel_win.cc
index 0507efe5abb..9c329bd6d81 100644
--- a/chromium/mojo/public/cpp/platform/named_platform_channel_win.cc
+++ b/chromium/mojo/public/cpp/platform/named_platform_channel_win.cc
@@ -5,6 +5,7 @@
#include "mojo/public/cpp/platform/named_platform_channel.h"
#include <windows.h>
+#include <memory>
// NOTE: This needs to be included *after* windows.h.
#include <sddl.h>
diff --git a/chromium/mojo/public/cpp/platform/platform_channel.cc b/chromium/mojo/public/cpp/platform/platform_channel.cc
index f707b7c2195..a82910d06a0 100644
--- a/chromium/mojo/public/cpp/platform/platform_channel.cc
+++ b/chromium/mojo/public/cpp/platform/platform_channel.cc
@@ -21,11 +21,11 @@
#include "base/win/scoped_handle.h"
#elif defined(OS_FUCHSIA)
+#include <lib/zx/channel.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
-#include <zircon/syscalls.h>
-#include "base/fuchsia/scoped_zx_handle.h"
+#include "base/fuchsia/fuchsia_logging.h"
#elif defined(OS_POSIX)
#include <fcntl.h>
#include <sys/types.h>
@@ -66,7 +66,8 @@ void CreateChannel(PlatformHandle* local_endpoint,
const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE;
// The SECURITY_ANONYMOUS flag means that the server side cannot impersonate
// the client.
- DWORD kFlags = SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS;
+ DWORD kFlags =
+ SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED;
// Allow the handle to be inherited by child processes.
SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES),
nullptr, TRUE};
@@ -83,12 +84,12 @@ void CreateChannel(PlatformHandle* local_endpoint,
#elif defined(OS_FUCHSIA)
void CreateChannel(PlatformHandle* local_endpoint,
PlatformHandle* remote_endpoint) {
- zx_handle_t handles[2] = {};
- zx_status_t result = zx_channel_create(0, &handles[0], &handles[1]);
- CHECK_EQ(ZX_OK, result);
+ zx::channel handles[2];
+ zx_status_t result = zx::channel::create(0, &handles[0], &handles[1]);
+ ZX_CHECK(result == ZX_OK, result);
- *local_endpoint = PlatformHandle(base::ScopedZxHandle(handles[0]));
- *remote_endpoint = PlatformHandle(base::ScopedZxHandle(handles[1]));
+ *local_endpoint = PlatformHandle(std::move(handles[0]));
+ *remote_endpoint = PlatformHandle(std::move(handles[1]));
DCHECK(local_endpoint->is_valid());
DCHECK(remote_endpoint->is_valid());
}
@@ -173,13 +174,14 @@ void PlatformChannel::PrepareToPassRemoteEndpoint(HandlePassingInfo* info,
*value = base::NumberToString(
HandleToLong(remote_endpoint_.platform_handle().GetHandle().Get()));
#elif defined(OS_FUCHSIA)
- const uint32_t id = PA_HND(PA_USER0, 0);
+ const uint32_t id = PA_HND(PA_USER0, info->size());
info->push_back({id, remote_endpoint_.platform_handle().GetHandle().get()});
*value = base::NumberToString(id);
#elif defined(OS_ANDROID)
int fd = remote_endpoint_.platform_handle().GetFD().get();
- info->emplace_back(fd, kAndroidClientHandleDescriptor);
- *value = base::NumberToString(kAndroidClientHandleDescriptor);
+ int mapped_fd = kAndroidClientHandleDescriptor + info->size();
+ info->emplace_back(fd, mapped_fd);
+ *value = base::NumberToString(mapped_fd);
#elif defined(OS_POSIX)
// Arbitrary sanity check to ensure the loop below terminates reasonably
// quickly.
@@ -206,10 +208,25 @@ void PlatformChannel::PrepareToPassRemoteEndpoint(
command_line->AppendSwitchASCII(kHandleSwitch, value);
}
-void PlatformChannel::RemoteProcessLaunched() {
+void PlatformChannel::PrepareToPassRemoteEndpoint(
+ base::LaunchOptions* options,
+ base::CommandLine* command_line) {
+#if defined(OS_WIN)
+ PrepareToPassRemoteEndpoint(&options->handles_to_inherit, command_line);
+#elif defined(OS_FUCHSIA)
+ PrepareToPassRemoteEndpoint(&options->handles_to_transfer, command_line);
+#elif defined(OS_POSIX)
+ PrepareToPassRemoteEndpoint(&options->fds_to_remap, command_line);
+#else
+#error "Platform not supported."
+#endif
+}
+
+void PlatformChannel::RemoteProcessLaunchAttempted() {
#if defined(OS_FUCHSIA)
- // Unlike other platforms, Fuchsia just transfers handle ownership to the
- // launcher process rather than duplicating it.
+ // Unlike other platforms, Fuchsia transfers handle ownership to the new
+ // process, rather than duplicating it. For consistency the process-launch
+ // call will have consumed the handle regardless of whether launch succeeded.
DCHECK(remote_endpoint_.platform_handle().is_valid_handle());
ignore_result(remote_endpoint_.TakePlatformHandle().ReleaseHandle());
#else
@@ -234,8 +251,8 @@ PlatformChannelEndpoint PlatformChannel::RecoverPassedEndpointFromString(
DLOG(ERROR) << "Invalid PlatformChannel endpoint string.";
return PlatformChannelEndpoint();
}
- return PlatformChannelEndpoint(PlatformHandle(base::ScopedZxHandle(
- zx_get_startup_handle(base::checked_cast<uint32_t>(handle_value)))));
+ return PlatformChannelEndpoint(PlatformHandle(zx::handle(
+ zx_take_startup_handle(base::checked_cast<uint32_t>(handle_value)))));
#elif defined(OS_ANDROID)
base::GlobalDescriptors::Key key = -1;
if (value.empty() || !base::StringToUint(value, &key)) {
diff --git a/chromium/mojo/public/cpp/platform/platform_channel.h b/chromium/mojo/public/cpp/platform/platform_channel.h
index 149c6b10a44..534c6bbfdc2 100644
--- a/chromium/mojo/public/cpp/platform/platform_channel.h
+++ b/chromium/mojo/public/cpp/platform/platform_channel.h
@@ -74,8 +74,9 @@ class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformChannel {
// passed on the new process's command line.
//
// **NOTE**: If this method is called it is important to also call
- // |RemoteProcessLaunched()| on this PlatformChanenl *after* the process has
- // launched. Failing to do so can result in leaked handles.
+ // |RemoteProcessLaunchAttempted()| on this PlatformChannel *after* attempting
+ // to launch the new process, regardless of whether the attempt succeeded.
+ // Failing to do so can result in leaked handles.
void PrepareToPassRemoteEndpoint(HandlePassingInfo* info, std::string* value);
// Like above but modifies |*command_line| to include the endpoint string
@@ -83,11 +84,17 @@ class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformChannel {
void PrepareToPassRemoteEndpoint(HandlePassingInfo* info,
base::CommandLine* command_line);
- // Must be called after the corresponding process launch if
+ // Like above but adds handle-passing information directly to
+ // |*launch_options|, eliminating the potential need for callers to write
+ // platform-specific code to do the same.
+ void PrepareToPassRemoteEndpoint(base::LaunchOptions* options,
+ base::CommandLine* command_line);
+
+ // Must be called after the corresponding process launch attempt if
// |PrepareToPassRemoteEndpoint()| was used.
- void RemoteProcessLaunched();
+ void RemoteProcessLaunchAttempted();
- // Recovers and endpoint handle which was passed to the calling process by
+ // Recovers an endpoint handle which was passed to the calling process by
// its creator. |value| is a string returned by
// |PrepareToPassRemoteEndpoint()| in the creator's process.
static PlatformChannelEndpoint RecoverPassedEndpointFromString(
diff --git a/chromium/mojo/public/cpp/platform/platform_handle.cc b/chromium/mojo/public/cpp/platform/platform_handle.cc
index 14140717143..106fe48e4cd 100644
--- a/chromium/mojo/public/cpp/platform/platform_handle.cc
+++ b/chromium/mojo/public/cpp/platform/platform_handle.cc
@@ -9,19 +9,25 @@
#if defined(OS_WIN)
#include <windows.h>
+
+#include "base/win/scoped_handle.h"
#elif defined(OS_FUCHSIA)
-#include <fdio/limits.h>
+#include <lib/fdio/limits.h>
#include <unistd.h>
#include <zircon/status.h>
-#include <zircon/syscalls.h>
+
+#include "base/fuchsia/fuchsia_logging.h"
#elif defined(OS_MACOSX) && !defined(OS_IOS)
#include <mach/mach_vm.h>
#include "base/mac/mach_logging.h"
+#include "base/mac/scoped_mach_port.h"
#endif
#if defined(OS_POSIX)
#include <unistd.h>
+
+#include "base/files/scoped_file.h"
#endif
namespace mojo {
@@ -42,14 +48,14 @@ base::win::ScopedHandle CloneHandle(const base::win::ScopedHandle& handle) {
return base::win::ScopedHandle(dupe);
}
#elif defined(OS_FUCHSIA)
-base::ScopedZxHandle CloneHandle(const base::ScopedZxHandle& handle) {
+zx::handle CloneHandle(const zx::handle& handle) {
DCHECK(handle.is_valid());
- zx_handle_t dupe;
- zx_status_t result =
- zx_handle_duplicate(handle.get(), ZX_RIGHT_SAME_RIGHTS, &dupe);
- DLOG_IF(ERROR, result != ZX_OK) << "zx_duplicate_handle failed: " << result;
- return base::ScopedZxHandle(dupe);
+ zx::handle dupe;
+ zx_status_t result = handle.duplicate(ZX_RIGHT_SAME_RIGHTS, &dupe);
+ if (result != ZX_OK)
+ ZX_DLOG(ERROR, result) << "zx_duplicate_handle";
+ return std::move(dupe);
}
#elif defined(OS_MACOSX) && !defined(OS_IOS)
base::mac::ScopedMachSendRight CloneMachPort(
@@ -77,21 +83,24 @@ base::ScopedFD CloneFD(const base::ScopedFD& fd) {
PlatformHandle::PlatformHandle() = default;
-PlatformHandle::PlatformHandle(PlatformHandle&& other) = default;
+PlatformHandle::PlatformHandle(PlatformHandle&& other) {
+ *this = std::move(other);
+}
#if defined(OS_WIN)
PlatformHandle::PlatformHandle(base::win::ScopedHandle handle)
- : handle_(std::move(handle)) {}
+ : type_(Type::kHandle), handle_(std::move(handle)) {}
#elif defined(OS_FUCHSIA)
-PlatformHandle::PlatformHandle(base::ScopedZxHandle handle)
- : handle_(std::move(handle)) {}
+PlatformHandle::PlatformHandle(zx::handle handle)
+ : type_(Type::kHandle), handle_(std::move(handle)) {}
#elif defined(OS_MACOSX) && !defined(OS_IOS)
PlatformHandle::PlatformHandle(base::mac::ScopedMachSendRight mach_port)
- : mach_port_(std::move(mach_port)) {}
+ : type_(Type::kMachPort), mach_port_(std::move(mach_port)) {}
#endif
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-PlatformHandle::PlatformHandle(base::ScopedFD fd) : fd_(std::move(fd)) {
+PlatformHandle::PlatformHandle(base::ScopedFD fd)
+ : type_(Type::kFd), fd_(std::move(fd)) {
#if defined(OS_FUCHSIA)
DCHECK_LT(fd_.get(), FDIO_MAX_FD);
#endif
@@ -100,9 +109,101 @@ PlatformHandle::PlatformHandle(base::ScopedFD fd) : fd_(std::move(fd)) {
PlatformHandle::~PlatformHandle() = default;
-PlatformHandle& PlatformHandle::operator=(PlatformHandle&& other) = default;
+PlatformHandle& PlatformHandle::operator=(PlatformHandle&& other) {
+ type_ = other.type_;
+ other.type_ = Type::kNone;
+
+#if defined(OS_WIN)
+ handle_ = std::move(other.handle_);
+#elif defined(OS_FUCHSIA)
+ handle_ = std::move(other.handle_);
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ mach_port_ = std::move(other.mach_port_);
+#endif
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+ fd_ = std::move(other.fd_);
+#endif
+
+ return *this;
+}
+
+// static
+void PlatformHandle::ToMojoPlatformHandle(PlatformHandle handle,
+ MojoPlatformHandle* out_handle) {
+ DCHECK(out_handle);
+ out_handle->struct_size = sizeof(MojoPlatformHandle);
+ if (handle.type_ == Type::kNone) {
+ out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
+ out_handle->value = 0;
+ return;
+ }
+
+ do {
+#if defined(OS_WIN)
+ out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
+ out_handle->value =
+ static_cast<uint64_t>(HandleToLong(handle.TakeHandle().Take()));
+ break;
+#elif defined(OS_FUCHSIA)
+ if (handle.is_handle()) {
+ out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE;
+ out_handle->value = handle.TakeHandle().release();
+ break;
+ }
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ if (handle.is_mach_port()) {
+ out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
+ out_handle->value =
+ static_cast<uint64_t>(handle.TakeMachPort().release());
+ break;
+ }
+#endif
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+ DCHECK(handle.is_fd());
+ out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
+ out_handle->value = static_cast<uint64_t>(handle.TakeFD().release());
+#endif
+ } while (false);
+
+ // One of the above cases must take ownership of |handle|.
+ DCHECK(!handle.is_valid());
+}
+
+// static
+PlatformHandle PlatformHandle::FromMojoPlatformHandle(
+ const MojoPlatformHandle* handle) {
+ if (handle->struct_size < sizeof(*handle) ||
+ handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
+ return PlatformHandle();
+ }
+
+#if defined(OS_WIN)
+ if (handle->type != MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE)
+ return PlatformHandle();
+ return PlatformHandle(
+ base::win::ScopedHandle(LongToHandle(static_cast<long>(handle->value))));
+#elif defined(OS_FUCHSIA)
+ if (handle->type == MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE)
+ return PlatformHandle(zx::handle(handle->value));
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ if (handle->type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT) {
+ return PlatformHandle(base::mac::ScopedMachSendRight(
+ static_cast<mach_port_t>(handle->value)));
+ }
+#endif
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+ if (handle->type != MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
+ return PlatformHandle();
+ return PlatformHandle(base::ScopedFD(static_cast<int>(handle->value)));
+#endif
+}
void PlatformHandle::reset() {
+ type_ = Type::kNone;
+
#if defined(OS_WIN)
handle_.Close();
#elif defined(OS_FUCHSIA)
@@ -116,6 +217,22 @@ void PlatformHandle::reset() {
#endif
}
+void PlatformHandle::release() {
+ type_ = Type::kNone;
+
+#if defined(OS_WIN)
+ ignore_result(handle_.Take());
+#elif defined(OS_FUCHSIA)
+ ignore_result(handle_.release());
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ ignore_result(mach_port_.release());
+#endif
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+ ignore_result(fd_.release());
+#endif
+}
+
PlatformHandle PlatformHandle::Clone() const {
#if defined(OS_WIN)
return PlatformHandle(CloneHandle(handle_));
diff --git a/chromium/mojo/public/cpp/platform/platform_handle.h b/chromium/mojo/public/cpp/platform/platform_handle.h
index c9608fab333..22ea774f56a 100644
--- a/chromium/mojo/public/cpp/platform/platform_handle.h
+++ b/chromium/mojo/public/cpp/platform/platform_handle.h
@@ -9,11 +9,12 @@
#include "base/logging.h"
#include "base/macros.h"
#include "build/build_config.h"
+#include "mojo/public/c/system/platform_handle.h"
#if defined(OS_WIN)
#include "base/win/scoped_handle.h"
#elif defined(OS_FUCHSIA)
-#include "base/fuchsia/scoped_zx_handle.h"
+#include <lib/zx/handle.h>
#elif defined(OS_MACOSX) && !defined(OS_IOS)
#include "base/mac/scoped_mach_port.h"
#endif
@@ -40,13 +41,25 @@ namespace mojo {
// NOTE: This assumes ownership if the handle it represents.
class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformHandle {
public:
+ enum class Type {
+ kNone,
+#if defined(OS_WIN) || defined(OS_FUCHSIA)
+ kHandle,
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ kMachPort,
+#endif
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+ kFd,
+#endif
+ };
+
PlatformHandle();
PlatformHandle(PlatformHandle&& other);
#if defined(OS_WIN)
explicit PlatformHandle(base::win::ScopedHandle handle);
#elif defined(OS_FUCHSIA)
- explicit PlatformHandle(base::ScopedZxHandle handle);
+ explicit PlatformHandle(zx::handle handle);
#elif defined(OS_MACOSX) && !defined(OS_IOS)
explicit PlatformHandle(base::mac::ScopedMachSendRight mach_port);
#endif
@@ -59,36 +72,76 @@ class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformHandle {
PlatformHandle& operator=(PlatformHandle&& other);
+ // Takes ownership of |handle|'s underlying platform handle and fills in
+ // |mojo_handle| with a representation of it. The caller assumes ownership of
+ // the platform handle.
+ static void ToMojoPlatformHandle(PlatformHandle handle,
+ MojoPlatformHandle* mojo_handle);
+
// Closes the underlying platform handle.
+ // Assumes ownership of the platform handle described by |handle|, and returns
+ // it as a new PlatformHandle.
+ static PlatformHandle FromMojoPlatformHandle(
+ const MojoPlatformHandle* handle);
+
+ Type type() const { return type_; }
+
void reset();
+ // Relinquishes ownership of the underlying handle, regardless of type, and
+ // discards its value. To release and obtain the underlying handle value, use
+ // one of the specific |Release*()| methods below.
+ void release();
+
// Duplicates the underlying platform handle, returning a new PlatformHandle
// which owns it.
PlatformHandle Clone() const;
#if defined(OS_WIN)
- bool is_valid() const { return handle_.IsValid(); }
+ bool is_valid() const { return is_valid_handle(); }
+ bool is_valid_handle() const { return handle_.IsValid(); }
+ bool is_handle() const { return type_ == Type::kHandle; }
const base::win::ScopedHandle& GetHandle() const { return handle_; }
- base::win::ScopedHandle TakeHandle() { return std::move(handle_); }
- HANDLE ReleaseHandle() WARN_UNUSED_RESULT { return handle_.Take(); }
+ base::win::ScopedHandle TakeHandle() {
+ DCHECK_EQ(type_, Type::kHandle);
+ type_ = Type::kNone;
+ return std::move(handle_);
+ }
+ HANDLE ReleaseHandle() WARN_UNUSED_RESULT {
+ DCHECK_EQ(type_, Type::kHandle);
+ type_ = Type::kNone;
+ return handle_.Take();
+ }
#elif defined(OS_FUCHSIA)
bool is_valid() const { return is_valid_fd() || is_valid_handle(); }
-
bool is_valid_handle() const { return handle_.is_valid(); }
- const base::ScopedZxHandle& GetHandle() const { return handle_; }
- base::ScopedZxHandle TakeHandle() { return std::move(handle_); }
- zx_handle_t ReleaseHandle() WARN_UNUSED_RESULT { return handle_.release(); }
+ bool is_handle() const { return type_ == Type::kHandle; }
+ const zx::handle& GetHandle() const { return handle_; }
+ zx::handle TakeHandle() {
+ if (type_ == Type::kHandle)
+ type_ = Type::kNone;
+ return std::move(handle_);
+ }
+ zx_handle_t ReleaseHandle() WARN_UNUSED_RESULT {
+ if (type_ == Type::kHandle)
+ type_ = Type::kNone;
+ return handle_.release();
+ }
#elif defined(OS_MACOSX) && !defined(OS_IOS)
bool is_valid() const { return is_valid_fd() || is_valid_mach_port(); }
-
bool is_valid_mach_port() const { return mach_port_.is_valid(); }
+ bool is_mach_port() const { return type_ == Type::kMachPort; }
const base::mac::ScopedMachSendRight& GetMachPort() const {
return mach_port_;
}
base::mac::ScopedMachSendRight TakeMachPort() {
+ if (type_ == Type::kMachPort)
+ type_ = Type::kNone;
return std::move(mach_port_);
}
mach_port_t ReleaseMachPort() WARN_UNUSED_RESULT {
+ if (type_ == Type::kMachPort)
+ type_ = Type::kNone;
return mach_port_.release();
}
#elif defined(OS_POSIX)
@@ -99,16 +152,27 @@ class COMPONENT_EXPORT(MOJO_CPP_PLATFORM) PlatformHandle {
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
bool is_valid_fd() const { return fd_.is_valid(); }
+ bool is_fd() const { return type_ == Type::kFd; }
const base::ScopedFD& GetFD() const { return fd_; }
- base::ScopedFD TakeFD() { return std::move(fd_); }
- int ReleaseFD() WARN_UNUSED_RESULT { return fd_.release(); }
+ base::ScopedFD TakeFD() {
+ if (type_ == Type::kFd)
+ type_ = Type::kNone;
+ return std::move(fd_);
+ }
+ int ReleaseFD() WARN_UNUSED_RESULT {
+ if (type_ == Type::kFd)
+ type_ = Type::kNone;
+ return fd_.release();
+ }
#endif
private:
+ Type type_ = Type::kNone;
+
#if defined(OS_WIN)
base::win::ScopedHandle handle_;
#elif defined(OS_FUCHSIA)
- base::ScopedZxHandle handle_;
+ zx::handle handle_;
#elif defined(OS_MACOSX) && !defined(OS_IOS)
base::mac::ScopedMachSendRight mach_port_;
#endif
diff --git a/chromium/mojo/public/cpp/platform/socket_utils_posix.cc b/chromium/mojo/public/cpp/platform/socket_utils_posix.cc
new file mode 100644
index 00000000000..4bbdcb754bb
--- /dev/null
+++ b/chromium/mojo/public/cpp/platform/socket_utils_posix.cc
@@ -0,0 +1,194 @@
+// Copyright 2018 The Chromium 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/platform/socket_utils_posix.h"
+
+#include <stddef.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#if !defined(OS_NACL)
+#include <sys/uio.h>
+#endif
+
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "build/build_config.h"
+
+namespace mojo {
+
+namespace {
+
+#if !defined(OS_NACL)
+bool IsRecoverableError() {
+ return errno == ECONNABORTED || errno == EMFILE || errno == ENFILE ||
+ errno == ENOMEM || errno == ENOBUFS;
+}
+
+bool GetPeerEuid(base::PlatformFile fd, uid_t* peer_euid) {
+#if defined(OS_MACOSX) || defined(OS_OPENBSD) || defined(OS_FREEBSD)
+ uid_t socket_euid;
+ gid_t socket_gid;
+ if (getpeereid(fd, &socket_euid, &socket_gid) < 0) {
+ PLOG(ERROR) << "getpeereid " << fd;
+ return false;
+ }
+ *peer_euid = socket_euid;
+ return true;
+#else
+ struct ucred cred;
+ socklen_t cred_len = sizeof(cred);
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) < 0) {
+ PLOG(ERROR) << "getsockopt " << fd;
+ return false;
+ }
+ if (static_cast<unsigned>(cred_len) < sizeof(cred)) {
+ NOTREACHED() << "Truncated ucred from SO_PEERCRED?";
+ return false;
+ }
+ *peer_euid = cred.uid;
+ return true;
+#endif
+}
+
+bool IsPeerAuthorized(base::PlatformFile fd) {
+ uid_t peer_euid;
+ if (!GetPeerEuid(fd, &peer_euid))
+ return false;
+ if (peer_euid != geteuid()) {
+ DLOG(ERROR) << "Client euid is not authorized";
+ return false;
+ }
+ return true;
+}
+#endif // !defined(OS_NACL)
+
+// NOTE: On Linux |SIGPIPE| is suppressed by passing |MSG_NOSIGNAL| to
+// |sendmsg()|. On Mac we instead set |SO_NOSIGPIPE| on the socket itself.
+#if defined(OS_MACOSX)
+constexpr int kSendmsgFlags = 0;
+#else
+constexpr int kSendmsgFlags = MSG_NOSIGNAL;
+#endif
+
+constexpr size_t kMaxSendmsgHandles = 128;
+
+} // namespace
+
+ssize_t SocketWrite(base::PlatformFile socket,
+ const void* bytes,
+ size_t num_bytes) {
+#if defined(OS_MACOSX) || defined(OS_NACL_NONSFI)
+ return HANDLE_EINTR(write(socket, bytes, num_bytes));
+#else
+ return send(socket, bytes, num_bytes, kSendmsgFlags);
+#endif
+}
+
+ssize_t SocketWritev(base::PlatformFile socket,
+ struct iovec* iov,
+ size_t num_iov) {
+#if defined(OS_MACOSX)
+ return HANDLE_EINTR(writev(socket, iov, static_cast<int>(num_iov)));
+#else
+ struct msghdr msg = {};
+ msg.msg_iov = iov;
+ msg.msg_iovlen = num_iov;
+ return HANDLE_EINTR(sendmsg(socket, &msg, kSendmsgFlags));
+#endif
+}
+
+ssize_t SendmsgWithHandles(base::PlatformFile socket,
+ struct iovec* iov,
+ size_t num_iov,
+ const std::vector<base::ScopedFD>& descriptors) {
+ DCHECK(iov);
+ DCHECK_GT(num_iov, 0u);
+ DCHECK(!descriptors.empty());
+ DCHECK_LE(descriptors.size(), kMaxSendmsgHandles);
+
+ char cmsg_buf[CMSG_SPACE(kMaxSendmsgHandles * sizeof(int))];
+ struct msghdr msg = {};
+ msg.msg_iov = iov;
+ msg.msg_iovlen = num_iov;
+ msg.msg_control = cmsg_buf;
+ msg.msg_controllen = CMSG_LEN(descriptors.size() * sizeof(int));
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(descriptors.size() * sizeof(int));
+ for (size_t i = 0; i < descriptors.size(); ++i) {
+ DCHECK_GE(descriptors[i].get(), 0);
+ reinterpret_cast<int*>(CMSG_DATA(cmsg))[i] = descriptors[i].get();
+ }
+ return HANDLE_EINTR(sendmsg(socket, &msg, kSendmsgFlags));
+}
+
+ssize_t SocketRecvmsg(base::PlatformFile socket,
+ void* buf,
+ size_t num_bytes,
+ std::vector<base::ScopedFD>* descriptors,
+ bool block) {
+ struct iovec iov = {buf, num_bytes};
+ char cmsg_buf[CMSG_SPACE(kMaxSendmsgHandles * sizeof(int))];
+ struct msghdr msg = {};
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsg_buf;
+ msg.msg_controllen = sizeof(cmsg_buf);
+ ssize_t result =
+ HANDLE_EINTR(recvmsg(socket, &msg, block ? 0 : MSG_DONTWAIT));
+ if (result < 0)
+ return result;
+
+ if (msg.msg_controllen == 0)
+ return result;
+
+ DCHECK(!(msg.msg_flags & MSG_CTRUNC));
+
+ descriptors->clear();
+ for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ size_t payload_length = cmsg->cmsg_len - CMSG_LEN(0);
+ DCHECK_EQ(payload_length % sizeof(int), 0u);
+ size_t num_fds = payload_length / sizeof(int);
+ const int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+ for (size_t i = 0; i < num_fds; ++i) {
+ base::ScopedFD fd(fds[i]);
+ DCHECK(fd.is_valid());
+ descriptors->emplace_back(std::move(fd));
+ }
+ }
+ }
+
+ return result;
+}
+
+bool AcceptSocketConnection(base::PlatformFile server_fd,
+ base::ScopedFD* connection_fd,
+ bool check_peer_user) {
+ DCHECK_GE(server_fd, 0);
+ connection_fd->reset();
+#if defined(OS_NACL)
+ NOTREACHED();
+ return false;
+#else
+ base::ScopedFD accepted_handle(HANDLE_EINTR(accept(server_fd, nullptr, 0)));
+ if (!accepted_handle.is_valid())
+ return IsRecoverableError();
+ if (check_peer_user && !IsPeerAuthorized(accepted_handle.get()))
+ return true;
+ if (!base::SetNonBlocking(accepted_handle.get())) {
+ PLOG(ERROR) << "base::SetNonBlocking() failed " << accepted_handle.get();
+ return true;
+ }
+
+ *connection_fd = std::move(accepted_handle);
+ return true;
+#endif // defined(OS_NACL)
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/platform/socket_utils_posix.h b/chromium/mojo/public/cpp/platform/socket_utils_posix.h
new file mode 100644
index 00000000000..e512f1bc807
--- /dev/null
+++ b/chromium/mojo/public/cpp/platform/socket_utils_posix.h
@@ -0,0 +1,80 @@
+// Copyright 2018 The Chromium 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_PLATFORM_SOCKET_UTILS_POSIX_H_
+#define MOJO_PUBLIC_CPP_PLATFORM_SOCKET_UTILS_POSIX_H_
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#include "base/component_export.h"
+#include "base/files/platform_file.h"
+#include "base/files/scoped_file.h"
+#include "base/logging.h"
+#include "base/macros.h"
+
+struct iovec; // Declared in <sys/uio.h>
+
+namespace mojo {
+
+// NOTE: Functions declared here really don't belong in Mojo, but they exist to
+// support code which used to rely on internal parts of the Mojo implementation
+// and there wasn't a much better home for them. Consider moving them to
+// src/base or something.
+
+// Like |write()| but handles |EINTR| and never raises |SIGPIPE|.
+COMPONENT_EXPORT(MOJO_CPP_PLATFORM)
+ssize_t SocketWrite(base::PlatformFile socket,
+ const void* bytes,
+ size_t num_bytes);
+
+// Like |writev()| but handles |EINTR| and never raises |SIGPIPE|.
+COMPONENT_EXPORT(MOJO_CPP_PLATFORM)
+ssize_t SocketWritev(base::PlatformFile socket,
+ struct iovec* iov,
+ size_t num_iov);
+
+// Wrapper around |sendmsg()| which makes it convenient to send attached file
+// descriptors. All entries in |descriptors| must be valid and |descriptors|
+// must be non-empty.
+//
+// Returns the same value as |sendmsg()|, i.e. -1 on error and otherwise the
+// number of bytes sent. Note that the number of bytes sent may be smaller
+// than the total data in |iov|.
+//
+// Note that regardless of success or failure, descriptors in |descriptors| are
+// not closed.
+COMPONENT_EXPORT(MOJO_CPP_PLATFORM)
+ssize_t SendmsgWithHandles(base::PlatformFile socket,
+ struct iovec* iov,
+ size_t num_iov,
+ const std::vector<base::ScopedFD>& descriptors);
+
+// Like |recvmsg()|, but handles |EINTR|.
+COMPONENT_EXPORT(MOJO_CPP_PLATFORM)
+ssize_t SocketRecvmsg(base::PlatformFile socket,
+ void* buf,
+ size_t num_bytes,
+ std::vector<base::ScopedFD>* descriptors,
+ bool block = false);
+
+// Treats |server_fd| as a socket listening for new connections. Returns |false|
+// if it encounters an unrecoverable error.
+//
+// If a connection wasn't established but the server is still OK, this returns
+// |true| and leaves |*connection_fd| unchanged.
+//
+// If a connection was accepted, this returns |true| and |*connection_fd| is
+// updated with a file descriptor for the new connection.
+//
+// Iff |check_peer_user| is |true|, connecting clients running as a different
+// user from the server (i.e. the calling process) will be rejected.
+COMPONENT_EXPORT(MOJO_CPP_PLATFORM)
+bool AcceptSocketConnection(base::PlatformFile server_fd,
+ base::ScopedFD* connection_fd,
+ bool check_peer_user = true);
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_PLATFORM_SOCKET_UTILS_POSIX_H_
diff --git a/chromium/mojo/public/cpp/system/BUILD.gn b/chromium/mojo/public/cpp/system/BUILD.gn
index bf9cecb9b25..155ac14ab3a 100644
--- a/chromium/mojo/public/cpp/system/BUILD.gn
+++ b/chromium/mojo/public/cpp/system/BUILD.gn
@@ -38,6 +38,10 @@ component("system") {
"handle_signal_tracker.cc",
"handle_signal_tracker.h",
"handle_signals_state.h",
+ "invitation.cc",
+ "invitation.h",
+ "isolated_connection.cc",
+ "isolated_connection.h",
"message.h",
"message_pipe.cc",
"message_pipe.h",
diff --git a/chromium/mojo/public/cpp/system/README.md b/chromium/mojo/public/cpp/system/README.md
index bb61bae931b..0e6d72df97f 100644
--- a/chromium/mojo/public/cpp/system/README.md
+++ b/chromium/mojo/public/cpp/system/README.md
@@ -23,7 +23,8 @@ top-level `mojo` namespace.
All types of Mojo handles in the C API are simply opaque, integral `MojoHandle`
values. The C++ API has more strongly typed wrappers defined for different
handle types: `MessagePipeHandle`, `SharedBufferHandle`,
-`DataPipeConsumerHandle`, `DataPipeProducerHandle`, and `WatcherHandle`.
+`DataPipeConsumerHandle`, `DataPipeProducerHandle`, `TrapHandle`, and
+`InvitationHandle`.
Each of these also has a corresponding, move-only, scoped type for safer usage:
`ScopedMessagePipeHandle`, `ScopedSharedBufferHandle`, and so on. When a scoped
@@ -160,15 +161,17 @@ for detailed C++ shared buffer API documentation.
The C++ library provides several helpers for wrapping system handle types.
These are specifically useful when working with a few `//base` types, namely
-`base::PlatformFile` and `base::SharedMemoryHandle`. See
+`base::PlatformFile`, `base::SharedMemoryHandle` (deprecated), and various
+strongly-typed shared memory region types like
+`base::ReadOnlySharedMemoryRegion`. See
[platform_handle.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/platform_handle.h)
for detailed C++ platform handle API documentation.
-## Signals & Watchers
+## Signals & Traps
-For an introduction to the concepts of handle signals and watchers, check out
+For an introduction to the concepts of handle signals and traps, check out
the C API's documentation on
-[Signals & Watchers](/mojo/public/c/system/README.md#Signals-Watchers).
+[Signals & Traps](/mojo/public/c/system/README.md#Signals-Traps).
### Querying Signals
@@ -206,7 +209,7 @@ if (message_pipe.handle0->QuerySignalsState().readable()) {
The [`mojo::SimpleWatcher`](https://cs.chromium.org/chromium/src/mojo/public/cpp/system/simple_watcher.h)
class serves as a convenient helper for using the
-[low-level watcher API](/mojo/public/c/system/README.md#Signals-Watchers)
+[low-level traps API](/mojo/public/c/system/README.md#Signals-Traps)
to watch a handle for signaling state changes. A `SimpleWatcher` is bound to a
single sequence and always dispatches its notifications on a
`base::SequencedTaskRunner`.
@@ -218,7 +221,7 @@ time by the `mojo::SimpleWatcher::ArmingPolicy` enum:
before any notifications will fire regarding the state of the watched handle.
Every time the notification callback is run, the `SimpleWatcher` must be
rearmed again before the next one can fire. See
- [Arming a Watcher](/mojo/public/c/system/README.md#Arming-a-Watcher) and the
+ [Arming a Trap](/mojo/public/c/system/README.md#Arming-a-Trap) and the
documentation in `SimpleWatcher`'s header.
* `AUTOMATIC` mode ensures that the `SimpleWatcher` always either is armed or
@@ -274,7 +277,7 @@ WriteABunchOfStuff(pipe.handle1.get());
The C++ System API defines some utilities to block a calling sequence while
waiting for one or more handles to change signaling state in an interesting way.
These threads combine usage of the
-[low-level Watcher API](/mojo/public/c/system/README.md#Signals-Watchers)
+[low-level traps API](/mojo/public/c/system/README.md#Signals-Traps)
with common synchronization primitives (namely `base::WaitableEvent`.)
While these API features should be used sparingly, they are sometimes necessary.
@@ -388,3 +391,150 @@ if (num_ready_handles > 0) {
// signaling races with timeout, both things might be true.
}
```
+
+## Invitations
+Invitations are the means by which two processes can have Mojo IPC bootstrapped
+between them. An invitation must be transmitted over some platform-specific IPC
+primitive (*e.g.* a Windows named pipe or UNIX domain socket), and the public
+[platform support library](/mojo/public/cpp/platform/README.md) provides some
+lightweight, cross-platform abstractions for those primitives.
+
+For any two processes looking to be connected, one must send an
+`OutgoingInvitation` and the other must accept an `IncomingInvitation`. The
+sender can attach named message pipe handles to the `OutgoingInvitation`, and
+the receiver can extract them from its `IncomingInvitation`.
+
+Basic usage might look something like this in the case where one process is
+responsible for launching the other.
+
+``` cpp
+#include "base/command_line.h"
+#include "base/process/launch.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/system/invitation.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+mojo::ScopedMessagePipeHandle LaunchAndConnectSomething() {
+ // Under the hood, this is essentially always an OS pipe (domain socket pair,
+ // Windows named pipe, Fuchsia channel, etc).
+ mojo::PlatformChannel channel;
+
+ mojo::OutgoingInvitation invitation;
+
+ // Attach a message pipe to be extracted by the receiver. The other end of the
+ // pipe is returned for us to use locally.
+ mojo::ScopedMessagePipeHandle pipe =
+ invitation->AttachMessagePipe("arbitrary pipe name");
+
+ base::LaunchOptions options;
+ base::CommandLine command_line("some_executable")
+ channel.PrepareToPassRemoteEndpoint(&options, &command_line);
+ base::Process child_process = base::LaunchProcess(command_line, options);
+ channel.RemoteProcessLaunchAttempted();
+
+ OutgoingInvitation::Send(std::move(invitation), child_process.Handle(),
+ channel.TakeLocalEndpoint());
+ return pipe;
+}
+```
+
+The launched process can in turn accept an `IncomingInvitation`:
+
+``` cpp
+#include "base/command_line.h"
+#include "base/threading/thread.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/embedder/scoped_ipc_support.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/system/invitation.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+int main(int argc, char** argv) {
+ // Basic Mojo initialization for a new process.
+ mojo::core::Init();
+ base::Thread ipc_thread("ipc!");
+ ipc_thread.StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+ mojo::core::ScopedIPCSupport ipc_support(
+ ipc_thread.task_runner(),
+ mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
+
+ // Accept an invitation.
+ mojo::IncomingInvitation invitation = mojo::IncomingInvitation::Accept(
+ mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(
+ *base::CommandLine::ForCurrentProcess()));
+ mojo::ScopedMessagePipeHandle pipe =
+ invitation->ExtractMessagePipe("arbitrary pipe name");
+
+ // etc...
+ return GoListenForMessagesAndRunForever(std::move(pipe));
+}
+```
+
+Now we have IPC initialized between the two processes.
+
+Also keep in mind that bindings interfaces are just message pipes with some
+semantic and syntactic sugar wrapping them, so you can use these primordial
+message pipe handles as mojom interfaces. For example:
+
+``` cpp
+// Process A
+mojo::OutgoingInvitation invitation;
+auto pipe = invitation->AttachMessagePipe("x");
+mojo::Binding<foo::mojom::Bar> binding(
+ &bar_impl,
+ foo::mojom::BarRequest(std::move(pipe)));
+
+// Process B
+auto invitation = mojo::IncomingInvitation::Accept(...);
+auto pipe = invitation->ExtractMessagePipe("x");
+foo::mojom::BarPtr bar(foo::mojom::BarPtrInfo(std::move(pipe), 0));
+
+// Will asynchronously invoke bar_impl.DoSomething() in process A.
+bar->DoSomething();
+```
+
+And just to be sure, the usage here could be reversed: the invitation sender
+could just as well treat its pipe endpoint as a `BarPtr` while the receiver
+treats theirs as a `BarRequest` to be bound.
+
+### Process Networks
+Accepting an invitation admits the accepting process into the sender's connected
+network of processes. Once this is done, it's possible for the newly admitted
+process to establish communication with any other process in that network via
+normal message pipe passing.
+
+This does not mean that the invited process can proactively locate and connect
+to other processes without assistance; rather it means that Mojo handles created
+by the process can safely be transferred to any other process in the network
+over established message pipes, and similarly that Mojo handles created by any
+other process in the network can be safely passed to the newly admitted process.
+
+### Invitation Restrictions
+A process may only belong to a single network at a time.
+
+Additionally, once a process has joined a network, it cannot join another for
+the remainder of its lifetime even if it has lost the connection to its original
+network. This restriction will soon be lifted, but for now developers must be
+mindful of it when authoring any long-running daemon process that will accept an
+incoming invitation.
+
+### Isolated Invitations
+It is possible to have two independent networks of Mojo-connected processes; for
+example, a long-running system daemon which uses Mojo to talk to child processes
+of its own, as well as the Chrome browser process running with no common
+ancestor, talking to its own child processes.
+
+In this scenario it may be desirable to have a process in one network talk to a
+process in the other network. Normal invitations cannot be used here since both
+processes already belong to a network. In this case, an **isolated** invitation
+can be used. These work just like regular invitations, except the sender must
+call `OutgoingInvitation::SendIsolated` and the receiver must call
+`IncomingInvitation::AcceptIsolated`.
+
+Once a connection is established via isolated invitation, Mojo IPC can be used
+normally, with the exception that transitive process connections are not
+supported; that is, if process A sends a message pipe handle to process B via
+an isolated connection, process B cannot reliably send that pipe handle onward
+to another process in its own network. Isolated invitations therefore may only
+be used to facilitate direct 1:1 communication between two processes.
diff --git a/chromium/mojo/public/cpp/system/handle_signals_state.h b/chromium/mojo/public/cpp/system/handle_signals_state.h
index 4c658f3d858..3eb295beccf 100644
--- a/chromium/mojo/public/cpp/system/handle_signals_state.h
+++ b/chromium/mojo/public/cpp/system/handle_signals_state.h
@@ -67,6 +67,11 @@ struct MOJO_CPP_SYSTEM_EXPORT HandleSignalsState final
return satisfies_any(MOJO_HANDLE_SIGNAL_PEER_REMOTE);
}
+ // Indicates whether the handle has exceeded some quota limit.
+ bool quota_exceeded() const {
+ return satisfies_any(MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
+ }
+
// The handle will never be |readable()| again.
bool never_readable() const {
return !can_satisfy_any(MOJO_HANDLE_SIGNAL_READABLE);
diff --git a/chromium/mojo/public/cpp/system/invitation.cc b/chromium/mojo/public/cpp/system/invitation.cc
new file mode 100644
index 00000000000..f70c435e955
--- /dev/null
+++ b/chromium/mojo/public/cpp/system/invitation.cc
@@ -0,0 +1,286 @@
+// Copyright 2018 The Chromium 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/system/invitation.h"
+
+#include "base/numerics/safe_conversions.h"
+#include "build/build_config.h"
+#include "mojo/public/c/system/invitation.h"
+#include "mojo/public/c/system/platform_handle.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+
+namespace mojo {
+
+namespace {
+
+static constexpr base::StringPiece kIsolatedPipeName = {"\0\0\0\0", 4};
+
+void ProcessHandleToMojoProcessHandle(base::ProcessHandle target_process,
+ MojoPlatformProcessHandle* handle) {
+ handle->struct_size = sizeof(*handle);
+#if defined(OS_WIN)
+ handle->value =
+ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(target_process));
+#else
+ handle->value = static_cast<uint64_t>(target_process);
+#endif
+}
+
+void PlatformHandleToTransportEndpoint(
+ PlatformHandle platform_handle,
+ MojoPlatformHandle* endpoint_handle,
+ MojoInvitationTransportEndpoint* endpoint) {
+ PlatformHandle::ToMojoPlatformHandle(std::move(platform_handle),
+ endpoint_handle);
+ CHECK_NE(endpoint_handle->type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
+
+ endpoint->struct_size = sizeof(*endpoint);
+ endpoint->num_platform_handles = 1;
+ endpoint->platform_handles = endpoint_handle;
+}
+
+void RunErrorCallback(uintptr_t context,
+ const MojoProcessErrorDetails* details) {
+ auto* callback = reinterpret_cast<ProcessErrorCallback*>(context);
+ std::string error_message;
+ if (details->error_message) {
+ error_message =
+ std::string(details->error_message, details->error_message_length - 1);
+ callback->Run(error_message);
+ } else if (details->flags & MOJO_PROCESS_ERROR_FLAG_DISCONNECTED) {
+ delete callback;
+ }
+}
+
+void SendInvitation(ScopedInvitationHandle invitation,
+ base::ProcessHandle target_process,
+ PlatformHandle endpoint_handle,
+ MojoInvitationTransportType transport_type,
+ MojoSendInvitationFlags flags,
+ const ProcessErrorCallback& error_callback,
+ base::StringPiece isolated_connection_name) {
+ MojoPlatformProcessHandle process_handle;
+ ProcessHandleToMojoProcessHandle(target_process, &process_handle);
+
+ MojoPlatformHandle platform_handle;
+ MojoInvitationTransportEndpoint endpoint;
+ PlatformHandleToTransportEndpoint(std::move(endpoint_handle),
+ &platform_handle, &endpoint);
+ endpoint.type = transport_type;
+
+ MojoProcessErrorHandler error_handler = nullptr;
+ uintptr_t error_handler_context = 0;
+ if (error_callback) {
+ error_handler = &RunErrorCallback;
+
+ // NOTE: The allocated callback is effectively owned by the error handler,
+ // which will delete it on the final invocation for this context (i.e.
+ // process disconnection).
+ error_handler_context =
+ reinterpret_cast<uintptr_t>(new ProcessErrorCallback(error_callback));
+ }
+
+ MojoSendInvitationOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = flags;
+ if (flags & MOJO_SEND_INVITATION_FLAG_ISOLATED) {
+ options.isolated_connection_name = isolated_connection_name.data();
+ options.isolated_connection_name_length =
+ static_cast<uint32_t>(isolated_connection_name.size());
+ }
+ MojoResult result =
+ MojoSendInvitation(invitation.get().value(), &process_handle, &endpoint,
+ error_handler, error_handler_context, &options);
+ // If successful, the invitation handle is already closed for us.
+ if (result == MOJO_RESULT_OK)
+ ignore_result(invitation.release());
+}
+
+} // namespace
+
+OutgoingInvitation::OutgoingInvitation() {
+ MojoHandle invitation_handle;
+ MojoResult result = MojoCreateInvitation(nullptr, &invitation_handle);
+ DCHECK_EQ(result, MOJO_RESULT_OK);
+
+ handle_.reset(InvitationHandle(invitation_handle));
+}
+
+OutgoingInvitation::OutgoingInvitation(OutgoingInvitation&& other) = default;
+
+OutgoingInvitation::~OutgoingInvitation() = default;
+
+OutgoingInvitation& OutgoingInvitation::operator=(OutgoingInvitation&& other) =
+ default;
+
+ScopedMessagePipeHandle OutgoingInvitation::AttachMessagePipe(
+ base::StringPiece name) {
+ DCHECK(!name.empty());
+ DCHECK(base::IsValueInRangeForNumericType<uint32_t>(name.size()));
+ MojoHandle message_pipe_handle;
+ MojoResult result = MojoAttachMessagePipeToInvitation(
+ handle_.get().value(), name.data(), static_cast<uint32_t>(name.size()),
+ nullptr, &message_pipe_handle);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ return ScopedMessagePipeHandle(MessagePipeHandle(message_pipe_handle));
+}
+
+ScopedMessagePipeHandle OutgoingInvitation::AttachMessagePipe(uint64_t name) {
+ return AttachMessagePipe(
+ base::StringPiece(reinterpret_cast<const char*>(&name), sizeof(name)));
+}
+
+ScopedMessagePipeHandle OutgoingInvitation::ExtractMessagePipe(
+ base::StringPiece name) {
+ DCHECK(!name.empty());
+ DCHECK(base::IsValueInRangeForNumericType<uint32_t>(name.size()));
+ MojoHandle message_pipe_handle;
+ MojoResult result = MojoExtractMessagePipeFromInvitation(
+ handle_.get().value(), name.data(), static_cast<uint32_t>(name.size()),
+ nullptr, &message_pipe_handle);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ return ScopedMessagePipeHandle(MessagePipeHandle(message_pipe_handle));
+}
+
+ScopedMessagePipeHandle OutgoingInvitation::ExtractMessagePipe(uint64_t name) {
+ return ExtractMessagePipe(
+ base::StringPiece(reinterpret_cast<const char*>(&name), sizeof(name)));
+}
+
+// static
+void OutgoingInvitation::Send(OutgoingInvitation invitation,
+ base::ProcessHandle target_process,
+ PlatformChannelEndpoint channel_endpoint,
+ const ProcessErrorCallback& error_callback) {
+ SendInvitation(std::move(invitation.handle_), target_process,
+ channel_endpoint.TakePlatformHandle(),
+ MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL,
+ MOJO_SEND_INVITATION_FLAG_NONE, error_callback, "");
+}
+
+// static
+void OutgoingInvitation::Send(OutgoingInvitation invitation,
+ base::ProcessHandle target_process,
+ PlatformChannelServerEndpoint server_endpoint,
+ const ProcessErrorCallback& error_callback) {
+ SendInvitation(std::move(invitation.handle_), target_process,
+ server_endpoint.TakePlatformHandle(),
+ MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER,
+ MOJO_SEND_INVITATION_FLAG_NONE, error_callback, "");
+}
+
+// static
+ScopedMessagePipeHandle OutgoingInvitation::SendIsolated(
+ PlatformChannelEndpoint channel_endpoint,
+ base::StringPiece connection_name) {
+ mojo::OutgoingInvitation invitation;
+ ScopedMessagePipeHandle pipe =
+ invitation.AttachMessagePipe(kIsolatedPipeName);
+ SendInvitation(std::move(invitation.handle_), base::kNullProcessHandle,
+ channel_endpoint.TakePlatformHandle(),
+ MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL,
+ MOJO_SEND_INVITATION_FLAG_ISOLATED, ProcessErrorCallback(),
+ connection_name);
+ return pipe;
+}
+
+// static
+ScopedMessagePipeHandle OutgoingInvitation::SendIsolated(
+ PlatformChannelServerEndpoint server_endpoint,
+ base::StringPiece connection_name) {
+ mojo::OutgoingInvitation invitation;
+ ScopedMessagePipeHandle pipe =
+ invitation.AttachMessagePipe(kIsolatedPipeName);
+ SendInvitation(std::move(invitation.handle_), base::kNullProcessHandle,
+ server_endpoint.TakePlatformHandle(),
+ MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER,
+ MOJO_SEND_INVITATION_FLAG_ISOLATED, ProcessErrorCallback(),
+ connection_name);
+ return pipe;
+}
+
+IncomingInvitation::IncomingInvitation() = default;
+
+IncomingInvitation::IncomingInvitation(IncomingInvitation&& other) = default;
+
+IncomingInvitation::IncomingInvitation(ScopedInvitationHandle handle)
+ : handle_(std::move(handle)) {}
+
+IncomingInvitation::~IncomingInvitation() = default;
+
+IncomingInvitation& IncomingInvitation::operator=(IncomingInvitation&& other) =
+ default;
+
+// static
+IncomingInvitation IncomingInvitation::Accept(
+ PlatformChannelEndpoint channel_endpoint) {
+ MojoPlatformHandle endpoint_handle;
+ PlatformHandle::ToMojoPlatformHandle(channel_endpoint.TakePlatformHandle(),
+ &endpoint_handle);
+ CHECK_NE(endpoint_handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
+
+ MojoInvitationTransportEndpoint transport_endpoint;
+ transport_endpoint.struct_size = sizeof(transport_endpoint);
+ transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL;
+ transport_endpoint.num_platform_handles = 1;
+ transport_endpoint.platform_handles = &endpoint_handle;
+
+ MojoHandle invitation_handle;
+ MojoResult result =
+ MojoAcceptInvitation(&transport_endpoint, nullptr, &invitation_handle);
+ if (result != MOJO_RESULT_OK)
+ return IncomingInvitation();
+
+ return IncomingInvitation(
+ ScopedInvitationHandle(InvitationHandle(invitation_handle)));
+}
+
+// static
+ScopedMessagePipeHandle IncomingInvitation::AcceptIsolated(
+ PlatformChannelEndpoint channel_endpoint) {
+ MojoPlatformHandle endpoint_handle;
+ PlatformHandle::ToMojoPlatformHandle(channel_endpoint.TakePlatformHandle(),
+ &endpoint_handle);
+ CHECK_NE(endpoint_handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
+
+ MojoInvitationTransportEndpoint transport_endpoint;
+ transport_endpoint.struct_size = sizeof(transport_endpoint);
+ transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL;
+ transport_endpoint.num_platform_handles = 1;
+ transport_endpoint.platform_handles = &endpoint_handle;
+
+ MojoAcceptInvitationOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = MOJO_ACCEPT_INVITATION_FLAG_ISOLATED;
+
+ MojoHandle invitation_handle;
+ MojoResult result =
+ MojoAcceptInvitation(&transport_endpoint, &options, &invitation_handle);
+ if (result != MOJO_RESULT_OK)
+ return ScopedMessagePipeHandle();
+
+ IncomingInvitation invitation{
+ ScopedInvitationHandle(InvitationHandle(invitation_handle))};
+ return invitation.ExtractMessagePipe(kIsolatedPipeName);
+}
+
+ScopedMessagePipeHandle IncomingInvitation::ExtractMessagePipe(
+ base::StringPiece name) {
+ DCHECK(!name.empty());
+ DCHECK(base::IsValueInRangeForNumericType<uint32_t>(name.size()));
+ DCHECK(handle_.is_valid());
+ MojoHandle message_pipe_handle;
+ MojoResult result = MojoExtractMessagePipeFromInvitation(
+ handle_.get().value(), name.data(), static_cast<uint32_t>(name.size()),
+ nullptr, &message_pipe_handle);
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ return ScopedMessagePipeHandle(MessagePipeHandle(message_pipe_handle));
+}
+
+ScopedMessagePipeHandle IncomingInvitation::ExtractMessagePipe(uint64_t name) {
+ return ExtractMessagePipe(
+ base::StringPiece(reinterpret_cast<const char*>(&name), sizeof(name)));
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/system/invitation.h b/chromium/mojo/public/cpp/system/invitation.h
new file mode 100644
index 00000000000..475a6735822
--- /dev/null
+++ b/chromium/mojo/public/cpp/system/invitation.h
@@ -0,0 +1,186 @@
+// Copyright 2018 The Chromium 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_INVITATION_H_
+#define MOJO_PUBLIC_CPP_SYSTEM_INVITATION_H_
+
+#include <cstdint>
+#include <string>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/process/process_handle.h"
+#include "base/strings/string_piece.h"
+#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
+#include "mojo/public/cpp/system/handle.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "mojo/public/cpp/system/system_export.h"
+
+namespace mojo {
+
+// A callback which may be provided when sending an invitation to another
+// process. In the event of any validation errors regarding messages from that
+// process (reported via MojoNotifyBadMessage etc and related helpers), the
+// callback will be invoked.
+using ProcessErrorCallback = base::RepeatingCallback<void(const std::string&)>;
+
+// A strongly-typed representation of a |MojoHandle| for an invitation.
+class InvitationHandle : public Handle {
+ public:
+ InvitationHandle() {}
+ explicit InvitationHandle(MojoHandle value) : Handle(value) {}
+
+ // Copying and assignment allowed.
+};
+
+static_assert(sizeof(InvitationHandle) == sizeof(Handle),
+ "Bad size for C++ InvitationHandle");
+
+using ScopedInvitationHandle = ScopedHandleBase<InvitationHandle>;
+static_assert(sizeof(ScopedInvitationHandle) == sizeof(InvitationHandle),
+ "Bad size for C++ ScopedInvitationHandle");
+
+// An OutgoingInvitation is used to invite another process to join the calling
+// process's IPC network.
+//
+// Typical use involves constructing a |PlatformChannel| and using one end to
+// send the invitation (see |Send()| below) while passing the other to a child
+// process.
+//
+// This may also be used with the server endpoint of a |NamedPlatformChannel|.
+class MOJO_CPP_SYSTEM_EXPORT OutgoingInvitation {
+ public:
+ OutgoingInvitation();
+ OutgoingInvitation(OutgoingInvitation&& other);
+ ~OutgoingInvitation();
+
+ OutgoingInvitation& operator=(OutgoingInvitation&& other);
+
+ // Creates a new message pipe, attaching one end to this invitation and
+ // returning the other end to the caller. The invitee can extract the
+ // attached endpoint (see |IncomingInvitation|) thus establishing end-to-end
+ // Mojo communication.
+ //
+ // |name| is an arbitrary value that must be used by the invitee to extract
+ // the corresponding attached endpoint.
+ ScopedMessagePipeHandle AttachMessagePipe(base::StringPiece name);
+
+ // Same as above but allows use of an integer name for convenience.
+ ScopedMessagePipeHandle AttachMessagePipe(uint64_t name);
+
+ // Extracts an attached pipe. Note that this is not typically useful, but it
+ // is potentially necessary in cases where a caller wants to, e.g., abort
+ // launching another process and recover a pipe endpoint they had previously
+ // attached.
+ ScopedMessagePipeHandle ExtractMessagePipe(base::StringPiece name);
+
+ // Same as above but allows use of an integer name for convenience.
+ ScopedMessagePipeHandle ExtractMessagePipe(uint64_t name);
+
+ // Sends |invitation| to another process via |channel_endpoint|, which should
+ // correspond to the local endpoint taken from a |PlatformChannel|.
+ //
+ // |process_handle| is a handle to the destination process if known. If not
+ // provided, IPC may be limited on some platforms (namely Mac and Windows) due
+ // to an inability to transfer system handles across the boundary.
+ static void Send(OutgoingInvitation invitation,
+ base::ProcessHandle target_process,
+ PlatformChannelEndpoint channel_endpoint,
+ const ProcessErrorCallback& error_callback = {});
+
+ // Similar to above, but sends |invitation| via |server_endpoint|, which
+ // should correspond to a |PlatformChannelServerEndpoint| taken from a
+ // |NamedPlatformChannel|.
+ static void Send(OutgoingInvitation invitation,
+ base::ProcessHandle target_process,
+ PlatformChannelServerEndpoint server_endpoint,
+ const ProcessErrorCallback& error_callback = {});
+
+ // Sends an isolated invitation over |endpoint|. The process at the other
+ // endpoint must use |IncomingInvitation::AcceptIsolated()| to accept the
+ // invitation.
+ //
+ // Isolated invitations must be used in lieu of regular invitations in cases
+ // where both of the processes being connected already belong to independent
+ // multiprocess graphs.
+ //
+ // Such connections are limited in functionality:
+ //
+ // * Platform handles may not be transferrable between the processes
+ //
+ // * Pipes sent between the processes may not be subsequently transferred to
+ // other processes in each others' process graph.
+ //
+ // Only one concurrent isolated connection is supported between any two
+ // processes.
+ //
+ // Unlike |Send()| above, isolated invitations automatically have a single
+ // message pipe attached and this is the only attachment allowed. The local
+ // end of the attached pipe is returned here.
+ //
+ // If |connection_name| is non-empty, any previously established isolated
+ // connection using the same name will be disconnected.
+ static ScopedMessagePipeHandle SendIsolated(
+ PlatformChannelEndpoint channel_endpoint,
+ base::StringPiece connection_name = {});
+
+ // Similar to above but sends |invitation| via |server_endpoint|, which should
+ // correspond to a |PlatformChannelServerEndpoint| taken from a
+ // |NamedPlatformChannel|.
+ //
+ // If |connection_name| is non-empty, any previously established isolated
+ // connection using the same name will be disconnected.
+ static ScopedMessagePipeHandle SendIsolated(
+ PlatformChannelServerEndpoint server_endpoint,
+ base::StringPiece connection_name = {});
+
+ private:
+ ScopedInvitationHandle handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(OutgoingInvitation);
+};
+
+// An IncomingInvitation can be accepted by an invited process by calling
+// |IncomingInvitation::Accept()|. Once accepted, the invitation can be used
+// to extract attached message pipes by name.
+class MOJO_CPP_SYSTEM_EXPORT IncomingInvitation {
+ public:
+ IncomingInvitation();
+ IncomingInvitation(IncomingInvitation&& other);
+ explicit IncomingInvitation(ScopedInvitationHandle handle);
+ ~IncomingInvitation();
+
+ IncomingInvitation& operator=(IncomingInvitation&& other);
+
+ // Accepts an incoming invitation from |channel_endpoint|. If the invitation
+ // was sent using one end of a |PlatformChannel|, |channel_endpoint| should be
+ // the other end of that channel. If the invitation was sent using a
+ // |PlatformChannelServerEndpoint|, then |channel_endpoint| should be created
+ // by |NamedPlatformChannel::ConnectToServer|.
+ static IncomingInvitation Accept(PlatformChannelEndpoint channel_endpoint);
+
+ // Accepts an incoming isolated invitation from |channel_endpoint|. See
+ // notes on |OutgoingInvitation::SendIsolated()|.
+ static ScopedMessagePipeHandle AcceptIsolated(
+ PlatformChannelEndpoint channel_endpoint);
+
+ // Extracts an attached message pipe from this invitation. This may succeed
+ // even if no such pipe was attached, though the extracted pipe will
+ // eventually observe peer closure.
+ ScopedMessagePipeHandle ExtractMessagePipe(base::StringPiece name);
+
+ // Same as above but allows use of an integer name for convenience.
+ ScopedMessagePipeHandle ExtractMessagePipe(uint64_t name);
+
+ private:
+ ScopedInvitationHandle handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(IncomingInvitation);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_SYSTEM_INVITATION_H_
diff --git a/chromium/mojo/public/cpp/system/isolated_connection.cc b/chromium/mojo/public/cpp/system/isolated_connection.cc
new file mode 100644
index 00000000000..f85be4e3d41
--- /dev/null
+++ b/chromium/mojo/public/cpp/system/isolated_connection.cc
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium 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/system/isolated_connection.h"
+
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/system/invitation.h"
+
+namespace mojo {
+
+IsolatedConnection::IsolatedConnection()
+ : token_(base::UnguessableToken::Create()) {}
+
+IsolatedConnection::~IsolatedConnection() {
+ // We send a dummy invitation over a temporary channel, re-using |token_| as
+ // the name. This ensures that the connection set up by Connect(), if any,
+ // will be replaced with a short-lived, self-terminating connection.
+ //
+ // This is a bit of a hack since Mojo does not provide any API for explicitly
+ // terminating isolated connections, but this is a decision made to minimize
+ // the API surface dedicated to isolated connections in anticipation of the
+ // concept being deprecated eventually.
+ PlatformChannel channel;
+ OutgoingInvitation::SendIsolated(channel.TakeLocalEndpoint(),
+ token_.ToString());
+}
+
+ScopedMessagePipeHandle IsolatedConnection::Connect(
+ PlatformChannelEndpoint endpoint) {
+ return OutgoingInvitation::SendIsolated(std::move(endpoint),
+ token_.ToString());
+}
+
+ScopedMessagePipeHandle IsolatedConnection::Connect(
+ PlatformChannelServerEndpoint endpoint) {
+ return OutgoingInvitation::SendIsolated(std::move(endpoint),
+ token_.ToString());
+}
+
+} // namespace mojo
diff --git a/chromium/mojo/public/cpp/system/isolated_connection.h b/chromium/mojo/public/cpp/system/isolated_connection.h
new file mode 100644
index 00000000000..42c90532ad8
--- /dev/null
+++ b/chromium/mojo/public/cpp/system/isolated_connection.h
@@ -0,0 +1,60 @@
+// Copyright 2018 The Chromium 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_ISOLATED_CONNECTION_H_
+#define MOJO_PUBLIC_CPP_SYSTEM_ISOLATED_CONNECTION_H_
+
+#include "base/macros.h"
+#include "base/unguessable_token.h"
+#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "mojo/public/cpp/system/system_export.h"
+
+namespace mojo {
+
+// IsolatedConnection establishes a one-off Mojo IPC connection between two
+// processes. Unlike more common connections established by invitation
+// (see OutgoingInvitation and IncomingInvitation), isolated connections
+// do not result in the two processes becoming part of the same connected
+// graph of processes. As such, any message pipe established over this
+// connection can only be used for direct IPC between the two processes in
+// question.
+//
+// This means that if one of the processes sends a Mojo handle (e.g. another
+// message pipe endpoint) to the other process, the receiving process cannot
+// pass that handle to yet another process in its own graph. This limitation is
+// subtle and can be difficult to work around, so use of IsolatedConnection
+// should be rare.
+//
+// This is primarily useful when you already have two established Mojo process
+// graphs isolated form each other, and you want to do some IPC between two
+// processes, one in each graph.
+//
+// A connection established via |Connect()|, and any opened message pipes
+// spanning that connection, will remain valid and connected as long as this
+// object remains alive.
+class MOJO_CPP_SYSTEM_EXPORT IsolatedConnection {
+ public:
+ IsolatedConnection();
+ ~IsolatedConnection();
+
+ // Connects to a process at the other end of the channel. Returns a primordial
+ // message pipe that can be used for Mojo IPC. The connection
+ // will be connected to a corresponding peer pipe in the remote process.
+ ScopedMessagePipeHandle Connect(PlatformChannelEndpoint endpoint);
+
+ // Same as above but works with a server endpoint. The corresponding client
+ // could use the above signature with NamedPlatformChannel::ConnectToServer.
+ ScopedMessagePipeHandle Connect(PlatformChannelServerEndpoint endpoint);
+
+ private:
+ const base::UnguessableToken token_;
+
+ DISALLOW_COPY_AND_ASSIGN(IsolatedConnection);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_SYSTEM_ISOLATED_CONNECTION_H_
diff --git a/chromium/mojo/public/cpp/system/platform_handle.cc b/chromium/mojo/public/cpp/system/platform_handle.cc
index 0ed2c15ca23..9e55f550b2f 100644
--- a/chromium/mojo/public/cpp/system/platform_handle.cc
+++ b/chromium/mojo/public/cpp/system/platform_handle.cc
@@ -179,75 +179,26 @@ base::subtle::PlatformSharedMemoryRegion UnwrapPlatformSharedMemoryRegion(
} // namespace
-void PlatformHandleToMojoPlatformHandle(PlatformHandle handle,
- MojoPlatformHandle* out_handle) {
- DCHECK(out_handle);
- out_handle->struct_size = sizeof(MojoPlatformHandle);
- if (!handle.is_valid()) {
- out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
- out_handle->value = 0;
- return;
- }
-
- do {
-#if defined(OS_WIN)
- out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
- out_handle->value =
- static_cast<uint64_t>(HandleToLong(handle.TakeHandle().Take()));
- break;
-#elif defined(OS_FUCHSIA)
- if (handle.is_valid_handle()) {
- out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE;
- out_handle->value = handle.TakeHandle().release();
- break;
- }
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
- if (handle.is_valid_mach_port()) {
- out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
- out_handle->value =
- static_cast<uint64_t>(handle.TakeMachPort().release());
- break;
- }
-#endif
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
- DCHECK(handle.is_valid_fd());
- out_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
- out_handle->value = static_cast<uint64_t>(handle.TakeFD().release());
-#endif
- } while (false);
+ScopedHandle WrapPlatformHandle(PlatformHandle handle) {
+ MojoPlatformHandle platform_handle;
+ PlatformHandle::ToMojoPlatformHandle(std::move(handle), &platform_handle);
- // One of the above cases must take ownership of |handle|.
- DCHECK(!handle.is_valid());
+ MojoHandle wrapped_handle;
+ MojoResult result =
+ MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle);
+ if (result != MOJO_RESULT_OK)
+ return ScopedHandle();
+ return ScopedHandle(Handle(wrapped_handle));
}
-PlatformHandle MojoPlatformHandleToPlatformHandle(
- const MojoPlatformHandle* handle) {
- if (handle->struct_size < sizeof(*handle) ||
- handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
- return PlatformHandle();
- }
-
-#if defined(OS_WIN)
- if (handle->type != MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE)
- return PlatformHandle();
- return PlatformHandle(
- base::win::ScopedHandle(LongToHandle(static_cast<long>(handle->value))));
-#elif defined(OS_FUCHSIA)
- if (handle->type == MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE)
- return PlatformHandle(base::ScopedZxHandle(handle->value));
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
- if (handle->type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT) {
- return PlatformHandle(base::mac::ScopedMachSendRight(
- static_cast<mach_port_t>(handle->value)));
- }
-#endif
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
- if (handle->type != MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
+PlatformHandle UnwrapPlatformHandle(ScopedHandle handle) {
+ MojoPlatformHandle platform_handle;
+ platform_handle.struct_size = sizeof(platform_handle);
+ MojoResult result = MojoUnwrapPlatformHandle(handle.release().value(),
+ nullptr, &platform_handle);
+ if (result != MOJO_RESULT_OK)
return PlatformHandle();
- return PlatformHandle(base::ScopedFD(static_cast<int>(handle->value)));
-#endif
+ return PlatformHandle::FromMojoPlatformHandle(&platform_handle);
}
// Wraps a PlatformFile as a Mojo handle. Takes ownership of the file object.
diff --git a/chromium/mojo/public/cpp/system/platform_handle.h b/chromium/mojo/public/cpp/system/platform_handle.h
index 5fbd569dc86..b18ceafacd9 100644
--- a/chromium/mojo/public/cpp/system/platform_handle.h
+++ b/chromium/mojo/public/cpp/system/platform_handle.h
@@ -76,18 +76,13 @@ enum class UnwrappedSharedMemoryHandleProtection {
kReadOnly,
};
-// Converts a PlatformHandle to the MojoPlatformHandle C struct for use with
-// Mojo APIs. Note that although MojoPlatformHandle has weak ownership, this
-// relinquishes ownership from |handle|.
-void MOJO_CPP_SYSTEM_EXPORT
-PlatformHandleToMojoPlatformHandle(PlatformHandle handle,
- MojoPlatformHandle* out_handle);
-
-// Converts a MojoPlatformHandle C struct to a PlatformHandle for use with
-// various C++ APIs. Note that although MojoPlatformHandle has weak ownership,
-// the new handle assumes ownership of the represented platform handle.
-PlatformHandle MOJO_CPP_SYSTEM_EXPORT
-MojoPlatformHandleToPlatformHandle(const MojoPlatformHandle* handle);
+// Wraps a PlatformHandle from the C++ platform support library as a Mojo
+// handle.
+MOJO_CPP_SYSTEM_EXPORT ScopedHandle WrapPlatformHandle(PlatformHandle handle);
+
+// Unwraps a Mojo handle to a PlatformHandle object from the C++ platform
+// support library.
+MOJO_CPP_SYSTEM_EXPORT PlatformHandle UnwrapPlatformHandle(ScopedHandle handle);
// Wraps a PlatformFile as a Mojo handle. Takes ownership of the file object.
// If |platform_file| is valid, this will return a valid handle.
diff --git a/chromium/mojo/public/cpp/system/simple_watcher.cc b/chromium/mojo/public/cpp/system/simple_watcher.cc
index 9c5017b4c9e..6384c1abed2 100644
--- a/chromium/mojo/public/cpp/system/simple_watcher.cc
+++ b/chromium/mojo/public/cpp/system/simple_watcher.cc
@@ -100,8 +100,8 @@ class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> {
task_runner_->RunsTasksInCurrentSequence() && weak_watcher_ &&
weak_watcher_->is_default_task_runner_) {
// System notifications will trigger from the task runner passed to
- // mojo::edk::ScopedIPCSupport. In Chrome this happens to always be the
- // default task runner for the IO thread.
+ // mojo::core::ScopedIPCSupport. In Chrome this happens to always be
+ // the default task runner for the IO thread.
weak_watcher_->OnHandleReady(watch_id_, result, state);
} else {
task_runner_->PostTask(
@@ -206,22 +206,21 @@ void SimpleWatcher::Cancel() {
MojoResult SimpleWatcher::Arm(MojoResult* ready_result,
HandleSignalsState* ready_state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- uint32_t num_ready_contexts = 1;
- uintptr_t ready_context;
- MojoResult local_ready_result;
- HandleSignalsState local_ready_state;
- if (!ready_state)
- ready_state = &local_ready_state;
- MojoResult rv =
- MojoArmTrap(trap_handle_.get().value(), nullptr, &num_ready_contexts,
- &ready_context, &local_ready_result,
- reinterpret_cast<MojoHandleSignalsState*>(ready_state));
+ uint32_t num_blocking_events = 1;
+ MojoTrapEvent blocking_event = {sizeof(blocking_event)};
+ MojoResult rv = MojoArmTrap(trap_handle_.get().value(), nullptr,
+ &num_blocking_events, &blocking_event);
if (rv == MOJO_RESULT_FAILED_PRECONDITION) {
DCHECK(context_);
- DCHECK_EQ(1u, num_ready_contexts);
- DCHECK_EQ(context_->value(), ready_context);
+ DCHECK_EQ(1u, num_blocking_events);
+ DCHECK_EQ(context_->value(), blocking_event.trigger_context);
if (ready_result)
- *ready_result = local_ready_result;
+ *ready_result = blocking_event.result;
+ if (ready_state) {
+ *ready_state =
+ HandleSignalsState(blocking_event.signals_state.satisfied_signals,
+ blocking_event.signals_state.satisfiable_signals);
+ }
}
return rv;
diff --git a/chromium/mojo/public/cpp/system/tests/BUILD.gn b/chromium/mojo/public/cpp/system/tests/BUILD.gn
index e29b5c03f30..c08f3c1099e 100644
--- a/chromium/mojo/public/cpp/system/tests/BUILD.gn
+++ b/chromium/mojo/public/cpp/system/tests/BUILD.gn
@@ -18,11 +18,16 @@ source_set("tests") {
"wait_unittest.cc",
]
+ if (!is_ios) {
+ sources += [ "invitation_unittest.cc" ]
+ }
+
deps = [
"//base",
"//base/test:test_support",
- "//mojo/edk/test:test_support",
+ "//mojo/core/test:test_support",
"//mojo/public/c/system/tests",
+ "//mojo/public/cpp/platform",
"//mojo/public/cpp/system",
"//mojo/public/cpp/test_support:test_utils",
"//testing/gtest",
diff --git a/chromium/mojo/public/cpp/system/wait.cc b/chromium/mojo/public/cpp/system/wait.cc
index a1aa4bc16c0..8defafe4d8f 100644
--- a/chromium/mojo/public/cpp/system/wait.cc
+++ b/chromium/mojo/public/cpp/system/wait.cc
@@ -87,23 +87,21 @@ MojoResult Wait(Handle handle,
}
DCHECK_EQ(MOJO_RESULT_OK, rv);
- uint32_t num_ready_contexts = 1;
- uintptr_t ready_context;
- MojoResult ready_result;
- MojoHandleSignalsState ready_state;
- rv = MojoArmTrap(trap.get().value(), nullptr, &num_ready_contexts,
- &ready_context, &ready_result, &ready_state);
+ uint32_t num_blocking_events = 1;
+ MojoTrapEvent blocking_event = {sizeof(blocking_event)};
+ rv = MojoArmTrap(trap.get().value(), nullptr, &num_blocking_events,
+ &blocking_event);
if (rv == MOJO_RESULT_FAILED_PRECONDITION) {
- DCHECK_EQ(1u, num_ready_contexts);
+ DCHECK_EQ(1u, num_blocking_events);
if (signals_state)
- *signals_state = ready_state;
- return ready_result;
+ *signals_state = blocking_event.signals_state;
+ return blocking_event.result;
}
// Wait for the first notification only.
context->event().Wait();
- ready_result = context->wait_result();
+ MojoResult ready_result = context->wait_result();
DCHECK_NE(MOJO_RESULT_UNKNOWN, ready_result);
if (signals_state)
@@ -150,22 +148,24 @@ MojoResult WaitMany(const Handle* handles,
events[i] = &contexts[i]->event();
}
- uint32_t num_ready_contexts = 1;
- uintptr_t ready_context = 0;
- MojoResult ready_result = MOJO_RESULT_UNKNOWN;
- MojoHandleSignalsState ready_state{0, 0};
- rv = MojoArmTrap(trap.get().value(), nullptr, &num_ready_contexts,
- &ready_context, &ready_result, &ready_state);
+ uint32_t num_blocking_events = 1;
+ MojoTrapEvent blocking_event = {sizeof(blocking_event)};
+ rv = MojoArmTrap(trap.get().value(), nullptr, &num_blocking_events,
+ &blocking_event);
size_t index = num_handles;
+ MojoResult ready_result = MOJO_RESULT_UNKNOWN;
+ MojoHandleSignalsState ready_state = {};
if (rv == MOJO_RESULT_FAILED_PRECONDITION) {
- DCHECK_EQ(1u, num_ready_contexts);
+ DCHECK_EQ(1u, num_blocking_events);
// Most commonly we only watch a small number of handles. Just scan for
// the right index.
for (size_t i = 0; i < num_handles; ++i) {
- if (contexts[i]->context_value() == ready_context) {
+ if (contexts[i]->context_value() == blocking_event.trigger_context) {
index = i;
+ ready_result = blocking_event.result;
+ ready_state = blocking_event.signals_state;
break;
}
}
diff --git a/chromium/mojo/public/cpp/system/wait_set.cc b/chromium/mojo/public/cpp/system/wait_set.cc
index 3ad98409160..cd8b859dc9c 100644
--- a/chromium/mojo/public/cpp/system/wait_set.cc
+++ b/chromium/mojo/public/cpp/system/wait_set.cc
@@ -145,22 +145,18 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> {
handle_event_.Reset();
DCHECK_LE(*num_ready_handles, std::numeric_limits<uint32_t>::max());
- uint32_t num_ready_contexts = static_cast<uint32_t>(*num_ready_handles);
-
- base::StackVector<uintptr_t, 4> ready_contexts;
- ready_contexts.container().resize(num_ready_contexts);
- base::StackVector<MojoHandleSignalsState, 4> ready_states;
- MojoHandleSignalsState* out_states = signals_states;
- if (!out_states) {
- // If the caller didn't provide a buffer for signal states, we provide
- // our own locally. MojoArmTrap() requires one if we want to handle
- // arming failure properly.
- ready_states.container().resize(num_ready_contexts);
- out_states = ready_states.container().data();
+ uint32_t num_blocking_events =
+ static_cast<uint32_t>(*num_ready_handles);
+
+ base::StackVector<MojoTrapEvent, 4> blocking_events;
+ blocking_events.container().resize(num_blocking_events);
+ for (size_t i = 0; i < num_blocking_events; ++i) {
+ blocking_events.container()[i].struct_size =
+ sizeof(blocking_events.container()[i]);
}
- MojoResult rv = MojoArmTrap(
- trap_handle_.get().value(), nullptr, &num_ready_contexts,
- ready_contexts.container().data(), ready_results, out_states);
+ MojoResult rv = MojoArmTrap(trap_handle_.get().value(), nullptr,
+ &num_blocking_events,
+ blocking_events.container().data());
if (rv == MOJO_RESULT_FAILED_PRECONDITION) {
// Simulate the handles becoming ready. We do this in lieu of
@@ -168,11 +164,12 @@ class WaitSet::State : public base::RefCountedThreadSafe<State> {
// starving user events. i.e., we always want to call WaitMany()
// below.
handle_event_.Signal();
- for (size_t i = 0; i < num_ready_contexts; ++i) {
- auto it = contexts_.find(ready_contexts.container()[i]);
+ for (size_t i = 0; i < num_blocking_events; ++i) {
+ const auto& event = blocking_events.container()[i];
+ auto it = contexts_.find(event.trigger_context);
DCHECK(it != contexts_.end());
- ready_handles_[it->second->handle()] = {ready_results[i],
- out_states[i]};
+ ready_handles_[it->second->handle()] = {event.result,
+ event.signals_state};
}
} else if (rv == MOJO_RESULT_NOT_FOUND) {
// Nothing to watch. If there are no user events, always signal to
diff --git a/chromium/mojo/public/java/BUILD.gn b/chromium/mojo/public/java/BUILD.gn
index 14951f4f095..c6159ab2e80 100644
--- a/chromium/mojo/public/java/BUILD.gn
+++ b/chromium/mojo/public/java/BUILD.gn
@@ -41,6 +41,7 @@ android_library("bindings_java") {
"bindings/src/org/chromium/mojo/bindings/DelegatingConnectionErrorHandler.java",
"bindings/src/org/chromium/mojo/bindings/DeserializationException.java",
"bindings/src/org/chromium/mojo/bindings/Encoder.java",
+ "bindings/src/org/chromium/mojo/bindings/ExceptionHandler.java",
"bindings/src/org/chromium/mojo/bindings/ExecutorFactory.java",
"bindings/src/org/chromium/mojo/bindings/HandleOwner.java",
"bindings/src/org/chromium/mojo/bindings/InterfaceControlMessagesHelper.java",
@@ -72,7 +73,7 @@ android_library("base_java") {
deps = [
":system_java",
- "//mojo/android:system_java",
+ "//mojo/public/java/system:system_impl_java",
"//mojo/public/mojom/base:base_java",
]
}
diff --git a/chromium/mojo/android/BUILD.gn b/chromium/mojo/public/java/system/BUILD.gn
index 223f859aae4..0025f5588d3 100644
--- a/chromium/mojo/android/BUILD.gn
+++ b/chromium/mojo/public/java/system/BUILD.gn
@@ -4,12 +4,12 @@
import("//build/config/android/rules.gni")
-group("android") {
+group("system") {
testonly = true
deps = [
":mojo_javatests",
":mojo_test_apk",
- ":system_java",
+ ":system_impl_java",
]
}
@@ -19,48 +19,48 @@ generate_jni("jni_headers") {
"javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java",
]
public_deps = [
- ":system_java_jni_headers",
+ ":system_impl_java_jni_headers",
]
jni_package = "mojo"
}
-generate_jni("system_java_jni_headers") {
+generate_jni("system_impl_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",
+ "src/org/chromium/mojo/system/impl/BaseRunLoop.java",
+ "src/org/chromium/mojo/system/impl/CoreImpl.java",
+ "src/org/chromium/mojo/system/impl/WatcherImpl.java",
]
jni_package = "mojo"
}
-source_set("libsystem_java") {
+source_set("native_support") {
sources = [
- "system/base_run_loop.cc",
- "system/core_impl.cc",
- "system/watcher_impl.cc",
+ "base_run_loop.cc",
+ "core_impl.cc",
+ "watcher_impl.cc",
]
deps = [
- ":system_java_jni_headers",
+ ":system_impl_java_jni_headers",
"//base",
"//mojo/public/c/system",
"//mojo/public/cpp/system",
]
}
-android_library("system_java") {
+android_library("system_impl_java") {
java_files = [
- "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/DataPipeConsumerHandleImpl.java",
- "system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java",
- "system/src/org/chromium/mojo/system/impl/HandleBase.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",
+ "src/org/chromium/mojo/system/impl/BaseRunLoop.java",
+ "src/org/chromium/mojo/system/impl/CoreImpl.java",
+ "src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/HandleBase.java",
+ "src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/UntypedHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/WatcherImpl.java",
]
deps = [
@@ -69,11 +69,34 @@ android_library("system_java") {
]
}
+# Targets should also depend on :test_support for the native side.
+android_library("test_support_java") {
+ testonly = true
+ java_files = [ "javatests/src/org/chromium/mojo/MojoTestRule.java" ]
+ deps = [
+ "//base:base_java",
+ "//third_party/junit",
+ ]
+}
+
+source_set("test_support") {
+ testonly = true
+ sources = [
+ "javatests/mojo_test_rule.cc",
+ ]
+ deps = [
+ ":jni_headers",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/embedder",
+ ]
+ defines = [ "UNIT_TEST" ]
+}
+
android_library("mojo_javatests") {
testonly = true
java_files = [
"javatests/src/org/chromium/mojo/HandleMock.java",
- "javatests/src/org/chromium/mojo/MojoTestRule.java",
"javatests/src/org/chromium/mojo/TestUtils.java",
"javatests/src/org/chromium/mojo/bindings/BindingsHelperTest.java",
"javatests/src/org/chromium/mojo/bindings/BindingsTest.java",
@@ -97,7 +120,8 @@ android_library("mojo_javatests") {
]
deps = [
- ":system_java",
+ ":system_impl_java",
+ ":test_support_java",
"//base:base_java",
"//base:base_java_test_support",
"//mojo/public/interfaces/bindings/tests:test_interfaces_java",
@@ -119,18 +143,17 @@ shared_library("mojo_java_unittests") {
sources = [
"javatests/init_library.cc",
- "javatests/mojo_test_rule.cc",
"javatests/validation_test_util.cc",
]
deps = [
":jni_headers",
- ":libsystem_java",
- ":system_java_jni_headers",
+ ":native_support",
+ ":system_impl_java_jni_headers",
+ ":test_support",
"//base",
"//base/test:test_support",
- "//build/config:exe_and_shlib_deps",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils",
"//mojo/public/cpp/test_support:test_utils",
]
@@ -142,7 +165,7 @@ shared_library("mojo_java_unittests") {
instrumentation_test_apk("mojo_test_apk") {
deps = [
":mojo_javatests",
- ":system_java",
+ ":system_impl_java",
"//base:base_java",
"//mojo/public/interfaces/bindings/tests:test_interfaces",
"//mojo/public/java:bindings_java",
diff --git a/chromium/mojo/android/DEPS b/chromium/mojo/public/java/system/DEPS
index c80012b5621..c80012b5621 100644
--- a/chromium/mojo/android/DEPS
+++ b/chromium/mojo/public/java/system/DEPS
diff --git a/chromium/mojo/android/system/base_run_loop.cc b/chromium/mojo/public/java/system/base_run_loop.cc
index bfc170007cf..5b14852b130 100644
--- a/chromium/mojo/android/system/base_run_loop.cc
+++ b/chromium/mojo/public/java/system/base_run_loop.cc
@@ -59,7 +59,8 @@ static void JNI_BaseRunLoop_PostDelayedTask(
runnable_ref.Reset(env, runnable);
reinterpret_cast<base::MessageLoop*>(runLoopID)
->task_runner()
- ->PostDelayedTask(FROM_HERE, base::Bind(&RunJavaRunnable, runnable_ref),
+ ->PostDelayedTask(FROM_HERE,
+ base::BindOnce(&RunJavaRunnable, runnable_ref),
base::TimeDelta::FromMicroseconds(delay));
}
diff --git a/chromium/mojo/android/system/core_impl.cc b/chromium/mojo/public/java/system/core_impl.cc
index 33f0576a4c4..33f0576a4c4 100644
--- a/chromium/mojo/android/system/core_impl.cc
+++ b/chromium/mojo/public/java/system/core_impl.cc
diff --git a/chromium/mojo/android/javatests/AndroidManifest.xml b/chromium/mojo/public/java/system/javatests/AndroidManifest.xml
index 37fc407e071..37fc407e071 100644
--- a/chromium/mojo/android/javatests/AndroidManifest.xml
+++ b/chromium/mojo/public/java/system/javatests/AndroidManifest.xml
diff --git a/chromium/mojo/public/java/system/javatests/DEPS b/chromium/mojo/public/java/system/javatests/DEPS
new file mode 100644
index 00000000000..9243dcd6900
--- /dev/null
+++ b/chromium/mojo/public/java/system/javatests/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+mojo/core/embedder",
+]
diff --git a/chromium/mojo/android/javatests/apk/.empty b/chromium/mojo/public/java/system/javatests/apk/.empty
index e69de29bb2d..e69de29bb2d 100644
--- a/chromium/mojo/android/javatests/apk/.empty
+++ b/chromium/mojo/public/java/system/javatests/apk/.empty
diff --git a/chromium/mojo/android/javatests/init_library.cc b/chromium/mojo/public/java/system/javatests/init_library.cc
index 2b2e81a5d19..2826d29b9d6 100644
--- a/chromium/mojo/android/javatests/init_library.cc
+++ b/chromium/mojo/public/java/system/javatests/init_library.cc
@@ -4,7 +4,7 @@
#include "base/android/base_jni_onload.h"
#include "base/android/jni_android.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
base::android::InitVM(vm);
@@ -12,6 +12,6 @@ JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
if (!base::android::OnJNIOnLoadInit())
return -1;
- mojo::edk::Init();
+ mojo::core::Init();
return JNI_VERSION_1_4;
}
diff --git a/chromium/mojo/android/javatests/mojo_test_rule.cc b/chromium/mojo/public/java/system/javatests/mojo_test_rule.cc
index 6a7503cab08..67576bbfac1 100644
--- a/chromium/mojo/android/javatests/mojo_test_rule.cc
+++ b/chromium/mojo/public/java/system/javatests/mojo_test_rule.cc
@@ -14,6 +14,7 @@
#include "base/test/test_support_android.h"
#include "base/threading/thread_task_runner_handle.h"
#include "jni/MojoTestRule_jni.h"
+#include "mojo/core/embedder/embedder.h"
using base::android::JavaParamRef;
@@ -31,6 +32,11 @@ struct TestEnvironment {
namespace mojo {
namespace android {
+static void JNI_MojoTestRule_InitCore(JNIEnv* env,
+ const JavaParamRef<jclass>& clazz) {
+ mojo::core::Init();
+}
+
static void JNI_MojoTestRule_Init(JNIEnv* env,
const JavaParamRef<jobject>& jcaller) {
base::InitAndroidTestMessageLoop();
diff --git a/chromium/mojo/android/javatests/validation_test_util.cc b/chromium/mojo/public/java/system/javatests/validation_test_util.cc
index 83ba6796791..277a2d5b634 100644
--- a/chromium/mojo/android/javatests/validation_test_util.cc
+++ b/chromium/mojo/public/java/system/javatests/validation_test_util.cc
@@ -27,8 +27,8 @@ ScopedJavaLocalRef<jobject> JNI_ValidationTestUtil_ParseData(
std::vector<uint8_t> data;
size_t num_handles;
std::string error_message;
- if (!test::ParseValidationTestInput(
- input, &data, &num_handles, &error_message)) {
+ if (!test::ParseValidationTestInput(input, &data, &num_handles,
+ &error_message)) {
ScopedJavaLocalRef<jstring> j_error_message =
base::android::ConvertUTF8ToJavaString(env, error_message);
return Java_ValidationTestUtil_buildData(env, nullptr, 0, j_error_message);
diff --git a/chromium/mojo/android/system/watcher_impl.cc b/chromium/mojo/public/java/system/watcher_impl.cc
index b744416ff7b..36196487ebc 100644
--- a/chromium/mojo/android/system/watcher_impl.cc
+++ b/chromium/mojo/public/java/system/watcher_impl.cc
@@ -34,8 +34,8 @@ class WatcherImpl {
jint signals) {
java_watcher_.Reset(env, jcaller);
- auto ready_callback =
- base::Bind(&WatcherImpl::OnHandleReady, base::Unretained(this));
+ auto ready_callback = base::BindRepeating(&WatcherImpl::OnHandleReady,
+ base::Unretained(this));
MojoResult result =
watcher_.Watch(mojo::Handle(static_cast<MojoHandle>(mojo_handle)),
diff --git a/chromium/mojo/public/js/lib/unicode.js b/chromium/mojo/public/js/lib/unicode.js
index 6ed8839c3fb..67976ae4e6d 100644
--- a/chromium/mojo/public/js/lib/unicode.js
+++ b/chromium/mojo/public/js/lib/unicode.js
@@ -9,6 +9,8 @@
*/
(function() {
var internal = mojo.internal;
+ var textDecoder = new TextDecoder('utf-8');
+ var textEncoder = new TextEncoder('utf-8');
/**
* Decodes the UTF8 string from the given buffer.
@@ -16,7 +18,7 @@
* @return {string} The corresponding JavaScript string.
*/
function decodeUtf8String(buffer) {
- return decodeURIComponent(escape(String.fromCharCode.apply(null, buffer)));
+ return textDecoder.decode(buffer);
}
/**
@@ -28,12 +30,11 @@
* @return {number} The number of bytes written to |outputBuffer|.
*/
function encodeUtf8String(str, outputBuffer) {
- var utf8String = unescape(encodeURIComponent(str));
- if (outputBuffer.length < utf8String.length)
+ const utf8Buffer = textEncoder.encode(str);
+ if (outputBuffer.length < utf8Buffer.length)
throw new Error("Buffer too small for encodeUtf8String");
- for (var i = 0; i < outputBuffer.length && i < utf8String.length; i++)
- outputBuffer[i] = utf8String.charCodeAt(i);
- return i;
+ outputBuffer.set(utf8Buffer);
+ return utf8Buffer.length;
}
/**
@@ -41,8 +42,7 @@
* |str| would occupy.
*/
function utf8Length(str) {
- var utf8String = unescape(encodeURIComponent(str));
- return utf8String.length;
+ return textEncoder.encode(str).length;
}
internal.decodeUtf8String = decodeUtf8String;
diff --git a/chromium/mojo/public/mojom/base/file.mojom b/chromium/mojo/public/mojom/base/file.mojom
index 824ebb1f133..9f08b26bea5 100644
--- a/chromium/mojo/public/mojom/base/file.mojom
+++ b/chromium/mojo/public/mojom/base/file.mojom
@@ -7,4 +7,5 @@ module mojo_base.mojom;
// Corresponds to |base::File| in base/files/file.h
struct File {
handle fd;
+ bool async;
};
diff --git a/chromium/mojo/public/mojom/base/file_info.mojom b/chromium/mojo/public/mojom/base/file_info.mojom
index 544f2914387..5dff3ca38a6 100644
--- a/chromium/mojo/public/mojom/base/file_info.mojom
+++ b/chromium/mojo/public/mojom/base/file_info.mojom
@@ -4,5 +4,14 @@
module mojo_base.mojom;
-[Native]
-struct FileInfo;
+import "mojo/public/mojom/base/time.mojom";
+
+// Corresponds to base::File::Info.
+struct FileInfo {
+ int64 size;
+ bool is_directory;
+ bool is_symbolic_link;
+ Time last_modified;
+ Time last_accessed;
+ Time creation_time;
+};
diff --git a/chromium/mojo/public/mojom/base/logfont_win.mojom b/chromium/mojo/public/mojom/base/logfont_win.mojom
index 81beefad726..27922b84782 100644
--- a/chromium/mojo/public/mojom/base/logfont_win.mojom
+++ b/chromium/mojo/public/mojom/base/logfont_win.mojom
@@ -5,5 +5,7 @@
module mojo_base.mojom;
// Native Windows struct. Its typemap only exists for windows builds.
-[Native]
-struct LOGFONT;
+[EnableIf=is_win]
+struct LOGFONT {
+ array<uint8> bytes;
+};
diff --git a/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni b/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni
index 178394599ac..990d1337deb 100644
--- a/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni
+++ b/chromium/mojo/public/tools/bindings/blink_bindings_configuration.gni
@@ -7,6 +7,7 @@ variant = "blink"
for_blink = true
_typemap_imports = [
+ "//device/gamepad/public/cpp/typemaps.gni",
"//mojo/public/cpp/bindings/tests/blink_typemaps.gni",
"//third_party/blink/renderer/platform/mojo/blink_typemaps.gni",
"//third_party/blink/public/blink_typemaps.gni",
diff --git a/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni
index 0f508ca2e5b..1893db1ac95 100644
--- a/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni
+++ b/chromium/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -8,7 +8,10 @@ _typemap_imports = [
"//chrome/common/importer/typemaps.gni",
"//chrome/common/media_router/mojo/typemaps.gni",
"//chrome/typemaps.gni",
+ "//chromecast/common/mojom/typemaps.gni",
+ "//chromeos/typemaps.gni",
"//chromeos/services/device_sync/public/mojom/typemaps.gni",
+ "//chromeos/services/secure_channel/public/mojom/typemaps.gni",
"//components/arc/common/typemaps.gni",
"//components/metrics/public/cpp/typemaps.gni",
"//components/sync/mojo/typemaps.gni",
@@ -20,8 +23,9 @@ _typemap_imports = [
"//content/public/common/typemaps.gni",
"//device/bluetooth/public/mojom/typemaps.gni",
"//device/bluetooth/public/mojom/test/typemaps.gni",
- "//device/gamepad/public/mojom/typemaps.gni",
+ "//device/gamepad/public/cpp/typemaps.gni",
"//gpu/ipc/common/typemaps.gni",
+ "//ipc/typemaps.gni",
"//media/capture/mojom/typemaps.gni",
"//media/mojo/interfaces/typemaps.gni",
"//mojo/public/cpp/base/typemaps.gni",
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 f0ea917a265..72c3101c142 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
@@ -142,6 +142,11 @@ bool {{proxy_name}}::{{method.name}}(
"message")}}
{%- endif %}
+#if defined(ENABLE_IPC_FUZZER)
+ message.set_interface_name({{class_name}}::Name_);
+ message.set_method_name("{{method.name}}");
+#endif
+
bool result = false;
std::unique_ptr<mojo::MessageReceiver> responder(
new {{class_name}}_{{method.name}}_HandleSyncResponse(
@@ -180,6 +185,11 @@ void {{proxy_name}}::{{method.name}}(
"message")}}
{%- endif %}
+#if defined(ENABLE_IPC_FUZZER)
+ message.set_interface_name({{class_name}}::Name_);
+ message.set_method_name("{{method.name}}");
+#endif
+
{%- if method.response_parameters != None %}
std::unique_ptr<mojo::MessageReceiver> responder(
new {{class_name}}_{{method.name}}_ForwardToCallback(
@@ -329,6 +339,12 @@ void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
TRACE_EVENT1("mojom", "(Impl){{namespace_as_string}}::{{class_name}}::{{method.name}}Callback",
"message", message.name());
#endif
+
+#if defined(ENABLE_IPC_FUZZER)
+ message.set_interface_name({{class_name}}::Name_);
+ message.set_method_name("{{method.name}}");
+#endif
+
message.set_request_id(request_id_);
ignore_result(responder_->Accept(&message));
// TODO(darin): Accept() returning false indicates a malformed message, and
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/externs/interface_definition.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/interface_definition.tmpl
index 9f9b9f1ebd3..672b5d5d893 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/externs/interface_definition.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/interface_definition.tmpl
@@ -1,6 +1,6 @@
-/** @implements {mojo.InterfacePtr} */
-{{module.namespace}}.{{interface.name}}Ptr = class {
-{% for method in interface.methods %}
+{% macro generateInterfaceClass() -%}
+class {
+{%- for method in interface.methods %}
/**
{%- for parameter in method.parameters %}
* @param { {{parameter.kind|closure_type_with_nullability}} } {{parameter.name|sanitize_identifier}}
@@ -9,16 +9,26 @@
* @return {Promise}
{%- endif %}
*/
- {{method.name}}(
+ {{method.name}}(
{%- for parameter in method.parameters -%}
{{parameter.name|sanitize_identifier}}{% if not loop.last %}, {% endif %}
{%- endfor -%}
) {}
{%- endfor %}
};
+{%- endmacro %}
/**
* @const
- * @type { mojo.Interface };
+ * @type { !mojo.Interface };
*/
{{module.namespace}}.{{interface.name}};
+
+/** @interface */
+{{module.namespace}}.{{interface.name}}Impl = {{ generateInterfaceClass() }}
+
+/**
+ * @implements { mojo.InterfacePtr }
+ * @implements { {{module.namespace}}.{{interface.name}}Impl }
+ */
+{{module.namespace}}.{{interface.name}}Ptr = {{ generateInterfaceClass() }}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/externs/module.externs.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/module.externs.tmpl
index 8eccefbfecf..fd711068f26 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/externs/module.externs.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/externs/module.externs.tmpl
@@ -5,12 +5,27 @@
{% for declaration in module.namespace|namespace_declarations -%}
/** @const */
{%- if loop.first %}
-let {{declaration}} = {};
+var {{declaration}} = {};
{% else %}
{{declaration}} = {};
{% endif -%}
{%- endfor -%}
+{#--- Constant definitions #}
+{%- for constant in module.constants %}
+/** @type { {{constant.kind|closure_type_with_nullability }} } */
+{{module.namespace}}.{{constant.name}};
+{%- endfor %}
+
+{#--- Enum definitions #}
+{% for enum in enums %}
+/** @enum {number} */
+{{module.namespace}}.{{enum.name}} = {};
+{%- for field in enum.fields %}
+{{module.namespace}}.{{enum.name}}.{{field.name}};
+{%- endfor %}
+{%- endfor %}
+
{#--- Interface definitions #}
{%- for interface in interfaces -%}
{%- include "externs/interface_definition.tmpl" %}
diff --git a/chromium/mojo/public/tools/bindings/generators/js_templates/fuzzing.tmpl b/chromium/mojo/public/tools/bindings/generators/js_templates/fuzzing.tmpl
index fb535fe03af..a91260ed9ac 100644
--- a/chromium/mojo/public/tools/bindings/generators/js_templates/fuzzing.tmpl
+++ b/chromium/mojo/public/tools/bindings/generators/js_templates/fuzzing.tmpl
@@ -114,9 +114,9 @@ idx = {{name}}.setHandlesInternal_(handles, idx)
{%- elif kind|is_enum_kind -%}
{{generate_or_mutate_enum(obj, operation, kind, name)}}
{%- elif kind|is_struct_kind -%}
-{{build_call(obj, operation, 'Struct', kind.module.namespace ~ '.' ~ kind.name, kind.is_nullable|to_js_boolean)}}
+{{build_call(obj, operation, 'Struct', name, kind.module.namespace ~ '.' ~ kind.name, kind.is_nullable|to_js_boolean)}}
{%- elif kind|is_union_kind -%}
-{{build_call(obj, operation, 'Union', kind.module.namespace ~ '.' ~ kind.name, kind.is_nullable|to_js_boolean)}}
+{{build_call(obj, operation, 'Union', name, kind.module.namespace ~ '.' ~ kind.name, kind.is_nullable|to_js_boolean)}}
{%- elif kind|is_array_kind -%}
{{generate_or_mutate_array(obj, operation, kind, name)}}
{%- elif kind|is_map_kind -%}
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 499c786e2e1..ad857b2c25c 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
@@ -64,13 +64,13 @@ function {{union.name}}(value) {
{
field: "{{field.name}}",
- mutator: function() { return {{generate_or_mutate('mutator_', 'mutate', field.kind, 'this.' ~ field.name)|indent(6)}}; },
+ mutator: function(val) { return {{generate_or_mutate('mutator_', 'mutate', field.kind, 'val.' ~ field.name)|indent(6)}}; },
},
{%- endfor %}
];
var result = mutator_.mutateUnionField(this, mutators);
- generated[result.field] = result.value;
+ this[result.field] = result.value;
return this;
}
diff --git a/chromium/mojo/public/tools/bindings/mojom.gni b/chromium/mojo/public/tools/bindings/mojom.gni
index a38262322e6..3329631470f 100644
--- a/chromium/mojo/public/tools/bindings/mojom.gni
+++ b/chromium/mojo/public/tools/bindings/mojom.gni
@@ -389,7 +389,7 @@ template("mojom") {
} else if (is_chromeos) {
enabled_features += [ "is_chromeos" ]
} else if (is_fuchsia) {
- enabled_features += [ "is_fuschia" ]
+ enabled_features += [ "is_fuchsia" ]
} else if (is_ios) {
enabled_features += [ "is_ios" ]
} else if (is_linux) {
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py
index 66f89540126..653a2dfc74d 100644
--- a/chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py
@@ -4,27 +4,14 @@
# Based on third_party/WebKit/Source/build/scripts/template_expander.py.
-import imp
import os.path
import sys
-# Disable lint check for finding modules:
-# pylint: disable=F0401
-
-def _GetDirAbove(dirname):
- """Returns the directory "above" this file containing |dirname| (which must
- also be "above" this file)."""
- path = os.path.abspath(__file__)
- while True:
- path, tail = os.path.split(path)
- assert tail
- if tail == dirname:
- return path
-
-try:
- imp.find_module("jinja2")
-except ImportError:
- sys.path.append(os.path.join(_GetDirAbove("mojo"), "third_party"))
+_current_dir = os.path.dirname(os.path.realpath(__file__))
+# jinja2 is in chromium's third_party directory
+# Insert at front to override system libraries, and after path[0] == script dir
+sys.path.insert(
+ 1, os.path.join(_current_dir, *([os.pardir] * 7 + ['third_party'])))
import jinja2
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
index 916d69d2242..b9f10dce9e3 100644
--- a/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom/parse/parser.py
@@ -4,24 +4,12 @@
"""Generates a syntax tree from a Mojo IDL file."""
-import imp
import os.path
import sys
-def _GetDirAbove(dirname):
- """Returns the directory "above" this file containing |dirname| (which must
- also be "above" this file)."""
- path = os.path.abspath(__file__)
- while True:
- path, tail = os.path.split(path)
- assert tail
- if tail == dirname:
- return path
-
-try:
- imp.find_module("ply")
-except ImportError:
- sys.path.append(os.path.join(_GetDirAbove("mojo"), "third_party"))
+_current_dir = os.path.dirname(os.path.realpath(__file__))
+sys.path.insert(
+ 1, os.path.join(_current_dir, *([os.pardir] * 7 + ['third_party'])))
from ply import lex
from ply import yacc
diff --git a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py
index 6822cbc8d0d..36d8c4abfe8 100644
--- a/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py
+++ b/chromium/mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py
@@ -17,10 +17,7 @@ def _GetDirAbove(dirname):
if tail == dirname:
return path
-try:
- imp.find_module("ply")
-except ImportError:
- sys.path.append(os.path.join(_GetDirAbove("mojo"), "third_party"))
+sys.path.insert(1, os.path.join(_GetDirAbove("mojo"), "third_party"))
from ply import lex
try:
diff --git a/chromium/mojo/public/tools/fuzzers/BUILD.gn b/chromium/mojo/public/tools/fuzzers/BUILD.gn
index 00d09f1969e..69531552db6 100644
--- a/chromium/mojo/public/tools/fuzzers/BUILD.gn
+++ b/chromium/mojo/public/tools/fuzzers/BUILD.gn
@@ -26,7 +26,7 @@ fuzzer_test("mojo_parse_message_fuzzer") {
]
deps = [
":fuzz_mojom",
- "//mojo/edk",
+ "//mojo/core/embedder",
]
seed_corpus = "//mojo/public/tools/fuzzers/message_corpus"
}
@@ -41,8 +41,7 @@ if (!is_win) {
deps = [
":fuzz_mojom",
"//base",
- "//build/config:exe_and_shlib_deps",
- "//mojo/edk",
+ "//mojo/core/embedder",
]
}
}
@@ -55,7 +54,7 @@ fuzzer_test("mojo_parse_message_proto_fuzzer") {
deps = [
":fuzz_mojom",
":mojo_fuzzer_proto",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//third_party/libprotobuf-mutator",
]
seed_corpus = "//mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus"
diff --git a/chromium/mojo/public/tools/fuzzers/DEPS b/chromium/mojo/public/tools/fuzzers/DEPS
index 909a8338dae..9243dcd6900 100644
--- a/chromium/mojo/public/tools/fuzzers/DEPS
+++ b/chromium/mojo/public/tools/fuzzers/DEPS
@@ -1,3 +1,3 @@
include_rules = [
- "+mojo/edk",
+ "+mojo/core/embedder",
]
diff --git a/chromium/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc b/chromium/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
index b1bdb95a6c2..62d8d87b29d 100644
--- a/chromium/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
+++ b/chromium/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
@@ -10,7 +10,7 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_scheduler/task_scheduler.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include "mojo/public/tools/fuzzers/fuzz.mojom.h"
#include "mojo/public/tools/fuzzers/fuzz_impl.h"
@@ -21,7 +21,7 @@ struct Environment {
Environment() : message_loop() {
base::TaskScheduler::CreateAndStartWithDefaultParams(
"MojoFuzzerMessageDumpProcess");
- mojo::edk::Init();
+ mojo::core::Init();
}
/* Message loop to send messages on. */
diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc
index 0adb6844462..ba0f15015f5 100644
--- a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc
+++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_fuzzer.cc
@@ -5,7 +5,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/task_scheduler/task_scheduler.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/tools/fuzzers/fuzz_impl.h"
@@ -38,7 +38,7 @@ struct Environment {
Environment() : message_loop(base::MessageLoop::TYPE_UI) {
base::TaskScheduler::CreateAndStartWithDefaultParams(
"MojoParseMessageFuzzerProcess");
- mojo::edk::Init();
+ mojo::core::Init();
}
/* Message loop to send and handle messages on. */
diff --git a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc
index 6772541db7e..69c70bea32c 100644
--- a/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc
+++ b/chromium/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc
@@ -8,7 +8,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/task_scheduler/task_scheduler.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/tools/fuzzers/fuzz_impl.h"
#include "mojo/public/tools/fuzzers/mojo_fuzzer.pb.h"
@@ -49,7 +49,7 @@ struct Environment {
Environment() : message_loop(base::MessageLoop::TYPE_UI) {
base::TaskScheduler::CreateAndStartWithDefaultParams(
"MojoParseMessageFuzzerProcess");
- mojo::edk::Init();
+ mojo::core::Init();
}
// Message loop to send and handle messages on.