summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/mojo/mojo_application_host.cc16
-rw-r--r--content/browser/mojo/mojo_application_host.h9
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc11
-rw-r--r--content/child/child_thread_impl.cc54
-rw-r--r--content/child/child_thread_impl.h10
-rw-r--r--content/child/mojo/mojo_application.cc11
-rw-r--r--content/child/mojo/mojo_application.h4
-rw-r--r--content/common/mojo/channel_init.cc80
-rw-r--r--content/common/mojo/channel_init.h64
-rw-r--r--content/content_common.gypi2
-rw-r--r--content/test/data/web_ui_mojo.js11
-rw-r--r--content/test/render_thread_impl_browser_test_ipc_helper.cc5
-rw-r--r--content/test/render_thread_impl_browser_test_ipc_helper.h2
-rw-r--r--crypto/crypto.gyp2
-rw-r--r--crypto/crypto.gypi8
-rw-r--r--ipc/mojo/BUILD.gn2
-rw-r--r--ipc/mojo/ipc_channel_mojo.cc28
-rw-r--r--ipc/mojo/ipc_channel_mojo.h4
-rw-r--r--ipc/mojo/ipc_channel_mojo_unittest.cc69
-rw-r--r--ipc/mojo/ipc_mojo.gyp2
-rw-r--r--ipc/mojo/scoped_ipc_support.cc112
-rw-r--r--ipc/mojo/scoped_ipc_support.h34
-rw-r--r--mojo/android/BUILD.gn1
-rw-r--r--mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java97
-rw-r--r--mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java46
-rw-r--r--mojo/android/javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterface2TestHelper.java31
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java17
-rw-r--r--mojo/services/html_viewer/html_viewer.cc4
-rw-r--r--third_party/mojo/mojo_edk.gyp4
-rw-r--r--third_party/mojo/mojo_edk_system_impl.gypi13
-rw-r--r--third_party/mojo/mojo_edk_tests.gyp3
-rw-r--r--third_party/mojo/mojo_public.gyp1
-rw-r--r--third_party/mojo/mojom_bindings_generator_variables.gypi1
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/BUILD.gn5
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/channel_init.cc56
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/channel_init.h57
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder.cc286
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder.h159
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder_internal.h24
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc35
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h24
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/platform_support.h3
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/process_delegate.h39
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/process_type.h26
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/simple_platform_support.cc6
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h1
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h11
-rw-r--r--third_party/mojo/src/mojo/edk/embedder/test_embedder.cc6
-rw-r--r--third_party/mojo/src/mojo/edk/js/tests/connection_tests.js44
-rw-r--r--third_party/mojo/src/mojo/edk/js/tests/sample_service_tests.js4
-rw-r--r--third_party/mojo/src/mojo/edk/system/BUILD.gn8
-rw-r--r--third_party/mojo/src/mojo/edk/system/async_waiter.cc2
-rw-r--r--third_party/mojo/src/mojo/edk/system/async_waiter.h2
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager.cc120
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager.h71
-rw-r--r--third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc78
-rw-r--r--third_party/mojo/src/mojo/edk/system/connection_manager.h18
-rw-r--r--third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc48
-rw-r--r--third_party/mojo/src/mojo/edk/system/core.cc5
-rw-r--r--third_party/mojo/src/mojo/edk/system/core.h2
-rw-r--r--third_party/mojo/src/mojo/edk/system/data_pipe.cc186
-rw-r--r--third_party/mojo/src/mojo/edk/system/data_pipe.h113
-rw-r--r--third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc21
-rw-r--r--third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h8
-rw-r--r--third_party/mojo/src/mojo/edk/system/data_pipe_impl.h122
-rw-r--r--third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc21
-rw-r--r--third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h8
-rw-r--r--third_party/mojo/src/mojo/edk/system/dispatcher.h10
-rw-r--r--third_party/mojo/src/mojo/edk/system/local_data_pipe.h89
-rw-r--r--third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.cc (renamed from third_party/mojo/src/mojo/edk/system/local_data_pipe.cc)179
-rw-r--r--third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h94
-rw-r--r--third_party/mojo/src/mojo/edk/system/local_data_pipe_impl_unittest.cc (renamed from third_party/mojo/src/mojo/edk/system/local_data_pipe_unittest.cc)86
-rw-r--r--third_party/mojo/src/mojo/edk/system/master_connection_manager.cc77
-rw-r--r--third_party/mojo/src/mojo/edk/system/master_connection_manager.h35
-rw-r--r--third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc9
-rw-r--r--third_party/mojo/src/mojo/edk/system/slave_connection_manager.h18
-rw-r--r--third_party/mojo/src/mojo/edk/system/unique_identifier.cc7
-rw-r--r--third_party/mojo/src/mojo/edk/system/unique_identifier.h13
-rw-r--r--third_party/mojo/src/mojo/edk/system/unique_identifier_unittest.cc39
-rw-r--r--third_party/mojo/src/mojo/edk/test/BUILD.gn2
-rw-r--r--third_party/mojo/src/mojo/edk/test/scoped_ipc_support.cc38
-rw-r--r--third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h43
-rw-r--r--third_party/mojo/src/mojo/public/.gitignore2
-rw-r--r--third_party/mojo/src/mojo/public/LICENSE27
-rw-r--r--third_party/mojo/src/mojo/public/VERSION2
-rw-r--r--third_party/mojo/src/mojo/public/c/system/tests/core_perftest.cc36
-rw-r--r--third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc57
-rw-r--r--third_party/mojo/src/mojo/public/c/system/tests/core_unittest_pure_c.c34
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/application_connection.h39
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/application_delegate.h7
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/application_impl.h18
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/connect.h1
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/lazy_interface_ptr.h2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc5
-rw-r--r--third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc6
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/binding.h10
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/callback.h2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h11
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h20
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc14
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h16
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/interface_ptr_internal.h29
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h14
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/map_internal.h4
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/message_builder.cc8
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc18
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h10
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/map.h4
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/message.h2
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/no_interface.h3
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h1
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc152
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc65
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc15
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/sample_service_unittest.cc9
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc222
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc18
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_test_input_parser.h6
-rw-r--r--third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc70
-rw-r--r--third_party/mojo/src/mojo/public/dart/application.dart4
-rw-r--r--third_party/mojo/src/mojo/public/dart/rules.gni7
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/application.dart91
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/application_connection.dart105
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/codec.dart142
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/drain_data.dart6
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/message.dart42
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/proxy.dart4
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/service_provider.dart40
-rw-r--r--third_party/mojo/src/mojo/public/dart/src/struct.dart12
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/async_waiter.go266
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/decoder.go21
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/encoder.go18
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/interface.go60
-rw-r--r--third_party/mojo/src/mojo/public/go/bindings/message.go4
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/application/application.mojom5
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_good.data1
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_good.data (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_good.data)2
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_good.expected (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_good.expected)0
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_unexpected_array_header.data (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_unexpected_array_header.data)2
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_unexpected_array_header.expected (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_unexpected_array_header.expected)0
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_good.data (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_good.data)5
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_good.expected (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_good.expected)0
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_unexpected_struct_header.data (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_unexpected_struct_header.data)5
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_unexpected_struct_header.expected (renamed from third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_unexpected_struct_header.expected)0
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests.mojom6
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests_import.mojom11
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_factory.mojom11
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom5
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_service.mojom7
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom66
-rw-r--r--third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom10
-rw-r--r--third_party/mojo/src/mojo/public/java/BUILD.gn2
-rw-r--r--third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java86
-rw-r--r--third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java2
-rw-r--r--third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/InterfaceWithClient.java115
-rw-r--r--third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageHeader.java31
-rw-r--r--third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Struct.java22
-rw-r--r--third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/Core.java9
-rw-r--r--third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/RunLoop.java41
-rw-r--r--third_party/mojo/src/mojo/public/js/connection.js50
-rw-r--r--third_party/mojo/src/mojo/public/js/validation_unittests.js24
-rw-r--r--third_party/mojo/src/mojo/public/mojo.gni11
-rw-r--r--third_party/mojo/src/mojo/public/mojo_application.gni27
-rw-r--r--third_party/mojo/src/mojo/public/python/BUILD.gn10
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_application/__init__.py3
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_application/application_delegate.py27
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_application/application_impl.py56
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_application/application_runner.py18
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_application/service_provider_impl.py24
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_bindings/descriptor.py34
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_bindings/messaging.py12
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py6
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_bindings/serialization.py7
-rw-r--r--third_party/mojo/src/mojo/public/python/mojo_system.pyx6
-rw-r--r--third_party/mojo/src/mojo/public/python/rules.gni8
-rw-r--r--third_party/mojo/src/mojo/public/tools/BUILD.gn52
-rw-r--r--third_party/mojo/src/mojo/public/tools/NETWORK_SERVICE_VERSION1
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl8
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl117
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl6
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl33
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl34
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl168
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl222
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl58
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl24
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl30
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl6
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl6
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface.java.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl40
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_internal.java.tmpl2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl17
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py132
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py9
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py2
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/mojom.gni1
-rw-r--r--third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py12
-rwxr-xr-xthird_party/mojo/src/mojo/public/tools/download_network_service.py89
-rwxr-xr-xthird_party/mojo/src/mojo/public/tools/download_shell_binary.py50
-rw-r--r--third_party/mojo/src/mojo/public/tools/pylib/gs.py34
-rw-r--r--third_party/mojo_services/src/public/js/application.js2
-rw-r--r--third_party/mojo_services/src/public/js/service_exchange.js6
-rw-r--r--third_party/mojo_services/src/public/js/shell.js4
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/BUILD.gn1
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/lib/view.cc19
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_factory.cc9
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.cc53
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h22
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_context.cc4
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/lib/view_observer.cc11
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h5
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/tests/BUILD.gn4
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.h3
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_unittest.cc652
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/tests/view_unittest.cc16
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/view.h23
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h6
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h5
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/view_observer.h2
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/view_property.h40
-rw-r--r--third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h6
-rw-r--r--tools/ipc_fuzzer/replay/replay_process.cc2
226 files changed, 4529 insertions, 3190 deletions
diff --git a/content/browser/mojo/mojo_application_host.cc b/content/browser/mojo/mojo_application_host.cc
index 883945f..a9d0002 100644
--- a/content/browser/mojo/mojo_application_host.cc
+++ b/content/browser/mojo/mojo_application_host.cc
@@ -63,9 +63,18 @@ bool MojoApplicationHost::Init() {
mojo::embedder::PlatformChannelPair channel_pair;
+ scoped_refptr<base::TaskRunner> io_task_runner;
+ if (io_task_runner_override_) {
+ io_task_runner = io_task_runner_override_;
+ } else {
+ io_task_runner =
+ BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
+ ->task_runner();
+ }
+
mojo::ScopedMessagePipeHandle message_pipe = channel_init_.Init(
PlatformFileFromScopedPlatformHandle(channel_pair.PassServerHandle()),
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
+ io_task_runner);
if (!message_pipe.is_valid())
return false;
@@ -93,4 +102,9 @@ void MojoApplicationHost::WillDestroySoon() {
channel_init_.WillDestroySoon();
}
+void MojoApplicationHost::OverrideIOTaskRunnerForTest(
+ scoped_refptr<base::TaskRunner> io_task_runner) {
+ io_task_runner_override_ = io_task_runner;
+}
+
} // namespace content
diff --git a/content/browser/mojo/mojo_application_host.h b/content/browser/mojo/mojo_application_host.h
index fc0693a..216b65a 100644
--- a/content/browser/mojo/mojo_application_host.h
+++ b/content/browser/mojo/mojo_application_host.h
@@ -8,8 +8,8 @@
#include "base/memory/scoped_ptr.h"
#include "base/process/process_handle.h"
#include "content/common/application_setup.mojom.h"
+#include "content/common/mojo/channel_init.h"
#include "content/common/mojo/service_registry_impl.h"
-#include "third_party/mojo/src/mojo/edk/embedder/channel_init.h"
#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
#if defined(OS_ANDROID)
@@ -48,8 +48,11 @@ class CONTENT_EXPORT MojoApplicationHost {
}
#endif
+ void OverrideIOTaskRunnerForTest(
+ scoped_refptr<base::TaskRunner> io_task_runner);
+
private:
- mojo::embedder::ChannelInit channel_init_;
+ ChannelInit channel_init_;
mojo::embedder::ScopedPlatformHandle client_handle_;
bool did_activate_;
@@ -57,6 +60,8 @@ class CONTENT_EXPORT MojoApplicationHost {
scoped_ptr<ApplicationSetup> application_setup_;
ServiceRegistryImpl service_registry_;
+ scoped_refptr<base::TaskRunner> io_task_runner_override_;
+
#if defined(OS_ANDROID)
scoped_ptr<ServiceRegistryAndroid> service_registry_android_;
#endif
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 6564c438..16aa989 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -110,6 +110,7 @@
#include "content/common/frame_messages.h"
#include "content/common/gpu/gpu_memory_buffer_factory.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/mojo/channel_init.h"
#include "content/common/mojo/mojo_messages.h"
#include "content/common/resource_messages.h"
#include "content/common/view_messages.h"
@@ -664,9 +665,15 @@ scoped_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
if (ShouldUseMojoChannel()) {
VLOG(1) << "Mojo Channel is enabled on host";
+ scoped_refptr<base::TaskRunner> io_task_runner =
+ BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
+ ->task_runner();
if (!channel_mojo_host_) {
- channel_mojo_host_.reset(new IPC::ChannelMojoHost(
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)));
+ channel_mojo_host_.reset(new IPC::ChannelMojoHost(io_task_runner));
+ }
+
+ if (run_renderer_in_process()) {
+ ChannelInit::SetSingleProcessIOTaskRunner(io_task_runner);
}
return IPC::ChannelProxy::Create(
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index 5df6631..8acc37d 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -49,12 +49,14 @@
#include "content/child/thread_safe_sender.h"
#include "content/child/websocket_dispatcher.h"
#include "content/common/child_process_messages.h"
+#include "content/common/mojo/channel_init.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_logging.h"
#include "ipc/ipc_switches.h"
#include "ipc/ipc_sync_channel.h"
#include "ipc/ipc_sync_message_filter.h"
#include "ipc/mojo/ipc_channel_mojo.h"
+#include "ipc/mojo/scoped_ipc_support.h"
#if defined(OS_WIN)
#include "content/common/handle_enumerator_win.h"
@@ -203,6 +205,42 @@ ChildThread* ChildThread::Get() {
return ChildThreadImpl::current();
}
+// Mojo client channel delegate to be used in single process mode.
+class ChildThreadImpl::SingleProcessChannelDelegate
+ : public IPC::ChannelMojo::Delegate {
+ public:
+ explicit SingleProcessChannelDelegate() : weak_factory_(this) {}
+
+ ~SingleProcessChannelDelegate() override {}
+
+ base::WeakPtr<IPC::ChannelMojo::Delegate> ToWeakPtr() override {
+ return weak_factory_.GetWeakPtr();
+ }
+
+ scoped_refptr<base::TaskRunner> GetIOTaskRunner() override {
+ return ChannelInit::GetSingleProcessIOTaskRunner();
+ }
+
+ void OnChannelCreated(base::WeakPtr<IPC::ChannelMojo> channel) override {}
+
+ void DeleteSoon() {
+ ChannelInit::GetSingleProcessIOTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&base::DeletePointer<SingleProcessChannelDelegate>,
+ base::Unretained(this)));
+ }
+
+ private:
+ base::WeakPtrFactory<IPC::ChannelMojo::Delegate> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SingleProcessChannelDelegate);
+};
+
+void ChildThreadImpl::SingleProcessChannelDelegateDeleter::operator()(
+ SingleProcessChannelDelegate* delegate) const {
+ delegate->DeleteSoon();
+}
+
ChildThreadImpl::Options::Options()
: channel_name(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessChannelID)),
@@ -250,8 +288,20 @@ void ChildThreadImpl::ConnectChannel(bool use_mojo_channel) {
bool create_pipe_now = true;
if (use_mojo_channel) {
VLOG(1) << "Mojo is enabled on child";
- channel_->Init(IPC::ChannelMojo::CreateClientFactory(channel_name_),
- create_pipe_now);
+ scoped_refptr<base::TaskRunner> io_task_runner =
+ ChannelInit::GetSingleProcessIOTaskRunner();
+ if (io_task_runner) {
+ single_process_channel_delegate_.reset(new SingleProcessChannelDelegate);
+ } else {
+ io_task_runner = ChildProcess::current()->io_message_loop_proxy();
+ }
+ DCHECK(io_task_runner);
+ ipc_support_.reset(new IPC::ScopedIPCSupport(io_task_runner));
+ channel_->Init(
+ IPC::ChannelMojo::CreateClientFactory(
+ single_process_channel_delegate_.get(),
+ channel_name_),
+ create_pipe_now);
return;
}
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h
index 4016861..b6094b5 100644
--- a/content/child/child_thread_impl.h
+++ b/content/child/child_thread_impl.h
@@ -29,6 +29,7 @@ class TraceMemoryController;
namespace IPC {
class MessageFilter;
+class ScopedIPCSupport;
class SyncChannel;
class SyncMessageFilter;
} // namespace IPC
@@ -239,6 +240,15 @@ class CONTENT_EXPORT ChildThreadImpl
void EnsureConnected();
+ class SingleProcessChannelDelegate;
+ class SingleProcessChannelDelegateDeleter {
+ public:
+ void operator()(SingleProcessChannelDelegate* delegate) const;
+ };
+
+ scoped_ptr<IPC::ScopedIPCSupport> ipc_support_;
+ scoped_ptr<SingleProcessChannelDelegate, SingleProcessChannelDelegateDeleter>
+ single_process_channel_delegate_;
scoped_ptr<MojoApplication> mojo_application_;
std::string channel_name_;
diff --git a/content/child/mojo/mojo_application.cc b/content/child/mojo/mojo_application.cc
index 34fc314..f896dc6 100644
--- a/content/child/mojo/mojo_application.cc
+++ b/content/child/mojo/mojo_application.cc
@@ -6,6 +6,7 @@
#include "content/child/child_process.h"
#include "content/common/application_setup.mojom.h"
+#include "content/common/mojo/channel_init.h"
#include "content/common/mojo/mojo_messages.h"
#include "ipc/ipc_message.h"
#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h"
@@ -34,9 +35,15 @@ void MojoApplication::OnActivate(
#elif defined(OS_WIN)
base::PlatformFile handle = file;
#endif
+ scoped_refptr<base::TaskRunner> io_task_runner =
+ ChannelInit::GetSingleProcessIOTaskRunner();
+ if (!io_task_runner) {
+ io_task_runner = ChildProcess::current()->io_message_loop_proxy();
+ }
+ DCHECK(io_task_runner);
+
mojo::ScopedMessagePipeHandle message_pipe =
- channel_init_.Init(handle,
- ChildProcess::current()->io_message_loop_proxy());
+ channel_init_.Init(handle, io_task_runner);
DCHECK(message_pipe.is_valid());
ApplicationSetupPtr application_setup;
diff --git a/content/child/mojo/mojo_application.h b/content/child/mojo/mojo_application.h
index 481c072..5b89ddb 100644
--- a/content/child/mojo/mojo_application.h
+++ b/content/child/mojo/mojo_application.h
@@ -5,9 +5,9 @@
#ifndef CONTENT_CHILD_MOJO_MOJO_APPLICATION_H_
#define CONTENT_CHILD_MOJO_MOJO_APPLICATION_H_
+#include "content/common/mojo/channel_init.h"
#include "content/common/mojo/service_registry_impl.h"
#include "ipc/ipc_platform_file.h"
-#include "third_party/mojo/src/mojo/edk/embedder/channel_init.h"
namespace IPC {
class Message;
@@ -31,7 +31,7 @@ class MojoApplication {
private:
void OnActivate(const IPC::PlatformFileForTransit& file);
- mojo::embedder::ChannelInit channel_init_;
+ ChannelInit channel_init_;
ServiceRegistryImpl service_registry_;
diff --git a/content/common/mojo/channel_init.cc b/content/common/mojo/channel_init.cc
new file mode 100644
index 0000000..1599eb11
--- /dev/null
+++ b/content/common/mojo/channel_init.cc
@@ -0,0 +1,80 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/mojo/channel_init.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/lazy_instance.h"
+#include "base/message_loop/message_loop.h"
+#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+
+namespace content {
+
+namespace {
+
+base::LazyInstance<scoped_refptr<base::TaskRunner>>
+ g_single_process_task_runner = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+ChannelInit::ChannelInit() : channel_info_(nullptr), weak_factory_(this) {}
+
+ChannelInit::~ChannelInit() {
+ if (channel_info_)
+ mojo::embedder::DestroyChannel(channel_info_,
+ base::Bind(&base::DoNothing), nullptr);
+}
+
+mojo::ScopedMessagePipeHandle ChannelInit::Init(
+ base::PlatformFile file,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner) {
+ scoped_ptr<IPC::ScopedIPCSupport> ipc_support(
+ new IPC::ScopedIPCSupport(io_thread_task_runner));
+ mojo::ScopedMessagePipeHandle message_pipe =
+ mojo::embedder::CreateChannel(
+ mojo::embedder::ScopedPlatformHandle(
+ mojo::embedder::PlatformHandle(file)),
+ io_thread_task_runner,
+ base::Bind(&ChannelInit::OnCreatedChannel,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(&ipc_support)),
+ base::MessageLoop::current()->task_runner()).Pass();
+ return message_pipe.Pass();
+}
+
+void ChannelInit::WillDestroySoon() {
+ if (channel_info_)
+ mojo::embedder::WillDestroyChannelSoon(channel_info_);
+}
+
+// static
+scoped_refptr<base::TaskRunner> ChannelInit::GetSingleProcessIOTaskRunner() {
+ return g_single_process_task_runner.Get();
+}
+
+// static
+void ChannelInit::SetSingleProcessIOTaskRunner(
+ scoped_refptr<base::TaskRunner> io_task_runner) {
+ g_single_process_task_runner.Get() = io_task_runner;
+}
+
+// static
+void ChannelInit::OnCreatedChannel(
+ base::WeakPtr<ChannelInit> self,
+ scoped_ptr<IPC::ScopedIPCSupport> ipc_support,
+ mojo::embedder::ChannelInfo* channel) {
+ // If |self| was already destroyed, shut the channel down.
+ if (!self) {
+ mojo::embedder::DestroyChannel(channel,
+ base::Bind(&base::DoNothing), nullptr);
+ return;
+ }
+
+ DCHECK(!self->channel_info_);
+ self->channel_info_ = channel;
+ self->ipc_support_ = ipc_support.Pass();
+}
+
+} // namespace content
diff --git a/content/common/mojo/channel_init.h b/content/common/mojo/channel_init.h
new file mode 100644
index 0000000..659d4bb
--- /dev/null
+++ b/content/common/mojo/channel_init.h
@@ -0,0 +1,64 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_MOJO_CHANNEL_INIT_H_
+#define CONTENT_COMMON_MOJO_CHANNEL_INIT_H_
+
+#include "base/files/file.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "ipc/mojo/scoped_ipc_support.h"
+#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h"
+#include "third_party/mojo/src/mojo/public/cpp/system/message_pipe.h"
+
+namespace base {
+class MessageLoopProxy;
+class TaskRunner;
+}
+
+namespace content {
+
+// ChannelInit handles creation and destruction of the Mojo channel. It is not
+// thread-safe, but may be used on any single thread with a MessageLoop.
+class CONTENT_EXPORT ChannelInit {
+ public:
+ ChannelInit();
+ ~ChannelInit();
+
+ // Initializes the channel. This takes ownership of |file|. Returns the
+ // primordial MessagePipe for the channel.
+ mojo::ScopedMessagePipeHandle Init(
+ base::PlatformFile file,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner);
+
+ // Notifies the channel that we (hence it) will soon be destroyed.
+ void WillDestroySoon();
+
+ // Get/Set a shared I/O TaskRunner for children to use in single process mode.
+ static scoped_refptr<base::TaskRunner> GetSingleProcessIOTaskRunner();
+ static void SetSingleProcessIOTaskRunner(
+ scoped_refptr<base::TaskRunner> io_task_runner);
+
+ private:
+ // Invoked on the thread on which this object lives once the channel has been
+ // established. This is a static method that takes a weak pointer to self,
+ // since we want to destroy the channel if we were destroyed first.
+ static void OnCreatedChannel(
+ base::WeakPtr<ChannelInit> self,
+ scoped_ptr<IPC::ScopedIPCSupport> ipc_support,
+ mojo::embedder::ChannelInfo* channel);
+
+ // If non-null the channel has been established.
+ mojo::embedder::ChannelInfo* channel_info_;
+
+ scoped_ptr<IPC::ScopedIPCSupport> ipc_support_;
+ base::WeakPtrFactory<ChannelInit> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChannelInit);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_MOJO_CHANNEL_INIT_H_
diff --git a/content/content_common.gypi b/content/content_common.gypi
index c62e10f..3a63205 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -416,6 +416,8 @@
'common/message_router.cc',
'common/message_router.h',
'common/mime_registry_messages.h',
+ 'common/mojo/channel_init.cc',
+ 'common/mojo/channel_init.h',
'common/mojo/mojo_messages.h',
'common/mojo/service_registry_impl.cc',
'common/mojo/service_registry_impl.h',
diff --git a/content/test/data/web_ui_mojo.js b/content/test/data/web_ui_mojo.js
index 38b0194..978d068 100644
--- a/content/test/data/web_ui_mojo.js
+++ b/content/test/data/web_ui_mojo.js
@@ -3,17 +3,16 @@
// found in the LICENSE file.
define('main', [
- 'mojo/public/js/connection',
+ 'mojo/public/js/router',
'content/test/data/web_ui_test_mojo_bindings.mojom',
'content/public/renderer/service_provider',
-], function (connection, bindings, serviceProvider) {
+], function (router, bindings, serviceProvider) {
var browserTarget;
return function() {
- browserTarget = connection.bindProxyHandle(
- serviceProvider.connectToService(bindings.BrowserTarget.name),
- undefined,
- bindings.BrowserTarget);
+ browserTarget = new bindings.BrowserTarget.proxyClass(
+ new router.Router(
+ serviceProvider.connectToService(bindings.BrowserTarget.name)));
browserTarget.start().then(function() {
browserTarget.stop();
diff --git a/content/test/render_thread_impl_browser_test_ipc_helper.cc b/content/test/render_thread_impl_browser_test_ipc_helper.cc
index 59d09c2..3075f75 100644
--- a/content/test/render_thread_impl_browser_test_ipc_helper.cc
+++ b/content/test/render_thread_impl_browser_test_ipc_helper.cc
@@ -4,6 +4,7 @@
#include "content/test/render_thread_impl_browser_test_ipc_helper.h"
+#include "content/common/mojo/channel_init.h"
#include "ipc/mojo/ipc_channel_mojo_host.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -40,13 +41,17 @@ void RenderThreadImplBrowserIPCTestHelper::SetupIpcThread() {
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_IO;
ASSERT_TRUE(ipc_thread_->StartWithOptions(options));
+ ChannelInit::SetSingleProcessIOTaskRunner(ipc_thread_->task_runner());
}
void RenderThreadImplBrowserIPCTestHelper::SetupMojo() {
InitializeMojo();
+ ipc_support_.reset(new IPC::ScopedIPCSupport(ipc_thread_->task_runner()));
mojo_host_.reset(new IPC::ChannelMojoHost(ipc_thread_->task_runner()));
mojo_application_host_.reset(new MojoApplicationHost());
+ mojo_application_host_->OverrideIOTaskRunnerForTest(
+ ipc_thread_->task_runner());
channel_ = IPC::ChannelProxy::Create(
IPC::ChannelMojo::CreateServerFactory(mojo_host_->channel_delegate(),
diff --git a/content/test/render_thread_impl_browser_test_ipc_helper.h b/content/test/render_thread_impl_browser_test_ipc_helper.h
index ce3b257..b2eebd4 100644
--- a/content/test/render_thread_impl_browser_test_ipc_helper.h
+++ b/content/test/render_thread_impl_browser_test_ipc_helper.h
@@ -10,6 +10,7 @@
#include "content/common/mojo/mojo_messages.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/mojo/ipc_channel_mojo.h"
+#include "ipc/mojo/scoped_ipc_support.h"
namespace IPC {
class ChannelMojoHost;
@@ -42,6 +43,7 @@ class RenderThreadImplBrowserIPCTestHelper {
scoped_ptr<base::Thread> ipc_thread_;
scoped_ptr<base::MessageLoopForIO> message_loop_;
scoped_ptr<DummyListener> dummy_listener_;
+ scoped_ptr<IPC::ScopedIPCSupport> ipc_support_;
scoped_ptr<MojoApplicationHost> mojo_application_host_;
scoped_ptr<IPC::ChannelMojoHost> mojo_host_;
std::string channel_id_;
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp
index 632c498..c8fdbc5 100644
--- a/crypto/crypto.gyp
+++ b/crypto/crypto.gyp
@@ -238,7 +238,7 @@
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
],
'sources': [
- '<@(hmac_win64_related_sources)',
+ '<@(nacl_win64_sources)',
],
'defines': [
'CRYPTO_IMPLEMENTATION',
diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi
index 82b5da5..6fdbdf4 100644
--- a/crypto/crypto.gypi
+++ b/crypto/crypto.gypi
@@ -23,7 +23,6 @@
'wincrypt_shim.h',
],
},
- 'hmac_win64_related_sources': [ '<@(hmac_win64_related_sources)' ],
'crypto_sources': [
# NOTE: all transitive dependencies of HMAC on windows need
# to be placed in the source list above.
@@ -100,6 +99,11 @@
'third_party/nss/pk11akey.cc',
'third_party/nss/rsawrapr.c',
'third_party/nss/secsign.cc',
- ]
+ ],
+ 'nacl_win64_sources': [
+ '<@(hmac_win64_related_sources)',
+ 'random.cc',
+ 'random.h',
+ ],
}
}
diff --git a/ipc/mojo/BUILD.gn b/ipc/mojo/BUILD.gn
index 39855c4..6d2a9f8 100644
--- a/ipc/mojo/BUILD.gn
+++ b/ipc/mojo/BUILD.gn
@@ -28,6 +28,8 @@ component("mojo") {
"ipc_mojo_handle_attachment.h",
"ipc_mojo_message_helper.cc",
"ipc_mojo_message_helper.h",
+ "scoped_ipc_support.cc",
+ "scoped_ipc_support.h",
]
defines = [ "IPC_MOJO_IMPLEMENTATION" ]
diff --git a/ipc/mojo/ipc_channel_mojo.cc b/ipc/mojo/ipc_channel_mojo.cc
index 0c6c994..6cf8130 100644
--- a/ipc/mojo/ipc_channel_mojo.cc
+++ b/ipc/mojo/ipc_channel_mojo.cc
@@ -48,9 +48,9 @@ class MojoChannelFactory : public ChannelFactory {
//------------------------------------------------------------------------------
-class ClientChannelMojo
- : public ChannelMojo,
- public NON_EXPORTED_BASE(mojo::InterfaceImpl<ClientChannel>) {
+class ClientChannelMojo : public ChannelMojo,
+ public ClientChannel,
+ public mojo::ErrorHandler {
public:
ClientChannelMojo(ChannelMojo::Delegate* delegate,
const ChannelHandle& handle,
@@ -58,7 +58,7 @@ class ClientChannelMojo
~ClientChannelMojo() override;
// MojoBootstrap::Delegate implementation
void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
- // InterfaceImpl implementation
+ // mojo::ErrorHandler implementation
void OnConnectionError() override;
// ClientChannel implementation
void Init(
@@ -66,13 +66,17 @@ class ClientChannelMojo
int32_t peer_pid,
const mojo::Callback<void(int32_t)>& callback) override;
+ private:
+ mojo::Binding<ClientChannel> binding_;
+
DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
};
ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate,
const ChannelHandle& handle,
Listener* listener)
- : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener) {
+ : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener),
+ binding_(this) {
}
ClientChannelMojo::~ClientChannelMojo() {
@@ -80,7 +84,7 @@ ClientChannelMojo::~ClientChannelMojo() {
void ClientChannelMojo::OnPipeAvailable(
mojo::embedder::ScopedPlatformHandle handle) {
- mojo::WeakBindToPipe(this, CreateMessagingPipe(handle.Pass()));
+ binding_.Bind(CreateMessagingPipe(handle.Pass()));
}
void ClientChannelMojo::OnConnectionError() {
@@ -106,7 +110,7 @@ class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler {
// MojoBootstrap::Delegate implementation
void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
- // ErrorHandler implementation
+ // mojo::ErrorHandler implementation
void OnConnectionError() override;
// Channel override
void Close() override;
@@ -180,7 +184,7 @@ base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
void ChannelMojo::ChannelInfoDeleter::operator()(
mojo::embedder::ChannelInfo* ptr) const {
- mojo::embedder::DestroyChannel(ptr);
+ mojo::embedder::DestroyChannel(ptr, base::Bind(&base::DoNothing), nullptr);
}
//------------------------------------------------------------------------------
@@ -219,9 +223,10 @@ scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
// static
scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
+ ChannelMojo::Delegate* delegate,
const ChannelHandle& channel_handle) {
return make_scoped_ptr(
- new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT));
+ new MojoChannelFactory(delegate, channel_handle, Channel::MODE_CLIENT));
}
ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
@@ -253,6 +258,8 @@ ChannelMojo::~ChannelMojo() {
}
void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
+ ipc_support_.reset(
+ new ScopedIPCSupport(base::MessageLoop::current()->task_runner()));
delegate_ = delegate->ToWeakPtr();
delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
}
@@ -275,6 +282,7 @@ bool ChannelMojo::Connect() {
void ChannelMojo::Close() {
message_reader_.reset();
channel_info_.reset();
+ ipc_support_.reset();
}
void ChannelMojo::OnBootstrapError() {
@@ -288,7 +296,7 @@ void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
for (size_t i = 0; i < pending_messages_.size(); ++i) {
bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
- pending_messages_[i] = NULL;
+ pending_messages_[i] = nullptr;
if (!sent) {
pending_messages_.clear();
listener_->OnChannelError();
diff --git a/ipc/mojo/ipc_channel_mojo.h b/ipc/mojo/ipc_channel_mojo.h
index 71d1d10..1959e0f 100644
--- a/ipc/mojo/ipc_channel_mojo.h
+++ b/ipc/mojo/ipc_channel_mojo.h
@@ -15,6 +15,7 @@
#include "ipc/ipc_export.h"
#include "ipc/mojo/ipc_message_pipe_reader.h"
#include "ipc/mojo/ipc_mojo_bootstrap.h"
+#include "ipc/mojo/scoped_ipc_support.h"
#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h"
#include "third_party/mojo/src/mojo/public/cpp/system/core.h"
@@ -75,6 +76,7 @@ class IPC_MOJO_EXPORT ChannelMojo
const ChannelHandle& channel_handle);
static scoped_ptr<ChannelFactory> CreateClientFactory(
+ Delegate* delegate,
const ChannelHandle& channel_handle);
~ChannelMojo() override;
@@ -147,6 +149,8 @@ class IPC_MOJO_EXPORT ChannelMojo
scoped_ptr<internal::MessagePipeReader, ReaderDeleter> message_reader_;
ScopedVector<Message> pending_messages_;
+ scoped_ptr<ScopedIPCSupport> ipc_support_;
+
base::WeakPtrFactory<ChannelMojo> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ChannelMojo);
diff --git a/ipc/mojo/ipc_channel_mojo_unittest.cc b/ipc/mojo/ipc_channel_mojo_unittest.cc
index d0ab5d6..c6d1894 100644
--- a/ipc/mojo/ipc_channel_mojo_unittest.cc
+++ b/ipc/mojo/ipc_channel_mojo_unittest.cc
@@ -9,6 +9,7 @@
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/pickle.h"
+#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread.h"
#include "ipc/ipc_message.h"
@@ -17,6 +18,7 @@
#include "ipc/mojo/ipc_channel_mojo_host.h"
#include "ipc/mojo/ipc_mojo_handle_attachment.h"
#include "ipc/mojo/ipc_mojo_message_helper.h"
+#include "ipc/mojo/scoped_ipc_support.h"
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
@@ -63,6 +65,8 @@ class ListenerThatExpectsOK : public IPC::Listener {
class ChannelClient {
public:
explicit ChannelClient(IPC::Listener* listener, const char* name) {
+ ipc_support_.reset(
+ new IPC::ScopedIPCSupport(main_message_loop_.task_runner()));
channel_ = IPC::ChannelMojo::Create(NULL,
IPCTestBase::GetChannelName(name),
IPC::Channel::MODE_CLIENT,
@@ -73,14 +77,45 @@ class ChannelClient {
CHECK(channel_->Connect());
}
+ void Close() {
+ channel_->Close();
+
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
IPC::ChannelMojo* channel() const { return channel_.get(); }
private:
base::MessageLoopForIO main_message_loop_;
+ scoped_ptr<IPC::ScopedIPCSupport> ipc_support_;
scoped_ptr<IPC::ChannelMojo> channel_;
};
-class IPCChannelMojoTest : public IPCTestBase {
+class IPCChannelMojoTestBase : public IPCTestBase {
+ public:
+ void InitWithMojo(const std::string& test_client_name) {
+ Init(test_client_name);
+ ipc_support_.reset(new IPC::ScopedIPCSupport(task_runner()));
+ }
+
+ void TearDown() override {
+ // Make sure Mojo IPC support is properly shutdown on the I/O loop before
+ // TearDown continues.
+ ipc_support_.reset();
+ base::RunLoop run_loop;
+ task_runner()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+
+ IPCTestBase::TearDown();
+ }
+
+ private:
+ scoped_ptr<IPC::ScopedIPCSupport> ipc_support_;
+};
+
+class IPCChannelMojoTest : public IPCChannelMojoTestBase {
protected:
scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
const IPC::ChannelHandle& handle,
@@ -122,7 +157,7 @@ class TestChannelListenerWithExtraExpectations
};
TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
- Init("IPCChannelMojoTestClient");
+ InitWithMojo("IPCChannelMojoTestClient");
// Set up IPC channel and start client.
TestChannelListenerWithExtraExpectations listener;
@@ -159,6 +194,8 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
EXPECT_TRUE(listener.is_connected_called());
EXPECT_TRUE(listener.HasSentAll());
+ client.Close();
+
return 0;
}
@@ -186,7 +223,7 @@ class ListenerExpectingErrors : public IPC::Listener {
};
-class IPCChannelMojoErrorTest : public IPCTestBase {
+class IPCChannelMojoErrorTest : public IPCChannelMojoTestBase {
protected:
scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
const IPC::ChannelHandle& handle,
@@ -229,11 +266,13 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
base::MessageLoop::current()->Run();
+ client.Close();
+
return 0;
}
TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
- Init("IPCChannelMojoErraticTestClient");
+ InitWithMojo("IPCChannelMojoErraticTestClient");
// Set up IPC channel and start client.
ListenerExpectingErrors listener;
@@ -373,7 +412,7 @@ class ListenerThatExpectsMessagePipe : public IPC::Listener {
};
TEST_F(IPCChannelMojoTest, SendMessagePipe) {
- Init("IPCChannelMojoTestSendMessagePipeClient");
+ InitWithMojo("IPCChannelMojoTestSendMessagePipeClient");
ListenerThatExpectsOK listener;
CreateChannel(&listener);
@@ -398,11 +437,13 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendMessagePipeClient) {
base::MessageLoop::current()->Run();
+ client.Close();
+
return 0;
}
#if defined(OS_WIN)
-class IPCChannelMojoDeadHandleTest : public IPCTestBase {
+class IPCChannelMojoDeadHandleTest : public IPCChannelMojoTestBase {
protected:
virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
const IPC::ChannelHandle& handle,
@@ -429,7 +470,7 @@ class IPCChannelMojoDeadHandleTest : public IPCTestBase {
TEST_F(IPCChannelMojoDeadHandleTest, InvalidClientHandle) {
// Any client type is fine as it is going to be killed anyway.
- Init("IPCChannelMojoTestDoNothingClient");
+ InitWithMojo("IPCChannelMojoTestDoNothingClient");
// Set up IPC channel and start client.
ListenerExpectingErrors listener;
@@ -489,7 +530,7 @@ class ListenerThatExpectsFile : public IPC::Listener {
TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
- Init("IPCChannelMojoTestSendPlatformHandleClient");
+ InitWithMojo("IPCChannelMojoTestSendPlatformHandleClient");
ListenerThatExpectsOK listener;
CreateChannel(&listener);
@@ -517,6 +558,8 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
base::MessageLoop::current()->Run();
+ client.Close();
+
return 0;
}
@@ -544,7 +587,7 @@ class ListenerThatExpectsFileAndPipe : public IPC::Listener {
};
TEST_F(IPCChannelMojoTest, SendPlatformHandleAndPipe) {
- Init("IPCChannelMojoTestSendPlatformHandleAndPipeClient");
+ InitWithMojo("IPCChannelMojoTestSendPlatformHandleAndPipeClient");
ListenerThatExpectsOK listener;
CreateChannel(&listener);
@@ -574,6 +617,8 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(
base::MessageLoop::current()->Run();
+ client.Close();
+
return 0;
}
@@ -597,7 +642,7 @@ class ListenerThatVerifiesPeerPid : public IPC::Listener {
};
TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
- Init("IPCChannelMojoTestVerifyGlobalPidClient");
+ InitWithMojo("IPCChannelMojoTestVerifyGlobalPidClient");
ListenerThatVerifiesPeerPid listener;
CreateChannel(&listener);
@@ -605,7 +650,7 @@ TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
ASSERT_TRUE(StartClient());
base::MessageLoop::current()->Run();
- this->channel()->Close();
+ channel()->Close();
EXPECT_TRUE(WaitForClientShutdown());
DestroyChannel();
@@ -620,6 +665,8 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestVerifyGlobalPidClient) {
base::MessageLoop::current()->Run();
+ client.Close();
+
return 0;
}
diff --git a/ipc/mojo/ipc_mojo.gyp b/ipc/mojo/ipc_mojo.gyp
index 0f746fc..44f1817 100644
--- a/ipc/mojo/ipc_mojo.gyp
+++ b/ipc/mojo/ipc_mojo.gyp
@@ -42,6 +42,8 @@
'ipc_mojo_message_helper.h',
'ipc_message_pipe_reader.cc',
'ipc_message_pipe_reader.h',
+ 'scoped_ipc_support.cc',
+ 'scoped_ipc_support.h',
],
# TODO(gregoryd): direct_dependent_settings should be shared with the
# 64-bit target, but it doesn't work due to a bug in gyp
diff --git a/ipc/mojo/scoped_ipc_support.cc b/ipc/mojo/scoped_ipc_support.cc
new file mode 100644
index 0000000..fafc9c2
--- /dev/null
+++ b/ipc/mojo/scoped_ipc_support.cc
@@ -0,0 +1,112 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ipc/mojo/scoped_ipc_support.h"
+
+#include "base/bind.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "third_party/mojo/src/mojo/edk/embedder/process_delegate.h"
+
+namespace IPC {
+
+namespace {
+
+class IPCSupportInitializer : public mojo::embedder::ProcessDelegate {
+ public:
+ IPCSupportInitializer()
+ : init_count_(0),
+ shutting_down_(false) {
+ }
+
+ ~IPCSupportInitializer() override {}
+
+ void Init(scoped_refptr<base::TaskRunner> io_thread_task_runner) {
+ base::AutoLock locker(lock_);
+ DCHECK((init_count_ == 0 && !io_thread_task_runner_) ||
+ io_thread_task_runner_ == io_thread_task_runner);
+
+ if (shutting_down_) {
+ // If reinitialized before a pending shutdown task is executed, we
+ // effectively cancel the shutdown task.
+ DCHECK(init_count_ == 1);
+ shutting_down_ = false;
+ return;
+ }
+
+ init_count_++;
+ if (init_count_ == 1) {
+ io_thread_task_runner_ = io_thread_task_runner;
+ mojo::embedder::InitIPCSupport(mojo::embedder::ProcessType::NONE,
+ io_thread_task_runner_,
+ this, io_thread_task_runner_,
+ mojo::embedder::ScopedPlatformHandle());
+ }
+ }
+
+ void ShutDown() {
+ base::AutoLock locker(lock_);
+ DCHECK(init_count_ > 0);
+ DCHECK(!shutting_down_);
+
+ if (init_count_ > 1) {
+ init_count_--;
+ return;
+ }
+
+ shutting_down_ = true;
+ if (base::MessageLoop::current() &&
+ base::MessageLoop::current()->task_runner() == io_thread_task_runner_) {
+ base::AutoUnlock unlocker_(lock_);
+ ShutDownOnIOThread();
+ } else {
+ io_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&IPCSupportInitializer::ShutDownOnIOThread,
+ base::Unretained(this)));
+ }
+ }
+
+ private:
+ void ShutDownOnIOThread() {
+ base::AutoLock locker(lock_);
+ if (shutting_down_) {
+ DCHECK(init_count_ == 1);
+ mojo::embedder::ShutdownIPCSupportOnIOThread();
+ init_count_ = 0;
+ shutting_down_ = false;
+ io_thread_task_runner_ = nullptr;
+ }
+ }
+
+ void OnShutdownComplete() override {}
+
+ base::Lock lock_;
+ size_t init_count_;
+ bool shutting_down_;
+
+ scoped_refptr<base::TaskRunner> io_thread_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(IPCSupportInitializer);
+};
+
+base::LazyInstance<IPCSupportInitializer>::Leaky ipc_support_initializer;
+
+} // namespace
+
+ScopedIPCSupport::ScopedIPCSupport(
+ scoped_refptr<base::TaskRunner> io_thread_task_runner) {
+ ipc_support_initializer.Get().Init(io_thread_task_runner);
+}
+
+ScopedIPCSupport::~ScopedIPCSupport() {
+ ipc_support_initializer.Get().ShutDown();
+}
+
+} // namespace IPC
diff --git a/ipc/mojo/scoped_ipc_support.h b/ipc/mojo/scoped_ipc_support.h
new file mode 100644
index 0000000..21013fa
--- /dev/null
+++ b/ipc/mojo/scoped_ipc_support.h
@@ -0,0 +1,34 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IPC_MOJO_SCOPED_IPC_SUPPORT_H_
+#define IPC_MOJO_SCOPED_IPC_SUPPORT_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/task_runner.h"
+#include "ipc/ipc_export.h"
+
+namespace IPC {
+
+// Perform any necessary Mojo IPC initialization. A ScopedIPCSupport object
+// should be instantiated and retained by any component which makes direct calls
+// to the Mojo EDK. This is used to ensure that the EDK is initialized within
+// the current process and that it is shutdown cleanly when no longer in use.
+//
+// NOTE: Unless you are making explicit calls to functions in the
+// mojo::embedder namespace, you almost definitely DO NOT need this and should
+// not be using it.
+class IPC_MOJO_EXPORT ScopedIPCSupport {
+ public:
+ ScopedIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner);
+ ~ScopedIPCSupport();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport);
+};
+
+} // namespace IPC
+
+#endif // IPC_MOJO_SCOPED_IPC_SUPPORT_H_
diff --git a/mojo/android/BUILD.gn b/mojo/android/BUILD.gn
index c21dc3f..d99e716 100644
--- a/mojo/android/BUILD.gn
+++ b/mojo/android/BUILD.gn
@@ -85,7 +85,6 @@ android_library("mojo_javatests") {
"javatests/src/org/chromium/mojo/bindings/ValidationTest.java",
"javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java",
"javatests/src/org/chromium/mojo/bindings/ValidationTestUtilTest.java",
- "javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterface2TestHelper.java",
"javatests/src/org/chromium/mojo/system/impl/CoreImplTest.java",
]
diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java
index 4744508..3b332e1 100644
--- a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java
+++ b/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java
@@ -10,7 +10,6 @@ import org.chromium.mojo.MojoTestCase;
import org.chromium.mojo.bindings.BindingsTestUtils.CapturingErrorHandler;
import org.chromium.mojo.bindings.test.mojom.imported.ImportedInterface;
import org.chromium.mojo.bindings.test.mojom.sample.Factory;
-import org.chromium.mojo.bindings.test.mojom.sample.FactoryClient;
import org.chromium.mojo.bindings.test.mojom.sample.NamedObject;
import org.chromium.mojo.bindings.test.mojom.sample.NamedObject.GetNameResponse;
import org.chromium.mojo.bindings.test.mojom.sample.Request;
@@ -101,18 +100,11 @@ public class InterfacesTest extends MojoTestCase {
public class MockFactoryImpl extends CapturingErrorHandler implements Factory {
private boolean mClosed = false;
- private FactoryClient mFactoryClient;
public boolean isClosed() {
return mClosed;
}
- @Override
- public void setClient(FactoryClient client) {
- mFactoryClient = client;
- mCloseablesToClose.add(client);
- }
-
/**
* @see org.chromium.mojo.bindings.Interface#close()
*/
@@ -122,17 +114,18 @@ public class InterfacesTest extends MojoTestCase {
}
@Override
- public void doStuff(Request request, MessagePipeHandle pipe) {
+ public void doStuff(Request request, MessagePipeHandle pipe, DoStuffResponse callback) {
if (pipe != null) {
pipe.close();
}
Response response = new Response();
response.x = 42;
- mFactoryClient.didStuff(response, "Hello");
+
+ callback.call(response, "Hello");
}
@Override
- public void doStuff2(ConsumerHandle pipe) {
+ public void doStuff2(ConsumerHandle pipe, DoStuff2Response callback) {
}
@Override
@@ -154,54 +147,6 @@ public class InterfacesTest extends MojoTestCase {
}
/**
- * Basic implementation of {@link FactoryClient}.
- */
- public static class MockFactoryClientImpl implements FactoryClient {
-
- private boolean mClosed = false;
- private boolean mDidStuffCalled = false;
-
- public boolean isClosed() {
- return mClosed;
- }
-
- public boolean wasDidStuffCalled() {
- return mDidStuffCalled;
- }
-
- /**
- * @see org.chromium.mojo.bindings.Interface#close()
- */
- @Override
- public void close() {
- mClosed = true;
- }
-
- /**
- * @see ConnectionErrorHandler#onConnectionError(MojoException)
- */
- @Override
- public void onConnectionError(MojoException e) {
- }
-
- /**
- * @see FactoryClient#didStuff(Response, java.lang.String)
- */
- @Override
- public void didStuff(Response response, String text) {
- mDidStuffCalled = true;
- }
-
- /**
- * @see FactoryClient#didStuff2(String)
- */
- @Override
- public void didStuff2(String text) {
- }
-
- }
-
- /**
* @see MojoTestCase#tearDown()
*/
@Override
@@ -225,17 +170,6 @@ public class InterfacesTest extends MojoTestCase {
return proxy;
}
- private <I extends InterfaceWithClient<C>, P extends InterfaceWithClient.Proxy<C>,
- C extends Interface> P newProxyOverPipeWithClient(
- InterfaceWithClient.Manager<I, P, C> manager, I impl, C client) {
- Pair<MessagePipeHandle, MessagePipeHandle> handles =
- CoreImpl.getInstance().createMessagePipe(null);
- P proxy = manager.attachProxy(handles.first, client);
- mCloseablesToClose.add(proxy);
- manager.bind(impl, handles.second);
- return proxy;
- }
-
/**
* Check that the given proxy receives the calls. If |impl| is not null, also check that the
* calls are forwared to |impl|.
@@ -311,34 +245,13 @@ public class InterfacesTest extends MojoTestCase {
@SmallTest
public void testInterfaceClosing() {
MockFactoryImpl impl = new MockFactoryImpl();
- MockFactoryClientImpl client = new MockFactoryClientImpl();
- Factory.Proxy proxy = newProxyOverPipeWithClient(
- Factory.MANAGER, impl, client);
+ Factory.Proxy proxy = newProxyOverPipe(Factory.MANAGER, impl);
assertFalse(impl.isClosed());
- assertFalse(client.isClosed());
proxy.close();
runLoopUntilIdle();
assertTrue(impl.isClosed());
- assertTrue(client.isClosed());
- }
-
- @SmallTest
- public void testClient() {
- MockFactoryImpl impl = new MockFactoryImpl();
- MockFactoryClientImpl client = new MockFactoryClientImpl();
- Factory.Proxy proxy = newProxyOverPipeWithClient(
- Factory.MANAGER, impl, client);
- Request request = new Request();
- request.x = 42;
- proxy.doStuff(request, null);
-
- assertFalse(client.wasDidStuffCalled());
-
- runLoopUntilIdle();
-
- assertTrue(client.wasDidStuffCalled());
}
}
diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java
index 076c94b..7942be6 100644
--- a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java
+++ b/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java
@@ -11,8 +11,7 @@ import org.chromium.base.test.util.UrlUtils;
import org.chromium.mojo.HandleMock;
import org.chromium.mojo.MojoTestCase;
import org.chromium.mojo.bindings.test.mojom.mojo.ConformanceTestInterface;
-import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterface1;
-import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterface2TestHelper;
+import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterface;
import org.chromium.mojo.system.Handle;
import java.io.File;
@@ -119,41 +118,6 @@ public class ValidationTest extends MojoTestCase {
}
}
- private static class RoutingMessageReceiver implements MessageReceiver {
- private final MessageReceiver mRequest;
- private final MessageReceiver mResponse;
-
- private RoutingMessageReceiver(MessageReceiver request, MessageReceiver response) {
- this.mRequest = request;
- this.mResponse = response;
- }
-
- /**
- * @see MessageReceiver#accept(Message)
- */
- @Override
- public boolean accept(Message message) {
- try {
- MessageHeader header = message.asServiceMessage().getHeader();
- if (header.hasFlag(MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
- return mResponse.accept(message);
- } else {
- return mRequest.accept(message);
- }
- } catch (DeserializationException e) {
- return false;
- }
- }
-
- /**
- * @see MessageReceiver#close()
- */
- @Override
- public void close() {
- }
-
- }
-
/**
* A trivial message receiver that refuses all messages it receives.
*/
@@ -188,11 +152,7 @@ public class ValidationTest extends MojoTestCase {
*/
@SmallTest
public void testIntegration() throws FileNotFoundException {
- runTest("integration_",
- new RoutingMessageReceiver(IntegrationTestInterface1.MANAGER.buildStub(null,
- IntegrationTestInterface1.MANAGER.buildProxy(null,
- new SinkMessageReceiver())),
- IntegrationTestInterface2TestHelper
- .newIntegrationTestInterface2MethodCallback()));
+ runTest("integration_", IntegrationTestInterface.MANAGER.buildStub(null,
+ IntegrationTestInterface.MANAGER.buildProxy(null, new SinkMessageReceiver())));
}
}
diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterface2TestHelper.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterface2TestHelper.java
deleted file mode 100644
index 2a2b6b8..0000000
--- a/mojo/android/javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterface2TestHelper.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.mojo.bindings.test.mojom.mojo;
-
-import org.chromium.mojo.bindings.MessageReceiver;
-import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterface2.Method0Response;
-import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterface2_Internal.IntegrationTestInterface2Method0ResponseParamsForwardToCallback;
-
-/**
- * Helper class to access {@link IntegrationTestInterface2_Internal} package protected method for
- * tests.
- */
-public class IntegrationTestInterface2TestHelper {
-
- private static final class SinkMethod0Response implements Method0Response {
- @Override
- public void call(byte[] arg1) {
- }
- }
-
- /**
- * Creates a new {@link MessageReceiver} to use for the callback of
- * |IntegrationTestInterface2#method0(Method0Response)|.
- */
- public static MessageReceiver newIntegrationTestInterface2MethodCallback() {
- return new IntegrationTestInterface2Method0ResponseParamsForwardToCallback(
- new SinkMethod0Response());
- }
-}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java
index 19b2d29..aaa49f2 100644
--- a/mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java
@@ -16,6 +16,7 @@ import org.chromium.mojo.system.MessagePipeHandle;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojo.system.MojoResult;
import org.chromium.mojo.system.Pair;
+import org.chromium.mojo.system.RunLoop;
import org.chromium.mojo.system.SharedBufferHandle;
import org.chromium.mojo.system.SharedBufferHandle.DuplicateOptions;
import org.chromium.mojo.system.SharedBufferHandle.MapFlags;
@@ -206,6 +207,22 @@ public class CoreImpl implements Core, AsyncWaiter {
}
/**
+ * @see Core#createDefaultRunLoop()
+ */
+ @Override
+ public RunLoop createDefaultRunLoop() {
+ return null;
+ }
+
+ /**
+ * @see Core#getCurrentRunLoop()
+ */
+ @Override
+ public RunLoop getCurrentRunLoop() {
+ return null;
+ }
+
+ /**
* @see AsyncWaiter#asyncWait(Handle, Core.HandleSignals, long, Callback)
*/
@Override
diff --git a/mojo/services/html_viewer/html_viewer.cc b/mojo/services/html_viewer/html_viewer.cc
index 1278a24..c89447b 100644
--- a/mojo/services/html_viewer/html_viewer.cc
+++ b/mojo/services/html_viewer/html_viewer.cc
@@ -75,7 +75,9 @@ class HTMLViewerApplication : public mojo::Application {
web_media_player_factory_(web_media_player_factory),
is_headless_(is_headless) {}
- void Initialize(ShellPtr shell, Array<String> args) override {
+ void Initialize(ShellPtr shell,
+ Array<String> args,
+ const String& url) override {
ServiceProviderPtr service_provider;
shell_ = shell.Pass();
shell_->ConnectToApplication("mojo:network_service",
diff --git a/third_party/mojo/mojo_edk.gyp b/third_party/mojo/mojo_edk.gyp
index 01edb62..20aa38a 100644
--- a/third_party/mojo/mojo_edk.gyp
+++ b/third_party/mojo/mojo_edk.gyp
@@ -24,6 +24,7 @@
'dependencies': [
'../../base/base.gyp:base',
'../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../../crypto/crypto.gyp:crypto',
],
'includes': [
'mojo_edk_system_impl.gypi',
@@ -86,6 +87,8 @@
'sources': [
'src/mojo/edk/test/multiprocess_test_helper.cc',
'src/mojo/edk/test/multiprocess_test_helper.h',
+ 'src/mojo/edk/test/scoped_ipc_support.cc',
+ 'src/mojo/edk/test/scoped_ipc_support.h',
'src/mojo/edk/test/test_utils.h',
'src/mojo/edk/test/test_utils_posix.cc',
'src/mojo/edk/test/test_utils_win.cc',
@@ -138,6 +141,7 @@
'dependencies': [
'../../base/base.gyp:base_win64',
'../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
+ '../../crypto/crypto.gyp:crypto_nacl_win64',
],
'includes': [
'mojo_edk_system_impl.gypi',
diff --git a/third_party/mojo/mojo_edk_system_impl.gypi b/third_party/mojo/mojo_edk_system_impl.gypi
index 50991bf..62b8529 100644
--- a/third_party/mojo/mojo_edk_system_impl.gypi
+++ b/third_party/mojo/mojo_edk_system_impl.gypi
@@ -14,8 +14,6 @@
'sources': [
'src/mojo/edk/embedder/configuration.h',
'src/mojo/edk/embedder/channel_info_forward.h',
- 'src/mojo/edk/embedder/channel_init.cc',
- 'src/mojo/edk/embedder/channel_init.h',
'src/mojo/edk/embedder/embedder.cc',
'src/mojo/edk/embedder/embedder.h',
'src/mojo/edk/embedder/embedder_internal.h',
@@ -64,6 +62,7 @@
'src/mojo/edk/system/core.h',
'src/mojo/edk/system/data_pipe.cc',
'src/mojo/edk/system/data_pipe.h',
+ 'src/mojo/edk/system/data_pipe_impl.h',
'src/mojo/edk/system/data_pipe_consumer_dispatcher.cc',
'src/mojo/edk/system/data_pipe_consumer_dispatcher.h',
'src/mojo/edk/system/data_pipe_producer_dispatcher.cc',
@@ -77,12 +76,14 @@
'src/mojo/edk/system/handle_table.h',
'src/mojo/edk/system/incoming_endpoint.cc',
'src/mojo/edk/system/incoming_endpoint.h',
- 'src/mojo/edk/system/local_data_pipe.cc',
- 'src/mojo/edk/system/local_data_pipe.h',
+ 'src/mojo/edk/system/local_data_pipe_impl.cc',
+ 'src/mojo/edk/system/local_data_pipe_impl.h',
'src/mojo/edk/system/local_message_pipe_endpoint.cc',
'src/mojo/edk/system/local_message_pipe_endpoint.h',
'src/mojo/edk/system/mapping_table.cc',
'src/mojo/edk/system/mapping_table.h',
+ 'src/mojo/edk/system/master_connection_manager.cc',
+ 'src/mojo/edk/system/master_connection_manager.h',
'src/mojo/edk/system/memory.cc',
'src/mojo/edk/system/memory.h',
'src/mojo/edk/system/message_in_transit.cc',
@@ -108,8 +109,12 @@
'src/mojo/edk/system/shared_buffer_dispatcher.h',
'src/mojo/edk/system/simple_dispatcher.cc',
'src/mojo/edk/system/simple_dispatcher.h',
+ 'src/mojo/edk/system/slave_connection_manager.cc',
+ 'src/mojo/edk/system/slave_connection_manager.h',
'src/mojo/edk/system/transport_data.cc',
'src/mojo/edk/system/transport_data.h',
+ 'src/mojo/edk/system/unique_identifier.cc',
+ 'src/mojo/edk/system/unique_identifier.h',
'src/mojo/edk/system/waiter.cc',
'src/mojo/edk/system/waiter.h',
# Test-only code:
diff --git a/third_party/mojo/mojo_edk_tests.gyp b/third_party/mojo/mojo_edk_tests.gyp
index 91a777f..13d24cb 100644
--- a/third_party/mojo/mojo_edk_tests.gyp
+++ b/third_party/mojo/mojo_edk_tests.gyp
@@ -177,7 +177,7 @@
'src/mojo/edk/system/core_test_base.h',
'src/mojo/edk/system/data_pipe_unittest.cc',
'src/mojo/edk/system/dispatcher_unittest.cc',
- 'src/mojo/edk/system/local_data_pipe_unittest.cc',
+ 'src/mojo/edk/system/local_data_pipe_impl_unittest.cc',
'src/mojo/edk/system/memory_unittest.cc',
'src/mojo/edk/system/message_pipe_dispatcher_unittest.cc',
'src/mojo/edk/system/message_pipe_test_utils.h',
@@ -193,6 +193,7 @@
'src/mojo/edk/system/simple_dispatcher_unittest.cc',
'src/mojo/edk/system/test_utils.cc',
'src/mojo/edk/system/test_utils.h',
+ 'src/mojo/edk/system/unique_identifier_unittest.cc',
'src/mojo/edk/system/waiter_test_utils.cc',
'src/mojo/edk/system/waiter_test_utils.h',
'src/mojo/edk/system/waiter_unittest.cc',
diff --git a/third_party/mojo/mojo_public.gyp b/third_party/mojo/mojo_public.gyp
index 0ab9e87..683791d 100644
--- a/third_party/mojo/mojo_public.gyp
+++ b/third_party/mojo/mojo_public.gyp
@@ -333,7 +333,6 @@
'src/mojo/public/interfaces/bindings/tests/no_module.mojom',
'src/mojo/public/interfaces/bindings/tests/rect.mojom',
'src/mojo/public/interfaces/bindings/tests/regression_tests.mojom',
- 'src/mojo/public/interfaces/bindings/tests/regression_tests_import.mojom',
'src/mojo/public/interfaces/bindings/tests/sample_factory.mojom',
'src/mojo/public/interfaces/bindings/tests/sample_import.mojom',
'src/mojo/public/interfaces/bindings/tests/sample_import2.mojom',
diff --git a/third_party/mojo/mojom_bindings_generator_variables.gypi b/third_party/mojo/mojom_bindings_generator_variables.gypi
index 727eef0..d09c13c 100644
--- a/third_party/mojo/mojom_bindings_generator_variables.gypi
+++ b/third_party/mojo/mojom_bindings_generator_variables.gypi
@@ -19,7 +19,6 @@
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl',
- '<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl',
diff --git a/third_party/mojo/src/mojo/edk/embedder/BUILD.gn b/third_party/mojo/src/mojo/edk/embedder/BUILD.gn
index 5eb77d7..9650209 100644
--- a/third_party/mojo/src/mojo/edk/embedder/BUILD.gn
+++ b/third_party/mojo/src/mojo/edk/embedder/BUILD.gn
@@ -11,8 +11,6 @@ mojo_edk_source_set("embedder") {
sources = [
"channel_info_forward.h",
- "channel_init.cc",
- "channel_init.h",
"configuration.h",
"embedder.cc",
"embedder.h",
@@ -84,6 +82,7 @@ mojo_edk_source_set("platform") {
deps = [
"//base",
+ "//crypto",
]
if (is_android) {
@@ -100,6 +99,8 @@ mojo_edk_source_set("delegates") {
sources = [
"master_process_delegate.h",
+ "process_delegate.h",
+ "process_type.h",
"slave_process_delegate.h",
]
diff --git a/third_party/mojo/src/mojo/edk/embedder/channel_init.cc b/third_party/mojo/src/mojo/edk/embedder/channel_init.cc
deleted file mode 100644
index 0b6d76c..0000000
--- a/third_party/mojo/src/mojo/edk/embedder/channel_init.cc
+++ /dev/null
@@ -1,56 +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/channel_init.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "mojo/edk/embedder/embedder.h"
-
-namespace mojo {
-namespace embedder {
-
-ChannelInit::ChannelInit() : channel_info_(nullptr), weak_factory_(this) {
-}
-
-ChannelInit::~ChannelInit() {
- // TODO(vtl): This is likely leaky in common scenarios (we're on the main
- // thread, which outlives the I/O thread, and we're destroyed after the I/O
- // thread is destroyed.
- if (channel_info_)
- DestroyChannel(channel_info_);
-}
-
-ScopedMessagePipeHandle ChannelInit::Init(
- base::PlatformFile file,
- scoped_refptr<base::TaskRunner> io_thread_task_runner) {
- ScopedMessagePipeHandle message_pipe =
- CreateChannel(ScopedPlatformHandle(PlatformHandle(file)),
- io_thread_task_runner,
- base::Bind(&ChannelInit::OnCreatedChannel,
- weak_factory_.GetWeakPtr()),
- base::MessageLoop::current()->task_runner()).Pass();
- return message_pipe.Pass();
-}
-
-void ChannelInit::WillDestroySoon() {
- if (channel_info_)
- WillDestroyChannelSoon(channel_info_);
-}
-
-// static
-void ChannelInit::OnCreatedChannel(base::WeakPtr<ChannelInit> self,
- ChannelInfo* channel) {
- // If |self| was already destroyed, shut the channel down.
- if (!self) {
- DestroyChannel(channel);
- return;
- }
-
- DCHECK(!self->channel_info_);
- self->channel_info_ = channel;
-}
-
-} // namespace embedder
-} // namespace mojo
diff --git a/third_party/mojo/src/mojo/edk/embedder/channel_init.h b/third_party/mojo/src/mojo/edk/embedder/channel_init.h
deleted file mode 100644
index 478da41..0000000
--- a/third_party/mojo/src/mojo/edk/embedder/channel_init.h
+++ /dev/null
@@ -1,57 +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_CHANNEL_INIT_H_
-#define MOJO_EDK_EMBEDDER_CHANNEL_INIT_H_
-
-#include "base/files/file.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "mojo/edk/embedder/channel_info_forward.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/cpp/system/message_pipe.h"
-
-namespace base {
-class MessageLoopProxy;
-class TaskRunner;
-}
-
-namespace mojo {
-namespace embedder {
-
-// |ChannelInit| handles creation (and destruction) of the Mojo channel. It is
-// not thread-safe, but may be used on any single thread (with a |MessageLoop|).
-class MOJO_SYSTEM_IMPL_EXPORT ChannelInit {
- public:
- ChannelInit();
- ~ChannelInit();
-
- // Initializes the channel. This takes ownership of |file|. Returns the
- // primordial |MessagePipe| for the channel.
- mojo::ScopedMessagePipeHandle Init(
- base::PlatformFile file,
- scoped_refptr<base::TaskRunner> io_thread_task_runner);
-
- // Notifies the channel that we (hence it) will soon be destroyed.
- void WillDestroySoon();
-
- private:
- // Invoked on the thread on which this object lives once the channel has been
- // established. (This is a static method that takes a weak pointer to self,
- // since we want to destroy the channel even if we're destroyed.)
- static void OnCreatedChannel(base::WeakPtr<ChannelInit> self,
- ChannelInfo* channel);
-
- // If non-null the channel has been established.
- ChannelInfo* channel_info_;
-
- base::WeakPtrFactory<ChannelInit> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ChannelInit);
-};
-
-} // namespace embedder
-} // namespace mojo
-
-#endif // MOJO_EDK_EMBEDDER_CHANNEL_INIT_H_
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.cc b/third_party/mojo/src/mojo/edk/embedder/embedder.cc
index d0a5135..a4997e7 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder.cc
@@ -6,25 +6,60 @@
#include "base/atomicops.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/task_runner.h"
#include "mojo/edk/embedder/embedder_internal.h"
+#include "mojo/edk/embedder/master_process_delegate.h"
#include "mojo/edk/embedder/platform_support.h"
+#include "mojo/edk/embedder/process_delegate.h"
+#include "mojo/edk/embedder/slave_process_delegate.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/channel_manager.h"
#include "mojo/edk/system/configuration.h"
+#include "mojo/edk/system/connection_manager.h"
#include "mojo/edk/system/core.h"
+#include "mojo/edk/system/master_connection_manager.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/system/platform_handle_dispatcher.h"
#include "mojo/edk/system/raw_channel.h"
+#include "mojo/edk/system/slave_connection_manager.h"
namespace mojo {
namespace embedder {
+namespace internal {
+
+// Declared in embedder_internal.h.
+PlatformSupport* g_platform_support = nullptr;
+system::Core* g_core = nullptr;
+ProcessType g_process_type = ProcessType::UNINITIALIZED;
+
+} // namespace internal
+
namespace {
+// The following global variables are set in |InitIPCSupport()| and reset by
+// |ShutdownIPCSupport()|/|ShutdownIPCSupportOnIOThread()|.
+
+// Note: This needs to be |AddRef()|ed/|Release()|d.
+base::TaskRunner* g_delegate_thread_task_runner = nullptr;
+
+ProcessDelegate* g_process_delegate = nullptr;
+
+// Note: This needs to be |AddRef()|ed/|Release()|d.
+base::TaskRunner* g_io_thread_task_runner = nullptr;
+
+// Instance of |ConnectionManager| used by the channel manager (below).
+system::ConnectionManager* g_connection_manager = nullptr;
+
+// Instance of |ChannelManager| used by the channel management functions
+// (|CreateChannel()|, etc.).
+system::ChannelManager* g_channel_manager = nullptr;
+
// TODO(vtl): For now, we need this to be thread-safe (since theoretically we
// currently support multiple channel creation threads -- possibly one per
// channel). Eventually, we won't need it to be thread-safe (we'll require a
@@ -46,18 +81,22 @@ system::ChannelId MakeChannelId() {
return static_cast<system::ChannelId>(-new_counter_value);
}
-} // namespace
+// Note: Called on the I/O thread.
+void ShutdownIPCSupportHelper() {
+ // Save these before nuking them using |ShutdownChannelOnIOThread()|.
+ scoped_refptr<base::TaskRunner> delegate_thread_task_runner(
+ g_delegate_thread_task_runner);
+ ProcessDelegate* process_delegate = g_process_delegate;
-namespace internal {
+ ShutdownIPCSupportOnIOThread();
-// Declared in embedder_internal.h.
-PlatformSupport* g_platform_support = nullptr;
-system::Core* g_core = nullptr;
-system::ChannelManager* g_channel_manager = nullptr;
-MasterProcessDelegate* g_master_process_delegate = nullptr;
-SlaveProcessDelegate* g_slave_process_delegate = nullptr;
+ bool ok = delegate_thread_task_runner->PostTask(
+ FROM_HERE, base::Bind(&ProcessDelegate::OnShutdownComplete,
+ base::Unretained(process_delegate)));
+ DCHECK(ok);
+}
-} // namespace internal
+} // namespace
Configuration* GetConfiguration() {
return system::GetMutableConfiguration();
@@ -71,33 +110,150 @@ void Init(scoped_ptr<PlatformSupport> platform_support) {
DCHECK(!internal::g_core);
internal::g_core = new system::Core(internal::g_platform_support);
+}
- DCHECK(!internal::g_channel_manager);
- internal::g_channel_manager =
- new system::ChannelManager(internal::g_platform_support);
+MojoResult AsyncWait(MojoHandle handle,
+ MojoHandleSignals signals,
+ const base::Callback<void(MojoResult)>& callback) {
+ return internal::g_core->AsyncWait(handle, signals, callback);
}
-void InitMaster(scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
- MasterProcessDelegate* master_process_delegate,
- scoped_refptr<base::TaskRunner> io_thread_task_runner) {
- // |Init()| must have already been called.
+MojoResult CreatePlatformHandleWrapper(
+ ScopedPlatformHandle platform_handle,
+ MojoHandle* platform_handle_wrapper_handle) {
+ DCHECK(platform_handle_wrapper_handle);
+
+ scoped_refptr<system::Dispatcher> dispatcher(
+ new system::PlatformHandleDispatcher(platform_handle.Pass()));
+
+ DCHECK(internal::g_core);
+ MojoHandle h = internal::g_core->AddDispatcher(dispatcher);
+ if (h == MOJO_HANDLE_INVALID) {
+ LOG(ERROR) << "Handle table full";
+ dispatcher->Close();
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+ }
+
+ *platform_handle_wrapper_handle = h;
+ return MOJO_RESULT_OK;
+}
+
+MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
+ ScopedPlatformHandle* platform_handle) {
+ DCHECK(platform_handle);
+
DCHECK(internal::g_core);
+ scoped_refptr<system::Dispatcher> dispatcher(
+ internal::g_core->GetDispatcher(platform_handle_wrapper_handle));
+ if (!dispatcher)
+ return MOJO_RESULT_INVALID_ARGUMENT;
- // TODO(vtl): This is temporary. We really want to construct a
- // |MasterConnectionManager| here, which will in turn hold on to the delegate.
- internal::g_master_process_delegate = master_process_delegate;
+ if (dispatcher->GetType() != system::Dispatcher::kTypePlatformHandle)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ *platform_handle =
+ static_cast<system::PlatformHandleDispatcher*>(dispatcher.get())
+ ->PassPlatformHandle()
+ .Pass();
+ return MOJO_RESULT_OK;
}
-void InitSlave(scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
- SlaveProcessDelegate* slave_process_delegate,
- scoped_refptr<base::TaskRunner> io_thread_task_runner,
- ScopedPlatformHandle platform_handle) {
+void InitIPCSupport(ProcessType process_type,
+ scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
+ ProcessDelegate* process_delegate,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner,
+ ScopedPlatformHandle platform_handle) {
// |Init()| must have already been called.
DCHECK(internal::g_core);
+ // And not |InitIPCSupport()| (without |ShutdownIPCSupport()|).
+ DCHECK(internal::g_process_type == ProcessType::UNINITIALIZED);
- // TODO(vtl): This is temporary. We really want to construct a
- // |SlaveConnectionManager| here, which will in turn hold on to the delegate.
- internal::g_slave_process_delegate = slave_process_delegate;
+ internal::g_process_type = process_type;
+
+ DCHECK(delegate_thread_task_runner);
+ DCHECK(!g_delegate_thread_task_runner);
+ g_delegate_thread_task_runner = delegate_thread_task_runner.get();
+ g_delegate_thread_task_runner->AddRef();
+
+ DCHECK(process_delegate->GetType() == process_type);
+ DCHECK(!g_process_delegate);
+ g_process_delegate = process_delegate;
+
+ DCHECK(io_thread_task_runner);
+ DCHECK(!g_io_thread_task_runner);
+ g_io_thread_task_runner = io_thread_task_runner.get();
+ g_io_thread_task_runner->AddRef();
+
+ DCHECK(!g_connection_manager);
+ switch (process_type) {
+ case ProcessType::UNINITIALIZED:
+ CHECK(false);
+ break;
+ case ProcessType::NONE:
+ DCHECK(!platform_handle.is_valid()); // We wouldn't do anything with it.
+ // Nothing to do.
+ break;
+ case ProcessType::MASTER:
+ DCHECK(!platform_handle.is_valid()); // We wouldn't do anything with it.
+ g_connection_manager = new system::MasterConnectionManager();
+ static_cast<system::MasterConnectionManager*>(g_connection_manager)
+ ->Init(g_delegate_thread_task_runner,
+ static_cast<MasterProcessDelegate*>(g_process_delegate));
+ break;
+ case ProcessType::SLAVE:
+ DCHECK(platform_handle.is_valid());
+ g_connection_manager = new system::SlaveConnectionManager();
+ static_cast<system::SlaveConnectionManager*>(g_connection_manager)
+ ->Init(g_delegate_thread_task_runner,
+ static_cast<SlaveProcessDelegate*>(g_process_delegate),
+ platform_handle.Pass());
+ break;
+ }
+
+ DCHECK(!g_channel_manager);
+ g_channel_manager =
+ new system::ChannelManager(internal::g_platform_support,
+ io_thread_task_runner, g_connection_manager);
+}
+
+void ShutdownIPCSupportOnIOThread() {
+ DCHECK(internal::g_process_type != ProcessType::UNINITIALIZED);
+
+ g_channel_manager->ShutdownOnIOThread();
+ delete g_channel_manager;
+ g_channel_manager = nullptr;
+
+ if (g_connection_manager) {
+ g_connection_manager->Shutdown();
+ delete g_connection_manager;
+ g_connection_manager = nullptr;
+ }
+
+ g_io_thread_task_runner->Release();
+ g_io_thread_task_runner = nullptr;
+
+ g_delegate_thread_task_runner->Release();
+ g_delegate_thread_task_runner = nullptr;
+
+ g_process_delegate = nullptr;
+
+ internal::g_process_type = ProcessType::UNINITIALIZED;
+}
+
+void ShutdownIPCSupport() {
+ DCHECK(internal::g_process_type != ProcessType::UNINITIALIZED);
+
+ bool ok = g_io_thread_task_runner->PostTask(
+ FROM_HERE, base::Bind(&ShutdownIPCSupportHelper));
+ DCHECK(ok);
+}
+
+void ConnectToSlave(SlaveInfo slave_info,
+ ScopedPlatformHandle platform_handle) {
+ DCHECK(platform_handle.is_valid());
+ DCHECK(internal::g_process_type == ProcessType::MASTER);
+ static_cast<system::MasterConnectionManager*>(g_connection_manager)
+ ->AddSlave(slave_info, platform_handle.Pass());
}
// TODO(vtl): Write tests for this.
@@ -109,8 +265,8 @@ ScopedMessagePipeHandle CreateChannelOnIOThread(
*channel_info = new ChannelInfo(MakeChannelId());
scoped_refptr<system::MessagePipeDispatcher> dispatcher =
- internal::g_channel_manager->CreateChannelOnIOThread(
- (*channel_info)->channel_id, platform_handle.Pass());
+ g_channel_manager->CreateChannelOnIOThread((*channel_info)->channel_id,
+ platform_handle.Pass());
ScopedMessagePipeHandle rv(
MessagePipeHandle(internal::g_core->AddDispatcher(dispatcher)));
@@ -123,7 +279,7 @@ ScopedMessagePipeHandle CreateChannelOnIOThread(
ScopedMessagePipeHandle CreateChannel(
ScopedPlatformHandle platform_handle,
scoped_refptr<base::TaskRunner> io_thread_task_runner,
- DidCreateChannelCallback callback,
+ const DidCreateChannelCallback& callback,
scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
DCHECK(platform_handle.is_valid());
DCHECK(io_thread_task_runner);
@@ -132,7 +288,7 @@ ScopedMessagePipeHandle CreateChannel(
system::ChannelId channel_id = MakeChannelId();
scoped_ptr<ChannelInfo> channel_info(new ChannelInfo(channel_id));
scoped_refptr<system::MessagePipeDispatcher> dispatcher =
- internal::g_channel_manager->CreateChannel(
+ g_channel_manager->CreateChannel(
channel_id, platform_handle.Pass(), io_thread_task_runner,
base::Bind(callback, base::Unretained(channel_info.release())),
callback_thread_task_runner);
@@ -146,66 +302,32 @@ ScopedMessagePipeHandle CreateChannel(
}
// TODO(vtl): Write tests for this.
-void DestroyChannel(ChannelInfo* channel_info) {
+void DestroyChannelOnIOThread(ChannelInfo* channel_info) {
DCHECK(channel_info);
DCHECK(channel_info->channel_id);
- DCHECK(internal::g_channel_manager);
- // This will destroy the channel synchronously if called from the channel
- // thread.
- internal::g_channel_manager->ShutdownChannel(channel_info->channel_id);
+ DCHECK(g_channel_manager);
+ g_channel_manager->ShutdownChannelOnIOThread(channel_info->channel_id);
delete channel_info;
}
-void WillDestroyChannelSoon(ChannelInfo* channel_info) {
+// TODO(vtl): Write tests for this.
+void DestroyChannel(
+ ChannelInfo* channel_info,
+ const DidDestroyChannelCallback& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
DCHECK(channel_info);
- DCHECK(internal::g_channel_manager);
- internal::g_channel_manager->WillShutdownChannel(channel_info->channel_id);
-}
-
-MojoResult CreatePlatformHandleWrapper(
- ScopedPlatformHandle platform_handle,
- MojoHandle* platform_handle_wrapper_handle) {
- DCHECK(platform_handle_wrapper_handle);
-
- scoped_refptr<system::Dispatcher> dispatcher(
- new system::PlatformHandleDispatcher(platform_handle.Pass()));
-
- DCHECK(internal::g_core);
- MojoHandle h = internal::g_core->AddDispatcher(dispatcher);
- if (h == MOJO_HANDLE_INVALID) {
- LOG(ERROR) << "Handle table full";
- dispatcher->Close();
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- }
-
- *platform_handle_wrapper_handle = h;
- return MOJO_RESULT_OK;
-}
-
-MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
- ScopedPlatformHandle* platform_handle) {
- DCHECK(platform_handle);
-
- DCHECK(internal::g_core);
- scoped_refptr<system::Dispatcher> dispatcher(
- internal::g_core->GetDispatcher(platform_handle_wrapper_handle));
- if (!dispatcher)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (dispatcher->GetType() != system::Dispatcher::kTypePlatformHandle)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- *platform_handle =
- static_cast<system::PlatformHandleDispatcher*>(dispatcher.get())
- ->PassPlatformHandle()
- .Pass();
- return MOJO_RESULT_OK;
+ DCHECK(channel_info->channel_id);
+ DCHECK(!callback.is_null());
+ DCHECK(g_channel_manager);
+ g_channel_manager->ShutdownChannel(channel_info->channel_id, callback,
+ callback_thread_task_runner);
+ delete channel_info;
}
-MojoResult AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- base::Callback<void(MojoResult)> callback) {
- return internal::g_core->AsyncWait(handle, signals, callback);
+void WillDestroyChannelSoon(ChannelInfo* channel_info) {
+ DCHECK(channel_info);
+ DCHECK(g_channel_manager);
+ g_channel_manager->WillShutdownChannel(channel_info->channel_id);
}
} // namespace embedder
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder.h b/third_party/mojo/src/mojo/edk/embedder/embedder.h
index 4898ae1..142c86f 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder.h
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/task_runner.h"
#include "mojo/edk/embedder/channel_info_forward.h"
+#include "mojo/edk/embedder/process_type.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/system_impl_export.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -18,9 +19,15 @@ namespace mojo {
namespace embedder {
struct Configuration;
-class MasterProcessDelegate;
class PlatformSupport;
-class SlaveProcessDelegate;
+class ProcessDelegate;
+typedef void* SlaveInfo;
+
+// Basic configuration/initialization ------------------------------------------
+
+// |Init()| sets up the basic Mojo system environment, making the |Mojo...()|
+// functions available and functional. This is never shut down (except in tests
+// -- see test_embedder.h).
// Returns the global configuration. In general, you should not need to change
// the configuration, but if you do you must do it before calling |Init()|.
@@ -30,31 +37,88 @@ MOJO_SYSTEM_IMPL_EXPORT Configuration* GetConfiguration();
// initialize the (global, singleton) system.
MOJO_SYSTEM_IMPL_EXPORT void Init(scoped_ptr<PlatformSupport> platform_support);
-// Initializes a master process. To be called after |Init()|.
-// |master_process_delegate| should live forever (or until after
-// |mojo::embedder::test::Shutdown()|); its methods will be called using
-// |delegate_thread_task_runner|, which must be the task runner for the thread
-// calling |InitMaster()|. |io_thread_task_runner| should be the task runner for
-// some I/O thread; this should be the same as that provided to
-// |CreateChannel()| (or on which |CreateChannelOnIOThread()| is called).
-// TODO(vtl): Remove the |io_thread_task_runner| argument from
-// |CreateChannel()| (and eventually |CreateChannel()| altogether) and require
-// that either this or |InitSlave()| be called. Currently, |CreateChannel()| can
-// be used with different I/O threads, but this capability will be removed.
-MOJO_SYSTEM_IMPL_EXPORT void InitMaster(
- scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
- MasterProcessDelegate* master_process_delegate,
- scoped_refptr<base::TaskRunner> io_thread_task_runner);
+// Basic functions -------------------------------------------------------------
+
+// The functions in this section are available once |Init()| has been called.
+
+// Start waiting on the handle asynchronously. On success, |callback| will be
+// called exactly once, when |handle| satisfies a signal in |signals| or it
+// becomes known that it will never do so. |callback| will be executed on an
+// arbitrary thread, so it must not call any Mojo system or embedder functions.
+MOJO_SYSTEM_IMPL_EXPORT MojoResult
+AsyncWait(MojoHandle handle,
+ MojoHandleSignals signals,
+ const base::Callback<void(MojoResult)>& callback);
+
+// Creates a |MojoHandle| that wraps the given |PlatformHandle| (taking
+// ownership of it). This |MojoHandle| can then, e.g., be passed through message
+// pipes. Note: This takes ownership (and thus closes) |platform_handle| even on
+// 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
+CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle,
+ MojoHandle* platform_handle_wrapper_handle);
+
+// Retrieves the |PlatformHandle| that was wrapped into a |MojoHandle| (using
+// |CreatePlatformHandleWrapper()| above). Note that the |MojoHandle| must still
+// be closed separately.
+MOJO_SYSTEM_IMPL_EXPORT MojoResult
+PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
+ ScopedPlatformHandle* platform_handle);
-// Initializes a slave process. Similar to |InitMaster()| (see above).
-// |platform_handle| should be connected to the handle passed to |AddSlave()|.
-// TODO(vtl): |AddSlave()| doesn't exist yet.
-MOJO_SYSTEM_IMPL_EXPORT void InitSlave(
+// Initialialization/shutdown for interprocess communication (IPC) -------------
+
+// |InitIPCSupport()| sets up the subsystem for interprocess communication,
+// making the IPC functions (in the following section) available and functional.
+// (This may only be done after |Init()|.)
+//
+// This subsystem may be shut down, using |ShutdownIPCSupportOnIOThread()| or
+// |ShutdownIPCSupport()|. None of the IPC functions may be called while or
+// after either of these is called.
+
+// Initializes a process of the given type; to be called after |Init()|.
+// - |process_delegate| must be a process delegate of the appropriate type
+// corresponding to |process_type|; its methods will be called on
+// |delegate_thread_task_runner|.
+// - |delegate_thread_task_runner|, |process_delegate|, and
+// |io_thread_task_runner| should live at least until
+// |ShutdownIPCSupport()|'s callback has been run or
+// |ShutdownIPCSupportOnIOThread()| has completed.
+// - For slave processes (i.e., |process_type| is |ProcessType::SLAVE|),
+// |platform_handle| should be connected to the handle passed to
+// |ConnectToSlave()| (in the master process). For other processes,
+// |platform_handle| is ignored (and should not be valid).
+MOJO_SYSTEM_IMPL_EXPORT void InitIPCSupport(
+ ProcessType process_type,
scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
- SlaveProcessDelegate* slave_process_delegate,
+ ProcessDelegate* process_delegate,
scoped_refptr<base::TaskRunner> io_thread_task_runner,
ScopedPlatformHandle platform_handle);
+// Shuts down the subsystem initialized by |InitIPCSupport()|. This must be
+// called on the I/O thread (given to |InitIPCSupport()|). This completes
+// synchronously and does not result in a call to the process delegate's
+// |OnShutdownComplete()|.
+MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupportOnIOThread();
+
+// Like |ShutdownIPCSupportOnIOThread()|, but may be called from any thread,
+// signalling shutdown completion via the process delegate's
+// |OnShutdownComplete()|.
+MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupport();
+
+// Interprocess communication (IPC) functions ----------------------------------
+
+// Connects to a slave process to the IPC system. This should only be called in
+// a process initialized (using |InitIPCSupport()|) with process type
+// |ProcessType::MASTER|. |slave_info| is caller-dependent slave information,
+// which should remain alive until the master process delegate's
+// |OnSlaveDisconnect()| is called. |platform_handle| should be a handle to one
+// end of an OS "pipe"; the slave process should |InitIPCSupport()| with
+// |ProcessType::SLAVE| and the handle to the other end of this OS "pipe".
+MOJO_SYSTEM_IMPL_EXPORT void ConnectToSlave(
+ SlaveInfo slave_info,
+ ScopedPlatformHandle platform_handle);
+
// A "channel" is a connection on top of an OS "pipe", on top of which Mojo
// message pipes (etc.) can be multiplexed. It must "live" on some I/O thread.
//
@@ -111,48 +175,33 @@ typedef base::Callback<void(ChannelInfo*)> DidCreateChannelCallback;
MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle
CreateChannel(ScopedPlatformHandle platform_handle,
scoped_refptr<base::TaskRunner> io_thread_task_runner,
- DidCreateChannelCallback callback,
+ const DidCreateChannelCallback& callback,
scoped_refptr<base::TaskRunner> callback_thread_task_runner);
// Destroys a channel that was created using |CreateChannel()| (or
-// |CreateChannelOnIOThread()|); may be called from any thread. |channel_info|
-// should be the value provided to the callback to |CreateChannel()| (or
-// returned by |CreateChannelOnIOThread()|). If called from the I/O thread, this
-// will complete synchronously (in particular, it will post no tasks).
-// TODO(vtl): If called from some other thread, it'll post tasks to the I/O
-// thread. This is obviously potentially problematic if you want to shut the I/O
-// thread down.
-MOJO_SYSTEM_IMPL_EXPORT void DestroyChannel(ChannelInfo* channel_info);
+// |CreateChannelOnIOThread()|); must be called from the channel's I'O thread.
+// |channel_info| should be the value provided to the callback to
+// |CreateChannel()| (or returned by |CreateChannelOnIOThread()|). Completes
+// synchronously (and posts no tasks).
+MOJO_SYSTEM_IMPL_EXPORT void DestroyChannelOnIOThread(
+ ChannelInfo* channel_info);
+
+typedef base::Closure DidDestroyChannelCallback;
+// Like |DestroyChannelOnIOThread()|, but asynchronous and may be called from
+// any thread. The callback will be called using |callback_thread_task_runner|
+// if that is non-null, or otherwise it will be called on the "channel thread".
+// The "channel thread" must remain alive and continue to process tasks until
+// the callback has been executed.
+MOJO_SYSTEM_IMPL_EXPORT void DestroyChannel(
+ ChannelInfo* channel_info,
+ const DidDestroyChannelCallback& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner);
// Inform the channel that it will soon be destroyed (doing so is optional).
// This may be called from any thread, but the caller must ensure that this is
// called before |DestroyChannel()|.
MOJO_SYSTEM_IMPL_EXPORT void WillDestroyChannelSoon(ChannelInfo* channel_info);
-// Creates a |MojoHandle| that wraps the given |PlatformHandle| (taking
-// ownership of it). This |MojoHandle| can then, e.g., be passed through message
-// pipes. Note: This takes ownership (and thus closes) |platform_handle| even on
-// 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
-CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle,
- MojoHandle* platform_handle_wrapper_handle);
-// Retrieves the |PlatformHandle| that was wrapped into a |MojoHandle| (using
-// |CreatePlatformHandleWrapper()| above). Note that the |MojoHandle| must still
-// be closed separately.
-MOJO_SYSTEM_IMPL_EXPORT MojoResult
-PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
- ScopedPlatformHandle* platform_handle);
-
-// Start waiting the handle asynchronously. On success, |callback| will be
-// called exactly once, when |handle| satisfies a signal in |signals| or it
-// becomes known that it will never do so. |callback| will be executed on an
-// arbitrary thread. It must not call any Mojo system or embedder functions.
-MOJO_SYSTEM_IMPL_EXPORT MojoResult
-AsyncWait(MojoHandle handle,
- MojoHandleSignals signals,
- base::Callback<void(MojoResult)> callback);
-
} // namespace embedder
} // namespace mojo
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h b/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h
index 7d90148..833e66b 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder_internal.h
@@ -11,6 +11,12 @@
#include <stdint.h>
+#include "mojo/edk/embedder/process_type.h"
+
+namespace base {
+class TaskRunner;
+}
+
namespace mojo {
namespace system {
@@ -26,9 +32,7 @@ typedef uint64_t ChannelId;
namespace embedder {
class PlatformSupport;
-// TODO(vtl): Remove these (see below).
-class MasterProcessDelegate;
-class SlaveProcessDelegate;
+class ProcessDelegate;
// This is a type that's opaque to users of the embedder API (which only
// gives/takes |ChannelInfo*|s). We make it a struct to make it
@@ -48,15 +52,11 @@ extern PlatformSupport* g_platform_support;
// Instance of |Core| used by the system functions (|Mojo...()|).
extern system::Core* g_core;
-// Instance of |ChannelManager| used by the channel management functions
-// (|mojo::embedder::CreateChannel()|, etc.).
-extern system::ChannelManager* g_channel_manager;
-
-// TODO(vtl): Remove these: We'll eventually really want to hold on to a
-// |MasterConnectionManager*| or a |SlaveConnectionManager*|. For now, keep
-// these around as globals to avoid triggering leak detectors.
-extern MasterProcessDelegate* g_master_process_delegate;
-extern SlaveProcessDelegate* g_slave_process_delegate;
+// Type of process initialized in |InitIPCSupport()| (set to |UNINITIALIZED| if
+// "outside" |InitIPCSupport()|/|ShutdownIPCSupport()|). This is declared here
+// so that |mojo::embedder::test::Shutdown()| can check that it's only called
+// after |ShutdownIPCSupport()|.
+extern ProcessType g_process_type;
} // namespace internal
diff --git a/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc b/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc
index aa0b08b..48a59c1 100644
--- a/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/embedder_unittest.cc
@@ -18,6 +18,7 @@
#include "mojo/edk/embedder/test_embedder.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/test/multiprocess_test_helper.h"
+#include "mojo/edk/test/scoped_ipc_support.h"
#include "mojo/public/c/system/core.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -44,7 +45,7 @@ class ScopedTestChannel {
ScopedPlatformHandle platform_handle)
: io_thread_task_runner_(io_thread_task_runner),
bootstrap_message_pipe_(MOJO_HANDLE_INVALID),
- did_create_channel_event_(true, false), // Manual reset.
+ event_(true, false), // Manual reset.
channel_info_(nullptr) {
bootstrap_message_pipe_ =
CreateChannel(platform_handle.Pass(), io_thread_task_runner_,
@@ -60,12 +61,17 @@ class ScopedTestChannel {
// the I/O thread must be alive and pumping messages.)
~ScopedTestChannel() {
// |WaitForChannelCreationCompletion()| must be called before destruction.
- CHECK(did_create_channel_event_.IsSignaled());
- DestroyChannel(channel_info_);
+ CHECK(event_.IsSignaled());
+ event_.Reset();
+ DestroyChannel(channel_info_,
+ base::Bind(&ScopedTestChannel::DidDestroyChannel,
+ base::Unretained(this)),
+ nullptr);
+ event_.Wait();
}
// Waits for channel creation to be completed.
- void WaitForChannelCreationCompletion() { did_create_channel_event_.Wait(); }
+ void WaitForChannelCreationCompletion() { event_.Wait(); }
MojoHandle bootstrap_message_pipe() const { return bootstrap_message_pipe_; }
@@ -78,9 +84,11 @@ class ScopedTestChannel {
CHECK(channel_info);
CHECK(!channel_info_);
channel_info_ = channel_info;
- did_create_channel_event_.Signal();
+ event_.Signal();
}
+ void DidDestroyChannel() { event_.Signal(); }
+
scoped_refptr<base::TaskRunner> io_thread_task_runner_;
// Valid from creation until whenever it gets closed (by the "owner" of this
@@ -90,8 +98,9 @@ class ScopedTestChannel {
MojoHandle bootstrap_message_pipe_;
// Set after channel creation has been completed (i.e., the callback to
- // |CreateChannel()| has been called).
- base::WaitableEvent did_create_channel_event_;
+ // |CreateChannel()| has been called). Also used in the destructor to wait for
+ // |DestroyChannel()| completion.
+ base::WaitableEvent event_;
// Valid after channel creation completion until destruction.
ChannelInfo* channel_info_;
@@ -120,6 +129,8 @@ class EmbedderTest : public testing::Test {
};
TEST_F(EmbedderTest, ChannelsBasic) {
+ mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner());
+
PlatformChannelPair channel_pair;
ScopedTestChannel server_channel(test_io_task_runner(),
channel_pair.PassServerHandle());
@@ -247,6 +258,8 @@ TEST_F(EmbedderTest, AsyncWait) {
}
TEST_F(EmbedderTest, ChannelsHandlePassing) {
+ mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner());
+
PlatformChannelPair channel_pair;
ScopedTestChannel server_channel(test_io_task_runner(),
channel_pair.PassServerHandle());
@@ -389,6 +402,10 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) {
#define MAYBE_MultiprocessChannels MultiprocessChannels
#endif // defined(OS_ANDROID)
TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) {
+ // TODO(vtl): This should eventually initialize a master process instead,
+ // probably.
+ mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner());
+
mojo::test::MultiprocessTestHelper multiprocess_test_helper;
multiprocess_test_helper.StartChild("MultiprocessChannelsClient");
@@ -512,6 +529,10 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) {
test::InitWithSimplePlatformSupport();
{
+ // TODO(vtl): This should eventually initialize a slave process instead,
+ // probably.
+ mojo::test::ScopedIPCSupport ipc_support(test_io_thread.task_runner());
+
ScopedTestChannel client_channel(test_io_thread.task_runner(),
client_platform_handle.Pass());
MojoHandle client_mp = client_channel.bootstrap_message_pipe();
diff --git a/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h b/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h
index 13791f4..bc3c909 100644
--- a/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h
+++ b/third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h
@@ -7,40 +7,38 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "mojo/edk/embedder/process_delegate.h"
#include "mojo/edk/system/system_impl_export.h"
namespace mojo {
namespace embedder {
-// An interface for containers of slave process information, to be used by
-// |MasterProcessDelegate| (below).
-class MOJO_SYSTEM_IMPL_EXPORT SlaveInfo {
- public:
- SlaveInfo() {}
- virtual ~SlaveInfo() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SlaveInfo);
-};
+typedef void* SlaveInfo;
// An interface for the master process delegate (which lives in the master
// process).
-class MOJO_SYSTEM_IMPL_EXPORT MasterProcessDelegate {
+class MOJO_SYSTEM_IMPL_EXPORT MasterProcessDelegate : public ProcessDelegate {
public:
+ ProcessType GetType() const override;
+
// Called when contact with the slave process specified by |slave_info| has
// been lost.
// TODO(vtl): Obviously, there needs to be a suitable embedder API for
// connecting to a process. What will it be? Mention that here once it exists.
- virtual void OnSlaveDisconnect(scoped_ptr<SlaveInfo> slave_info) = 0;
+ virtual void OnSlaveDisconnect(SlaveInfo slave_info) = 0;
protected:
MasterProcessDelegate() {}
- virtual ~MasterProcessDelegate() {}
+ ~MasterProcessDelegate() override {}
private:
DISALLOW_COPY_AND_ASSIGN(MasterProcessDelegate);
};
+inline ProcessType MasterProcessDelegate::GetType() const {
+ return ProcessType::MASTER;
+}
+
} // namespace embedder
} // namespace mojo
diff --git a/third_party/mojo/src/mojo/edk/embedder/platform_support.h b/third_party/mojo/src/mojo/edk/embedder/platform_support.h
index 4556ee3..80ee81b 100644
--- a/third_party/mojo/src/mojo/edk/embedder/platform_support.h
+++ b/third_party/mojo/src/mojo/edk/embedder/platform_support.h
@@ -18,10 +18,13 @@ class PlatformSharedBuffer;
// This class is provided by the embedder to implement (typically
// platform-dependent) things needed by the Mojo system implementation.
+// Implementations must be thread-safe.
class MOJO_SYSTEM_IMPL_EXPORT PlatformSupport {
public:
virtual ~PlatformSupport() {}
+ virtual void GetCryptoRandomBytes(void* bytes, size_t num_bytes) = 0;
+
virtual PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) = 0;
virtual PlatformSharedBuffer* CreateSharedBufferFromHandle(
size_t num_bytes,
diff --git a/third_party/mojo/src/mojo/edk/embedder/process_delegate.h b/third_party/mojo/src/mojo/edk/embedder/process_delegate.h
new file mode 100644
index 0000000..325c532
--- /dev/null
+++ b/third_party/mojo/src/mojo/edk/embedder/process_delegate.h
@@ -0,0 +1,39 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_
+#define MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_
+
+#include "base/macros.h"
+#include "mojo/edk/embedder/process_type.h"
+#include "mojo/edk/system/system_impl_export.h"
+
+namespace mojo {
+namespace embedder {
+
+// An interface for process delegates.
+class MOJO_SYSTEM_IMPL_EXPORT ProcessDelegate {
+ public:
+ virtual ProcessType GetType() const;
+
+ // Called when |ShutdownIPCSupport()| has "completed". Note that this is NOT
+ // called if |ShutdownIPCSupportOnIOThread()| is used instead.
+ virtual void OnShutdownComplete() = 0;
+
+ protected:
+ ProcessDelegate() {}
+ virtual ~ProcessDelegate() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProcessDelegate);
+};
+
+inline ProcessType ProcessDelegate::GetType() const {
+ return ProcessType::NONE;
+}
+
+} // namespace embedder
+} // namespace mojo
+
+#endif // MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_
diff --git a/third_party/mojo/src/mojo/edk/embedder/process_type.h b/third_party/mojo/src/mojo/edk/embedder/process_type.h
new file mode 100644
index 0000000..87292df9
--- /dev/null
+++ b/third_party/mojo/src/mojo/edk/embedder/process_type.h
@@ -0,0 +1,26 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EDK_EMBEDDER_PROCESS_TYPE_H_
+#define MOJO_EDK_EMBEDDER_PROCESS_TYPE_H_
+
+namespace mojo {
+namespace embedder {
+
+enum class ProcessType {
+ // |InitIPCSupport()| has not been called (or |ShutdownIPCSupport()| has been
+ // called).
+ UNINITIALIZED,
+ // Process without connection management.
+ NONE,
+ // Master process.
+ MASTER,
+ // Slave process.
+ SLAVE,
+};
+
+} // namespace embedder
+} // namespace mojo
+
+#endif // MOJO_EDK_EMBEDDER_PROCESS_TYPE_H_
diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.cc b/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.cc
index c59cfb3..5024087 100644
--- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.cc
@@ -4,11 +4,17 @@
#include "mojo/edk/embedder/simple_platform_support.h"
+#include "crypto/random.h"
#include "mojo/edk/embedder/simple_platform_shared_buffer.h"
namespace mojo {
namespace embedder {
+void SimplePlatformSupport::GetCryptoRandomBytes(void* bytes,
+ size_t num_bytes) {
+ crypto::RandBytes(bytes, num_bytes);
+}
+
PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBuffer(
size_t num_bytes) {
return SimplePlatformSharedBuffer::Create(num_bytes);
diff --git a/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h b/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h
index 2013f8d..9be7dc0 100644
--- a/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h
+++ b/third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h
@@ -22,6 +22,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSupport : public PlatformSupport {
SimplePlatformSupport() {}
~SimplePlatformSupport() override {}
+ void GetCryptoRandomBytes(void* bytes, size_t num_bytes) override;
PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) override;
PlatformSharedBuffer* CreateSharedBufferFromHandle(
size_t num_bytes,
diff --git a/third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h b/third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h
index 1c55a7a..d959215 100644
--- a/third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h
+++ b/third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "mojo/edk/embedder/process_delegate.h"
#include "mojo/edk/system/system_impl_export.h"
namespace mojo {
@@ -14,8 +15,10 @@ namespace embedder {
// An interface for the slave process delegate (which lives in each slave
// process).
-class MOJO_SYSTEM_IMPL_EXPORT SlaveProcessDelegate {
+class MOJO_SYSTEM_IMPL_EXPORT SlaveProcessDelegate : public ProcessDelegate {
public:
+ ProcessType GetType() const override;
+
// Called when contact with the master process has been lost.
// TODO(vtl): Obviously, there needs to be a suitable embedder API for
// connecting to the master process. What will it be? Mention that here once
@@ -24,12 +27,16 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveProcessDelegate {
protected:
SlaveProcessDelegate() {}
- virtual ~SlaveProcessDelegate() {}
+ ~SlaveProcessDelegate() override {}
private:
DISALLOW_COPY_AND_ASSIGN(SlaveProcessDelegate);
};
+inline ProcessType SlaveProcessDelegate::GetType() const {
+ return ProcessType::SLAVE;
+}
+
} // namespace embedder
} // namespace mojo
diff --git a/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc b/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc
index 3412626..791a888 100644
--- a/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc
+++ b/third_party/mojo/src/mojo/edk/embedder/test_embedder.cc
@@ -46,9 +46,9 @@ void InitWithSimplePlatformSupport() {
}
bool Shutdown() {
- CHECK(internal::g_channel_manager);
- delete internal::g_channel_manager;
- internal::g_channel_manager = nullptr;
+ // If |InitIPCSupport()| was called, then |ShutdownIPCSupport()| must have
+ // been called first.
+ CHECK(internal::g_process_type == ProcessType::UNINITIALIZED);
CHECK(internal::g_core);
bool rv = system::internal::ShutdownCheckNoLeaks(internal::g_core);
diff --git a/third_party/mojo/src/mojo/edk/js/tests/connection_tests.js b/third_party/mojo/src/mojo/edk/js/tests/connection_tests.js
index 17009d9..ff59aeb 100644
--- a/third_party/mojo/src/mojo/edk/js/tests/connection_tests.js
+++ b/third_party/mojo/src/mojo/edk/js/tests/connection_tests.js
@@ -83,14 +83,15 @@ define([
function createPeerConnection(handle, stubClass, proxyClass) {
var c = new connection.Connection(handle, stubClass, proxyClass);
- c.local.peer = c.remote;
- c.remote.peer = c.local;
+ if (c.local)
+ c.local.peer = c.remote;
+ if (c.remote)
+ c.remote.peer = c.local;
return c;
}
function testClientServer() {
var receivedFrobinate = false;
- var receivedDidFrobinate = false;
// ServiceImpl ------------------------------------------------------------
@@ -107,21 +108,7 @@ define([
expect(baz).toBeTruthy();
expect(core.close(port)).toBe(core.RESULT_OK);
- this.peer.didFrobinate(42);
- };
-
- // ServiceClientImpl ------------------------------------------------------
-
- function ServiceClientImpl() {
- }
-
- ServiceClientImpl.prototype =
- Object.create(sample_service.ServiceClient.stubClass.prototype);
-
- ServiceClientImpl.prototype.didFrobinate = function(result) {
- receivedDidFrobinate = true;
-
- expect(result).toBe(42);
+ return Promise.resolve(42);
};
var pipe = core.createMessagePipe();
@@ -129,10 +116,10 @@ define([
var sourcePipe = core.createMessagePipe();
var connection0 = createPeerConnection(
- pipe.handle0, ServiceImpl, sample_service.ServiceClient.proxyClass);
+ pipe.handle0, ServiceImpl);
var connection1 = createPeerConnection(
- pipe.handle1, ServiceClientImpl, sample_service.Service.proxyClass);
+ pipe.handle1, undefined, sample_service.Service.proxyClass);
var foo = new sample_service.Foo();
foo.bar = new sample_service.Bar();
@@ -143,7 +130,6 @@ define([
mockSupport.pumpOnce(core.RESULT_OK);
expect(receivedFrobinate).toBeTruthy();
- expect(receivedDidFrobinate).toBeTruthy();
connection0.close();
connection1.close();
@@ -179,8 +165,7 @@ define([
var foo = new sample_service.Foo();
foo.bar = new sample_service.Bar();
- // TODO(darin): crbug.com/357043: pass null in place of |foo| here.
- connection1.remote.frobinate(foo, true, null);
+ connection1.remote.frobinate(null, true, null);
// Write failures are not reported.
expect(connection1.encounteredError()).toBeFalsy();
@@ -213,24 +198,15 @@ define([
return Promise.resolve({a: a, b: b});
};
- // ProviderClientImpl ------------------------------------------------------
-
- function ProviderClientImpl() {
- }
-
- ProviderClientImpl.prototype =
- Object.create(sample_interfaces.ProviderClient.stubClass.prototype);
-
var pipe = core.createMessagePipe();
var connection0 = createPeerConnection(
pipe.handle0,
- ProviderImpl,
- sample_interfaces.ProviderClient.proxyClass);
+ ProviderImpl);
var connection1 = createPeerConnection(
pipe.handle1,
- ProviderClientImpl,
+ undefined,
sample_interfaces.Provider.proxyClass);
var origReadMessage = core.readMessage;
diff --git a/third_party/mojo/src/mojo/edk/js/tests/sample_service_tests.js b/third_party/mojo/src/mojo/edk/js/tests/sample_service_tests.js
index 2afdf3e..ac8ce2e 100644
--- a/third_party/mojo/src/mojo/edk/js/tests/sample_service_tests.js
+++ b/third_party/mojo/src/mojo/edk/js/tests/sample_service_tests.js
@@ -146,14 +146,14 @@ define([
function SimpleMessageReceiver() {
}
- SimpleMessageReceiver.prototype.accept = function(message) {
+ SimpleMessageReceiver.prototype.acceptAndExpectResponse = function(message) {
if (dumpMessageAsHex) {
var uint8Array = new Uint8Array(message.buffer.arrayBuffer);
console.log(hexdump.dumpArray(uint8Array));
}
// Imagine some IPC happened here.
var serviceImpl = new ServiceImpl();
- serviceImpl.accept(message);
+ return serviceImpl.acceptWithResponder(message, { accept: function() {} });
};
var serviceProxy = new sample.Service.proxyClass;
diff --git a/third_party/mojo/src/mojo/edk/system/BUILD.gn b/third_party/mojo/src/mojo/edk/system/BUILD.gn
index a386ff9..40bf20d 100644
--- a/third_party/mojo/src/mojo/edk/system/BUILD.gn
+++ b/third_party/mojo/src/mojo/edk/system/BUILD.gn
@@ -44,6 +44,7 @@ component("system") {
"core.h",
"data_pipe.cc",
"data_pipe.h",
+ "data_pipe_impl.h",
"data_pipe_consumer_dispatcher.cc",
"data_pipe_consumer_dispatcher.h",
"data_pipe_producer_dispatcher.cc",
@@ -57,8 +58,8 @@ component("system") {
"handle_table.h",
"incoming_endpoint.cc",
"incoming_endpoint.h",
- "local_data_pipe.cc",
- "local_data_pipe.h",
+ "local_data_pipe_impl.cc",
+ "local_data_pipe_impl.h",
"local_message_pipe_endpoint.cc",
"local_message_pipe_endpoint.h",
"mapping_table.cc",
@@ -117,7 +118,6 @@ component("system") {
deps = [
"//base",
"//base/third_party/dynamic_annotations",
- "//crypto",
]
allow_circular_includes_from = [ "../embedder" ]
@@ -158,7 +158,7 @@ test("mojo_system_unittests") {
"core_unittest.cc",
"data_pipe_unittest.cc",
"dispatcher_unittest.cc",
- "local_data_pipe_unittest.cc",
+ "local_data_pipe_impl_unittest.cc",
"memory_unittest.cc",
"message_pipe_dispatcher_unittest.cc",
"message_pipe_test_utils.cc",
diff --git a/third_party/mojo/src/mojo/edk/system/async_waiter.cc b/third_party/mojo/src/mojo/edk/system/async_waiter.cc
index 071eb01..4f539b9 100644
--- a/third_party/mojo/src/mojo/edk/system/async_waiter.cc
+++ b/third_party/mojo/src/mojo/edk/system/async_waiter.cc
@@ -7,7 +7,7 @@
namespace mojo {
namespace system {
-AsyncWaiter::AsyncWaiter(AwakeCallback callback) : callback_(callback) {
+AsyncWaiter::AsyncWaiter(const AwakeCallback& callback) : callback_(callback) {
}
AsyncWaiter::~AsyncWaiter() {
diff --git a/third_party/mojo/src/mojo/edk/system/async_waiter.h b/third_party/mojo/src/mojo/edk/system/async_waiter.h
index da412c0..df3b482 100644
--- a/third_party/mojo/src/mojo/edk/system/async_waiter.h
+++ b/third_party/mojo/src/mojo/edk/system/async_waiter.h
@@ -20,7 +20,7 @@ class MOJO_SYSTEM_IMPL_EXPORT AsyncWaiter final : public Awakable {
typedef base::Callback<void(MojoResult)> AwakeCallback;
// |callback| must satisfy the same contract as |Awakable::Awake()|.
- explicit AsyncWaiter(AwakeCallback callback);
+ explicit AsyncWaiter(const AwakeCallback& callback);
virtual ~AsyncWaiter();
private:
diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager.cc b/third_party/mojo/src/mojo/edk/system/channel_manager.cc
index 634accc..a5301b3 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_manager.cc
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager.cc
@@ -18,27 +18,68 @@ namespace system {
namespace {
-void ShutdownChannelHelper(const ChannelInfo& channel_info) {
- if (base::MessageLoopProxy::current() ==
- channel_info.channel_thread_task_runner) {
- channel_info.channel->Shutdown();
+void ShutdownChannelHelper(
+ const ChannelInfo& channel_info,
+ const base::Closure& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
+ DCHECK(base::MessageLoopProxy::current() ==
+ channel_info.channel_thread_task_runner);
+ channel_info.channel->Shutdown();
+ if (callback_thread_task_runner) {
+ bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback);
+ DCHECK(ok);
} else {
- channel_info.channel->WillShutdownSoon();
- channel_info.channel_thread_task_runner->PostTask(
- FROM_HERE, base::Bind(&Channel::Shutdown, channel_info.channel));
+ callback.Run();
}
}
} // namespace
-ChannelManager::ChannelManager(embedder::PlatformSupport* platform_support)
- : platform_support_(platform_support) {
+ChannelManager::ChannelManager(
+ embedder::PlatformSupport* platform_support,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner,
+ ConnectionManager* connection_manager)
+ : platform_support_(platform_support),
+ io_thread_task_runner_(io_thread_task_runner),
+ connection_manager_(connection_manager) {
+ DCHECK(platform_support_);
+ DCHECK(io_thread_task_runner_);
+ // (|connection_manager_| may be null.)
}
ChannelManager::~ChannelManager() {
- // No need to take the lock.
- for (const auto& map_elem : channel_infos_)
- ShutdownChannelHelper(map_elem.second);
+ // |Shutdown()| must be called before destruction and have been completed.
+ // TODO(vtl): This doesn't verify the above condition very strictly at all
+ // (e.g., we may never have had any channels, or we may have manually shut all
+ // the channels down).
+ DCHECK(channel_infos_.empty());
+}
+
+void ChannelManager::ShutdownOnIOThread() {
+ // Taking this lock really shouldn't be necessary, but we do it for
+ // consistency.
+ base::hash_map<ChannelId, ChannelInfo> channel_infos;
+ {
+ base::AutoLock locker(lock_);
+ channel_infos.swap(channel_infos_);
+ }
+
+ for (const auto& map_elem : channel_infos) {
+ const ChannelInfo& channel_info = map_elem.second;
+ DCHECK(base::MessageLoopProxy::current() ==
+ channel_info.channel_thread_task_runner);
+ channel_info.channel->Shutdown();
+ }
+}
+
+void ChannelManager::Shutdown(
+ const base::Closure& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
+ bool ok = io_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&ChannelManager::ShutdownHelper, base::Unretained(this),
+ callback, callback_thread_task_runner));
+ DCHECK(ok);
}
scoped_refptr<MessagePipeDispatcher> ChannelManager::CreateChannelOnIOThread(
@@ -57,9 +98,10 @@ scoped_refptr<MessagePipeDispatcher> ChannelManager::CreateChannel(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle,
scoped_refptr<base::TaskRunner> io_thread_task_runner,
- base::Closure callback,
+ const base::Closure& callback,
scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
- DCHECK(io_thread_task_runner);
+ // TODO(vtl): Remove |io_thread_task_runner| argument.
+ DCHECK_EQ(io_thread_task_runner, io_thread_task_runner_);
DCHECK(!callback.is_null());
// (|callback_thread_task_runner| may be null.)
@@ -67,12 +109,13 @@ scoped_refptr<MessagePipeDispatcher> ChannelManager::CreateChannel(
scoped_refptr<system::MessagePipeDispatcher> dispatcher =
system::MessagePipeDispatcher::CreateRemoteMessagePipe(
&bootstrap_channel_endpoint);
- io_thread_task_runner->PostTask(
+ bool ok = io_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&ChannelManager::CreateChannelHelper, base::Unretained(this),
channel_id, base::Passed(&platform_handle),
bootstrap_channel_endpoint, callback,
callback_thread_task_runner));
+ DCHECK(ok);
return dispatcher;
}
@@ -87,7 +130,24 @@ void ChannelManager::WillShutdownChannel(ChannelId channel_id) {
GetChannel(channel_id)->WillShutdownSoon();
}
-void ChannelManager::ShutdownChannel(ChannelId channel_id) {
+void ChannelManager::ShutdownChannelOnIOThread(ChannelId channel_id) {
+ ChannelInfo channel_info;
+ {
+ base::AutoLock locker(lock_);
+ auto it = channel_infos_.find(channel_id);
+ DCHECK(it != channel_infos_.end());
+ channel_info.Swap(&it->second);
+ channel_infos_.erase(it);
+ }
+ DCHECK(base::MessageLoopProxy::current() ==
+ channel_info.channel_thread_task_runner);
+ channel_info.channel->Shutdown();
+}
+
+void ChannelManager::ShutdownChannel(
+ ChannelId channel_id,
+ const base::Closure& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
ChannelInfo channel_info;
{
base::AutoLock locker(lock_);
@@ -96,7 +156,23 @@ void ChannelManager::ShutdownChannel(ChannelId channel_id) {
channel_info.Swap(&it->second);
channel_infos_.erase(it);
}
- ShutdownChannelHelper(channel_info);
+ channel_info.channel->WillShutdownSoon();
+ bool ok = channel_info.channel_thread_task_runner->PostTask(
+ FROM_HERE, base::Bind(&ShutdownChannelHelper, channel_info, callback,
+ callback_thread_task_runner));
+ DCHECK(ok);
+}
+
+void ChannelManager::ShutdownHelper(
+ const base::Closure& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
+ ShutdownOnIOThread();
+ if (callback_thread_task_runner) {
+ bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback);
+ DCHECK(ok);
+ } else {
+ callback.Run();
+ }
}
void ChannelManager::CreateChannelOnIOThreadHelper(
@@ -126,14 +202,16 @@ void ChannelManager::CreateChannelHelper(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle,
scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint,
- base::Closure callback,
+ const base::Closure& callback,
scoped_refptr<base::TaskRunner> callback_thread_task_runner) {
CreateChannelOnIOThreadHelper(channel_id, platform_handle.Pass(),
bootstrap_channel_endpoint);
- if (callback_thread_task_runner)
- callback_thread_task_runner->PostTask(FROM_HERE, callback);
- else
+ if (callback_thread_task_runner) {
+ bool ok = callback_thread_task_runner->PostTask(FROM_HERE, callback);
+ DCHECK(ok);
+ } else {
callback.Run();
+ }
}
} // namespace system
diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager.h b/third_party/mojo/src/mojo/edk/system/channel_manager.h
index da3e030..77ff953 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_manager.h
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager.h
@@ -29,6 +29,7 @@ namespace system {
class Channel;
class ChannelEndpoint;
+class ConnectionManager;
class MessagePipeDispatcher;
// IDs for |Channel|s managed by a |ChannelManager|. (IDs should be thought of
@@ -42,17 +43,37 @@ const ChannelId kInvalidChannelId = 0;
// specifically noted.
class MOJO_SYSTEM_IMPL_EXPORT ChannelManager {
public:
- // |*platform_support| must remain alive longer than this object.
- explicit ChannelManager(embedder::PlatformSupport* platform_support);
+ // |io_thread_task_runner| should be the |TaskRunner| for the I/O thread, on
+ // which this channel manager will create all channels. Connection manager is
+ // optional and may be null. All arguments (if non-null) must remain alive at
+ // least until after shutdown completion.
+ ChannelManager(embedder::PlatformSupport* platform_support,
+ scoped_refptr<base::TaskRunner> io_thread_task_runner,
+ ConnectionManager* connection_manager);
~ChannelManager();
+ // Shuts down the channel manager, including shutting down all channels (as if
+ // |ShutdownChannelOnIOThread()| were called for each channel). This must be
+ // called from the I/O thread (given to the constructor) and completes
+ // synchronously. This, or |Shutdown()|, must be called before destroying this
+ // object.
+ void ShutdownOnIOThread();
+
+ // Like |ShutdownOnIOThread()|, but may be called from any thread. On
+ // completion, will call |callback| ("on" |io_thread_task_runner| if
+ // |callback_thread_task_runner| is null else by posted using
+ // |callback_thread_task_runner|). Note: This will always post a task to the
+ // I/O thread, even it is the current thread.
+ // TODO(vtl): Consider if this is really necessary, since it only has one use
+ // (in tests).
+ void Shutdown(const base::Closure& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner);
+
// Creates a |Channel| and adds it to the set of channels managed by this
- // |ChannelManager|. |channel_id| should be a valid |ChannelId| (i.e.,
- // nonzero) not "assigned" to any other |Channel| being managed by this
+ // |ChannelManager|. This must be called from the I/O thread (given to the
+ // constructor). |channel_id| should be a valid |ChannelId| (i.e., nonzero)
+ // not "assigned" to any other |Channel| being managed by this
// |ChannelManager|.
- // TODO(vtl): Currently, this should be called on any I/O thread (which will
- // become the new channel's "channel thread"). Eventually, the channel manager
- // will have an assigned I/O thread, on which this must be called.
scoped_refptr<MessagePipeDispatcher> CreateChannelOnIOThread(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle);
@@ -69,7 +90,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelManager {
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle,
scoped_refptr<base::TaskRunner> io_thread_task_runner,
- base::Closure callback,
+ const base::Closure& callback,
scoped_refptr<base::TaskRunner> callback_thread_task_runner);
// Gets the |Channel| with the given ID (which must exist).
@@ -82,14 +103,31 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelManager {
// the channel).
void WillShutdownChannel(ChannelId channel_id);
- // Shuts down the channel specified by the given ID. It is up to the caller to
- // guarantee that this is only called once per channel (that was added using
- // |CreateChannelOnIOThread()|). If called from the channel's creation thread
- // (i.e., |base::MessageLoopProxy::current()| is the channel thread's
- // |TaskRunner|), this will complete synchronously.
- void ShutdownChannel(ChannelId channel_id);
+ // Shuts down the channel specified by the given ID. This, or
+ // |ShutdownChannel()|, should be called once per channel (created using
+ // |CreateChannelOnIOThread()| or |CreateChannel()|). This must be called from
+ // the channel's "channel thread", and completes synchronously.
+ // TODO(vtl): "channel thread" will become "this object's I/O thread".
+ void ShutdownChannelOnIOThread(ChannelId channel_id);
+
+ // Like |ShutdownChannelOnIOThread()|, but may be called from any thread. It
+ // will always post a task to the channel's "channel thread", and post
+ // |callback| to |callback_thread_task_runner| (or execute it directly on the
+ // "channel thread" if |callback_thread_task_runner| is null) on completion.
+ // TODO(vtl): "channel thread" will become "this object's I/O thread".
+ void ShutdownChannel(
+ ChannelId channel_id,
+ const base::Closure& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner);
+
+ ConnectionManager* connection_manager() const { return connection_manager_; }
private:
+ // Used by |Shutdown()|. Called on the I/O thread.
+ void ShutdownHelper(
+ const base::Closure& callback,
+ scoped_refptr<base::TaskRunner> callback_thread_task_runner);
+
// Used by |CreateChannelOnIOThread()| and |CreateChannelHelper()|. Called on
// the I/O thread.
void CreateChannelOnIOThreadHelper(
@@ -102,10 +140,13 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelManager {
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle,
scoped_refptr<system::ChannelEndpoint> bootstrap_channel_endpoint,
- base::Closure callback,
+ const base::Closure& callback,
scoped_refptr<base::TaskRunner> callback_thread_task_runner);
+ // Note: These must not be used after shutdown.
embedder::PlatformSupport* const platform_support_;
+ const scoped_refptr<base::TaskRunner> io_thread_task_runner_;
+ ConnectionManager* const connection_manager_;
// Note: |Channel| methods should not be called under |lock_|.
mutable base::Lock lock_; // Protects the members below.
diff --git a/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc b/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc
index 86ab4a0..1a3176e 100644
--- a/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc
+++ b/third_party/mojo/src/mojo/edk/system/channel_manager_unittest.cc
@@ -10,10 +10,7 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "base/task_runner.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/edk/system/channel.h"
@@ -27,42 +24,44 @@ namespace {
class ChannelManagerTest : public testing::Test {
public:
- ChannelManagerTest() : message_loop_(base::MessageLoop::TYPE_IO) {}
+ ChannelManagerTest()
+ : message_loop_(base::MessageLoop::TYPE_IO),
+ channel_manager_(&platform_support_,
+ message_loop_.task_runner(),
+ nullptr) {}
~ChannelManagerTest() override {}
protected:
- embedder::SimplePlatformSupport* platform_support() {
- return &platform_support_;
- }
- base::MessageLoop* message_loop() { return &message_loop_; }
+ ChannelManager& channel_manager() { return channel_manager_; }
private:
embedder::SimplePlatformSupport platform_support_;
base::MessageLoop message_loop_;
+ // Note: This should be *after* the above, since they must be initialized
+ // before it (and should outlive it).
+ ChannelManager channel_manager_;
DISALLOW_COPY_AND_ASSIGN(ChannelManagerTest);
};
TEST_F(ChannelManagerTest, Basic) {
- ChannelManager cm(platform_support());
-
embedder::PlatformChannelPair channel_pair;
const ChannelId id = 1;
scoped_refptr<MessagePipeDispatcher> d =
- cm.CreateChannelOnIOThread(id, channel_pair.PassServerHandle());
+ channel_manager().CreateChannelOnIOThread(
+ id, channel_pair.PassServerHandle());
- scoped_refptr<Channel> ch = cm.GetChannel(id);
+ scoped_refptr<Channel> ch = channel_manager().GetChannel(id);
EXPECT_TRUE(ch);
// |ChannelManager| should have a ref.
EXPECT_FALSE(ch->HasOneRef());
- cm.WillShutdownChannel(id);
+ channel_manager().WillShutdownChannel(id);
// |ChannelManager| should still have a ref.
EXPECT_FALSE(ch->HasOneRef());
- cm.ShutdownChannel(id);
- // On the "I/O" thread, so shutdown should happen synchronously.
+ channel_manager().ShutdownChannelOnIOThread(id);
// |ChannelManager| should have given up its ref.
EXPECT_TRUE(ch->HasOneRef());
@@ -70,33 +69,33 @@ TEST_F(ChannelManagerTest, Basic) {
}
TEST_F(ChannelManagerTest, TwoChannels) {
- ChannelManager cm(platform_support());
-
embedder::PlatformChannelPair channel_pair;
const ChannelId id1 = 1;
scoped_refptr<MessagePipeDispatcher> d1 =
- cm.CreateChannelOnIOThread(id1, channel_pair.PassServerHandle());
+ channel_manager().CreateChannelOnIOThread(
+ id1, channel_pair.PassServerHandle());
const ChannelId id2 = 2;
scoped_refptr<MessagePipeDispatcher> d2 =
- cm.CreateChannelOnIOThread(id2, channel_pair.PassClientHandle());
+ channel_manager().CreateChannelOnIOThread(
+ id2, channel_pair.PassClientHandle());
- scoped_refptr<Channel> ch1 = cm.GetChannel(id1);
+ scoped_refptr<Channel> ch1 = channel_manager().GetChannel(id1);
EXPECT_TRUE(ch1);
- scoped_refptr<Channel> ch2 = cm.GetChannel(id2);
+ scoped_refptr<Channel> ch2 = channel_manager().GetChannel(id2);
EXPECT_TRUE(ch2);
// Calling |WillShutdownChannel()| multiple times (on |id1|) is okay.
- cm.WillShutdownChannel(id1);
- cm.WillShutdownChannel(id1);
+ channel_manager().WillShutdownChannel(id1);
+ channel_manager().WillShutdownChannel(id1);
EXPECT_FALSE(ch1->HasOneRef());
// Not calling |WillShutdownChannel()| (on |id2|) is okay too.
- cm.ShutdownChannel(id1);
+ channel_manager().ShutdownChannelOnIOThread(id1);
EXPECT_TRUE(ch1->HasOneRef());
- cm.ShutdownChannel(id2);
+ channel_manager().ShutdownChannelOnIOThread(id2);
EXPECT_TRUE(ch2->HasOneRef());
EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
@@ -110,7 +109,7 @@ class OtherThread : public base::SimpleThread {
OtherThread(scoped_refptr<base::TaskRunner> task_runner,
ChannelManager* channel_manager,
ChannelId channel_id,
- base::Closure quit_closure)
+ const base::Closure& quit_closure)
: base::SimpleThread("other_thread"),
task_runner_(task_runner),
channel_manager_(channel_manager),
@@ -132,20 +131,12 @@ class OtherThread : public base::SimpleThread {
// |ChannelManager| should still have a ref.
EXPECT_FALSE(ch->HasOneRef());
- channel_manager_->ShutdownChannel(channel_id_);
- // This doesn't happen synchronously, so we "wait" until it does.
- // TODO(vtl): Probably |Channel| should provide some notification of being
- // shut down.
- base::TimeTicks start_time(base::TimeTicks::Now());
- for (;;) {
- if (ch->HasOneRef())
- break;
-
- // Check, instead of assert, since if things go wrong, dying is more
- // reliable than tearing down.
- CHECK_LT(base::TimeTicks::Now() - start_time,
- TestTimeouts::action_timeout());
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
+ {
+ base::MessageLoop message_loop;
+ base::RunLoop run_loop;
+ channel_manager_->ShutdownChannel(channel_id_, run_loop.QuitClosure(),
+ message_loop.task_runner());
+ run_loop.Run();
}
CHECK(task_runner_->PostTask(FROM_HERE, quit_closure_));
@@ -160,16 +151,15 @@ class OtherThread : public base::SimpleThread {
};
TEST_F(ChannelManagerTest, CallsFromOtherThread) {
- ChannelManager cm(platform_support());
-
embedder::PlatformChannelPair channel_pair;
const ChannelId id = 1;
scoped_refptr<MessagePipeDispatcher> d =
- cm.CreateChannelOnIOThread(id, channel_pair.PassServerHandle());
+ channel_manager().CreateChannelOnIOThread(
+ id, channel_pair.PassServerHandle());
base::RunLoop run_loop;
- OtherThread thread(base::MessageLoopProxy::current(), &cm, id,
+ OtherThread thread(base::MessageLoopProxy::current(), &channel_manager(), id,
run_loop.QuitClosure());
thread.Start();
run_loop.Run();
diff --git a/third_party/mojo/src/mojo/edk/system/connection_manager.h b/third_party/mojo/src/mojo/edk/system/connection_manager.h
index fede7a5..921d19c 100644
--- a/third_party/mojo/src/mojo/edk/system/connection_manager.h
+++ b/third_party/mojo/src/mojo/edk/system/connection_manager.h
@@ -6,6 +6,7 @@
#define MOJO_EDK_SYSTEM_CONNECTION_MANAGER_H_
#include "base/macros.h"
+#include "mojo/edk/system/system_impl_export.h"
#include "mojo/edk/system/unique_identifier.h"
namespace mojo {
@@ -62,15 +63,21 @@ const ProcessIdentifier kInvalidProcessIdentifier = 0;
// connected to the master by a special dedicated |RawChannel|, on which it does
// synchronous IPC (note, however, that the master should never block on any
// slave).
-class ConnectionManager {
+class MOJO_SYSTEM_IMPL_EXPORT ConnectionManager {
public:
- // All of these methods return true on success or false on failure. Failure is
- // obviously fatal for the establishment of a particular connection, but
- // should not be treated as fatal to the process. Failure may, e.g., be caused
- // by a misbehaving (malicious) untrusted peer process.
+ virtual ~ConnectionManager() {}
+
+ // Shuts down this connection manager. No other methods may be called after
+ // this is (or while it is being) called.
+ virtual void Shutdown() = 0;
// TODO(vtl): Add a "get my own process identifier" method?
+ // All of the methods below return true on success or false on failure.
+ // Failure is obviously fatal for the establishment of a particular
+ // connection, but should not be treated as fatal to the process. Failure may,
+ // e.g., be caused by a misbehaving (malicious) untrusted peer process.
+
// Allows a process who makes the identical call (with equal |connection_id|)
// to connect to the calling process. (On success, there will be a "pending
// connection" for the given |connection_id| for the calling process.)
@@ -93,7 +100,6 @@ class ConnectionManager {
protected:
ConnectionManager() {}
- virtual ~ConnectionManager() {}
private:
DISALLOW_COPY_AND_ASSIGN(ConnectionManager);
diff --git a/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc b/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc
index f1939a0..fea0920 100644
--- a/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc
+++ b/third_party/mojo/src/mojo/edk/system/connection_manager_unittest.cc
@@ -17,6 +17,7 @@
#include "base/threading/thread_checker.h"
#include "mojo/edk/embedder/master_process_delegate.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/edk/embedder/slave_process_delegate.h"
#include "mojo/edk/system/master_connection_manager.h"
#include "mojo/edk/system/slave_connection_manager.h"
@@ -63,10 +64,10 @@ bool IsValidSlaveProcessIdentifier(ProcessIdentifier process_identifier) {
process_identifier != kMasterProcessIdentifier;
}
-class TestSlaveInfo : public embedder::SlaveInfo {
+class TestSlaveInfo {
public:
explicit TestSlaveInfo(const std::string& name) : name_(name) {}
- ~TestSlaveInfo() override { CHECK(thread_checker_.CalledOnValidThread()); }
+ ~TestSlaveInfo() { CHECK(thread_checker_.CalledOnValidThread()); }
const std::string& name() const { return name_; }
@@ -85,7 +86,7 @@ void ConnectSlave(MasterConnectionManager* master,
SlaveConnectionManager* slave,
const std::string& slave_name) {
embedder::PlatformChannelPair platform_channel_pair;
- master->AddSlave(make_scoped_ptr(new TestSlaveInfo(slave_name)),
+ master->AddSlave(new TestSlaveInfo(slave_name),
platform_channel_pair.PassServerHandle());
slave->Init(base::MessageLoop::current()->task_runner(),
slave_process_delegate, platform_channel_pair.PassClientHandle());
@@ -113,14 +114,16 @@ class MockMasterProcessDelegate : public embedder::MasterProcessDelegate {
}
// |embedder::MasterProcessDelegate| implementation:
- void OnSlaveDisconnect(scoped_ptr<embedder::SlaveInfo> slave_info) override {
+ void OnShutdownComplete() override { NOTREACHED(); }
+
+ void OnSlaveDisconnect(embedder::SlaveInfo slave_info) override {
CHECK(thread_checker_.CalledOnValidThread());
on_slave_disconnect_calls_++;
last_slave_disconnect_name_ =
- static_cast<TestSlaveInfo*>(slave_info.get())->name();
+ static_cast<TestSlaveInfo*>(slave_info)->name();
DVLOG(1) << "Disconnected from slave process "
<< last_slave_disconnect_name_;
- slave_info.reset();
+ delete static_cast<TestSlaveInfo*>(slave_info);
if (current_run_loop_)
current_run_loop_->Quit();
@@ -155,6 +158,8 @@ class MockSlaveProcessDelegate : public embedder::SlaveProcessDelegate {
}
// |embedder::SlaveProcessDelegate| implementation:
+ void OnShutdownComplete() override { NOTREACHED(); }
+
void OnMasterDisconnect() override {
CHECK(thread_checker_.CalledOnValidThread());
on_master_disconnect_calls_++;
@@ -178,12 +183,15 @@ class ConnectionManagerTest : public testing::Test {
ConnectionManagerTest() {}
~ConnectionManagerTest() override {}
+ embedder::PlatformSupport* platform_support() { return &platform_support_; }
+
base::MessageLoop& message_loop() { return message_loop_; }
MockMasterProcessDelegate& master_process_delegate() {
return master_process_delegate_;
}
private:
+ embedder::SimplePlatformSupport platform_support_;
base::MessageLoop message_loop_;
MockMasterProcessDelegate master_process_delegate_;
@@ -203,7 +211,8 @@ TEST_F(ConnectionManagerTest, BasicConnectSlaves) {
SlaveConnectionManager slave2;
ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2");
- ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
+ ConnectionIdentifier connection_id =
+ ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(slave1.AllowConnect(connection_id));
EXPECT_TRUE(slave2.AllowConnect(connection_id));
@@ -291,7 +300,8 @@ TEST_F(ConnectionManagerTest, SlaveCancelConnect) {
SlaveConnectionManager slave2;
ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2");
- ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
+ ConnectionIdentifier connection_id =
+ ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(slave1.AllowConnect(connection_id));
EXPECT_TRUE(slave2.AllowConnect(connection_id));
@@ -321,7 +331,8 @@ TEST_F(ConnectionManagerTest, ErrorRemovePending) {
SlaveConnectionManager slave2;
ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2");
- ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
+ ConnectionIdentifier connection_id =
+ ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(slave1.AllowConnect(connection_id));
EXPECT_TRUE(slave2.AllowConnect(connection_id));
@@ -352,7 +363,8 @@ TEST_F(ConnectionManagerTest, ConnectSlaveToSelf) {
SlaveConnectionManager slave;
ConnectSlave(&master, &slave_process_delegate, &slave, "slave");
- ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
+ ConnectionIdentifier connection_id =
+ ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(slave.AllowConnect(connection_id));
EXPECT_TRUE(slave.AllowConnect(connection_id));
@@ -388,7 +400,8 @@ TEST_F(ConnectionManagerTest, ConnectSlavesTwice) {
SlaveConnectionManager slave2;
ConnectSlave(&master, &slave2_process_delegate, &slave2, "slave2");
- ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
+ ConnectionIdentifier connection_id =
+ ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(slave1.AllowConnect(connection_id));
EXPECT_TRUE(slave2.AllowConnect(connection_id));
@@ -407,7 +420,7 @@ TEST_F(ConnectionManagerTest, ConnectSlavesTwice) {
// tracking and is prone to races -- especially if we want slaves to be able
// to tear down no-longer-needed connections.) But the slaves should be able
// to do the tracking themselves (using the peer process identifiers).
- connection_id = ConnectionIdentifier::Generate();
+ connection_id = ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(slave1.AllowConnect(connection_id));
EXPECT_TRUE(slave2.AllowConnect(connection_id));
@@ -436,7 +449,8 @@ TEST_F(ConnectionManagerTest, ConnectMasterToSlave) {
SlaveConnectionManager slave;
ConnectSlave(&master, &slave_process_delegate, &slave, "slave");
- ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
+ ConnectionIdentifier connection_id =
+ ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(master.AllowConnect(connection_id));
EXPECT_TRUE(slave.AllowConnect(connection_id));
@@ -463,7 +477,8 @@ TEST_F(ConnectionManagerTest, ConnectMasterToSelf) {
master.Init(base::MessageLoop::current()->task_runner(),
&master_process_delegate());
- ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
+ ConnectionIdentifier connection_id =
+ ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(master.AllowConnect(connection_id));
EXPECT_TRUE(master.AllowConnect(connection_id));
@@ -494,7 +509,8 @@ TEST_F(ConnectionManagerTest, MasterCancelConnect) {
SlaveConnectionManager slave;
ConnectSlave(&master, &slave_process_delegate, &slave, "slave");
- ConnectionIdentifier connection_id = ConnectionIdentifier::Generate();
+ ConnectionIdentifier connection_id =
+ ConnectionIdentifier::Generate(platform_support());
EXPECT_TRUE(master.AllowConnect(connection_id));
EXPECT_TRUE(slave.AllowConnect(connection_id));
@@ -517,7 +533,7 @@ TEST_F(ConnectionManagerTest, AddSlaveThenImmediateShutdown) {
MockSlaveProcessDelegate slave_process_delegate;
SlaveConnectionManager slave;
embedder::PlatformChannelPair platform_channel_pair;
- master.AddSlave(make_scoped_ptr(new TestSlaveInfo("slave")),
+ master.AddSlave(new TestSlaveInfo("slave"),
platform_channel_pair.PassServerHandle());
master.Shutdown();
// Since we never initialized |slave|, we don't have to shut it down.
diff --git a/third_party/mojo/src/mojo/edk/system/core.cc b/third_party/mojo/src/mojo/edk/system/core.cc
index 4460088..80c3d36 100644
--- a/third_party/mojo/src/mojo/edk/system/core.cc
+++ b/third_party/mojo/src/mojo/edk/system/core.cc
@@ -17,7 +17,6 @@
#include "mojo/edk/system/data_pipe_producer_dispatcher.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/handle_signals_state.h"
-#include "mojo/edk/system/local_data_pipe.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
@@ -100,7 +99,7 @@ scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
MojoResult Core::AsyncWait(MojoHandle handle,
MojoHandleSignals signals,
- base::Callback<void(MojoResult)> callback) {
+ const base::Callback<void(MojoResult)>& callback) {
scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle);
DCHECK(dispatcher);
@@ -381,7 +380,7 @@ MojoResult Core::CreateDataPipe(
}
DCHECK_NE(handle_pair.second, MOJO_HANDLE_INVALID);
- scoped_refptr<DataPipe> data_pipe(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> data_pipe(DataPipe::CreateLocal(validated_options));
producer_dispatcher->Init(data_pipe);
consumer_dispatcher->Init(data_pipe);
diff --git a/third_party/mojo/src/mojo/edk/system/core.h b/third_party/mojo/src/mojo/edk/system/core.h
index 7833193c..aadfb66 100644
--- a/third_party/mojo/src/mojo/edk/system/core.h
+++ b/third_party/mojo/src/mojo/edk/system/core.h
@@ -58,7 +58,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// awakable.h. In particular, it must not call any Mojo system functions.
MojoResult AsyncWait(MojoHandle handle,
MojoHandleSignals signals,
- base::Callback<void(MojoResult)> callback);
+ const base::Callback<void(MojoResult)>& callback);
embedder::PlatformSupport* platform_support() const {
return platform_support_;
diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe.cc b/third_party/mojo/src/mojo/edk/system/data_pipe.cc
index 2f433bd..d5e9db9 100644
--- a/third_party/mojo/src/mojo/edk/system/data_pipe.cc
+++ b/third_party/mojo/src/mojo/edk/system/data_pipe.cc
@@ -12,6 +12,8 @@
#include "base/logging.h"
#include "mojo/edk/system/awakable_list.h"
#include "mojo/edk/system/configuration.h"
+#include "mojo/edk/system/data_pipe_impl.h"
+#include "mojo/edk/system/local_data_pipe_impl.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/options_validation.h"
@@ -83,6 +85,13 @@ MojoResult DataPipe::ValidateCreateOptions(
return MOJO_RESULT_OK;
}
+// static
+DataPipe* DataPipe::CreateLocal(
+ const MojoCreateDataPipeOptions& validated_options) {
+ return new DataPipe(true, true, validated_options,
+ make_scoped_ptr(new LocalDataPipeImpl()));
+}
+
void DataPipe::ProducerCancelAllAwakables() {
base::AutoLock locker(lock_);
DCHECK(has_local_producer_no_lock());
@@ -91,17 +100,7 @@ void DataPipe::ProducerCancelAllAwakables() {
void DataPipe::ProducerClose() {
base::AutoLock locker(lock_);
- DCHECK(producer_open_);
- producer_open_ = false;
- DCHECK(has_local_producer_no_lock());
- producer_awakable_list_.reset();
- // Not a bug, except possibly in "user" code.
- DVLOG_IF(2, producer_in_two_phase_write_no_lock())
- << "Producer closed with active two-phase write";
- producer_two_phase_max_num_bytes_written_ = 0;
- ProducerCloseImplNoLock();
- AwakeConsumerAwakablesForStateChangeNoLock(
- ConsumerGetHandleSignalsStateImplNoLock());
+ ProducerCloseNoLock();
}
MojoResult DataPipe::ProducerWriteData(UserPointer<const void> elements,
@@ -117,7 +116,7 @@ MojoResult DataPipe::ProducerWriteData(UserPointer<const void> elements,
// Returning "busy" takes priority over "invalid argument".
uint32_t max_num_bytes_to_write = num_bytes.Get();
- if (max_num_bytes_to_write % element_num_bytes_ != 0)
+ if (max_num_bytes_to_write % element_num_bytes() != 0)
return MOJO_RESULT_INVALID_ARGUMENT;
if (max_num_bytes_to_write == 0)
@@ -126,11 +125,11 @@ MojoResult DataPipe::ProducerWriteData(UserPointer<const void> elements,
uint32_t min_num_bytes_to_write = all_or_none ? max_num_bytes_to_write : 0;
HandleSignalsState old_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
- MojoResult rv = ProducerWriteDataImplNoLock(
+ impl_->ConsumerGetHandleSignalsState();
+ MojoResult rv = impl_->ProducerWriteData(
elements, num_bytes, max_num_bytes_to_write, min_num_bytes_to_write);
HandleSignalsState new_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
+ impl_->ConsumerGetHandleSignalsState();
if (!new_consumer_state.equals(old_consumer_state))
AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
return rv;
@@ -151,12 +150,12 @@ MojoResult DataPipe::ProducerBeginWriteData(
uint32_t min_num_bytes_to_write = 0;
if (all_or_none) {
min_num_bytes_to_write = buffer_num_bytes.Get();
- if (min_num_bytes_to_write % element_num_bytes_ != 0)
+ if (min_num_bytes_to_write % element_num_bytes() != 0)
return MOJO_RESULT_INVALID_ARGUMENT;
}
- MojoResult rv = ProducerBeginWriteDataImplNoLock(buffer, buffer_num_bytes,
- min_num_bytes_to_write);
+ MojoResult rv = impl_->ProducerBeginWriteData(buffer, buffer_num_bytes,
+ min_num_bytes_to_write);
if (rv != MOJO_RESULT_OK)
return rv;
// Note: No need to awake producer awakables, even though we're going from
@@ -177,25 +176,25 @@ MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) {
// consumer has been closed.
HandleSignalsState old_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
+ impl_->ConsumerGetHandleSignalsState();
MojoResult rv;
if (num_bytes_written > producer_two_phase_max_num_bytes_written_ ||
- num_bytes_written % element_num_bytes_ != 0) {
+ num_bytes_written % element_num_bytes() != 0) {
rv = MOJO_RESULT_INVALID_ARGUMENT;
producer_two_phase_max_num_bytes_written_ = 0;
} else {
- rv = ProducerEndWriteDataImplNoLock(num_bytes_written);
+ rv = impl_->ProducerEndWriteData(num_bytes_written);
}
// Two-phase write ended even on failure.
DCHECK(!producer_in_two_phase_write_no_lock());
// If we're now writable, we *became* writable (since we weren't writable
// during the two-phase write), so awake producer awakables.
HandleSignalsState new_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
+ impl_->ProducerGetHandleSignalsState();
if (new_producer_state.satisfies(MOJO_HANDLE_SIGNAL_WRITABLE))
AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
HandleSignalsState new_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
+ impl_->ConsumerGetHandleSignalsState();
if (!new_consumer_state.equals(old_consumer_state))
AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
return rv;
@@ -204,7 +203,7 @@ MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) {
HandleSignalsState DataPipe::ProducerGetHandleSignalsState() {
base::AutoLock locker(lock_);
DCHECK(has_local_producer_no_lock());
- return ProducerGetHandleSignalsStateImplNoLock();
+ return impl_->ProducerGetHandleSignalsState();
}
MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable,
@@ -214,7 +213,7 @@ MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable,
base::AutoLock locker(lock_);
DCHECK(has_local_producer_no_lock());
- HandleSignalsState producer_state = ProducerGetHandleSignalsStateImplNoLock();
+ HandleSignalsState producer_state = impl_->ProducerGetHandleSignalsState();
if (producer_state.satisfies(signals)) {
if (signals_state)
*signals_state = producer_state;
@@ -236,7 +235,26 @@ void DataPipe::ProducerRemoveAwakable(Awakable* awakable,
DCHECK(has_local_producer_no_lock());
producer_awakable_list_->Remove(awakable);
if (signals_state)
- *signals_state = ProducerGetHandleSignalsStateImplNoLock();
+ *signals_state = impl_->ProducerGetHandleSignalsState();
+}
+
+void DataPipe::ProducerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) {
+ base::AutoLock locker(lock_);
+ DCHECK(has_local_producer_no_lock());
+ impl_->ProducerStartSerialize(channel, max_size, max_platform_handles);
+}
+
+bool DataPipe::ProducerEndSerialize(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) {
+ base::AutoLock locker(lock_);
+ DCHECK(has_local_producer_no_lock());
+ return impl_->ProducerEndSerialize(channel, destination, actual_size,
+ platform_handles);
}
bool DataPipe::ProducerIsBusy() const {
@@ -252,17 +270,7 @@ void DataPipe::ConsumerCancelAllAwakables() {
void DataPipe::ConsumerClose() {
base::AutoLock locker(lock_);
- DCHECK(consumer_open_);
- consumer_open_ = false;
- DCHECK(has_local_consumer_no_lock());
- consumer_awakable_list_.reset();
- // Not a bug, except possibly in "user" code.
- DVLOG_IF(2, consumer_in_two_phase_read_no_lock())
- << "Consumer closed with active two-phase read";
- consumer_two_phase_max_num_bytes_read_ = 0;
- ConsumerCloseImplNoLock();
- AwakeProducerAwakablesForStateChangeNoLock(
- ProducerGetHandleSignalsStateImplNoLock());
+ ConsumerCloseNoLock();
}
MojoResult DataPipe::ConsumerReadData(UserPointer<void> elements,
@@ -276,7 +284,7 @@ MojoResult DataPipe::ConsumerReadData(UserPointer<void> elements,
return MOJO_RESULT_BUSY;
uint32_t max_num_bytes_to_read = num_bytes.Get();
- if (max_num_bytes_to_read % element_num_bytes_ != 0)
+ if (max_num_bytes_to_read % element_num_bytes() != 0)
return MOJO_RESULT_INVALID_ARGUMENT;
if (max_num_bytes_to_read == 0)
@@ -285,11 +293,11 @@ MojoResult DataPipe::ConsumerReadData(UserPointer<void> elements,
uint32_t min_num_bytes_to_read = all_or_none ? max_num_bytes_to_read : 0;
HandleSignalsState old_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- MojoResult rv = ConsumerReadDataImplNoLock(
+ impl_->ProducerGetHandleSignalsState();
+ MojoResult rv = impl_->ConsumerReadData(
elements, num_bytes, max_num_bytes_to_read, min_num_bytes_to_read, peek);
HandleSignalsState new_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
+ impl_->ProducerGetHandleSignalsState();
if (!new_producer_state.equals(old_producer_state))
AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
return rv;
@@ -304,7 +312,7 @@ MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes,
return MOJO_RESULT_BUSY;
uint32_t max_num_bytes_to_discard = num_bytes.Get();
- if (max_num_bytes_to_discard % element_num_bytes_ != 0)
+ if (max_num_bytes_to_discard % element_num_bytes() != 0)
return MOJO_RESULT_INVALID_ARGUMENT;
if (max_num_bytes_to_discard == 0)
@@ -314,11 +322,11 @@ MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes,
all_or_none ? max_num_bytes_to_discard : 0;
HandleSignalsState old_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
- MojoResult rv = ConsumerDiscardDataImplNoLock(
+ impl_->ProducerGetHandleSignalsState();
+ MojoResult rv = impl_->ConsumerDiscardData(
num_bytes, max_num_bytes_to_discard, min_num_bytes_to_discard);
HandleSignalsState new_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
+ impl_->ProducerGetHandleSignalsState();
if (!new_producer_state.equals(old_producer_state))
AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
return rv;
@@ -332,7 +340,7 @@ MojoResult DataPipe::ConsumerQueryData(UserPointer<uint32_t> num_bytes) {
return MOJO_RESULT_BUSY;
// Note: Don't need to validate |*num_bytes| for query.
- return ConsumerQueryDataImplNoLock(num_bytes);
+ return impl_->ConsumerQueryData(num_bytes);
}
MojoResult DataPipe::ConsumerBeginReadData(
@@ -348,12 +356,12 @@ MojoResult DataPipe::ConsumerBeginReadData(
uint32_t min_num_bytes_to_read = 0;
if (all_or_none) {
min_num_bytes_to_read = buffer_num_bytes.Get();
- if (min_num_bytes_to_read % element_num_bytes_ != 0)
+ if (min_num_bytes_to_read % element_num_bytes() != 0)
return MOJO_RESULT_INVALID_ARGUMENT;
}
- MojoResult rv = ConsumerBeginReadDataImplNoLock(buffer, buffer_num_bytes,
- min_num_bytes_to_read);
+ MojoResult rv = impl_->ConsumerBeginReadData(buffer, buffer_num_bytes,
+ min_num_bytes_to_read);
if (rv != MOJO_RESULT_OK)
return rv;
DCHECK(consumer_in_two_phase_read_no_lock());
@@ -368,25 +376,25 @@ MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) {
return MOJO_RESULT_FAILED_PRECONDITION;
HandleSignalsState old_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
+ impl_->ProducerGetHandleSignalsState();
MojoResult rv;
if (num_bytes_read > consumer_two_phase_max_num_bytes_read_ ||
- num_bytes_read % element_num_bytes_ != 0) {
+ num_bytes_read % element_num_bytes() != 0) {
rv = MOJO_RESULT_INVALID_ARGUMENT;
consumer_two_phase_max_num_bytes_read_ = 0;
} else {
- rv = ConsumerEndReadDataImplNoLock(num_bytes_read);
+ rv = impl_->ConsumerEndReadData(num_bytes_read);
}
// Two-phase read ended even on failure.
DCHECK(!consumer_in_two_phase_read_no_lock());
// If we're now readable, we *became* readable (since we weren't readable
// during the two-phase read), so awake consumer awakables.
HandleSignalsState new_consumer_state =
- ConsumerGetHandleSignalsStateImplNoLock();
+ impl_->ConsumerGetHandleSignalsState();
if (new_consumer_state.satisfies(MOJO_HANDLE_SIGNAL_READABLE))
AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state);
HandleSignalsState new_producer_state =
- ProducerGetHandleSignalsStateImplNoLock();
+ impl_->ProducerGetHandleSignalsState();
if (!new_producer_state.equals(old_producer_state))
AwakeProducerAwakablesForStateChangeNoLock(new_producer_state);
return rv;
@@ -395,7 +403,7 @@ MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) {
HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() {
base::AutoLock locker(lock_);
DCHECK(has_local_consumer_no_lock());
- return ConsumerGetHandleSignalsStateImplNoLock();
+ return impl_->ConsumerGetHandleSignalsState();
}
MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable,
@@ -405,7 +413,7 @@ MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable,
base::AutoLock locker(lock_);
DCHECK(has_local_consumer_no_lock());
- HandleSignalsState consumer_state = ConsumerGetHandleSignalsStateImplNoLock();
+ HandleSignalsState consumer_state = impl_->ConsumerGetHandleSignalsState();
if (consumer_state.satisfies(signals)) {
if (signals_state)
*signals_state = consumer_state;
@@ -427,7 +435,26 @@ void DataPipe::ConsumerRemoveAwakable(Awakable* awakable,
DCHECK(has_local_consumer_no_lock());
consumer_awakable_list_->Remove(awakable);
if (signals_state)
- *signals_state = ConsumerGetHandleSignalsStateImplNoLock();
+ *signals_state = impl_->ConsumerGetHandleSignalsState();
+}
+
+void DataPipe::ConsumerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) {
+ base::AutoLock locker(lock_);
+ DCHECK(has_local_consumer_no_lock());
+ impl_->ConsumerStartSerialize(channel, max_size, max_platform_handles);
+}
+
+bool DataPipe::ConsumerEndSerialize(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) {
+ base::AutoLock locker(lock_);
+ DCHECK(has_local_consumer_no_lock());
+ return impl_->ConsumerEndSerialize(channel, destination, actual_size,
+ platform_handles);
}
bool DataPipe::ConsumerIsBusy() const {
@@ -437,11 +464,9 @@ bool DataPipe::ConsumerIsBusy() const {
DataPipe::DataPipe(bool has_local_producer,
bool has_local_consumer,
- const MojoCreateDataPipeOptions& validated_options)
- : may_discard_((validated_options.flags &
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD)),
- element_num_bytes_(validated_options.element_num_bytes),
- capacity_num_bytes_(validated_options.capacity_num_bytes),
+ const MojoCreateDataPipeOptions& validated_options,
+ scoped_ptr<DataPipeImpl> impl)
+ : validated_options_(validated_options),
producer_open_(true),
consumer_open_(true),
producer_awakable_list_(has_local_producer ? new AwakableList()
@@ -449,11 +474,16 @@ DataPipe::DataPipe(bool has_local_producer,
consumer_awakable_list_(has_local_consumer ? new AwakableList()
: nullptr),
producer_two_phase_max_num_bytes_written_(0),
- consumer_two_phase_max_num_bytes_read_(0) {
+ consumer_two_phase_max_num_bytes_read_(0),
+ impl_(impl.Pass()) {
+ impl_->set_owner(this);
+
+#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
// Check that the passed in options actually are validated.
MojoCreateDataPipeOptions unused = {0};
DCHECK_EQ(ValidateCreateOptions(MakeUserPointer(&validated_options), &unused),
MOJO_RESULT_OK);
+#endif // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
}
DataPipe::~DataPipe() {
@@ -463,6 +493,36 @@ DataPipe::~DataPipe() {
DCHECK(!consumer_awakable_list_);
}
+void DataPipe::ProducerCloseNoLock() {
+ lock_.AssertAcquired();
+ DCHECK(producer_open_);
+ producer_open_ = false;
+ DCHECK(has_local_producer_no_lock());
+ producer_awakable_list_.reset();
+ // Not a bug, except possibly in "user" code.
+ DVLOG_IF(2, producer_in_two_phase_write_no_lock())
+ << "Producer closed with active two-phase write";
+ producer_two_phase_max_num_bytes_written_ = 0;
+ impl_->ProducerClose();
+ AwakeConsumerAwakablesForStateChangeNoLock(
+ impl_->ConsumerGetHandleSignalsState());
+}
+
+void DataPipe::ConsumerCloseNoLock() {
+ lock_.AssertAcquired();
+ DCHECK(consumer_open_);
+ consumer_open_ = false;
+ DCHECK(has_local_consumer_no_lock());
+ consumer_awakable_list_.reset();
+ // Not a bug, except possibly in "user" code.
+ DVLOG_IF(2, consumer_in_two_phase_read_no_lock())
+ << "Consumer closed with active two-phase read";
+ consumer_two_phase_max_num_bytes_read_ = 0;
+ impl_->ConsumerClose();
+ AwakeProducerAwakablesForStateChangeNoLock(
+ impl_->ProducerGetHandleSignalsState());
+}
+
void DataPipe::AwakeProducerAwakablesForStateChangeNoLock(
const HandleSignalsState& new_producer_state) {
lock_.AssertAcquired();
diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe.h b/third_party/mojo/src/mojo/edk/system/data_pipe.h
index d893465..dfac644 100644
--- a/third_party/mojo/src/mojo/edk/system/data_pipe.h
+++ b/third_party/mojo/src/mojo/edk/system/data_pipe.h
@@ -7,10 +7,12 @@
#include <stdint.h>
+#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
+#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/system_impl_export.h"
@@ -22,6 +24,8 @@ namespace system {
class Awakable;
class AwakableList;
+class Channel;
+class DataPipeImpl;
// |DataPipe| is a base class for secondary objects implementing data pipes,
// similar to |MessagePipe| (see the explanatory comment in core.cc). It is
@@ -46,6 +50,14 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe
UserPointer<const MojoCreateDataPipeOptions> in_options,
MojoCreateDataPipeOptions* out_options);
+ // Creates a local (both producer and consumer) data pipe (using
+ // |LocalDataPipeImpl|. |validated_options| should be the output of
+ // |ValidateOptions()|. In particular: |struct_size| is ignored (so
+ // |validated_options| must be the current version of the struct) and
+ // |capacity_num_bytes| must be nonzero.
+ static DataPipe* CreateLocal(
+ const MojoCreateDataPipeOptions& validated_options);
+
// These are called by the producer dispatcher to implement its methods of
// corresponding names.
void ProducerCancelAllAwakables();
@@ -64,6 +76,13 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe
HandleSignalsState* signals_state);
void ProducerRemoveAwakable(Awakable* awakable,
HandleSignalsState* signals_state);
+ void ProducerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles);
+ bool ProducerEndSerialize(Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles);
bool ProducerIsBusy() const;
// These are called by the consumer dispatcher to implement its methods of
@@ -90,60 +109,34 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe
HandleSignalsState* signals_state);
void ConsumerRemoveAwakable(Awakable* awakable,
HandleSignalsState* signals_state);
+ void ConsumerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles);
+ bool ConsumerEndSerialize(Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles);
bool ConsumerIsBusy() const;
- protected:
- DataPipe(bool has_local_producer,
- bool has_local_consumer,
- const MojoCreateDataPipeOptions& validated_options);
-
- friend class base::RefCountedThreadSafe<DataPipe>;
- virtual ~DataPipe();
+ // The following are only to be used by |DataPipeImpl| (and its subclasses):
- virtual void ProducerCloseImplNoLock() = 0;
- // |num_bytes.Get()| will be a nonzero multiple of |element_num_bytes_|.
- virtual MojoResult ProducerWriteDataImplNoLock(
- UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_write,
- uint32_t min_num_bytes_to_write) = 0;
- virtual MojoResult ProducerBeginWriteDataImplNoLock(
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_write) = 0;
- virtual MojoResult ProducerEndWriteDataImplNoLock(
- uint32_t num_bytes_written) = 0;
- // Note: A producer should not be writable during a two-phase write.
- virtual HandleSignalsState ProducerGetHandleSignalsStateImplNoLock()
- const = 0;
-
- virtual void ConsumerCloseImplNoLock() = 0;
- // |*num_bytes| will be a nonzero multiple of |element_num_bytes_|.
- virtual MojoResult ConsumerReadDataImplNoLock(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_read,
- uint32_t min_num_bytes_to_read,
- bool peek) = 0;
- virtual MojoResult ConsumerDiscardDataImplNoLock(
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_discard,
- uint32_t min_num_bytes_to_discard) = 0;
- // |*num_bytes| will be a nonzero multiple of |element_num_bytes_|.
- virtual MojoResult ConsumerQueryDataImplNoLock(
- UserPointer<uint32_t> num_bytes) = 0;
- virtual MojoResult ConsumerBeginReadDataImplNoLock(
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_read) = 0;
- virtual MojoResult ConsumerEndReadDataImplNoLock(uint32_t num_bytes_read) = 0;
- // Note: A consumer should not be writable during a two-phase read.
- virtual HandleSignalsState ConsumerGetHandleSignalsStateImplNoLock()
- const = 0;
+ void ProducerCloseNoLock();
+ void ConsumerCloseNoLock();
// Thread-safe and fast (they don't take the lock):
- bool may_discard() const { return may_discard_; }
- size_t element_num_bytes() const { return element_num_bytes_; }
- size_t capacity_num_bytes() const { return capacity_num_bytes_; }
+ const MojoCreateDataPipeOptions& validated_options() const {
+ return validated_options_;
+ }
+ bool may_discard() const {
+ return (validated_options_.flags &
+ MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD);
+ }
+ size_t element_num_bytes() const {
+ return validated_options_.element_num_bytes;
+ }
+ size_t capacity_num_bytes() const {
+ return validated_options_.capacity_num_bytes;
+ }
// Must be called under lock.
bool producer_open_no_lock() const {
@@ -181,6 +174,22 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe
}
private:
+ friend class base::RefCountedThreadSafe<DataPipe>;
+
+ // |validated_options| should be the output of |ValidateOptions()|. In
+ // particular: |struct_size| is ignored (so |validated_options| must be the
+ // current version of the struct) and |capacity_num_bytes| must be nonzero.
+ // TODO(vtl): |has_local_producer|/|has_local_consumer| shouldn't really be
+ // arguments here. Instead, they should be determined from the |impl| ... but
+ // the |impl|'s typically figures these out by examining the owner, i.e., the
+ // |DataPipe| object. Probably, this indicates that more stuff should be moved
+ // to |DataPipeImpl|, but for now we'll live with this.
+ DataPipe(bool has_local_producer,
+ bool has_local_consumer,
+ const MojoCreateDataPipeOptions& validated_options,
+ scoped_ptr<DataPipeImpl> impl);
+ virtual ~DataPipe();
+
void AwakeProducerAwakablesForStateChangeNoLock(
const HandleSignalsState& new_producer_state);
void AwakeConsumerAwakablesForStateChangeNoLock(
@@ -195,9 +204,8 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe
return !!consumer_awakable_list_;
}
- const bool may_discard_;
- const size_t element_num_bytes_;
- const size_t capacity_num_bytes_;
+ MSVC_SUPPRESS_WARNING(4324) // Suppress an alignment warning on 64-bit MSVC.
+ const MojoCreateDataPipeOptions validated_options_;
mutable base::Lock lock_; // Protects the following members.
// *Known* state of producer or consumer.
@@ -209,6 +217,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe
// These are nonzero if and only if a two-phase write/read is in progress.
uint32_t producer_two_phase_max_num_bytes_written_;
uint32_t consumer_two_phase_max_num_bytes_read_;
+ scoped_ptr<DataPipeImpl> impl_;
DISALLOW_COPY_AND_ASSIGN(DataPipe);
};
diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc
index 21127c6..65ec8ef 100644
--- a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc
+++ b/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.cc
@@ -126,6 +126,27 @@ void DataPipeConsumerDispatcher::RemoveAwakableImplNoLock(
data_pipe_->ConsumerRemoveAwakable(awakable, signals_state);
}
+void DataPipeConsumerDispatcher::StartSerializeImplNoLock(
+ Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) {
+ DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
+ data_pipe_->ConsumerStartSerialize(channel, max_size, max_platform_handles);
+}
+
+bool DataPipeConsumerDispatcher::EndSerializeAndCloseImplNoLock(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) {
+ DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
+
+ bool rv = data_pipe_->ConsumerEndSerialize(channel, destination, actual_size,
+ platform_handles);
+ data_pipe_ = nullptr;
+ return rv;
+}
+
bool DataPipeConsumerDispatcher::IsBusyNoLock() const {
lock().AssertAcquired();
return data_pipe_->ConsumerIsBusy();
diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h b/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h
index 10a3d94..34b3f4a 100644
--- a/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h
+++ b/third_party/mojo/src/mojo/edk/system/data_pipe_consumer_dispatcher.h
@@ -50,6 +50,14 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher : public Dispatcher {
HandleSignalsState* signals_state) override;
void RemoveAwakableImplNoLock(Awakable* awakable,
HandleSignalsState* signals_state) override;
+ void StartSerializeImplNoLock(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) override;
+ bool EndSerializeAndCloseImplNoLock(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) override;
bool IsBusyNoLock() const override;
// Protected by |lock()|:
diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_impl.h b/third_party/mojo/src/mojo/edk/system/data_pipe_impl.h
new file mode 100644
index 0000000..e1339c0
--- /dev/null
+++ b/third_party/mojo/src/mojo/edk/system/data_pipe_impl.h
@@ -0,0 +1,122 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EDK_SYSTEM_DATA_PIPE_IMPL_H_
+#define MOJO_EDK_SYSTEM_DATA_PIPE_IMPL_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "mojo/edk/embedder/platform_handle_vector.h"
+#include "mojo/edk/system/data_pipe.h"
+#include "mojo/edk/system/handle_signals_state.h"
+#include "mojo/edk/system/memory.h"
+#include "mojo/edk/system/system_impl_export.h"
+#include "mojo/public/c/system/types.h"
+
+namespace mojo {
+namespace system {
+
+class Channel;
+
+// Base class/interface for classes that "implement" |DataPipe| for various
+// situations (local versus remote). The methods, other than the constructor,
+// |set_owner()|, and the destructor, are always protected by |DataPipe|'s
+// |lock_|.
+class MOJO_SYSTEM_IMPL_EXPORT DataPipeImpl {
+ public:
+ virtual ~DataPipeImpl() {}
+
+ // This is only called by |DataPipe| during its construction.
+ void set_owner(DataPipe* owner) { owner_ = owner; }
+
+ virtual void ProducerClose() = 0;
+ // |num_bytes.Get()| will be a nonzero multiple of |element_num_bytes()|.
+ virtual MojoResult ProducerWriteData(UserPointer<const void> elements,
+ UserPointer<uint32_t> num_bytes,
+ uint32_t max_num_bytes_to_write,
+ uint32_t min_num_bytes_to_write) = 0;
+ virtual MojoResult ProducerBeginWriteData(
+ UserPointer<void*> buffer,
+ UserPointer<uint32_t> buffer_num_bytes,
+ uint32_t min_num_bytes_to_write) = 0;
+ virtual MojoResult ProducerEndWriteData(uint32_t num_bytes_written) = 0;
+ // Note: A producer should not be writable during a two-phase write.
+ virtual HandleSignalsState ProducerGetHandleSignalsState() const = 0;
+ virtual void ProducerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) = 0;
+ virtual bool ProducerEndSerialize(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) = 0;
+
+ virtual void ConsumerClose() = 0;
+ // |num_bytes.Get()| will be a nonzero multiple of |element_num_bytes()|.
+ virtual MojoResult ConsumerReadData(UserPointer<void> elements,
+ UserPointer<uint32_t> num_bytes,
+ uint32_t max_num_bytes_to_read,
+ uint32_t min_num_bytes_to_read,
+ bool peek) = 0;
+ virtual MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes,
+ uint32_t max_num_bytes_to_discard,
+ uint32_t min_num_bytes_to_discard) = 0;
+ // |num_bytes.Get()| will be a nonzero multiple of |element_num_bytes()|.
+ virtual MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes) = 0;
+ virtual MojoResult ConsumerBeginReadData(
+ UserPointer<const void*> buffer,
+ UserPointer<uint32_t> buffer_num_bytes,
+ uint32_t min_num_bytes_to_read) = 0;
+ virtual MojoResult ConsumerEndReadData(uint32_t num_bytes_read) = 0;
+ // Note: A consumer should not be writable during a two-phase read.
+ virtual HandleSignalsState ConsumerGetHandleSignalsState() const = 0;
+ virtual void ConsumerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) = 0;
+ virtual bool ConsumerEndSerialize(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) = 0;
+
+ protected:
+ DataPipeImpl() : owner_() {}
+
+ DataPipe* owner() const { return owner_; }
+
+ bool may_discard() const { return owner_->may_discard(); }
+ size_t element_num_bytes() const { return owner_->element_num_bytes(); }
+ size_t capacity_num_bytes() const { return owner_->capacity_num_bytes(); }
+ bool producer_open() const { return owner_->producer_open_no_lock(); }
+ bool consumer_open() const { return owner_->consumer_open_no_lock(); }
+ uint32_t producer_two_phase_max_num_bytes_written() const {
+ return owner_->producer_two_phase_max_num_bytes_written_no_lock();
+ }
+ uint32_t consumer_two_phase_max_num_bytes_read() const {
+ return owner_->consumer_two_phase_max_num_bytes_read_no_lock();
+ }
+ void set_producer_two_phase_max_num_bytes_written(uint32_t num_bytes) {
+ owner_->set_producer_two_phase_max_num_bytes_written_no_lock(num_bytes);
+ }
+ void set_consumer_two_phase_max_num_bytes_read(uint32_t num_bytes) {
+ owner_->set_consumer_two_phase_max_num_bytes_read_no_lock(num_bytes);
+ }
+ bool producer_in_two_phase_write() const {
+ return owner_->producer_in_two_phase_write_no_lock();
+ }
+ bool consumer_in_two_phase_read() const {
+ return owner_->consumer_in_two_phase_read_no_lock();
+ }
+
+ private:
+ DataPipe* owner_;
+
+ DISALLOW_COPY_AND_ASSIGN(DataPipeImpl);
+};
+
+} // namespace system
+} // namespace mojo
+
+#endif // MOJO_EDK_SYSTEM_DATA_PIPE_IMPL_H_
diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc b/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc
index 0531126..f5c8b82 100644
--- a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc
+++ b/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.cc
@@ -99,6 +99,27 @@ void DataPipeProducerDispatcher::RemoveAwakableImplNoLock(
data_pipe_->ProducerRemoveAwakable(awakable, signals_state);
}
+void DataPipeProducerDispatcher::StartSerializeImplNoLock(
+ Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) {
+ DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
+ data_pipe_->ProducerStartSerialize(channel, max_size, max_platform_handles);
+}
+
+bool DataPipeProducerDispatcher::EndSerializeAndCloseImplNoLock(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) {
+ DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
+
+ bool rv = data_pipe_->ProducerEndSerialize(channel, destination, actual_size,
+ platform_handles);
+ data_pipe_ = nullptr;
+ return rv;
+}
+
bool DataPipeProducerDispatcher::IsBusyNoLock() const {
lock().AssertAcquired();
return data_pipe_->ProducerIsBusy();
diff --git a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h b/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h
index 39c070c..e3a00d2 100644
--- a/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h
+++ b/third_party/mojo/src/mojo/edk/system/data_pipe_producer_dispatcher.h
@@ -50,6 +50,14 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher : public Dispatcher {
HandleSignalsState* signals_state) override;
void RemoveAwakableImplNoLock(Awakable* awakable,
HandleSignalsState* signals_state) override;
+ void StartSerializeImplNoLock(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) override;
+ bool EndSerializeAndCloseImplNoLock(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) override;
bool IsBusyNoLock() const override;
// Protected by |lock()|:
diff --git a/third_party/mojo/src/mojo/edk/system/dispatcher.h b/third_party/mojo/src/mojo/edk/system/dispatcher.h
index c069269..4bbc5ed 100644
--- a/third_party/mojo/src/mojo/edk/system/dispatcher.h
+++ b/third_party/mojo/src/mojo/edk/system/dispatcher.h
@@ -297,6 +297,11 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
size_t* actual_size,
embedder::PlatformHandleVector* platform_handles);
+ // This should be overridden to return true if/when there's an ongoing
+ // operation (e.g., two-phase read/writes on data pipes) that should prevent a
+ // handle from being sent over a message pipe (with status "busy").
+ virtual bool IsBusyNoLock() const;
+
// Available to subclasses. (Note: Returns a non-const reference, just like
// |base::AutoLock|'s constructor takes a non-const reference.)
base::Lock& lock() const { return lock_; }
@@ -304,11 +309,6 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
private:
friend class DispatcherTransport;
- // This should be overridden to return true if/when there's an ongoing
- // operation (e.g., two-phase read/writes on data pipes) that should prevent a
- // handle from being sent over a message pipe (with status "busy").
- virtual bool IsBusyNoLock() const;
-
// Closes the dispatcher. This must be done under lock, and unlike |Close()|,
// the dispatcher must not be closed already. (This is the "equivalent" of
// |CreateEquivalentDispatcherAndCloseNoLock()|, for situations where the
diff --git a/third_party/mojo/src/mojo/edk/system/local_data_pipe.h b/third_party/mojo/src/mojo/edk/system/local_data_pipe.h
deleted file mode 100644
index abe3a46..0000000
--- a/third_party/mojo/src/mojo/edk/system/local_data_pipe.h
+++ /dev/null
@@ -1,89 +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_SYSTEM_LOCAL_DATA_PIPE_H_
-#define MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_H_
-
-#include "base/macros.h"
-#include "base/memory/aligned_memory.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "mojo/edk/system/data_pipe.h"
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace system {
-
-// |LocalDataPipe| is a subclass that "implements" |DataPipe| for data pipes
-// whose producer and consumer are both local. This class is thread-safe (with
-// protection provided by |DataPipe|'s |lock_|.
-class MOJO_SYSTEM_IMPL_EXPORT LocalDataPipe : public DataPipe {
- public:
- // |validated_options| should be the output of |DataPipe::ValidateOptions()|.
- // In particular: |struct_size| is ignored (so |validated_options| must be the
- // current version of the struct) and |capacity_num_bytes| must be nonzero.
- explicit LocalDataPipe(const MojoCreateDataPipeOptions& validated_options);
-
- private:
- friend class base::RefCountedThreadSafe<LocalDataPipe>;
- ~LocalDataPipe() override;
-
- // |DataPipe| implementation:
- void ProducerCloseImplNoLock() override;
- MojoResult ProducerWriteDataImplNoLock(
- UserPointer<const void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_write,
- uint32_t min_num_bytes_to_write) override;
- MojoResult ProducerBeginWriteDataImplNoLock(
- UserPointer<void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_write) override;
- MojoResult ProducerEndWriteDataImplNoLock(
- uint32_t num_bytes_written) override;
- HandleSignalsState ProducerGetHandleSignalsStateImplNoLock() const override;
- void ConsumerCloseImplNoLock() override;
- MojoResult ConsumerReadDataImplNoLock(UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_read,
- uint32_t min_num_bytes_to_read,
- bool peek) override;
- MojoResult ConsumerDiscardDataImplNoLock(
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_discard,
- uint32_t min_num_bytes_to_discard) override;
- MojoResult ConsumerQueryDataImplNoLock(
- UserPointer<uint32_t> num_bytes) override;
- MojoResult ConsumerBeginReadDataImplNoLock(
- UserPointer<const void*> buffer,
- UserPointer<uint32_t> buffer_num_bytes,
- uint32_t min_num_bytes_to_read) override;
- MojoResult ConsumerEndReadDataImplNoLock(uint32_t num_bytes_read) override;
- HandleSignalsState ConsumerGetHandleSignalsStateImplNoLock() const override;
-
- void EnsureBufferNoLock();
- void DestroyBufferNoLock();
-
- // Get the maximum (single) write/read size right now (in number of elements);
- // result fits in a |uint32_t|.
- size_t GetMaxNumBytesToWriteNoLock();
- size_t GetMaxNumBytesToReadNoLock();
-
- // Marks the given number of bytes as consumed/discarded. |num_bytes| must be
- // greater than |current_num_bytes_|.
- void MarkDataAsConsumedNoLock(size_t num_bytes);
-
- // The members below are protected by |DataPipe|'s |lock_|:
- scoped_ptr<char, base::AlignedFreeDeleter> buffer_;
- // Circular buffer.
- size_t start_index_;
- size_t current_num_bytes_;
-
- DISALLOW_COPY_AND_ASSIGN(LocalDataPipe);
-};
-
-} // namespace system
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_H_
diff --git a/third_party/mojo/src/mojo/edk/system/local_data_pipe.cc b/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.cc
index 8b9f673..3ca76d3 100644
--- a/third_party/mojo/src/mojo/edk/system/local_data_pipe.cc
+++ b/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.cc
@@ -8,7 +8,7 @@
// saved by the limit on capacity -- the maximum size of the buffer, checked in
// |DataPipe::ValidateOptions()|, is currently sufficiently small.)
-#include "mojo/edk/system/local_data_pipe.h"
+#include "mojo/edk/system/local_data_pipe_impl.h"
#include <string.h>
@@ -16,33 +16,34 @@
#include "base/logging.h"
#include "mojo/edk/system/configuration.h"
+#include "mojo/edk/system/data_pipe.h"
namespace mojo {
namespace system {
-LocalDataPipe::LocalDataPipe(const MojoCreateDataPipeOptions& options)
- : DataPipe(true, true, options), start_index_(0), current_num_bytes_(0) {
+LocalDataPipeImpl::LocalDataPipeImpl()
+ : start_index_(0), current_num_bytes_(0) {
// Note: |buffer_| is lazily allocated, since a common case will be that one
// of the handles is immediately passed off to another process.
}
-LocalDataPipe::~LocalDataPipe() {
+LocalDataPipeImpl::~LocalDataPipeImpl() {
}
-void LocalDataPipe::ProducerCloseImplNoLock() {
+void LocalDataPipeImpl::ProducerClose() {
// If the consumer is still open and we still have data, we have to keep the
// buffer around. Currently, we won't free it even if it empties later. (We
// could do this -- requiring a check on every read -- but that seems to be
// optimizing for the uncommon case.)
- if (!consumer_open_no_lock() || !current_num_bytes_) {
+ if (!consumer_open() || !current_num_bytes_) {
// Note: There can only be a two-phase *read* (by the consumer) if we still
// have data.
- DCHECK(!consumer_in_two_phase_read_no_lock());
- DestroyBufferNoLock();
+ DCHECK(!consumer_in_two_phase_read());
+ DestroyBuffer();
}
}
-MojoResult LocalDataPipe::ProducerWriteDataImplNoLock(
+MojoResult LocalDataPipeImpl::ProducerWriteData(
UserPointer<const void> elements,
UserPointer<uint32_t> num_bytes,
uint32_t max_num_bytes_to_write,
@@ -50,7 +51,7 @@ MojoResult LocalDataPipe::ProducerWriteDataImplNoLock(
DCHECK_EQ(max_num_bytes_to_write % element_num_bytes(), 0u);
DCHECK_EQ(min_num_bytes_to_write % element_num_bytes(), 0u);
DCHECK_GT(max_num_bytes_to_write, 0u);
- DCHECK(consumer_open_no_lock());
+ DCHECK(consumer_open());
size_t num_bytes_to_write = 0;
if (may_discard()) {
@@ -61,8 +62,8 @@ MojoResult LocalDataPipe::ProducerWriteDataImplNoLock(
capacity_num_bytes());
if (num_bytes_to_write > capacity_num_bytes() - current_num_bytes_) {
// Discard as much as needed (discard oldest first).
- MarkDataAsConsumedNoLock(num_bytes_to_write -
- (capacity_num_bytes() - current_num_bytes_));
+ MarkDataAsConsumed(num_bytes_to_write -
+ (capacity_num_bytes() - current_num_bytes_));
// No need to wake up write waiters, since we're definitely going to leave
// the buffer full.
}
@@ -81,11 +82,11 @@ MojoResult LocalDataPipe::ProducerWriteDataImplNoLock(
// The amount we can write in our first |memcpy()|.
size_t num_bytes_to_write_first =
- std::min(num_bytes_to_write, GetMaxNumBytesToWriteNoLock());
+ std::min(num_bytes_to_write, GetMaxNumBytesToWrite());
// Do the first (and possibly only) |memcpy()|.
size_t first_write_index =
(start_index_ + current_num_bytes_) % capacity_num_bytes();
- EnsureBufferNoLock();
+ EnsureBuffer();
elements.GetArray(buffer_.get() + first_write_index,
num_bytes_to_write_first);
@@ -101,17 +102,17 @@ MojoResult LocalDataPipe::ProducerWriteDataImplNoLock(
return MOJO_RESULT_OK;
}
-MojoResult LocalDataPipe::ProducerBeginWriteDataImplNoLock(
+MojoResult LocalDataPipeImpl::ProducerBeginWriteData(
UserPointer<void*> buffer,
UserPointer<uint32_t> buffer_num_bytes,
uint32_t min_num_bytes_to_write) {
- DCHECK(consumer_open_no_lock());
+ DCHECK(consumer_open());
// The index we need to start writing at.
size_t write_index =
(start_index_ + current_num_bytes_) % capacity_num_bytes();
- size_t max_num_bytes_to_write = GetMaxNumBytesToWriteNoLock();
+ size_t max_num_bytes_to_write = GetMaxNumBytesToWrite();
if (min_num_bytes_to_write > max_num_bytes_to_write) {
// In "may discard" mode, we can always write from the write index to the
// end of the buffer.
@@ -121,7 +122,7 @@ MojoResult LocalDataPipe::ProducerBeginWriteDataImplNoLock(
// We should only reach here if the start index is after the write index!
DCHECK_GE(start_index_, write_index);
DCHECK_GT(min_num_bytes_to_write - max_num_bytes_to_write, 0u);
- MarkDataAsConsumedNoLock(min_num_bytes_to_write - max_num_bytes_to_write);
+ MarkDataAsConsumed(min_num_bytes_to_write - max_num_bytes_to_write);
max_num_bytes_to_write = min_num_bytes_to_write;
} else {
// Don't return "should wait" since you can't wait for a specified amount
@@ -134,30 +135,27 @@ MojoResult LocalDataPipe::ProducerBeginWriteDataImplNoLock(
if (max_num_bytes_to_write == 0)
return MOJO_RESULT_SHOULD_WAIT;
- EnsureBufferNoLock();
+ EnsureBuffer();
buffer.Put(buffer_.get() + write_index);
buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_write));
- set_producer_two_phase_max_num_bytes_written_no_lock(
+ set_producer_two_phase_max_num_bytes_written(
static_cast<uint32_t>(max_num_bytes_to_write));
return MOJO_RESULT_OK;
}
-MojoResult LocalDataPipe::ProducerEndWriteDataImplNoLock(
- uint32_t num_bytes_written) {
- DCHECK_LE(num_bytes_written,
- producer_two_phase_max_num_bytes_written_no_lock());
+MojoResult LocalDataPipeImpl::ProducerEndWriteData(uint32_t num_bytes_written) {
+ DCHECK_LE(num_bytes_written, producer_two_phase_max_num_bytes_written());
current_num_bytes_ += num_bytes_written;
DCHECK_LE(current_num_bytes_, capacity_num_bytes());
- set_producer_two_phase_max_num_bytes_written_no_lock(0);
+ set_producer_two_phase_max_num_bytes_written(0);
return MOJO_RESULT_OK;
}
-HandleSignalsState LocalDataPipe::ProducerGetHandleSignalsStateImplNoLock()
- const {
+HandleSignalsState LocalDataPipeImpl::ProducerGetHandleSignalsState() const {
HandleSignalsState rv;
- if (consumer_open_no_lock()) {
+ if (consumer_open()) {
if ((may_discard() || current_num_bytes_ < capacity_num_bytes()) &&
- !producer_in_two_phase_write_no_lock())
+ !producer_in_two_phase_write())
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
} else {
@@ -167,21 +165,38 @@ HandleSignalsState LocalDataPipe::ProducerGetHandleSignalsStateImplNoLock()
return rv;
}
-void LocalDataPipe::ConsumerCloseImplNoLock() {
+void LocalDataPipeImpl::ProducerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) {
+ // TODO(vtl): Support serializing producer data pipe handles.
+ *max_size = 0;
+ *max_platform_handles = 0;
+}
+
+bool LocalDataPipeImpl::ProducerEndSerialize(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) {
+ // TODO(vtl): Support serializing producer data pipe handles.
+ owner()->ProducerCloseNoLock();
+ return false;
+}
+
+void LocalDataPipeImpl::ConsumerClose() {
// If the producer is around and in a two-phase write, we have to keep the
// buffer around. (We then don't free it until the producer is closed. This
// could be rectified, but again seems like optimizing for the uncommon case.)
- if (!producer_open_no_lock() || !producer_in_two_phase_write_no_lock())
- DestroyBufferNoLock();
+ if (!producer_open() || !producer_in_two_phase_write())
+ DestroyBuffer();
current_num_bytes_ = 0;
}
-MojoResult LocalDataPipe::ConsumerReadDataImplNoLock(
- UserPointer<void> elements,
- UserPointer<uint32_t> num_bytes,
- uint32_t max_num_bytes_to_read,
- uint32_t min_num_bytes_to_read,
- bool peek) {
+MojoResult LocalDataPipeImpl::ConsumerReadData(UserPointer<void> elements,
+ UserPointer<uint32_t> num_bytes,
+ uint32_t max_num_bytes_to_read,
+ uint32_t min_num_bytes_to_read,
+ bool peek) {
DCHECK_EQ(max_num_bytes_to_read % element_num_bytes(), 0u);
DCHECK_EQ(min_num_bytes_to_read % element_num_bytes(), 0u);
DCHECK_GT(max_num_bytes_to_read, 0u);
@@ -189,20 +204,20 @@ MojoResult LocalDataPipe::ConsumerReadDataImplNoLock(
if (min_num_bytes_to_read > current_num_bytes_) {
// Don't return "should wait" since you can't wait for a specified amount of
// data.
- return producer_open_no_lock() ? MOJO_RESULT_OUT_OF_RANGE
- : MOJO_RESULT_FAILED_PRECONDITION;
+ return producer_open() ? MOJO_RESULT_OUT_OF_RANGE
+ : MOJO_RESULT_FAILED_PRECONDITION;
}
size_t num_bytes_to_read =
std::min(static_cast<size_t>(max_num_bytes_to_read), current_num_bytes_);
if (num_bytes_to_read == 0) {
- return producer_open_no_lock() ? MOJO_RESULT_SHOULD_WAIT
- : MOJO_RESULT_FAILED_PRECONDITION;
+ return producer_open() ? MOJO_RESULT_SHOULD_WAIT
+ : MOJO_RESULT_FAILED_PRECONDITION;
}
// The amount we can read in our first |memcpy()|.
size_t num_bytes_to_read_first =
- std::min(num_bytes_to_read, GetMaxNumBytesToReadNoLock());
+ std::min(num_bytes_to_read, GetMaxNumBytesToRead());
elements.PutArray(buffer_.get() + start_index_, num_bytes_to_read_first);
if (num_bytes_to_read_first < num_bytes_to_read) {
@@ -212,12 +227,12 @@ MojoResult LocalDataPipe::ConsumerReadDataImplNoLock(
}
if (!peek)
- MarkDataAsConsumedNoLock(num_bytes_to_read);
+ MarkDataAsConsumed(num_bytes_to_read);
num_bytes.Put(static_cast<uint32_t>(num_bytes_to_read));
return MOJO_RESULT_OK;
}
-MojoResult LocalDataPipe::ConsumerDiscardDataImplNoLock(
+MojoResult LocalDataPipeImpl::ConsumerDiscardData(
UserPointer<uint32_t> num_bytes,
uint32_t max_num_bytes_to_discard,
uint32_t min_num_bytes_to_discard) {
@@ -228,82 +243,98 @@ MojoResult LocalDataPipe::ConsumerDiscardDataImplNoLock(
if (min_num_bytes_to_discard > current_num_bytes_) {
// Don't return "should wait" since you can't wait for a specified amount of
// data.
- return producer_open_no_lock() ? MOJO_RESULT_OUT_OF_RANGE
- : MOJO_RESULT_FAILED_PRECONDITION;
+ return producer_open() ? MOJO_RESULT_OUT_OF_RANGE
+ : MOJO_RESULT_FAILED_PRECONDITION;
}
// Be consistent with other operations; error if no data available.
if (current_num_bytes_ == 0) {
- return producer_open_no_lock() ? MOJO_RESULT_SHOULD_WAIT
- : MOJO_RESULT_FAILED_PRECONDITION;
+ return producer_open() ? MOJO_RESULT_SHOULD_WAIT
+ : MOJO_RESULT_FAILED_PRECONDITION;
}
size_t num_bytes_to_discard = std::min(
static_cast<size_t>(max_num_bytes_to_discard), current_num_bytes_);
- MarkDataAsConsumedNoLock(num_bytes_to_discard);
+ MarkDataAsConsumed(num_bytes_to_discard);
num_bytes.Put(static_cast<uint32_t>(num_bytes_to_discard));
return MOJO_RESULT_OK;
}
-MojoResult LocalDataPipe::ConsumerQueryDataImplNoLock(
+MojoResult LocalDataPipeImpl::ConsumerQueryData(
UserPointer<uint32_t> num_bytes) {
// Note: This cast is safe, since the capacity fits into a |uint32_t|.
num_bytes.Put(static_cast<uint32_t>(current_num_bytes_));
return MOJO_RESULT_OK;
}
-MojoResult LocalDataPipe::ConsumerBeginReadDataImplNoLock(
+MojoResult LocalDataPipeImpl::ConsumerBeginReadData(
UserPointer<const void*> buffer,
UserPointer<uint32_t> buffer_num_bytes,
uint32_t min_num_bytes_to_read) {
- size_t max_num_bytes_to_read = GetMaxNumBytesToReadNoLock();
+ size_t max_num_bytes_to_read = GetMaxNumBytesToRead();
if (min_num_bytes_to_read > max_num_bytes_to_read) {
// Don't return "should wait" since you can't wait for a specified amount of
// data.
- return producer_open_no_lock() ? MOJO_RESULT_OUT_OF_RANGE
- : MOJO_RESULT_FAILED_PRECONDITION;
+ return producer_open() ? MOJO_RESULT_OUT_OF_RANGE
+ : MOJO_RESULT_FAILED_PRECONDITION;
}
// Don't go into a two-phase read if there's no data.
if (max_num_bytes_to_read == 0) {
- return producer_open_no_lock() ? MOJO_RESULT_SHOULD_WAIT
- : MOJO_RESULT_FAILED_PRECONDITION;
+ return producer_open() ? MOJO_RESULT_SHOULD_WAIT
+ : MOJO_RESULT_FAILED_PRECONDITION;
}
buffer.Put(buffer_.get() + start_index_);
buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_read));
- set_consumer_two_phase_max_num_bytes_read_no_lock(
+ set_consumer_two_phase_max_num_bytes_read(
static_cast<uint32_t>(max_num_bytes_to_read));
return MOJO_RESULT_OK;
}
-MojoResult LocalDataPipe::ConsumerEndReadDataImplNoLock(
- uint32_t num_bytes_read) {
- DCHECK_LE(num_bytes_read, consumer_two_phase_max_num_bytes_read_no_lock());
+MojoResult LocalDataPipeImpl::ConsumerEndReadData(uint32_t num_bytes_read) {
+ DCHECK_LE(num_bytes_read, consumer_two_phase_max_num_bytes_read());
DCHECK_LE(start_index_ + num_bytes_read, capacity_num_bytes());
- MarkDataAsConsumedNoLock(num_bytes_read);
- set_consumer_two_phase_max_num_bytes_read_no_lock(0);
+ MarkDataAsConsumed(num_bytes_read);
+ set_consumer_two_phase_max_num_bytes_read(0);
return MOJO_RESULT_OK;
}
-HandleSignalsState LocalDataPipe::ConsumerGetHandleSignalsStateImplNoLock()
- const {
+HandleSignalsState LocalDataPipeImpl::ConsumerGetHandleSignalsState() const {
HandleSignalsState rv;
if (current_num_bytes_ > 0) {
- if (!consumer_in_two_phase_read_no_lock())
+ if (!consumer_in_two_phase_read())
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE;
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE;
- } else if (producer_open_no_lock()) {
+ } else if (producer_open()) {
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE;
}
- if (!producer_open_no_lock())
+ if (!producer_open())
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
return rv;
}
-void LocalDataPipe::EnsureBufferNoLock() {
- DCHECK(producer_open_no_lock());
+void LocalDataPipeImpl::ConsumerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) {
+ // TODO(vtl): Support serializing consumer data pipe handles.
+ *max_size = 0;
+ *max_platform_handles = 0;
+}
+
+bool LocalDataPipeImpl::ConsumerEndSerialize(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) {
+ // TODO(vtl): Support serializing consumer data pipe handles.
+ owner()->ConsumerCloseNoLock();
+ return false;
+}
+
+void LocalDataPipeImpl::EnsureBuffer() {
+ DCHECK(producer_open());
if (buffer_)
return;
buffer_.reset(static_cast<char*>(
@@ -311,7 +342,7 @@ void LocalDataPipe::EnsureBufferNoLock() {
GetConfiguration().data_pipe_buffer_alignment_bytes)));
}
-void LocalDataPipe::DestroyBufferNoLock() {
+void LocalDataPipeImpl::DestroyBuffer() {
#ifndef NDEBUG
// Scribble on the buffer to help detect use-after-frees. (This also helps the
// unit test detect certain bugs without needing ASAN or similar.)
@@ -321,7 +352,7 @@ void LocalDataPipe::DestroyBufferNoLock() {
buffer_.reset();
}
-size_t LocalDataPipe::GetMaxNumBytesToWriteNoLock() {
+size_t LocalDataPipeImpl::GetMaxNumBytesToWrite() {
size_t next_index = start_index_ + current_num_bytes_;
if (next_index >= capacity_num_bytes()) {
next_index %= capacity_num_bytes();
@@ -333,13 +364,13 @@ size_t LocalDataPipe::GetMaxNumBytesToWriteNoLock() {
return capacity_num_bytes() - next_index;
}
-size_t LocalDataPipe::GetMaxNumBytesToReadNoLock() {
+size_t LocalDataPipeImpl::GetMaxNumBytesToRead() {
if (start_index_ + current_num_bytes_ > capacity_num_bytes())
return capacity_num_bytes() - start_index_;
return current_num_bytes_;
}
-void LocalDataPipe::MarkDataAsConsumedNoLock(size_t num_bytes) {
+void LocalDataPipeImpl::MarkDataAsConsumed(size_t num_bytes) {
DCHECK_LE(num_bytes, current_num_bytes_);
start_index_ += num_bytes;
start_index_ %= capacity_num_bytes();
diff --git a/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h b/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h
new file mode 100644
index 0000000..14defcb
--- /dev/null
+++ b/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl.h
@@ -0,0 +1,94 @@
+// 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_SYSTEM_LOCAL_DATA_PIPE_IMPL_H_
+#define MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_IMPL_H_
+
+#include "base/macros.h"
+#include "base/memory/aligned_memory.h"
+#include "base/memory/scoped_ptr.h"
+#include "mojo/edk/system/data_pipe_impl.h"
+#include "mojo/edk/system/system_impl_export.h"
+
+namespace mojo {
+namespace system {
+
+class DataPipe;
+
+// |LocalDataPipeImpl| is a subclass that "implements" |DataPipe| for data pipes
+// whose producer and consumer are both local. See |DataPipeImpl| for more
+// details.
+class MOJO_SYSTEM_IMPL_EXPORT LocalDataPipeImpl : public DataPipeImpl {
+ public:
+ LocalDataPipeImpl();
+ ~LocalDataPipeImpl() override;
+
+ private:
+ // |DataPipeImpl| implementation:
+ void ProducerClose() override;
+ MojoResult ProducerWriteData(UserPointer<const void> elements,
+ UserPointer<uint32_t> num_bytes,
+ uint32_t max_num_bytes_to_write,
+ uint32_t min_num_bytes_to_write) override;
+ MojoResult ProducerBeginWriteData(UserPointer<void*> buffer,
+ UserPointer<uint32_t> buffer_num_bytes,
+ uint32_t min_num_bytes_to_write) override;
+ MojoResult ProducerEndWriteData(uint32_t num_bytes_written) override;
+ HandleSignalsState ProducerGetHandleSignalsState() const override;
+ void ProducerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) override;
+ bool ProducerEndSerialize(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) override;
+ void ConsumerClose() override;
+ MojoResult ConsumerReadData(UserPointer<void> elements,
+ UserPointer<uint32_t> num_bytes,
+ uint32_t max_num_bytes_to_read,
+ uint32_t min_num_bytes_to_read,
+ bool peek) override;
+ MojoResult ConsumerDiscardData(UserPointer<uint32_t> num_bytes,
+ uint32_t max_num_bytes_to_discard,
+ uint32_t min_num_bytes_to_discard) override;
+ MojoResult ConsumerQueryData(UserPointer<uint32_t> num_bytes) override;
+ MojoResult ConsumerBeginReadData(UserPointer<const void*> buffer,
+ UserPointer<uint32_t> buffer_num_bytes,
+ uint32_t min_num_bytes_to_read) override;
+ MojoResult ConsumerEndReadData(uint32_t num_bytes_read) override;
+ HandleSignalsState ConsumerGetHandleSignalsState() const override;
+ void ConsumerStartSerialize(Channel* channel,
+ size_t* max_size,
+ size_t* max_platform_handles) override;
+ bool ConsumerEndSerialize(
+ Channel* channel,
+ void* destination,
+ size_t* actual_size,
+ embedder::PlatformHandleVector* platform_handles) override;
+
+ void EnsureBuffer();
+ void DestroyBuffer();
+
+ // Get the maximum (single) write/read size right now (in number of elements);
+ // result fits in a |uint32_t|.
+ size_t GetMaxNumBytesToWrite();
+ size_t GetMaxNumBytesToRead();
+
+ // Marks the given number of bytes as consumed/discarded. |num_bytes| must be
+ // greater than |current_num_bytes_|.
+ void MarkDataAsConsumed(size_t num_bytes);
+
+ scoped_ptr<char, base::AlignedFreeDeleter> buffer_;
+ // Circular buffer.
+ size_t start_index_;
+ size_t current_num_bytes_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalDataPipeImpl);
+};
+
+} // namespace system
+} // namespace mojo
+
+#endif // MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_IMPL_H_
diff --git a/third_party/mojo/src/mojo/edk/system/local_data_pipe_unittest.cc b/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl_unittest.cc
index 1223a2ba..3b42e57 100644
--- a/third_party/mojo/src/mojo/edk/system/local_data_pipe_unittest.cc
+++ b/third_party/mojo/src/mojo/edk/system/local_data_pipe_impl_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/local_data_pipe.h"
+#include "mojo/edk/system/local_data_pipe_impl.h"
#include <string.h>
@@ -20,14 +20,14 @@ const uint32_t kSizeOfOptions =
static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions));
// Validate options.
-TEST(LocalDataPipeTest, Creation) {
+TEST(LocalDataPipeImplTest, Creation) {
// Create using default options.
{
// Get default options.
MojoCreateDataPipeOptions default_options = {0};
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
NullUserPointer(), &default_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(default_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(default_options));
dp->ProducerClose();
dp->ConsumerClose();
}
@@ -44,7 +44,7 @@ TEST(LocalDataPipeTest, Creation) {
EXPECT_EQ(MOJO_RESULT_OK,
DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
&validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
dp->ProducerClose();
dp->ConsumerClose();
}
@@ -59,7 +59,7 @@ TEST(LocalDataPipeTest, Creation) {
EXPECT_EQ(MOJO_RESULT_OK,
DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
&validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
dp->ProducerClose();
dp->ConsumerClose();
}
@@ -74,7 +74,7 @@ TEST(LocalDataPipeTest, Creation) {
EXPECT_EQ(MOJO_RESULT_OK,
DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
&validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
dp->ProducerClose();
dp->ConsumerClose();
}
@@ -90,13 +90,13 @@ TEST(LocalDataPipeTest, Creation) {
EXPECT_EQ(MOJO_RESULT_OK,
DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
&validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
dp->ProducerClose();
dp->ConsumerClose();
}
}
-TEST(LocalDataPipeTest, SimpleReadWrite) {
+TEST(LocalDataPipeImplTest, SimpleReadWrite) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
@@ -107,7 +107,7 @@ TEST(LocalDataPipeTest, SimpleReadWrite) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
int32_t elements[10] = {0};
uint32_t num_bytes = 0;
@@ -213,9 +213,9 @@ TEST(LocalDataPipeTest, SimpleReadWrite) {
// Note: The "basic" waiting tests test that the "wait states" are correct in
// various situations; they don't test that waiters are properly awoken on state
// changes. (For that, we need to use multiple threads.)
-TEST(LocalDataPipeTest, BasicProducerWaiting) {
- // Note: We take advantage of the fact that for |LocalDataPipe|, capacities
- // are strict maximums. This is not guaranteed by the API.
+TEST(LocalDataPipeImplTest, BasicProducerWaiting) {
+ // Note: We take advantage of the fact that for |LocalDataPipeImpl|,
+ // capacities are strict maximums. This is not guaranteed by the API.
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
@@ -227,7 +227,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
Waiter waiter;
uint32_t context = 0;
HandleSignalsState hss;
@@ -392,7 +392,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
dp->ProducerClose();
}
-TEST(LocalDataPipeTest, PeerClosedWaiting) {
+TEST(LocalDataPipeImplTest, PeerClosedWaiting) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
@@ -408,7 +408,7 @@ TEST(LocalDataPipeTest, PeerClosedWaiting) {
// Check MOJO_HANDLE_SIGNAL_PEER_CLOSED on producer.
{
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Add a waiter.
waiter.Init();
ASSERT_EQ(MOJO_RESULT_OK,
@@ -432,7 +432,7 @@ TEST(LocalDataPipeTest, PeerClosedWaiting) {
// Check MOJO_HANDLE_SIGNAL_PEER_CLOSED on consumer.
{
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Add a waiter.
waiter.Init();
ASSERT_EQ(MOJO_RESULT_OK,
@@ -455,7 +455,7 @@ TEST(LocalDataPipeTest, PeerClosedWaiting) {
}
}
-TEST(LocalDataPipeTest, BasicConsumerWaiting) {
+TEST(LocalDataPipeImplTest, BasicConsumerWaiting) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
@@ -467,7 +467,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
MakeUserPointer(&options), &validated_options));
{
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
Waiter waiter;
uint32_t context = 0;
HandleSignalsState hss;
@@ -622,7 +622,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
// Test with two-phase APIs and closing the producer with an active consumer
// waiter.
{
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
Waiter waiter;
uint32_t context = 0;
HandleSignalsState hss;
@@ -713,7 +713,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
}
// Tests that data pipes aren't writable/readable during two-phase writes/reads.
-TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
+TEST(LocalDataPipeImplTest, BasicTwoPhaseWaiting) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
@@ -724,7 +724,7 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
Waiter waiter;
HandleSignalsState hss;
@@ -866,7 +866,7 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
}
// Test that a "may discard" data pipe is writable even when it's full.
-TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
+TEST(LocalDataPipeImplTest, BasicMayDiscardWaiting) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
@@ -877,7 +877,7 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
Waiter waiter;
HandleSignalsState hss;
@@ -998,7 +998,7 @@ void Seq(int32_t start, size_t count, int32_t* out) {
out[i] = start + static_cast<int32_t>(i);
}
-TEST(LocalDataPipeTest, MayDiscard) {
+TEST(LocalDataPipeImplTest, MayDiscard) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
@@ -1009,7 +1009,7 @@ TEST(LocalDataPipeTest, MayDiscard) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
int32_t buffer[100] = {0};
uint32_t num_bytes = 0;
@@ -1191,7 +1191,7 @@ TEST(LocalDataPipeTest, MayDiscard) {
dp->ConsumerClose();
}
-TEST(LocalDataPipeTest, AllOrNone) {
+TEST(LocalDataPipeImplTest, AllOrNone) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
@@ -1202,7 +1202,7 @@ TEST(LocalDataPipeTest, AllOrNone) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Try writing way too much.
uint32_t num_bytes = 20u * sizeof(int32_t);
@@ -1351,7 +1351,7 @@ TEST(LocalDataPipeTest, AllOrNone) {
dp->ConsumerClose();
}
-TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
+TEST(LocalDataPipeImplTest, AllOrNoneMayDiscard) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
@@ -1362,7 +1362,7 @@ TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Try writing way too much.
uint32_t num_bytes = 20u * sizeof(int32_t);
@@ -1444,13 +1444,13 @@ TEST(LocalDataPipeTest, AllOrNoneMayDiscard) {
EXPECT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer)));
// Note: All-or-none two-phase writes on a "may discard" data pipe are tested
- // in LocalDataPipeTest.MayDiscard.
+ // in LocalDataPipeImplTest.MayDiscard.
dp->ProducerClose();
dp->ConsumerClose();
}
-TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
+TEST(LocalDataPipeImplTest, TwoPhaseAllOrNone) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
@@ -1461,7 +1461,7 @@ TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Try writing way too much (two-phase).
uint32_t num_bytes = 20u * sizeof(int32_t);
@@ -1585,7 +1585,7 @@ TEST(LocalDataPipeTest, TwoPhaseAllOrNone) {
// respectively, as much as possible, even if it has to "wrap around" the
// internal circular buffer. (Note that the two-phase write and read do not do
// this.)
-TEST(LocalDataPipeTest, WrapAround) {
+TEST(LocalDataPipeImplTest, WrapAround) {
unsigned char test_data[1000];
for (size_t i = 0; i < arraysize(test_data); i++)
test_data[i] = static_cast<unsigned char>(i);
@@ -1603,7 +1603,7 @@ TEST(LocalDataPipeTest, WrapAround) {
// pipe more space.
ASSERT_EQ(100u, validated_options.capacity_num_bytes);
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Write 20 bytes.
uint32_t num_bytes = 20u;
@@ -1670,7 +1670,7 @@ TEST(LocalDataPipeTest, WrapAround) {
// Tests the behavior of closing the producer or consumer with respect to
// writes and reads (simple and two-phase).
-TEST(LocalDataPipeTest, CloseWriteRead) {
+TEST(LocalDataPipeImplTest, CloseWriteRead) {
const char kTestData[] = "hello world";
const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData));
@@ -1686,7 +1686,7 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
// Close producer first, then consumer.
{
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Write some data, so we'll have something to read.
uint32_t num_bytes = kTestDataSize;
@@ -1742,7 +1742,7 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
// Close consumer first, then producer.
{
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Write some data, so we'll have something to read.
uint32_t num_bytes = kTestDataSize;
@@ -1798,7 +1798,7 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
// Test closing the consumer first, then the producer, with an active
// two-phase write.
{
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Start two-phase write.
void* write_buffer_ptr = nullptr;
@@ -1815,7 +1815,7 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
// Test closing the producer and then trying to read (with no data).
{
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Write some data, so we'll have something to read.
uint32_t num_bytes = kTestDataSize;
@@ -1867,7 +1867,7 @@ TEST(LocalDataPipeTest, CloseWriteRead) {
}
}
-TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
+TEST(LocalDataPipeImplTest, TwoPhaseMoreInvalidArguments) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
@@ -1878,7 +1878,7 @@ TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// No data.
uint32_t num_bytes = 1000u;
@@ -1993,7 +1993,7 @@ TEST(LocalDataPipeTest, TwoPhaseMoreInvalidArguments) {
// |ConsumerBeginReadData()| isn't discardable until |ConsumerEndReadData()|,
// and thus we erroneously allow |ProducerWriteData()| to succeed. Second, the
// |ProducerWriteData()| then changes the data underneath the two-phase read.)
-TEST(LocalDataPipeTest, DISABLED_MayDiscardTwoPhaseConsistent) {
+TEST(LocalDataPipeImplTest, DISABLED_MayDiscardTwoPhaseConsistent) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD, // |flags|.
@@ -2004,7 +2004,7 @@ TEST(LocalDataPipeTest, DISABLED_MayDiscardTwoPhaseConsistent) {
EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
MakeUserPointer(&options), &validated_options));
- scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ scoped_refptr<DataPipe> dp(DataPipe::CreateLocal(validated_options));
// Write some elements.
char elements[2] = {'a', 'b'};
diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
index b401bcd..e98908d 100644
--- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
+++ b/third_party/mojo/src/mojo/edk/system/master_connection_manager.cc
@@ -37,12 +37,12 @@ class MasterConnectionManager::Helper : public RawChannel::Delegate {
public:
Helper(MasterConnectionManager* owner,
ProcessIdentifier process_identifier,
- scoped_ptr<embedder::SlaveInfo> slave_info,
+ embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle);
~Helper() override;
void Init();
- scoped_ptr<embedder::SlaveInfo> Shutdown();
+ embedder::SlaveInfo Shutdown();
private:
// |RawChannel::Delegate| methods:
@@ -58,7 +58,7 @@ class MasterConnectionManager::Helper : public RawChannel::Delegate {
MasterConnectionManager* const owner_;
const ProcessIdentifier process_identifier_;
- scoped_ptr<embedder::SlaveInfo> slave_info_;
+ embedder::SlaveInfo const slave_info_;
scoped_ptr<RawChannel> raw_channel_;
DISALLOW_COPY_AND_ASSIGN(Helper);
@@ -67,26 +67,26 @@ class MasterConnectionManager::Helper : public RawChannel::Delegate {
MasterConnectionManager::Helper::Helper(
MasterConnectionManager* owner,
ProcessIdentifier process_identifier,
- scoped_ptr<embedder::SlaveInfo> slave_info,
+ embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle)
: owner_(owner),
process_identifier_(process_identifier),
- slave_info_(slave_info.Pass()),
+ slave_info_(slave_info),
raw_channel_(RawChannel::Create(platform_handle.Pass())) {
}
MasterConnectionManager::Helper::~Helper() {
- DCHECK(!slave_info_);
+ DCHECK(!raw_channel_);
}
void MasterConnectionManager::Helper::Init() {
raw_channel_->Init(this);
}
-scoped_ptr<embedder::SlaveInfo> MasterConnectionManager::Helper::Shutdown() {
+embedder::SlaveInfo MasterConnectionManager::Helper::Shutdown() {
raw_channel_->Shutdown();
raw_channel_.reset();
- return slave_info_.Pass();
+ return slave_info_;
}
void MasterConnectionManager::Helper::OnReadMessage(
@@ -243,30 +243,13 @@ void MasterConnectionManager::Init(
DCHECK(!private_thread_.message_loop());
delegate_thread_task_runner_ = delegate_thread_task_runner;
- AssertOnDelegateThread();
master_process_delegate_ = master_process_delegate;
CHECK(private_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
}
-void MasterConnectionManager::Shutdown() {
- AssertOnDelegateThread();
- DCHECK(master_process_delegate_);
- DCHECK(private_thread_.message_loop());
-
- // The |Stop()| will actually finish all posted tasks.
- private_thread_.message_loop()->PostTask(
- FROM_HERE, base::Bind(&MasterConnectionManager::ShutdownOnPrivateThread,
- base::Unretained(this)));
- private_thread_.Stop();
- DCHECK(helpers_.empty());
- DCHECK(pending_connections_.empty());
- master_process_delegate_ = nullptr;
- delegate_thread_task_runner_ = nullptr;
-}
-
void MasterConnectionManager::AddSlave(
- scoped_ptr<embedder::SlaveInfo> slave_info,
+ embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle) {
// We don't really care if |slave_info| is non-null or not.
DCHECK(platform_handle.is_valid());
@@ -278,11 +261,27 @@ void MasterConnectionManager::AddSlave(
private_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&MasterConnectionManager::AddSlaveOnPrivateThread,
- base::Unretained(this), base::Passed(&slave_info),
+ base::Unretained(this), base::Unretained(slave_info),
base::Passed(&platform_handle), base::Unretained(&event)));
event.Wait();
}
+void MasterConnectionManager::Shutdown() {
+ AssertNotOnPrivateThread();
+ DCHECK(master_process_delegate_);
+ DCHECK(private_thread_.message_loop());
+
+ // The |Stop()| will actually finish all posted tasks.
+ private_thread_.message_loop()->PostTask(
+ FROM_HERE, base::Bind(&MasterConnectionManager::ShutdownOnPrivateThread,
+ base::Unretained(this)));
+ private_thread_.Stop();
+ DCHECK(helpers_.empty());
+ DCHECK(pending_connections_.empty());
+ master_process_delegate_ = nullptr;
+ delegate_thread_task_runner_ = nullptr;
+}
+
bool MasterConnectionManager::AllowConnect(
const ConnectionIdentifier& connection_id) {
AssertNotOnPrivateThread();
@@ -482,16 +481,16 @@ void MasterConnectionManager::ShutdownOnPrivateThread() {
if (!helpers_.empty()) {
DVLOG(1) << "Shutting down with slaves still connected";
for (auto& p : helpers_) {
- scoped_ptr<embedder::SlaveInfo> slave_info = p.second->Shutdown();
+ embedder::SlaveInfo slave_info = p.second->Shutdown();
delete p.second;
- CallOnSlaveDisconnect(slave_info.Pass());
+ CallOnSlaveDisconnect(slave_info);
}
helpers_.clear();
}
}
void MasterConnectionManager::AddSlaveOnPrivateThread(
- scoped_ptr<embedder::SlaveInfo> slave_info,
+ embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle,
base::WaitableEvent* event) {
DCHECK(platform_handle.is_valid());
@@ -502,8 +501,8 @@ void MasterConnectionManager::AddSlaveOnPrivateThread(
ProcessIdentifier process_identifier = next_process_identifier_;
next_process_identifier_++;
- scoped_ptr<Helper> helper(new Helper(
- this, process_identifier, slave_info.Pass(), platform_handle.Pass()));
+ scoped_ptr<Helper> helper(
+ new Helper(this, process_identifier, slave_info, platform_handle.Pass()));
helper->Init();
DCHECK(helpers_.find(process_identifier) == helpers_.end());
@@ -520,7 +519,7 @@ void MasterConnectionManager::OnError(ProcessIdentifier process_identifier) {
auto it = helpers_.find(process_identifier);
DCHECK(it != helpers_.end());
Helper* helper = it->second;
- scoped_ptr<embedder::SlaveInfo> slave_info = helper->Shutdown();
+ embedder::SlaveInfo slave_info = helper->Shutdown();
helpers_.erase(it);
delete helper;
@@ -542,23 +541,17 @@ void MasterConnectionManager::OnError(ProcessIdentifier process_identifier) {
}
}
- CallOnSlaveDisconnect(slave_info.Pass());
+ CallOnSlaveDisconnect(slave_info);
}
void MasterConnectionManager::CallOnSlaveDisconnect(
- scoped_ptr<embedder::SlaveInfo> slave_info) {
+ embedder::SlaveInfo slave_info) {
AssertOnPrivateThread();
DCHECK(master_process_delegate_);
delegate_thread_task_runner_->PostTask(
FROM_HERE, base::Bind(&embedder::MasterProcessDelegate::OnSlaveDisconnect,
base::Unretained(master_process_delegate_),
- base::Passed(&slave_info)));
-}
-
-void MasterConnectionManager::AssertOnDelegateThread() const {
- DCHECK(base::MessageLoop::current());
- DCHECK_EQ(base::MessageLoop::current()->task_runner(),
- delegate_thread_task_runner_);
+ base::Unretained(slave_info)));
}
void MasterConnectionManager::AssertNotOnPrivateThread() const {
diff --git a/third_party/mojo/src/mojo/edk/system/master_connection_manager.h b/third_party/mojo/src/mojo/edk/system/master_connection_manager.h
index 5bdb810..8367723 100644
--- a/third_party/mojo/src/mojo/edk/system/master_connection_manager.h
+++ b/third_party/mojo/src/mojo/edk/system/master_connection_manager.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -25,7 +26,7 @@ namespace mojo {
namespace embedder {
class MasterProcessDelegate;
-class SlaveInfo;
+typedef void* SlaveInfo;
}
namespace system {
@@ -35,10 +36,10 @@ const ProcessIdentifier kMasterProcessIdentifier = 1;
// The |ConnectionManager| implementation for the master process.
//
-// Objects of this class may be created and destroyed on any thread. However,
-// |Init()| and |Shutdown()| must be called on the "delegate thread". Otherwise,
-// its public methods are thread-safe (except that they may not be called from
-// its internal, private thread).
+// This class is thread-safe (except that no public methods may be called from
+// its internal, private thread), with condition that |Init()| be called before
+// anything else and |Shutdown()| be called before destruction (and no other
+// public methods may be called during/after |Shutdown()|).
class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager
: public ConnectionManager {
public:
@@ -54,18 +55,17 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager
void Init(scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
embedder::MasterProcessDelegate* master_process_delegate);
- // No other methods may be called after this is (or while it is being) called.
- void Shutdown();
-
// Adds a slave process and sets up/tracks a connection to that slave (using
- // |platform_handle|). (|slave_info| is used by the caller/implementation of
- // |embedder::MasterProcessDelegate| to track this process; ownership of
- // |slave_info| will be returned to the delegate via |OnSlaveDisconnect()|,
- // which will always be called for each slave, assuming proper shutdown.)
- void AddSlave(scoped_ptr<embedder::SlaveInfo> slave_info,
+ // |platform_handle|). |slave_info| is used by the caller/implementation of
+ // |embedder::MasterProcessDelegate| to track this process. It must remain
+ // alive until the delegate's |OnSlaveDisconnect()| is called with it as the
+ // argument. |OnSlaveDisconnect()| will always be called for each slave,
+ // assuming proper shutdown.)
+ void AddSlave(embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle);
// |ConnectionManager| methods:
+ void Shutdown() override;
bool AllowConnect(const ConnectionIdentifier& connection_id) override;
bool CancelConnect(const ConnectionIdentifier& connection_id) override;
bool Connect(const ConnectionIdentifier& connection_id,
@@ -89,18 +89,13 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager
// These should only be called on |private_thread_|:
void ShutdownOnPrivateThread();
// Signals |*event| on completion.
- void AddSlaveOnPrivateThread(scoped_ptr<embedder::SlaveInfo> slave_info,
+ void AddSlaveOnPrivateThread(embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle,
base::WaitableEvent* event);
// Called by |Helper::OnError()|.
void OnError(ProcessIdentifier process_identifier);
// Posts a call to |master_process_delegate_->OnSlaveDisconnect()|.
- void CallOnSlaveDisconnect(scoped_ptr<embedder::SlaveInfo> slave_info);
-
- // Asserts that the current thread is the delegate thread. (This actually
- // checks the current message loop.)
- // TODO(vtl): Probably we should actually check the thread.
- void AssertOnDelegateThread() const;
+ void CallOnSlaveDisconnect(embedder::SlaveInfo slave_info);
// Asserts that the current thread is *not* |private_thread_| (no-op if
// DCHECKs are not enabled). This should only be called while
diff --git a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc
index de8d17f..5ff8e56 100644
--- a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc
+++ b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.cc
@@ -48,7 +48,6 @@ void SlaveConnectionManager::Init(
DCHECK(!private_thread_.message_loop());
delegate_thread_task_runner_ = delegate_thread_task_runner;
- AssertOnDelegateThread();
slave_process_delegate_ = slave_process_delegate;
CHECK(private_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
@@ -60,7 +59,7 @@ void SlaveConnectionManager::Init(
}
void SlaveConnectionManager::Shutdown() {
- AssertOnDelegateThread();
+ AssertNotOnPrivateThread();
DCHECK(slave_process_delegate_);
DCHECK(private_thread_.message_loop());
@@ -294,12 +293,6 @@ void SlaveConnectionManager::OnError(Error error) {
base::Unretained(slave_process_delegate_)));
}
-void SlaveConnectionManager::AssertOnDelegateThread() const {
- DCHECK(base::MessageLoop::current());
- DCHECK_EQ(base::MessageLoop::current()->task_runner(),
- delegate_thread_task_runner_);
-}
-
void SlaveConnectionManager::AssertNotOnPrivateThread() const {
// This should only be called after |Init()| and before |Shutdown()|. (If not,
// the subsequent |DCHECK_NE()| is invalid, since the current thread may not
diff --git a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h
index 731d9db..c710854 100644
--- a/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h
+++ b/third_party/mojo/src/mojo/edk/system/slave_connection_manager.h
@@ -5,6 +5,7 @@
#ifndef MOJO_EDK_SYSTEM_SLAVE_CONNECTION_MANAGER_H_
#define MOJO_EDK_SYSTEM_SLAVE_CONNECTION_MANAGER_H_
+#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -31,10 +32,10 @@ namespace system {
// The |ConnectionManager| implementation for slave processes.
//
-// Objects of this class may be created and destroyed on any thread. However,
-// |Init()| and |Shutdown()| must be called on the "delegate thread". Otherwise,
-// its public methods are thread-safe (except that they may not be called from
-// its internal, private thread).
+// This class is thread-safe (except that no public methods may be called from
+// its internal, private thread), with condition that |Init()| be called before
+// anything else and |Shutdown()| be called before destruction (and no other
+// public methods may be called during/after |Shutdown()|).
class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager
: public ConnectionManager,
public RawChannel::Delegate {
@@ -52,10 +53,8 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager
embedder::SlaveProcessDelegate* slave_process_delegate,
embedder::ScopedPlatformHandle platform_handle);
- // No other methods may be called after this is (or while it is being) called.
- void Shutdown();
-
// |ConnectionManager| methods:
+ void Shutdown() override;
bool AllowConnect(const ConnectionIdentifier& connection_id) override;
bool CancelConnect(const ConnectionIdentifier& connection_id) override;
bool Connect(const ConnectionIdentifier& connection_id,
@@ -81,11 +80,6 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager
embedder::ScopedPlatformHandleVectorPtr platform_handles) override;
void OnError(Error error) override;
- // Asserts that the current thread is the delegate thread. (This actually
- // checks the current message loop.)
- // TODO(vtl): Probably we should actually check the thread.
- void AssertOnDelegateThread() const;
-
// Asserts that the current thread is *not* |private_thread_| (no-op if
// DCHECKs are not enabled). This should only be called while
// |private_thread_| is alive (i.e., after |Init()| but before |Shutdown()|).
diff --git a/third_party/mojo/src/mojo/edk/system/unique_identifier.cc b/third_party/mojo/src/mojo/edk/system/unique_identifier.cc
index e851e2b..11e482b 100644
--- a/third_party/mojo/src/mojo/edk/system/unique_identifier.cc
+++ b/third_party/mojo/src/mojo/edk/system/unique_identifier.cc
@@ -7,7 +7,7 @@
#include <ostream>
#include "base/strings/string_number_conversions.h"
-#include "crypto/random.h"
+#include "mojo/edk/embedder/platform_support.h"
namespace mojo {
namespace system {
@@ -19,9 +19,10 @@ std::ostream& operator<<(std::ostream& out,
}
// static
-UniqueIdentifier UniqueIdentifier::Generate() {
+UniqueIdentifier UniqueIdentifier::Generate(
+ embedder::PlatformSupport* platform_support) {
UniqueIdentifier rv;
- crypto::RandBytes(rv.data_, sizeof(rv.data_));
+ platform_support->GetCryptoRandomBytes(rv.data_, sizeof(rv.data_));
return rv;
}
diff --git a/third_party/mojo/src/mojo/edk/system/unique_identifier.h b/third_party/mojo/src/mojo/edk/system/unique_identifier.h
index a7f68ba..c9cba88 100644
--- a/third_party/mojo/src/mojo/edk/system/unique_identifier.h
+++ b/third_party/mojo/src/mojo/edk/system/unique_identifier.h
@@ -31,6 +31,13 @@ struct hash<mojo::system::UniqueIdentifier>;
} // BASE_HASH_NAMESPACE
namespace mojo {
+
+namespace embedder {
+
+class PlatformSupport;
+
+} // namespace embedder
+
namespace system {
// Declare this before |UniqueIdentifier|, so that it can be friended.
@@ -44,7 +51,7 @@ class MOJO_SYSTEM_IMPL_EXPORT UniqueIdentifier {
public:
// This generates a new identifier. Uniqueness is "guaranteed" (i.e.,
// probabilistically) for identifiers.
- static UniqueIdentifier Generate();
+ static UniqueIdentifier Generate(embedder::PlatformSupport* platform_support);
bool operator==(const UniqueIdentifier& other) const {
return memcmp(data_, other.data_, sizeof(data_)) == 0;
@@ -58,7 +65,9 @@ class MOJO_SYSTEM_IMPL_EXPORT UniqueIdentifier {
private:
friend BASE_HASH_NAMESPACE::hash<mojo::system::UniqueIdentifier>;
- friend std::ostream& operator<<(std::ostream&, const UniqueIdentifier&);
+ friend MOJO_SYSTEM_IMPL_EXPORT std::ostream& operator<<(
+ std::ostream&,
+ const UniqueIdentifier&);
explicit UniqueIdentifier() {}
diff --git a/third_party/mojo/src/mojo/edk/system/unique_identifier_unittest.cc b/third_party/mojo/src/mojo/edk/system/unique_identifier_unittest.cc
index 2be4f6e..5241293 100644
--- a/third_party/mojo/src/mojo/edk/system/unique_identifier_unittest.cc
+++ b/third_party/mojo/src/mojo/edk/system/unique_identifier_unittest.cc
@@ -8,21 +8,36 @@
#include <sstream>
#include "base/containers/hash_tables.h"
+#include "base/macros.h"
+#include "mojo/edk/embedder/simple_platform_support.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
namespace system {
namespace {
-TEST(UniqueIdentifierTest, Basic) {
+class UniqueIdentifierTest : public testing::Test {
+ public:
+ UniqueIdentifierTest() {}
+ ~UniqueIdentifierTest() override {}
+
+ embedder::PlatformSupport* platform_support() { return &platform_support_; }
+
+ private:
+ embedder::SimplePlatformSupport platform_support_;
+
+ DISALLOW_COPY_AND_ASSIGN(UniqueIdentifierTest);
+};
+
+TEST_F(UniqueIdentifierTest, Basic) {
// (This also checks copy constructibility.)
- UniqueIdentifier id1 = UniqueIdentifier::Generate();
+ UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support());
EXPECT_EQ(id1, id1);
EXPECT_FALSE(id1 != id1);
EXPECT_FALSE(id1 < id1);
- UniqueIdentifier id2 = UniqueIdentifier::Generate();
+ UniqueIdentifier id2 = UniqueIdentifier::Generate(platform_support());
EXPECT_FALSE(id2 == id1);
EXPECT_NE(id2, id1);
@@ -32,14 +47,14 @@ TEST(UniqueIdentifierTest, Basic) {
id2 = id1;
}
-TEST(UniqueIdentifierTest, Logging) {
+TEST_F(UniqueIdentifierTest, Logging) {
std::ostringstream oss1;
- UniqueIdentifier id1 = UniqueIdentifier::Generate();
+ UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support());
oss1 << id1;
EXPECT_FALSE(oss1.str().empty());
std::ostringstream oss2;
- UniqueIdentifier id2 = UniqueIdentifier::Generate();
+ UniqueIdentifier id2 = UniqueIdentifier::Generate(platform_support());
oss2 << id2;
EXPECT_FALSE(oss2.str().empty());
@@ -47,17 +62,17 @@ TEST(UniqueIdentifierTest, Logging) {
EXPECT_NE(oss1.str(), oss2.str());
}
-TEST(UniqueIdentifierTest, StdSet) {
+TEST_F(UniqueIdentifierTest, StdSet) {
std::set<UniqueIdentifier> s;
EXPECT_TRUE(s.empty());
- UniqueIdentifier id1 = UniqueIdentifier::Generate();
+ UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support());
EXPECT_TRUE(s.find(id1) == s.end());
s.insert(id1);
EXPECT_TRUE(s.find(id1) != s.end());
EXPECT_FALSE(s.empty());
- UniqueIdentifier id2 = UniqueIdentifier::Generate();
+ UniqueIdentifier id2 = UniqueIdentifier::Generate(platform_support());
EXPECT_TRUE(s.find(id2) == s.end());
s.insert(id2);
EXPECT_TRUE(s.find(id2) != s.end());
@@ -74,17 +89,17 @@ TEST(UniqueIdentifierTest, StdSet) {
EXPECT_TRUE(s.empty());
}
-TEST(UniqueIdentifierTest, HashSet) {
+TEST_F(UniqueIdentifierTest, HashSet) {
base::hash_set<UniqueIdentifier> s;
EXPECT_TRUE(s.empty());
- UniqueIdentifier id1 = UniqueIdentifier::Generate();
+ UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support());
EXPECT_TRUE(s.find(id1) == s.end());
s.insert(id1);
EXPECT_TRUE(s.find(id1) != s.end());
EXPECT_FALSE(s.empty());
- UniqueIdentifier id2 = UniqueIdentifier::Generate();
+ UniqueIdentifier id2 = UniqueIdentifier::Generate(platform_support());
EXPECT_TRUE(s.find(id2) == s.end());
s.insert(id2);
EXPECT_TRUE(s.find(id2) != s.end());
diff --git a/third_party/mojo/src/mojo/edk/test/BUILD.gn b/third_party/mojo/src/mojo/edk/test/BUILD.gn
index 3a15663..e8f55ad 100644
--- a/third_party/mojo/src/mojo/edk/test/BUILD.gn
+++ b/third_party/mojo/src/mojo/edk/test/BUILD.gn
@@ -10,6 +10,8 @@ mojo_edk_source_set("test_support") {
sources = [
"multiprocess_test_helper.cc",
"multiprocess_test_helper.h",
+ "scoped_ipc_support.cc",
+ "scoped_ipc_support.h",
"test_utils.h",
"test_utils_posix.cc",
"test_utils_win.cc",
diff --git a/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.cc b/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.cc
new file mode 100644
index 0000000..9f3b97d
--- /dev/null
+++ b/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.cc
@@ -0,0 +1,38 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/edk/test/scoped_ipc_support.h"
+
+#include "base/message_loop/message_loop.h"
+#include "mojo/edk/embedder/embedder.h"
+
+namespace mojo {
+namespace test {
+
+ScopedIPCSupport::ScopedIPCSupport(
+ scoped_refptr<base::TaskRunner> io_thread_task_runner)
+ : io_thread_task_runner_(io_thread_task_runner),
+ event_(true, false) { // Manual reset.
+ // Note: Run delegate methods on the I/O thread.
+ embedder::InitIPCSupport(embedder::ProcessType::NONE, io_thread_task_runner,
+ this, io_thread_task_runner,
+ embedder::ScopedPlatformHandle());
+}
+
+ScopedIPCSupport::~ScopedIPCSupport() {
+ if (base::MessageLoop::current() &&
+ base::MessageLoop::current()->task_runner() == io_thread_task_runner_) {
+ embedder::ShutdownIPCSupportOnIOThread();
+ } else {
+ embedder::ShutdownIPCSupport();
+ event_.Wait();
+ }
+}
+
+void ScopedIPCSupport::OnShutdownComplete() {
+ event_.Signal();
+}
+
+} // namespace test
+} // namespace mojo
diff --git a/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h b/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h
new file mode 100644
index 0000000..2569c4e
--- /dev/null
+++ b/third_party/mojo/src/mojo/edk/test/scoped_ipc_support.h
@@ -0,0 +1,43 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_
+#define MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/task_runner.h"
+#include "mojo/edk/embedder/process_delegate.h"
+
+namespace mojo {
+namespace test {
+
+// A simple class that calls |mojo::embedder::InitIPCSupport()| (with
+// |ProcessType::NONE|) on construction and |ShutdownIPCSupport()| on
+// destruction (or |ShutdownIPCSupportOnIOThread()| if destroyed on the I/O
+// thread).
+// TODO(vtl): Need master/slave versions.
+class ScopedIPCSupport : public embedder::ProcessDelegate {
+ public:
+ ScopedIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner);
+ ~ScopedIPCSupport() override;
+
+ private:
+ // ProcessDelegate| implementation:
+ // Note: Executed on the I/O thread.
+ void OnShutdownComplete() override;
+
+ scoped_refptr<base::TaskRunner> io_thread_task_runner_;
+
+ // Set after shut down.
+ base::WaitableEvent event_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport);
+};
+
+} // namespace test
+} // namespace mojo
+
+#endif // MOJO_EDK_TEST_SCOPED_IPC_SUPPORT_H_
diff --git a/third_party/mojo/src/mojo/public/.gitignore b/third_party/mojo/src/mojo/public/.gitignore
new file mode 100644
index 0000000..8fb6a7d
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/.gitignore
@@ -0,0 +1,2 @@
+*.pyc
+/tools/prebuilt/
diff --git a/third_party/mojo/src/mojo/public/LICENSE b/third_party/mojo/src/mojo/public/LICENSE
new file mode 100644
index 0000000..972bb2e
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/mojo/src/mojo/public/VERSION b/third_party/mojo/src/mojo/public/VERSION
index c755f39..29c42bf 100644
--- a/third_party/mojo/src/mojo/public/VERSION
+++ b/third_party/mojo/src/mojo/public/VERSION
@@ -1 +1 @@
-1027d24a1f68c6d10b7539b32114f1272b2cc9f1 \ No newline at end of file
+3d23dae011859a2aae49f1d1adde705c8e85d819 \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/c/system/tests/core_perftest.cc b/third_party/mojo/src/mojo/public/c/system/tests/core_perftest.cc
index 23fd92b..3ee3015 100644
--- a/third_party/mojo/src/mojo/public/c/system/tests/core_perftest.cc
+++ b/third_party/mojo/src/mojo/public/c/system/tests/core_perftest.cc
@@ -7,7 +7,6 @@
#include "mojo/public/c/system/core.h"
#include <assert.h>
-#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@@ -37,8 +36,8 @@ class MessagePipeWriterThread : public mojo::Thread {
// TODO(vtl): Should I throttle somehow?
for (;;) {
- MojoResult result = MojoWriteMessage(
- handle_, buffer, num_bytes_, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
+ MojoResult result = MojoWriteMessage(handle_, buffer, num_bytes_, nullptr,
+ 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
if (result == MOJO_RESULT_OK) {
num_writes_++;
continue;
@@ -74,8 +73,8 @@ class MessagePipeReaderThread : public mojo::Thread {
for (;;) {
uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
- MojoResult result = MojoReadMessage(
- handle_, buffer, &num_bytes, NULL, NULL, MOJO_READ_MESSAGE_FLAG_NONE);
+ MojoResult result = MojoReadMessage(handle_, buffer, &num_bytes, nullptr,
+ nullptr, MOJO_READ_MESSAGE_FLAG_NONE);
if (result == MOJO_RESULT_OK) {
num_reads_++;
continue;
@@ -111,14 +110,14 @@ class MessagePipeReaderThread : public mojo::Thread {
class CorePerftest : public testing::Test {
public:
- CorePerftest() : buffer_(NULL), num_bytes_(0) {}
+ CorePerftest() : buffer_(nullptr), num_bytes_(0) {}
~CorePerftest() override {}
static void NoOp(void* /*closure*/) {}
static void MessagePipe_CreateAndClose(void* closure) {
CorePerftest* self = static_cast<CorePerftest*>(closure);
- MojoResult result = MojoCreateMessagePipe(NULL, &self->h0_, &self->h1_);
+ MojoResult result = MojoCreateMessagePipe(nullptr, &self->h0_, &self->h1_);
MOJO_ALLOW_UNUSED_LOCAL(result);
assert(result == MOJO_RESULT_OK);
result = MojoClose(self->h0_);
@@ -129,21 +128,22 @@ class CorePerftest : public testing::Test {
static void MessagePipe_WriteAndRead(void* closure) {
CorePerftest* self = static_cast<CorePerftest*>(closure);
- MojoResult result = MojoWriteMessage(self->h0_, self->buffer_,
- self->num_bytes_, NULL, 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE);
+ MojoResult result =
+ MojoWriteMessage(self->h0_, self->buffer_, self->num_bytes_, nullptr, 0,
+ MOJO_WRITE_MESSAGE_FLAG_NONE);
MOJO_ALLOW_UNUSED_LOCAL(result);
assert(result == MOJO_RESULT_OK);
uint32_t read_bytes = self->num_bytes_;
- result = MojoReadMessage(self->h1_, self->buffer_, &read_bytes, NULL, NULL,
- MOJO_READ_MESSAGE_FLAG_NONE);
+ result = MojoReadMessage(self->h1_, self->buffer_, &read_bytes, nullptr,
+ nullptr, MOJO_READ_MESSAGE_FLAG_NONE);
assert(result == MOJO_RESULT_OK);
}
static void MessagePipe_EmptyRead(void* closure) {
CorePerftest* self = static_cast<CorePerftest*>(closure);
- MojoResult result = MojoReadMessage(self->h0_, NULL, NULL, NULL, NULL,
- MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
+ MojoResult result =
+ MojoReadMessage(self->h0_, nullptr, nullptr, nullptr, nullptr,
+ MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
MOJO_ALLOW_UNUSED_LOCAL(result);
assert(result == MOJO_RESULT_SHOULD_WAIT);
}
@@ -158,7 +158,7 @@ class CorePerftest : public testing::Test {
assert(num_writers > 0);
assert(num_readers > 0);
- MojoResult result = MojoCreateMessagePipe(NULL, &h0_, &h1_);
+ MojoResult result = MojoCreateMessagePipe(nullptr, &h0_, &h1_);
MOJO_ALLOW_UNUSED_LOCAL(result);
assert(result == MOJO_RESULT_OK);
@@ -239,7 +239,7 @@ class CorePerftest : public testing::Test {
static_cast<time_t>(microseconds / 1000000), // Seconds.
static_cast<long>(microseconds % 1000000) * 1000L // Nanoseconds.
};
- int rv = nanosleep(&req, NULL);
+ int rv = nanosleep(&req, nullptr);
MOJO_ALLOW_UNUSED_LOCAL(rv);
assert(rv == 0);
}
@@ -261,7 +261,7 @@ TEST_F(CorePerftest, MessagePipe_CreateAndClose) {
}
TEST_F(CorePerftest, MessagePipe_WriteAndRead) {
- MojoResult result = MojoCreateMessagePipe(NULL, &h0_, &h1_);
+ MojoResult result = MojoCreateMessagePipe(nullptr, &h0_, &h1_);
MOJO_ALLOW_UNUSED_LOCAL(result);
assert(result == MOJO_RESULT_OK);
char buffer[10000] = {0};
@@ -289,7 +289,7 @@ TEST_F(CorePerftest, MessagePipe_WriteAndRead) {
}
TEST_F(CorePerftest, MessagePipe_EmptyRead) {
- MojoResult result = MojoCreateMessagePipe(NULL, &h0_, &h1_);
+ MojoResult result = MojoCreateMessagePipe(nullptr, &h0_, &h1_);
MOJO_ALLOW_UNUSED_LOCAL(result);
assert(result == MOJO_RESULT_OK);
mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead", nullptr,
diff --git a/third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc b/third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc
index 71e61f4..de59a70 100644
--- a/third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc
+++ b/third_party/mojo/src/mojo/public/c/system/tests/core_unittest.cc
@@ -40,29 +40,30 @@ TEST(CoreTest, InvalidHandle) {
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(MOJO_HANDLE_INVALID));
// Wait:
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- MojoWait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, 1000000, NULL));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoWait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, 1000000,
+ nullptr));
h0 = MOJO_HANDLE_INVALID;
sig = ~MOJO_HANDLE_SIGNAL_NONE;
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoWaitMany(&h0, &sig, 1, MOJO_DEADLINE_INDEFINITE, NULL, NULL));
-
- // Message pipe:
EXPECT_EQ(
MOJO_RESULT_INVALID_ARGUMENT,
- MojoWriteMessage(h0, buffer, 3, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
+ MojoWaitMany(&h0, &sig, 1, MOJO_DEADLINE_INDEFINITE, nullptr, nullptr));
+
+ // Message pipe:
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoWriteMessage(h0, buffer, 3, nullptr, 0,
+ MOJO_WRITE_MESSAGE_FLAG_NONE));
buffer_size = static_cast<uint32_t>(sizeof(buffer));
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoReadMessage(h0, buffer, &buffer_size, NULL, NULL,
+ MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr,
MOJO_READ_MESSAGE_FLAG_NONE));
// Data pipe:
buffer_size = static_cast<uint32_t>(sizeof(buffer));
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
MojoWriteData(h0, buffer, &buffer_size, MOJO_WRITE_DATA_FLAG_NONE));
- write_pointer = NULL;
+ write_pointer = nullptr;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
MojoBeginWriteData(h0, &write_pointer, &buffer_size,
MOJO_WRITE_DATA_FLAG_NONE));
@@ -70,7 +71,7 @@ TEST(CoreTest, InvalidHandle) {
buffer_size = static_cast<uint32_t>(sizeof(buffer));
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
MojoReadData(h0, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
- read_pointer = NULL;
+ read_pointer = nullptr;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
MojoBeginReadData(h0, &read_pointer, &buffer_size,
MOJO_READ_DATA_FLAG_NONE));
@@ -79,7 +80,7 @@ TEST(CoreTest, InvalidHandle) {
// Shared buffer:
h1 = MOJO_HANDLE_INVALID;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoDuplicateBufferHandle(h0, NULL, &h1));
+ MojoDuplicateBufferHandle(h0, nullptr, &h1));
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
MojoMapBuffer(h0, 0, 1, &write_pointer, MOJO_MAP_BUFFER_FLAG_NONE));
}
@@ -92,7 +93,7 @@ TEST(CoreTest, BasicMessagePipe) {
h0 = MOJO_HANDLE_INVALID;
h1 = MOJO_HANDLE_INVALID;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(NULL, &h0, &h1));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &h0, &h1));
EXPECT_NE(h0, MOJO_HANDLE_INVALID);
EXPECT_NE(h1, MOJO_HANDLE_INVALID);
@@ -110,19 +111,20 @@ TEST(CoreTest, BasicMessagePipe) {
EXPECT_EQ(kSignalAll, state.satisfiable_signals);
// Last parameter is optional.
- EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0, NULL));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoWait(h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0, nullptr));
// Try to read.
buffer_size = static_cast<uint32_t>(sizeof(buffer));
EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
- MojoReadMessage(h0, buffer, &buffer_size, NULL, NULL,
+ MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr,
MOJO_READ_MESSAGE_FLAG_NONE));
// Write to |h1|.
static const char kHello[] = "hello";
buffer_size = static_cast<uint32_t>(sizeof(kHello));
- EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h1, kHello, buffer_size, NULL, 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h1, kHello, buffer_size, nullptr,
+ 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
// |h0| should be readable.
uint32_t result_index = 1;
@@ -137,8 +139,9 @@ TEST(CoreTest, BasicMessagePipe) {
// Read from |h0|.
buffer_size = static_cast<uint32_t>(sizeof(buffer));
- EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(h0, buffer, &buffer_size, NULL,
- NULL, MOJO_READ_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr,
+ MOJO_READ_MESSAGE_FLAG_NONE));
EXPECT_EQ(static_cast<uint32_t>(sizeof(kHello)), buffer_size);
EXPECT_STREQ(kHello, buffer);
@@ -183,7 +186,7 @@ TEST(CoreTest, MAYBE_BasicDataPipe) {
hp = MOJO_HANDLE_INVALID;
hc = MOJO_HANDLE_INVALID;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(NULL, &hp, &hc));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &hp, &hc));
EXPECT_NE(hp, MOJO_HANDLE_INVALID);
EXPECT_NE(hc, MOJO_HANDLE_INVALID);
@@ -210,7 +213,7 @@ TEST(CoreTest, MAYBE_BasicDataPipe) {
MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
// Try to begin a two-phase read from |hc|.
- read_pointer = NULL;
+ read_pointer = nullptr;
EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
MojoBeginReadData(hc, &read_pointer, &buffer_size,
MOJO_READ_DATA_FLAG_NONE));
@@ -263,7 +266,7 @@ TEST(CoreTest, MAYBE_BasicDataPipe) {
state.satisfiable_signals);
// Do a two-phase read from |hc|.
- read_pointer = NULL;
+ read_pointer = nullptr;
EXPECT_EQ(MOJO_RESULT_OK, MojoBeginReadData(hc, &read_pointer, &buffer_size,
MOJO_READ_DATA_FLAG_NONE));
ASSERT_LE(buffer_size, sizeof(buffer) - 1);
@@ -290,11 +293,11 @@ TEST(CoreTest, MAYBE_BasicSharedBuffer) {
// Create a shared buffer (|h0|).
h0 = MOJO_HANDLE_INVALID;
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(NULL, 100, &h0));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 100, &h0));
EXPECT_NE(h0, MOJO_HANDLE_INVALID);
// Map everything.
- pointer = NULL;
+ pointer = nullptr;
EXPECT_EQ(MOJO_RESULT_OK,
MojoMapBuffer(h0, 0, 100, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
ASSERT_TRUE(pointer);
@@ -302,7 +305,7 @@ TEST(CoreTest, MAYBE_BasicSharedBuffer) {
// Duplicate |h0| to |h1|.
h1 = MOJO_HANDLE_INVALID;
- EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(h0, NULL, &h1));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(h0, nullptr, &h1));
EXPECT_NE(h1, MOJO_HANDLE_INVALID);
// Close |h0|.
@@ -315,7 +318,7 @@ TEST(CoreTest, MAYBE_BasicSharedBuffer) {
EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer));
// Map half of |h1|.
- pointer = NULL;
+ pointer = nullptr;
EXPECT_EQ(MOJO_RESULT_OK,
MojoMapBuffer(h1, 50, 50, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
ASSERT_TRUE(pointer);
@@ -336,7 +339,7 @@ extern "C" const char* MinimalCTest(void);
// This checks that things actually work in C (not C++).
TEST(CoreTest, MinimalCTest) {
const char* failure = MinimalCTest();
- EXPECT_TRUE(failure == NULL) << failure;
+ EXPECT_FALSE(failure) << failure;
}
// TODO(vtl): Add multi-threaded tests.
diff --git a/third_party/mojo/src/mojo/public/c/system/tests/core_unittest_pure_c.c b/third_party/mojo/src/mojo/public/c/system/tests/core_unittest_pure_c.c
index fd4d9e9..d5978a9 100644
--- a/third_party/mojo/src/mojo/public/c/system/tests/core_unittest_pure_c.c
+++ b/third_party/mojo/src/mojo/public/c/system/tests/core_unittest_pure_c.c
@@ -53,10 +53,9 @@ const char* MinimalCTest(void) {
handle0 = MOJO_HANDLE_INVALID;
EXPECT_NE(MOJO_RESULT_OK, MojoClose(handle0));
- EXPECT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- MojoWait(handle0, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE,
- NULL));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoWait(handle0, ~MOJO_HANDLE_SIGNAL_NONE,
+ MOJO_DEADLINE_INDEFINITE, NULL));
handle1 = MOJO_HANDLE_INVALID;
EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(NULL, &handle0, &handle1));
@@ -72,37 +71,26 @@ const char* MinimalCTest(void) {
EXPECT_EQ(123u, result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[0].satisfied_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
- MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED,
states[0].satisfiable_signals);
EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(handle0,
- kHello,
- (uint32_t)sizeof(kHello),
- NULL,
- 0u,
- MOJO_WRITE_DATA_FLAG_NONE));
+ MojoWriteMessage(handle0, kHello, (uint32_t)sizeof(kHello), NULL,
+ 0u, MOJO_WRITE_DATA_FLAG_NONE));
struct MojoHandleSignalsState state;
- EXPECT_EQ(
- MOJO_RESULT_OK,
- MojoWait(handle1, MOJO_HANDLE_SIGNAL_READABLE,
- MOJO_DEADLINE_INDEFINITE, &state));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWait(handle1, MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE, &state));
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_CLOSED,
state.satisfiable_signals);
num_bytes = (uint32_t)sizeof(buffer);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(handle1,
- buffer,
- &num_bytes,
- NULL,
- NULL,
- MOJO_READ_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(handle1, buffer, &num_bytes, NULL,
+ NULL, MOJO_READ_MESSAGE_FLAG_NONE));
EXPECT_EQ((uint32_t)sizeof(kHello), num_bytes);
EXPECT_EQ(0, memcmp(buffer, kHello, sizeof(kHello)));
diff --git a/third_party/mojo/src/mojo/public/cpp/application/application_connection.h b/third_party/mojo/src/mojo/public/cpp/application/application_connection.h
index e461e6c..5990be3 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/application_connection.h
+++ b/third_party/mojo/src/mojo/public/cpp/application/application_connection.h
@@ -12,39 +12,40 @@
namespace mojo {
-// An instance of this class is passed to
-// ApplicationDelegate's ConfigureIncomingConnection() method each time a
-// connection is made to this app, and to ApplicationDelegate's
-// ConfigureOutgoingConnection() method when the app connects to
-// another.
+// Represents a connection to another application. An instance of this class is
+// passed to ApplicationDelegate's ConfigureIncomingConnection() method each
+// time a connection is made to this app, and to ApplicationDelegate's
+// ConfigureOutgoingConnection() method when the app connects to another.
//
-// To use define a class that implements your specific service api, e.g. FooImpl
-// to implement a service named Foo.
-// That class must subclass an InterfaceImpl specialization.
+// To use, define a class that implements your specific service API (e.g.,
+// FooImpl to implement a service named Foo). Then implement an
+// InterfaceFactory<Foo> that binds instances of FooImpl to
+// InterfaceRequest<Foo>s and register that on the connection like this:
//
-// Then implement an InterfaceFactory<Foo> that binds instances of FooImpl to
-// InterfaceRequest<Foo>s and register that on the connection.
+// connection->AddService(&factory);
//
-// connection->AddService(&factory);
-//
-// Or if you have multiple factories implemented by the same type, explicitly
+// Or, if you have multiple factories implemented by the same type, explicitly
// specify the interface to register the factory for:
//
-// connection->AddService<Foo>(&my_foo_and_bar_factory_);
-// connection->AddService<Bar>(&my_foo_and_bar_factory_);
+// connection->AddService<Foo>(&my_foo_and_bar_factory_);
+// connection->AddService<Bar>(&my_foo_and_bar_factory_);
//
// The InterfaceFactory must outlive the ApplicationConnection.
class ApplicationConnection {
public:
virtual ~ApplicationConnection();
+ // Makes Interface available as a service to the remote application.
+ // |factory| will create implementations of Interface on demand.
template <typename Interface>
void AddService(InterfaceFactory<Interface>* factory) {
AddServiceConnector(
new internal::InterfaceFactoryConnector<Interface>(factory));
}
- // Connect to the service implementing |Interface|.
+ // Binds |ptr| to an implemention of Interface in the remote application.
+ // |ptr| can immediately be used to start sending requests to the remote
+ // service.
template <typename Interface>
void ConnectToService(InterfacePtr<Interface>* ptr) {
if (ServiceProvider* sp = GetServiceProvider()) {
@@ -54,10 +55,12 @@ class ApplicationConnection {
}
}
- // The url identifying the application on the other end of this connection.
+ // Returns the URL identifying the remote application on this connection.
virtual const std::string& GetRemoteApplicationURL() = 0;
- // Raw ServiceProvider interface to remote application.
+ // Returns the raw proxy to the remote application's ServiceProvider
+ // interface. Most applications will just use ConnectToService() instead.
+ // Caller does not take ownership.
virtual ServiceProvider* GetServiceProvider() = 0;
private:
diff --git a/third_party/mojo/src/mojo/public/cpp/application/application_delegate.h b/third_party/mojo/src/mojo/public/cpp/application/application_delegate.h
index b0f2916..f95dca5 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/application_delegate.h
+++ b/third_party/mojo/src/mojo/public/cpp/application/application_delegate.h
@@ -14,21 +14,24 @@ namespace mojo {
class ApplicationConnection;
class ApplicationImpl;
+// An abstract class that the application may subclass to control various
+// behaviors of ApplicationImpl.
class ApplicationDelegate {
public:
ApplicationDelegate();
virtual ~ApplicationDelegate();
+ // Called exactly once before any other method.
virtual void Initialize(ApplicationImpl* app);
// Override this method to configure what services a connection supports when
// being connected to from an app.
- // return false to reject the connection entirely.
+ // Return false to reject the connection entirely.
virtual bool ConfigureIncomingConnection(ApplicationConnection* connection);
// Override this method to configure what services a connection supports when
// connecting to another app.
- // return false to reject the connection entirely.
+ // Return false to reject the connection entirely.
virtual bool ConfigureOutgoingConnection(ApplicationConnection* connection);
private:
diff --git a/third_party/mojo/src/mojo/public/cpp/application/application_impl.h b/third_party/mojo/src/mojo/public/cpp/application/application_impl.h
index 46d368d..21d44d3 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/application_impl.h
+++ b/third_party/mojo/src/mojo/public/cpp/application/application_impl.h
@@ -52,17 +52,28 @@ class ApplicationDelegate;
//
class ApplicationImpl : public Application {
public:
+ // Does not take ownership of |delegate|, which must remain valid for the
+ // lifetime of ApplicationImpl.
ApplicationImpl(ApplicationDelegate* delegate,
InterfaceRequest<Application> request);
~ApplicationImpl() override;
+ // The Mojo shell. This will return a valid pointer after Initialize() has
+ // been invoked. It will remain valid until UnbindConnections() is invoked or
+ // the ApplicationImpl is destroyed.
Shell* shell() const { return shell_.get(); }
+ const std::string& url() const { return url_; }
+
// Returns any initial configuration arguments, passed by the Shell.
const std::vector<std::string>& args() const { return args_; }
bool HasArg(const std::string& arg) const;
- // Establishes a new connection to an application. Caller does not own.
+ // Requests a new connection to an application. Returns a pointer to the
+ // connection if the connection is permitted by this application's delegate,
+ // or nullptr otherwise. Caller does not take ownership. The pointer remains
+ // valid until an error occurs on the connection with the Shell, or until the
+ // ApplicationImpl is destroyed, whichever occurs first.
ApplicationConnection* ConnectToApplication(const String& application_url);
// Connect to application identified by |application_url| and connect to the
@@ -74,7 +85,9 @@ class ApplicationImpl : public Application {
}
// Application implementation.
- void Initialize(ShellPtr shell, Array<String> args) override;
+ void Initialize(ShellPtr shell,
+ Array<String> args,
+ const mojo::String& url) override;
// Block until the Application is initialized, if it is not already.
void WaitForInitialize();
@@ -113,6 +126,7 @@ class ApplicationImpl : public Application {
Binding<Application> binding_;
ShellPtr shell_;
ShellPtrWatcher* shell_watch_;
+ std::string url_;
std::vector<std::string> args_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ApplicationImpl);
diff --git a/third_party/mojo/src/mojo/public/cpp/application/connect.h b/third_party/mojo/src/mojo/public/cpp/application/connect.h
index a41c028..79762e2 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/connect.h
+++ b/third_party/mojo/src/mojo/public/cpp/application/connect.h
@@ -9,6 +9,7 @@
namespace mojo {
+// Binds |ptr| to a remote implementation of Interface from |service_provider|.
template <typename Interface>
inline void ConnectToService(ServiceProvider* service_provider,
InterfacePtr<Interface>* ptr) {
diff --git a/third_party/mojo/src/mojo/public/cpp/application/lazy_interface_ptr.h b/third_party/mojo/src/mojo/public/cpp/application/lazy_interface_ptr.h
index a9b57db..2d58db1 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/lazy_interface_ptr.h
+++ b/third_party/mojo/src/mojo/public/cpp/application/lazy_interface_ptr.h
@@ -10,6 +10,8 @@
namespace mojo {
+// An InterfacePtr that will request an implementation from a specified
+// ServiceProvider when it is first accessed with the get() method.
template <typename Interface>
class LazyInterfacePtr : public InterfacePtr<Interface> {
public:
diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc b/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc
index c66dbb5..1fbfcac 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc
+++ b/third_party/mojo/src/mojo/public/cpp/application/lib/application_impl.cc
@@ -71,10 +71,13 @@ ApplicationConnection* ApplicationImpl::ConnectToApplication(
return registry;
}
-void ApplicationImpl::Initialize(ShellPtr shell, Array<String> args) {
+void ApplicationImpl::Initialize(ShellPtr shell,
+ Array<String> args,
+ const mojo::String& url) {
shell_ = shell.Pass();
shell_watch_ = new ShellPtrWatcher(this);
shell_.set_error_handler(shell_watch_);
+ url_ = url;
args_ = args.To<std::vector<std::string>>();
delegate_->Initialize(this);
}
diff --git a/third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc b/third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc
index ba6dd3f..d4e002f 100644
--- a/third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc
+++ b/third_party/mojo/src/mojo/public/cpp/application/lib/application_test_base.cc
@@ -47,7 +47,9 @@ class ShellAndArgumentGrabber : public Application {
private:
// Application implementation.
- void Initialize(ShellPtr shell, Array<String> args) override {
+ void Initialize(ShellPtr shell,
+ Array<String> args,
+ const mojo::String& url) override {
*args_ = args.Pass();
g_application_request = binding_.Unbind();
g_shell = shell.Pass();
@@ -137,7 +139,7 @@ void ApplicationTestBase::SetUp() {
g_application_request.Pass());
// Fake application initialization with the given command line arguments.
- application_impl_->Initialize(g_shell.Pass(), g_args.Clone());
+ application_impl_->Initialize(g_shell.Pass(), g_args.Clone(), "");
}
void ApplicationTestBase::TearDown() {
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/binding.h b/third_party/mojo/src/mojo/public/cpp/bindings/binding.h
index 7b663c4..77d015a 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/binding.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/binding.h
@@ -58,8 +58,6 @@ namespace mojo {
template <typename Interface>
class Binding : public ErrorHandler {
public:
- using Client = typename Interface::Client;
-
// Constructs an incomplete binding that will use the implementation |impl|.
// The binding may be completed with a subsequent call to the |Bind| method.
// Does not take ownership of |impl|, which must outlive the binding.
@@ -102,7 +100,6 @@ class Binding : public ErrorHandler {
// Tears down the binding, closing the message pipe and leaving the interface
// implementation unbound.
~Binding() override {
- delete proxy_;
if (internal_router_) {
internal_router_->set_error_handler(nullptr);
delete internal_router_;
@@ -118,14 +115,11 @@ class Binding : public ErrorHandler {
internal::FilterChain filters;
filters.Append<internal::MessageHeaderValidator>();
filters.Append<typename Interface::RequestValidator_>();
- filters.Append<typename Client::ResponseValidator_>();
internal_router_ =
new internal::Router(handle.Pass(), filters.Pass(), waiter);
internal_router_->set_incoming_receiver(&stub_);
internal_router_->set_error_handler(this);
-
- proxy_ = new typename Client::Proxy_(internal_router_);
}
// Completes a binding that was constructed with only an interface
@@ -188,9 +182,6 @@ class Binding : public ErrorHandler {
// does not take ownership.
Interface* impl() { return impl_; }
- // Returns the client's interface.
- Client* client() { return proxy_; }
-
// Indicates whether the binding has been completed (i.e., whether a message
// pipe has been bound to the implementation).
bool is_bound() const { return !!internal_router_; }
@@ -200,7 +191,6 @@ class Binding : public ErrorHandler {
private:
internal::Router* internal_router_ = nullptr;
- typename Client::Proxy_* proxy_ = nullptr;
typename Interface::Stub_ stub_;
Interface* impl_;
ErrorHandler* error_handler_ = nullptr;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/callback.h b/third_party/mojo/src/mojo/public/cpp/bindings/callback.h
index c2ed955..17d1caf 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/callback.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/callback.h
@@ -38,7 +38,7 @@ class Callback<void(Args...)> {
// As above, but can take an object that isn't derived from Runnable, so long
// as it has a compatible operator() or Run() method. operator() will be
- // prefered if the type has both.
+ // preferred if the type has both.
template <typename Sink>
Callback(const Sink& sink) {
using sink_type = typename internal::Conditional<
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h b/third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h
index 5663cc3..b5191ef 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h
@@ -21,7 +21,6 @@ template <typename Interface>
class InterfaceImpl : public Interface, public ErrorHandler {
public:
using ImplementedInterface = Interface;
- using Client = typename Interface::Client;
InterfaceImpl() : binding_(this), error_handler_impl_(this) {
binding_.set_error_handler(&error_handler_impl_);
@@ -38,15 +37,12 @@ class InterfaceImpl : public Interface, public ErrorHandler {
return binding_.WaitForIncomingMethodCall();
}
- Client* client() { return binding_.client(); }
internal::Router* internal_router() { return binding_.internal_router(); }
// Implements ErrorHandler.
//
- // Called when the client is no longer connected to this instance. NOTE: The
- // client() method continues to return a non-null pointer after this method
- // is called. After this method is called, any method calls made on client()
- // will be silently ignored.
+ // Called when the underlying pipe is closed. After this point no more
+ // calls will be made on Interface and all responses will be silently ignored.
void OnConnectionError() override {}
void set_delete_on_error(bool delete_on_error) {
@@ -159,9 +155,6 @@ Impl* WeakBindToProxy(
// The instance is also bound to the current thread. Its methods will only be
// called on the current thread, and if the current thread exits, then it will
// also be deleted, and along with it, its end point of the pipe will be closed.
-//
-// Before returning, the instance will receive a SetClient call, providing it
-// with a proxy to the client on the other end of the pipe.
template <typename Impl, typename Interface>
Impl* BindToRequest(
Impl* instance,
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h b/third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h
index b7f1a4e..8b5e0b4 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h
@@ -20,11 +20,6 @@ class ErrorHandler;
// closes the pipe and deletes the proxy on destruction. The pointer must be
// bound to a message pipe before the interface methods can be called.
//
-// Can also route incoming calls to a local implementation of the
-// Interface::Client interface. To enable this, call the set_client() method.
-// Calls to the client interface will originate from the same thread that owns
-// this InterfacePtr.
-//
// This class is thread hostile, as is the local proxy it manages. All calls to
// this class or the proxy should be from the same thread that created it. If
// you need to move the proxy to a different thread, extract the message pipe
@@ -87,23 +82,18 @@ class InterfacePtr {
internal_state_.Swap(&doomed);
}
- // Blocks the current thread until the next incoming call to a client method
- // or callback arrives, or until an error occurs. Returns |true| if a call
- // arrived, or |false| in case of error.
+ // Blocks the current thread until the next incoming response callback arrives
+ // or an error occurs. Returns |true| if a response arrived, or |false| in
+ // case of error.
//
// This method may only be called after the InterfacePtr has been bound to a
// message pipe.
+ //
+ // TODO(jamesr): Rename to WaitForIncomingResponse().
bool WaitForIncomingMethodCall() {
return internal_state_.WaitForIncomingMethodCall();
}
- // Enables routing of incoming method calls to a local implementation of the
- // Interface::Client interface. Calls to |client| will come from the thread
- // that owns this InterfacePtr.
- void set_client(typename Interface::Client* client) {
- internal_state_.set_client(client);
- }
-
// Indicates whether the message pipe has encountered an error. If true,
// method calls made on this interface will be dropped (and may already have
// been dropped).
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
index ec70d37..a8f95b2 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -26,7 +26,7 @@ class Array_Data;
struct StructHeader {
uint32_t num_bytes;
- uint32_t num_fields;
+ uint32_t version;
};
static_assert(sizeof(StructHeader) == 8, "Bad sizeof(StructHeader)");
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc
index 936d0ca..6332090 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc
@@ -79,12 +79,8 @@ void DecodeHandle(Handle* handle, std::vector<Handle>* handles) {
*handle = FetchAndReset(&handles->at(handle->value()));
}
-bool ValidateStructHeader(const void* data,
- uint32_t min_num_bytes,
- uint32_t min_num_fields,
- BoundsChecker* bounds_checker) {
- MOJO_DCHECK(min_num_bytes >= sizeof(StructHeader));
-
+bool ValidateStructHeaderAndClaimMemory(const void* data,
+ BoundsChecker* bounds_checker) {
if (!IsAligned(data)) {
ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT);
return false;
@@ -96,11 +92,7 @@ bool ValidateStructHeader(const void* data,
const StructHeader* header = static_cast<const StructHeader*>(data);
- // TODO(yzshen): Currently our binding code cannot handle structs of smaller
- // size or with fewer fields than the version that it sees. That needs to be
- // changed in order to provide backward compatibility.
- if (header->num_bytes < min_num_bytes ||
- header->num_fields < min_num_fields) {
+ if (header->num_bytes < sizeof(StructHeader)) {
ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
return false;
}
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h
index 6bebf90..ceb213d 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h
@@ -69,13 +69,15 @@ inline void Decode(T* obj, std::vector<Handle>* handles) {
obj->ptr->DecodePointersAndHandles(handles);
}
-// If returns true, this function also claims the memory range of the size
-// specified in the struct header, starting from |data|.
-// Note: |min_num_bytes| must be no less than sizeof(StructHeader).
-bool ValidateStructHeader(const void* data,
- uint32_t min_num_bytes,
- uint32_t min_num_fields,
- BoundsChecker* bounds_checker);
+// Validates that |data| contains a valid struct header, in terms of alignment
+// and size (i.e., the |num_bytes| field of the header is sufficient for storing
+// the header itself). Besides, it checks that the memory range
+// [data, data + num_bytes) is not marked as occupied by other objects in
+// |bounds_checker|. On success, the memory range is marked as occupied.
+// Note: Does not verify |version| or that |num_bytes| is correct for the
+// claimed version.
+bool ValidateStructHeaderAndClaimMemory(const void* data,
+ BoundsChecker* bounds_checker);
} // namespace internal
} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/interface_ptr_internal.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/interface_ptr_internal.h
index a38baf7..3618a26 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/interface_ptr_internal.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/interface_ptr_internal.h
@@ -24,8 +24,8 @@ class InterfacePtrState {
~InterfacePtrState() {
// Destruction order matters here. We delete |proxy_| first, even though
- // |router_| may have a reference to it, so that |~Interface| may have a
- // shot at generating new outbound messages (ie, invoking client methods).
+ // |router_| may have a reference to it, so that destructors for any request
+ // callbacks still pending can interact with the InterfacePtr.
delete proxy_;
delete router_;
}
@@ -71,13 +71,6 @@ class InterfacePtrState {
bool is_bound() const { return handle_.is_valid() || router_; }
- void set_client(typename Interface::Client* client) {
- ConfigureProxyIfNecessary();
-
- MOJO_DCHECK(proxy_);
- proxy_->stub.set_sink(client);
- }
-
bool encountered_error() const {
return router_ ? router_->encountered_error() : false;
}
@@ -95,15 +88,7 @@ class InterfacePtrState {
}
private:
- class ProxyWithStub : public Interface::Proxy_ {
- public:
- explicit ProxyWithStub(MessageReceiverWithResponder* receiver)
- : Interface::Proxy_(receiver) {}
- typename Interface::Client::Stub_ stub;
-
- private:
- MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyWithStub);
- };
+ using Proxy = typename Interface::Proxy_;
void ConfigureProxyIfNecessary() {
// The proxy has been configured.
@@ -119,19 +104,15 @@ class InterfacePtrState {
FilterChain filters;
filters.Append<MessageHeaderValidator>();
- filters.Append<typename Interface::Client::RequestValidator_>();
filters.Append<typename Interface::ResponseValidator_>();
router_ = new Router(handle_.Pass(), filters.Pass(), waiter_);
waiter_ = nullptr;
- ProxyWithStub* proxy = new ProxyWithStub(router_);
- router_->set_incoming_receiver(&proxy->stub);
-
- proxy_ = proxy;
+ proxy_ = new Proxy(router_);
}
- ProxyWithStub* proxy_;
+ Proxy* proxy_;
Router* router_;
// |proxy_| and |router_| are not initialized until read/write with the
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h
index 7787714..16f6b08 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h
@@ -44,10 +44,18 @@ class Map_Data {
if (!data)
return true;
- if (!ValidateStructHeader(data, sizeof(Map_Data), 2, bounds_checker))
+ if (!ValidateStructHeaderAndClaimMemory(data, bounds_checker))
return false;
const Map_Data* object = static_cast<const Map_Data*>(data);
+ // TODO(yzshen): In order to work with other bindings which still interprets
+ // the |version| field as |num_fields|, |version| is set to 2.
+ if (object->header_.num_bytes != sizeof(Map_Data) ||
+ object->header_.version != 2) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
+ return false;
+ }
+
if (!ValidateEncodedPointer(&object->keys.offset)) {
ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER);
return false;
@@ -106,7 +114,9 @@ class Map_Data {
private:
Map_Data() {
header_.num_bytes = sizeof(*this);
- header_.num_fields = 2;
+ // TODO(yzshen): In order to work with other bindings which still interprets
+ // the |version| field as |num_fields|, set it to version 2 for now.
+ header_.version = 2;
}
~Map_Data() = delete;
};
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_internal.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_internal.h
index 8afc18c..84f927c 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_internal.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_internal.h
@@ -21,7 +21,7 @@ template <typename Key, typename Value>
struct MapTraits<Key, Value, false> {
// Map keys can't be move only types.
static_assert(!internal::IsMoveOnlyType<Key>::value,
- "Map keys can not be move only types.");
+ "Map keys cannot be move only types.");
typedef Key KeyStorageType;
typedef Key& KeyRefType;
@@ -111,7 +111,7 @@ template <typename Key, typename Value>
struct MapTraits<Key, Value, true> {
// Map keys can't be move only types.
static_assert(!internal::IsMoveOnlyType<Key>::value,
- "Map keys can not be move only types.");
+ "Map keys cannot be move only types.");
typedef Key KeyStorageType;
typedef Key& KeyRefType;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_builder.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_builder.cc
index cc914e8..837ac81 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_builder.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_builder.cc
@@ -19,7 +19,9 @@ MessageBuilder::MessageBuilder(uint32_t name, size_t payload_size)
: buf_(sizeof(MessageHeader) + payload_size) {
MessageHeader* header;
Allocate(&buf_, &header);
- header->num_fields = 2;
+ // TODO(yzshen): In order to work with other bindings which still interprets
+ // the |version| field as |num_fields|, set it to version 2 for now.
+ header->version = 2;
header->name = name;
}
@@ -41,7 +43,9 @@ MessageWithRequestIDBuilder::MessageWithRequestIDBuilder(uint32_t name,
: MessageBuilder(sizeof(MessageHeaderWithRequestID) + payload_size) {
MessageHeaderWithRequestID* header;
Allocate(&buf_, &header);
- header->num_fields = 3;
+ // TODO(yzshen): In order to work with other bindings which still interprets
+ // the |version| field as |num_fields|, set it to version 3 for now.
+ header->version = 3;
header->name = name;
header->flags = flags;
header->request_id = request_id;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc
index 9d28ecc..fdcc365 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc
@@ -17,17 +17,21 @@ bool IsValidMessageHeader(const MessageHeader* header) {
// header. If we encounter fields we do not understand, we must ignore them.
// Extra validation of the struct header:
- if (header->num_fields == 2) {
+ if (header->version < 2) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
+ return false;
+ }
+ if (header->version == 2) {
if (header->num_bytes != sizeof(MessageHeader)) {
ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
return false;
}
- } else if (header->num_fields == 3) {
+ } else if (header->version == 3) {
if (header->num_bytes != sizeof(MessageHeaderWithRequestID)) {
ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
return false;
}
- } else if (header->num_fields > 3) {
+ } else if (header->version > 3) {
if (header->num_bytes < sizeof(MessageHeaderWithRequestID)) {
ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
return false;
@@ -37,8 +41,8 @@ bool IsValidMessageHeader(const MessageHeader* header) {
// Validate flags (allow unknown bits):
// These flags require a RequestID.
- if (header->num_fields < 3 && ((header->flags & kMessageExpectsResponse) ||
- (header->flags & kMessageIsResponse))) {
+ if (header->version < 3 && ((header->flags & kMessageExpectsResponse) ||
+ (header->flags & kMessageIsResponse))) {
ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID);
return false;
}
@@ -65,10 +69,8 @@ bool MessageHeaderValidator::Accept(Message* message) {
// if |message| contains handles.
BoundsChecker bounds_checker(message->data(), message->data_num_bytes(), 0);
- if (!ValidateStructHeader(
- message->data(), sizeof(MessageHeader), 2, &bounds_checker)) {
+ if (!ValidateStructHeaderAndClaimMemory(message->data(), &bounds_checker))
return false;
- }
if (!IsValidMessageHeader(message->header()))
return false;
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
index 4facf6e..fbba6b3 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_errors.h
@@ -19,11 +19,11 @@ enum ValidationError {
// objects.
VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE,
// A struct header doesn't make sense, for example:
- // - |num_bytes| is smaller than the size of the oldest version that we
- // support.
- // - |num_fields| is smaller than the field number of the oldest version that
- // we support.
- // - |num_bytes| and |num_fields| don't match.
+ // - |num_bytes| is smaller than the size of the struct header.
+ // - |num_bytes| and |version| don't match.
+ // TODO(yzshen): Consider splitting it into two different error codes. Because
+ // the former indicates someone is misbehaving badly whereas the latter could
+ // be due to an inappropriately-modified .mojom file.
VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER,
// An array header doesn't make sense, for example:
// - |num_bytes| is smaller than the size of the header plus the size required
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/map.h b/third_party/mojo/src/mojo/public/cpp/bindings/map.h
index 8ac183f..09ca4ad 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/map.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/map.h
@@ -25,9 +25,9 @@ class Map {
MOJO_MOVE_ONLY_TYPE(Map)
public:
- // Map keys can not be move only classes.
+ // Map keys cannot be move only classes.
static_assert(!internal::IsMoveOnlyType<Key>::value,
- "Map keys can not be move only types.");
+ "Map keys cannot be move only types.");
typedef internal::MapTraits<Key,
Value,
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/message.h b/third_party/mojo/src/mojo/public/cpp/bindings/message.h
index 5cab4ea..80cd6d5 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/message.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/message.h
@@ -43,7 +43,7 @@ class Message {
bool has_flag(uint32_t flag) const { return !!(data_->header.flags & flag); }
// Access the request_id field (if present).
- bool has_request_id() const { return data_->header.num_fields >= 3; }
+ bool has_request_id() const { return data_->header.version >= 3; }
uint64_t request_id() const {
MOJO_DCHECK(has_request_id());
return static_cast<const internal::MessageHeaderWithRequestID*>(
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/no_interface.h b/third_party/mojo/src/mojo/public/cpp/bindings/no_interface.h
index 4c35789..d8915cd 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/no_interface.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/no_interface.h
@@ -12,7 +12,7 @@
namespace mojo {
// NoInterface is for use in cases when a non-existent or empty interface is
-// needed (e.g., when the Mojom "Peer" attribute is not present).
+// needed.
class NoInterfaceProxy;
class NoInterfaceStub;
@@ -24,7 +24,6 @@ class NoInterface {
typedef NoInterfaceStub Stub_;
typedef PassThroughFilter RequestValidator_;
typedef PassThroughFilter ResponseValidator_;
- typedef NoInterface Client;
virtual ~NoInterface() {}
};
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h b/third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h
index 7caf54a..c891a21 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h
@@ -108,7 +108,6 @@ class StrongBinding : public ErrorHandler {
}
Interface* impl() { return binding_.impl(); }
- typename Interface::Client* client() { return binding_.client(); }
// Exposed for testing, should not generally be used.
internal::Router* internal_router() { return binding_.internal_router(); }
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
index 5667f64..f936361 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
@@ -2,6 +2,8 @@
// 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/binding.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "mojo/public/cpp/utility/run_loop.h"
@@ -24,20 +26,26 @@ class StringRecorder {
std::string* buf_;
};
-class ImportedInterfaceImpl
- : public InterfaceImpl<imported::ImportedInterface> {
+class ImportedInterfaceImpl : public imported::ImportedInterface {
public:
+ explicit ImportedInterfaceImpl(
+ InterfaceRequest<imported::ImportedInterface> request)
+ : binding_(this, request.Pass()) {}
+
void DoSomething() override { do_something_count_++; }
static int do_something_count() { return do_something_count_; }
private:
static int do_something_count_;
+ Binding<ImportedInterface> binding_;
};
int ImportedInterfaceImpl::do_something_count_ = 0;
-class SampleNamedObjectImpl : public InterfaceImpl<sample::NamedObject> {
+class SampleNamedObjectImpl : public sample::NamedObject {
public:
+ explicit SampleNamedObjectImpl(InterfaceRequest<sample::NamedObject> request)
+ : binding_(this, request.Pass()) {}
void SetName(const mojo::String& name) override { name_ = name; }
void GetName(const mojo::Callback<void(mojo::String)>& callback) override {
@@ -46,12 +54,17 @@ class SampleNamedObjectImpl : public InterfaceImpl<sample::NamedObject> {
private:
std::string name_;
+ StrongBinding<sample::NamedObject> binding_;
};
-class SampleFactoryImpl : public InterfaceImpl<sample::Factory> {
+class SampleFactoryImpl : public sample::Factory {
public:
+ explicit SampleFactoryImpl(InterfaceRequest<sample::Factory> request)
+ : binding_(this, request.Pass()) {}
+
void DoStuff(sample::RequestPtr request,
- ScopedMessagePipeHandle pipe) override {
+ ScopedMessagePipeHandle pipe,
+ const DoStuffCallback& callback) override {
std::string text1;
if (pipe.is_valid())
EXPECT_TRUE(ReadTextMessage(pipe.get(), &text1));
@@ -73,13 +86,14 @@ class SampleFactoryImpl : public InterfaceImpl<sample::Factory> {
sample::ResponsePtr response(sample::Response::New());
response->x = 2;
response->pipe = pipe0.Pass();
- client()->DidStuff(response.Pass(), text1);
+ callback.Run(response.Pass(), text1);
if (request->obj)
request->obj->DoSomething();
}
- void DoStuff2(ScopedDataPipeConsumerHandle pipe) override {
+ void DoStuff2(ScopedDataPipeConsumerHandle pipe,
+ const DoStuff2Callback& callback) override {
// Read the data from the pipe, writing the response (as a string) to
// DidStuff2().
ASSERT_TRUE(pipe.is_valid());
@@ -95,13 +109,13 @@ class SampleFactoryImpl : public InterfaceImpl<sample::Factory> {
ReadDataRaw(
pipe.get(), data, &data_size, MOJO_READ_DATA_FLAG_ALL_OR_NONE));
- client()->DidStuff2(data);
+ callback.Run(data);
}
void CreateNamedObject(
InterfaceRequest<sample::NamedObject> object_request) override {
EXPECT_TRUE(object_request.is_pending());
- BindToRequest(new SampleNamedObjectImpl(), &object_request);
+ new SampleNamedObjectImpl(object_request.Pass());
}
// These aren't called or implemented, but exist here to test that the
@@ -118,21 +132,26 @@ class SampleFactoryImpl : public InterfaceImpl<sample::Factory> {
private:
ScopedMessagePipeHandle pipe1_;
+ Binding<sample::Factory> binding_;
};
-class SampleFactoryClientImpl : public sample::FactoryClient {
+class HandlePassingTest : public testing::Test {
public:
- SampleFactoryClientImpl() : got_response_(false) {}
+ void TearDown() override { PumpMessages(); }
- void set_expected_text_reply(const std::string& expected_text_reply) {
- expected_text_reply_ = expected_text_reply;
- }
+ void PumpMessages() { loop_.RunUntilIdle(); }
+
+ private:
+ Environment env_;
+ RunLoop loop_;
+};
- bool got_response() const { return got_response_; }
+struct DoStuffCallback {
+ DoStuffCallback(bool* got_response, std::string* got_text_reply)
+ : got_response(got_response), got_text_reply(got_text_reply) {}
- void DidStuff(sample::ResponsePtr response,
- const String& text_reply) override {
- EXPECT_EQ(expected_text_reply_, text_reply);
+ void Run(sample::ResponsePtr response, const String& text_reply) const {
+ *got_text_reply = text_reply;
if (response->pipe.is_valid()) {
std::string text2;
@@ -149,40 +168,16 @@ class SampleFactoryClientImpl : public sample::FactoryClient {
EXPECT_FALSE(response->pipe.is_valid());
}
- got_response_ = true;
+ *got_response = true;
}
- void DidStuff2(const String& text_reply) override {
- got_response_ = true;
- EXPECT_EQ(expected_text_reply_, text_reply);
- }
-
- private:
- ScopedMessagePipeHandle pipe1_;
- ScopedMessagePipeHandle pipe3_;
- std::string expected_text_reply_;
- bool got_response_;
-};
-
-class HandlePassingTest : public testing::Test {
- public:
- void TearDown() override { PumpMessages(); }
-
- void PumpMessages() { loop_.RunUntilIdle(); }
-
- private:
- Environment env_;
- RunLoop loop_;
+ bool* got_response;
+ std::string* got_text_reply;
};
TEST_F(HandlePassingTest, Basic) {
sample::FactoryPtr factory;
- BindToProxy(new SampleFactoryImpl(), &factory);
-
- SampleFactoryClientImpl factory_client;
- factory_client.set_expected_text_reply(kText1);
-
- factory.set_client(&factory_client);
+ SampleFactoryImpl factory_impl(GetProxy(&factory));
MessagePipe pipe0;
EXPECT_TRUE(WriteTextMessage(pipe0.handle1.get(), kText1));
@@ -191,48 +186,62 @@ TEST_F(HandlePassingTest, Basic) {
EXPECT_TRUE(WriteTextMessage(pipe1.handle1.get(), kText2));
imported::ImportedInterfacePtr imported;
- BindToProxy(new ImportedInterfaceImpl(), &imported);
+ ImportedInterfaceImpl imported_impl(GetProxy(&imported));
sample::RequestPtr request(sample::Request::New());
request->x = 1;
request->pipe = pipe1.handle0.Pass();
request->obj = imported.Pass();
- factory->DoStuff(request.Pass(), pipe0.handle0.Pass());
+ bool got_response = false;
+ std::string got_text_reply;
+ DoStuffCallback cb(&got_response, &got_text_reply);
+ factory->DoStuff(request.Pass(), pipe0.handle0.Pass(), cb);
- EXPECT_FALSE(factory_client.got_response());
+ EXPECT_FALSE(*cb.got_response);
int count_before = ImportedInterfaceImpl::do_something_count();
PumpMessages();
- EXPECT_TRUE(factory_client.got_response());
+ EXPECT_TRUE(*cb.got_response);
+ EXPECT_EQ(kText1, *cb.got_text_reply);
EXPECT_EQ(1, ImportedInterfaceImpl::do_something_count() - count_before);
}
TEST_F(HandlePassingTest, PassInvalid) {
sample::FactoryPtr factory;
- BindToProxy(new SampleFactoryImpl(), &factory);
-
- SampleFactoryClientImpl factory_client;
- factory.set_client(&factory_client);
+ SampleFactoryImpl factory_impl(GetProxy(&factory));
sample::RequestPtr request(sample::Request::New());
request->x = 1;
- factory->DoStuff(request.Pass(), ScopedMessagePipeHandle().Pass());
+ bool got_response = false;
+ std::string got_text_reply;
+ DoStuffCallback cb(&got_response, &got_text_reply);
+ factory->DoStuff(request.Pass(), ScopedMessagePipeHandle().Pass(), cb);
- EXPECT_FALSE(factory_client.got_response());
+ EXPECT_FALSE(*cb.got_response);
PumpMessages();
- EXPECT_TRUE(factory_client.got_response());
+ EXPECT_TRUE(*cb.got_response);
}
+struct DoStuff2Callback {
+ DoStuff2Callback(bool* got_response, std::string* got_text_reply)
+ : got_response(got_response), got_text_reply(got_text_reply) {}
+
+ void Run(const String& text_reply) const {
+ *got_response = true;
+ *got_text_reply = text_reply;
+ }
+
+ bool* got_response;
+ std::string* got_text_reply;
+};
+
// Verifies DataPipeConsumer can be passed and read from.
TEST_F(HandlePassingTest, DataPipe) {
sample::FactoryPtr factory;
- BindToProxy(new SampleFactoryImpl(), &factory);
-
- SampleFactoryClientImpl factory_client;
- factory.set_client(&factory_client);
+ SampleFactoryImpl factory_impl(GetProxy(&factory));
// Writes a string to a data pipe and passes the data pipe (consumer) to the
// factory.
@@ -245,7 +254,6 @@ TEST_F(HandlePassingTest, DataPipe) {
ASSERT_EQ(MOJO_RESULT_OK,
CreateDataPipe(&options, &producer_handle, &consumer_handle));
std::string expected_text_reply = "got it";
- factory_client.set_expected_text_reply(expected_text_reply);
// +1 for \0.
uint32_t data_size = static_cast<uint32_t>(expected_text_reply.size() + 1);
ASSERT_EQ(MOJO_RESULT_OK,
@@ -254,21 +262,22 @@ TEST_F(HandlePassingTest, DataPipe) {
&data_size,
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
- factory->DoStuff2(consumer_handle.Pass());
+ bool got_response = false;
+ std::string got_text_reply;
+ DoStuff2Callback cb(&got_response, &got_text_reply);
+ factory->DoStuff2(consumer_handle.Pass(), cb);
- EXPECT_FALSE(factory_client.got_response());
+ EXPECT_FALSE(*cb.got_response);
PumpMessages();
- EXPECT_TRUE(factory_client.got_response());
+ EXPECT_TRUE(*cb.got_response);
+ EXPECT_EQ(expected_text_reply, *cb.got_text_reply);
}
TEST_F(HandlePassingTest, PipesAreClosed) {
sample::FactoryPtr factory;
- BindToProxy(new SampleFactoryImpl(), &factory);
-
- SampleFactoryClientImpl factory_client;
- factory.set_client(&factory_client);
+ SampleFactoryImpl factory_impl(GetProxy(&factory));
MessagePipe extra_pipe;
@@ -283,7 +292,8 @@ TEST_F(HandlePassingTest, PipesAreClosed) {
sample::RequestPtr request(sample::Request::New());
request->more_pipes = pipes.Pass();
- factory->DoStuff(request.Pass(), ScopedMessagePipeHandle());
+ factory->DoStuff(request.Pass(), ScopedMessagePipeHandle(),
+ sample::Factory::DoStuffCallback());
}
// We expect the pipes to have been closed.
@@ -308,7 +318,7 @@ TEST_F(HandlePassingTest, IsHandle) {
TEST_F(HandlePassingTest, CreateNamedObject) {
sample::FactoryPtr factory;
- BindToProxy(new SampleFactoryImpl(), &factory);
+ SampleFactoryImpl factory_impl(GetProxy(&factory));
sample::NamedObjectPtr object1;
EXPECT_FALSE(object1);
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc
index ded5888..3fcade6 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc
@@ -49,11 +49,15 @@ RunnableImpl<Method, Class> MakeRunnable(Method method, Class object) {
typedef mojo::Callback<void(double)> CalcCallback;
-class MathCalculatorImpl : public InterfaceImpl<math::Calculator> {
+class MathCalculatorImpl : public math::Calculator {
public:
+ explicit MathCalculatorImpl(InterfaceRequest<math::Calculator> request)
+ : total_(0.0), binding_(this, request.Pass()) {}
~MathCalculatorImpl() override {}
- MathCalculatorImpl() : total_(0.0) {}
+ void CloseMessagePipe() { binding_.Close(); }
+
+ void WaitForIncomingMethodCall() { binding_.WaitForIncomingMethodCall(); }
void Clear(const CalcCallback& callback) override {
total_ = 0.0;
@@ -72,6 +76,7 @@ class MathCalculatorImpl : public InterfaceImpl<math::Calculator> {
private:
double total_;
+ Binding<math::Calculator> binding_;
};
class MathCalculatorUI {
@@ -142,22 +147,25 @@ class SelfDestructingMathCalculatorUI {
// static
int SelfDestructingMathCalculatorUI::num_instances_ = 0;
-class ReentrantServiceImpl : public InterfaceImpl<sample::Service> {
+class ReentrantServiceImpl : public sample::Service {
public:
~ReentrantServiceImpl() override {}
- ReentrantServiceImpl() : call_depth_(0), max_call_depth_(0) {}
+ explicit ReentrantServiceImpl(InterfaceRequest<sample::Service> request)
+ : call_depth_(0), max_call_depth_(0), binding_(this, request.Pass()) {}
int max_call_depth() { return max_call_depth_; }
void Frobinate(sample::FooPtr foo,
sample::Service::BazOptions baz,
- sample::PortPtr port) override {
+ sample::PortPtr port,
+ const sample::Service::FrobinateCallback& callback) override {
max_call_depth_ = std::max(++call_depth_, max_call_depth_);
if (call_depth_ == 1) {
- EXPECT_TRUE(WaitForIncomingMethodCall());
+ EXPECT_TRUE(binding_.WaitForIncomingMethodCall());
}
call_depth_--;
+ callback.Run(5);
}
void GetPort(mojo::InterfaceRequest<sample::Port> port) override {}
@@ -165,6 +173,7 @@ class ReentrantServiceImpl : public InterfaceImpl<sample::Service> {
private:
int call_depth_;
int max_call_depth_;
+ Binding<sample::Service> binding_;
};
class InterfacePtrTest : public testing::Test {
@@ -180,7 +189,7 @@ class InterfacePtrTest : public testing::Test {
TEST_F(InterfacePtrTest, EndToEnd) {
math::CalculatorPtr calc;
- BindToProxy(new MathCalculatorImpl(), &calc);
+ MathCalculatorImpl calc_impl(GetProxy(&calc));
// Suppose this is instantiated in a process that has pipe1_.
MathCalculatorUI calculator_ui(calc.Pass());
@@ -195,7 +204,7 @@ TEST_F(InterfacePtrTest, EndToEnd) {
TEST_F(InterfacePtrTest, EndToEnd_Synchronous) {
math::CalculatorPtr calc;
- MathCalculatorImpl* impl = BindToProxy(new MathCalculatorImpl(), &calc);
+ MathCalculatorImpl calc_impl(GetProxy(&calc));
// Suppose this is instantiated in a process that has pipe1_.
MathCalculatorUI calculator_ui(calc.Pass());
@@ -204,13 +213,13 @@ TEST_F(InterfacePtrTest, EndToEnd_Synchronous) {
calculator_ui.Add(2.0);
EXPECT_EQ(0.0, calculator_ui.GetOutput());
- impl->WaitForIncomingMethodCall();
+ calc_impl.WaitForIncomingMethodCall();
calculator_ui.WaitForIncomingMethodCall();
EXPECT_EQ(2.0, calculator_ui.GetOutput());
calculator_ui.Multiply(5.0);
EXPECT_EQ(2.0, calculator_ui.GetOutput());
- impl->WaitForIncomingMethodCall();
+ calc_impl.WaitForIncomingMethodCall();
calculator_ui.WaitForIncomingMethodCall();
EXPECT_EQ(10.0, calculator_ui.GetOutput());
}
@@ -218,7 +227,7 @@ TEST_F(InterfacePtrTest, EndToEnd_Synchronous) {
TEST_F(InterfacePtrTest, Movable) {
math::CalculatorPtr a;
math::CalculatorPtr b;
- BindToProxy(new MathCalculatorImpl(), &b);
+ MathCalculatorImpl calc_impl(GetProxy(&b));
EXPECT_TRUE(!a);
EXPECT_FALSE(!b);
@@ -254,7 +263,7 @@ TEST_F(InterfacePtrTest, Resettable) {
TEST_F(InterfacePtrTest, EncounteredError) {
math::CalculatorPtr proxy;
- MathCalculatorImpl* server = BindToProxy(new MathCalculatorImpl(), &proxy);
+ MathCalculatorImpl calc_impl(GetProxy(&proxy));
MathCalculatorUI calculator_ui(proxy.Pass());
@@ -267,7 +276,7 @@ TEST_F(InterfacePtrTest, EncounteredError) {
EXPECT_FALSE(calculator_ui.encountered_error());
// Close the server.
- server->internal_router()->CloseMessagePipe();
+ calc_impl.CloseMessagePipe();
// The state change isn't picked up locally yet.
EXPECT_FALSE(calculator_ui.encountered_error());
@@ -280,7 +289,7 @@ TEST_F(InterfacePtrTest, EncounteredError) {
TEST_F(InterfacePtrTest, EncounteredErrorCallback) {
math::CalculatorPtr proxy;
- MathCalculatorImpl* server = BindToProxy(new MathCalculatorImpl(), &proxy);
+ MathCalculatorImpl calc_impl(GetProxy(&proxy));
ErrorObserver error_observer;
proxy.set_error_handler(&error_observer);
@@ -296,7 +305,7 @@ TEST_F(InterfacePtrTest, EncounteredErrorCallback) {
EXPECT_FALSE(calculator_ui.encountered_error());
// Close the server.
- server->internal_router()->CloseMessagePipe();
+ calc_impl.CloseMessagePipe();
// The state change isn't picked up locally yet.
EXPECT_FALSE(calculator_ui.encountered_error());
@@ -311,17 +320,9 @@ TEST_F(InterfacePtrTest, EncounteredErrorCallback) {
EXPECT_TRUE(error_observer.encountered_error());
}
-TEST_F(InterfacePtrTest, NoClientAttribute) {
- // This is a test to ensure the following compiles. The sample::Port interface
- // does not have an explicit Client attribute.
- sample::PortPtr port;
- MessagePipe pipe;
- port.Bind(pipe.handle0.Pass());
-}
-
-TEST_F(InterfacePtrTest, DestroyInterfacePtrOnClientMethod) {
+TEST_F(InterfacePtrTest, DestroyInterfacePtrOnMethodResponse) {
math::CalculatorPtr proxy;
- BindToProxy(new MathCalculatorImpl(), &proxy);
+ MathCalculatorImpl calc_impl(GetProxy(&proxy));
EXPECT_EQ(0, SelfDestructingMathCalculatorUI::num_instances());
@@ -334,9 +335,9 @@ TEST_F(InterfacePtrTest, DestroyInterfacePtrOnClientMethod) {
EXPECT_EQ(0, SelfDestructingMathCalculatorUI::num_instances());
}
-TEST_F(InterfacePtrTest, NestedDestroyInterfacePtrOnClientMethod) {
+TEST_F(InterfacePtrTest, NestedDestroyInterfacePtrOnMethodResponse) {
math::CalculatorPtr proxy;
- BindToProxy(new MathCalculatorImpl(), &proxy);
+ MathCalculatorImpl calc_impl(GetProxy(&proxy));
EXPECT_EQ(0, SelfDestructingMathCalculatorUI::num_instances());
@@ -351,14 +352,16 @@ TEST_F(InterfacePtrTest, NestedDestroyInterfacePtrOnClientMethod) {
TEST_F(InterfacePtrTest, ReentrantWaitForIncomingMethodCall) {
sample::ServicePtr proxy;
- ReentrantServiceImpl* impl = BindToProxy(new ReentrantServiceImpl(), &proxy);
+ ReentrantServiceImpl impl(GetProxy(&proxy));
- proxy->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr);
- proxy->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr);
+ proxy->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr,
+ sample::Service::FrobinateCallback());
+ proxy->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr,
+ sample::Service::FrobinateCallback());
PumpMessages();
- EXPECT_EQ(2, impl->max_call_depth());
+ EXPECT_EQ(2, impl.max_call_depth());
}
class StrongMathCalculatorImpl : public math::Calculator, public ErrorHandler {
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc
index 4864e35..a1fe8e6 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/request_response_unittest.cc
@@ -13,8 +13,11 @@ namespace mojo {
namespace test {
namespace {
-class ProviderImpl : public InterfaceImpl<sample::Provider> {
+class ProviderImpl : public sample::Provider {
public:
+ explicit ProviderImpl(InterfaceRequest<sample::Provider> request)
+ : binding_(this, request.Pass()) {}
+
void EchoString(const String& a,
const Callback<void(String)>& callback) override {
Callback<void(String)> callback_copy;
@@ -39,6 +42,8 @@ class ProviderImpl : public InterfaceImpl<sample::Provider> {
const Callback<void(sample::Enum)>& callback) override {
callback.Run(a);
}
+
+ Binding<sample::Provider> binding_;
};
class StringRecorder {
@@ -86,7 +91,7 @@ class RequestResponseTest : public testing::Test {
TEST_F(RequestResponseTest, EchoString) {
sample::ProviderPtr provider;
- BindToProxy(new ProviderImpl(), &provider);
+ ProviderImpl provider_impl(GetProxy(&provider));
std::string buf;
provider->EchoString(String::From("hello"), StringRecorder(&buf));
@@ -98,7 +103,7 @@ TEST_F(RequestResponseTest, EchoString) {
TEST_F(RequestResponseTest, EchoStrings) {
sample::ProviderPtr provider;
- BindToProxy(new ProviderImpl(), &provider);
+ ProviderImpl provider_impl(GetProxy(&provider));
std::string buf;
provider->EchoStrings(
@@ -111,7 +116,7 @@ TEST_F(RequestResponseTest, EchoStrings) {
TEST_F(RequestResponseTest, EchoMessagePipeHandle) {
sample::ProviderPtr provider;
- BindToProxy(new ProviderImpl(), &provider);
+ ProviderImpl provider_impl(GetProxy(&provider));
MessagePipe pipe2;
provider->EchoMessagePipeHandle(pipe2.handle1.Pass(),
@@ -127,7 +132,7 @@ TEST_F(RequestResponseTest, EchoMessagePipeHandle) {
TEST_F(RequestResponseTest, EchoEnum) {
sample::ProviderPtr provider;
- BindToProxy(new ProviderImpl(), &provider);
+ ProviderImpl provider_impl(GetProxy(&provider));
sample::Enum value;
provider->EchoEnum(sample::ENUM_VALUE, EnumRecorder(&value));
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
index ff047cb..5d1617f 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
@@ -256,7 +256,10 @@ void DumpHex(const uint8_t* bytes, uint32_t num_bytes) {
class ServiceImpl : public Service {
public:
- void Frobinate(FooPtr foo, BazOptions baz, PortPtr port) override {
+ void Frobinate(FooPtr foo,
+ BazOptions baz,
+ PortPtr port,
+ const Service::FrobinateCallback& callback) override {
// Users code goes here to handle the incoming Frobinate message.
// We mainly check that we're given the expected arguments.
@@ -273,6 +276,7 @@ class ServiceImpl : public Service {
Print(depth, "baz", baz);
Print(depth, "port", port.get());
}
+ callback.Run(5);
}
void GetPort(mojo::InterfaceRequest<Port> port_request) override {}
@@ -336,7 +340,8 @@ TEST_F(BindingsSampleTest, Basic) {
CheckFoo(*foo);
PortPtr port;
- service->Frobinate(foo.Pass(), Service::BAZ_OPTIONS_EXTRA, port.Pass());
+ service->Frobinate(foo.Pass(), Service::BAZ_OPTIONS_EXTRA, port.Pass(),
+ Service::FrobinateCallback());
delete service;
}
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc
index 52d1313..7f5a376 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/struct_unittest.cc
@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <string.h>
+
#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/message_pipe.h"
#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,6 +30,48 @@ void CheckRect(const Rect& rect, int32_t factor = 1) {
EXPECT_EQ(20 * factor, rect.height);
}
+MultiVersionStructPtr MakeMultiVersionStruct() {
+ MultiVersionStructPtr output(MultiVersionStruct::New());
+ output->f_int32 = 123;
+ output->f_rect = MakeRect(5);
+ output->f_string = "hello";
+ output->f_array = Array<int8_t>(3);
+ output->f_array[0] = 10;
+ output->f_array[1] = 9;
+ output->f_array[2] = 8;
+ MessagePipe pipe;
+ output->f_message_pipe = pipe.handle0.Pass();
+ output->f_int16 = 42;
+
+ return output.Pass();
+}
+
+template <typename U, typename T>
+U SerializeAndDeserialize(T input) {
+ typedef typename mojo::internal::WrapperTraits<T>::DataType InputDataType;
+ typedef typename mojo::internal::WrapperTraits<U>::DataType OutputDataType;
+
+ size_t size = GetSerializedSize_(input);
+ mojo::internal::FixedBuffer buf(size + 32);
+ InputDataType data;
+ Serialize_(input.Pass(), &buf, &data);
+
+ std::vector<Handle> handles;
+ data->EncodePointersAndHandles(&handles);
+
+ // Set the subsequent area to a special value, so that we can find out if we
+ // mistakenly access the area.
+ void* subsequent_area = buf.Allocate(32);
+ memset(subsequent_area, 0xAA, 32);
+
+ OutputDataType output_data = reinterpret_cast<OutputDataType>(data);
+ output_data->DecodePointersAndHandles(&handles);
+
+ U output;
+ Deserialize_(output_data, &output);
+ return output.Pass();
+}
+
class StructTest : public testing::Test {
public:
~StructTest() override {}
@@ -197,5 +242,182 @@ TEST_F(StructTest, Serialization_NullArrayPointers) {
EXPECT_TRUE(region2->rects.is_null());
}
+// Tests deserializing structs as a newer version.
+TEST_F(StructTest, Versioning_OldToNew) {
+ {
+ MultiVersionStructV0Ptr input(MultiVersionStructV0::New());
+ input->f_int32 = 123;
+ MultiVersionStructPtr expected_output(MultiVersionStruct::New());
+ expected_output->f_int32 = 123;
+
+ MultiVersionStructPtr output =
+ SerializeAndDeserialize<MultiVersionStructPtr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+
+ {
+ MultiVersionStructV1Ptr input(MultiVersionStructV1::New());
+ input->f_int32 = 123;
+ input->f_rect = MakeRect(5);
+ MultiVersionStructPtr expected_output(MultiVersionStruct::New());
+ expected_output->f_int32 = 123;
+ expected_output->f_rect = MakeRect(5);
+
+ MultiVersionStructPtr output =
+ SerializeAndDeserialize<MultiVersionStructPtr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+
+ {
+ MultiVersionStructV3Ptr input(MultiVersionStructV3::New());
+ input->f_int32 = 123;
+ input->f_rect = MakeRect(5);
+ input->f_string = "hello";
+ MultiVersionStructPtr expected_output(MultiVersionStruct::New());
+ expected_output->f_int32 = 123;
+ expected_output->f_rect = MakeRect(5);
+ expected_output->f_string = "hello";
+
+ MultiVersionStructPtr output =
+ SerializeAndDeserialize<MultiVersionStructPtr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+
+ {
+ MultiVersionStructV5Ptr input(MultiVersionStructV5::New());
+ input->f_int32 = 123;
+ input->f_rect = MakeRect(5);
+ input->f_string = "hello";
+ input->f_array = Array<int8_t>(3);
+ input->f_array[0] = 10;
+ input->f_array[1] = 9;
+ input->f_array[2] = 8;
+ MultiVersionStructPtr expected_output(MultiVersionStruct::New());
+ expected_output->f_int32 = 123;
+ expected_output->f_rect = MakeRect(5);
+ expected_output->f_string = "hello";
+ expected_output->f_array = Array<int8_t>(3);
+ expected_output->f_array[0] = 10;
+ expected_output->f_array[1] = 9;
+ expected_output->f_array[2] = 8;
+
+ MultiVersionStructPtr output =
+ SerializeAndDeserialize<MultiVersionStructPtr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+
+ {
+ MultiVersionStructV7Ptr input(MultiVersionStructV7::New());
+ input->f_int32 = 123;
+ input->f_rect = MakeRect(5);
+ input->f_string = "hello";
+ input->f_array = Array<int8_t>(3);
+ input->f_array[0] = 10;
+ input->f_array[1] = 9;
+ input->f_array[2] = 8;
+ MessagePipe pipe;
+ input->f_message_pipe = pipe.handle0.Pass();
+
+ MultiVersionStructPtr expected_output(MultiVersionStruct::New());
+ expected_output->f_int32 = 123;
+ expected_output->f_rect = MakeRect(5);
+ expected_output->f_string = "hello";
+ expected_output->f_array = Array<int8_t>(3);
+ expected_output->f_array[0] = 10;
+ expected_output->f_array[1] = 9;
+ expected_output->f_array[2] = 8;
+ // Save the raw handle value separately so that we can compare later.
+ MojoHandle expected_handle = input->f_message_pipe.get().value();
+
+ MultiVersionStructPtr output =
+ SerializeAndDeserialize<MultiVersionStructPtr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_EQ(expected_handle, output->f_message_pipe.get().value());
+ output->f_message_pipe.reset();
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+}
+
+// Tests deserializing structs as an older version.
+TEST_F(StructTest, Versioning_NewToOld) {
+ {
+ MultiVersionStructPtr input = MakeMultiVersionStruct();
+ MultiVersionStructV7Ptr expected_output(MultiVersionStructV7::New());
+ expected_output->f_int32 = 123;
+ expected_output->f_rect = MakeRect(5);
+ expected_output->f_string = "hello";
+ expected_output->f_array = Array<int8_t>(3);
+ expected_output->f_array[0] = 10;
+ expected_output->f_array[1] = 9;
+ expected_output->f_array[2] = 8;
+ // Save the raw handle value separately so that we can compare later.
+ MojoHandle expected_handle = input->f_message_pipe.get().value();
+
+ MultiVersionStructV7Ptr output =
+ SerializeAndDeserialize<MultiVersionStructV7Ptr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_EQ(expected_handle, output->f_message_pipe.get().value());
+ output->f_message_pipe.reset();
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+
+ {
+ MultiVersionStructPtr input = MakeMultiVersionStruct();
+ MultiVersionStructV5Ptr expected_output(MultiVersionStructV5::New());
+ expected_output->f_int32 = 123;
+ expected_output->f_rect = MakeRect(5);
+ expected_output->f_string = "hello";
+ expected_output->f_array = Array<int8_t>(3);
+ expected_output->f_array[0] = 10;
+ expected_output->f_array[1] = 9;
+ expected_output->f_array[2] = 8;
+
+ MultiVersionStructV5Ptr output =
+ SerializeAndDeserialize<MultiVersionStructV5Ptr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+
+ {
+ MultiVersionStructPtr input = MakeMultiVersionStruct();
+ MultiVersionStructV3Ptr expected_output(MultiVersionStructV3::New());
+ expected_output->f_int32 = 123;
+ expected_output->f_rect = MakeRect(5);
+ expected_output->f_string = "hello";
+
+ MultiVersionStructV3Ptr output =
+ SerializeAndDeserialize<MultiVersionStructV3Ptr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+
+ {
+ MultiVersionStructPtr input = MakeMultiVersionStruct();
+ MultiVersionStructV1Ptr expected_output(MultiVersionStructV1::New());
+ expected_output->f_int32 = 123;
+ expected_output->f_rect = MakeRect(5);
+
+ MultiVersionStructV1Ptr output =
+ SerializeAndDeserialize<MultiVersionStructV1Ptr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+
+ {
+ MultiVersionStructPtr input = MakeMultiVersionStruct();
+ MultiVersionStructV0Ptr expected_output(MultiVersionStructV0::New());
+ expected_output->f_int32 = 123;
+
+ MultiVersionStructV0Ptr output =
+ SerializeAndDeserialize<MultiVersionStructV0Ptr>(input.Pass());
+ EXPECT_TRUE(output);
+ EXPECT_TRUE(output->Equals(*expected_output));
+ }
+}
+
} // namespace test
} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
index f811a22..aba7faa 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc
@@ -130,7 +130,8 @@ TEST(UnionTest, ValidationJustWorksPod) {
internal::PodUnion_Data* data;
Serialize_(pod.Pass(), &buf, &data);
void* raw_buf = buf.Leak();
- mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ mojo::internal::BoundsChecker bounds_checker(data,
+ static_cast<uint32_t>(size), 0);
EXPECT_TRUE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
free(raw_buf);
}
@@ -151,7 +152,8 @@ TEST(UnionTest, OutOfAlignmentValidation) {
internal::PodUnion_Data* data =
reinterpret_cast<internal::PodUnion_Data*>(buf);
- mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ mojo::internal::BoundsChecker bounds_checker(data,
+ static_cast<uint32_t>(size), 0);
EXPECT_FALSE(internal::PodUnion_Data::Validate(buf, &bounds_checker));
free(raw_buf);
}
@@ -161,7 +163,8 @@ TEST(UnionTest, OOBValidation) {
size_t size = sizeof(internal::PodUnion_Data) - 1;
mojo::internal::FixedBuffer buf(size);
internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
- mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ mojo::internal::BoundsChecker bounds_checker(data,
+ static_cast<uint32_t>(size), 0);
void* raw_buf = buf.Leak();
EXPECT_FALSE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
free(raw_buf);
@@ -173,7 +176,8 @@ TEST(UnionTest, UnknownTagValidation) {
mojo::internal::FixedBuffer buf(size);
internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
data->tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(0xFFFFFF);
- mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ mojo::internal::BoundsChecker bounds_checker(data,
+ static_cast<uint32_t>(size), 0);
void* raw_buf = buf.Leak();
EXPECT_FALSE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
free(raw_buf);
@@ -237,7 +241,8 @@ TEST(UnionTest, StringValidationNull) {
internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
data->data.unknown = 0x0;
- mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ mojo::internal::BoundsChecker bounds_checker(data,
+ static_cast<uint32_t>(size), 0);
void* raw_buf = buf.Leak();
EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
free(raw_buf);
@@ -250,7 +255,8 @@ TEST(UnionTest, StringValidationPointerOverflow) {
internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
data->data.unknown = 0xFFFFFFFFFFFFFFFF;
- mojo::internal::BoundsChecker bounds_checker(data, size, 0);
+ mojo::internal::BoundsChecker bounds_checker(data,
+ static_cast<uint32_t>(size), 0);
void* raw_buf = buf.Leak();
EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
free(raw_buf);
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_test_input_parser.h b/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_test_input_parser.h
index c8821cd..d5f8c81 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_test_input_parser.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_test_input_parser.h
@@ -82,7 +82,7 @@ namespace test {
// The following describes a valid message whose payload is a Foo struct:
// // message header
// [dist4]message_header // num_bytes
-// [u4]3 // num_fields
+// [u4]3 // version
// [u4]0 // type
// [u4]1 // flags
// [u8]1234 // request_id
@@ -90,7 +90,7 @@ namespace test {
//
// // payload
// [dist4]foo // num_bytes
-// [u4]2 // num_fields
+// [u4]2 // version
// [dist8]bar_ptr // x
// [u4]0xABCD // y
// [u4]0 // padding
@@ -98,7 +98,7 @@ namespace test {
//
// [anchr]bar_ptr
// [dist4]bar // num_bytes
-// [u4]3 // num_fields
+// [u4]3 // version
// [s4]-1 // a
// [b]00000010 // b and c
// 0 0 0 // padding
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc
index 6507f21..f8eeae3 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_unittest.cc
@@ -225,7 +225,9 @@ class ValidationIntegrationTest : public ValidationTest {
public:
TestMessageReceiver(ValidationIntegrationTest* owner,
ScopedMessagePipeHandle handle)
- : owner_(owner), connector_(handle.Pass()) {}
+ : owner_(owner), connector_(handle.Pass()) {
+ connector_.set_enforce_errors_from_incoming_receiver(false);
+ }
~TestMessageReceiver() override {}
bool Accept(Message* message) override {
@@ -246,19 +248,14 @@ class ValidationIntegrationTest : public ValidationTest {
ScopedMessagePipeHandle testee_endpoint_;
};
-class IntegrationTestInterface1Client : public IntegrationTestInterface1 {
- public:
- ~IntegrationTestInterface1Client() override {}
-
- void Method0(BasicStructPtr param0) override {}
-};
-
-class IntegrationTestInterface1Impl
- : public InterfaceImpl<IntegrationTestInterface1> {
+class IntegrationTestInterfaceImpl : public IntegrationTestInterface {
public:
- ~IntegrationTestInterface1Impl() override {}
+ ~IntegrationTestInterfaceImpl() override {}
- void Method0(BasicStructPtr param0) override {}
+ void Method0(BasicStructPtr param0,
+ const Method0Callback& callback) override {
+ callback.Run(Array<uint8_t>::New(0u));
+ }
};
TEST_F(ValidationTest, InputParser) {
@@ -383,35 +380,32 @@ TEST_F(ValidationTest, NotImplemented) {
RunValidationTests("not_implemented_", validators.GetHead());
}
+// Test that InterfacePtr<X> applies the correct validators and they don't
+// conflict with each other:
+// - MessageHeaderValidator
+// - X::ResponseValidator_
TEST_F(ValidationIntegrationTest, InterfacePtr) {
- // Test that InterfacePtr<X> applies the correct validators and they don't
- // conflict with each other:
- // - MessageHeaderValidator
- // - X::Client::RequestValidator_
- // - X::ResponseValidator_
-
- IntegrationTestInterface1Client interface1_client;
- IntegrationTestInterface2Ptr interface2_ptr =
- MakeProxy<IntegrationTestInterface2>(testee_endpoint().Pass());
- interface2_ptr.set_client(&interface1_client);
- interface2_ptr.internal_state()->router_for_testing()->EnableTestingMode();
-
- RunValidationTests("integration_", test_message_receiver());
-}
+ IntegrationTestInterfacePtr interface_ptr =
+ MakeProxy<IntegrationTestInterface>(testee_endpoint().Pass());
+ interface_ptr.internal_state()->router_for_testing()->EnableTestingMode();
-TEST_F(ValidationIntegrationTest, InterfaceImpl) {
- // Test that InterfaceImpl<X> applies the correct validators and they don't
- // conflict with each other:
- // - MessageHeaderValidator
- // - X::RequestValidator_
- // - X::Client::ResponseValidator_
-
- // |interface1_impl| will delete itself when the pipe is closed.
- IntegrationTestInterface1Impl* interface1_impl =
- BindToPipe(new IntegrationTestInterface1Impl(), testee_endpoint().Pass());
- interface1_impl->internal_router()->EnableTestingMode();
+ RunValidationTests("integration_intf_resp", test_message_receiver());
+ RunValidationTests("integration_msghdr", test_message_receiver());
+}
- RunValidationTests("integration_", test_message_receiver());
+// Test that Binding<X> applies the correct validators and they don't
+// conflict with each other:
+// - MessageHeaderValidator
+// - X::RequestValidator_
+TEST_F(ValidationIntegrationTest, Binding) {
+ IntegrationTestInterfaceImpl interface_impl;
+ Binding<IntegrationTestInterface> binding(
+ &interface_impl,
+ MakeRequest<IntegrationTestInterface>(testee_endpoint().Pass()));
+ binding.internal_router()->EnableTestingMode();
+
+ RunValidationTests("integration_intf_rqst", test_message_receiver());
+ RunValidationTests("integration_msghdr", test_message_receiver());
}
} // namespace
diff --git a/third_party/mojo/src/mojo/public/dart/application.dart b/third_party/mojo/src/mojo/public/dart/application.dart
index 80cc144..77afce9 100644
--- a/third_party/mojo/src/mojo/public/dart/application.dart
+++ b/third_party/mojo/src/mojo/public/dart/application.dart
@@ -11,8 +11,8 @@ import 'dart:mojo_core' as core;
import 'dart:typed_data';
import 'package:mojo/public/interfaces/application/application.mojom.dart' as application_mojom;
-import 'package:mojo/public/interfaces/application/service_provider.mojom.dart' as service_provider;
+import 'package:mojo/public/interfaces/application/service_provider.mojom.dart';
import 'package:mojo/public/interfaces/application/shell.mojom.dart' as shell_mojom;
part 'src/application.dart';
-part 'src/service_provider.dart';
+part 'src/application_connection.dart';
diff --git a/third_party/mojo/src/mojo/public/dart/rules.gni b/third_party/mojo/src/mojo/public/dart/rules.gni
index aea59e3..5845f2e 100644
--- a/third_party/mojo/src/mojo/public/dart/rules.gni
+++ b/third_party/mojo/src/mojo/public/dart/rules.gni
@@ -101,12 +101,17 @@ template("dart_packaged_application") {
datadeps = invoker.datadeps
}
+ line = "#!mojo mojo:dart_content_handler"
+ if (defined(invoker.strict) && invoker.strict == true) {
+ line = "#!mojo mojo:dart_content_handler?strict=true"
+ }
+
rebase_input = rebase_path(input, root_build_dir)
rebase_output = rebase_path(output, root_build_dir)
args = [
"--input=$rebase_input",
"--output=$rebase_output",
- "--line=#!mojo mojo:dart_content_handler",
+ "--line=$line",
]
}
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/application.dart b/third_party/mojo/src/mojo/public/dart/src/application.dart
index e5b9d4b..4be554d 100644
--- a/third_party/mojo/src/mojo/public/dart/src/application.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/application.dart
@@ -19,16 +19,17 @@ class _ApplicationImpl extends application_mojom.Application {
super.delegate = this;
}
- void initialize(shell_mojom.ShellProxy shellProxy, List<String> args) {
+ void initialize(
+ shell_mojom.ShellProxy shellProxy, List<String> args, String url) {
assert(shell == null);
shell = shellProxy;
- _application.initialize(args);
+ _application.initialize(args, url);
}
void acceptConnection(
String requestorUrl,
- service_provider.ServiceProviderStub services,
- service_provider.ServiceProviderProxy exposedServices) =>
+ ServiceProviderStub services,
+ ServiceProviderProxy exposedServices) =>
_application._acceptConnection(requestorUrl, services, exposedServices);
void requestQuit() => _application._requestQuitAndClose();
@@ -36,72 +37,46 @@ class _ApplicationImpl extends application_mojom.Application {
void close({bool nodefer: false}) => shell.close();
}
-// ApplicationConnection represents a single outgoing connection to another app.
-class ApplicationConnection {
- // ServiceProvider used to obtain services from the remote application.
- service_provider.ServiceProviderProxy serviceProvider;
-
- ApplicationConnection(this.serviceProvider);
-
- // Obtains a service from the remote application.
- void connectToService(bindings.Proxy proxy) {
- assert(!proxy.isBound);
- var applicationPipe = new core.MojoMessagePipe();
- var proxyEndpoint = applicationPipe.endpoints[0];
- var applicationEndpoint = applicationPipe.endpoints[1];
- proxy.bind(proxyEndpoint);
- serviceProvider.connectToService(proxy.name, applicationEndpoint);
- }
-}
-
// TODO(zra): Better documentation and examples.
// To implement, do the following:
+// - Optionally override initialize() to process command-line args.
// - Optionally override acceptConnection() if services are to be provided.
-// The override should assign a factory function to the passed in
-// ServiceProvider's |factory| field, and then call listen on the
-// ServiceProvider. The factory function should take a MojoMessagePipeEndpoint
-// and return an object that implements the requested interface.
-// - Optionally override initialize() where needed.
-// - Optionally override requestClose() to clean up state specific to your
-// application.
-// To use an Application:
-// - Call listen() on a newly created Application to begin providing services.
-// - Call connectToService() to request services from the Shell.
-// - Call close() to close connections to any requested ServiceProviders and the
-// Shell.
+// - Optionally override close() to clean up application resources.
abstract class Application {
_ApplicationImpl _applicationImpl;
List<ApplicationConnection> _applicationConnections;
- List<ServiceProvider> _serviceProviders;
Application(core.MojoMessagePipeEndpoint endpoint) {
_applicationConnections = [];
- _serviceProviders = [];
_applicationImpl = new _ApplicationImpl(this, endpoint);
}
Application.fromHandle(core.MojoHandle appHandle) {
_applicationConnections = [];
- _serviceProviders = [];
_applicationImpl = new _ApplicationImpl.fromHandle(this, appHandle);
}
- void initialize(List<String> args) {}
+ void initialize(List<String> args, String url) {}
- // Establishes a connection to the app at |url|.
+ // TODO(skydart): This is a temporary fix to allow sky application to consume
+ // mojo services. Do not use for any other purpose.
+ void initializeFromShellProxy(shell_mojom.ShellProxy shellProxy,
+ List<String> args, String url) {
+ _applicationImpl.initialize(shellProxy, args, url);
+ }
+
+ // Returns a connection to the app at |url|.
ApplicationConnection connectToApplication(String url) {
- var serviceProviderProxy =
- new service_provider.ServiceProviderProxy.unbound();
- // TODO: Need to expose ServiceProvider for local services.
- _applicationImpl.shell.connectToApplication(
- url, serviceProviderProxy, null);
- var applicationConnection = new ApplicationConnection(serviceProviderProxy);
- _applicationConnections.add(applicationConnection);
- return applicationConnection;
+ var proxy = new ServiceProviderProxy.unbound();
+ var stub = new ServiceProviderStub.unbound();
+ _applicationImpl.shell.connectToApplication(url, proxy, stub);
+ var connection = new ApplicationConnection(stub, proxy);
+ _applicationConnections.add(connection);
+ return connection;
}
void connectToService(String url, bindings.Proxy proxy) {
- connectToApplication(url).connectToService(proxy);
+ connectToApplication(url).requestService(proxy);
}
void requestQuit() {}
@@ -115,21 +90,23 @@ abstract class Application {
void close() {
assert(_applicationImpl != null);
- _applicationConnections.forEach((c) => c.serviceProvider.close());
+ _applicationConnections.forEach((c) => c.close());
_applicationConnections.clear();
- _serviceProviders.forEach((sp) => sp.close());
- _serviceProviders.clear();
_applicationImpl.close();
}
void _acceptConnection(
String requestorUrl,
- service_provider.ServiceProviderStub services,
- service_provider.ServiceProviderProxy exposedServices) {
- var serviceProvider = new ServiceProvider(services, exposedServices);
- _serviceProviders.add(serviceProvider);
- acceptConnection(requestorUrl, serviceProvider);
+ ServiceProviderStub services,
+ ServiceProviderProxy exposedServices) {
+ var connection = new ApplicationConnection(services, exposedServices);
+ _applicationConnections.add(connection);
+ acceptConnection(requestorUrl, connection);
}
- void acceptConnection(String requestorUrl, ServiceProvider serviceProvider) {}
+ // Override this method to provide services on |connection|.
+ // If you provide at least one service or set fallbackServiceProvider,
+ // then you must invoke connection.listen().
+ void acceptConnection(String requestorUrl, ApplicationConnection connection) {
+ }
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/application_connection.dart b/third_party/mojo/src/mojo/public/dart/src/application_connection.dart
new file mode 100644
index 0000000..4f31468
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/dart/src/application_connection.dart
@@ -0,0 +1,105 @@
+// 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.
+
+part of application;
+
+typedef core.Listener ServiceFactory(core.MojoMessagePipeEndpoint endpoint);
+typedef void FallbackServiceFactory(String interfaceName,
+ core.MojoMessagePipeEndpoint endpoint);
+
+
+class LocalServiceProvider extends ServiceProvider {
+ final ApplicationConnection connection;
+
+ LocalServiceProvider(ApplicationConnection this.connection,
+ ServiceProviderStub stub)
+ : super.fromStub(stub) {
+ delegate = this;
+ }
+
+ void connectToService(String interfaceName,
+ core.MojoMessagePipeEndpoint pipe) {
+ if (connection._nameToServiceFactory.containsKey(interfaceName)) {
+ var listener = connection._nameToServiceFactory[interfaceName](pipe);
+ if (listener != null) {
+ listener.listen();
+ return;
+ }
+ }
+ if (connection.fallbackServiceFactory != null) {
+ connection.fallbackServiceFactory(interfaceName, pipe);
+ return;
+ }
+ // The specified interface isn't provided. Close the pipe so the
+ // remote endpoint sees that we don't support this interface.
+ pipe.handle.close();
+ }
+}
+
+// Encapsulates a pair of ServiceProviders that enable services (interface
+// implementations) to be provided to a remote application as well as exposing
+// services provided by a remote application. ApplicationConnection
+// objects are returned by the Application ConnectToApplication() method
+// and they're passed to the Application AcceptConnection() method.
+//
+// To request a service from the remote application:
+// var proxy = applicationConnection.requestService(ViewManagerClient.name);
+//
+// To provide a service to the remote application, specify a function that
+// returns a service. For example:
+// applicationConnection.provideService(ViewManagerClient.name, (pipe) =>
+// new ViewManagerClientImpl(pipe));
+//
+// To handle requests for any interface, set fallbackServiceFactory to a
+// function that takes ownership of the incoming message pipe endpoint. If the
+// fallbackServiceFactory function doesn't bind the pipe, it should close it.
+//
+// The fallbackServiceFactory is only used if a service wasn't specified
+// with provideService().
+
+class ApplicationConnection {
+ ServiceProviderProxy remoteServiceProvider;
+ LocalServiceProvider _localServiceProvider;
+ final _nameToServiceFactory = new Map<String, ServiceFactory>();
+ FallbackServiceFactory fallbackServiceFactory;
+
+ ApplicationConnection(ServiceProviderStub stub, ServiceProviderProxy proxy)
+ : remoteServiceProvider = proxy {
+ if (stub != null) _localServiceProvider =
+ new LocalServiceProvider(this, stub);
+ }
+
+ bindings.Proxy requestService(bindings.Proxy proxy) {
+ assert(!proxy.isBound &&
+ (remoteServiceProvider != null) &&
+ remoteServiceProvider.isBound);
+ var applicationPipe = new core.MojoMessagePipe();
+ var proxyEndpoint = applicationPipe.endpoints[0];
+ var applicationEndpoint = applicationPipe.endpoints[1];
+ proxy.bind(proxyEndpoint);
+ remoteServiceProvider.connectToService(proxy.name, applicationEndpoint);
+ return proxy;
+ }
+
+ void provideService(String interfaceName, ServiceFactory factory) {
+ assert(_localServiceProvider != null);
+ _nameToServiceFactory[interfaceName] = factory;
+ }
+
+ void listen() {
+ if (_localServiceProvider != null) _localServiceProvider.listen();
+ }
+
+ void close({bool nodefer: false}) {
+ if (remoteServiceProvider != null) {
+ remoteServiceProvider.close();
+ remoteServiceProvider = null;
+ }
+ if (_localServiceProvider != null) {
+ _localServiceProvider.close(nodefer: nodefer);
+ _localServiceProvider = null;
+ }
+
+ }
+}
diff --git a/third_party/mojo/src/mojo/public/dart/src/codec.dart b/third_party/mojo/src/mojo/public/dart/src/codec.dart
index 268daee..677dc10 100644
--- a/third_party/mojo/src/mojo/public/dart/src/codec.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/codec.dart
@@ -9,7 +9,9 @@ int align(int size) => size + (kAlignment - (size % kAlignment)) % kAlignment;
const int kAlignment = 8;
const int kSerializedHandleSize = 4;
const int kPointerSize = 8;
-const DataHeader kMapStructHeader = const DataHeader(24, 2);
+// TODO(yzshen): In order to work with other bindings which still interprets
+// the |version| field as |num_fields|, set it to version 2 for now.
+const StructDataHeader kMapStructHeader = const StructDataHeader(24, 2);
const int kUnspecifiedArrayLength = -1;
const int kNothingNullable = 0;
const int kArrayNullable = (1 << 0);
@@ -18,6 +20,30 @@ const int kElementNullable = (1 << 1);
bool isArrayNullable(int nullability) => (nullability & kArrayNullable) > 0;
bool isElementNullable(int nullability) => (nullability & kElementNullable) > 0;
+class StructDataHeader {
+ static const int kHeaderSize = 8;
+ static const int kSizeOffset = 0;
+ static const int kVersionOffset = 4;
+ final int size;
+ final int version;
+
+ const StructDataHeader(this.size, this.version);
+
+ String toString() => "StructDataHeader($size, $version)";
+}
+
+class ArrayDataHeader {
+ static const int kHeaderSize = 8;
+ static const int kSizeOffset = 0;
+ static const int kNumElementsOffset = 4;
+ final int size;
+ final int numElements;
+
+ const ArrayDataHeader(this.size, this.numElements);
+
+ String toString() => "ArrayDataHeader($size, $numElements)";
+}
+
class MojoCodecError {
final String message;
MojoCodecError(this.message);
@@ -64,18 +90,30 @@ class Encoder {
_buffer = buffer,
_base = buffer.extent;
- Encoder getEncoderAtOffset(DataHeader dataHeader) {
+ Encoder getStructEncoderAtOffset(StructDataHeader dataHeader) {
var result = new Encoder._fromBuffer(_buffer);
- result.encodeDataHeader(dataHeader);
+ result.encodeStructDataHeader(dataHeader);
+ return result;
+ }
+
+ Encoder getArrayEncoderAtOffset(ArrayDataHeader dataHeader) {
+ var result = new Encoder._fromBuffer(_buffer);
+ result.encodeArrayDataHeader(dataHeader);
return result;
}
Message get message => new Message(_buffer.trimmed, _buffer.handles);
- void encodeDataHeader(DataHeader dataHeader) {
+ void encodeStructDataHeader(StructDataHeader dataHeader) {
_buffer.claimMemory(align(dataHeader.size));
- encodeUint32(dataHeader.size, DataHeader.kSizeOffset);
- encodeUint32(dataHeader.numFields, DataHeader.kNumFieldsOffset);
+ encodeUint32(dataHeader.size, StructDataHeader.kSizeOffset);
+ encodeUint32(dataHeader.version, StructDataHeader.kVersionOffset);
+ }
+
+ void encodeArrayDataHeader(ArrayDataHeader dataHeader) {
+ _buffer.claimMemory(align(dataHeader.size));
+ encodeUint32(dataHeader.size, ArrayDataHeader.kSizeOffset);
+ encodeUint32(dataHeader.numElements, ArrayDataHeader.kNumElementsOffset);
}
static const String kErrorUnsigned =
@@ -223,8 +261,8 @@ class Encoder {
Encoder encoderForArrayByTotalSize(int size, int length, int offset) {
encodePointerToNextUnclaimed(offset);
- return getEncoderAtOffset(
- new DataHeader(DataHeader.kHeaderSize + size, length));
+ return getArrayEncoderAtOffset(
+ new ArrayDataHeader(ArrayDataHeader.kHeaderSize + size, length));
}
void encodeBoolArray(
@@ -329,7 +367,8 @@ class Encoder {
var encoder = encoderForArray(
kSerializedHandleSize, value.length, offset, expectedLength);
for (int i = 0; i < value.length; ++i) {
- int handleOffset = DataHeader.kHeaderSize + kSerializedHandleSize * i;
+ int handleOffset =
+ ArrayDataHeader.kHeaderSize + kSerializedHandleSize * i;
elementEncoder(
encoder, value[i], handleOffset, isElementNullable(nullability));
}
@@ -415,8 +454,8 @@ class Encoder {
void appendBytes(Uint8List value) {
_buffer.buffer.buffer.asUint8List().setRange(
- _base + DataHeader.kHeaderSize,
- _base + DataHeader.kHeaderSize + value.lengthInBytes,
+ _base + ArrayDataHeader.kHeaderSize,
+ _base + ArrayDataHeader.kHeaderSize + value.lengthInBytes,
value);
}
@@ -452,7 +491,7 @@ class Encoder {
Encoder encoderForMap(int offset) {
encodePointerToNextUnclaimed(offset);
- return getEncoderAtOffset(kMapStructHeader);
+ return getStructEncoderAtOffset(kMapStructHeader);
}
}
@@ -588,31 +627,47 @@ class Decoder {
return new Decoder.atOffset(this, newPosition, _validator);
}
- DataHeader decodeDataHeader() {
- _validator.claimMemory(_base, _base + DataHeader.kHeaderSize);
- int size = decodeUint32(DataHeader.kSizeOffset);
- int numFields = decodeUint32(DataHeader.kNumFieldsOffset);
+ StructDataHeader decodeStructDataHeader() {
+ _validator.claimMemory(_base, _base + StructDataHeader.kHeaderSize);
+ int size = decodeUint32(StructDataHeader.kSizeOffset);
+ int version = decodeUint32(StructDataHeader.kVersionOffset);
+ if (size < 0) {
+ throw new MojoCodecError('Negative size.');
+ }
+ if (version < 0) {
+ throw new MojoCodecError('Negative version number.');
+ }
+ _validator.claimMemory(_base + StructDataHeader.kHeaderSize, _base + size);
+ return new StructDataHeader(size, version);
+ }
+
+ ArrayDataHeader decodeArrayDataHeader() {
+ _validator.claimMemory(_base, _base + ArrayDataHeader.kHeaderSize);
+ int size = decodeUint32(ArrayDataHeader.kSizeOffset);
+ int numElements = decodeUint32(ArrayDataHeader.kNumElementsOffset);
if (size < 0) {
throw new MojoCodecError('Negative size.');
}
- if (numFields < 0) {
- throw new MojoCodecError('Negative number of fields.');
+ if (numElements < 0) {
+ throw new MojoCodecError('Negative number of elements.');
}
- _validator.claimMemory(_base + DataHeader.kHeaderSize, _base + size);
- return new DataHeader(size, numFields);
+ _validator.claimMemory(_base + ArrayDataHeader.kHeaderSize, _base + size);
+ return new ArrayDataHeader(size, numElements);
}
// Decode arrays.
- DataHeader decodeDataHeaderForBoolArray(int expectedLength) {
- var header = decodeDataHeader();
- if (header.size < DataHeader.kHeaderSize + (header.numFields + 7) ~/ 8) {
+ ArrayDataHeader decodeDataHeaderForBoolArray(int expectedLength) {
+ var header = decodeArrayDataHeader();
+ var arrayByteCount =
+ ArrayDataHeader.kHeaderSize + (header.numElements + 7) ~/ 8;
+ if (header.size < arrayByteCount) {
throw new MojoCodecError('Array header is incorrect');
}
if ((expectedLength != kUnspecifiedArrayLength) &&
- (header.numFields != expectedLength)) {
+ (header.numElements != expectedLength)) {
throw new MojoCodecError(
'Incorrect array length. Expected $expectedLength, but got '
- '${header.numFields}.');
+ '${header.numElements}.');
}
return header;
}
@@ -625,9 +680,9 @@ class Decoder {
var header = d.decodeDataHeaderForBoolArray(expectedLength);
var bytes = new Uint8List.view(
d._buffer.buffer,
- d._buffer.offsetInBytes + d._base + DataHeader.kHeaderSize,
- (header.numFields + 7) ~/ kAlignment);
- var result = new List<bool>(header.numFields);
+ d._buffer.offsetInBytes + d._base + ArrayDataHeader.kHeaderSize,
+ (header.numElements + 7) ~/ kAlignment);
+ var result = new List<bool>(header.numElements);
for (int i = 0; i < bytes.lengthInBytes; ++i) {
for (int j = 0; j < kAlignment; ++j) {
int boolIndex = i * kAlignment + j;
@@ -639,22 +694,25 @@ class Decoder {
return result;
}
- DataHeader decodeDataHeaderForArray(int elementSize, int expectedLength) {
- var header = decodeDataHeader();
- if (header.size < DataHeader.kHeaderSize + header.numFields * elementSize) {
+ ArrayDataHeader decodeDataHeaderForArray(int elementSize,
+ int expectedLength) {
+ var header = decodeArrayDataHeader();
+ var arrayByteCount =
+ ArrayDataHeader.kHeaderSize + header.numElements * elementSize;
+ if (header.size < arrayByteCount) {
throw new MojoCodecError(
'Array header is incorrect: $header, elementSize = $elementSize');
}
if ((expectedLength != kUnspecifiedArrayLength) &&
- (header.numFields != expectedLength)) {
+ (header.numElements != expectedLength)) {
throw new MojoCodecError(
'Incorrect array length. Expected $expectedLength, but got '
- '${header.numFields}');
+ '${header.numElements}');
}
return header;
}
- DataHeader decodeDataHeaderForPointerArray(int expectedLength) =>
+ ArrayDataHeader decodeDataHeaderForPointerArray(int expectedLength) =>
decodeDataHeaderForArray(kPointerSize, expectedLength);
List decodeArray(Function arrayViewer,
@@ -669,8 +727,8 @@ class Decoder {
var header = d.decodeDataHeaderForArray(elementSize, expectedLength);
return arrayViewer(
d._buffer.buffer,
- d._buffer.offsetInBytes + d._base + DataHeader.kHeaderSize,
- header.numFields);
+ d._buffer.offsetInBytes + d._base + ArrayDataHeader.kHeaderSize,
+ header.numElements);
}
List<int> decodeInt8Array(
@@ -732,11 +790,11 @@ class Decoder {
return null;
}
var header = d.decodeDataHeaderForArray(4, expectedLength);
- var result = new List(header.numFields);
+ var result = new List(header.numElements);
for (int i = 0; i < result.length; ++i) {
result[i] = elementDecoder(
d,
- DataHeader.kHeaderSize + kSerializedHandleSize * i,
+ ArrayDataHeader.kHeaderSize + kSerializedHandleSize * i,
isElementNullable(nullability));
}
return result;
@@ -798,15 +856,15 @@ class Decoder {
return _stringOfUtf8(bytes);
}
- DataHeader decodeDataHeaderForMap() {
- var header = decodeDataHeader();
+ StructDataHeader decodeDataHeaderForMap() {
+ var header = decodeStructDataHeader();
if (header.size != kMapStructHeader.size) {
throw new MojoCodecError(
'Incorrect header for map. The size is incorrect.');
}
- if (header.numFields != kMapStructHeader.numFields) {
+ if (header.version != kMapStructHeader.version) {
throw new MojoCodecError(
- 'Incorrect header for map. The number of fields is incorrect.');
+ 'Incorrect header for map. The version is incorrect.');
}
return header;
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/drain_data.dart b/third_party/mojo/src/mojo/public/dart/src/drain_data.dart
index ffc56e5..b5929e5 100644
--- a/third_party/mojo/src/mojo/public/dart/src/drain_data.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/drain_data.dart
@@ -16,12 +16,16 @@ class DataPipeDrainer {
_dataSize = 0;
}
+ ByteData _copy(ByteData byteData) =>
+ new ByteData.view(
+ new Uint8List.fromList(byteData.buffer.asUint8List()).buffer);
+
MojoResult _doRead() {
ByteData thisRead = _consumer.beginRead();
if (thisRead == null) {
throw 'Data pipe beginRead failed: ${_consumer.status}';
}
- _dataList.add(thisRead);
+ _dataList.add(_copy(thisRead));
_dataSize += thisRead.lengthInBytes;
return _consumer.endRead(thisRead.lengthInBytes);
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/message.dart b/third_party/mojo/src/mojo/public/dart/src/message.dart
index 918d219..9c7cf46 100644
--- a/third_party/mojo/src/mojo/public/dart/src/message.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/message.dart
@@ -6,16 +6,20 @@ part of bindings;
class MessageHeader {
static const int kSimpleMessageSize = 16;
- static const int kSimpleMessageNumFields = 2;
+ // TODO(yzshen): In order to work with other bindings which still interprets
+ // the |version| field as |num_fields|, set it to version 2 for now.
+ static const int kSimpleMessageVersion = 2;
static const int kMessageWithRequestIdSize = 24;
- static const int kMessageWithRequestIdNumFields = 3;
- static const int kMessageTypeOffset = DataHeader.kHeaderSize;
+ // TODO(yzshen): In order to work with other bindings which still interprets
+ // the |version| field as |num_fields|, set it to version 3 for now.
+ static const int kMessageWithRequestIdVersion = 3;
+ static const int kMessageTypeOffset = StructDataHeader.kHeaderSize;
static const int kMessageFlagsOffset = kMessageTypeOffset + 4;
static const int kMessageRequestIdOffset = kMessageFlagsOffset + 4;
static const int kMessageExpectsResponse = 1 << 0;
static const int kMessageIsResponse = 1 << 1;
- DataHeader _header;
+ StructDataHeader _header;
int type;
int flags;
int requestId;
@@ -24,17 +28,17 @@ class MessageHeader {
(flags & (kMessageExpectsResponse | kMessageIsResponse)) != 0;
MessageHeader(this.type) :
- _header = new DataHeader(kSimpleMessageSize, kSimpleMessageNumFields),
+ _header = new StructDataHeader(kSimpleMessageSize, kSimpleMessageVersion),
flags = 0,
requestId = 0;
MessageHeader.withRequestId(this.type, this.flags, this.requestId) :
- _header = new DataHeader(
- kMessageWithRequestIdSize, kMessageWithRequestIdNumFields);
+ _header = new StructDataHeader(
+ kMessageWithRequestIdSize, kMessageWithRequestIdVersion);
MessageHeader.fromMessage(Message message) {
var decoder = new Decoder(message);
- _header = decoder.decodeDataHeader();
+ _header = decoder.decodeStructDataHeader();
if (_header.size < kSimpleMessageSize) {
throw new MojoCodecError(
'Incorrect message size. Got: ${_header.size} '
@@ -58,7 +62,7 @@ class MessageHeader {
bool get hasRequestId => mustHaveRequestId(flags);
void encode(Encoder encoder) {
- encoder.encodeDataHeader(_header);
+ encoder.encodeStructDataHeader(_header);
encoder.encodeUint32(type, kMessageTypeOffset);
encoder.encodeUint32(flags, kMessageFlagsOffset);
if (hasRequestId) {
@@ -76,25 +80,25 @@ class MessageHeader {
bool validateHeader(int expectedType, int expectedFlags) =>
(type == expectedType) && validateHeaderFlags(expectedFlags);
- static void _validateDataHeader(DataHeader dataHeader) {
- if (dataHeader.numFields < kSimpleMessageNumFields) {
- throw 'Incorrect number of fields, expecting at least '
- '$kSimpleMessageNumFields, but got: ${dataHeader.numFields}.';
+ static void _validateDataHeader(StructDataHeader dataHeader) {
+ if (dataHeader.version < kSimpleMessageVersion) {
+ throw 'Incorrect version, expecting at least '
+ '$kSimpleMessageVersion, but got: ${dataHeader.version}.';
}
if (dataHeader.size < kSimpleMessageSize) {
throw 'Incorrect message size, expecting at least $kSimpleMessageSize, '
'but got: ${dataHeader.size}';
}
- if ((dataHeader.numFields == kSimpleMessageSize) &&
+ if ((dataHeader.version == kSimpleMessageVersion) &&
(dataHeader.size != kSimpleMessageSize)) {
- throw 'Incorrect message size for a message with $kSimpleMessageNumFields'
- ' fields, expecting $kSimpleMessageSize, '
+ throw 'Incorrect message size for a message of version '
+ '$kSimpleMessageVersion, expecting $kSimpleMessageSize, '
'but got ${dataHeader.size}';
}
- if ((dataHeader.numFields == kMessageWithRequestIdNumFields) &&
+ if ((dataHeader.version == kMessageWithRequestIdVersion) &&
(dataHeader.size != kMessageWithRequestIdSize)) {
- throw 'Incorrect message size for a message with '
- '$kMessageWithRequestIdNumFields fields, expecting '
+ throw 'Incorrect message size for a message of version '
+ '$kMessageWithRequestIdVersion, expecting '
'$kMessageWithRequestIdSize, but got ${dataHeader.size}';
}
}
diff --git a/third_party/mojo/src/mojo/public/dart/src/proxy.dart b/third_party/mojo/src/mojo/public/dart/src/proxy.dart
index 1186232..f1df3c7 100644
--- a/third_party/mojo/src/mojo/public/dart/src/proxy.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/proxy.dart
@@ -50,7 +50,7 @@ abstract class Proxy extends core.MojoEventStreamListener {
serviceMessage.buffer.lengthInBytes,
serviceMessage.handles);
if (!endpoint.status.isOk) {
- throw "message pipe write failed";
+ throw "message pipe write failed - ${endpoint.status}";
}
}
@@ -69,7 +69,7 @@ abstract class Proxy extends core.MojoEventStreamListener {
serviceMessage.buffer.lengthInBytes,
serviceMessage.handles);
if (!endpoint.status.isOk) {
- throw "message pipe write failed";
+ throw "message pipe write failed - ${endpoint.status}";
}
var completer = new Completer();
diff --git a/third_party/mojo/src/mojo/public/dart/src/service_provider.dart b/third_party/mojo/src/mojo/public/dart/src/service_provider.dart
deleted file mode 100644
index 6b07f2e..0000000
--- a/third_party/mojo/src/mojo/public/dart/src/service_provider.dart
+++ /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.
-
-part of application;
-
-typedef core.Listener ListenerFactory(core.MojoMessagePipeEndpoint endpoint);
-
-class ServiceProvider extends service_provider.ServiceProvider {
- ListenerFactory factory;
-
- service_provider.ServiceProviderProxy _proxy;
-
- ServiceProvider(
- service_provider.ServiceProviderStub services,
- [service_provider.ServiceProviderProxy exposedServices = null])
- : _proxy = exposedServices,
- super.fromStub(services) {
- delegate = this;
- }
-
- connectToService(String interfaceName, core.MojoMessagePipeEndpoint pipe) =>
- factory(pipe).listen();
-
- requestService(String name, bindings.Proxy clientImpl) {
- assert(_proxy != null);
- assert(!clientImpl.isBound);
- var pipe = new core.MojoMessagePipe();
- clientImpl.bind(pipe.endpoints[0]);
- _proxy.connectToService(name, pipe.endpoints[1]);
- }
-
- close({bool nodefer : false}) {
- if (_proxy != null) {
- _proxy.close();
- _proxy = null;
- }
- super.close(nodefer: nodefer);
- }
-}
diff --git a/third_party/mojo/src/mojo/public/dart/src/struct.dart b/third_party/mojo/src/mojo/public/dart/src/struct.dart
index 0111732..d4ac365 100644
--- a/third_party/mojo/src/mojo/public/dart/src/struct.dart
+++ b/third_party/mojo/src/mojo/public/dart/src/struct.dart
@@ -4,18 +4,6 @@
part of bindings;
-class DataHeader {
- static const int kHeaderSize = 8;
- static const int kSizeOffset = 0;
- static const int kNumFieldsOffset = 4;
- final int size;
- final int numFields;
-
- const DataHeader(this.size, this.numFields);
-
- String toString() => "DataHeader($size, $numFields)";
-}
-
abstract class Struct {
final int encodedSize;
diff --git a/third_party/mojo/src/mojo/public/go/bindings/async_waiter.go b/third_party/mojo/src/mojo/public/go/bindings/async_waiter.go
new file mode 100644
index 0000000..15fd822
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/go/bindings/async_waiter.go
@@ -0,0 +1,266 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package bindings
+
+import (
+ "fmt"
+ "sync"
+ "sync/atomic"
+
+ "mojo/public/go/system"
+)
+
+var waiter *asyncWaiterImpl
+var once sync.Once
+
+// GetAsyncWaiter returns a default implementation of |AsyncWaiter| interface.
+func GetAsyncWaiter() AsyncWaiter {
+ once.Do(func() {
+ waiter = newAsyncWaiter()
+ })
+ return waiter
+}
+
+// AsyncWaitId is an id returned by |AsyncWait()| used to cancel it.
+type AsyncWaitId uint64
+
+// WaitResponse is a struct sent to a channel waiting for |AsyncWait()| to
+// finish. It contains the same information as if |Wait()| was called on a
+// handle.
+type WaitResponse struct {
+ Result system.MojoResult
+ State system.MojoHandleSignalsState
+}
+
+// AsyncWaiter defines an interface for asynchronously waiting (and cancelling
+// asynchronous waits) on a handle.
+type AsyncWaiter interface {
+ // AsyncWait asynchronously waits on a given handle until a signal
+ // indicated by |signals| is satisfied or it becomes known that no
+ // signal indicated by |signals| will ever be satisified. The wait
+ // response will be sent to |responseChan|.
+ //
+ // |handle| must not be closed or transferred until the wait response
+ // is received from |responseChan|.
+ AsyncWait(handle system.Handle, signals system.MojoHandleSignals, responseChan chan<- WaitResponse) AsyncWaitId
+
+ // CancelWait cancels an outstanding async wait (specified by |id|)
+ // initiated by |AsyncWait()|. A response with Mojo result
+ // |MOJO_RESULT_ABORTED| is sent to the corresponding |responseChan|.
+ CancelWait(id AsyncWaitId)
+}
+
+// waitRequest is a struct sent to asyncWaiterWorker to add another handle to
+// the list of waiting handles.
+type waitRequest struct {
+ handle system.Handle
+ signals system.MojoHandleSignals
+
+ // Used for |CancelWait()| calls. The worker should issue IDs so that
+ // you can't cancel the wait until the worker received the wait request.
+ idChan chan<- AsyncWaitId
+
+ // A channel end to send wait results.
+ responseChan chan<- WaitResponse
+}
+
+// asyncWaiterWorker does the actual work, in its own goroutine. It calls
+// |WaitMany()| on all provided handles. New handles a added via |waitChan|
+// and removed via |cancelChan| messages. To wake the worker asyncWaiterImpl
+// sends mojo messages to a dedicated message pipe, the other end of which has
+// index 0 in all slices of the worker.
+type asyncWaiterWorker struct {
+ // |handles| and |signals| are used to make |WaitMany()| calls directly.
+ // All these arrays should be operated simultaneously; i-th element
+ // of each refers to i-th handle.
+ handles []system.Handle
+ signals []system.MojoHandleSignals
+ asyncWaitIds []AsyncWaitId
+ responses []chan<- WaitResponse
+
+ // Flag shared between waiterImpl and worker that is 1 iff the worker is
+ // already notified by waiterImpl. The worker sets it to 0 as soon as
+ // |WaitMany()| succeeds.
+ isNotified *int32
+ waitChan <-chan waitRequest // should have a non-empty buffer
+ cancelChan <-chan AsyncWaitId // should have a non-empty buffer
+ lastUsedId AsyncWaitId // is incremented each |AsyncWait()| call
+}
+
+// removeHandle removes handle at provided index without sending response by
+// swapping all information associated with index-th handle with the last one
+// and removing the last one.
+func (w *asyncWaiterWorker) removeHandle(index int) {
+ l := len(w.handles) - 1
+ // Swap with the last and remove last.
+ w.handles[index] = w.handles[l]
+ w.handles = w.handles[0:l]
+ w.signals[index] = w.signals[l]
+ w.signals = w.signals[0:l]
+
+ w.asyncWaitIds[index] = w.asyncWaitIds[l]
+ w.asyncWaitIds = w.asyncWaitIds[0:l]
+ w.responses[index] = w.responses[l]
+ w.responses = w.responses[0:l]
+}
+
+// sendWaitResponseAndRemove send response to corresponding channel and removes
+// index-th waiting handle.
+func (w *asyncWaiterWorker) sendWaitResponseAndRemove(index int, result system.MojoResult, state system.MojoHandleSignalsState) {
+ w.responses[index] <- WaitResponse{
+ result,
+ state,
+ }
+ w.removeHandle(index)
+}
+
+// respondToSatisfiedWaits responds to all wait requests that have at least
+// one satisfied signal and removes them.
+func (w *asyncWaiterWorker) respondToSatisfiedWaits(states []system.MojoHandleSignalsState) {
+ // Don't touch handle at index 0 as it is the waking handle.
+ for i := 1; i < len(states); {
+ if (states[i].SatisfiedSignals & w.signals[i]) != 0 {
+ // Respond and swap i-th with last and remove last.
+ w.sendWaitResponseAndRemove(i, system.MOJO_RESULT_OK, states[i])
+ // Swap i-th with last and remove last.
+ states[i] = states[len(states)-1]
+ states = states[:len(states)-1]
+ } else {
+ i++
+ }
+ }
+}
+
+// processIncomingRequests processes all queued async wait or cancel requests
+// sent by asyncWaiterImpl.
+func (w *asyncWaiterWorker) processIncomingRequests() {
+ for {
+ select {
+ case request := <-w.waitChan:
+ w.handles = append(w.handles, request.handle)
+ w.signals = append(w.signals, request.signals)
+ w.responses = append(w.responses, request.responseChan)
+
+ w.lastUsedId++
+ id := w.lastUsedId
+ w.asyncWaitIds = append(w.asyncWaitIds, id)
+ request.idChan <- id
+ case AsyncWaitId := <-w.cancelChan:
+ // Zero index is reserved for the waking message pipe handle.
+ index := 0
+ for i := 1; i < len(w.asyncWaitIds); i++ {
+ if w.asyncWaitIds[i] == AsyncWaitId {
+ index = i
+ break
+ }
+ }
+ // Do nothing if the id was not found as wait response may be
+ // already sent if the async wait was successful.
+ if index > 0 {
+ w.sendWaitResponseAndRemove(index, system.MOJO_RESULT_ABORTED, system.MojoHandleSignalsState{})
+ }
+ default:
+ return
+ }
+ }
+}
+
+// runLoop run loop of the asyncWaiterWorker. Blocks on |WaitMany()|. If the
+// wait is interrupted by waking handle (index 0) then it means that the worker
+// was woken by waiterImpl, so the worker processes incoming requests from
+// waiterImpl; otherwise responses to corresponding wait request.
+func (w *asyncWaiterWorker) runLoop() {
+ for {
+ result, index, states := system.GetCore().WaitMany(w.handles, w.signals, system.MOJO_DEADLINE_INDEFINITE)
+ // Set flag to 0, so that the next incoming request to
+ // waiterImpl would explicitly wake worker by sending a message
+ // to waking message pipe.
+ atomic.StoreInt32(w.isNotified, 0)
+ if index == -1 {
+ panic(fmt.Sprintf("error waiting on handles: %v", result))
+ break
+ }
+ // Zero index means that the worker was signaled by asyncWaiterImpl.
+ if index == 0 {
+ if result != system.MOJO_RESULT_OK {
+ panic(fmt.Sprintf("error waiting on waking handle: %v", result))
+ }
+ w.handles[0].(system.MessagePipeHandle).ReadMessage(system.MOJO_READ_MESSAGE_FLAG_NONE)
+ w.processIncomingRequests()
+ } else if result != system.MOJO_RESULT_OK {
+ w.sendWaitResponseAndRemove(index, result, system.MojoHandleSignalsState{})
+ } else {
+ w.respondToSatisfiedWaits(states)
+ }
+ }
+}
+
+// asyncWaiterImpl is an implementation of |AsyncWaiter| interface.
+// Runs a worker in a separate goroutine and comunicates with it by sending a
+// message to |wakingHandle| to wake worker from |WaitMany()| call and
+// sending request via |waitChan| and |cancelChan|.
+type asyncWaiterImpl struct {
+ wakingHandle system.MessagePipeHandle
+
+ // Flag shared between waiterImpl and worker that is 1 iff the worker is
+ // already notified by waiterImpl. The worker sets it to 0 as soon as
+ // |WaitMany()| succeeds.
+ isWorkerNotified *int32
+ waitChan chan<- waitRequest // should have a non-empty buffer
+ cancelChan chan<- AsyncWaitId // should have a non-empty buffer
+}
+
+// newAsyncWaiter creates an asyncWaiterImpl and starts its worker goroutine.
+func newAsyncWaiter() *asyncWaiterImpl {
+ result, h0, h1 := system.GetCore().CreateMessagePipe(nil)
+ if result != system.MOJO_RESULT_OK {
+ panic(fmt.Sprintf("can't create message pipe %v", result))
+ }
+ waitChan := make(chan waitRequest, 10)
+ cancelChan := make(chan AsyncWaitId, 10)
+ isNotified := new(int32)
+ worker := asyncWaiterWorker{
+ []system.Handle{h1},
+ []system.MojoHandleSignals{system.MOJO_HANDLE_SIGNAL_READABLE},
+ []AsyncWaitId{0},
+ []chan<- WaitResponse{make(chan WaitResponse)},
+ isNotified,
+ waitChan,
+ cancelChan,
+ 0,
+ }
+ go worker.runLoop()
+ return &asyncWaiterImpl{
+ wakingHandle: h0,
+ isWorkerNotified: isNotified,
+ waitChan: waitChan,
+ cancelChan: cancelChan,
+ }
+}
+
+// wakeWorker wakes the worker from |WaitMany()| call. This should be called
+// after sending a message to |waitChan| or |cancelChan| to avoid deadlock.
+func (w *asyncWaiterImpl) wakeWorker() {
+ if atomic.CompareAndSwapInt32(w.isWorkerNotified, 0, 1) {
+ w.wakingHandle.WriteMessage([]byte{0}, nil, system.MOJO_WRITE_MESSAGE_FLAG_NONE)
+ }
+}
+
+func (w *asyncWaiterImpl) AsyncWait(handle system.Handle, signals system.MojoHandleSignals, responseChan chan<- WaitResponse) AsyncWaitId {
+ idChan := make(chan AsyncWaitId, 1)
+ w.waitChan <- waitRequest{
+ handle,
+ signals,
+ idChan,
+ responseChan,
+ }
+ w.wakeWorker()
+ return <-idChan
+}
+
+func (w *asyncWaiterImpl) CancelWait(id AsyncWaitId) {
+ w.cancelChan <- id
+ w.wakeWorker()
+}
diff --git a/third_party/mojo/src/mojo/public/go/bindings/decoder.go b/third_party/mojo/src/mojo/public/go/bindings/decoder.go
index 3f3cce9..6f6b433 100644
--- a/third_party/mojo/src/mojo/public/go/bindings/decoder.go
+++ b/third_party/mojo/src/mojo/public/go/bindings/decoder.go
@@ -68,11 +68,15 @@ func (d *Decoder) pushState(header DataHeader, elementBitSize uint32) error {
if err := d.claimData(int(header.Size - dataHeaderSize)); err != nil {
return err
}
+ elements := uint32(0)
+ if elementBitSize != 0 {
+ elements = header.ElementsOrVersion
+ }
d.stateStack = append(d.stateStack, encodingState{
offset: oldEnd,
limit: d.end,
elementBitSize: elementBitSize,
- elements: header.Elements,
+ elements: elements,
})
return nil
}
@@ -94,13 +98,14 @@ func (d *Decoder) StartArray(elementBitSize uint32) (uint32, error) {
if err != nil {
return 0, err
}
- if got, want := int(header.Size), dataHeaderSize+bytesForBits(uint64(header.Elements)*uint64(elementBitSize)); got < want {
+ minSize := bytesForBits(uint64(header.ElementsOrVersion) * uint64(elementBitSize))
+ if got, want := int(header.Size), dataHeaderSize+minSize; got < want {
return 0, fmt.Errorf("data header size is too small: is %d, but should be at least %d", got, want)
}
if err := d.pushState(header, elementBitSize); err != nil {
return 0, err
}
- return header.Elements, nil
+ return header.ElementsOrVersion, nil
}
// StartMap starts decoding a map and reads its data header.
@@ -120,8 +125,8 @@ func (d *Decoder) StartMap() error {
return nil
}
-// StartArray starts decoding a struct and reads its data header,
-// returning number of fields declared in data header.
+// StartStruct starts decoding a struct and reads its data header,
+// returning struct version declared in data header.
// Note: it doesn't read a pointer to the encoded struct.
// Call |Finish()| after reading all fields.
func (d *Decoder) StartStruct() (uint32, error) {
@@ -135,7 +140,7 @@ func (d *Decoder) StartStruct() (uint32, error) {
if err := d.pushState(header, 0); err != nil {
return 0, err
}
- return header.Elements, nil
+ return header.ElementsOrVersion, nil
}
func (d *Decoder) readDataHeader() (DataHeader, error) {
@@ -144,8 +149,8 @@ func (d *Decoder) readDataHeader() (DataHeader, error) {
}
oldEnd := d.end - dataHeaderSize
header := DataHeader{
- Size: binary.LittleEndian.Uint32(d.buf[oldEnd:]),
- Elements: binary.LittleEndian.Uint32(d.buf[oldEnd+4:]),
+ Size: binary.LittleEndian.Uint32(d.buf[oldEnd:]),
+ ElementsOrVersion: binary.LittleEndian.Uint32(d.buf[oldEnd+4:]),
}
return header, nil
}
diff --git a/third_party/mojo/src/mojo/public/go/bindings/encoder.go b/third_party/mojo/src/mojo/public/go/bindings/encoder.go
index 5ea1a50..542cc21 100644
--- a/third_party/mojo/src/mojo/public/go/bindings/encoder.go
+++ b/third_party/mojo/src/mojo/public/go/bindings/encoder.go
@@ -74,10 +74,10 @@ func ensureElementBitSizeAndCapacity(state *encodingState, bitSize uint32) error
if state == nil {
return fmt.Errorf("empty state stack")
}
- if state.elementBitSize > 0 && state.elementBitSize != bitSize {
+ if state.elementBitSize != 0 && state.elementBitSize != bitSize {
return fmt.Errorf("unexpected element bit size: expected %d, but got %d", state.elementBitSize, bitSize)
}
- if state.elementsProcessed >= state.elements {
+ if state.elementBitSize != 0 && state.elementsProcessed >= state.elements {
return fmt.Errorf("can't process more than elements defined in header(%d)", state.elements)
}
byteSize := bytesForBits(uint64(state.bitOffset + bitSize))
@@ -112,11 +112,15 @@ func (e *Encoder) popState() {
func (e *Encoder) pushState(header DataHeader, elementBitSize uint32) {
oldEnd := e.end
e.claimData(align(int(header.Size), defaultAlignment))
+ elements := uint32(0)
+ if elementBitSize != 0 {
+ elements = header.ElementsOrVersion
+ }
e.stateStack = append(e.stateStack, encodingState{
offset: oldEnd,
limit: e.end,
elementBitSize: elementBitSize,
- elements: header.Elements,
+ elements: elements,
})
e.writeDataHeader(header)
}
@@ -153,15 +157,15 @@ func (e *Encoder) StartMap() {
// StartStruct starts encoding a struct and writes its data header.
// Note: it doesn't write a pointer to the encoded struct.
// Call |Finish()| after writing all fields.
-func (e *Encoder) StartStruct(size, numFields uint32) {
+func (e *Encoder) StartStruct(size, version uint32) {
dataSize := dataHeaderSize + int(size)
- header := DataHeader{uint32(dataSize), numFields}
+ header := DataHeader{uint32(dataSize), version}
e.pushState(header, 0)
}
func (e *Encoder) writeDataHeader(header DataHeader) {
binary.LittleEndian.PutUint32(e.buf[e.state().offset:], header.Size)
- binary.LittleEndian.PutUint32(e.buf[e.state().offset+4:], header.Elements)
+ binary.LittleEndian.PutUint32(e.buf[e.state().offset+4:], header.ElementsOrVersion)
e.state().offset += 8
}
@@ -171,7 +175,7 @@ func (e *Encoder) Finish() error {
if e.state() == nil {
return fmt.Errorf("state stack is empty")
}
- if e.state().elementsProcessed != e.state().elements {
+ if e.state().elementBitSize != 0 && e.state().elementsProcessed != e.state().elements {
return fmt.Errorf("unexpected number of elements written: defined in header %d, but written %d", e.state().elements, e.state().elementsProcessed)
}
e.popState()
diff --git a/third_party/mojo/src/mojo/public/go/bindings/interface.go b/third_party/mojo/src/mojo/public/go/bindings/interface.go
new file mode 100644
index 0000000..03ab791
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/go/bindings/interface.go
@@ -0,0 +1,60 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package bindings
+
+import (
+ "mojo/public/go/system"
+)
+
+// messagePipeHandleOwner owns a message pipe handle, it can only pass it
+// invalidating itself or close it.
+type messagePipeHandleOwner struct {
+ handle system.MessagePipeHandle
+}
+
+// PassMessagePipe passes ownership of the underlying message pipe handle to
+// the newly created handle object, invalidating the underlying handle object
+// in the process.
+func (o *messagePipeHandleOwner) PassMessagePipe() system.MessagePipeHandle {
+ if o.handle == nil {
+ return &InvalidHandle{}
+ }
+ return o.handle.ToUntypedHandle().ToMessagePipeHandle()
+}
+
+// Close closes the underlying handle.
+func (o *messagePipeHandleOwner) Close() {
+ if o.handle != nil {
+ o.handle.Close()
+ }
+}
+
+// InterfaceRequest represents a request from a remote client for an
+// implementation of mojo interface over a specified message pipe. The
+// implementor of the interface should remove the message pipe by calling
+// PassMessagePipe() and attach it to the implementation.
+type InterfaceRequest struct {
+ messagePipeHandleOwner
+}
+
+// InterfacePointer owns a message pipe handle with an implementation of mojo
+// interface attached to the other end of the message pipe. The client of the
+// interface should remove the message pipe by calling PassMessagePipe() and
+// attach it to the proxy.
+type InterfacePointer struct {
+ messagePipeHandleOwner
+}
+
+// CreateMessagePipeForInterface creates a message pipe with interface request
+// on one end and interface pointer on the other end. The interface request
+// should be attached to appropriate mojo interface implementation and
+// the interface pointer should be attached to mojo interface proxy.
+func CreateMessagePipeForMojoInterface() (InterfaceRequest, InterfacePointer) {
+ r, h0, h1 := system.GetCore().CreateMessagePipe(nil)
+ if r != system.MOJO_RESULT_OK {
+ panic("can't create a message pipe")
+ }
+ return InterfaceRequest{messagePipeHandleOwner{h0}}, InterfacePointer{messagePipeHandleOwner{h1}}
+}
diff --git a/third_party/mojo/src/mojo/public/go/bindings/message.go b/third_party/mojo/src/mojo/public/go/bindings/message.go
index 786ec47..e5c8329 100644
--- a/third_party/mojo/src/mojo/public/go/bindings/message.go
+++ b/third_party/mojo/src/mojo/public/go/bindings/message.go
@@ -40,8 +40,8 @@ type Payload interface {
// DataHeader is a header for a mojo complex element.
type DataHeader struct {
- Size uint32
- Elements uint32
+ Size uint32
+ ElementsOrVersion uint32
}
// MessageHeader is a header information for a message.
diff --git a/third_party/mojo/src/mojo/public/interfaces/application/application.mojom b/third_party/mojo/src/mojo/public/interfaces/application/application.mojom
index cffcb1f..03fe943 100644
--- a/third_party/mojo/src/mojo/public/interfaces/application/application.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/application/application.mojom
@@ -13,8 +13,9 @@ import "mojo/public/interfaces/application/shell.mojom";
interface Application {
// Initializes the application with the specified arguments. This method is
// guaranteed to be called before any other method is called, and will only be
- // called once.
- Initialize(Shell shell, array<string>? args);
+ // called once. The |url| parameter is the final url the application was found
+ // at, after all redirects and resolutions.
+ Initialize(Shell shell, array<string>? args, string url);
// Called when another application (identified by |requestor_url|) attempts to
// open a connection to this application.
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
index f68b113..dabc3f6 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -11,7 +11,6 @@ mojom("test_interfaces") {
"no_module.mojom",
"rect.mojom",
"regression_tests.mojom",
- "regression_tests_import.mojom",
"sample_factory.mojom",
"sample_import.mojom",
"sample_import2.mojom",
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_good.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_good.data
index 9a983a7..c0be013 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_good.data
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_good.data
@@ -8,7 +8,6 @@
[u4]2 // num_fields
[dist8]param0_ptr // param0
[dist8]param1_ptr // param1
-[u8]0 // unknown
[anchr]method7_params
[anchr]param0_ptr
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_good.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_good.data
index f4b6c40..0ee26af 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_good.data
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_good.data
@@ -1,7 +1,7 @@
[dist4]message_header // num_bytes
[u4]3 // num_fields
[u4]0 // name
-[u4]2 // flags: Is response.
+[u4]2 // flags kMessageIsResponse
[u8]1 // request_id
[anchr]message_header
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_good.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_good.expected
index 7ef22e9..7ef22e9 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_good.expected
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_good.expected
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_unexpected_array_header.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_unexpected_array_header.data
index a357013..25540b1 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_unexpected_array_header.data
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_unexpected_array_header.data
@@ -1,7 +1,7 @@
[dist4]message_header // num_bytes
[u4]3 // num_fields
[u4]0 // name
-[u4]2 // flags: Is response.
+[u4]2 // flags kMessageIsResponse
[u8]1 // request_id
[anchr]message_header
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_unexpected_array_header.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_unexpected_array_header.expected
index 5a1ec4e..5a1ec4e 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_unexpected_array_header.expected
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_unexpected_array_header.expected
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_good.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_good.data
index df7b7e8..c57d4bd 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_good.data
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_good.data
@@ -1,7 +1,8 @@
[dist4]message_header // num_bytes
-[u4]2 // num_fields
+[u4]3 // num_fields
[u4]0 // name
-[u4]0 // flags
+[u4]1 // flags kMessageExpectsResponse
+[u8]7 // request_id
[anchr]message_header
[dist4]method0_params // num_bytes
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_good.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_good.expected
index 7ef22e9..7ef22e9 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf2_mthd0_resp_good.expected
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_good.expected
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_unexpected_struct_header.data b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_unexpected_struct_header.data
index 3dcca9d..8b6bd2d 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_unexpected_struct_header.data
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_unexpected_struct_header.data
@@ -1,7 +1,8 @@
[dist4]message_header // num_bytes
-[u4]2 // num_fields
+[u4]3 // num_fields
[u4]0 // name
-[u4]0 // flags
+[u4]1 // flags kMessageExpectsResponse
+[u8]7 // request_id
[anchr]message_header
[dist4]method0_params // num_bytes
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_unexpected_struct_header.expected b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_unexpected_struct_header.expected
index 25aceee..25aceee 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf1_mthd0_rqst_unexpected_struct_header.expected
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_unexpected_struct_header.expected
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests.mojom
index 4a85b0a..313f1f4 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests.mojom
@@ -7,8 +7,6 @@
[JavaPackage="org.chromium.mojo.bindings.test.mojom.regression_tests"]
module regression_tests;
-import "regression_tests_import.mojom";
-
interface CheckMethodWithEmptyResponse {
WithouParameterAndEmptyResponse() => ();
WithParameterAndEmptyResponse(bool b) => ();
@@ -54,7 +52,3 @@ struct A {
struct B {
A? a;
};
-
-[Client=InterfaceWithClientImportedClient]
-interface InterfaceWithClientImported {
-};
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests_import.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests_import.mojom
deleted file mode 100644
index fbed983..0000000
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/regression_tests_import.mojom
+++ /dev/null
@@ -1,11 +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.
-
-// Module containing entities for regression tests of the generator. Entities
-// must never be modified, instead new entity must be added to add new tests.
-[JavaPackage="org.chromium.mojo.bindings.test.mojom.regression_tests_import"]
-module regression_tests_import;
-
-interface InterfaceWithClientImportedClient {
-};
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_factory.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_factory.mojom
index eb5d930..ade3bf3 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_factory.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_factory.mojom
@@ -29,18 +29,13 @@ interface NamedObject {
GetName() => (string name);
};
-[Client=FactoryClient]
interface Factory {
- DoStuff(Request request, handle<message_pipe>? pipe);
- DoStuff2(handle<data_pipe_consumer> pipe);
+ DoStuff(Request request, handle<message_pipe>? pipe) =>
+ (Response response, string text);
+ DoStuff2(handle<data_pipe_consumer> pipe) => (string text);
CreateNamedObject(NamedObject& obj);
RequestImportedInterface(
imported.ImportedInterface& obj) => (imported.ImportedInterface& obj);
TakeImportedInterface(
imported.ImportedInterface obj) => (imported.ImportedInterface obj);
};
-
-interface FactoryClient {
- DidStuff(Response response, string text);
- DidStuff2(string text);
-};
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
index 37405ca..52589a9 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom
@@ -13,14 +13,9 @@ enum Enum {
VALUE
};
-[Client=ProviderClient]
interface Provider {
EchoString(string a) => (string a);
EchoStrings(string a, string b) => (string a, string b);
EchoMessagePipeHandle(handle<message_pipe> a) => (handle<message_pipe> a);
EchoEnum(Enum a) => (Enum a);
};
-
-// TODO(darin): We shouldn't need this, but JS bindings don't work without it.
-interface ProviderClient {
-};
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_service.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_service.mojom
index 5c80781..700481c 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_service.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/sample_service.mojom
@@ -104,21 +104,16 @@ struct StructWithHoleV2 {
int32 v3 = 3;
};
-[Client=ServiceClient]
interface Service {
enum BazOptions {
REGULAR = 0,
EXTRA
};
const uint8 kFavoriteBaz = 1;
- Frobinate@0(Foo? foo@0, BazOptions baz@1, Port? port@2);
+ Frobinate@0(Foo? foo@0, BazOptions baz@1, Port? port@2) => (int32 result@0);
GetPort@1(Port& port @0);
};
-interface ServiceClient {
- DidFrobinate@0(int32 result@0);
-};
-
// This interface is referenced above where it is defined. It also refers to
// itself from a method.
interface Port {
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
index dc4f05e..97ce3a3 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
@@ -283,3 +283,69 @@ struct BitArrayValues {
array<array<bool>?> f5;
array<array<bool, 2>?> f6;
};
+
+// Used to verify that different versions can be decoded correctly.
+
+struct MultiVersionStruct {
+ [MinVersion=0]
+ int32 f_int32;
+ [MinVersion=1]
+ Rect? f_rect;
+ [MinVersion=3]
+ string? f_string;
+ [MinVersion=5]
+ array<int8> f_array;
+ [MinVersion=7]
+ handle<message_pipe>? f_message_pipe;
+ [MinVersion=7]
+ bool f_bool;
+ [MinVersion=9]
+ int16 f_int16;
+};
+
+struct MultiVersionStructV0 {
+ [MinVersion=0]
+ int32 f_int32;
+};
+
+struct MultiVersionStructV1 {
+ [MinVersion=0]
+ int32 f_int32;
+ [MinVersion=1]
+ Rect? f_rect;
+};
+
+struct MultiVersionStructV3 {
+ [MinVersion=0]
+ int32 f_int32;
+ [MinVersion=1]
+ Rect? f_rect;
+ [MinVersion=3]
+ string? f_string;
+};
+
+struct MultiVersionStructV5 {
+ [MinVersion=0]
+ int32 f_int32;
+ [MinVersion=1]
+ Rect? f_rect;
+ [MinVersion=3]
+ string? f_string;
+ [MinVersion=5]
+ array<int8> f_array;
+};
+
+struct MultiVersionStructV7 {
+ [MinVersion=0]
+ int32 f_int32;
+ [MinVersion=1]
+ Rect? f_rect;
+ [MinVersion=3]
+ string? f_string;
+ [MinVersion=5]
+ array<int8> f_array;
+ [MinVersion=7]
+ handle<message_pipe>? f_message_pipe;
+ [MinVersion=7]
+ bool f_bool;
+};
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
index 290b792..fb1f4b7 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
@@ -49,12 +49,6 @@ struct BasicStruct {
int32 a;
};
-[Client=IntegrationTestInterface2]
-interface IntegrationTestInterface1 {
- Method0(BasicStruct param0);
-};
-
-[Client=IntegrationTestInterface1]
-interface IntegrationTestInterface2 {
- Method0() => (array<uint8> param0);
+interface IntegrationTestInterface {
+ Method0(BasicStruct param0) => (array<uint8> param0);
};
diff --git a/third_party/mojo/src/mojo/public/java/BUILD.gn b/third_party/mojo/src/mojo/public/java/BUILD.gn
index 04d2ef6..edfd9a0 100644
--- a/third_party/mojo/src/mojo/public/java/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/java/BUILD.gn
@@ -18,6 +18,7 @@ android_library("system") {
"system/src/org/chromium/mojo/system/Pair.java",
"system/src/org/chromium/mojo/system/SharedBufferHandle.java",
"system/src/org/chromium/mojo/system/UntypedHandle.java",
+ "system/src/org/chromium/mojo/system/RunLoop.java",
]
}
@@ -36,7 +37,6 @@ android_library("bindings") {
"bindings/src/org/chromium/mojo/bindings/HandleOwner.java",
"bindings/src/org/chromium/mojo/bindings/Interface.java",
"bindings/src/org/chromium/mojo/bindings/InterfaceRequest.java",
- "bindings/src/org/chromium/mojo/bindings/InterfaceWithClient.java",
"bindings/src/org/chromium/mojo/bindings/MessageHeader.java",
"bindings/src/org/chromium/mojo/bindings/Message.java",
"bindings/src/org/chromium/mojo/bindings/MessageReceiver.java",
diff --git a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java
index b95b6dd..fa1eb23 100644
--- a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java
+++ b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java
@@ -120,22 +120,47 @@ public class Decoder {
// Claim the memory for the header.
mValidator.claimMemory(mBaseOffset, mBaseOffset + DataHeader.HEADER_SIZE);
int size = readInt(DataHeader.SIZE_OFFSET);
- int numFields = readInt(DataHeader.NUM_FIELDS_OFFSET);
+ int elementsOrVersion = readInt(DataHeader.ELEMENTS_OR_VERSION_OFFSET);
if (size < 0) {
throw new DeserializationException(
"Negative size. Unsigned integers are not valid for java.");
}
- if (numFields < 0) {
+ if (elementsOrVersion < 0) {
throw new DeserializationException(
- "Negative number of fields. Unsigned integers are not valid for java.");
+ "Negative elements or version. Unsigned integers are not valid for java.");
}
// Claim the remaining memory.
mValidator.claimMemory(mBaseOffset + DataHeader.HEADER_SIZE, mBaseOffset + size);
- DataHeader res = new DataHeader(size, numFields);
+ DataHeader res = new DataHeader(size, elementsOrVersion);
return res;
}
+ public DataHeader readAndValidateDataHeader(DataHeader[] versionArray) {
+ DataHeader header = readDataHeader();
+ int maxVersionIndex = versionArray.length - 1;
+ if (header.elementsOrVersion <= versionArray[maxVersionIndex].elementsOrVersion) {
+ DataHeader referenceHeader = null;
+ for (int index = maxVersionIndex; index >= 0; index--) {
+ DataHeader dataHeader = versionArray[index];
+ if (header.elementsOrVersion >= dataHeader.elementsOrVersion) {
+ referenceHeader = dataHeader;
+ break;
+ }
+ }
+ if (referenceHeader == null || referenceHeader.size != header.size) {
+ throw new DeserializationException(
+ "Header doesn't correspond to any known version.");
+ }
+ } else {
+ if (header.size < versionArray[maxVersionIndex].size) {
+ throw new DeserializationException("Message newer than the last known version"
+ + " cannot be shorter than required by the last known version.");
+ }
+ }
+ return header;
+ }
+
/**
* Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
* array where element have the given size.
@@ -153,9 +178,9 @@ public class Decoder {
throw new DeserializationException(
"Incorrect header for map. The size is incorrect.");
}
- if (si.numFields != BindingsHelper.MAP_STRUCT_HEADER.numFields) {
+ if (si.elementsOrVersion != BindingsHelper.MAP_STRUCT_HEADER.elementsOrVersion) {
throw new DeserializationException(
- "Incorrect header for map. The number of fields is incorrect.");
+ "Incorrect header for map. The version is incorrect.");
}
}
@@ -244,10 +269,10 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForBooleanArray(expectedLength);
- byte[] bytes = new byte[(si.numFields + 7) / BindingsHelper.ALIGNMENT];
+ byte[] bytes = new byte[(si.elementsOrVersion + 7) / BindingsHelper.ALIGNMENT];
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
d.mMessage.getData().get(bytes);
- boolean[] result = new boolean[si.numFields];
+ boolean[] result = new boolean[si.elementsOrVersion];
for (int i = 0; i < bytes.length; ++i) {
for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) {
int booleanIndex = i * BindingsHelper.ALIGNMENT + j;
@@ -268,7 +293,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(1, expectedLength);
- byte[] result = new byte[si.numFields];
+ byte[] result = new byte[si.elementsOrVersion];
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
d.mMessage.getData().get(result);
return result;
@@ -283,7 +308,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(2, expectedLength);
- short[] result = new short[si.numFields];
+ short[] result = new short[si.elementsOrVersion];
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
d.mMessage.getData().asShortBuffer().get(result);
return result;
@@ -298,7 +323,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- int[] result = new int[si.numFields];
+ int[] result = new int[si.elementsOrVersion];
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
d.mMessage.getData().asIntBuffer().get(result);
return result;
@@ -313,7 +338,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- float[] result = new float[si.numFields];
+ float[] result = new float[si.elementsOrVersion];
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
d.mMessage.getData().asFloatBuffer().get(result);
return result;
@@ -328,7 +353,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(8, expectedLength);
- long[] result = new long[si.numFields];
+ long[] result = new long[si.elementsOrVersion];
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
d.mMessage.getData().asLongBuffer().get(result);
return result;
@@ -343,7 +368,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(8, expectedLength);
- double[] result = new double[si.numFields];
+ double[] result = new double[si.elementsOrVersion];
d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
d.mMessage.getData().asDoubleBuffer().get(result);
return result;
@@ -447,7 +472,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- Handle[] result = new Handle[si.numFields];
+ Handle[] result = new Handle[si.elementsOrVersion];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readHandle(
DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
@@ -466,7 +491,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- UntypedHandle[] result = new UntypedHandle[si.numFields];
+ UntypedHandle[] result = new UntypedHandle[si.elementsOrVersion];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readUntypedHandle(
DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
@@ -485,7 +510,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- DataPipe.ConsumerHandle[] result = new DataPipe.ConsumerHandle[si.numFields];
+ DataPipe.ConsumerHandle[] result = new DataPipe.ConsumerHandle[si.elementsOrVersion];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readConsumerHandle(
DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
@@ -504,7 +529,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- DataPipe.ProducerHandle[] result = new DataPipe.ProducerHandle[si.numFields];
+ DataPipe.ProducerHandle[] result = new DataPipe.ProducerHandle[si.elementsOrVersion];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readProducerHandle(
DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
@@ -524,7 +549,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- MessagePipeHandle[] result = new MessagePipeHandle[si.numFields];
+ MessagePipeHandle[] result = new MessagePipeHandle[si.elementsOrVersion];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readMessagePipeHandle(
DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
@@ -544,7 +569,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- SharedBufferHandle[] result = new SharedBufferHandle[si.numFields];
+ SharedBufferHandle[] result = new SharedBufferHandle[si.elementsOrVersion];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readSharedBufferHandle(
DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
@@ -564,7 +589,7 @@ public class Decoder {
return null;
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
- S[] result = manager.buildArray(si.numFields);
+ S[] result = manager.buildArray(si.elementsOrVersion);
for (int i = 0; i < result.length; ++i) {
// This cast is necessary because java 6 doesn't handle wildcard correctly when using
// Manager<S, ? extends S>
@@ -588,7 +613,7 @@ public class Decoder {
}
DataHeader si = d.readDataHeaderForArray(4, expectedLength);
@SuppressWarnings("unchecked")
- InterfaceRequest<I>[] result = new InterfaceRequest[si.numFields];
+ InterfaceRequest<I>[] result = new InterfaceRequest[si.elementsOrVersion];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readInterfaceRequest(
DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
@@ -610,13 +635,13 @@ public class Decoder {
*/
private DataHeader readDataHeaderForBooleanArray(int expectedLength) {
DataHeader dataHeader = readDataHeader();
- if (dataHeader.size < DataHeader.HEADER_SIZE + (dataHeader.numFields + 7) / 8) {
+ if (dataHeader.size < DataHeader.HEADER_SIZE + (dataHeader.elementsOrVersion + 7) / 8) {
throw new DeserializationException("Array header is incorrect.");
}
if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
- && dataHeader.numFields != expectedLength) {
- throw new DeserializationException("Incorrect array length. Expected: "
- + expectedLength + ", but got: " + dataHeader.numFields + ".");
+ && dataHeader.elementsOrVersion != expectedLength) {
+ throw new DeserializationException("Incorrect array length. Expected: " + expectedLength
+ + ", but got: " + dataHeader.elementsOrVersion + ".");
}
return dataHeader;
}
@@ -626,13 +651,14 @@ public class Decoder {
*/
private DataHeader readDataHeaderForArray(long elementSize, int expectedLength) {
DataHeader dataHeader = readDataHeader();
- if (dataHeader.size < (DataHeader.HEADER_SIZE + elementSize * dataHeader.numFields)) {
+ if (dataHeader.size
+ < (DataHeader.HEADER_SIZE + elementSize * dataHeader.elementsOrVersion)) {
throw new DeserializationException("Array header is incorrect.");
}
if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
- && dataHeader.numFields != expectedLength) {
- throw new DeserializationException("Incorrect array length. Expected: "
- + expectedLength + ", but got: " + dataHeader.numFields + ".");
+ && dataHeader.elementsOrVersion != expectedLength) {
+ throw new DeserializationException("Incorrect array length. Expected: " + expectedLength
+ + ", but got: " + dataHeader.elementsOrVersion + ".");
}
return dataHeader;
}
diff --git a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java
index 75cddc9..0f85232 100644
--- a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java
+++ b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java
@@ -150,7 +150,7 @@ public class Encoder {
public void encode(DataHeader s) {
mEncoderState.claimMemory(BindingsHelper.align(s.size));
encode(s.size, DataHeader.SIZE_OFFSET);
- encode(s.numFields, DataHeader.NUM_FIELDS_OFFSET);
+ encode(s.elementsOrVersion, DataHeader.ELEMENTS_OR_VERSION_OFFSET);
}
/**
diff --git a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/InterfaceWithClient.java b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/InterfaceWithClient.java
deleted file mode 100644
index f7d8afe..0000000
--- a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/InterfaceWithClient.java
+++ /dev/null
@@ -1,115 +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.
-
-package org.chromium.mojo.bindings;
-
-import org.chromium.mojo.system.Core;
-import org.chromium.mojo.system.MessagePipeHandle;
-import org.chromium.mojo.system.Pair;
-
-/**
- * Base class for mojo generated interfaces that have a client.
- *
- * @param <CI> the type of the client interface.
- */
-public interface InterfaceWithClient<CI extends Interface> extends Interface {
-
- /**
- * Proxy class for interfaces with a client.
- */
- interface Proxy<CI extends Interface> extends Interface.Proxy, InterfaceWithClient<CI> {
- }
-
- /**
- * Base implementation of Proxy.
- *
- * @param <CI> the type of the client interface.
- */
- abstract class AbstractProxy<CI extends Interface> extends Interface.AbstractProxy
- implements Proxy<CI> {
-
- /**
- * Constructor.
- *
- * @param core the Core implementation used to create pipes and access the async waiter.
- * @param messageReceiver the message receiver to send message to.
- */
- public AbstractProxy(Core core, MessageReceiverWithResponder messageReceiver) {
- super(core, messageReceiver);
- }
-
- /**
- * @see InterfaceWithClient#setClient(Interface)
- */
- @Override
- public void setClient(CI client) {
- throw new UnsupportedOperationException(
- "Setting the client on a proxy is not supported");
- }
- }
-
- /**
- * Base manager implementation for interfaces that have a client.
- *
- * @param <I> the type of the interface the manager can handle.
- * @param <P> the type of the proxy the manager can handle. To be noted, P always extends I.
- * @param <CI> the type of the client interface.
- */
- abstract class Manager<I extends InterfaceWithClient<CI>, P extends Proxy<CI>,
- CI extends Interface> extends Interface.Manager<I, P> {
-
- /**
- * @see Interface.Manager#bind(Interface, MessagePipeHandle)
- */
- @Override
- public final void bind(I impl, MessagePipeHandle handle) {
- Router router = new RouterImpl(handle);
- super.bind(handle.getCore(), impl, router);
- @SuppressWarnings("unchecked")
- CI client = (CI) getClientManager().attachProxy(handle.getCore(), router);
- impl.setClient(client);
- router.start();
- }
-
- /**
- * Returns a Proxy that will send messages to the given |handle|. This implies that the
- * other end of the handle must be connected to an implementation of the interface. |client|
- * is the implementation of the client interface.
- */
- public P attachProxy(MessagePipeHandle handle, CI client) {
- Router router = new RouterImpl(handle);
- DelegatingConnectionErrorHandler handlers = new DelegatingConnectionErrorHandler();
- handlers.addConnectionErrorHandler(client);
- router.setErrorHandler(handlers);
- getClientManager().bind(handle.getCore(), client, router);
- P proxy = super.attachProxy(handle.getCore(), router);
- handlers.addConnectionErrorHandler(proxy);
- router.start();
- return proxy;
- }
-
- /**
- * Constructs a new |InterfaceRequest| for the interface. This method returns a Pair where
- * the first element is a proxy, and the second element is the request. The proxy can be
- * used immediately.
- *
- * @param client the implementation of the client interface.
- */
- public final Pair<P, InterfaceRequest<I>> getInterfaceRequest(Core core, CI client) {
- Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe(null);
- P proxy = attachProxy(handles.first, client);
- return Pair.create(proxy, new InterfaceRequest<I>(handles.second));
- }
-
- /**
- * Returns a manager for the client inetrafce.
- */
- protected abstract Interface.Manager<CI, ?> getClientManager();
- }
-
- /**
- * Set the client implementation for this interface.
- */
- public void setClient(CI client);
-}
diff --git a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageHeader.java b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageHeader.java
index dcaf86c..34f3d14 100644
--- a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageHeader.java
+++ b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageHeader.java
@@ -14,14 +14,14 @@ import java.nio.ByteBuffer;
public class MessageHeader {
private static final int SIMPLE_MESSAGE_SIZE = 16;
- private static final int SIMPLE_MESSAGE_NUM_FIELDS = 2;
+ private static final int SIMPLE_MESSAGE_VERSION = 2;
private static final DataHeader SIMPLE_MESSAGE_STRUCT_INFO =
- new DataHeader(SIMPLE_MESSAGE_SIZE, SIMPLE_MESSAGE_NUM_FIELDS);
+ new DataHeader(SIMPLE_MESSAGE_SIZE, SIMPLE_MESSAGE_VERSION);
private static final int MESSAGE_WITH_REQUEST_ID_SIZE = 24;
- private static final int MESSAGE_WITH_REQUEST_ID_NUM_FIELDS = 3;
+ private static final int MESSAGE_WITH_REQUEST_ID_VERSION = 3;
private static final DataHeader MESSAGE_WITH_REQUEST_ID_STRUCT_INFO =
- new DataHeader(MESSAGE_WITH_REQUEST_ID_SIZE, MESSAGE_WITH_REQUEST_ID_NUM_FIELDS);
+ new DataHeader(MESSAGE_WITH_REQUEST_ID_SIZE, MESSAGE_WITH_REQUEST_ID_VERSION);
private static final int TYPE_OFFSET = 8;
private static final int FLAGS_OFFSET = 12;
@@ -216,28 +216,25 @@ public class MessageHeader {
* Validate that the given {@link DataHeader} can be the data header of a message header.
*/
private static void validateDataHeader(DataHeader dataHeader) {
- if (dataHeader.numFields < SIMPLE_MESSAGE_NUM_FIELDS) {
- throw new DeserializationException(
- "Incorrect number of fields, expecting at least " + SIMPLE_MESSAGE_NUM_FIELDS
- + ", but got: " + dataHeader.numFields);
+ if (dataHeader.elementsOrVersion < SIMPLE_MESSAGE_VERSION) {
+ throw new DeserializationException("Incorrect number of fields, expecting at least "
+ + SIMPLE_MESSAGE_VERSION + ", but got: " + dataHeader.elementsOrVersion);
}
if (dataHeader.size < SIMPLE_MESSAGE_SIZE) {
throw new DeserializationException(
"Incorrect message size, expecting at least " + SIMPLE_MESSAGE_SIZE
+ ", but got: " + dataHeader.size);
}
- if (dataHeader.numFields == SIMPLE_MESSAGE_NUM_FIELDS
+ if (dataHeader.elementsOrVersion == SIMPLE_MESSAGE_VERSION
&& dataHeader.size != SIMPLE_MESSAGE_SIZE) {
- throw new DeserializationException(
- "Incorrect message size for a message with " + SIMPLE_MESSAGE_NUM_FIELDS
- + " fields, expecting " + SIMPLE_MESSAGE_SIZE + ", but got: "
- + dataHeader.size);
+ throw new DeserializationException("Incorrect message size for a message with "
+ + SIMPLE_MESSAGE_VERSION + " fields, expecting " + SIMPLE_MESSAGE_SIZE
+ + ", but got: " + dataHeader.size);
}
- if (dataHeader.numFields == MESSAGE_WITH_REQUEST_ID_NUM_FIELDS
+ if (dataHeader.elementsOrVersion == MESSAGE_WITH_REQUEST_ID_VERSION
&& dataHeader.size != MESSAGE_WITH_REQUEST_ID_SIZE) {
- throw new DeserializationException(
- "Incorrect message size for a message with "
- + MESSAGE_WITH_REQUEST_ID_NUM_FIELDS + " fields, expecting "
+ throw new DeserializationException("Incorrect message size for a message with "
+ + MESSAGE_WITH_REQUEST_ID_VERSION + " fields, expecting "
+ MESSAGE_WITH_REQUEST_ID_SIZE + ", but got: " + dataHeader.size);
}
}
diff --git a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Struct.java b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Struct.java
index 017d0ef..d7369fa 100644
--- a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Struct.java
+++ b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Struct.java
@@ -15,7 +15,6 @@ public abstract class Struct {
* The header for a mojo complex element.
*/
public static final class DataHeader {
-
/**
* The size of a serialized header, in bytes.
*/
@@ -29,18 +28,26 @@ public abstract class Struct {
/**
* The offset of the number of fields field.
*/
- public static final int NUM_FIELDS_OFFSET = 4;
+ public static final int ELEMENTS_OR_VERSION_OFFSET = 4;
+ /**
+ * The size of the object owning this header.
+ */
public final int size;
- public final int numFields;
+
+ /**
+ * Number of element (for an array) or version (for a struct) of the object owning this
+ * header.
+ */
+ public final int elementsOrVersion;
/**
* Constructor.
*/
- public DataHeader(int size, int numFields) {
+ public DataHeader(int size, int elementsOrVersion) {
super();
this.size = size;
- this.numFields = numFields;
+ this.elementsOrVersion = elementsOrVersion;
}
/**
@@ -50,7 +57,7 @@ public abstract class Struct {
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + numFields;
+ result = prime * result + elementsOrVersion;
result = prime * result + size;
return result;
}
@@ -68,8 +75,7 @@ public abstract class Struct {
return false;
DataHeader other = (DataHeader) object;
- return (numFields == other.numFields &&
- size == other.size);
+ return (elementsOrVersion == other.elementsOrVersion && size == other.size);
}
}
diff --git a/third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/Core.java b/third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
index 660a13f..ba0e5c6 100644
--- a/third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
+++ b/third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/Core.java
@@ -309,4 +309,13 @@ public interface Core {
*/
public AsyncWaiter getDefaultAsyncWaiter();
+ /**
+ * Returns a new run loop.
+ */
+ public RunLoop createDefaultRunLoop();
+
+ /**
+ * Returns the current run loop if it exists.
+ */
+ public RunLoop getCurrentRunLoop();
}
diff --git a/third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/RunLoop.java b/third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/RunLoop.java
new file mode 100644
index 0000000..4038b295
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/java/system/src/org/chromium/mojo/system/RunLoop.java
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.mojo.system;
+
+import java.io.Closeable;
+
+/**
+ * Definition of a run loop.
+ */
+public interface RunLoop extends Closeable {
+ /**
+ * Start the run loop. It will continue until quit() is called.
+ */
+ public void run();
+
+ /**
+ * Start the run loop and stop it as soon as no task is present in the work queue.
+ */
+ public void runUntilIdle();
+
+ /*
+ * Quit the currently running run loop.
+ */
+ public void quit();
+
+ /**
+ * Add a runnable to the queue of tasks.
+ * @param runnable Callback to be executed by the run loop.
+ * @param delay Delay, in MojoTimeTicks (microseconds) before the callback should
+ * be executed.
+ */
+ public void postDelayedTask(Runnable runnable, long delay);
+
+ /**
+ * Destroy the run loop and deregister it from Core.
+ */
+ @Override
+ public abstract void close();
+}
diff --git a/third_party/mojo/src/mojo/public/js/connection.js b/third_party/mojo/src/mojo/public/js/connection.js
index 4a7a8b8..62e8798 100644
--- a/third_party/mojo/src/mojo/public/js/connection.js
+++ b/third_party/mojo/src/mojo/public/js/connection.js
@@ -73,52 +73,6 @@ define("mojo/public/js/connection", [
TestConnection.prototype = Object.create(Connection.prototype);
- // TODO(hansmuller): remove when Shell.mojom loses its client.
- function createOpenConnection(
- messagePipeHandle, client, localInterface, remoteInterface) {
- var stubClass = (localInterface && localInterface.stubClass) || EmptyStub;
- var proxyClass =
- (remoteInterface && remoteInterface.proxyClass) || EmptyProxy;
- var proxy = new proxyClass;
- var stub = new stubClass;
- var router = new Router(messagePipeHandle);
- var connection = new BaseConnection(stub, proxy, router);
-
- ProxyBindings(proxy).connection = connection;
- ProxyBindings(proxy).local = connection.local;
- StubBindings(stub).connection = connection;
- StubBindings(proxy).remote = connection.remote;
-
- var clientImpl = client instanceof Function ? client(proxy) : client;
- if (clientImpl)
- StubBindings(stub).delegate = clientImpl;
-
- return connection;
- }
-
- // TODO(hansmuller): remove when Shell.mojom loses its client.
- // Return a message pipe handle.
- function bindProxyClient(clientImpl, localInterface, remoteInterface) {
- var messagePipe = core.createMessagePipe();
- if (messagePipe.result != core.RESULT_OK)
- throw new Error("createMessagePipe failed " + messagePipe.result);
-
- createOpenConnection(
- messagePipe.handle0, clientImpl, localInterface, remoteInterface);
- return messagePipe.handle1;
- }
-
- // TODO(hansmuller): remove when Shell.mojom loses its client.
- // Return a proxy.
- function bindProxyHandle(proxyHandle, localInterface, remoteInterface) {
- if (!core.isHandle(proxyHandle))
- throw new Error("Not a handle " + proxyHandle);
-
- var connection = createOpenConnection(
- proxyHandle, undefined, localInterface, remoteInterface);
- return connection.remote;
- }
-
// Return a handle for a message pipe that's connected to a proxy
// for remoteInterface. Used by generated code for outgoing interface&
// (request) parameters: the caller is given the generated proxy via
@@ -193,10 +147,6 @@ define("mojo/public/js/connection", [
exports.Connection = Connection;
exports.TestConnection = TestConnection;
- // TODO(hansmuller): remove these when Shell.mojom loses its client.
- exports.bindProxyHandle = bindProxyHandle;
- exports.bindProxyClient = bindProxyClient;
-
exports.bindProxy = bindProxy;
exports.bindImpl = bindImpl;
exports.bindHandleToProxy = bindHandleToProxy;
diff --git a/third_party/mojo/src/mojo/public/js/validation_unittests.js b/third_party/mojo/src/mojo/public/js/validation_unittests.js
index 05988f3..8a1f385 100644
--- a/third_party/mojo/src/mojo/public/js/validation_unittests.js
+++ b/third_party/mojo/src/mojo/public/js/validation_unittests.js
@@ -254,8 +254,8 @@ define([
testInterface.ConformanceTestInterface.validateRequest]);
}
- function testIntegratedMessageValidation() {
- var testFiles = getMessageTestFiles("integration_");
+ function testIntegratedMessageValidation(testFilesPattern) {
+ var testFiles = getMessageTestFiles(testFilesPattern);
expect(testFiles.length).toBeGreaterThan(0);
for (var i = 0; i < testFiles.length; i++) {
@@ -279,8 +279,8 @@ define([
var testConnection = new connection.TestConnection(
testMessagePipe.handle1,
- testInterface.IntegrationTestInterface1.stubClass,
- testInterface.IntegrationTestInterface2.proxyClass);
+ testInterface.IntegrationTestInterface.stubClass,
+ testInterface.IntegrationTestInterface.proxyClass);
var validationError = noError;
testConnection.router_.validationErrorHandler = function(err) {
@@ -295,8 +295,22 @@ define([
}
}
+ function testIntegratedMessageHeaderValidation() {
+ testIntegratedMessageValidation("integration_msghdr");
+ }
+
+ function testIntegratedRequestMessageValidation() {
+ testIntegratedMessageValidation("integration_intf_rqst");
+ }
+
+ function testIntegratedResponseMessageValidation() {
+ testIntegratedMessageValidation("integration_intf_resp");
+ }
+
expect(checkTestMessageParser()).toBeNull();
testConformanceMessageValidation();
- testIntegratedMessageValidation();
+ testIntegratedMessageHeaderValidation();
+ testIntegratedResponseMessageValidation();
+ testIntegratedRequestMessageValidation();
this.result = "PASS";
});
diff --git a/third_party/mojo/src/mojo/public/mojo.gni b/third_party/mojo/src/mojo/public/mojo.gni
index 9f1b86b..bc90a23 100644
--- a/third_party/mojo/src/mojo/public/mojo.gni
+++ b/third_party/mojo/src/mojo/public/mojo.gni
@@ -6,10 +6,19 @@ import("//build/module_args/mojo.gni")
# If using the prebuilt shell, gate its usage by the platforms for which it is
# published.
-if (!defined(use_prebuilt_mojo_shell) || use_prebuilt_mojo_shell) {
+use_prebuilt_mojo_shell = false
+if (!defined(build_mojo_shell_from_source) || !build_mojo_shell_from_source) {
use_prebuilt_mojo_shell = is_linux || is_android
}
+# If using the prebuilt network service, gate its usage by the platforms for
+# which it is published.
+use_prebuilt_network_service = false
+if (!defined(build_network_service_from_source) ||
+ !build_network_service_from_source) {
+ use_prebuilt_network_service = is_linux || is_android
+}
+
# The absolute path to the directory containing the mojo public SDK (i.e., the
# directory containing mojo/public). The build files within the Mojo public
# SDK use this variable to allow themselves to be parameterized by the location
diff --git a/third_party/mojo/src/mojo/public/mojo_application.gni b/third_party/mojo/src/mojo/public/mojo_application.gni
index 7661c88..77ed4bb 100644
--- a/third_party/mojo/src/mojo/public/mojo_application.gni
+++ b/third_party/mojo/src/mojo/public/mojo_application.gni
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/module_args/mojo.gni")
import("mojo.gni")
import("mojo_sdk.gni")
@@ -68,22 +69,22 @@ template("mojo_native_application") {
libs = invoker.libs
}
- if (use_prebuilt_mojo_shell) {
- copy_mojo_shell =
- rebase_path("mojo/public/tools:copy_mojo_shell", ".", mojo_root)
- }
-
- # Copy the prebuilt mojo_shell if using it.
+ data_deps = []
if (defined(invoker.data_deps)) {
data_deps = invoker.data_deps
- if (use_prebuilt_mojo_shell) {
- data_deps += [ copy_mojo_shell ]
- }
- } else {
- if (use_prebuilt_mojo_shell) {
- data_deps = [ copy_mojo_shell ]
- }
}
+
+ # Copy any necessary prebuilt artifacts.
+ if (use_prebuilt_mojo_shell) {
+ data_deps +=
+ [ rebase_path("mojo/public/tools:copy_mojo_shell", ".", mojo_root) ]
+ }
+ if (use_prebuilt_network_service) {
+ data_deps += [ rebase_path("mojo/public/tools:copy_network_service",
+ ".",
+ mojo_root) ]
+ }
+
deps = rebase_path([
"mojo/public/c/system",
"mojo/public/platform/native:system",
diff --git a/third_party/mojo/src/mojo/public/python/BUILD.gn b/third_party/mojo/src/mojo/public/python/BUILD.gn
index f4b0b03..d2e13c2 100644
--- a/third_party/mojo/src/mojo/public/python/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/python/BUILD.gn
@@ -78,6 +78,16 @@ python_binary_source_set("python_common") {
]
}
+python_package("packaged_application") {
+ sources = [
+ "mojo_application/__init__.py",
+ "mojo_application/application_delegate.py",
+ "mojo_application/application_impl.py",
+ "mojo_application/application_runner.py",
+ "mojo_application/service_provider_impl.py",
+ ]
+}
+
# GYP version: mojo.gyp:mojo_python_bindings
copy("bindings") {
sources = [
diff --git a/third_party/mojo/src/mojo/public/python/mojo_application/__init__.py b/third_party/mojo/src/mojo/public/python/mojo_application/__init__.py
new file mode 100644
index 0000000..50b23df
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/python/mojo_application/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/third_party/mojo/src/mojo/public/python/mojo_application/application_delegate.py b/third_party/mojo/src/mojo/public/python/mojo_application/application_delegate.py
new file mode 100644
index 0000000..c4a817d
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/python/mojo_application/application_delegate.py
@@ -0,0 +1,27 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Interface for the delegate of ApplicationImpl."""
+
+import mojo_application.application_impl
+import mojo_application.service_provider_impl
+import shell_mojom
+
+import mojo_system
+
+# pylint: disable=unused-argument
+class ApplicationDelegate:
+ def Initialize(self, shell, application):
+ """
+ Called from ApplicationImpl's Initialize() method.
+ """
+ pass
+
+ def OnAcceptConnection(self, service_provider, requestor_url,
+ exposed_services):
+ """
+ Called from ApplicationImpl's OnAcceptConnection() method. Returns a bool
+ indicating whether this connection should be accepted.
+ """
+ return True
diff --git a/third_party/mojo/src/mojo/public/python/mojo_application/application_impl.py b/third_party/mojo/src/mojo/public/python/mojo_application/application_impl.py
new file mode 100644
index 0000000..248329a
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/python/mojo_application/application_impl.py
@@ -0,0 +1,56 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Python implementation of the Application interface."""
+
+import application_mojom
+import service_provider_mojom
+import shell_mojom
+from mojo_application.service_provider_impl import ServiceProviderImpl
+
+import mojo_system
+
+class ApplicationImpl(application_mojom.Application):
+ def __init__(self, delegate, app_request_handle):
+ self.shell = None
+ self.url = None
+ self.args = None
+ self._delegate = delegate
+ self._providers = []
+ application_mojom.Application.manager.Bind(self, app_request_handle)
+
+ def Initialize(self, shell, url, args):
+ self.shell = shell
+ self.url = url
+ self.args = args
+ self._delegate.Initialize(shell, self)
+
+ def AcceptConnection(self, requestor_url, services, exposed_services):
+ service_provider = ServiceProviderImpl(services)
+ if self._delegate.OnAcceptConnection(service_provider, requestor_url,
+ exposed_services):
+ # We keep a reference to ServiceProviderImpl to ensure neither it nor
+ # |services| gets garbage collected.
+ services.Bind(service_provider)
+ self._providers.append(service_provider)
+
+ def removeServiceProvider():
+ self._providers.remove(service_provider)
+ service_provider.manager.AddOnErrorCallback(removeServiceProvider)
+
+ def ConnectToService(self, application_url, service_class):
+ """
+ Helper method to connect to a service. |application_url| is the URL of the
+ application to be connected to, and |service_class| is the class of the
+ service to be connected to. Returns a proxy to the service.
+ """
+ application_proxy, request = (
+ service_provider_mojom.ServiceProvider.manager.NewRequest())
+ self.shell.ConnectToApplication(application_url, request, None)
+
+ service_proxy, request = service_class.manager.NewRequest()
+ application_proxy.ConnectToService(service_class.manager.name,
+ request.PassMessagePipe())
+
+ return service_proxy
diff --git a/third_party/mojo/src/mojo/public/python/mojo_application/application_runner.py b/third_party/mojo/src/mojo/public/python/mojo_application/application_runner.py
new file mode 100644
index 0000000..94f472c
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/python/mojo_application/application_runner.py
@@ -0,0 +1,18 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Helper for running Mojo applications in Python."""
+
+from mojo_application.application_impl import ApplicationImpl
+
+import mojo_system
+
+def RunMojoApplication(application_delegate, app_request_handle):
+ loop = mojo_system.RunLoop()
+
+ application = ApplicationImpl(application_delegate,
+ mojo_system.Handle(app_request_handle))
+ application.manager.AddOnErrorCallback(loop.Quit)
+
+ loop.Run()
diff --git a/third_party/mojo/src/mojo/public/python/mojo_application/service_provider_impl.py b/third_party/mojo/src/mojo/public/python/mojo_application/service_provider_impl.py
new file mode 100644
index 0000000..0166c76
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/python/mojo_application/service_provider_impl.py
@@ -0,0 +1,24 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Python implementation of the ServiceProvider interface."""
+
+import logging
+
+import service_provider_mojom
+
+class ServiceProviderImpl(service_provider_mojom.ServiceProvider):
+ def __init__(self, provider):
+ self._provider = provider
+ self._name_to_service_connector = {}
+
+ def AddService(self, service_class):
+ self._name_to_service_connector[service_class.manager.name] = service_class
+
+ def ConnectToService(self, interface_name, pipe):
+ if interface_name in self._name_to_service_connector:
+ service = self._name_to_service_connector[interface_name]
+ service.manager.Bind(service(), pipe)
+ else:
+ logging.error("Unable to find service " + interface_name)
diff --git a/third_party/mojo/src/mojo/public/python/mojo_bindings/descriptor.py b/third_party/mojo/src/mojo/public/python/mojo_bindings/descriptor.py
index 45e073f..109e5ce 100644
--- a/third_party/mojo/src/mojo/public/python/mojo_bindings/descriptor.py
+++ b/third_party/mojo/src/mojo/public/python/mojo_bindings/descriptor.py
@@ -508,8 +508,8 @@ class MapType(SerializableType):
'__module__': __name__,
'DESCRIPTOR': {
'fields': [
- SingleFieldGroup('keys', MapType._GetArrayType(key_type), 0, 0),
- SingleFieldGroup('values', MapType._GetArrayType(value_type), 1, 1),
+ SingleFieldGroup('keys', MapType._GetArrayType(key_type), 0, 1),
+ SingleFieldGroup('values', MapType._GetArrayType(value_type), 1, 2),
],
}
}
@@ -608,7 +608,10 @@ class FieldGroup(object):
def GetByteSize(self):
raise NotImplementedError()
- def GetVersion(self):
+ def GetMinVersion(self):
+ raise NotImplementedError()
+
+ def GetMaxVersion(self):
raise NotImplementedError()
def Serialize(self, obj, data_offset, data, handle_offset):
@@ -617,6 +620,9 @@ class FieldGroup(object):
def Deserialize(self, value, context):
raise NotImplementedError()
+ def Filter(self, version):
+ raise NotImplementedError()
+
class SingleFieldGroup(FieldGroup, FieldDescriptor):
"""A FieldGroup that contains a single FieldDescriptor."""
@@ -632,7 +638,10 @@ class SingleFieldGroup(FieldGroup, FieldDescriptor):
def GetByteSize(self):
return self.field_type.GetByteSize()
- def GetVersion(self):
+ def GetMinVersion(self):
+ return self.version
+
+ def GetMaxVersion(self):
return self.version
def Serialize(self, obj, data_offset, data, handle_offset):
@@ -643,12 +652,16 @@ class SingleFieldGroup(FieldGroup, FieldDescriptor):
entity = self.field_type.Deserialize(value, context)
return { self.name: entity }
+ def Filter(self, version):
+ return self
+
class BooleanGroup(FieldGroup):
"""A FieldGroup to pack booleans."""
def __init__(self, descriptors):
FieldGroup.__init__(self, descriptors)
- self.version = min([descriptor.version for descriptor in descriptors])
+ self.min_version = min([descriptor.version for descriptor in descriptors])
+ self.max_version = max([descriptor.version for descriptor in descriptors])
def GetTypeCode(self):
return 'B'
@@ -656,8 +669,11 @@ class BooleanGroup(FieldGroup):
def GetByteSize(self):
return 1
- def GetVersion(self):
- return self.version
+ def GetMinVersion(self):
+ return self.min_version
+
+ def GetMaxVersion(self):
+ return self.max_version
def Serialize(self, obj, data_offset, data, handle_offset):
value = _ConvertBooleansToByte(
@@ -670,6 +686,10 @@ class BooleanGroup(FieldGroup):
fillvalue=False)
return dict(values)
+ def Filter(self, version):
+ return BooleanGroup(
+ filter(lambda d: d.version <= version, self.descriptors))
+
def _SerializeNativeArray(value, data_offset, data, length):
data_size = len(data)
diff --git a/third_party/mojo/src/mojo/public/python/mojo_bindings/messaging.py b/third_party/mojo/src/mojo/public/python/mojo_bindings/messaging.py
index 385a080..ebdf1ee 100644
--- a/third_party/mojo/src/mojo/public/python/mojo_bindings/messaging.py
+++ b/third_party/mojo/src/mojo/public/python/mojo_bindings/messaging.py
@@ -30,13 +30,13 @@ class MessagingException(Exception):
class MessageHeader(object):
"""The header of a mojo message."""
- _SIMPLE_MESSAGE_NUM_FIELDS = 2
+ _SIMPLE_MESSAGE_VERSION = 2
_SIMPLE_MESSAGE_STRUCT = struct.Struct("<IIII")
_REQUEST_ID_STRUCT = struct.Struct("<Q")
_REQUEST_ID_OFFSET = _SIMPLE_MESSAGE_STRUCT.size
- _MESSAGE_WITH_REQUEST_ID_NUM_FIELDS = 3
+ _MESSAGE_WITH_REQUEST_ID_VERSION = 3
_MESSAGE_WITH_REQUEST_ID_SIZE = (
_SIMPLE_MESSAGE_STRUCT.size + _REQUEST_ID_STRUCT.size)
@@ -53,11 +53,11 @@ class MessageHeader(object):
raise serialization.DeserializationException('Header is too short.')
(size, version, message_type, flags) = (
cls._SIMPLE_MESSAGE_STRUCT.unpack_from(buf))
- if (version < cls._SIMPLE_MESSAGE_NUM_FIELDS):
+ if (version < cls._SIMPLE_MESSAGE_VERSION):
raise serialization.DeserializationException('Incorrect version.')
request_id = 0
if _HasRequestId(flags):
- if version < cls._MESSAGE_WITH_REQUEST_ID_NUM_FIELDS:
+ if version < cls._MESSAGE_WITH_REQUEST_ID_VERSION:
raise serialization.DeserializationException('Incorrect version.')
if (size < cls._MESSAGE_WITH_REQUEST_ID_SIZE or
len(data) < cls._MESSAGE_WITH_REQUEST_ID_SIZE):
@@ -105,10 +105,10 @@ class MessageHeader(object):
def Serialize(self):
if not self._data:
self._data = bytearray(self.size)
- version = self._SIMPLE_MESSAGE_NUM_FIELDS
+ version = self._SIMPLE_MESSAGE_VERSION
size = self._SIMPLE_MESSAGE_STRUCT.size
if self.has_request_id:
- version = self._MESSAGE_WITH_REQUEST_ID_NUM_FIELDS
+ version = self._MESSAGE_WITH_REQUEST_ID_VERSION
size = self._MESSAGE_WITH_REQUEST_ID_SIZE
self._SIMPLE_MESSAGE_STRUCT.pack_into(self._data, 0, size, version,
self._message_type, self._flags)
diff --git a/third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py b/third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py
index 35b8ff2..cec05fa 100644
--- a/third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py
+++ b/third_party/mojo/src/mojo/public/python/mojo_bindings/reflection.py
@@ -12,6 +12,7 @@ import sys
import mojo_bindings.messaging as messaging
import mojo_bindings.promise as promise
import mojo_bindings.serialization as serialization
+import mojo_system
class MojoEnumType(type):
@@ -273,6 +274,10 @@ class InterfaceManager(object):
router.Start()
+ def NewRequest(self):
+ pipe = mojo_system.MessagePipe()
+ return (self.Proxy(pipe.handle0), InterfaceRequest(pipe.handle1))
+
def _InternalProxy(self, router, error_handler):
if error_handler is None:
error_handler = _ProxyErrorHandler()
@@ -550,6 +555,7 @@ def _StubAccept(methods):
# Close the connection in case of error.
logging.warning(
'Error occured in accept method. Connection will be closed.')
+ logging.debug("Exception", exc_info=True)
if self.impl.manager:
self.impl.manager.Close()
return False
diff --git a/third_party/mojo/src/mojo/public/python/mojo_bindings/serialization.py b/third_party/mojo/src/mojo/public/python/mojo_bindings/serialization.py
index b5ea1bd..8f5cc67 100644
--- a/third_party/mojo/src/mojo/public/python/mojo_bindings/serialization.py
+++ b/third_party/mojo/src/mojo/public/python/mojo_bindings/serialization.py
@@ -168,11 +168,14 @@ def NeededPaddingForAlignment(value, alignment=8):
def _GetVersion(groups):
- return sum([len(x.descriptors) for x in groups])
+ if not len(groups):
+ return 0
+ return max([x.GetMaxVersion() for x in groups])
def _FilterGroups(groups, version):
- return [group for group in groups if group.GetVersion() < version]
+ return [group.Filter(version) for
+ group in groups if group.GetMinVersion() <= version]
def _GetStruct(groups):
diff --git a/third_party/mojo/src/mojo/public/python/mojo_system.pyx b/third_party/mojo/src/mojo/public/python/mojo_system.pyx
index 4e684af..d5f164d 100644
--- a/third_party/mojo/src/mojo/public/python/mojo_system.pyx
+++ b/third_party/mojo/src/mojo/public/python/mojo_system.pyx
@@ -19,7 +19,7 @@ from cpython.mem cimport PyMem_Malloc, PyMem_Free
from cpython.object cimport Py_EQ, Py_NE
from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t, uintptr_t
-import ctypes
+import weakref
import threading
import mojo_system_impl
@@ -770,7 +770,7 @@ class RunLoop(object):
def __init__(self):
self.__run_loop = mojo_system_impl.RunLoop()
- _RUN_LOOPS.loop = id(self)
+ _RUN_LOOPS.loop = weakref.ref(self)
def __del__(self):
del _RUN_LOOPS.loop
@@ -797,7 +797,7 @@ class RunLoop(object):
@staticmethod
def Current():
if hasattr(_RUN_LOOPS, 'loop'):
- return ctypes.cast(_RUN_LOOPS.loop, ctypes.py_object).value
+ return _RUN_LOOPS.loop()
return None
diff --git a/third_party/mojo/src/mojo/public/python/rules.gni b/third_party/mojo/src/mojo/public/python/rules.gni
index 934a94e5..2c1fab1 100644
--- a/third_party/mojo/src/mojo/public/python/rules.gni
+++ b/third_party/mojo/src/mojo/public/python/rules.gni
@@ -62,6 +62,12 @@ template("python_packaged_application") {
mojo_output = "$root_out_dir/" + target_name + ".mojo"
}
+ if (defined(invoker.debug) && invoker.debug) {
+ content_handler_param = "?debug=true"
+ } else {
+ content_handler_param = ""
+ }
+
python_package(package_name) {
sources = invoker.sources
if (defined(invoker.deps)) {
@@ -106,7 +112,7 @@ template("python_packaged_application") {
args = [
"--input=$rebase_input",
"--output=$rebase_output",
- "--line=#!mojo mojo:py_content_handler",
+ "--line=#!mojo mojo:py_content_handler${content_handler_param}",
]
}
}
diff --git a/third_party/mojo/src/mojo/public/tools/BUILD.gn b/third_party/mojo/src/mojo/public/tools/BUILD.gn
index 103c259..e03d1d3 100644
--- a/third_party/mojo/src/mojo/public/tools/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/tools/BUILD.gn
@@ -2,28 +2,64 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/module_args/mojo.gni")
import("../mojo.gni")
if (use_prebuilt_mojo_shell) {
copy("copy_mojo_shell") {
filename = "mojo_shell"
- if (is_win) {
- filename += ".exe"
- }
if (is_android) {
filename = "MojoShell.apk"
- }
- sources = [
- "prebuilt/$filename",
- ]
- if (is_android) {
+ sources = [
+ "prebuilt/shell/android-arm/$filename",
+ ]
outputs = [
"$root_out_dir/apks/$filename",
]
} else {
+ assert(is_linux)
+ sources = [
+ "prebuilt/shell/linux-x64/$filename",
+ ]
outputs = [
"$root_out_dir/$filename",
]
}
}
}
+
+if (use_prebuilt_network_service) {
+ copy("copy_network_service") {
+ filename = "network_service.mojo"
+ if (is_android) {
+ sources = [
+ "prebuilt/network_service/android-arm/$filename",
+ ]
+ } else {
+ assert(is_linux)
+ sources = [
+ "prebuilt/network_service/linux-x64/$filename",
+ ]
+ }
+ outputs = [
+ "$root_out_dir/$filename",
+ ]
+ }
+
+ copy("copy_network_service_apptests") {
+ filename = "network_service_apptests.mojo"
+ if (is_android) {
+ sources = [
+ "prebuilt/network_service_apptests/android-arm/$filename",
+ ]
+ } else {
+ assert(is_linux)
+ sources = [
+ "prebuilt/network_service_apptests/linux-x64/$filename",
+ ]
+ }
+ outputs = [
+ "$root_out_dir/$filename",
+ ]
+ }
+}
diff --git a/third_party/mojo/src/mojo/public/tools/NETWORK_SERVICE_VERSION b/third_party/mojo/src/mojo/public/tools/NETWORK_SERVICE_VERSION
new file mode 100644
index 0000000..597e852
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/NETWORK_SERVICE_VERSION
@@ -0,0 +1 @@
+bf9a4b53049b10cfdd85934075ed3e147be889f5 \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
index 25c01bb..2c21d0d 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
@@ -6,9 +6,6 @@ class {{interface.name}}RequestValidator;
{%- if interface|has_callbacks %}
class {{interface.name}}ResponseValidator;
{%- endif %}
-{% if interface.client %}
-class {{interface.client}};
-{% endif %}
class {{interface.name}} {
public:
@@ -23,11 +20,6 @@ class {{interface.name}} {
{%- else %}
using ResponseValidator_ = mojo::PassThroughFilter;
{%- endif %}
-{% if interface.client %}
- using Client = {{interface.client}};
-{% else %}
- using Client = mojo::NoInterface;
-{% endif %}
{#--- Constants #}
{%- for constant in interface.constants %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
index 2b45808..308c8b6 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -1,90 +1,29 @@
{%- import "interface_macros.tmpl" as interface_macros %}
+{%- import "struct_macros.tmpl" as struct_macros %}
{%- set class_name = interface.name %}
{%- set proxy_name = interface.name ~ "Proxy" %}
{%- set namespace_as_string = "%s"|format(namespace|replace(".","::")) %}
-{%- macro alloc_params(parameters) %}
-{%- for param in parameters %}
-{%- if param.kind|is_object_kind %}
-{{param.kind|cpp_result_type}} p{{loop.index}};
-Deserialize_(params->{{param.name}}.ptr, &p{{loop.index}});
-{% endif -%}
+{%- macro alloc_params(struct) %}
+{%- for param in struct.packed.packed_fields_in_ordinal_order %}
+ {{param.field.kind|cpp_result_type}} p_{{param.field.name}}{};
{%- endfor %}
+ {{struct_macros.deserialize(struct, "params", "p_%s")}}
{%- endmacro %}
{%- macro pass_params(parameters) %}
{%- for param in parameters %}
-{%- if param.kind|is_string_kind -%}
-p{{loop.index}}
-{%- elif param.kind|is_object_kind -%}
-p{{loop.index}}.Pass()
-{%- elif param.kind|is_interface_kind -%}
-mojo::MakeProxy<{{param.kind|get_name_for_kind}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}})))
-{%- elif param.kind|is_interface_request_kind -%}
-mojo::MakeRequest<{{param.kind.kind|get_name_for_kind}}>(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}})))
-{%- elif param.kind|is_any_handle_kind -%}
-mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&params->{{param.name}}))
-{%- elif param.kind|is_enum_kind -%}
-static_cast<{{param.kind|cpp_wrapper_type}}>(params->{{param.name}})
+{%- if param.kind|is_move_only_kind -%}
+p_{{param.name}}.Pass()
{%- else -%}
-params->{{param.name}}
+p_{{param.name}}
{%- endif -%}
{%- if not loop.last %}, {% endif %}
{%- endfor %}
{%- endmacro %}
-{%- macro compute_payload_size(params_name, parameters) -%}
- size_t payload_size =
- mojo::internal::Align(sizeof({{params_name}}));
-{#--- Computes #}
-{%- for param in parameters %}
-{%- if param.kind|is_object_kind %}
- payload_size += GetSerializedSize_(in_{{param.name}});
-{%- endif %}
-{%- endfor %}
-{%- endmacro %}
-
-{%- macro build_message(params_name, parameters, params_description) -%}
- {# TODO(yzshen): Consider refactoring to share code with
- struct_serialization_definition.tmpl #}
- {{params_name}}* params =
- {{params_name}}::New(builder.buffer());
-{#--- Sets #}
-{% for param in parameters %}
-{%- if param.kind|is_object_kind %}
-{%- if param.kind|is_array_kind %}
- mojo::SerializeArray_<{{param.kind|get_array_validate_params|indent(24)}}>(
- mojo::internal::Forward(in_{{param.name}}), builder.buffer(), &params->{{param.name}}.ptr);
-{%- elif param.kind|is_map_kind %}
- mojo::SerializeMap_<{{param.kind.value_kind|get_map_validate_params|indent(24)}}>(
- mojo::internal::Forward(in_{{param.name}}), builder.buffer(), &params->{{param.name}}.ptr);
-{%- else %}
- Serialize_(mojo::internal::Forward(in_{{param.name}}), builder.buffer(), &params->{{param.name}}.ptr);
-{%- endif %}
-{%- if not param.kind|is_nullable_kind %}
- MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !params->{{param.name}}.ptr,
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
- "null {{param.name}} argument in {{params_description}}");
-{%- endif %}
-{%- elif param.kind|is_any_handle_kind %}
-{%- if param.kind|is_interface_kind or
- param.kind|is_interface_request_kind %}
- // Delegate handle.
- params->{{param.name}} = in_{{param.name}}.PassMessagePipe().release();
-{%- else %}
- params->{{param.name}} = in_{{param.name}}.release();
-{%- endif %}
-{%- if not param.kind|is_nullable_kind %}
- MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !params->{{param.name}}.is_valid(),
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
- "invalid {{param.name}} argument in {{params_description}}");
-{%- endif %}
-{%- else %}
- params->{{param.name}} = in_{{param.name}};
-{%- endif %}
-{%- endfor %}
+{%- macro build_message(struct, struct_display_name) -%}
+ {{struct_macros.serialize(struct, struct_display_name, "in_%s", "params", "builder.buffer()")}}
mojo::Message message;
params->EncodePointersAndHandles(message.mutable_handles());
builder.Finish(&message);
@@ -119,7 +58,7 @@ bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept(
message->mutable_payload());
params->DecodePointersAndHandles(message->mutable_handles());
- {{alloc_params(method.response_parameters)|indent(2)}}
+ {{alloc_params(method|response_struct_from_method)}}
callback_.Run({{pass_params(method.response_parameters)}});
return true;
}
@@ -135,21 +74,20 @@ bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept(
{%- for method in interface.methods %}
{%- set message_name =
"internal::k%s_%s_Name"|format(interface.name, method.name) %}
-{%- set params_name =
- "internal::%s_%s_Params_Data"|format(interface.name, method.name) %}
+{%- set params_struct = method|struct_from_method %}
{%- set params_description =
"%s.%s request"|format(interface.name, method.name) %}
void {{proxy_name}}::{{method.name}}(
{{interface_macros.declare_request_params("in_", method)}}) {
- {{compute_payload_size(params_name, method.parameters)}}
+ {{struct_macros.get_serialized_size(params_struct, "in_%s")}}
{%- if method.response_parameters != None %}
- mojo::internal::RequestMessageBuilder builder({{message_name}}, payload_size);
+ mojo::internal::RequestMessageBuilder builder({{message_name}}, size);
{%- else %}
- mojo::internal::MessageBuilder builder({{message_name}}, payload_size);
+ mojo::internal::MessageBuilder builder({{message_name}}, size);
{%- endif %}
- {{build_message(params_name, method.parameters, params_description)}}
+ {{build_message(params_struct, params_description)}}
{%- if method.response_parameters != None %}
mojo::MessageReceiver* responder =
@@ -170,8 +108,7 @@ void {{proxy_name}}::{{method.name}}(
{%- if method.response_parameters != None %}
{%- set message_name =
"internal::k%s_%s_Name"|format(interface.name, method.name) %}
-{%- set params_name =
- "internal::%s_%s_ResponseParams_Data"|format(interface.name, method.name) %}
+{%- set response_params_struct = method|response_struct_from_method %}
{%- set params_description =
"%s.%s response"|format(interface.name, method.name) %}
class {{class_name}}_{{method.name}}_ProxyToResponder
@@ -197,10 +134,10 @@ class {{class_name}}_{{method.name}}_ProxyToResponder
};
void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
{{interface_macros.declare_params("in_", method.response_parameters)}}) const {
- {{compute_payload_size(params_name, method.response_parameters)}}
+ {{struct_macros.get_serialized_size(response_params_struct, "in_%s")}}
mojo::internal::ResponseMessageBuilder builder(
- {{message_name}}, payload_size, request_id_);
- {{build_message(params_name, method.response_parameters, params_description)}}
+ {{message_name}}, size, request_id_);
+ {{build_message(response_params_struct, params_description)}}
bool ok = responder_->Accept(&message);
MOJO_ALLOW_UNUSED_LOCAL(ok);
// TODO(darin): !ok returned here indicates a malformed message, and that may
@@ -229,9 +166,8 @@ bool {{class_name}}Stub::Accept(mojo::Message* message) {
message->mutable_payload());
params->DecodePointersAndHandles(message->mutable_handles());
- {{alloc_params(method.parameters)|indent(6)}}
- // A null |sink_| typically means there is a missing call to
- // InterfacePtr::set_client().
+ {{alloc_params(method|struct_from_method)|indent(4)}}
+ // A null |sink_| means no implementation was bound.
assert(sink_);
sink_->{{method.name}}({{pass_params(method.parameters)}});
return true;
@@ -261,9 +197,8 @@ bool {{class_name}}Stub::AcceptWithResponder(
new {{class_name}}_{{method.name}}_ProxyToResponder(
message->request_id(), responder);
{{class_name}}::{{method.name}}Callback callback(runnable);
- {{alloc_params(method.parameters)|indent(6)}}
- // A null |sink_| typically means there is a missing call to
- // InterfacePtr::set_client().
+ {{alloc_params(method|struct_from_method)|indent(4)}}
+ // A null |sink_| means no implementation was bound.
assert(sink_);
sink_->{{method.name}}(
{%- if method.parameters -%}{{pass_params(method.parameters)}}, {% endif -%}callback);
@@ -311,8 +246,6 @@ bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
}
{%- endif %}
- // A null |sink_| typically means there is a missing call to
- // InterfacePtr::set_client().
assert(sink_);
return sink_->Accept(message);
}
@@ -343,8 +276,6 @@ bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) {
}
{%- endif %}
- // A null |sink_| typically means there is a missing call to
- // InterfacePtr::set_client().
assert(sink_);
return sink_->Accept(message);
}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
index 863d18f..969bea2 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
@@ -47,10 +47,12 @@ namespace {
{%- set method_name = "k%s_%s_Name"|format(interface.name, method.name) %}
const uint32_t {{method_name}} = {{method.ordinal}};
{% set struct = method|struct_from_method %}
-{%- include "params_definition.tmpl" %}
+{% include "struct_declaration.tmpl" %}
+{%- include "struct_definition.tmpl" %}
{%- if method.response_parameters != None %}
{%- set struct = method|response_struct_from_method %}
-{%- include "params_definition.tmpl" %}
+{% include "struct_declaration.tmpl" %}
+{%- include "struct_definition.tmpl" %}
{%- endif %}
{%- endfor %}
{%- endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl
deleted file mode 100644
index 0892b64..0000000
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/params_definition.tmpl
+++ /dev/null
@@ -1,33 +0,0 @@
-{%- import "struct_macros.tmpl" as struct_macros %}
-{%- set class_name = struct.name ~ "_Data" %}
-class {{class_name}} {
- public:
- static {{class_name}}* New(mojo::internal::Buffer* buf) {
- return new (buf->Allocate(sizeof({{class_name}})))
- {{class_name}}();
- }
-
- static bool Validate(const void* data,
- mojo::internal::BoundsChecker* bounds_checker) {
- {{ struct_macros.validate(struct, class_name)|indent(4) }}
- }
-
- mojo::internal::StructHeader header_;
-{{struct_macros.fields(struct)}}
-
- void EncodePointersAndHandles(std::vector<mojo::Handle>* handles) {
- {{ struct_macros.encodes(struct)|indent(4) }}
- }
-
- void DecodePointersAndHandles(std::vector<mojo::Handle>* handles) {
- {{ struct_macros.decodes(struct)|indent(4) }}
- }
-
- private:
- {{class_name}}() {
- header_.num_bytes = sizeof(*this);
- header_.num_fields = {{struct.packed.packed_fields|length}};
- }
-};
-static_assert(sizeof({{class_name}}) == {{struct.versions[-1].num_bytes}},
- "Bad sizeof({{class_name}})");
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
index ee8934e..255005a 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
@@ -1,4 +1,3 @@
-{%- import "struct_macros.tmpl" as struct_macros %}
{%- set class_name = struct.name ~ "_Data" -%}
class {{class_name}} {
@@ -8,12 +7,39 @@ class {{class_name}} {
static bool Validate(const void* data,
mojo::internal::BoundsChecker* bounds_checker);
- mojo::internal::StructHeader header_;
-{{struct_macros.fields(struct)}}
-
void EncodePointersAndHandles(std::vector<mojo::Handle>* handles);
void DecodePointersAndHandles(std::vector<mojo::Handle>* handles);
+ mojo::internal::StructHeader header_;
+{%- for packed_field in struct.packed.packed_fields %}
+{%- set name = packed_field.field.name %}
+{%- set kind = packed_field.field.kind %}
+{%- if kind.spec == 'b' %}
+ uint8_t {{name}} : 1;
+{%- elif kind|is_enum_kind %}
+ int32_t {{name}};
+{%- else %}
+ {{kind|cpp_field_type}} {{name}};
+{%- endif %}
+{%- if not loop.last %}
+{%- set next_pf = struct.packed.packed_fields[loop.index0 + 1] %}
+{%- set pad = next_pf.offset - (packed_field.offset + packed_field.size) %}
+{%- if pad > 0 %}
+ uint8_t pad{{loop.index0}}_[{{pad}}];
+{%- endif %}
+{%- endif %}
+{%- endfor %}
+
+{%- set num_fields = struct.versions[-1].num_fields %}
+{%- if num_fields > 0 %}
+{%- set last_field = struct.packed.packed_fields[num_fields - 1] %}
+{%- set offset = last_field.offset + last_field.size %}
+{%- set pad = offset|get_pad(8) %}
+{%- if pad > 0 %}
+ uint8_t padfinal_[{{pad}}];
+{%- endif %}
+{%- endif %}
+
private:
{{class_name}}();
~{{class_name}}() = delete;
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
index 461f158..79a0bc4 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
@@ -1,6 +1,69 @@
-{%- import "struct_macros.tmpl" as struct_macros %}
{%- set class_name = struct.name ~ "_Data" %}
+{#- TODO(yzshen): Consider eliminating _validate_object() and
+ _validate_handle(). #}
+
+{#- Validates the specified struct field, which is supposed to be an object
+ (struct/array/string/map/union).
+ This macro is expanded by the Validate() method. #}
+{%- macro _validate_object(struct, packed_field) %}
+{%- set name = packed_field.field.name %}
+{%- set kind = packed_field.field.kind %}
+{%- set wrapper_type = kind|cpp_wrapper_type %}
+{%- if not kind|is_nullable_kind %}
+ if (!object->{{name}}.offset) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
+ "null {{name}} field in {{struct.name}} struct");
+ return false;
+ }
+{%- endif %}
+ if (!mojo::internal::ValidateEncodedPointer(&object->{{name}}.offset)) {
+ ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_POINTER);
+ return false;
+ }
+{%- if kind|is_array_kind or kind|is_string_kind %}
+ if (!{{wrapper_type}}::Data_::Validate<
+ {{kind|get_array_validate_params|indent(10)}}>(
+ mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
+ bounds_checker)) {
+{%- elif kind|is_map_kind %}
+ if (!{{wrapper_type}}::Data_::Validate<
+ {{kind.value_kind|get_map_validate_params|indent(10)}}>(
+ mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
+ bounds_checker)) {
+{%- elif kind|is_struct_kind %}
+ if (!{{kind|get_name_for_kind}}::Data_::Validate(
+ mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
+ bounds_checker)) {
+{%- else %}
+ if (!{{wrapper_type}}::Data_::Validate(
+ mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
+ bounds_checker)) {
+{%- endif %}
+ return false;
+ }
+{%- endmacro %}
+
+{#- Validates the specified struct field, which is supposed to be a handle.
+ This macro is expanded by the Validate() method. #}
+{%- macro _validate_handle(struct, packed_field) %}
+{%- set name = packed_field.field.name %}
+{%- set kind = packed_field.field.kind %}
+{%- if not kind|is_nullable_kind %}
+ if (object->{{name}}.value() == mojo::internal::kEncodedInvalidHandleValue) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
+ "invalid {{name}} field in {{struct.name}} struct");
+ return false;
+ }
+{%- endif %}
+ if (!bounds_checker->ClaimHandle(object->{{name}})) {
+ ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_HANDLE);
+ return false;
+ }
+{%- endmacro %}
+
// static
{{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) {
return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}();
@@ -9,20 +72,109 @@
// static
bool {{class_name}}::Validate(const void* data,
mojo::internal::BoundsChecker* bounds_checker) {
- {{ struct_macros.validate(struct, class_name)|indent(2) }}
-}
+ if (!data)
+ return true;
-{{class_name}}::{{class_name}}() {
- header_.num_bytes = sizeof(*this);
- header_.num_fields = {{struct.packed.packed_fields|length}};
+ if (!ValidateStructHeaderAndClaimMemory(data, bounds_checker))
+ return false;
+
+ // NOTE: The memory backing |object| may be smaller than |sizeof(*object)| if
+ // the message comes from an older version.
+ const {{class_name}}* object = static_cast<const {{class_name}}*>(data);
+
+ static const struct {
+ uint32_t version;
+ uint32_t num_bytes;
+ } kVersionSizes[] = {
+{%- for version in struct.versions -%}
+ { {{version.version}}, {{version.num_bytes}} }{% if not loop.last %}, {% endif -%}
+{%- endfor -%}
+ };
+
+ if (object->header_.version <=
+ kVersionSizes[MOJO_ARRAYSIZE(kVersionSizes) - 1].version) {
+ // Scan in reverse order to optimize for more recent versions.
+ for (int i = MOJO_ARRAYSIZE(kVersionSizes) - 1; i >= 0; --i) {
+ if (object->header_.version >= kVersionSizes[i].version) {
+ if (object->header_.num_bytes == kVersionSizes[i].num_bytes)
+ break;
+
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
+ return false;
+ }
+ }
+ } else if (object->header_.num_bytes <
+ kVersionSizes[MOJO_ARRAYSIZE(kVersionSizes) - 1].num_bytes) {
+ ReportValidationError(
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
+ return false;
+ }
+
+{#- Before validating fields introduced at a certain version, we need to add
+ a version check, which makes sure we skip further validation if |object|
+ is from an earlier version. |last_checked_version| records the last
+ version that we have added such version check. #}
+{%- set last_checked_version = 0 %}
+{%- for packed_field in struct.packed.packed_fields_in_ordinal_order %}
+{%- set kind = packed_field.field.kind %}
+{%- if kind|is_object_kind or kind|is_any_handle_kind %}
+{%- if packed_field.min_version > last_checked_version %}
+{%- set last_checked_version = packed_field.min_version %}
+ if (object->header_.version < {{packed_field.min_version}})
+ return true;
+{%- endif %}
+{%- if kind|is_object_kind %}
+{{_validate_object(struct, packed_field)}}
+{%- elif kind|is_any_handle_kind %}
+{{_validate_handle(struct, packed_field)}}
+{%- endif %}
+{%- endif %}
+{%- endfor %}
+
+ return true;
}
void {{class_name}}::EncodePointersAndHandles(
std::vector<mojo::Handle>* handles) {
- {{ struct_macros.encodes(struct)|indent(2) }}
+ MOJO_CHECK(header_.version == {{struct.versions[-1].version}});
+{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
+{%- if pf.field.kind|is_object_kind %}
+ mojo::internal::Encode(&{{pf.field.name}}, handles);
+{%- elif pf.field.kind|is_any_handle_kind %}
+ mojo::internal::EncodeHandle(&{{pf.field.name}}, handles);
+{%- endif %}
+{%- endfor %}
}
void {{class_name}}::DecodePointersAndHandles(
std::vector<mojo::Handle>* handles) {
- {{ struct_macros.decodes(struct)|indent(2) }}
+ // NOTE: The memory backing |this| may has be smaller than |sizeof(*this)|, if
+ // the message comes from an older version.
+{#- Before decoding fields introduced at a certain version, we need to add
+ a version check, which makes sure we skip further decoding if |this|
+ is from an earlier version. |last_checked_version| records the last
+ version that we have added such version check. #}
+{%- set last_checked_version = 0 %}
+{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
+{%- set name = pf.field.name %}
+{%- set kind = pf.field.kind %}
+{%- if kind|is_object_kind or kind|is_any_handle_kind %}
+{%- if pf.min_version > last_checked_version %}
+{%- set last_checked_version = pf.min_version %}
+ if (header_.version < {{pf.min_version}})
+ return;
+{%- endif %}
+{%- if kind|is_object_kind %}
+ mojo::internal::Decode(&{{name}}, handles);
+{%- else %}
+ mojo::internal::DecodeHandle(&{{name}}, handles);
+{%- endif %}
+{%- endif %}
+{%- endfor %}
+}
+
+{{class_name}}::{{class_name}}() {
+ header_.num_bytes = sizeof(*this);
+ header_.version = {{struct.versions[-1].version}};
}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
index 623ebb4..03911b9 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
@@ -1,124 +1,118 @@
-{%- macro validate(struct, class_name) %}
- if (!data)
- return true;
+{# TODO(yzshen): Make these templates more readable. #}
- if (!ValidateStructHeader(
- data, sizeof({{class_name}}),
- {{struct.packed.packed_fields|length}}, bounds_checker)) {
- return false;
- }
-
- const {{class_name}}* object = static_cast<const {{class_name}}*>(data);
- MOJO_ALLOW_UNUSED_LOCAL(object);
-
-{%- for packed_field in struct.packed.packed_fields %}
-{%- set name = packed_field.field.name %}
-{%- set kind = packed_field.field.kind %}
-{%- if kind|is_object_kind %}
-{%- set wrapper_type = kind|cpp_wrapper_type %}
-{%- if not kind|is_nullable_kind %}
- if (!object->{{name}}.offset) {
- ReportValidationError(
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
- "null {{name}} field in {{struct.name}} struct");
- return false;
- }
-{%- endif %}
- if (!mojo::internal::ValidateEncodedPointer(&object->{{name}}.offset)) {
- ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_POINTER);
- return false;
- }
-{%- if kind|is_array_kind or kind|is_string_kind %}
- if (!{{wrapper_type}}::Data_::Validate<
- {{kind|get_array_validate_params|indent(10)}}>(
- mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
- bounds_checker)) {
-{%- elif kind|is_map_kind %}
- if (!{{wrapper_type}}::Data_::Validate<
- {{kind.value_kind|get_map_validate_params|indent(10)}}>(
- mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
- bounds_checker)) {
-{%- elif kind|is_struct_kind %}
- if (!{{kind|get_name_for_kind}}::Data_::Validate(
- mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
- bounds_checker)) {
-{%- else %}
- if (!{{wrapper_type}}::Data_::Validate(
- mojo::internal::DecodePointerRaw(&object->{{name}}.offset),
- bounds_checker)) {
-{%- endif %}
- return false;
- }
-{%- elif kind|is_any_handle_kind %}
-{%- if not kind|is_nullable_kind %}
- if (object->{{name}}.value() == mojo::internal::kEncodedInvalidHandleValue) {
- ReportValidationError(
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
- "invalid {{name}} field in {{struct.name}} struct");
- return false;
- }
-{%- endif %}
- if (!bounds_checker->ClaimHandle(object->{{name}})) {
- ReportValidationError(mojo::internal::VALIDATION_ERROR_ILLEGAL_HANDLE);
- return false;
- }
-{%- endif %}
+{# Computes the serialized size for the specified struct.
+ |struct| is the struct definition.
+ |input_field_pattern| should be a pattern that contains one string
+ placeholder, for example, "input->%s", "p_%s". The placeholder will be
+ substituted with struct field names to refer to the input fields.
+ This macro is expanded to compute seriailized size for both:
+ - user-defined structs: the input is an instance of the corresponding struct
+ wrapper class.
+ - method parameters/response parameters: the input is a list of
+ arguments.
+ It declares |size| of type size_t to store the resulting size. #}
+{%- macro get_serialized_size(struct, input_field_pattern) -%}
+ size_t size = sizeof(internal::{{struct.name}}_Data);
+{%- for pf in struct.packed.packed_fields_in_ordinal_order if pf.field.kind|is_object_kind %}
+ size += GetSerializedSize_({{input_field_pattern|format(pf.field.name)}});
{%- endfor %}
+{%- endmacro -%}
- return true;
-{%- endmacro %}
-
-{%- macro field_line(field) %}
-{%- set type = field.kind|cpp_field_type %}
-{%- set name = field.name -%}
-{%- if field.kind.spec == 'b' -%}
- uint8_t {{name}} : 1;
-{%- elif field.kind|is_enum_kind -%}
- int32_t {{name}};
-{%- else -%}
- {{type}} {{name}};
-{%- endif %}
-{%- endmacro %}
-
-{%- macro fields(struct) %}
-{%- for packed_field in struct.packed.packed_fields %}
- {{field_line(packed_field.field)}}
-{%- if not loop.last %}
-{%- set next_pf = struct.packed.packed_fields[loop.index0 + 1] %}
-{%- set pad = next_pf.offset - (packed_field.offset + packed_field.size) %}
-{%- if pad > 0 %}
- uint8_t pad{{loop.index0}}_[{{pad}}];
-{%- endif %}
+{# Serializes the specified struct.
+ |struct| is the struct definition.
+ |struct_display_name| is the display name for the struct that can be showed
+ in error/log messages, for example, "FooStruct", "FooMethod request".
+ |input_field_pattern| should be a pattern that contains one string
+ placeholder, for example, "input->%s", "p_%s". The placeholder will be
+ substituted with struct field names to refer to the input fields.
+ |output| is the name of the output struct instance.
+ |buffer| is the name of the Buffer instance used.
+ This macro is expanded to do serialization for both:
+ - user-defined structs: the input is an instance of the corresponding struct
+ wrapper class.
+ - method parameters/response parameters: the input is a list of
+ arguments. #}
+{%- macro serialize(struct, struct_display_name, input_field_pattern, output, buffer) -%}
+ internal::{{struct.name}}_Data* {{output}} =
+ internal::{{struct.name}}_Data::New({{buffer}});
+{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
+{%- set input_field = input_field_pattern|format(pf.field.name) %}
+{%- set name = pf.field.name %}
+{%- set kind = pf.field.kind %}
+{%- if kind|is_object_kind %}
+{%- if kind|is_array_kind %}
+ mojo::SerializeArray_<{{kind|get_array_validate_params|indent(24)}}>(
+ mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr);
+{%- elif kind|is_map_kind %}
+ mojo::SerializeMap_<{{kind.value_kind|get_map_validate_params|indent(24)}}>(
+ mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr);
+{%- else %}
+ Serialize_(mojo::internal::Forward({{input_field}}), {{buffer}}, &{{output}}->{{name}}.ptr);
{%- endif %}
-{%- endfor -%}
-
-{%- set num_fields = struct.packed.packed_fields|length %}
-{%- if num_fields > 0 %}
-{%- set last_field = struct.packed.packed_fields[num_fields - 1] %}
-{%- set offset = last_field.offset + last_field.size %}
-{%- set pad = offset|get_pad(8) -%}
-{%- if pad > 0 %}
- uint8_t padfinal_[{{pad}}];
+{%- if not kind|is_nullable_kind %}
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ !{{output}}->{{name}}.ptr,
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
+ "null {{name}} in {{struct_display_name}}");
{%- endif %}
-{%- endif %}
-{%- endmacro %}
-
-{%- macro encodes(struct) -%}
-{%- for pf in struct.packed.packed_fields %}
-{%- if pf.field.kind|is_object_kind %}
-mojo::internal::Encode(&{{pf.field.name}}, handles);
-{%- elif pf.field.kind|is_any_handle_kind %}
-mojo::internal::EncodeHandle(&{{pf.field.name}}, handles);
+{%- elif kind|is_any_handle_kind %}
+{%- if kind|is_interface_kind or kind|is_interface_request_kind %}
+ {{output}}->{{name}} = {{input_field}}.PassMessagePipe().release();
+{%- else %}
+ {{output}}->{{name}} = {{input_field}}.release();
{%- endif %}
-{%- endfor %}
+{%- if not kind|is_nullable_kind %}
+ MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+ !{{output}}->{{name}}.is_valid(),
+ mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
+ "invalid {{name}} in {{struct_display_name}}");
+{%- endif %}
+{%- else %}
+ {{output}}->{{name}} = {{input_field}};
+{%- endif %}
+{%- endfor %}
{%- endmacro -%}
-{%- macro decodes(struct) -%}
-{%- for pf in struct.packed.packed_fields %}
-{%- if pf.field.kind|is_object_kind %}
-mojo::internal::Decode(&{{pf.field.name}}, handles);
-{%- elif pf.field.kind|is_any_handle_kind %}
-mojo::internal::DecodeHandle(&{{pf.field.name}}, handles);
+{# Deserializes the specified struct.
+ |struct| is the struct definition.
+ |input| is the name of the input struct instance.
+ |output_field_pattern| should be a pattern that contains one string
+ placeholder, for example, "result->%s", "p_%s". The placeholder will be
+ substituted with struct field names to refer to the output fields.
+ This macro is expanded to do deserialization for both:
+ - user-defined structs: the output is an instance of the corresponding
+ struct wrapper class.
+ - method parameters/response parameters: the output is a list of
+ arguments. #}
+{%- macro deserialize(struct, input, output_field_pattern) -%}
+ do {
+ // NOTE: The memory backing |{{input}}| may has be smaller than
+ // |sizeof(*{{input}})| if the message comes from an older version.
+{#- Before deserialize fields introduced at a certain version, we need to add
+ a version check, which makes sure we skip further deserialization if
+ |input| is from an earlier version. |last_checked_version| records the
+ last version that we have added such version check. #}
+{%- set last_checked_version = 0 %}
+{%- for pf in struct.packed.packed_fields_in_ordinal_order %}
+{%- set output_field = output_field_pattern|format(pf.field.name) %}
+{%- set name = pf.field.name %}
+{%- set kind = pf.field.kind %}
+{%- if pf.min_version > last_checked_version %}
+{%- set last_checked_version = pf.min_version %}
+ if ({{input}}->header_.version < {{pf.min_version}})
+ break;
+{%- endif %}
+{%- if kind|is_object_kind %}
+ Deserialize_({{input}}->{{name}}.ptr, &{{output_field}});
+{%- elif kind|is_interface_kind or kind|is_interface_request_kind %}
+ {{output_field}}.Bind(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&{{input}}->{{name}})));
+{%- elif kind|is_any_handle_kind %}
+ {{output_field}}.reset(mojo::internal::FetchAndReset(&{{input}}->{{name}}));
+{%- elif kind|is_enum_kind %}
+ {{output_field}} = static_cast<{{kind|cpp_wrapper_type}}>({{input}}->{{name}});
+{%- else %}
+ {{output_field}} = {{input}}->{{name}};
{%- endif %}
{%- endfor %}
-{%- endmacro -%}
+ } while (false);
+{%- endmacro %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
index 1612bbe..fe25553 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_definition.tmpl
@@ -1,51 +1,15 @@
+{%- import "struct_macros.tmpl" as struct_macros %}
size_t GetSerializedSize_(const {{struct.name}}Ptr& input) {
if (!input)
return 0;
- size_t size = sizeof(internal::{{struct.name}}_Data);
-{%- for pf in struct.packed.packed_fields if pf.field.kind|is_object_kind %}
- size += GetSerializedSize_(input->{{pf.field.name}});
-{%- endfor %}
+ {{struct_macros.get_serialized_size(struct, "input->%s")}}
return size;
}
void Serialize_({{struct.name}}Ptr input, mojo::internal::Buffer* buf,
internal::{{struct.name}}_Data** output) {
if (input) {
- internal::{{struct.name}}_Data* result =
- internal::{{struct.name}}_Data::New(buf);
-{%- for pf in struct.packed.packed_fields %}
-{%- if pf.field.kind|is_object_kind %}
-{%- if pf.field.kind|is_array_kind %}
- mojo::SerializeArray_<{{pf.field.kind|get_array_validate_params|indent(26)}}>(
- mojo::internal::Forward(input->{{pf.field.name}}), buf, &result->{{pf.field.name}}.ptr);
-{%- elif pf.field.kind|is_map_kind %}
- mojo::SerializeMap_<{{pf.field.kind.value_kind|get_map_validate_params|indent(26)}}>(
- mojo::internal::Forward(input->{{pf.field.name}}), buf, &result->{{pf.field.name}}.ptr);
-{%- else %}
- Serialize_(mojo::internal::Forward(input->{{pf.field.name}}), buf, &result->{{pf.field.name}}.ptr);
-{%- endif %}
-{%- if not pf.field.kind|is_nullable_kind %}
- MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !result->{{pf.field.name}}.ptr,
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
- "null {{pf.field.name}} field in {{struct.name}} struct");
-{%- endif %}
-{%- elif pf.field.kind|is_any_handle_kind %}
-{%- if pf.field.kind|is_interface_kind %}
- result->{{pf.field.name}} = input->{{pf.field.name}}.PassMessagePipe().release();
-{%- else %}
- result->{{pf.field.name}} = input->{{pf.field.name}}.release();
-{%- endif %}
-{%- if not pf.field.kind|is_nullable_kind %}
- MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
- !result->{{pf.field.name}}.is_valid(),
- mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
- "invalid {{pf.field.name}} field in {{struct.name}} struct");
-{%- endif %}
-{%- else %}
- result->{{pf.field.name}} = input->{{pf.field.name}};
-{%- endif %}
-{%- endfor %}
+ {{struct_macros.serialize(struct, struct.name ~ " struct", "input->%s", "result", "buf")|indent(2)}}
*output = result;
} else {
*output = nullptr;
@@ -56,21 +20,7 @@ void Deserialize_(internal::{{struct.name}}_Data* input,
{{struct.name}}Ptr* output) {
if (input) {
{{struct.name}}Ptr result({{struct.name}}::New());
-{%- for pf in struct.packed.packed_fields %}
-{%- if pf.field.kind|is_object_kind %}
- Deserialize_(input->{{pf.field.name}}.ptr, &result->{{pf.field.name}});
-{%- elif pf.field.kind|is_interface_kind %}
- if (input->{{pf.field.name}}.is_valid())
- result->{{pf.field.name}}.Bind(mojo::MakeScopedHandle(mojo::internal::FetchAndReset(&input->{{pf.field.name}})));
-{%- elif pf.field.kind|is_any_handle_kind %}
- result->{{pf.field.name}}.reset(mojo::internal::FetchAndReset(&input->{{pf.field.name}}));
-{%- elif pf.field.kind|is_enum_kind %}
- result->{{pf.field.name}} = static_cast<{{pf.field.kind|cpp_wrapper_type}}>(
- input->{{pf.field.name}});
-{%- else %}
- result->{{pf.field.name}} = input->{{pf.field.name}};
-{%- endif %}
-{%- endfor %}
+ {{struct_macros.deserialize(struct, "input", "result->%s")|indent(2)}}
*output = result.Pass();
} else {
output->reset();
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
index ebcba7b..6242be4 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
@@ -32,7 +32,7 @@ class {{struct.name}} {
{%- endif %}
bool Equals(const {{struct.name}}& other) const;
-{#--- Getters #}
+{#--- Struct members #}
{% for field in struct.fields %}
{%- set type = field.kind|cpp_wrapper_type %}
{%- set name = field.name %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl
index a73ad8e..f8f92dc9 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/interface_definition.tmpl
@@ -42,6 +42,19 @@ abstract class {{interface|name}} implements core.Listener {
[Function responseFactory = null]);
{%- endif %}
{%- endfor %}
+
+
+{#--- Interface Constants #}
+{% for constant in interface.constants %}
+ static final {{constant|name}} = {{constant.value|expression_to_text}};
+{%- endfor %}
+
+
+{#--- Interface Enums #}
+{%- from "enum_definition.tmpl" import enum_def -%}
+{%- for enum in interface.enums %}
+ {{ enum_def(" static ", enum) }}
+{%- endfor %}
}
class {{interface|name}}Proxy extends bindings.Proxy implements {{interface|name}} {
@@ -200,14 +213,3 @@ class {{interface|name}}Stub extends bindings.Stub {
{#--- TODO(zra): Validation #}
-{#--- Interface Constants #}
-{% for constant in interface.constants %}
-final {{constant|name}} = {{constant.value|expression_to_text}};
-{%- endfor %}
-
-
-{#--- Interface Enums #}
-{%- from "enum_definition.tmpl" import enum_def -%}
-{%- for enum in interface.enums %}
- {{ enum_def("", enum) }}
-{%- endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
index 93a3e42..7538e8b 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl
@@ -12,7 +12,7 @@ if ({{variable}} == null) {
{%- endif %}
var encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}, {{kind|array_expected_length}});
for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) {
- {{encode(variable~'[i'~level~']', sub_kind, 'bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i'~level, 0, level+1)|indent(4)}}
+ {{encode(variable~'[i'~level~']', sub_kind, 'bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i'~level, 0, level+1)|indent(4)}}
}
}
{%- elif kind|is_map_kind %}
@@ -23,8 +23,8 @@ if ({{variable}} == null) {
int size{{level}} = {{variable}}.length;
var keys{{level}} = {{variable}}.keys.toList();
var values{{level}} = {{variable}}.values.toList();
- {{encode('keys'~level, kind.key_kind|array, 'bindings.DataHeader.kHeaderSize', 0, level+1, False)|indent(2)}}
- {{encode('values'~level, kind.value_kind|array, 'bindings.DataHeader.kHeaderSize + bindings.kPointerSize', 0, level+1, False)|indent(2)}}
+ {{encode('keys'~level, kind.key_kind|array, 'bindings.ArrayDataHeader.kHeaderSize', 0, level+1, False)|indent(2)}}
+ {{encode('values'~level, kind.value_kind|array, 'bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize', 0, level+1, False)|indent(2)}}
}
{%- else %}
encoder{{level}}.{{kind|encode_method(variable, offset, bit)}};
@@ -50,18 +50,18 @@ if (decoder{{level+1}} == null) {
List<{{kind.key_kind|dart_type}}> keys{{level}};
List<{{kind.value_kind|dart_type}}> values{{level}};
{
- {{decode('keys'~level, kind.key_kind|array, 'bindings.DataHeader.kHeaderSize', 0, level+1)|indent(4)}}
+ {{decode('keys'~level, kind.key_kind|array, 'bindings.ArrayDataHeader.kHeaderSize', 0, level+1)|indent(4)}}
}
{
- {{decode('values'~level, kind.value_kind|array('keys'~level~'.length'), 'bindings.DataHeader.kHeaderSize + bindings.kPointerSize', 0, level+1)|indent(4)}}
+ {{decode('values'~level, kind.value_kind|array('keys'~level~'.length'), 'bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize', 0, level+1)|indent(4)}}
}
{{variable}} = new Map<{{kind.key_kind|dart_type}}, {{kind.value_kind|dart_type}}>.fromIterables(
keys{{level}}, values{{level}});
{%- else %}
var si{{level+1}} = decoder{{level+1}}.decodeDataHeaderForPointerArray({{kind|array_expected_length}});
- {{variable}} = new {{kind|dart_type}}(si{{level+1}}.numFields);
- for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numFields; ++i{{level+1}}) {
- {{decode(variable~'[i'~(level+1)~']', kind.kind, 'bindings.DataHeader.kHeaderSize + bindings.kPointerSize * i'~(level+1), 0, level+1)|indent(4)}}
+ {{variable}} = new {{kind|dart_type}}(si{{level+1}}.numElements);
+ for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numElements; ++i{{level+1}}) {
+ {{decode(variable~'[i'~(level+1)~']', kind.kind, 'bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i'~(level+1), 0, level+1)|indent(4)}}
}
{%- endif %}
}
@@ -75,8 +75,8 @@ if (decoder{{level+1}} == null) {
{%- macro struct_def(struct) %}
class {{struct|name}} extends bindings.Struct {
static const int kStructSize = {{struct.versions[-1].num_bytes}};
- static const bindings.DataHeader kDefaultStructInfo =
- const bindings.DataHeader(kStructSize, {{struct.packed.packed_fields|length}});
+ static const bindings.StructDataHeader kDefaultStructInfo =
+ const bindings.StructDataHeader(kStructSize, {{struct.versions[-1].version}});
{#--- Enums #}
{%- from "enum_definition.tmpl" import enum_def %}
@@ -107,15 +107,15 @@ class {{struct|name}} extends bindings.Struct {
}
{{struct|name}} result = new {{struct|name}}();
- var mainDataHeader = decoder0.decodeDataHeader();
+ var mainDataHeader = decoder0.decodeStructDataHeader();
if ((mainDataHeader.size < kStructSize) ||
- (mainDataHeader.numFields < {{struct.packed.packed_fields|length}})) {
+ (mainDataHeader.version < {{struct.versions[-1].version}})) {
throw new bindings.MojoCodecError('Malformed header');
}
{%- for byte in struct.bytes %}
{%- for packed_field in byte.packed_fields %}
- if (mainDataHeader.numFields > {{packed_field.ordinal}}) {
+ {
{{decode('result.' ~ packed_field.field|name, packed_field.field.kind, 8+packed_field.offset, packed_field.bit)|indent(6)}}
}
{%- endfor %}
@@ -125,9 +125,9 @@ class {{struct|name}} extends bindings.Struct {
void encode(bindings.Encoder encoder) {
{%- if not struct.bytes %}
- encoder.getEncoderAtOffset(kDefaultStructInfo);
+ encoder.getStructEncoderAtOffset(kDefaultStructInfo);
{%- else %}
- var encoder0 = encoder.getEncoderAtOffset(kDefaultStructInfo);
+ var encoder0 = encoder.getStructEncoderAtOffset(kDefaultStructInfo);
{%- endif %}
{%- for byte in struct.bytes %}
{%- for packed_field in byte.packed_fields %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl
index 3769585..d691cde 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/source.tmpl
@@ -12,13 +12,13 @@ package {{package}}
import (
"fmt"
-
- "mojo/public/go/bindings"
"mojo/public/go/system"
+{% for i in imports %}
+ {{i}}
+{% endfor %}
)
var _ = fmt.Errorf
-var _ = bindings.NewEncoder
var _ = system.GetCore
{% import "enum.tmpl" as enum_macros %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl
index eb6b121..c9f044a 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl
@@ -10,7 +10,7 @@ type {{struct|name(exported)}} struct {
}
func (s *{{struct|name(exported)}}) Encode(encoder *bindings.Encoder) error {
- encoder.StartStruct({{struct.versions[-1].num_bytes}}, {{struct.packed.packed_fields|length}})
+ encoder.StartStruct({{struct.versions[-1].num_bytes}}, {{struct.versions[-1].version}})
{% for byte in struct.bytes %}
{% for packed_field in byte.packed_fields %}
{{encode('s.'~packed_field.field|name(exported), packed_field.field.kind)|tab_indent()}}
@@ -24,7 +24,7 @@ func (s *{{struct|name(exported)}}) Encode(encoder *bindings.Encoder) error {
func (s *{{struct|name(exported)}}) Decode(decoder *bindings.Decoder) error {
{% if struct.bytes %}
- numFields, err := decoder.StartStruct()
+ version, err := decoder.StartStruct()
{% else %}
_, err := decoder.StartStruct()
{% endif %}
@@ -33,7 +33,7 @@ func (s *{{struct|name(exported)}}) Decode(decoder *bindings.Decoder) error {
}
{% for byte in struct.bytes %}
{% for packed_field in byte.packed_fields %}
- if numFields > {{packed_field.ordinal}} {
+ if version >= {{packed_field.min_version}} {
{{decode('s.'~packed_field.field|name(exported), packed_field.field.kind)|tab_indent(2)}}
}
{% endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface.java.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface.java.tmpl
index 10e5d7a..a13be3e 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface.java.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface.java.tmpl
@@ -1,4 +1,4 @@
{% from "interface_definition.tmpl" import interface_def %}
{% include "header.java.tmpl" %}
-{{ interface_def(interface, client) }}
+{{ interface_def(interface) }}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl
index 941fec7..e38c895 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl
@@ -36,14 +36,6 @@ interface {{method|interface_response_name}} extends org.chromium.mojo.bindings.
{%- endif -%}
{%- endmacro -%}
-{%- macro super_class(client, with_generic=True) -%}
-{%- if client -%}
-org.chromium.mojo.bindings.InterfaceWithClient{% if with_generic %}<{{client|java_type}}>{% endif %}
-{%- else -%}
-org.chromium.mojo.bindings.Interface
-{%- endif -%}
-{%- endmacro -%}
-
{%- macro flags_for_method(method, is_parameter) -%}
{{flags(method.response_parameters, is_parameter)}}
{%- endmacro -%}
@@ -58,15 +50,13 @@ org.chromium.mojo.bindings.MessageHeader.MESSAGE_IS_RESPONSE_FLAG
{%- endif -%}
{%- endmacro -%}
-{%- macro manager_class(interface, client, fully_qualified=False) -%}
-{% if fully_qualified %}{{super_class(client, False)}}.{% endif %}Manager<{{interface|name}}, {{interface|name}}.Proxy
-{%- if client -%}, {{client|java_type}}{%- endif -%}
->
+{%- macro manager_class(interface, fully_qualified=False) -%}
+{% if fully_qualified %}org.chromium.mojo.bindings.Interface.{% endif %}Manager<{{interface|name}}, {{interface|name}}.Proxy>
{%- endmacro -%}
-{%- macro manager_def(interface, client) -%}
-public static final {{manager_class(interface, client, True)}} MANAGER =
- new {{manager_class(interface, client, True)}}() {
+{%- macro manager_def(interface) -%}
+public static final {{manager_class(interface, True)}} MANAGER =
+ new {{manager_class(interface, True)}}() {
public String getName() {
return "{{namespace|replace(".","::")}}::{{interface.name}}";
@@ -84,12 +74,6 @@ public static final {{manager_class(interface, client, True)}} MANAGER =
public {{interface|name}}[] buildArray(int size) {
return new {{interface|name}}[size];
}
-{% if client %}
-
- protected org.chromium.mojo.bindings.Interface.Manager<{{client|java_type}}, ?> getClientManager() {
- return {{client|java_type}}.MANAGER;
- }
-{% endif %}
};
{%- endmacro -%}
@@ -134,8 +118,8 @@ return false;
{% endif %}
{%- endmacro -%}
-{% macro interface_def(interface, client) %}
-public interface {{interface|name}} extends {{super_class(client)}} {
+{% macro interface_def(interface) %}
+public interface {{interface|name}} extends org.chromium.mojo.bindings.Interface {
{% for constant in interface.constants %}
{{constant_def(constant)|indent(4)}}
@@ -145,10 +129,10 @@ public interface {{interface|name}} extends {{super_class(client)}} {
{{enum_def(enum, false)|indent(4)}}
{% endfor %}
- public interface Proxy extends {{interface|name}}, {{super_class(client, False)}}.Proxy{% if client %}<{{client|java_type}}>{% endif %} {
+ public interface Proxy extends {{interface|name}}, org.chromium.mojo.bindings.Interface.Proxy {
}
- {{manager_class(interface, client)}} MANAGER = {{interface|name}}_Internal.MANAGER;
+ {{manager_class(interface)}} MANAGER = {{interface|name}}_Internal.MANAGER;
{% for method in interface.methods %}
void {{method|name}}({{declare_request_params(method)}});
@@ -159,16 +143,16 @@ public interface {{interface|name}} extends {{super_class(client)}} {
}
{% endmacro %}
-{% macro interface_internal_def(interface, client) %}
+{% macro interface_internal_def(interface) %}
class {{interface|name}}_Internal {
- {{manager_def(interface, client)|indent(4)}}
+ {{manager_def(interface)|indent(4)}}
{% for method in interface.methods %}
private static final int {{method|method_ordinal_name}} = {{method.ordinal}};
{% endfor %}
- static final class Proxy extends {% if client %}org.chromium.mojo.bindings.InterfaceWithClient.AbstractProxy<{{client|java_type}}>{% else %}org.chromium.mojo.bindings.Interface.AbstractProxy{% endif %} implements {{interface|name}}.Proxy {
+ static final class Proxy extends org.chromium.mojo.bindings.Interface.AbstractProxy implements {{interface|name}}.Proxy {
Proxy(org.chromium.mojo.system.Core core,
org.chromium.mojo.bindings.MessageReceiverWithResponder messageReceiver) {
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_internal.java.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_internal.java.tmpl
index efb17f3..50c7a7b 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_internal.java.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_internal.java.tmpl
@@ -1,4 +1,4 @@
{% from "interface_definition.tmpl" import interface_internal_def %}
{% include "header.java.tmpl" %}
-{{ interface_internal_def(interface, client) }}
+{{ interface_internal_def(interface) }}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl
index 333e0da..f0cb982 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/struct_definition.tmpl
@@ -95,8 +95,8 @@ if (decoder{{level+1}} == null) {
}
{% else %}
DataHeader si{{level+1}} = decoder{{level+1}}.readDataHeaderForPointerArray({{kind|array_expected_length}});
- {{variable}} = {{kind|new_array('si'~(level+1)~'.numFields')}};
- for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numFields; ++i{{level+1}}) {
+ {{variable}} = {{kind|new_array('si'~(level+1)~'.elementsOrVersion')}};
+ for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.elementsOrVersion; ++i{{level+1}}) {
{{decode(variable~'[i'~(level+1)~']', kind.kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~(level+1), 0, level+1)|indent(8)}}
}
{% endif %}
@@ -111,7 +111,12 @@ if (decoder{{level+1}} == null) {
{{'static' if inner_class else 'public'}} final class {{struct|name}} extends org.chromium.mojo.bindings.Struct {
private static final int STRUCT_SIZE = {{struct.versions[-1].num_bytes}};
- private static final DataHeader DEFAULT_STRUCT_INFO = new DataHeader(STRUCT_SIZE, {{struct.packed.packed_fields|length}});
+ private static final DataHeader[] VERSION_ARRAY = new DataHeader[] {
+{%- for version in struct.versions -%}
+ new DataHeader({{version.num_bytes}}, {{version.version}}){% if not loop.last %}, {% endif -%}
+{%- endfor -%}
+ };
+ private static final DataHeader DEFAULT_STRUCT_INFO = VERSION_ARRAY[{{struct.versions|length - 1}}];
{% for constant in struct.constants %}
{{constant_def(constant)|indent(4)}}
@@ -149,13 +154,13 @@ if (decoder{{level+1}} == null) {
}
{{struct|name}} result = new {{struct|name}}();
{% if not struct.bytes %}
- decoder0.readDataHeader();
+ decoder0.readAndValidateDataHeader(VERSION_ARRAY);
{% else %}
- DataHeader mainDataHeader = decoder0.readDataHeader();
+ DataHeader mainDataHeader = decoder0.readAndValidateDataHeader(VERSION_ARRAY);
{% endif %}
{% for byte in struct.bytes %}
{% for packed_field in byte.packed_fields %}
- if (mainDataHeader.numFields > {{packed_field.ordinal}}) {
+ if (mainDataHeader.elementsOrVersion >= {{packed_field.min_version}}) {
{{decode('result.' ~ packed_field.field|name, packed_field.field.kind, 8+packed_field.offset, packed_field.bit)|indent(12)}}
}
{% endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py
index 1196276..bdcb84f 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_go_generator.py
@@ -57,6 +57,8 @@ _kind_infos = {
mojom.NULLABLE_STRING: KindInfo('string', 'String', 'String', 64),
}
+_imports = {}
+
def GetBitSize(kind):
if isinstance(kind, (mojom.Array, mojom.Map, mojom.Struct)):
return 64
@@ -66,14 +68,18 @@ def GetBitSize(kind):
kind = mojom.INT32
return _kind_infos[kind].bit_size
+# Returns go type corresponding to provided kind. If |nullable| is true
+# and kind is nullable adds an '*' to type (example: ?string -> *string).
def GetGoType(kind, nullable = True):
if nullable and mojom.IsNullableKind(kind):
return '*%s' % GetNonNullableGoType(kind)
return GetNonNullableGoType(kind)
+# Returns go type corresponding to provided kind. Ignores nullability of
+# top-level kind.
def GetNonNullableGoType(kind):
if mojom.IsStructKind(kind):
- return '%s' % FormatName(kind.name)
+ return '%s' % GetFullName(kind)
if mojom.IsArrayKind(kind):
if kind.length:
return '[%s]%s' % (kind.length, GetGoType(kind.kind))
@@ -86,6 +92,8 @@ def GetNonNullableGoType(kind):
return GetNameForNestedElement(kind)
return _kind_infos[kind].go_type
+# Splits name to lower-cased parts used for camel-casing
+# (example: HTTPEntry2FooBar -> ['http', 'entry2', 'foo', 'bar']).
def NameToComponent(name):
# insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
# HTTP_Entry2_FooBar)
@@ -98,24 +106,44 @@ def NameToComponent(name):
def UpperCamelCase(name):
return ''.join([x.capitalize() for x in NameToComponent(name)])
+# Formats a name. If |exported| is true makes name camel-cased with first
+# letter capital, otherwise does no camel-casing and makes first letter
+# lower-cased (which is used for making internal names more readable).
def FormatName(name, exported=True):
if exported:
return UpperCamelCase(name)
# Leave '_' symbols for unexported names.
return name[0].lower() + name[1:]
+# Returns full name of an imported element based on prebuilt dict |_imports|.
+# If the |element| is not imported returns formatted name of it.
+# |element| should have attr 'name'. |exported| argument is used to make
+# |FormatName()| calls only.
+def GetFullName(element, exported=True):
+ if not hasattr(element, 'imported_from') or not element.imported_from:
+ return FormatName(element.name, exported)
+ path = 'gen/mojom'
+ if element.imported_from['namespace']:
+ path = '/'.join([path] + element.imported_from['namespace'].split('.'))
+ if path in _imports:
+ return '%s.%s' % (_imports[path], FormatName(element.name, exported))
+ return FormatName(element.name, exported)
+
+# Returns a name for nested elements like enum field or constant.
+# The returned name consists of camel-cased parts separated by '_'.
def GetNameForNestedElement(element):
if element.parent_kind:
return "%s_%s" % (GetNameForElement(element.parent_kind),
FormatName(element.name))
- return FormatName(element.name)
+ return GetFullName(element)
def GetNameForElement(element, exported=True):
- if (mojom.IsInterfaceKind(element) or mojom.IsStructKind(element) or
- isinstance(element, (mojom.EnumField,
- mojom.Field,
- mojom.Method,
- mojom.Parameter))):
+ if (mojom.IsInterfaceKind(element) or mojom.IsStructKind(element)):
+ return GetFullName(element, exported)
+ if isinstance(element, (mojom.EnumField,
+ mojom.Field,
+ mojom.Method,
+ mojom.Parameter)):
return FormatName(element.name, exported)
if isinstance(element, (mojom.Enum,
mojom.Constant,
@@ -147,14 +175,14 @@ def EncodeSuffix(kind):
return EncodeSuffix(mojom.MSGPIPE)
return _kind_infos[kind].encode_suffix
-def GetPackage(module):
- if module.namespace:
- return module.namespace.split('.')[-1]
+def GetPackage(namespace):
+ if namespace:
+ return namespace.split('.')[-1]
return 'mojom'
-def GetPackagePath(module):
+def GetPackagePath(namespace):
path = 'mojom'
- for i in module.namespace.split('.'):
+ for i in namespace.split('.'):
path = os.path.join(path, i)
return path
@@ -182,6 +210,74 @@ def GetResponseStructFromMethod(method):
struct.versions = pack.GetVersionInfo(struct.packed)
return struct
+def GetAllConstants(module):
+ data = [module] + module.structs + module.interfaces
+ constants = [x.constants for x in data]
+ return [i for i in chain.from_iterable(constants)]
+
+def GetAllEnums(module):
+ data = [module] + module.structs + module.interfaces
+ enums = [x.enums for x in data]
+ return [i for i in chain.from_iterable(enums)]
+
+# Adds an import required to use the provided |element|.
+# The required import is stored at '_imports'.
+def AddImport(module, element):
+ if not hasattr(element, 'imported_from') or not element.imported_from:
+ return
+ if isinstance(element, mojom.Kind) and mojom.IsAnyHandleKind(element):
+ return
+ imported = element.imported_from
+ if imported['namespace'] == module.namespace:
+ return
+ path = 'gen/mojom'
+ name = 'mojom'
+ if imported['namespace']:
+ path = '/'.join([path] + imported['namespace'].split('.'))
+ name = '_'.join([name] + imported['namespace'].split('.'))
+ while (name in _imports.values() and _imports[path] != path):
+ name += '_'
+ _imports[path] = name
+
+# Scans |module| for elements that require imports and adds all found imports
+# to '_imports' dict. Returns a list of imports that should include the
+# generated go file.
+def GetImports(module):
+ # Imports can only be used in structs, constants, enums, interfaces.
+ all_structs = list(module.structs)
+ for i in module.interfaces:
+ AddImport(module, i)
+ for method in i.methods:
+ all_structs.append(GetStructFromMethod(method))
+ if method.response_parameters:
+ all_structs.append(GetResponseStructFromMethod(method))
+
+ if len(all_structs) > 0:
+ _imports['mojo/public/go/bindings'] = 'bindings'
+ for struct in all_structs:
+ for field in struct.fields:
+ AddImport(module, field.kind)
+# TODO(rogulenko): add these after generating constants and struct defaults.
+# if field.default:
+# AddImport(module, field.default)
+
+ for enum in GetAllEnums(module):
+ for field in enum.fields:
+ if field.value:
+ AddImport(module, field.value)
+
+# TODO(rogulenko): add these after generating constants and struct defaults.
+# for constant in GetAllConstants(module):
+# AddImport(module, constant.value)
+
+ imports_list = []
+ for i in _imports:
+ if i.split('/')[-1] == _imports[i]:
+ imports_list.append('"%s"' % i)
+ else:
+ imports_list.append('%s "%s"' % (_imports[i], i))
+ return sorted(imports_list)
+
class Generator(generator.Generator):
go_filters = {
'array': lambda kind: mojom.Array(kind),
@@ -204,16 +300,12 @@ class Generator(generator.Generator):
'tab_indent': lambda s, size = 1: ('\n' + '\t' * size).join(s.splitlines())
}
- def GetAllEnums(self):
- data = [self.module] + self.GetStructs() + self.module.interfaces
- enums = [x.enums for x in data]
- return [i for i in chain.from_iterable(enums)]
-
def GetParameters(self):
return {
- 'enums': self.GetAllEnums(),
+ 'enums': GetAllEnums(self.module),
+ 'imports': GetImports(self.module),
'interfaces': self.module.interfaces,
- 'package': GetPackage(self.module),
+ 'package': GetPackage(self.module.namespace),
'structs': self.GetStructs(),
}
@@ -223,7 +315,7 @@ class Generator(generator.Generator):
def GenerateFiles(self, args):
self.Write(self.GenerateSource(), os.path.join("go", "src", "gen",
- GetPackagePath(self.module), '%s.go' % self.module.name))
+ GetPackagePath(self.module.namespace), '%s.go' % self.module.name))
def GetJinjaParameters(self):
return {
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py
index f279ef8..d6712f3 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -422,15 +422,6 @@ class Generator(generator.Generator):
def GetJinjaExportsForInterface(self, interface):
exports = self.GetJinjaExports()
exports.update({'interface': interface})
- if interface.client:
- all_interfaces = [] + self.module.interfaces
- for each in self.module.imports:
- all_interfaces += each['module'].interfaces
- interfaces_by_name = dict((x.name, x) for x in all_interfaces)
- assert interface.client in interfaces_by_name, (
- 'Unable to find interface %s declared as client of %s.' %
- (interface.client, interface.name))
- exports.update({'client': interfaces_by_name[interface.client]})
return exports
@UseJinja('java_templates/enum.java.tmpl', filters=java_filters)
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py
index d4d4ed7..cbb1962 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py
@@ -176,7 +176,7 @@ def GetFieldDescriptor(packed_field):
arguments = [ '%r' % GetNameForElement(field) ]
arguments.append(GetFieldType(field.kind, field))
arguments.append(str(packed_field.index))
- arguments.append(str(packed_field.ordinal))
+ arguments.append(str(packed_field.min_version))
if field.default:
if mojom.IsStructKind(field.kind):
arguments.append('default_value=True')
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
index 3b2874f..0a8e0f2 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
+++ b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
@@ -60,7 +60,6 @@ template("mojom") {
"$generator_root/generators/cpp_templates/module.cc.tmpl",
"$generator_root/generators/cpp_templates/module.h.tmpl",
"$generator_root/generators/cpp_templates/module-internal.h.tmpl",
- "$generator_root/generators/cpp_templates/params_definition.tmpl",
"$generator_root/generators/cpp_templates/serialization_macros.tmpl",
"$generator_root/generators/cpp_templates/struct_declaration.tmpl",
"$generator_root/generators/cpp_templates/struct_definition.tmpl",
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py
index c2e59a6..8d052d9 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -131,7 +131,6 @@ PRIMITIVES = (
ATTRIBUTE_MIN_VERSION = 'MinVersion'
-ATTRIBUTE_CLIENT = 'Client'
class NamedValue(object):
@@ -271,16 +270,16 @@ class Map(ReferenceKind):
'm[' + key_kind.spec + '][' + value_kind.spec +
']')
if IsNullableKind(key_kind):
- raise Exception("Nullable kinds can not be keys in maps.")
+ raise Exception("Nullable kinds cannot be keys in maps.")
if IsStructKind(key_kind):
# TODO(erg): It would sometimes be nice if we could key on struct
# values. However, what happens if the struct has a handle in it? Or
# non-copyable data like an array?
- raise Exception("Structs can not be keys in maps.")
+ raise Exception("Structs cannot be keys in maps.")
if IsAnyHandleKind(key_kind):
- raise Exception("Handles can not be keys in maps.")
+ raise Exception("Handles cannot be keys in maps.")
if IsArrayKind(key_kind):
- raise Exception("Arrays can not be keys in maps.")
+ raise Exception("Arrays cannot be keys in maps.")
else:
ReferenceKind.__init__(self)
@@ -370,9 +369,10 @@ class Interface(ReferenceKind):
self.methods.append(method)
return method
+ # TODO(451323): Remove when the language backends no longer rely on this.
@property
def client(self):
- return self.attributes.get(ATTRIBUTE_CLIENT) if self.attributes else None
+ return None
class EnumField(object):
diff --git a/third_party/mojo/src/mojo/public/tools/download_network_service.py b/third_party/mojo/src/mojo/public/tools/download_network_service.py
new file mode 100755
index 0000000..43b1172
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/download_network_service.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import sys
+import tempfile
+import zipfile
+
+_PLATFORMS = ["linux-x64", "android-arm"]
+_APPS = ["network_service", "network_service_apptests"]
+_CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
+sys.path.insert(0, os.path.join(_CURRENT_PATH, "pylib"))
+import gs
+
+if not sys.platform.startswith("linux"):
+ print "Not supported for your platform"
+ sys.exit(0)
+
+script_dir = os.path.dirname(os.path.realpath(__file__))
+
+
+def download_app(app, version, tools_directory):
+ prebuilt_directory = os.path.join(script_dir, "prebuilt/%s" % app)
+ stamp_path = os.path.join(prebuilt_directory, "VERSION")
+
+ try:
+ with open(stamp_path) as stamp_file:
+ current_version = stamp_file.read().strip()
+ if current_version == version:
+ return # Already have the right version.
+ except IOError:
+ pass # If the stamp file does not exist we need to download a new binary.
+
+ for platform in _PLATFORMS:
+ download_app_for_platform(app, version, platform, tools_directory)
+
+ with open(stamp_path, 'w') as stamp_file:
+ stamp_file.write(version)
+
+def download_app_for_platform(app, version, platform, tools_directory):
+ find_depot_tools_path = os.path.join(_CURRENT_PATH, tools_directory)
+ sys.path.insert(0, find_depot_tools_path)
+ # pylint: disable=F0401
+ import find_depot_tools
+ depot_tools_path = find_depot_tools.add_depot_tools_to_path()
+
+ binary_name = app + ".mojo"
+ gs_path = "gs://mojo/%s/%s/%s/%s.zip" % (app, version, platform, binary_name)
+ output_directory = os.path.join(script_dir,
+ "prebuilt/%s/%s" % (app, platform))
+
+ with tempfile.NamedTemporaryFile() as temp_zip_file:
+ gs.download_from_public_bucket(gs_path, temp_zip_file.name,
+ depot_tools_path)
+ with zipfile.ZipFile(temp_zip_file.name) as z:
+ zi = z.getinfo(binary_name)
+ mode = zi.external_attr >> 16
+ z.extract(zi, output_directory)
+ os.chmod(os.path.join(output_directory, binary_name), mode)
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Download prebuilt network service binaries from google " +
+ "storage")
+ parser.add_argument("--tools-directory",
+ dest="tools_directory",
+ metavar="<tools-directory>",
+ type=str,
+ required=True,
+ help="Path to the directory containing "
+ "find_depot_tools.py, specified as a relative path "
+ "from the location of this file.")
+ args = parser.parse_args()
+
+ version_path = os.path.join(script_dir, "NETWORK_SERVICE_VERSION")
+ with open(version_path) as version_file:
+ version = version_file.read().strip()
+
+ for app in _APPS:
+ download_app(app, version, args.tools_directory)
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/third_party/mojo/src/mojo/public/tools/download_shell_binary.py b/third_party/mojo/src/mojo/public/tools/download_shell_binary.py
index ee74231..512e3a6 100755
--- a/third_party/mojo/src/mojo/public/tools/download_shell_binary.py
+++ b/third_party/mojo/src/mojo/public/tools/download_shell_binary.py
@@ -20,7 +20,10 @@ if not sys.platform.startswith("linux"):
sys.exit(0)
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
-PREBUILT_FILE_PATH = os.path.join(CURRENT_PATH, "prebuilt")
+sys.path.insert(0, os.path.join(CURRENT_PATH, "pylib"))
+import gs
+
+PREBUILT_FILE_PATH = os.path.join(CURRENT_PATH, "prebuilt", "shell")
def download(tools_directory):
@@ -50,44 +53,21 @@ def download_version_for_platform(version, platform, tools_directory):
sys.path.insert(0, find_depot_tools_path)
# pylint: disable=F0401
import find_depot_tools
+ depot_tools_path = find_depot_tools.add_depot_tools_to_path()
basename = platform + ".zip"
gs_path = "gs://mojo/shell/" + version + "/" + basename
- depot_tools_path = find_depot_tools.add_depot_tools_to_path()
- gsutil_exe = os.path.join(depot_tools_path, "third_party", "gsutil", "gsutil")
-
with tempfile.NamedTemporaryFile() as temp_zip_file:
- # We're downloading from a public bucket which does not need authentication,
- # but the user might have busted credential files somewhere such as ~/.boto
- # that the gsutil script will try (and fail) to use. Setting these
- # environment variables convinces gsutil not to attempt to use these, but
- # also generates a useless warning about failing to load the file. We want
- # to discard this warning but still preserve all output in the case of an
- # actual failure. So, we run the script and capture all output and then
- # throw the output away if the script succeeds (return code 0).
- env = os.environ.copy()
- env["AWS_CREDENTIAL_FILE"] = ""
- env["BOTO_CONFIG"] = ""
- try:
- subprocess.check_output(
- [gsutil_exe,
- "--bypass_prodaccess",
- "cp",
- gs_path,
- temp_zip_file.name],
- stderr=subprocess.STDOUT,
- env=env)
- except subprocess.CalledProcessError as e:
- print e.output
- sys.exit(1)
-
+ gs.download_from_public_bucket(gs_path, temp_zip_file.name,
+ depot_tools_path)
binary_name = BINARY_FOR_PLATFORM[platform]
+ output_dir = os.path.join(PREBUILT_FILE_PATH, platform)
with zipfile.ZipFile(temp_zip_file.name) as z:
zi = z.getinfo(binary_name)
mode = zi.external_attr >> 16
- z.extract(zi, PREBUILT_FILE_PATH)
- os.chmod(os.path.join(PREBUILT_FILE_PATH, binary_name), mode)
+ z.extract(zi, output_dir)
+ os.chmod(os.path.join(output_dir, binary_name), mode)
def main():
@@ -97,13 +77,11 @@ def main():
dest="tools_directory",
metavar="<tools-directory>",
type=str,
- help="Path to the directory containing"
- " find_depot_tools.py, specified as a relative path"
- " from the location of this file.")
+ required=True,
+ help="Path to the directory containing "
+ "find_depot_tools.py, specified as a relative path "
+ "from the location of this file.")
args = parser.parse_args()
- if not args.tools_directory:
- print "Must specify --tools_directory; please see help message."
- sys.exit(1)
return download(args.tools_directory)
if __name__ == "__main__":
diff --git a/third_party/mojo/src/mojo/public/tools/pylib/gs.py b/third_party/mojo/src/mojo/public/tools/pylib/gs.py
new file mode 100644
index 0000000..f8761b5
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/tools/pylib/gs.py
@@ -0,0 +1,34 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import sys
+
+def download_from_public_bucket(gs_path, output_path, depot_tools_path):
+ gsutil_exe = os.path.join(depot_tools_path, "third_party", "gsutil", "gsutil")
+
+ # We're downloading from a public bucket which does not need authentication,
+ # but the user might have busted credential files somewhere such as ~/.boto
+ # that the gsutil script will try (and fail) to use. Setting these
+ # environment variables convinces gsutil not to attempt to use these, but
+ # also generates a useless warning about failing to load the file. We want
+ # to discard this warning but still preserve all output in the case of an
+ # actual failure. So, we run the script and capture all output and then
+ # throw the output away if the script succeeds (return code 0).
+ env = os.environ.copy()
+ env["AWS_CREDENTIAL_FILE"] = ""
+ env["BOTO_CONFIG"] = ""
+ try:
+ subprocess.check_output(
+ [gsutil_exe,
+ "--bypass_prodaccess",
+ "cp",
+ gs_path,
+ output_path],
+ stderr=subprocess.STDOUT,
+ env=env)
+ except subprocess.CalledProcessError as e:
+ print e.output
+ sys.exit(1)
diff --git a/third_party/mojo_services/src/public/js/application.js b/third_party/mojo_services/src/public/js/application.js
index aea60fd..cadba0f 100644
--- a/third_party/mojo_services/src/public/js/application.js
+++ b/third_party/mojo_services/src/public/js/application.js
@@ -30,7 +30,7 @@ define("mojo/services/public/js/application", [
};
}
- doInitialize(shellProxy, args) {
+ doInitialize(shellProxy, args, url) {
this.shellProxy_ = shellProxy;
this.shell = new Shell(shellProxy);
this.initialize(args);
diff --git a/third_party/mojo_services/src/public/js/service_exchange.js b/third_party/mojo_services/src/public/js/service_exchange.js
index a424c12..f23c0ef 100644
--- a/third_party/mojo_services/src/public/js/service_exchange.js
+++ b/third_party/mojo_services/src/public/js/service_exchange.js
@@ -47,7 +47,7 @@ define("mojo/services/public/js/service_exchange", [
var provider = {
service: service, // A JS bindings interface object.
- factory: factory, // factory(clientProxy) => interface implemntation
+ factory: factory, // factory() => interface implemntation
connections: [],
};
this.providers_.set(service.name, provider);
@@ -60,12 +60,10 @@ define("mojo/services/public/js/service_exchange", [
}
// Outgoing requests
- requestService(interfaceObject, clientImpl) {
+ requestService(interfaceObject) {
checkServiceExchange(this);
if (!interfaceObject.name)
throw new Error("Invalid service parameter");
- if (!clientImpl && interfaceObject.client)
- throw new Error("Client implementation must be provided");
var serviceProxy;
var serviceHandle = connection.bindProxy(
diff --git a/third_party/mojo_services/src/public/js/shell.js b/third_party/mojo_services/src/public/js/shell.js
index 358f272..e8bab6f 100644
--- a/third_party/mojo_services/src/public/js/shell.js
+++ b/third_party/mojo_services/src/public/js/shell.js
@@ -41,8 +41,8 @@ define("mojo/services/public/js/shell", [
return application;
}
- connectToService(url, service, client) {
- return this.connectToApplication(url).requestService(service, client);
+ connectToService(url, service) {
+ return this.connectToApplication(url).requestService(service);
};
close() {
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/BUILD.gn b/third_party/mojo_services/src/view_manager/public/cpp/BUILD.gn
index b1a0bdb..72cb55e 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/BUILD.gn
+++ b/third_party/mojo_services/src/view_manager/public/cpp/BUILD.gn
@@ -45,6 +45,7 @@ mojo_sdk_source_set("cpp") {
"mojo/public/c/gles2:headers",
"mojo/public/cpp/application",
"mojo/public/cpp/bindings:bindings",
+ "mojo/public/cpp/system",
"mojo/public/interfaces/application",
]
}
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view.cc
index 1e8b2b0..9ed458c 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view.cc
+++ b/third_party/mojo_services/src/view_manager/public/cpp/lib/view.cc
@@ -77,7 +77,7 @@ class ScopedTreeNotifier {
private:
ViewObserver::TreeChangeParams params_;
- DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier);
};
void RemoveChildImpl(View* child, View::Children* children) {
@@ -112,7 +112,7 @@ class ScopedOrderChangedNotifier {
View* relative_view_;
OrderDirection direction_;
- DISALLOW_COPY_AND_ASSIGN(ScopedOrderChangedNotifier);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedOrderChangedNotifier);
};
// Returns true if the order actually changed.
@@ -168,7 +168,7 @@ class ScopedSetBoundsNotifier {
const Rect old_bounds_;
const Rect new_bounds_;
- DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsNotifier);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsNotifier);
};
// Some operations are only permitted in the connection that created the view.
@@ -220,9 +220,7 @@ void View::SetVisible(bool value) {
if (manager_)
static_cast<ViewManagerClientImpl*>(manager_)->SetVisible(id_, value);
- FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanging(this));
- visible_ = value;
- NotifyViewVisibilityChanged(this);
+ LocalSetVisible(value);
}
void View::SetSharedProperty(const std::string& name,
@@ -531,6 +529,15 @@ void View::LocalSetDrawn(bool value) {
FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDrawnChanged(this));
}
+void View::LocalSetVisible(bool visible) {
+ if (visible_ == visible)
+ return;
+
+ FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanging(this));
+ visible_ = visible;
+ NotifyViewVisibilityChanged(this);
+}
+
void View::NotifyViewVisibilityChanged(View* target) {
if (!NotifyViewVisibilityChangedDown(target)) {
return; // |this| has been deleted.
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_factory.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_factory.cc
index cfa2b79..bb39fc9 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_factory.cc
+++ b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_factory.cc
@@ -19,17 +19,16 @@ ViewManagerClientFactory::~ViewManagerClientFactory() {
}
// static
-scoped_ptr<ViewManagerClient>
-ViewManagerClientFactory::WeakBindViewManagerToPipe(
+ViewManagerClient* ViewManagerClientFactory::WeakBindViewManagerToPipe(
InterfaceRequest<ViewManagerClient> request,
ViewManagerServicePtr view_manager_service,
Shell* shell,
ViewManagerDelegate* delegate) {
const bool delete_on_error = false;
- scoped_ptr<ViewManagerClientImpl> client(new ViewManagerClientImpl(
- delegate, shell, request.Pass(), delete_on_error));
+ auto client = new ViewManagerClientImpl(delegate, shell, request.Pass(),
+ delete_on_error);
client->SetViewManagerService(view_manager_service.Pass());
- return client.Pass();
+ return client;
}
// InterfaceFactory<ViewManagerClient> implementation.
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.cc
index 574d300..9a3c022 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.cc
+++ b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.cc
@@ -4,9 +4,6 @@
#include "view_manager/public/cpp/lib/view_manager_client_impl.h"
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/public/cpp/application/service_provider_impl.h"
@@ -90,7 +87,7 @@ class RootObserver : public ViewObserver {
View* root_;
- DISALLOW_COPY_AND_ASSIGN(RootObserver);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(RootObserver);
};
ViewManagerClientImpl::ViewManagerClientImpl(
@@ -236,7 +233,9 @@ void ViewManagerClientImpl::SetViewManagerService(
Id ViewManagerClientImpl::CreateViewOnServer() {
DCHECK(service_);
const Id view_id = MakeTransportId(connection_id_, ++next_id_);
- service_->CreateView(view_id, ActionCompletedCallbackWithErrorCode());
+ service_->CreateView(view_id, [this](ErrorCode code) {
+ OnActionCompleted(code == ERROR_CODE_NONE);
+ });
return view_id;
}
@@ -286,14 +285,21 @@ void ViewManagerClientImpl::OnEmbed(
root_->AddObserver(new RootObserver(root_));
window_manager_.Bind(window_manager_pipe.Pass());
- // base::Unretained() is safe here as |window_manager_| is bound to our
- // lifetime.
WindowManagerObserverPtr observer;
wm_observer_binding_.Bind(GetProxy(&observer));
+ // binding to |this| is safe here as |window_manager_| is bound to our
+ // lifetime.
window_manager_->GetFocusedAndActiveViews(
observer.Pass(),
- base::Bind(&ViewManagerClientImpl::OnGotFocusedAndActiveViews,
- base::Unretained(this)));
+ [this](uint32_t capture_view_id, uint32_t focused_view_id,
+ uint32_t active_view_id) {
+ if (GetViewById(capture_view_id) != capture_view_)
+ OnCaptureChanged(capture_view_id);
+ if (GetViewById(focused_view_id) != focused_view_)
+ OnFocusChanged(focused_view_id);
+ if (GetViewById(active_view_id) != activated_view_)
+ OnActiveWindowChanged(active_view_id);
+ });
delegate_->OnEmbed(root_, services.Pass(), exposed_services.Pass());
}
@@ -373,7 +379,7 @@ void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) {
// Deal with this some how.
View* view = GetViewById(view_id);
if (view)
- view->SetVisible(visible);
+ ViewPrivate(view).LocalSetVisible(visible);
}
void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) {
@@ -483,31 +489,8 @@ void ViewManagerClientImpl::OnActionCompleted(bool success) {
change_acked_callback_.Run();
}
-void ViewManagerClientImpl::OnActionCompletedWithErrorCode(ErrorCode code) {
- OnActionCompleted(code == ERROR_CODE_NONE);
-}
-
-base::Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() {
- return base::Bind(&ViewManagerClientImpl::OnActionCompleted,
- base::Unretained(this));
-}
-
-base::Callback<void(ErrorCode)>
- ViewManagerClientImpl::ActionCompletedCallbackWithErrorCode() {
- return base::Bind(&ViewManagerClientImpl::OnActionCompletedWithErrorCode,
- base::Unretained(this));
-}
-
-void ViewManagerClientImpl::OnGotFocusedAndActiveViews(
- uint32_t capture_view_id,
- uint32_t focused_view_id,
- uint32_t active_view_id) {
- if (GetViewById(capture_view_id) != capture_view_)
- OnCaptureChanged(capture_view_id);
- if (GetViewById(focused_view_id) != focused_view_)
- OnFocusChanged(focused_view_id);
- if (GetViewById(active_view_id) != activated_view_)
- OnActiveWindowChanged(active_view_id);
+Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() {
+ return [this](bool success) { OnActionCompleted(success); };
}
} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h
index c3a2ad5..94db93d 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h
@@ -5,9 +5,6 @@
#ifndef MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_MANAGER_CLIENT_IMPL_H_
#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_MANAGER_CLIENT_IMPL_H_
-#include "base/callback.h"
-#include "base/memory/scoped_vector.h"
-#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "view_manager/public/cpp/types.h"
#include "view_manager/public/cpp/view.h"
@@ -66,12 +63,10 @@ class ViewManagerClientImpl : public ViewManager,
ServiceProviderPtr exposed_services);
void Embed(Id view_id, ViewManagerClientPtr client);
- void set_change_acked_callback(const base::Callback<void(void)>& callback) {
+ void set_change_acked_callback(const Callback<void(void)>& callback) {
change_acked_callback_ = callback;
}
- void ClearChangeAckedCallback() {
- change_acked_callback_ = base::Callback<void(void)>();
- }
+ void ClearChangeAckedCallback() { change_acked_callback_.reset(); }
// Start/stop tracking views. While tracked, they can be retrieved via
// ViewManager::GetViewById.
@@ -136,22 +131,15 @@ class ViewManagerClientImpl : public ViewManager,
void RootDestroyed(View* root);
void OnActionCompleted(bool success);
- void OnActionCompletedWithErrorCode(ErrorCode code);
-
- base::Callback<void(bool)> ActionCompletedCallback();
- base::Callback<void(ErrorCode)> ActionCompletedCallbackWithErrorCode();
- // Callback from server for initial request of capture/focused/active views.
- void OnGotFocusedAndActiveViews(uint32_t capture_view_id,
- uint32_t focused_view_id,
- uint32_t active_view_id);
+ Callback<void(bool)> ActionCompletedCallback();
ConnectionSpecificId connection_id_;
ConnectionSpecificId next_id_;
std::string creator_url_;
- base::Callback<void(void)> change_acked_callback_;
+ Callback<void(void)> change_acked_callback_;
ViewManagerDelegate* delegate_;
@@ -170,7 +158,7 @@ class ViewManagerClientImpl : public ViewManager,
ViewManagerServicePtr service_;
const bool delete_on_error_;
- DISALLOW_COPY_AND_ASSIGN(ViewManagerClientImpl);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerClientImpl);
};
} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_context.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_context.cc
index a47f59a..d1c2fd0 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_context.cc
+++ b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_context.cc
@@ -28,7 +28,9 @@ class ViewManagerContext::InternalState {
ViewManagerContext::ViewManagerContext(ApplicationImpl* application_impl)
: state_(new InternalState(application_impl)) {}
-ViewManagerContext::~ViewManagerContext() {}
+ViewManagerContext::~ViewManagerContext() {
+ delete state_;
+}
void ViewManagerContext::Embed(const String& url) {
Embed(url, nullptr, nullptr);
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_observer.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_observer.cc
index 456147c..7e6acc0 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_observer.cc
+++ b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_observer.cc
@@ -4,17 +4,16 @@
#include "view_manager/public/cpp/view_observer.h"
-#include "base/basictypes.h"
-
namespace mojo {
////////////////////////////////////////////////////////////////////////////////
// ViewObserver, public:
ViewObserver::TreeChangeParams::TreeChangeParams()
- : target(NULL),
- old_parent(NULL),
- new_parent(NULL),
- receiver(NULL) {}
+ : target(nullptr),
+ old_parent(nullptr),
+ new_parent(nullptr),
+ receiver(nullptr) {
+}
} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h
index 1c54567..0b58280 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h
@@ -5,8 +5,6 @@
#ifndef MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_PRIVATE_H_
#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_PRIVATE_H_
-#include "base/basictypes.h"
-
#include "view_manager/public/cpp/view.h"
namespace mojo {
@@ -61,11 +59,12 @@ class ViewPrivate {
view_->LocalSetBounds(old_bounds, new_bounds);
}
void LocalSetDrawn(bool drawn) { view_->LocalSetDrawn(drawn); }
+ void LocalSetVisible(bool visible) { view_->LocalSetVisible(visible); }
private:
View* view_;
- DISALLOW_COPY_AND_ASSIGN(ViewPrivate);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ViewPrivate);
};
} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/BUILD.gn b/third_party/mojo_services/src/view_manager/public/cpp/tests/BUILD.gn
index 3414d33..0adbb5d 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/tests/BUILD.gn
+++ b/third_party/mojo_services/src/view_manager/public/cpp/tests/BUILD.gn
@@ -10,7 +10,6 @@ test("mojo_view_manager_lib_unittests") {
"run_all_unittests.cc",
"view_manager_test_suite.cc",
"view_manager_test_suite.h",
- "view_manager_unittest.cc",
"view_unittest.cc",
]
@@ -18,11 +17,10 @@ test("mojo_view_manager_lib_unittests") {
"//base",
"//base/test:test_support",
"//mojo/public/cpp/application",
+ "//mojo/public/cpp/system",
"//mojo/services/geometry/public/cpp",
"//mojo/services/geometry/public/interfaces",
"//mojo/services/view_manager/public/cpp",
- "//mojo/services/view_manager/public/interfaces",
- "//shell/application_manager",
"//shell:test_support",
"//testing/gtest",
]
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.h b/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.h
index ef81661..547efc2 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.h
@@ -6,6 +6,7 @@
#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_TESTS_VIEW_MANAGER_TEST_SUITE_H_
#include "base/test/test_suite.h"
+#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@@ -18,7 +19,7 @@ class ViewManagerTestSuite : public base::TestSuite {
void Initialize() override;
private:
- DISALLOW_COPY_AND_ASSIGN(ViewManagerTestSuite);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerTestSuite);
};
} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_unittest.cc b/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_unittest.cc
deleted file mode 100644
index bc69464..0000000
--- a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_unittest.cc
+++ /dev/null
@@ -1,652 +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/services/view_manager/public/cpp/view_manager.h"
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/logging.h"
-#include "mojo/public/cpp/application/application_connection.h"
-#include "mojo/public/cpp/application/application_delegate.h"
-#include "mojo/public/cpp/application/application_impl.h"
-#include "mojo/public/cpp/application/service_provider_impl.h"
-#include "mojo/public/interfaces/application/service_provider.mojom.h"
-#include "mojo/services/geometry/public/cpp/geometry_util.h"
-#include "mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h"
-#include "mojo/services/view_manager/public/cpp/lib/view_private.h"
-#include "mojo/services/view_manager/public/cpp/util.h"
-#include "mojo/services/view_manager/public/cpp/view_manager_client_factory.h"
-#include "mojo/services/view_manager/public/cpp/view_manager_delegate.h"
-#include "mojo/services/view_manager/public/cpp/view_observer.h"
-#include "shell/application_manager/application_manager.h"
-#include "shell/shell_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-
-namespace {
-
-const char kWindowManagerURL[] = "mojo:window_manager";
-const char kEmbeddedApp1URL[] = "mojo:embedded_app_1";
-
-base::RunLoop* current_run_loop = NULL;
-
-void DoRunLoop() {
- base::RunLoop run_loop;
- current_run_loop = &run_loop;
- current_run_loop->Run();
- current_run_loop = NULL;
-}
-
-void QuitRunLoop() {
- current_run_loop->Quit();
-}
-
-class ConnectApplicationLoader : public ApplicationLoader,
- public ApplicationDelegate,
- public ViewManagerDelegate {
- public:
- typedef base::Callback<void(View*)> LoadedCallback;
-
- explicit ConnectApplicationLoader(const LoadedCallback& callback)
- : callback_(callback) {}
- ~ConnectApplicationLoader() override {}
-
- private:
- // Overridden from ApplicationDelegate:
- void Initialize(ApplicationImpl* app) override {
- view_manager_client_factory_.reset(
- new ViewManagerClientFactory(app->shell(), this));
- }
-
- // Overridden from ApplicationLoader:
- void Load(ApplicationManager* manager,
- const GURL& url,
- InterfaceRequest<Application> application_request,
- LoadCallback callback) override {
- ASSERT_TRUE(application_request.is_pending());
- scoped_ptr<ApplicationImpl> app(
- new ApplicationImpl(this, application_request.Pass()));
- apps_.push_back(app.release());
- }
-
- void OnApplicationError(ApplicationManager* manager,
- const GURL& url) override {}
-
- bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
- connection->AddService(view_manager_client_factory_.get());
- return true;
- }
-
- // Overridden from ViewManagerDelegate:
- void OnEmbed(View* root,
- InterfaceRequest<ServiceProvider> services,
- ServiceProviderPtr exposed_services) override {
- callback_.Run(root);
- }
- void OnViewManagerDisconnected(ViewManager* view_manager) override {}
-
- ScopedVector<ApplicationImpl> apps_;
- LoadedCallback callback_;
- scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ConnectApplicationLoader);
-};
-
-class BoundsChangeObserver : public ViewObserver {
- public:
- explicit BoundsChangeObserver(View* view) : view_(view) {}
- ~BoundsChangeObserver() override {}
-
- private:
- // Overridden from ViewObserver:
- void OnViewBoundsChanged(View* view,
- const Rect& old_bounds,
- const Rect& new_bounds) override {
- DCHECK_EQ(view, view_);
- QuitRunLoop();
- }
-
- View* view_;
-
- DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
-};
-
-// Wait until the bounds of the supplied view change.
-void WaitForBoundsToChange(View* view) {
- BoundsChangeObserver observer(view);
- view->AddObserver(&observer);
- DoRunLoop();
- view->RemoveObserver(&observer);
-}
-
-// Spins a runloop until the tree beginning at |root| has |tree_size| views
-// (including |root|).
-class TreeSizeMatchesObserver : public ViewObserver {
- public:
- TreeSizeMatchesObserver(View* tree, size_t tree_size)
- : tree_(tree),
- tree_size_(tree_size) {}
- ~TreeSizeMatchesObserver() override {}
-
- bool IsTreeCorrectSize() {
- return CountViews(tree_) == tree_size_;
- }
-
- private:
- // Overridden from ViewObserver:
- void OnTreeChanged(const TreeChangeParams& params) override {
- if (IsTreeCorrectSize())
- QuitRunLoop();
- }
-
- size_t CountViews(const View* view) const {
- size_t count = 1;
- View::Children::const_iterator it = view->children().begin();
- for (; it != view->children().end(); ++it)
- count += CountViews(*it);
- return count;
- }
-
- View* tree_;
- size_t tree_size_;
-
- DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver);
-};
-
-void WaitForTreeSizeToMatch(View* view, size_t tree_size) {
- TreeSizeMatchesObserver observer(view, tree_size);
- if (observer.IsTreeCorrectSize())
- return;
- view->AddObserver(&observer);
- DoRunLoop();
- view->RemoveObserver(&observer);
-}
-
-// Utility class that waits for the destruction of some number of views and
-// views.
-class DestructionObserver : public ViewObserver {
- public:
- // |views| or |views| can be NULL.
- explicit DestructionObserver(std::set<Id>* views) : views_(views) {}
-
- private:
- // Overridden from ViewObserver:
- void OnViewDestroyed(View* view) override {
- std::set<Id>::iterator it = views_->find(view->id());
- if (it != views_->end())
- views_->erase(it);
- if (CanQuit())
- QuitRunLoop();
- }
-
- bool CanQuit() {
- return !views_ || views_->empty();
- }
-
- std::set<Id>* views_;
-
- DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
-};
-
-void WaitForDestruction(ViewManager* view_manager, std::set<Id>* views) {
- DestructionObserver observer(views);
- DCHECK(views);
- if (views) {
- for (std::set<Id>::const_iterator it = views->begin();
- it != views->end(); ++it) {
- view_manager->GetViewById(*it)->AddObserver(&observer);
- }
- }
- DoRunLoop();
-}
-
-class OrderChangeObserver : public ViewObserver {
- public:
- OrderChangeObserver(View* view) : view_(view) {
- view_->AddObserver(this);
- }
- ~OrderChangeObserver() override { view_->RemoveObserver(this); }
-
- private:
- // Overridden from ViewObserver:
- void OnViewReordered(View* view,
- View* relative_view,
- OrderDirection direction) override {
- DCHECK_EQ(view, view_);
- QuitRunLoop();
- }
-
- View* view_;
-
- DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
-};
-
-void WaitForOrderChange(ViewManager* view_manager, View* view) {
- OrderChangeObserver observer(view);
- DoRunLoop();
-}
-
-// Tracks a view's destruction. Query is_valid() for current state.
-class ViewTracker : public ViewObserver {
- public:
- explicit ViewTracker(View* view) : view_(view) {
- view_->AddObserver(this);
- }
- ~ViewTracker() override {
- if (view_)
- view_->RemoveObserver(this);
- }
-
- bool is_valid() const { return !!view_; }
-
- private:
- // Overridden from ViewObserver:
- void OnViewDestroyed(View* view) override {
- DCHECK_EQ(view, view_);
- view_ = NULL;
- }
-
- int id_;
- View* view_;
-
- DISALLOW_COPY_AND_ASSIGN(ViewTracker);
-};
-
-} // namespace
-
-// ViewManager -----------------------------------------------------------------
-
-// These tests model synchronization of two peer connections to the view manager
-// service, that are given access to some root view.
-
-class ViewManagerTest : public testing::Test {
- public:
- ViewManagerTest()
- : connect_loop_(NULL),
- loaded_view_manager_(NULL),
- window_manager_(NULL),
- commit_count_(0) {}
-
- protected:
- ViewManager* window_manager() { return window_manager_; }
-
- View* CreateViewInParent(View* parent) {
- ViewManager* parent_manager = parent->view_manager();
- View* view = parent_manager->CreateView();
- view->SetVisible(true);
- parent->AddChild(view);
- return view;
- }
-
- // Embeds another version of the test app @ view.
- ViewManager* Embed(ViewManager* view_manager, View* view) {
- DCHECK_EQ(view_manager, view->view_manager());
- view->Embed(kEmbeddedApp1URL);
- RunRunLoop();
- return GetLoadedViewManager();
- }
-
- ViewManager* GetLoadedViewManager() {
- ViewManager* view_manager = loaded_view_manager_;
- loaded_view_manager_ = NULL;
- return view_manager;
- }
-
- void UnloadApplication(const GURL& url) {
- test_helper_.SetLoaderForURL(scoped_ptr<ApplicationLoader>(), url);
- }
-
- private:
- // Overridden from testing::Test:
- void SetUp() override {
- ConnectApplicationLoader::LoadedCallback ready_callback = base::Bind(
- &ViewManagerTest::OnViewManagerLoaded, base::Unretained(this));
- test_helper_.Init();
- test_helper_.SetLoaderForURL(
- scoped_ptr<ApplicationLoader>(
- new ConnectApplicationLoader(ready_callback)),
- GURL(kWindowManagerURL));
- test_helper_.SetLoaderForURL(
- scoped_ptr<ApplicationLoader>(
- new ConnectApplicationLoader(ready_callback)),
- GURL(kEmbeddedApp1URL));
-
- // TODO(sky): resolve this. Need to establish initial connection.
- }
-
- void OnViewManagerLoaded(View* root) {
- loaded_view_manager_ = root->view_manager();
- connect_loop_->Quit();
- }
-
- void RunRunLoop() {
- base::RunLoop run_loop;
- connect_loop_ = &run_loop;
- connect_loop_->Run();
- connect_loop_ = NULL;
- }
-
- base::RunLoop* connect_loop_;
- shell::ShellTestHelper test_helper_;
- // Used to receive the most recent view manager loaded by an embed action.
- ViewManager* loaded_view_manager_;
- // The View Manager connection held by the window manager (app running at the
- // root view).
- ViewManager* window_manager_;
- int commit_count_;
-
- DISALLOW_COPY_AND_ASSIGN(ViewManagerTest);
-};
-
-// TODO(sky): all of these tests are disabled as each test triggers running
-// ViewsInit, which tries to register the same set of paths with the
-// PathService, triggering a DCHECK.
-TEST_F(ViewManagerTest, DISABLED_SetUp) {}
-
-TEST_F(ViewManagerTest, DISABLED_Embed) {
- View* view = window_manager()->CreateView();
- view->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view);
- ViewManager* embedded = Embed(window_manager(), view);
- EXPECT_TRUE(NULL != embedded);
-
- View* view_in_embedded = embedded->GetRoot();
- EXPECT_EQ(view->parent(), window_manager()->GetRoot());
- EXPECT_EQ(NULL, view_in_embedded->parent());
-}
-
-// Window manager has two views, N1 and N11. Embeds A at N1. A should not see
-// N11.
-// TODO(sky): Update client lib to match server.
-TEST_F(ViewManagerTest, DISABLED_EmbeddedDoesntSeeChild) {
- View* view = window_manager()->CreateView();
- view->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view);
- View* nested = window_manager()->CreateView();
- nested->SetVisible(true);
- view->AddChild(nested);
-
- ViewManager* embedded = Embed(window_manager(), view);
- EXPECT_EQ(embedded->GetRoot()->children().front()->id(),
- nested->id());
- EXPECT_TRUE(embedded->GetRoot()->children().empty());
- EXPECT_TRUE(nested->parent() == NULL);
-}
-
-// http://crbug.com/396300
-TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupView) {
- View* view = window_manager()->CreateView();
- view->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view);
- ViewManager* embedded = Embed(window_manager(), view);
-
- Id view_id = view->id();
-
- UnloadApplication(GURL(kWindowManagerURL));
-
- std::set<Id> views;
- views.insert(view_id);
- WaitForDestruction(embedded, &views);
-
- EXPECT_EQ(nullptr, embedded->GetRoot());
-}
-
-// TODO(beng): write a replacement test for the one that once existed here:
-// This test validates the following scenario:
-// - a view originating from one connection
-// - a view originating from a second connection
-// + the connection originating the view is destroyed
-// -> the view should still exist (since the second connection is live) but
-// should be disconnected from any views.
-// http://crbug.com/396300
-//
-// TODO(beng): The new test should validate the scenario as described above
-// except that the second connection still has a valid tree.
-
-// Verifies that bounds changes applied to a view hierarchy in one connection
-// are reflected to another.
-TEST_F(ViewManagerTest, DISABLED_SetBounds) {
- View* view = window_manager()->CreateView();
- view->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view);
- ViewManager* embedded = Embed(window_manager(), view);
-
- View* view_in_embedded = embedded->GetViewById(view->id());
- EXPECT_EQ(view->bounds(), view_in_embedded->bounds());
-
- Rect rect;
- rect.width = rect.height = 100;
- view->SetBounds(rect);
- EXPECT_NE(view->bounds(), view_in_embedded->bounds());
- WaitForBoundsToChange(view_in_embedded);
- EXPECT_EQ(view->bounds(), view_in_embedded->bounds());
-}
-
-// Verifies that bounds changes applied to a view owned by a different
-// connection are refused.
-TEST_F(ViewManagerTest, DISABLED_SetBoundsSecurity) {
- View* view = window_manager()->CreateView();
- view->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view);
- ViewManager* embedded = Embed(window_manager(), view);
-
- View* view_in_embedded = embedded->GetViewById(view->id());
- Rect rect;
- rect.width = 800;
- rect.height = 600;
- view->SetBounds(rect);
- WaitForBoundsToChange(view_in_embedded);
-
- rect.width = 1024;
- rect.height = 768;
- view_in_embedded->SetBounds(rect);
- // Bounds change should have been rejected.
- EXPECT_EQ(view->bounds(), view_in_embedded->bounds());
-}
-
-// Verifies that a view can only be destroyed by the connection that created it.
-TEST_F(ViewManagerTest, DISABLED_DestroySecurity) {
- View* view = window_manager()->CreateView();
- view->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view);
- ViewManager* embedded = Embed(window_manager(), view);
-
- View* view_in_embedded = embedded->GetViewById(view->id());
-
- ViewTracker tracker2(view_in_embedded);
- view_in_embedded->Destroy();
- // View should not have been destroyed.
- EXPECT_TRUE(tracker2.is_valid());
-
- ViewTracker tracker1(view);
- view->Destroy();
- EXPECT_FALSE(tracker1.is_valid());
-}
-
-TEST_F(ViewManagerTest, DISABLED_MultiRoots) {
- View* view1 = window_manager()->CreateView();
- view1->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view1);
- View* view2 = window_manager()->CreateView();
- view2->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view2);
- ViewManager* embedded1 = Embed(window_manager(), view1);
- ViewManager* embedded2 = Embed(window_manager(), view2);
- EXPECT_EQ(embedded1, embedded2);
-}
-
-TEST_F(ViewManagerTest, DISABLED_EmbeddingIdentity) {
- View* view = window_manager()->CreateView();
- view->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view);
- ViewManager* embedded = Embed(window_manager(), view);
- EXPECT_EQ(kWindowManagerURL, embedded->GetEmbedderURL());
-}
-
-TEST_F(ViewManagerTest, DISABLED_Reorder) {
- View* view1 = window_manager()->CreateView();
- view1->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view1);
-
- ViewManager* embedded = Embed(window_manager(), view1);
-
- View* view11 = embedded->CreateView();
- view11->SetVisible(true);
- embedded->GetRoot()->AddChild(view11);
- View* view12 = embedded->CreateView();
- view12->SetVisible(true);
- embedded->GetRoot()->AddChild(view12);
-
- View* view1_in_wm = window_manager()->GetViewById(view1->id());
-
- {
- WaitForTreeSizeToMatch(view1, 2u);
- view11->MoveToFront();
- WaitForOrderChange(window_manager(),
- window_manager()->GetViewById(view11->id()));
-
- EXPECT_EQ(view1_in_wm->children().front(),
- window_manager()->GetViewById(view12->id()));
- EXPECT_EQ(view1_in_wm->children().back(),
- window_manager()->GetViewById(view11->id()));
- }
-
- {
- view11->MoveToBack();
- WaitForOrderChange(window_manager(),
- window_manager()->GetViewById(view11->id()));
-
- EXPECT_EQ(view1_in_wm->children().front(),
- window_manager()->GetViewById(view11->id()));
- EXPECT_EQ(view1_in_wm->children().back(),
- window_manager()->GetViewById(view12->id()));
- }
-}
-
-namespace {
-
-class VisibilityChangeObserver : public ViewObserver {
- public:
- explicit VisibilityChangeObserver(View* view) : view_(view) {
- view_->AddObserver(this);
- }
- ~VisibilityChangeObserver() override { view_->RemoveObserver(this); }
-
- private:
- // Overridden from ViewObserver:
- void OnViewVisibilityChanged(View* view) override {
- EXPECT_EQ(view, view_);
- QuitRunLoop();
- }
-
- View* view_;
-
- DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver);
-};
-
-} // namespace
-
-TEST_F(ViewManagerTest, DISABLED_Visible) {
- View* view1 = window_manager()->CreateView();
- view1->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view1);
-
- // Embed another app and verify initial state.
- ViewManager* embedded = Embed(window_manager(), view1);
- ASSERT_NE(nullptr, embedded->GetRoot());
- View* embedded_root = embedded->GetRoot();
- EXPECT_TRUE(embedded_root->visible());
- EXPECT_TRUE(embedded_root->IsDrawn());
-
- // Change the visible state from the first connection and verify its mirrored
- // correctly to the embedded app.
- {
- VisibilityChangeObserver observer(embedded_root);
- view1->SetVisible(false);
- DoRunLoop();
- }
-
- EXPECT_FALSE(view1->visible());
- EXPECT_FALSE(view1->IsDrawn());
-
- EXPECT_FALSE(embedded_root->visible());
- EXPECT_FALSE(embedded_root->IsDrawn());
-
- // Make the node visible again.
- {
- VisibilityChangeObserver observer(embedded_root);
- view1->SetVisible(true);
- DoRunLoop();
- }
-
- EXPECT_TRUE(view1->visible());
- EXPECT_TRUE(view1->IsDrawn());
-
- EXPECT_TRUE(embedded_root->visible());
- EXPECT_TRUE(embedded_root->IsDrawn());
-}
-
-namespace {
-
-class DrawnChangeObserver : public ViewObserver {
- public:
- explicit DrawnChangeObserver(View* view) : view_(view) {
- view_->AddObserver(this);
- }
- ~DrawnChangeObserver() override { view_->RemoveObserver(this); }
-
- private:
- // Overridden from ViewObserver:
- void OnViewDrawnChanged(View* view) override {
- EXPECT_EQ(view, view_);
- QuitRunLoop();
- }
-
- View* view_;
-
- DISALLOW_COPY_AND_ASSIGN(DrawnChangeObserver);
-};
-
-} // namespace
-
-TEST_F(ViewManagerTest, DISABLED_Drawn) {
- View* view1 = window_manager()->CreateView();
- view1->SetVisible(true);
- window_manager()->GetRoot()->AddChild(view1);
-
- // Embed another app and verify initial state.
- ViewManager* embedded = Embed(window_manager(), view1);
- ASSERT_NE(nullptr, embedded->GetRoot());
- View* embedded_root = embedded->GetRoot();
- EXPECT_TRUE(embedded_root->visible());
- EXPECT_TRUE(embedded_root->IsDrawn());
-
- // Change the visibility of the root, this should propagate a drawn state
- // change to |embedded|.
- {
- DrawnChangeObserver observer(embedded_root);
- window_manager()->GetRoot()->SetVisible(false);
- DoRunLoop();
- }
-
- EXPECT_TRUE(view1->visible());
- EXPECT_FALSE(view1->IsDrawn());
-
- EXPECT_TRUE(embedded_root->visible());
- EXPECT_FALSE(embedded_root->IsDrawn());
-}
-
-// TODO(beng): tests for view event dispatcher.
-// - verify that we see events for all views.
-
-// TODO(beng): tests for focus:
-// - focus between two views known to a connection
-// - focus between views unknown to one of the connections.
-// - focus between views unknown to either connection.
-
-// TODO(sky): need test of root being destroyed with existing views. See
-// 434555 for specific case.
-
-} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_unittest.cc b/third_party/mojo_services/src/view_manager/public/cpp/tests/view_unittest.cc
index 149eb3a..abbd712 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_unittest.cc
+++ b/third_party/mojo_services/src/view_manager/public/cpp/tests/view_unittest.cc
@@ -27,7 +27,7 @@ class TestView : public View {
~TestView() {}
private:
- DISALLOW_COPY_AND_ASSIGN(TestView);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(TestView);
};
TEST_F(ViewTest, AddChild) {
@@ -148,7 +148,7 @@ class TestProperty {
private:
static TestProperty* last_deleted_;
- DISALLOW_COPY_AND_ASSIGN(TestProperty);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(TestProperty);
};
TestProperty* TestProperty::last_deleted_ = NULL;
@@ -222,7 +222,7 @@ class TreeChangeObserver : public ViewObserver {
View* observee_;
std::vector<TreeChangeParams> received_params_;
- DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver);
};
// Adds/Removes v11 to v1.
@@ -463,7 +463,7 @@ class OrderChangeObserver : public ViewObserver {
View* observee_;
Changes changes_;
- DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
};
} // namespace
@@ -613,7 +613,7 @@ class BoundsChangeObserver : public ViewObserver {
View* view_;
Changes changes_;
- DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
};
} // namespace
@@ -669,7 +669,7 @@ class VisibilityChangeObserver : public ViewObserver {
View* view_;
Changes changes_;
- DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver);
};
} // namespace
@@ -775,7 +775,7 @@ class SharedPropertyChangeObserver : public ViewObserver {
View* view_;
Changes changes_;
- DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver);
};
} // namespace
@@ -856,7 +856,7 @@ class LocalPropertyChangeObserver : public ViewObserver {
const void* property_key_;
intptr_t old_property_value_;
- DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver);
};
} // namespace
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view.h b/third_party/mojo_services/src/view_manager/public/cpp/view.h
index d888ef0..fcb49bc 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/view.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/view.h
@@ -5,12 +5,13 @@
#ifndef MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_H_
#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_H_
+#include <stdint.h>
#include <vector>
-#include "base/basictypes.h"
#include "base/observer_list.h"
#include "geometry/public/interfaces/geometry.mojom.h"
#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/system/macros.h"
#include "mojo/public/interfaces/application/service_provider.mojom.h"
#include "surfaces/public/interfaces/surface_id.mojom.h"
#include "view_manager/public/cpp/types.h"
@@ -87,7 +88,7 @@ class View {
void ClearLocalProperty(const ViewProperty<T>* property);
// Type of a function to delete a property that this view owns.
- typedef void (*PropertyDeallocator)(int64 value);
+ typedef void (*PropertyDeallocator)(int64_t value);
// A View is drawn if the View and all its ancestors are visible and the
// View is attached to the root.
@@ -141,12 +142,13 @@ class View {
View(ViewManager* manager, Id id);
// Called by the public {Set,Get,Clear}Property functions.
- int64 SetLocalPropertyInternal(const void* key,
- const char* name,
- PropertyDeallocator deallocator,
- int64 value,
- int64 default_value);
- int64 GetLocalPropertyInternal(const void* key, int64 default_value) const;
+ int64_t SetLocalPropertyInternal(const void* key,
+ const char* name,
+ PropertyDeallocator deallocator,
+ int64_t value,
+ int64_t default_value);
+ int64_t GetLocalPropertyInternal(const void* key,
+ int64_t default_value) const;
void LocalDestroy();
void LocalAddChild(View* child);
@@ -157,6 +159,7 @@ class View {
void LocalSetViewportMetrics(const ViewportMetrics& old_metrics,
const ViewportMetrics& new_metrics);
void LocalSetDrawn(bool drawn);
+ void LocalSetVisible(bool visible);
// Methods implementing visibility change notifications. See ViewObserver
// for more details.
@@ -193,13 +196,13 @@ class View {
// WindowProperty<>.
struct Value {
const char* name;
- int64 value;
+ int64_t value;
PropertyDeallocator deallocator;
};
std::map<const void*, Value> prop_map_;
- DISALLOW_COPY_AND_ASSIGN(View);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(View);
};
} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h b/third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h
index edb5ca3..e47da3d 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h
@@ -5,7 +5,6 @@
#ifndef MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CLIENT_FACTORY_H_
#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CLIENT_FACTORY_H_
-#include "base/memory/scoped_ptr.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "view_manager/public/interfaces/view_manager.mojom.h"
@@ -22,8 +21,9 @@ class ViewManagerClientFactory : public InterfaceFactory<ViewManagerClient> {
ViewManagerClientFactory(Shell* shell, ViewManagerDelegate* delegate);
~ViewManagerClientFactory() override;
- // Creates a ViewManagerClient from the supplied arguments.
- static scoped_ptr<ViewManagerClient> WeakBindViewManagerToPipe(
+ // Creates a ViewManagerClient from the supplied arguments. Returns ownership
+ // to the caller.
+ static ViewManagerClient* WeakBindViewManagerToPipe(
InterfaceRequest<ViewManagerClient> request,
ViewManagerServicePtr view_manager_service,
Shell* shell,
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h b/third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h
index 1976598..de7b84b 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h
@@ -8,9 +8,8 @@
#include <string>
#include <vector>
-#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
#include "mojo/public/cpp/application/service_provider_impl.h"
+#include "mojo/public/cpp/system/macros.h"
namespace mojo {
class ApplicationImpl;
@@ -37,7 +36,7 @@ class ViewManagerContext {
private:
class InternalState;
- scoped_ptr<InternalState> state_;
+ InternalState* state_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerContext);
};
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_observer.h b/third_party/mojo_services/src/view_manager/public/cpp/view_observer.h
index f059e11..341a4f0 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/view_observer.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/view_observer.h
@@ -7,8 +7,6 @@
#include <vector>
-#include "base/basictypes.h"
-
#include "input_events/public/interfaces/input_events.mojom.h"
#include "view_manager/public/cpp/view.h"
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_property.h b/third_party/mojo_services/src/view_manager/public/cpp/view_property.h
index d3a345f..2dbd317 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/view_property.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/view_property.h
@@ -5,7 +5,7 @@
#ifndef MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_PROPERTY_H_
#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_PROPERTY_H_
-#include "base/basictypes.h"
+#include <stdint.h>
// This header should be included by code that defines ViewProperties. It
// should not be included by code that only gets and sets ViewProperties.
@@ -43,27 +43,27 @@
namespace mojo {
namespace {
-// No single new-style cast works for every conversion to/from int64, so we
+// No single new-style cast works for every conversion to/from int64_t, so we
// need this helper class. A third specialization is needed for bool because
// MSVC warning C4800 (forcing value to bool) is not suppressed by an explicit
// cast (!).
template <typename T>
class ViewPropertyCaster {
public:
- static int64 ToInt64(T x) { return static_cast<int64>(x); }
- static T FromInt64(int64 x) { return static_cast<T>(x); }
+ static int64_t ToInt64(T x) { return static_cast<int64_t>(x); }
+ static T FromInt64(int64_t x) { return static_cast<T>(x); }
};
template <typename T>
class ViewPropertyCaster<T*> {
public:
- static int64 ToInt64(T* x) { return reinterpret_cast<int64>(x); }
- static T* FromInt64(int64 x) { return reinterpret_cast<T*>(x); }
+ static int64_t ToInt64(T* x) { return reinterpret_cast<int64_t>(x); }
+ static T* FromInt64(int64_t x) { return reinterpret_cast<T*>(x); }
};
template <>
class ViewPropertyCaster<bool> {
public:
- static int64 ToInt64(bool x) { return static_cast<int64>(x); }
- static bool FromInt64(int64 x) { return x != 0; }
+ static int64_t ToInt64(bool x) { return static_cast<int64_t>(x); }
+ static bool FromInt64(int64_t x) { return x != 0; }
};
} // namespace
@@ -77,7 +77,7 @@ struct ViewProperty {
template <typename T>
void View::SetLocalProperty(const ViewProperty<T>* property, T value) {
- int64 old = SetLocalPropertyInternal(
+ int64_t old = SetLocalPropertyInternal(
property, property->name,
value == property->default_value ? nullptr : property->deallocator,
ViewPropertyCaster<T>::ToInt64(value),
@@ -111,23 +111,23 @@ void View::ClearLocalProperty(const ViewProperty<T>* property) {
const mojo::ViewProperty<T>*);
#define DECLARE_VIEW_PROPERTY_TYPE(T) DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(, T)
-#define DEFINE_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \
- COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64), property_type_too_large); \
- namespace { \
- const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \
- } \
+#define DEFINE_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \
+ COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64_t), property_type_too_large); \
+ namespace { \
+ const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \
+ } \
const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value;
-#define DEFINE_LOCAL_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \
- COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64), property_type_too_large); \
- namespace { \
- const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \
- const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value; \
+#define DEFINE_LOCAL_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \
+ COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64_t), property_type_too_large); \
+ namespace { \
+ const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \
+ const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value; \
}
#define DEFINE_OWNED_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \
namespace { \
- void Deallocator##NAME(int64 p) { \
+ void Deallocator##NAME(int64_t p) { \
enum { type_must_be_complete = sizeof(TYPE) }; \
delete mojo::ViewPropertyCaster<TYPE*>::FromInt64(p); \
} \
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h b/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h
index 05325b7..1d6bf14 100644
--- a/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h
+++ b/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h
@@ -5,10 +5,10 @@
#ifndef MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_TRACKER_H_
#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_TRACKER_H_
+#include <stdint.h>
#include <set>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "mojo/public/cpp/system/macros.h"
#include "view_manager/public/cpp/view_observer.h"
namespace mojo {
@@ -39,7 +39,7 @@ class ViewTracker : public ViewObserver {
private:
Views views_;
- DISALLOW_COPY_AND_ASSIGN(ViewTracker);
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ViewTracker);
};
} // namespace mojo
diff --git a/tools/ipc_fuzzer/replay/replay_process.cc b/tools/ipc_fuzzer/replay/replay_process.cc
index 0a7b830..8f942c6 100644
--- a/tools/ipc_fuzzer/replay/replay_process.cc
+++ b/tools/ipc_fuzzer/replay/replay_process.cc
@@ -93,7 +93,7 @@ void ReplayProcess::OpenChannel() {
content::ShouldUseMojoChannel();
if (should_use_mojo) {
channel_ = IPC::ChannelProxy::Create(
- IPC::ChannelMojo::CreateClientFactory(channel_name), this,
+ IPC::ChannelMojo::CreateClientFactory(nullptr, channel_name), this,
io_thread_.message_loop_proxy());
} else {
channel_ =