From 920588a1acdc4721abb713d8162010e4b85ae53e Mon Sep 17 00:00:00 2001 From: Hidehiko Abe Date: Tue, 24 Apr 2018 02:15:00 +0900 Subject: Migrate libmojo repository into libchrome, part 2. This CL moves following files. - .gitignore - Android.bp is merged into libchrome's Android.bp. - base/android/* - build/* except build_config.h which is exactly same with libchrome's. - ipc/* - mojo/* - soong/* into libchrome_tools/ - third_party/{catapult,jinja2,markupsafe,ply}/* - ui/gfx/{geometry,range}/mojo/* Then removed following files: - Android.bp - CleanSpec.mk - build/build_config.h And added README.md to notify the migration. Bug: 73606903 Test: Built locally. Ran on DUT. Change-Id: I94aa1b43ff0854f48f30fdf03025bd1c8a346038 --- .gitignore | 1 - Android.bp | 415 --- CleanSpec.mk | 56 - README.md | 1 + base/android/build_info.cc | 80 - base/android/build_info.h | 145 - base/android/context_utils.cc | 53 - base/android/context_utils.h | 26 - .../java/src/org/chromium/base/BuildInfo.java | 171 - .../java/src/org/chromium/base/ContextUtils.java | 115 - base/android/java/src/org/chromium/base/Log.java | 387 --- .../java/src/org/chromium/base/PackageUtils.java | 37 - .../src/org/chromium/base/VisibleForTesting.java | 12 - .../base/annotations/AccessedByNative.java | 20 - .../chromium/base/annotations/CalledByNative.java | 23 - .../base/annotations/CalledByNativeUnchecked.java | 27 - .../base/annotations/JNIAdditionalImport.java | 35 - .../chromium/base/annotations/JNINamespace.java | 20 - .../src/org/chromium/base/annotations/MainDex.java | 21 - .../org/chromium/base/annotations/NativeCall.java | 24 - .../base/annotations/NativeClassQualifiedName.java | 25 - .../base/annotations/RemovableInRelease.java | 18 - .../base/annotations/SuppressFBWarnings.java | 20 - .../base/annotations/UsedByReflection.java | 24 - base/android/java_runtime.cc | 21 - base/android/java_runtime.h | 25 - base/android/jni_android.cc | 320 -- base/android/jni_android.h | 190 -- base/android/jni_android_unittest.cc | 61 - base/android/jni_generator/android_jar.classes | 98 - .../example/jni_generator/SampleForTests.java | 318 -- base/android/jni_generator/jni_generator.py | 1418 --------- base/android/jni_generator/jni_generator_helper.h | 62 - base/android/jni_generator/jni_generator_tests.py | 1097 ------- base/android/jni_generator/sample_for_tests.cc | 142 - base/android/jni_generator/sample_for_tests.h | 126 - .../jni_generator/testCalledByNatives.golden | 497 --- .../jni_generator/testConstantsFromJavaP.golden | 2195 ------------- base/android/jni_generator/testFromJavaP.golden | 260 -- .../jni_generator/testFromJavaPGenerics.golden | 56 - .../jni_generator/testInnerClassNatives.golden | 71 - .../testInnerClassNativesBothInnerAndOuter.golden | 98 - .../testInnerClassNativesMultiple.golden | 105 - base/android/jni_generator/testInputStream.javap | 228 -- base/android/jni_generator/testMotionEvent.javap | 2295 -------------- base/android/jni_generator/testMotionEvent.javap7 | 2370 -------------- .../testMultipleJNIAdditionalImport.golden | 95 - base/android/jni_generator/testNatives.golden | 340 -- base/android/jni_generator/testNativesLong.golden | 66 - .../testSingleJNIAdditionalImport.golden | 89 - base/android/jni_int_wrapper.h | 56 - base/android/jni_string.cc | 121 - base/android/jni_string.h | 49 - base/android/jni_string_unittest.cc | 48 - base/android/scoped_java_ref.cc | 92 - base/android/scoped_java_ref.h | 301 -- base/android/scoped_java_ref_unittest.cc | 133 - build/android/gyp/util/__init__.py | 4 - build/android/gyp/util/build_utils.py | 589 ---- build/android/gyp/util/md5_check.py | 410 --- build/android/pylib/__init__.py | 31 - build/android/pylib/constants/__init__.py | 225 -- build/android/pylib/constants/host_paths.py | 38 - build/build_config.h | 229 -- build/gn_helpers.py | 351 --- gen/mojo/common/common_custom_types__type_mappings | 193 -- ipc/ipc.mojom | 40 - ipc/ipc_channel_handle.h | 41 - ipc/ipc_export.h | 34 - ipc/ipc_listener.h | 60 - ipc/ipc_message.cc | 205 -- ipc/ipc_message.h | 305 -- ipc/ipc_message_attachment.cc | 15 - ipc/ipc_message_attachment.h | 36 - ipc/ipc_message_attachment_set.cc | 136 - ipc/ipc_message_attachment_set.h | 96 - ipc/ipc_message_start.h | 126 - ipc/ipc_message_utils.cc | 1238 -------- ipc/ipc_message_utils.h | 1145 ------- ipc/ipc_mojo_handle_attachment.cc | 29 - ipc/ipc_mojo_handle_attachment.h | 42 - ipc/ipc_mojo_message_helper.cc | 51 - ipc/ipc_mojo_message_helper.h | 29 - ipc/ipc_mojo_param_traits.cc | 50 - ipc/ipc_mojo_param_traits.h | 34 - ipc/ipc_param_traits.h | 23 - ipc/ipc_platform_file_attachment_posix.cc | 38 - ipc/ipc_platform_file_attachment_posix.h | 43 - ipc/ipc_sync_message.h | 107 - libmojo.pc.in | 13 - mojo/BUILD.gn | 41 - mojo/DEPS | 7 - mojo/PRESUBMIT.py | 44 - mojo/README.md | 142 - mojo/android/BUILD.gn | 155 - mojo/android/DEPS | 3 - mojo/android/javatests/AndroidManifest.xml | 29 - mojo/android/javatests/DEPS | 4 - mojo/android/javatests/apk/.empty | 0 mojo/android/javatests/init_library.cc | 50 - mojo/android/javatests/mojo_test_case.cc | 70 - mojo/android/javatests/mojo_test_case.h | 20 - .../src/org/chromium/mojo/HandleMock.java | 226 -- .../src/org/chromium/mojo/MojoTestCase.java | 66 - .../javatests/src/org/chromium/mojo/TestUtils.java | 32 - .../chromium/mojo/bindings/BindingsHelperTest.java | 55 - .../org/chromium/mojo/bindings/BindingsTest.java | 241 -- .../chromium/mojo/bindings/BindingsTestUtils.java | 108 - .../mojo/bindings/BindingsVersioningTest.java | 211 -- .../org/chromium/mojo/bindings/CallbacksTest.java | 59 - .../org/chromium/mojo/bindings/ConnectorTest.java | 108 - .../mojo/bindings/ExecutorFactoryTest.java | 104 - .../mojo/bindings/InterfaceControlMessageTest.java | 129 - .../org/chromium/mojo/bindings/InterfacesTest.java | 284 -- .../chromium/mojo/bindings/MessageHeaderTest.java | 69 - .../mojo/bindings/ReadAndDispatchMessageTest.java | 109 - .../src/org/chromium/mojo/bindings/RouterTest.java | 231 -- .../chromium/mojo/bindings/SerializationTest.java | 175 -- .../org/chromium/mojo/bindings/ValidationTest.java | 237 -- .../chromium/mojo/bindings/ValidationTestUtil.java | 68 - .../mojo/bindings/ValidationTestUtilTest.java | 151 - .../mojo/IntegrationTestInterfaceTestHelper.java | 31 - .../chromium/mojo/system/impl/CoreImplTest.java | 545 ---- .../chromium/mojo/system/impl/WatcherImplTest.java | 255 -- mojo/android/javatests/validation_test_util.cc | 54 - mojo/android/javatests/validation_test_util.h | 20 - mojo/android/system/base_run_loop.cc | 82 - mojo/android/system/base_run_loop.h | 20 - mojo/android/system/core_impl.cc | 310 -- mojo/android/system/core_impl.h | 20 - .../org/chromium/mojo/system/impl/BaseRunLoop.java | 74 - .../org/chromium/mojo/system/impl/CoreImpl.java | 522 ---- .../system/impl/DataPipeConsumerHandleImpl.java | 72 - .../system/impl/DataPipeProducerHandleImpl.java | 64 - .../org/chromium/mojo/system/impl/HandleBase.java | 140 - .../mojo/system/impl/MessagePipeHandleImpl.java | 58 - .../mojo/system/impl/SharedBufferHandleImpl.java | 62 - .../mojo/system/impl/UntypedHandleImpl.java | 72 - .../org/chromium/mojo/system/impl/WatcherImpl.java | 63 - mojo/android/system/watcher_impl.cc | 109 - mojo/android/system/watcher_impl.h | 20 - mojo/common/BUILD.gn | 93 - mojo/common/DEPS | 6 - mojo/common/common_custom_types_struct_traits.cc | 108 - mojo/common/common_custom_types_struct_traits.h | 85 - mojo/common/common_custom_types_unittest.cc | 433 --- mojo/common/data_pipe_drainer.cc | 50 - mojo/common/data_pipe_drainer.h | 49 - mojo/common/data_pipe_utils.cc | 96 - mojo/common/data_pipe_utils.h | 32 - mojo/common/file.mojom | 10 - mojo/common/file.typemap | 13 - mojo/common/file_path.mojom | 8 - mojo/common/file_path.typemap | 12 - mojo/common/mojo_common_export.h | 32 - mojo/common/string16.mojom | 12 - mojo/common/string16.typemap | 12 - mojo/common/struct_traits_unittest.cc | 57 - mojo/common/test_common_custom_types.mojom | 61 - mojo/common/text_direction.mojom | 12 - mojo/common/text_direction.typemap | 12 - mojo/common/time.mojom | 21 - mojo/common/time.typemap | 20 - mojo/common/time_struct_traits.h | 55 - mojo/common/traits_test_service.mojom | 14 - mojo/common/typemaps.gni | 14 - mojo/common/unguessable_token.mojom | 11 - mojo/common/unguessable_token.typemap | 12 - mojo/common/values.mojom | 32 - mojo/common/values.typemap | 25 - mojo/common/values_struct_traits.cc | 109 - mojo/common/values_struct_traits.h | 257 -- mojo/common/version.mojom | 10 - mojo/common/version.typemap | 12 - mojo/edk/DEPS | 14 - mojo/edk/embedder/BUILD.gn | 147 - mojo/edk/embedder/README.md | 346 --- mojo/edk/embedder/configuration.h | 65 - mojo/edk/embedder/connection_params.cc | 28 - mojo/edk/embedder/connection_params.h | 34 - mojo/edk/embedder/embedder.cc | 158 - mojo/edk/embedder/embedder.h | 173 -- mojo/edk/embedder/embedder_internal.h | 44 - mojo/edk/embedder/embedder_unittest.cc | 603 ---- mojo/edk/embedder/entrypoints.cc | 283 -- mojo/edk/embedder/entrypoints.h | 22 - mojo/edk/embedder/named_platform_channel_pair.h | 73 - .../embedder/named_platform_channel_pair_win.cc | 89 - mojo/edk/embedder/named_platform_handle.h | 51 - mojo/edk/embedder/named_platform_handle_utils.h | 56 - .../embedder/named_platform_handle_utils_posix.cc | 141 - .../embedder/named_platform_handle_utils_win.cc | 95 - mojo/edk/embedder/pending_process_connection.cc | 50 - mojo/edk/embedder/pending_process_connection.h | 124 - mojo/edk/embedder/platform_channel_pair.cc | 34 - mojo/edk/embedder/platform_channel_pair.h | 106 - mojo/edk/embedder/platform_channel_pair_posix.cc | 172 - .../platform_channel_pair_posix_unittest.cc | 261 -- mojo/edk/embedder/platform_channel_pair_win.cc | 123 - mojo/edk/embedder/platform_channel_utils_posix.cc | 282 -- mojo/edk/embedder/platform_channel_utils_posix.h | 87 - mojo/edk/embedder/platform_handle.cc | 74 - mojo/edk/embedder/platform_handle.h | 90 - mojo/edk/embedder/platform_handle_utils.h | 33 - mojo/edk/embedder/platform_handle_utils_posix.cc | 24 - mojo/edk/embedder/platform_handle_utils_win.cc | 28 - mojo/edk/embedder/platform_handle_vector.h | 35 - mojo/edk/embedder/platform_shared_buffer.cc | 325 -- mojo/edk/embedder/platform_shared_buffer.h | 178 -- .../embedder/platform_shared_buffer_unittest.cc | 227 -- mojo/edk/embedder/scoped_ipc_support.cc | 39 - mojo/edk/embedder/scoped_ipc_support.h | 118 - mojo/edk/embedder/scoped_platform_handle.h | 63 - mojo/edk/embedder/test_embedder.cc | 46 - mojo/edk/embedder/test_embedder.h | 28 - mojo/edk/js/BUILD.gn | 35 - mojo/edk/js/core.cc | 454 --- mojo/edk/js/core.h | 25 - mojo/edk/js/drain_data.cc | 129 - mojo/edk/js/drain_data.h | 65 - mojo/edk/js/handle.cc | 85 - mojo/edk/js/handle.h | 107 - mojo/edk/js/handle_close_observer.h | 24 - mojo/edk/js/handle_unittest.cc | 92 - mojo/edk/js/js_export.h | 32 - mojo/edk/js/mojo_runner_delegate.cc | 80 - mojo/edk/js/mojo_runner_delegate.h | 36 - mojo/edk/js/support.cc | 77 - mojo/edk/js/support.h | 25 - mojo/edk/js/tests/BUILD.gn | 68 - mojo/edk/js/tests/js_to_cpp.mojom | 54 - mojo/edk/js/tests/js_to_cpp_tests.cc | 455 --- mojo/edk/js/tests/js_to_cpp_tests.js | 223 -- mojo/edk/js/tests/run_js_unittests.cc | 61 - mojo/edk/js/threading.cc | 49 - mojo/edk/js/threading.h | 28 - mojo/edk/js/waiting_callback.cc | 95 - mojo/edk/js/waiting_callback.h | 67 - mojo/edk/system/BUILD.gn | 205 -- mojo/edk/system/atomic_flag.h | 57 - mojo/edk/system/broker.h | 52 - mojo/edk/system/broker_host.cc | 153 - mojo/edk/system/broker_host.h | 64 - mojo/edk/system/broker_messages.h | 80 - mojo/edk/system/broker_posix.cc | 125 - mojo/edk/system/broker_win.cc | 155 - mojo/edk/system/channel.cc | 683 ---- mojo/edk/system/channel.h | 303 -- mojo/edk/system/channel_posix.cc | 572 ---- mojo/edk/system/channel_unittest.cc | 177 -- mojo/edk/system/channel_win.cc | 360 --- mojo/edk/system/configuration.cc | 25 - mojo/edk/system/configuration.h | 29 - mojo/edk/system/core.cc | 1019 ------ mojo/edk/system/core.h | 297 -- mojo/edk/system/core_test_base.cc | 272 -- mojo/edk/system/core_test_base.h | 94 - mojo/edk/system/core_unittest.cc | 971 ------ mojo/edk/system/data_pipe_consumer_dispatcher.cc | 562 ---- mojo/edk/system/data_pipe_consumer_dispatcher.h | 123 - mojo/edk/system/data_pipe_control_message.cc | 35 - mojo/edk/system/data_pipe_control_message.h | 43 - mojo/edk/system/data_pipe_producer_dispatcher.cc | 507 --- mojo/edk/system/data_pipe_producer_dispatcher.h | 123 - mojo/edk/system/data_pipe_unittest.cc | 2034 ------------ mojo/edk/system/dispatcher.cc | 198 -- mojo/edk/system/dispatcher.h | 245 -- mojo/edk/system/handle_signals_state.h | 13 - mojo/edk/system/handle_table.cc | 135 - mojo/edk/system/handle_table.h | 75 - mojo/edk/system/mach_port_relay.cc | 248 -- mojo/edk/system/mach_port_relay.h | 94 - mojo/edk/system/mapping_table.cc | 48 - mojo/edk/system/mapping_table.h | 57 - mojo/edk/system/message_for_transit.cc | 136 - mojo/edk/system/message_for_transit.h | 115 - mojo/edk/system/message_pipe_dispatcher.cc | 554 ---- mojo/edk/system/message_pipe_dispatcher.h | 115 - mojo/edk/system/message_pipe_perftest.cc | 167 - mojo/edk/system/message_pipe_unittest.cc | 699 ----- .../system/multiprocess_message_pipe_unittest.cc | 1366 -------- mojo/edk/system/node_channel.cc | 905 ------ mojo/edk/system/node_channel.h | 219 -- mojo/edk/system/node_controller.cc | 1470 --------- mojo/edk/system/node_controller.h | 378 --- mojo/edk/system/options_validation.h | 97 - mojo/edk/system/options_validation_unittest.cc | 134 - mojo/edk/system/platform_handle_dispatcher.cc | 104 - mojo/edk/system/platform_handle_dispatcher.h | 61 - .../system/platform_handle_dispatcher_unittest.cc | 123 - mojo/edk/system/platform_wrapper_unittest.cc | 212 -- mojo/edk/system/ports/BUILD.gn | 46 - mojo/edk/system/ports/event.cc | 46 - mojo/edk/system/ports/event.h | 111 - mojo/edk/system/ports/message.cc | 100 - mojo/edk/system/ports/message.h | 93 - mojo/edk/system/ports/message_filter.h | 29 - mojo/edk/system/ports/message_queue.cc | 87 - mojo/edk/system/ports/message_queue.h | 73 - mojo/edk/system/ports/name.cc | 26 - mojo/edk/system/ports/name.h | 74 - mojo/edk/system/ports/node.cc | 1385 --------- mojo/edk/system/ports/node.h | 228 -- mojo/edk/system/ports/node_delegate.h | 48 - mojo/edk/system/ports/port.cc | 24 - mojo/edk/system/ports/port.h | 60 - mojo/edk/system/ports/port_ref.cc | 36 - mojo/edk/system/ports/port_ref.h | 41 - mojo/edk/system/ports/ports_unittest.cc | 1478 --------- mojo/edk/system/ports/user_data.h | 25 - mojo/edk/system/ports_message.cc | 62 - mojo/edk/system/ports_message.h | 69 - mojo/edk/system/request_context.cc | 110 - mojo/edk/system/request_context.h | 107 - mojo/edk/system/shared_buffer_dispatcher.cc | 339 -- mojo/edk/system/shared_buffer_dispatcher.h | 127 - .../system/shared_buffer_dispatcher_unittest.cc | 312 -- mojo/edk/system/shared_buffer_unittest.cc | 318 -- mojo/edk/system/signals_unittest.cc | 76 - mojo/edk/system/system_impl_export.h | 29 - mojo/edk/system/test_utils.cc | 76 - mojo/edk/system/test_utils.h | 59 - mojo/edk/system/watch.cc | 83 - mojo/edk/system/watch.h | 124 - mojo/edk/system/watcher_dispatcher.cc | 232 -- mojo/edk/system/watcher_dispatcher.h | 101 - mojo/edk/system/watcher_set.cc | 82 - mojo/edk/system/watcher_set.h | 71 - mojo/edk/system/watcher_unittest.cc | 1637 ---------- mojo/edk/test/BUILD.gn | 131 - mojo/edk/test/mojo_test_base.cc | 327 -- mojo/edk/test/mojo_test_base.h | 249 -- mojo/edk/test/multiprocess_test_helper.cc | 263 -- mojo/edk/test/multiprocess_test_helper.h | 110 - mojo/edk/test/multiprocess_test_helper_unittest.cc | 165 - mojo/edk/test/run_all_perftests.cc | 26 - mojo/edk/test/run_all_unittests.cc | 49 - mojo/edk/test/test_support_impl.cc | 84 - mojo/edk/test/test_support_impl.h | 38 - mojo/edk/test/test_utils.h | 55 - mojo/edk/test/test_utils_posix.cc | 94 - mojo/edk/test/test_utils_win.cc | 115 - mojo/public/BUILD.gn | 28 - mojo/public/DEPS | 11 - mojo/public/LICENSE | 27 - mojo/public/c/system/BUILD.gn | 37 - mojo/public/c/system/README.md | 869 ------ mojo/public/c/system/buffer.h | 188 -- mojo/public/c/system/core.h | 22 - mojo/public/c/system/data_pipe.h | 344 -- mojo/public/c/system/functions.h | 78 - mojo/public/c/system/macros.h | 49 - mojo/public/c/system/message_pipe.h | 341 -- mojo/public/c/system/platform_handle.h | 191 -- mojo/public/c/system/set_thunks_for_app.cc | 20 - mojo/public/c/system/system_export.h | 33 - mojo/public/c/system/tests/BUILD.gn | 38 - mojo/public/c/system/tests/core_perftest.cc | 329 -- mojo/public/c/system/tests/core_unittest.cc | 322 -- mojo/public/c/system/tests/core_unittest_pure_c.c | 77 - mojo/public/c/system/tests/macros_unittest.cc | 68 - mojo/public/c/system/thunks.cc | 273 -- mojo/public/c/system/thunks.h | 148 - mojo/public/c/system/types.h | 223 -- mojo/public/c/system/watcher.h | 184 -- mojo/public/c/test_support/BUILD.gn | 15 - mojo/public/c/test_support/test_support.h | 52 - mojo/public/cpp/bindings/BUILD.gn | 194 -- mojo/public/cpp/bindings/DEPS | 3 - mojo/public/cpp/bindings/README.md | 1231 -------- mojo/public/cpp/bindings/array_data_view.h | 244 -- mojo/public/cpp/bindings/array_traits.h | 71 - mojo/public/cpp/bindings/array_traits_carray.h | 76 - mojo/public/cpp/bindings/array_traits_stl.h | 127 - mojo/public/cpp/bindings/array_traits_wtf_vector.h | 47 - mojo/public/cpp/bindings/associated_binding.h | 171 - mojo/public/cpp/bindings/associated_binding_set.h | 29 - mojo/public/cpp/bindings/associated_group.h | 51 - .../cpp/bindings/associated_group_controller.h | 93 - .../public/cpp/bindings/associated_interface_ptr.h | 283 -- .../cpp/bindings/associated_interface_ptr_info.h | 77 - .../cpp/bindings/associated_interface_request.h | 90 - mojo/public/cpp/bindings/binding.h | 276 -- mojo/public/cpp/bindings/binding_set.h | 267 -- mojo/public/cpp/bindings/bindings_export.h | 34 - mojo/public/cpp/bindings/clone_traits.h | 86 - .../cpp/bindings/connection_error_callback.h | 21 - mojo/public/cpp/bindings/connector.h | 241 -- mojo/public/cpp/bindings/disconnect_reason.h | 25 - mojo/public/cpp/bindings/enum_traits.h | 27 - mojo/public/cpp/bindings/filter_chain.h | 61 - mojo/public/cpp/bindings/interface_data_view.h | 25 - .../cpp/bindings/interface_endpoint_client.h | 193 -- .../cpp/bindings/interface_endpoint_controller.h | 37 - mojo/public/cpp/bindings/interface_id.h | 35 - mojo/public/cpp/bindings/interface_ptr.h | 242 -- mojo/public/cpp/bindings/interface_ptr_info.h | 63 - mojo/public/cpp/bindings/interface_ptr_set.h | 107 - mojo/public/cpp/bindings/interface_request.h | 178 -- mojo/public/cpp/bindings/lib/array_internal.cc | 59 - mojo/public/cpp/bindings/lib/array_internal.h | 368 --- mojo/public/cpp/bindings/lib/array_serialization.h | 555 ---- mojo/public/cpp/bindings/lib/associated_binding.cc | 62 - mojo/public/cpp/bindings/lib/associated_group.cc | 34 - .../bindings/lib/associated_group_controller.cc | 24 - .../cpp/bindings/lib/associated_interface_ptr.cc | 18 - .../bindings/lib/associated_interface_ptr_state.h | 157 - mojo/public/cpp/bindings/lib/binding_state.cc | 90 - mojo/public/cpp/bindings/lib/binding_state.h | 128 - mojo/public/cpp/bindings/lib/bindings_internal.h | 336 -- mojo/public/cpp/bindings/lib/buffer.h | 70 - mojo/public/cpp/bindings/lib/connector.cc | 493 --- .../cpp/bindings/lib/control_message_handler.cc | 150 - .../cpp/bindings/lib/control_message_handler.h | 48 - .../cpp/bindings/lib/control_message_proxy.cc | 188 -- .../cpp/bindings/lib/control_message_proxy.h | 49 - mojo/public/cpp/bindings/lib/equals_traits.h | 94 - mojo/public/cpp/bindings/lib/filter_chain.cc | 47 - mojo/public/cpp/bindings/lib/fixed_buffer.cc | 30 - mojo/public/cpp/bindings/lib/fixed_buffer.h | 39 - .../bindings/lib/handle_interface_serialization.h | 181 -- mojo/public/cpp/bindings/lib/hash_util.h | 84 - .../cpp/bindings/lib/interface_endpoint_client.cc | 412 --- mojo/public/cpp/bindings/lib/interface_ptr_state.h | 226 -- mojo/public/cpp/bindings/lib/map_data_internal.h | 85 - mojo/public/cpp/bindings/lib/map_serialization.h | 182 -- mojo/public/cpp/bindings/lib/may_auto_lock.h | 62 - mojo/public/cpp/bindings/lib/message.cc | 332 -- mojo/public/cpp/bindings/lib/message_buffer.cc | 52 - mojo/public/cpp/bindings/lib/message_buffer.h | 43 - mojo/public/cpp/bindings/lib/message_builder.cc | 69 - mojo/public/cpp/bindings/lib/message_builder.h | 45 - .../cpp/bindings/lib/message_header_validator.cc | 133 - mojo/public/cpp/bindings/lib/message_internal.h | 82 - mojo/public/cpp/bindings/lib/multiplex_router.cc | 960 ------ mojo/public/cpp/bindings/lib/multiplex_router.h | 275 -- mojo/public/cpp/bindings/lib/native_enum_data.h | 26 - .../cpp/bindings/lib/native_enum_serialization.h | 82 - mojo/public/cpp/bindings/lib/native_struct.cc | 34 - mojo/public/cpp/bindings/lib/native_struct_data.cc | 22 - mojo/public/cpp/bindings/lib/native_struct_data.h | 38 - .../bindings/lib/native_struct_serialization.cc | 61 - .../cpp/bindings/lib/native_struct_serialization.h | 134 - .../bindings/lib/pipe_control_message_handler.cc | 90 - .../cpp/bindings/lib/pipe_control_message_proxy.cc | 68 - .../lib/scoped_interface_endpoint_handle.cc | 382 --- mojo/public/cpp/bindings/lib/serialization.h | 107 - .../cpp/bindings/lib/serialization_context.cc | 57 - .../cpp/bindings/lib/serialization_context.h | 77 - .../cpp/bindings/lib/serialization_forward.h | 123 - mojo/public/cpp/bindings/lib/serialization_util.h | 213 -- .../public/cpp/bindings/lib/string_serialization.h | 70 - .../cpp/bindings/lib/string_traits_string16.cc | 42 - mojo/public/cpp/bindings/lib/string_traits_wtf.cc | 84 - .../cpp/bindings/lib/sync_call_restrictions.cc | 93 - mojo/public/cpp/bindings/lib/sync_event_watcher.cc | 67 - .../cpp/bindings/lib/sync_handle_registry.cc | 135 - .../public/cpp/bindings/lib/sync_handle_watcher.cc | 76 - mojo/public/cpp/bindings/lib/template_util.h | 120 - mojo/public/cpp/bindings/lib/union_accessor.h | 33 - mojo/public/cpp/bindings/lib/validate_params.h | 88 - mojo/public/cpp/bindings/lib/validation_context.cc | 50 - mojo/public/cpp/bindings/lib/validation_context.h | 169 - mojo/public/cpp/bindings/lib/validation_errors.cc | 150 - mojo/public/cpp/bindings/lib/validation_errors.h | 167 - mojo/public/cpp/bindings/lib/validation_util.cc | 210 -- mojo/public/cpp/bindings/lib/validation_util.h | 206 -- .../cpp/bindings/lib/wtf_clone_equals_util.h | 78 - mojo/public/cpp/bindings/lib/wtf_hash_util.h | 132 - mojo/public/cpp/bindings/lib/wtf_serialization.h | 12 - mojo/public/cpp/bindings/map.h | 42 - mojo/public/cpp/bindings/map_data_view.h | 63 - mojo/public/cpp/bindings/map_traits.h | 56 - mojo/public/cpp/bindings/map_traits_stl.h | 109 - mojo/public/cpp/bindings/map_traits_wtf_hash_map.h | 64 - mojo/public/cpp/bindings/message.h | 302 -- .../public/cpp/bindings/message_header_validator.h | 32 - mojo/public/cpp/bindings/native_enum.h | 28 - mojo/public/cpp/bindings/native_struct.h | 51 - mojo/public/cpp/bindings/native_struct_data_view.h | 36 - .../cpp/bindings/pipe_control_message_handler.h | 55 - .../pipe_control_message_handler_delegate.h | 29 - .../cpp/bindings/pipe_control_message_proxy.h | 45 - mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h | 22 - .../bindings/scoped_interface_endpoint_handle.h | 123 - mojo/public/cpp/bindings/string_data_view.h | 34 - mojo/public/cpp/bindings/string_traits.h | 54 - mojo/public/cpp/bindings/string_traits_stl.h | 38 - mojo/public/cpp/bindings/string_traits_string16.h | 37 - .../cpp/bindings/string_traits_string_piece.h | 43 - mojo/public/cpp/bindings/string_traits_wtf.h | 31 - .../cpp/bindings/strong_associated_binding.h | 125 - mojo/public/cpp/bindings/strong_binding.h | 125 - mojo/public/cpp/bindings/strong_binding_set.h | 26 - mojo/public/cpp/bindings/struct_ptr.h | 283 -- mojo/public/cpp/bindings/struct_traits.h | 165 - mojo/public/cpp/bindings/sync_call_restrictions.h | 108 - mojo/public/cpp/bindings/sync_event_watcher.h | 68 - mojo/public/cpp/bindings/sync_handle_registry.h | 71 - mojo/public/cpp/bindings/sync_handle_watcher.h | 75 - mojo/public/cpp/bindings/tests/BUILD.gn | 146 - .../tests/associated_interface_unittest.cc | 1189 ------- .../bindings/tests/bind_task_runner_unittest.cc | 395 --- .../bindings/tests/binding_callback_unittest.cc | 338 -- .../cpp/bindings/tests/binding_set_unittest.cc | 416 --- mojo/public/cpp/bindings/tests/binding_unittest.cc | 611 ---- .../public/cpp/bindings/tests/bindings_perftest.cc | 286 -- mojo/public/cpp/bindings/tests/blink_typemaps.gni | 8 - mojo/public/cpp/bindings/tests/buffer_unittest.cc | 93 - .../cpp/bindings/tests/chromium_typemaps.gni | 9 - .../cpp/bindings/tests/connector_unittest.cc | 599 ---- .../public/cpp/bindings/tests/constant_unittest.cc | 60 - .../cpp/bindings/tests/container_test_util.cc | 52 - .../cpp/bindings/tests/container_test_util.h | 55 - .../cpp/bindings/tests/data_view_unittest.cc | 303 -- mojo/public/cpp/bindings/tests/e2e_perftest.cc | 204 -- mojo/public/cpp/bindings/tests/equals_unittest.cc | 122 - .../cpp/bindings/tests/handle_passing_unittest.cc | 356 --- mojo/public/cpp/bindings/tests/hash_unittest.cc | 35 - .../cpp/bindings/tests/interface_ptr_unittest.cc | 937 ------ mojo/public/cpp/bindings/tests/map_unittest.cc | 46 - mojo/public/cpp/bindings/tests/message_queue.cc | 39 - mojo/public/cpp/bindings/tests/message_queue.h | 44 - .../cpp/bindings/tests/mojo_test_blink_export.h | 29 - mojo/public/cpp/bindings/tests/mojo_test_export.h | 29 - .../bindings/tests/multiplex_router_unittest.cc | 314 -- mojo/public/cpp/bindings/tests/pickle_unittest.cc | 403 --- .../cpp/bindings/tests/pickled_types_blink.cc | 67 - .../cpp/bindings/tests/pickled_types_blink.h | 88 - .../cpp/bindings/tests/pickled_types_chromium.cc | 69 - .../cpp/bindings/tests/pickled_types_chromium.h | 81 - mojo/public/cpp/bindings/tests/rect_blink.h | 83 - mojo/public/cpp/bindings/tests/rect_blink.typemap | 18 - mojo/public/cpp/bindings/tests/rect_blink_traits.h | 35 - mojo/public/cpp/bindings/tests/rect_chromium.h | 87 - .../cpp/bindings/tests/rect_chromium.typemap | 18 - .../cpp/bindings/tests/rect_chromium_traits.h | 34 - .../bindings/tests/report_bad_message_unittest.cc | 194 -- .../bindings/tests/request_response_unittest.cc | 157 - mojo/public/cpp/bindings/tests/router_test_util.cc | 111 - mojo/public/cpp/bindings/tests/router_test_util.h | 92 - .../cpp/bindings/tests/sample_service_unittest.cc | 362 --- .../tests/serialization_warning_unittest.cc | 251 -- mojo/public/cpp/bindings/tests/shared_rect.h | 43 - .../public/cpp/bindings/tests/shared_rect_traits.h | 33 - .../cpp/bindings/tests/struct_traits_unittest.cc | 553 ---- mojo/public/cpp/bindings/tests/struct_unittest.cc | 526 ---- .../cpp/bindings/tests/struct_with_traits.typemap | 26 - .../cpp/bindings/tests/struct_with_traits_impl.cc | 36 - .../cpp/bindings/tests/struct_with_traits_impl.h | 168 - .../tests/struct_with_traits_impl_traits.cc | 137 - .../tests/struct_with_traits_impl_traits.h | 196 -- .../cpp/bindings/tests/sync_method_unittest.cc | 831 ----- .../bindings/tests/test_native_types_blink.typemap | 17 - .../tests/test_native_types_chromium.typemap | 17 - .../cpp/bindings/tests/type_conversion_unittest.cc | 161 - mojo/public/cpp/bindings/tests/union_unittest.cc | 1246 -------- .../bindings/tests/validation_context_unittest.cc | 297 -- .../bindings/tests/validation_test_input_parser.cc | 412 --- .../bindings/tests/validation_test_input_parser.h | 121 - .../cpp/bindings/tests/validation_unittest.cc | 498 --- mojo/public/cpp/bindings/tests/variant_test_util.h | 32 - .../cpp/bindings/tests/versioning_apptest.cc | 123 - .../cpp/bindings/tests/versioning_test_service.cc | 127 - .../public/cpp/bindings/tests/wtf_hash_unittest.cc | 60 - mojo/public/cpp/bindings/tests/wtf_map_unittest.cc | 41 - .../cpp/bindings/tests/wtf_types_unittest.cc | 245 -- .../cpp/bindings/thread_safe_interface_ptr.h | 394 --- mojo/public/cpp/bindings/type_converter.h | 116 - mojo/public/cpp/bindings/union_traits.h | 39 - .../cpp/bindings/unique_ptr_impl_ref_traits.h | 22 - mojo/public/cpp/system/BUILD.gn | 57 - mojo/public/cpp/system/README.md | 396 --- mojo/public/cpp/system/buffer.cc | 46 - mojo/public/cpp/system/buffer.h | 82 - mojo/public/cpp/system/core.h | 14 - mojo/public/cpp/system/data_pipe.h | 163 - mojo/public/cpp/system/functions.h | 26 - mojo/public/cpp/system/handle.h | 220 -- mojo/public/cpp/system/handle_signals_state.h | 83 - mojo/public/cpp/system/message.cc | 13 - mojo/public/cpp/system/message.h | 83 - mojo/public/cpp/system/message_pipe.h | 158 - mojo/public/cpp/system/platform_handle.cc | 178 -- mojo/public/cpp/system/platform_handle.h | 92 - mojo/public/cpp/system/simple_watcher.cc | 279 -- mojo/public/cpp/system/simple_watcher.h | 215 -- mojo/public/cpp/system/system_export.h | 34 - mojo/public/cpp/system/tests/BUILD.gn | 23 - mojo/public/cpp/system/tests/core_unittest.cc | 510 --- .../system/tests/handle_signals_state_unittest.cc | 42 - .../cpp/system/tests/simple_watcher_unittest.cc | 277 -- mojo/public/cpp/system/tests/wait_set_unittest.cc | 376 --- mojo/public/cpp/system/tests/wait_unittest.cc | 321 -- mojo/public/cpp/system/wait.cc | 200 -- mojo/public/cpp/system/wait.h | 75 - mojo/public/cpp/system/wait_set.cc | 371 --- mojo/public/cpp/system/wait_set.h | 124 - mojo/public/cpp/system/watcher.cc | 20 - mojo/public/cpp/system/watcher.h | 37 - mojo/public/cpp/test_support/BUILD.gn | 19 - mojo/public/cpp/test_support/lib/test_support.cc | 26 - mojo/public/cpp/test_support/lib/test_utils.cc | 100 - mojo/public/cpp/test_support/test_support.h | 35 - mojo/public/cpp/test_support/test_utils.h | 40 - mojo/public/interfaces/BUILD.gn | 9 - mojo/public/interfaces/bindings/BUILD.gn | 29 - .../bindings/interface_control_messages.mojom | 67 - .../new_bindings/interface_control_messages.mojom | 67 - .../new_bindings/pipe_control_messages.mojom | 46 - .../bindings/pipe_control_messages.mojom | 46 - mojo/public/interfaces/bindings/tests/BUILD.gn | 204 -- .../associated_conformance_mthd0_good.data | 26 - .../associated_conformance_mthd0_good.expected | 1 - ...ormance_mthd0_illegal_invalid_interface_id.data | 24 - ...nce_mthd0_illegal_invalid_interface_id.expected | 1 - ...formance_mthd0_illegal_master_interface_id.data | 24 - ...ance_mthd0_illegal_master_interface_id.expected | 1 - ...ance_mthd0_interface_id_index_out_of_range.data | 27 - ..._mthd0_interface_id_index_out_of_range.expected | 1 - ...d0_unexpected_invalid_associated_interface.data | 25 - ...nexpected_invalid_associated_interface.expected | 1 - .../associated_conformance_mthd1_good.data | 26 - .../associated_conformance_mthd1_good.expected | 1 - ...thd1_unexpected_invalid_associated_request.data | 27 - ..._unexpected_invalid_associated_request.expected | 1 - .../associated_conformance_mthd2_good.data | 18 - .../associated_conformance_mthd2_good.expected | 1 - ...rmance_mthd3_collided_interface_id_indices.data | 36 - ...ce_mthd3_collided_interface_id_indices.expected | 1 - .../associated_conformance_mthd3_good.data | 35 - .../associated_conformance_mthd3_good.expected | 1 - ...cted_invalid_associated_interface_in_array.data | 36 - ..._invalid_associated_interface_in_array.expected | 1 - ...mance_mthd3_wrong_interface_id_index_order.data | 38 - ...e_mthd3_wrong_interface_id_index_order.expected | 1 - .../boundscheck_msghdr_no_such_method.data | 7 - .../boundscheck_msghdr_no_such_method.expected | 1 - .../tests/data/validation/conformance_empty.data | 0 .../data/validation/conformance_empty.expected | 1 - .../conformance_msghdr_incomplete_struct.data | 2 - .../conformance_msghdr_incomplete_struct.expected | 1 - ...onformance_msghdr_incomplete_struct_header.data | 1 - ...rmance_msghdr_incomplete_struct_header.expected | 1 - .../conformance_msghdr_invalid_flag_combo.data | 8 - .../conformance_msghdr_invalid_flag_combo.expected | 1 - .../conformance_msghdr_missing_request_id.data | 8 - .../conformance_msghdr_missing_request_id.expected | 1 - .../conformance_msghdr_no_such_method.data | 7 - .../conformance_msghdr_no_such_method.expected | 1 - .../conformance_msghdr_num_bytes_huge.data | 6 - .../conformance_msghdr_num_bytes_huge.expected | 1 - ...msghdr_num_bytes_less_than_min_requirement.data | 4 - ...dr_num_bytes_less_than_min_requirement.expected | 1 - ...e_msghdr_num_bytes_less_than_struct_header.data | 6 - ...ghdr_num_bytes_less_than_struct_header.expected | 1 - ...rmance_msghdr_num_bytes_version_mismatch_1.data | 9 - ...ce_msghdr_num_bytes_version_mismatch_1.expected | 1 - ...rmance_msghdr_num_bytes_version_mismatch_2.data | 10 - ...ce_msghdr_num_bytes_version_mismatch_2.expected | 1 - ...rmance_msghdr_num_bytes_version_mismatch_3.data | 7 - ...ce_msghdr_num_bytes_version_mismatch_3.expected | 1 - .../data/validation/conformance_mthd0_good.data | 13 - .../validation/conformance_mthd0_good.expected | 1 - .../conformance_mthd0_incomplete_struct.data | 11 - .../conformance_mthd0_incomplete_struct.expected | 1 - ...conformance_mthd0_incomplete_struct_header.data | 9 - ...ormance_mthd0_incomplete_struct_header.expected | 1 - .../conformance_mthd0_invalid_request_flags.data | 8 - ...onformance_mthd0_invalid_request_flags.expected | 1 - .../conformance_mthd0_invalid_request_flags2.data | 9 - ...nformance_mthd0_invalid_request_flags2.expected | 1 - .../conformance_mthd0_struct_num_bytes_huge.data | 12 - ...onformance_mthd0_struct_num_bytes_huge.expected | 1 - ...struct_num_bytes_less_than_min_requirement.data | 11 - ...ct_num_bytes_less_than_min_requirement.expected | 1 - ...0_struct_num_bytes_less_than_struct_header.data | 12 - ...ruct_num_bytes_less_than_struct_header.expected | 1 - .../data/validation/conformance_mthd10_good.data | 48 - .../validation/conformance_mthd10_good.expected | 1 - .../conformance_mthd10_good_non_unique_keys.data | 48 - ...onformance_mthd10_good_non_unique_keys.expected | 1 - .../validation/conformance_mthd10_null_keys.data | 25 - .../conformance_mthd10_null_keys.expected | 1 - .../validation/conformance_mthd10_null_values.data | 40 - .../conformance_mthd10_null_values.expected | 1 - .../conformance_mthd10_one_null_key.data | 40 - .../conformance_mthd10_one_null_key.expected | 1 - .../conformance_mthd10_unequal_array_size.data | 48 - .../conformance_mthd10_unequal_array_size.expected | 1 - .../conformance_mthd11_good_version0.data | 19 - .../conformance_mthd11_good_version0.expected | 1 - .../conformance_mthd11_good_version1.data | 20 - .../conformance_mthd11_good_version1.expected | 1 - .../conformance_mthd11_good_version2.data | 20 - .../conformance_mthd11_good_version2.expected | 1 - .../conformance_mthd11_good_version3.data | 28 - .../conformance_mthd11_good_version3.expected | 1 - ...nce_mthd11_good_version_newer_than_known_1.data | 30 - ...mthd11_good_version_newer_than_known_1.expected | 1 - ...nce_mthd11_good_version_newer_than_known_2.data | 30 - ...mthd11_good_version_newer_than_known_2.expected | 1 - ...rmance_mthd11_num_bytes_version_mismatch_1.data | 21 - ...ce_mthd11_num_bytes_version_mismatch_1.expected | 1 - ...rmance_mthd11_num_bytes_version_mismatch_2.data | 19 - ...ce_mthd11_num_bytes_version_mismatch_2.expected | 1 - .../conformance_mthd12_invalid_request_flags.data | 9 - ...nformance_mthd12_invalid_request_flags.expected | 1 - .../data/validation/conformance_mthd13_good_1.data | 17 - .../validation/conformance_mthd13_good_1.expected | 1 - .../data/validation/conformance_mthd13_good_2.data | 19 - .../validation/conformance_mthd13_good_2.expected | 1 - .../conformance_mthd14_good_known_enum_values.data | 13 - ...formance_mthd14_good_known_enum_values.expected | 1 - ...e_mthd14_good_uknown_extensible_enum_value.data | 13 - ...hd14_good_uknown_extensible_enum_value.expected | 1 - ...ce_mthd14_uknown_non_extensible_enum_value.data | 14 - ...thd14_uknown_non_extensible_enum_value.expected | 1 - .../conformance_mthd15_good_empy_enum_array.data | 22 - ...onformance_mthd15_good_empy_enum_array.expected | 1 - ...rmance_mthd15_good_known_enum_array_values.data | 27 - ...ce_mthd15_good_known_enum_array_values.expected | 1 - ...15_good_uknown_extensible_enum_array_value.data | 20 - ...ood_uknown_extensible_enum_array_value.expected | 1 - ...d15_uknown_non_extensible_enum_array_value.data | 21 - ...uknown_non_extensible_enum_array_value.expected | 1 - ..._mthd16_uknown_non_extensible_enum_map_key.data | 34 - ...d16_uknown_non_extensible_enum_map_key.expected | 1 - ...thd16_uknown_non_extensible_enum_map_value.data | 34 - ...6_uknown_non_extensible_enum_map_value.expected | 1 - .../data/validation/conformance_mthd17_good.data | 23 - .../validation/conformance_mthd17_good.expected | 1 - ...d17_interface_handle_out_of_range_in_array.data | 24 - ...interface_handle_out_of_range_in_array.expected | 1 - ...hd17_unexpected_invalid_interface_in_array.data | 23 - ..._unexpected_invalid_interface_in_array.expected | 1 - .../data/validation/conformance_mthd18_good.data | 14 - .../validation/conformance_mthd18_good.expected | 1 - .../conformance_mthd19_exceed_recursion_limit.data | 612 ---- ...formance_mthd19_exceed_recursion_limit.expected | 1 - .../data/validation/conformance_mthd1_good.data | 18 - .../validation/conformance_mthd1_good.expected | 1 - .../conformance_mthd1_misaligned_struct.data | 20 - .../conformance_mthd1_misaligned_struct.expected | 1 - .../conformance_mthd1_struct_pointer_overflow.data | 13 - ...formance_mthd1_struct_pointer_overflow.expected | 1 - .../conformance_mthd1_unexpected_null_struct.data | 12 - ...nformance_mthd1_unexpected_null_struct.expected | 1 - .../data/validation/conformance_mthd20_good.data | 57 - .../validation/conformance_mthd20_good.expected | 1 - ...21_empty_extensible_enum_accepts_any_value.data | 13 - ...mpty_extensible_enum_accepts_any_value.expected | 1 - ...empty_nonextensible_enum_accepts_no_values.data | 14 - ...y_nonextensible_enum_accepts_no_values.expected | 1 - .../data/validation/conformance_mthd2_good.data | 34 - .../validation/conformance_mthd2_good.expected | 1 - ...nce_mthd2_multiple_pointers_to_same_struct.data | 27 - ...mthd2_multiple_pointers_to_same_struct.expected | 1 - .../conformance_mthd2_overlapped_objects.data | 32 - .../conformance_mthd2_overlapped_objects.expected | 1 - .../conformance_mthd2_wrong_layout_order.data | 34 - .../conformance_mthd2_wrong_layout_order.expected | 1 - .../conformance_mthd3_array_num_bytes_huge.data | 18 - ...conformance_mthd3_array_num_bytes_huge.expected | 1 - ...hd3_array_num_bytes_less_than_array_header.data | 18 - ...array_num_bytes_less_than_array_header.expected | 1 - ...3_array_num_bytes_less_than_necessary_size.data | 20 - ...ray_num_bytes_less_than_necessary_size.expected | 1 - .../conformance_mthd3_array_pointer_overflow.data | 13 - ...nformance_mthd3_array_pointer_overflow.expected | 1 - .../data/validation/conformance_mthd3_good.data | 19 - .../validation/conformance_mthd3_good.expected | 1 - .../conformance_mthd3_incomplete_array.data | 16 - .../conformance_mthd3_incomplete_array.expected | 1 - .../conformance_mthd3_incomplete_array_header.data | 15 - ...formance_mthd3_incomplete_array_header.expected | 1 - .../conformance_mthd3_misaligned_array.data | 21 - .../conformance_mthd3_misaligned_array.expected | 1 - .../conformance_mthd3_unexpected_null_array.data | 12 - ...onformance_mthd3_unexpected_null_array.expected | 1 - .../data/validation/conformance_mthd4_good.data | 34 - .../validation/conformance_mthd4_good.expected | 1 - ...ance_mthd4_multiple_pointers_to_same_array.data | 26 - ..._mthd4_multiple_pointers_to_same_array.expected | 1 - .../conformance_mthd4_overlapped_objects.data | 32 - .../conformance_mthd4_overlapped_objects.expected | 1 - .../conformance_mthd4_wrong_layout_order.data | 35 - .../conformance_mthd4_wrong_layout_order.expected | 1 - .../data/validation/conformance_mthd5_good.data | 37 - .../validation/conformance_mthd5_good.expected | 1 - .../conformance_mthd5_handle_out_of_range.data | 38 - .../conformance_mthd5_handle_out_of_range.expected | 1 - ...e_mthd5_multiple_handles_with_same_value_1.data | 37 - ...hd5_multiple_handles_with_same_value_1.expected | 1 - ...e_mthd5_multiple_handles_with_same_value_2.data | 37 - ...hd5_multiple_handles_with_same_value_2.expected | 1 - ...onformance_mthd5_unexpected_invalid_handle.data | 36 - ...rmance_mthd5_unexpected_invalid_handle.expected | 1 - .../conformance_mthd5_wrong_handle_order.data | 38 - .../conformance_mthd5_wrong_handle_order.expected | 1 - .../data/validation/conformance_mthd6_good.data | 24 - .../validation/conformance_mthd6_good.expected | 1 - ...d_array_num_bytes_less_than_necessary_size.data | 24 - ...ray_num_bytes_less_than_necessary_size.expected | 1 - .../data/validation/conformance_mthd7_good.data | 40 - .../validation/conformance_mthd7_good.expected | 1 - ...formance_mthd7_unexpected_null_fixed_array.data | 26 - ...ance_mthd7_unexpected_null_fixed_array.expected | 1 - ...conformance_mthd7_unmatched_array_elements.data | 34 - ...ormance_mthd7_unmatched_array_elements.expected | 1 - ...ance_mthd7_unmatched_array_elements_nested.data | 40 - ..._mthd7_unmatched_array_elements_nested.expected | 1 - ...conformance_mthd8_array_num_bytes_overflow.data | 21 - ...ormance_mthd8_array_num_bytes_overflow.expected | 1 - .../data/validation/conformance_mthd8_good.data | 32 - .../validation/conformance_mthd8_good.expected | 1 - .../conformance_mthd8_unexpected_null_array.data | 12 - ...onformance_mthd8_unexpected_null_array.expected | 1 - .../conformance_mthd8_unexpected_null_string.data | 33 - ...nformance_mthd8_unexpected_null_string.expected | 1 - .../data/validation/conformance_mthd9_good.data | 36 - .../validation/conformance_mthd9_good.expected | 1 - .../conformance_mthd9_good_null_array.data | 14 - .../conformance_mthd9_good_null_array.expected | 1 - .../conformance_mthd9_unexpected_null_array.data | 27 - ...onformance_mthd9_unexpected_null_array.expected | 1 - .../integration_intf_resp_mthd0_good.data | 19 - .../integration_intf_resp_mthd0_good.expected | 1 - ...on_intf_resp_mthd0_unexpected_array_header.data | 19 - ...ntf_resp_mthd0_unexpected_array_header.expected | 1 - .../integration_intf_rqst_mthd0_good.data | 20 - .../integration_intf_rqst_mthd0_good.expected | 1 - ...n_intf_rqst_mthd0_unexpected_struct_header.data | 17 - ...tf_rqst_mthd0_unexpected_struct_header.expected | 1 - .../integration_msghdr_invalid_flags.data | 8 - .../integration_msghdr_invalid_flags.expected | 1 - .../resp_boundscheck_msghdr_no_such_method.data | 8 - ...resp_boundscheck_msghdr_no_such_method.expected | 1 - ...conformance_msghdr_invalid_response_flags1.data | 8 - ...ormance_msghdr_invalid_response_flags1.expected | 1 - ...conformance_msghdr_invalid_response_flags2.data | 8 - ...ormance_msghdr_invalid_response_flags2.expected | 1 - .../resp_conformance_msghdr_no_such_method.data | 8 - ...resp_conformance_msghdr_no_such_method.expected | 1 - mojo/public/interfaces/bindings/tests/echo.mojom | 12 - .../interfaces/bindings/tests/echo_import.mojom | 10 - .../bindings/tests/math_calculator.mojom | 12 - .../interfaces/bindings/tests/no_module.mojom | 9 - .../interfaces/bindings/tests/ping_service.mojom | 14 - mojo/public/interfaces/bindings/tests/rect.mojom | 31 - .../bindings/tests/regression_tests.mojom | 76 - .../interfaces/bindings/tests/sample_factory.mojom | 41 - .../interfaces/bindings/tests/sample_import.mojom | 38 - .../interfaces/bindings/tests/sample_import2.mojom | 28 - .../bindings/tests/sample_interfaces.mojom | 32 - .../interfaces/bindings/tests/sample_service.mojom | 112 - .../public/interfaces/bindings/tests/scoping.mojom | 17 - .../tests/serialization_test_structs.mojom | 36 - .../bindings/tests/struct_with_traits.mojom | 83 - .../tests/test_associated_interfaces.mojom | 54 - .../bindings/tests/test_bad_messages.mojom | 13 - .../interfaces/bindings/tests/test_constants.mojom | 57 - .../interfaces/bindings/tests/test_data_view.mojom | 41 - .../interfaces/bindings/tests/test_export.mojom | 20 - .../interfaces/bindings/tests/test_export2.mojom | 10 - .../interfaces/bindings/tests/test_import.mojom | 11 - .../bindings/tests/test_native_types.mojom | 38 - .../interfaces/bindings/tests/test_structs.mojom | 414 --- .../bindings/tests/test_sync_methods.mojom | 44 - .../interfaces/bindings/tests/test_unions.mojom | 105 - .../interfaces/bindings/tests/test_wtf_types.mojom | 50 - .../validation_test_associated_interfaces.mojom | 18 - .../tests/validation_test_interfaces.mojom | 135 - .../bindings/tests/versioning_test_client.mojom | 34 - .../bindings/tests/versioning_test_service.mojom | 38 - mojo/public/java/BUILD.gn | 64 - mojo/public/java/bindings/README.md | 12 - .../bindings/AssociatedInterfaceNotSupported.java | 11 - .../AssociatedInterfaceRequestNotSupported.java | 11 - .../mojo/bindings/AutoCloseableRouter.java | 116 - .../org/chromium/mojo/bindings/BindingsHelper.java | 199 -- .../src/org/chromium/mojo/bindings/Callbacks.java | 130 - .../mojo/bindings/ConnectionErrorHandler.java | 15 - .../src/org/chromium/mojo/bindings/Connector.java | 214 -- .../src/org/chromium/mojo/bindings/DataHeader.java | 70 - .../src/org/chromium/mojo/bindings/Decoder.java | 776 ----- .../bindings/DelegatingConnectionErrorHandler.java | 49 - .../mojo/bindings/DeserializationException.java | 26 - .../src/org/chromium/mojo/bindings/Encoder.java | 587 ---- .../chromium/mojo/bindings/ExecutorFactory.java | 169 - .../org/chromium/mojo/bindings/HandleOwner.java | 29 - .../src/org/chromium/mojo/bindings/Interface.java | 425 --- .../bindings/InterfaceControlMessagesHelper.java | 105 - .../chromium/mojo/bindings/InterfaceRequest.java | 58 - .../src/org/chromium/mojo/bindings/Message.java | 69 - .../org/chromium/mojo/bindings/MessageHeader.java | 248 -- .../chromium/mojo/bindings/MessageReceiver.java | 25 - .../bindings/MessageReceiverWithResponder.java | 21 - .../src/org/chromium/mojo/bindings/Router.java | 31 - .../src/org/chromium/mojo/bindings/RouterImpl.java | 274 -- .../mojo/bindings/SerializationException.java | 26 - .../org/chromium/mojo/bindings/ServiceMessage.java | 73 - .../mojo/bindings/SideEffectFreeCloseable.java | 21 - .../src/org/chromium/mojo/bindings/Struct.java | 88 - .../src/org/chromium/mojo/bindings/Union.java | 30 - mojo/public/java/system/README.md | 25 - .../system/src/org/chromium/mojo/system/Core.java | 183 -- .../src/org/chromium/mojo/system/DataPipe.java | 334 -- .../system/src/org/chromium/mojo/system/Flags.java | 83 - .../src/org/chromium/mojo/system/Handle.java | 61 - .../org/chromium/mojo/system/InvalidHandle.java | 219 -- .../chromium/mojo/system/MessagePipeHandle.java | 224 -- .../org/chromium/mojo/system/MojoException.java | 44 - .../src/org/chromium/mojo/system/MojoResult.java | 82 - .../system/src/org/chromium/mojo/system/Pair.java | 67 - .../src/org/chromium/mojo/system/ResultAnd.java | 34 - .../src/org/chromium/mojo/system/RunLoop.java | 41 - .../chromium/mojo/system/SharedBufferHandle.java | 160 - .../org/chromium/mojo/system/UntypedHandle.java | 45 - .../src/org/chromium/mojo/system/Watcher.java | 38 - mojo/public/js/BUILD.gn | 93 - mojo/public/js/README.md | 7 - mojo/public/js/bindings.js | 322 -- mojo/public/js/buffer.js | 156 - mojo/public/js/codec.js | 926 ------ mojo/public/js/connector.js | 113 - mojo/public/js/constants.cc | 33 - mojo/public/js/constants.h | 30 - mojo/public/js/core.js | 304 -- mojo/public/js/interface_types.js | 70 - mojo/public/js/lib/control_message_handler.js | 111 - mojo/public/js/lib/control_message_proxy.js | 104 - mojo/public/js/lib/interface_endpoint_client.js | 232 -- mojo/public/js/lib/interface_endpoint_handle.js | 158 - mojo/public/js/lib/pipe_control_message_handler.js | 61 - mojo/public/js/lib/pipe_control_message_proxy.js | 56 - mojo/public/js/new_bindings/base.js | 111 - mojo/public/js/new_bindings/bindings.js | 275 -- mojo/public/js/new_bindings/buffer.js | 155 - mojo/public/js/new_bindings/codec.js | 917 ------ mojo/public/js/new_bindings/connector.js | 104 - mojo/public/js/new_bindings/interface_types.js | 46 - .../js/new_bindings/lib/control_message_handler.js | 106 - .../js/new_bindings/lib/control_message_proxy.js | 97 - mojo/public/js/new_bindings/router.js | 190 -- mojo/public/js/new_bindings/unicode.js | 51 - mojo/public/js/new_bindings/validator.js | 511 --- mojo/public/js/router.js | 269 -- mojo/public/js/support.js | 53 - mojo/public/js/tests/core_unittest.js | 223 -- .../js/tests/validation_test_input_parser.js | 299 -- mojo/public/js/tests/validation_unittest.js | 334 -- mojo/public/js/threading.js | 21 - mojo/public/js/unicode.js | 51 - mojo/public/js/validator.js | 560 ---- mojo/public/tests/test_support_private.cc | 76 - mojo/public/tests/test_support_private.h | 37 - mojo/public/tools/bindings/BUILD.gn | 77 - mojo/public/tools/bindings/README.md | 749 ----- .../bindings/blink_bindings_configuration.gni | 33 - .../bindings/chromium_bindings_configuration.gni | 83 - .../bindings/format_typemap_generator_args.py | 34 - .../tools/bindings/generate_type_mappings.py | 148 - mojo/public/tools/bindings/generators/__init__.py | 0 .../generators/cpp_templates/enum_macros.tmpl | 131 - .../enum_serialization_declaration.tmpl | 29 - .../cpp_templates/interface_declaration.tmpl | 65 - .../cpp_templates/interface_definition.tmpl | 448 --- .../generators/cpp_templates/interface_macros.tmpl | 49 - .../cpp_templates/interface_proxy_declaration.tmpl | 16 - .../interface_request_validator_declaration.tmpl | 4 - .../interface_response_validator_declaration.tmpl | 4 - .../cpp_templates/interface_stub_declaration.tmpl | 41 - .../cpp_templates/module-shared-internal.h.tmpl | 96 - .../generators/cpp_templates/module-shared.cc.tmpl | 64 - .../generators/cpp_templates/module-shared.h.tmpl | 212 -- .../generators/cpp_templates/module.cc.tmpl | 111 - .../generators/cpp_templates/module.h.tmpl | 236 -- .../struct_data_view_declaration.tmpl | 118 - .../cpp_templates/struct_data_view_definition.tmpl | 30 - .../cpp_templates/struct_declaration.tmpl | 46 - .../cpp_templates/struct_definition.tmpl | 70 - .../generators/cpp_templates/struct_macros.tmpl | 161 - .../struct_serialization_declaration.tmpl | 57 - .../cpp_templates/struct_traits_declaration.tmpl | 32 - .../cpp_templates/struct_traits_definition.tmpl | 14 - .../cpp_templates/union_data_view_declaration.tmpl | 92 - .../cpp_templates/union_data_view_definition.tmpl | 12 - .../cpp_templates/union_declaration.tmpl | 56 - .../generators/cpp_templates/union_definition.tmpl | 47 - .../union_serialization_declaration.tmpl | 141 - .../cpp_templates/union_traits_declaration.tmpl | 24 - .../cpp_templates/union_traits_definition.tmpl | 47 - .../cpp_templates/validation_macros.tmpl | 82 - .../cpp_templates/wrapper_class_declaration.tmpl | 94 - .../cpp_templates/wrapper_class_definition.tmpl | 39 - .../wrapper_class_template_definition.tmpl | 20 - .../wrapper_union_class_declaration.tmpl | 80 - .../wrapper_union_class_definition.tmpl | 85 - .../wrapper_union_class_template_definition.tmpl | 41 - .../java_templates/constant_definition.tmpl | 3 - .../generators/java_templates/constants.java.tmpl | 12 - .../java_templates/data_types_definition.tmpl | 418 --- .../generators/java_templates/enum.java.tmpl | 4 - .../generators/java_templates/enum_definition.tmpl | 42 - .../generators/java_templates/header.java.tmpl | 14 - .../generators/java_templates/interface.java.tmpl | 4 - .../java_templates/interface_definition.tmpl | 297 -- .../java_templates/interface_internal.java.tmpl | 4 - .../generators/java_templates/struct.java.tmpl | 4 - .../generators/java_templates/union.java.tmpl | 4 - .../generators/js_templates/enum_definition.tmpl | 33 - .../js_templates/interface_definition.tmpl | 198 -- .../generators/js_templates/module.amd.tmpl | 70 - .../generators/js_templates/module_definition.tmpl | 49 - .../generators/js_templates/struct_definition.tmpl | 126 - .../generators/js_templates/union_definition.tmpl | 154 - .../generators/js_templates/validation_macros.tmpl | 60 - .../bindings/generators/mojom_cpp_generator.py | 818 ----- .../bindings/generators/mojom_java_generator.py | 550 ---- .../bindings/generators/mojom_js_generator.py | 425 --- mojo/public/tools/bindings/mojom.gni | 661 ---- .../tools/bindings/mojom_bindings_generator.py | 336 -- .../bindings/mojom_bindings_generator_unittest.py | 23 - mojo/public/tools/bindings/pylib/mojom/__init__.py | 0 mojo/public/tools/bindings/pylib/mojom/error.py | 27 - mojo/public/tools/bindings/pylib/mojom/fileutil.py | 18 - .../bindings/pylib/mojom/generate/__init__.py | 0 .../pylib/mojom/generate/constant_resolver.py | 91 - .../bindings/pylib/mojom/generate/generator.py | 153 - .../pylib/mojom/generate/generator_unittest.py | 24 - .../tools/bindings/pylib/mojom/generate/module.py | 891 ------ .../bindings/pylib/mojom/generate/module_tests.py | 34 - .../tools/bindings/pylib/mojom/generate/pack.py | 250 -- .../bindings/pylib/mojom/generate/pack_tests.py | 193 -- .../bindings/pylib/mojom/generate/run_tests.py | 35 - .../pylib/mojom/generate/template_expander.py | 67 - .../bindings/pylib/mojom/generate/test_support.py | 193 -- .../bindings/pylib/mojom/generate/translate.py | 639 ---- .../tools/bindings/pylib/mojom/parse/__init__.py | 0 .../public/tools/bindings/pylib/mojom/parse/ast.py | 410 --- .../tools/bindings/pylib/mojom/parse/lexer.py | 254 -- .../tools/bindings/pylib/mojom/parse/parser.py | 461 --- .../tools/bindings/pylib/mojom_tests/__init__.py | 0 .../pylib/mojom_tests/fileutil_unittest.py | 55 - .../pylib/mojom_tests/generate/__init__.py | 0 .../pylib/mojom_tests/generate/data_unittest.py | 156 - .../mojom_tests/generate/generator_unittest.py | 37 - .../pylib/mojom_tests/generate/module_unittest.py | 48 - .../pylib/mojom_tests/generate/pack_unittest.py | 136 - .../bindings/pylib/mojom_tests/parse/__init__.py | 0 .../pylib/mojom_tests/parse/ast_unittest.py | 135 - .../pylib/mojom_tests/parse/lexer_unittest.py | 192 -- .../pylib/mojom_tests/parse/parser_unittest.py | 1497 --------- .../bindings/pylib/mojom_tests/parse/run_parser.py | 36 - .../pylib/mojom_tests/parse/run_translate.py | 34 - .../pylib/mojom_tests/parse/translate_unittest.py | 80 - .../bindings/pylib/mojom_tests/support/__init__.py | 0 .../pylib/mojom_tests/support/find_files.py | 32 - .../mojom_tests/support/run_bindings_generator.py | 47 - mojo/public/tools/chrome_ipc/generate_mojom.py | 453 --- mojo/public/tools/gn/zip.py | 86 - soong/jni_generator_helper.sh | 42 - soong/mojom_source_generator.sh | 115 - third_party/catapult/LICENSE | 27 - third_party/catapult/devil/PRESUBMIT.py | 81 - third_party/catapult/devil/README.md | 37 - third_party/catapult/devil/bin/generate_md_docs | 45 - third_party/catapult/devil/bin/run_py_devicetests | 32 - third_party/catapult/devil/bin/run_py_tests | 22 - third_party/catapult/devil/devil/__init__.py | 7 - .../catapult/devil/devil/android/__init__.py | 3 - .../catapult/devil/devil/android/apk_helper.py | 164 - .../devil/devil/android/apk_helper_test.py | 169 - third_party/catapult/devil/devil/android/app_ui.py | 243 -- .../catapult/devil/devil/android/app_ui_test.py | 191 -- .../catapult/devil/devil/android/battery_utils.py | 699 ----- .../devil/devil/android/battery_utils_test.py | 694 ----- .../devil/devil/android/constants/__init__.py | 3 - .../devil/devil/android/constants/chrome.py | 57 - .../devil/devil/android/constants/file_system.py | 5 - .../catapult/devil/devil/android/decorators.py | 176 -- .../devil/devil/android/decorators_test.py | 332 -- .../devil/devil/android/device_blacklist.py | 80 - .../devil/devil/android/device_blacklist_test.py | 38 - .../catapult/devil/devil/android/device_errors.py | 180 -- .../devil/devil/android/device_errors_test.py | 72 - .../catapult/devil/devil/android/device_list.py | 52 - .../catapult/devil/devil/android/device_signal.py | 41 - .../devil/devil/android/device_temp_file.py | 63 - .../devil/devil/android/device_test_case.py | 54 - .../catapult/devil/devil/android/device_utils.py | 2640 ---------------- .../devil/devil/android/device_utils_devicetest.py | 229 -- .../devil/devil/android/device_utils_test.py | 2900 ----------------- .../catapult/devil/devil/android/fastboot_utils.py | 256 -- .../devil/devil/android/fastboot_utils_test.py | 375 --- .../catapult/devil/devil/android/flag_changer.py | 300 -- .../devil/devil/android/flag_changer_devicetest.py | 88 - .../devil/devil/android/flag_changer_test.py | 135 - .../catapult/devil/devil/android/forwarder.py | 464 --- .../devil/devil/android/install_commands.py | 57 - .../catapult/devil/devil/android/logcat_monitor.py | 255 -- .../devil/devil/android/logcat_monitor_test.py | 230 -- third_party/catapult/devil/devil/android/md5sum.py | 120 - .../catapult/devil/devil/android/md5sum_test.py | 237 -- .../catapult/devil/devil/android/perf/__init__.py | 3 - .../devil/devil/android/perf/cache_control.py | 15 - .../devil/devil/android/perf/perf_control.py | 210 -- .../devil/android/perf/perf_control_devicetest.py | 38 - .../devil/android/perf/surface_stats_collector.py | 186 -- .../devil/devil/android/perf/thermal_throttle.py | 135 - third_party/catapult/devil/devil/android/ports.py | 178 -- .../catapult/devil/devil/android/sdk/__init__.py | 6 - .../catapult/devil/devil/android/sdk/aapt.py | 43 - .../android/sdk/adb_compatibility_devicetest.py | 230 -- .../devil/devil/android/sdk/adb_wrapper.py | 917 ------ .../devil/android/sdk/adb_wrapper_devicetest.py | 118 - .../devil/devil/android/sdk/adb_wrapper_test.py | 59 - .../devil/devil/android/sdk/build_tools.py | 51 - .../catapult/devil/devil/android/sdk/dexdump.py | 31 - .../catapult/devil/devil/android/sdk/fastboot.py | 98 - .../devil/devil/android/sdk/gce_adb_wrapper.py | 154 - .../catapult/devil/devil/android/sdk/intent.py | 129 - .../catapult/devil/devil/android/sdk/keyevent.py | 63 - .../devil/devil/android/sdk/shared_prefs.py | 420 --- .../devil/devil/android/sdk/shared_prefs_test.py | 171 - .../devil/devil/android/sdk/split_select.py | 63 - .../push_directory/push_directory_contents.txt | 1 - .../devil/android/sdk/test/data/push_file.txt | 1 - .../devil/devil/android/sdk/version_codes.py | 20 - .../catapult/devil/devil/android/settings.py | 273 -- .../catapult/devil/devil/android/tools/__init__.py | 3 - .../devil/devil/android/tools/adb_run_shell_cmd.py | 61 - .../catapult/devil/devil/android/tools/cpufreq.py | 87 - .../devil/devil/android/tools/device_monitor.py | 231 -- .../devil/android/tools/device_monitor_test.py | 168 - .../devil/devil/android/tools/device_recovery.py | 208 -- .../devil/devil/android/tools/device_status.py | 313 -- .../devil/devil/android/tools/flash_device.py | 70 - .../catapult/devil/devil/android/tools/keyboard.py | 129 - .../devil/devil/android/tools/provision_devices.py | 637 ---- .../devil/devil/android/tools/screenshot.py | 59 - .../devil/devil/android/tools/script_common.py | 29 - .../devil/android/tools/script_common_test.py | 58 - .../devil/devil/android/tools/video_recorder.py | 175 -- .../devil/devil/android/tools/wait_for_devices.py | 50 - .../devil/devil/android/valgrind_tools/__init__.py | 21 - .../devil/android/valgrind_tools/base_tool.py | 53 - third_party/catapult/devil/devil/base_error.py | 24 - .../catapult/devil/devil/constants/__init__.py | 3 - .../catapult/devil/devil/constants/exit_codes.py | 9 - .../catapult/devil/devil/devil_dependencies.json | 127 - third_party/catapult/devil/devil/devil_env.py | 194 -- third_party/catapult/devil/devil/devil_env_test.py | 63 - third_party/catapult/devil/devil/utils/__init__.py | 23 - .../devil/devil/utils/battor_device_mapping.py | 309 -- .../catapult/devil/devil/utils/cmd_helper.py | 394 --- .../catapult/devil/devil/utils/cmd_helper_test.py | 262 -- .../catapult/devil/devil/utils/file_utils.py | 31 - .../catapult/devil/devil/utils/find_usb_devices.py | 532 ---- .../devil/devil/utils/find_usb_devices_test.py | 379 --- third_party/catapult/devil/devil/utils/geometry.py | 75 - .../catapult/devil/devil/utils/geometry_test.py | 61 - .../catapult/devil/devil/utils/host_utils.py | 16 - .../catapult/devil/devil/utils/lazy/__init__.py | 5 - .../devil/devil/utils/lazy/weak_constant.py | 29 - third_party/catapult/devil/devil/utils/lsusb.py | 174 -- .../catapult/devil/devil/utils/lsusb_test.py | 250 -- third_party/catapult/devil/devil/utils/markdown.py | 320 -- .../catapult/devil/devil/utils/markdown_test.py | 121 - .../catapult/devil/devil/utils/mock_calls.py | 180 -- .../catapult/devil/devil/utils/mock_calls_test.py | 173 -- .../catapult/devil/devil/utils/parallelizer.py | 238 -- .../devil/devil/utils/parallelizer_test.py | 162 - .../catapult/devil/devil/utils/reraiser_thread.py | 228 -- .../devil/devil/utils/reraiser_thread_unittest.py | 117 - .../catapult/devil/devil/utils/reset_usb.py | 111 - .../catapult/devil/devil/utils/run_tests_helper.py | 44 - .../catapult/devil/devil/utils/signal_handler.py | 48 - .../devil/utils/test/data/test_serial_map.json | 1 - .../catapult/devil/devil/utils/timeout_retry.py | 175 -- .../devil/devil/utils/timeout_retry_unittest.py | 79 - .../catapult/devil/devil/utils/update_mapping.py | 47 - third_party/catapult/devil/devil/utils/usb_hubs.py | 165 - .../catapult/devil/devil/utils/watchdog_timer.py | 47 - .../catapult/devil/devil/utils/zip_utils.py | 33 - third_party/catapult/devil/docs/adb_wrapper.md | 388 --- .../catapult/devil/docs/device_blacklist.md | 59 - third_party/catapult/devil/docs/device_utils.md | 1041 ------- third_party/catapult/devil/docs/markdown.md | 139 - .../catapult/devil/docs/persistent_device_list.md | 41 - third_party/catapult/devil/pylintrc | 68 - third_party/jinja2/AUTHORS | 33 - third_party/jinja2/Jinja2-2.8.tar.gz.md5 | 1 - third_party/jinja2/Jinja2-2.8.tar.gz.sha512 | 1 - third_party/jinja2/LICENSE | 31 - third_party/jinja2/README.chromium | 25 - third_party/jinja2/__init__.py | 70 - third_party/jinja2/_compat.py | 111 - third_party/jinja2/_stringdefs.py | 132 - third_party/jinja2/bccache.py | 362 --- third_party/jinja2/compiler.py | 1686 ---------- third_party/jinja2/constants.py | 32 - third_party/jinja2/debug.py | 350 --- third_party/jinja2/defaults.py | 43 - third_party/jinja2/environment.py | 1213 -------- third_party/jinja2/exceptions.py | 146 - third_party/jinja2/ext.py | 636 ---- third_party/jinja2/filters.py | 996 ------ third_party/jinja2/get_jinja2.sh | 122 - third_party/jinja2/lexer.py | 734 ----- third_party/jinja2/loaders.py | 481 --- third_party/jinja2/meta.py | 103 - third_party/jinja2/nodes.py | 919 ------ third_party/jinja2/optimizer.py | 68 - third_party/jinja2/parser.py | 899 ------ third_party/jinja2/runtime.py | 667 ---- third_party/jinja2/sandbox.py | 367 --- third_party/jinja2/tests.py | 173 -- third_party/jinja2/utils.py | 531 ---- third_party/jinja2/visitor.py | 87 - third_party/markupsafe/AUTHORS | 13 - third_party/markupsafe/LICENSE | 33 - third_party/markupsafe/MarkupSafe-0.18.tar.gz.md5 | 1 - .../markupsafe/MarkupSafe-0.18.tar.gz.sha512 | 1 - third_party/markupsafe/README.chromium | 24 - third_party/markupsafe/__init__.py | 234 -- third_party/markupsafe/_compat.py | 24 - third_party/markupsafe/_constants.py | 267 -- third_party/markupsafe/_native.py | 46 - third_party/markupsafe/_speedups.c | 239 -- third_party/markupsafe/get_markupsafe.sh | 121 - third_party/ply/LICENSE | 30 - third_party/ply/README | 271 -- third_party/ply/README.chromium | 21 - third_party/ply/__init__.py | 36 - third_party/ply/lex.py | 1058 ------- third_party/ply/license.patch | 41 - third_party/ply/yacc.py | 3276 -------------------- ui/gfx/geometry/mojo/BUILD.gn | 49 - ui/gfx/geometry/mojo/DEPS | 4 - ui/gfx/geometry/mojo/geometry.mojom | 63 - ui/gfx/geometry/mojo/geometry.typemap | 32 - ui/gfx/geometry/mojo/geometry_struct_traits.h | 146 - .../mojo/geometry_struct_traits_unittest.cc | 206 -- .../mojo/geometry_traits_test_service.mojom | 41 - ui/gfx/range/mojo/BUILD.gn | 49 - ui/gfx/range/mojo/DEPS | 4 - ui/gfx/range/mojo/range.mojom | 15 - ui/gfx/range/mojo/range.typemap | 17 - ui/gfx/range/mojo/range_struct_traits.h | 38 - ui/gfx/range/mojo/range_struct_traits_unittest.cc | 65 - ui/gfx/range/mojo/range_traits_test_service.mojom | 17 - 1253 files changed, 1 insertion(+), 179624 deletions(-) delete mode 100644 .gitignore delete mode 100644 Android.bp delete mode 100644 CleanSpec.mk create mode 100644 README.md delete mode 100644 base/android/build_info.cc delete mode 100644 base/android/build_info.h delete mode 100644 base/android/context_utils.cc delete mode 100644 base/android/context_utils.h delete mode 100644 base/android/java/src/org/chromium/base/BuildInfo.java delete mode 100644 base/android/java/src/org/chromium/base/ContextUtils.java delete mode 100644 base/android/java/src/org/chromium/base/Log.java delete mode 100644 base/android/java/src/org/chromium/base/PackageUtils.java delete mode 100644 base/android/java/src/org/chromium/base/VisibleForTesting.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/AccessedByNative.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/CalledByNative.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/JNINamespace.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/MainDex.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/NativeCall.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/RemovableInRelease.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/SuppressFBWarnings.java delete mode 100644 base/android/java/src/org/chromium/base/annotations/UsedByReflection.java delete mode 100644 base/android/java_runtime.cc delete mode 100644 base/android/java_runtime.h delete mode 100644 base/android/jni_android.cc delete mode 100644 base/android/jni_android.h delete mode 100644 base/android/jni_android_unittest.cc delete mode 100644 base/android/jni_generator/android_jar.classes delete mode 100644 base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java delete mode 100755 base/android/jni_generator/jni_generator.py delete mode 100644 base/android/jni_generator/jni_generator_helper.h delete mode 100755 base/android/jni_generator/jni_generator_tests.py delete mode 100644 base/android/jni_generator/sample_for_tests.cc delete mode 100644 base/android/jni_generator/sample_for_tests.h delete mode 100644 base/android/jni_generator/testCalledByNatives.golden delete mode 100644 base/android/jni_generator/testConstantsFromJavaP.golden delete mode 100644 base/android/jni_generator/testFromJavaP.golden delete mode 100644 base/android/jni_generator/testFromJavaPGenerics.golden delete mode 100644 base/android/jni_generator/testInnerClassNatives.golden delete mode 100644 base/android/jni_generator/testInnerClassNativesBothInnerAndOuter.golden delete mode 100644 base/android/jni_generator/testInnerClassNativesMultiple.golden delete mode 100644 base/android/jni_generator/testInputStream.javap delete mode 100644 base/android/jni_generator/testMotionEvent.javap delete mode 100644 base/android/jni_generator/testMotionEvent.javap7 delete mode 100644 base/android/jni_generator/testMultipleJNIAdditionalImport.golden delete mode 100644 base/android/jni_generator/testNatives.golden delete mode 100644 base/android/jni_generator/testNativesLong.golden delete mode 100644 base/android/jni_generator/testSingleJNIAdditionalImport.golden delete mode 100644 base/android/jni_int_wrapper.h delete mode 100644 base/android/jni_string.cc delete mode 100644 base/android/jni_string.h delete mode 100644 base/android/jni_string_unittest.cc delete mode 100644 base/android/scoped_java_ref.cc delete mode 100644 base/android/scoped_java_ref.h delete mode 100644 base/android/scoped_java_ref_unittest.cc delete mode 100644 build/android/gyp/util/__init__.py delete mode 100644 build/android/gyp/util/build_utils.py delete mode 100644 build/android/gyp/util/md5_check.py delete mode 100644 build/android/pylib/__init__.py delete mode 100644 build/android/pylib/constants/__init__.py delete mode 100644 build/android/pylib/constants/host_paths.py delete mode 100644 build/build_config.h delete mode 100644 build/gn_helpers.py delete mode 100644 gen/mojo/common/common_custom_types__type_mappings delete mode 100644 ipc/ipc.mojom delete mode 100644 ipc/ipc_channel_handle.h delete mode 100644 ipc/ipc_export.h delete mode 100644 ipc/ipc_listener.h delete mode 100644 ipc/ipc_message.cc delete mode 100644 ipc/ipc_message.h delete mode 100644 ipc/ipc_message_attachment.cc delete mode 100644 ipc/ipc_message_attachment.h delete mode 100644 ipc/ipc_message_attachment_set.cc delete mode 100644 ipc/ipc_message_attachment_set.h delete mode 100644 ipc/ipc_message_start.h delete mode 100644 ipc/ipc_message_utils.cc delete mode 100644 ipc/ipc_message_utils.h delete mode 100644 ipc/ipc_mojo_handle_attachment.cc delete mode 100644 ipc/ipc_mojo_handle_attachment.h delete mode 100644 ipc/ipc_mojo_message_helper.cc delete mode 100644 ipc/ipc_mojo_message_helper.h delete mode 100644 ipc/ipc_mojo_param_traits.cc delete mode 100644 ipc/ipc_mojo_param_traits.h delete mode 100644 ipc/ipc_param_traits.h delete mode 100644 ipc/ipc_platform_file_attachment_posix.cc delete mode 100644 ipc/ipc_platform_file_attachment_posix.h delete mode 100644 ipc/ipc_sync_message.h delete mode 100644 libmojo.pc.in delete mode 100644 mojo/BUILD.gn delete mode 100644 mojo/DEPS delete mode 100644 mojo/PRESUBMIT.py delete mode 100644 mojo/README.md delete mode 100644 mojo/android/BUILD.gn delete mode 100644 mojo/android/DEPS delete mode 100644 mojo/android/javatests/AndroidManifest.xml delete mode 100644 mojo/android/javatests/DEPS delete mode 100644 mojo/android/javatests/apk/.empty delete mode 100644 mojo/android/javatests/init_library.cc delete mode 100644 mojo/android/javatests/mojo_test_case.cc delete mode 100644 mojo/android/javatests/mojo_test_case.h delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/HandleMock.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/TestUtils.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsHelperTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsTestUtils.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/CallbacksTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/ConnectorTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/ExecutorFactoryTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/InterfaceControlMessageTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/MessageHeaderTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/ReadAndDispatchMessageTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/SerializationTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtilTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterfaceTestHelper.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/system/impl/CoreImplTest.java delete mode 100644 mojo/android/javatests/src/org/chromium/mojo/system/impl/WatcherImplTest.java delete mode 100644 mojo/android/javatests/validation_test_util.cc delete mode 100644 mojo/android/javatests/validation_test_util.h delete mode 100644 mojo/android/system/base_run_loop.cc delete mode 100644 mojo/android/system/base_run_loop.h delete mode 100644 mojo/android/system/core_impl.cc delete mode 100644 mojo/android/system/core_impl.h delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/HandleBase.java delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java delete mode 100644 mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java delete mode 100644 mojo/android/system/watcher_impl.cc delete mode 100644 mojo/android/system/watcher_impl.h delete mode 100644 mojo/common/BUILD.gn delete mode 100644 mojo/common/DEPS delete mode 100644 mojo/common/common_custom_types_struct_traits.cc delete mode 100644 mojo/common/common_custom_types_struct_traits.h delete mode 100644 mojo/common/common_custom_types_unittest.cc delete mode 100644 mojo/common/data_pipe_drainer.cc delete mode 100644 mojo/common/data_pipe_drainer.h delete mode 100644 mojo/common/data_pipe_utils.cc delete mode 100644 mojo/common/data_pipe_utils.h delete mode 100644 mojo/common/file.mojom delete mode 100644 mojo/common/file.typemap delete mode 100644 mojo/common/file_path.mojom delete mode 100644 mojo/common/file_path.typemap delete mode 100644 mojo/common/mojo_common_export.h delete mode 100644 mojo/common/string16.mojom delete mode 100644 mojo/common/string16.typemap delete mode 100644 mojo/common/struct_traits_unittest.cc delete mode 100644 mojo/common/test_common_custom_types.mojom delete mode 100644 mojo/common/text_direction.mojom delete mode 100644 mojo/common/text_direction.typemap delete mode 100644 mojo/common/time.mojom delete mode 100644 mojo/common/time.typemap delete mode 100644 mojo/common/time_struct_traits.h delete mode 100644 mojo/common/traits_test_service.mojom delete mode 100644 mojo/common/typemaps.gni delete mode 100644 mojo/common/unguessable_token.mojom delete mode 100644 mojo/common/unguessable_token.typemap delete mode 100644 mojo/common/values.mojom delete mode 100644 mojo/common/values.typemap delete mode 100644 mojo/common/values_struct_traits.cc delete mode 100644 mojo/common/values_struct_traits.h delete mode 100644 mojo/common/version.mojom delete mode 100644 mojo/common/version.typemap delete mode 100644 mojo/edk/DEPS delete mode 100644 mojo/edk/embedder/BUILD.gn delete mode 100644 mojo/edk/embedder/README.md delete mode 100644 mojo/edk/embedder/configuration.h delete mode 100644 mojo/edk/embedder/connection_params.cc delete mode 100644 mojo/edk/embedder/connection_params.h delete mode 100644 mojo/edk/embedder/embedder.cc delete mode 100644 mojo/edk/embedder/embedder.h delete mode 100644 mojo/edk/embedder/embedder_internal.h delete mode 100644 mojo/edk/embedder/embedder_unittest.cc delete mode 100644 mojo/edk/embedder/entrypoints.cc delete mode 100644 mojo/edk/embedder/entrypoints.h delete mode 100644 mojo/edk/embedder/named_platform_channel_pair.h delete mode 100644 mojo/edk/embedder/named_platform_channel_pair_win.cc delete mode 100644 mojo/edk/embedder/named_platform_handle.h delete mode 100644 mojo/edk/embedder/named_platform_handle_utils.h delete mode 100644 mojo/edk/embedder/named_platform_handle_utils_posix.cc delete mode 100644 mojo/edk/embedder/named_platform_handle_utils_win.cc delete mode 100644 mojo/edk/embedder/pending_process_connection.cc delete mode 100644 mojo/edk/embedder/pending_process_connection.h delete mode 100644 mojo/edk/embedder/platform_channel_pair.cc delete mode 100644 mojo/edk/embedder/platform_channel_pair.h delete mode 100644 mojo/edk/embedder/platform_channel_pair_posix.cc delete mode 100644 mojo/edk/embedder/platform_channel_pair_posix_unittest.cc delete mode 100644 mojo/edk/embedder/platform_channel_pair_win.cc delete mode 100644 mojo/edk/embedder/platform_channel_utils_posix.cc delete mode 100644 mojo/edk/embedder/platform_channel_utils_posix.h delete mode 100644 mojo/edk/embedder/platform_handle.cc delete mode 100644 mojo/edk/embedder/platform_handle.h delete mode 100644 mojo/edk/embedder/platform_handle_utils.h delete mode 100644 mojo/edk/embedder/platform_handle_utils_posix.cc delete mode 100644 mojo/edk/embedder/platform_handle_utils_win.cc delete mode 100644 mojo/edk/embedder/platform_handle_vector.h delete mode 100644 mojo/edk/embedder/platform_shared_buffer.cc delete mode 100644 mojo/edk/embedder/platform_shared_buffer.h delete mode 100644 mojo/edk/embedder/platform_shared_buffer_unittest.cc delete mode 100644 mojo/edk/embedder/scoped_ipc_support.cc delete mode 100644 mojo/edk/embedder/scoped_ipc_support.h delete mode 100644 mojo/edk/embedder/scoped_platform_handle.h delete mode 100644 mojo/edk/embedder/test_embedder.cc delete mode 100644 mojo/edk/embedder/test_embedder.h delete mode 100644 mojo/edk/js/BUILD.gn delete mode 100644 mojo/edk/js/core.cc delete mode 100644 mojo/edk/js/core.h delete mode 100644 mojo/edk/js/drain_data.cc delete mode 100644 mojo/edk/js/drain_data.h delete mode 100644 mojo/edk/js/handle.cc delete mode 100644 mojo/edk/js/handle.h delete mode 100644 mojo/edk/js/handle_close_observer.h delete mode 100644 mojo/edk/js/handle_unittest.cc delete mode 100644 mojo/edk/js/js_export.h delete mode 100644 mojo/edk/js/mojo_runner_delegate.cc delete mode 100644 mojo/edk/js/mojo_runner_delegate.h delete mode 100644 mojo/edk/js/support.cc delete mode 100644 mojo/edk/js/support.h delete mode 100644 mojo/edk/js/tests/BUILD.gn delete mode 100644 mojo/edk/js/tests/js_to_cpp.mojom delete mode 100644 mojo/edk/js/tests/js_to_cpp_tests.cc delete mode 100644 mojo/edk/js/tests/js_to_cpp_tests.js delete mode 100644 mojo/edk/js/tests/run_js_unittests.cc delete mode 100644 mojo/edk/js/threading.cc delete mode 100644 mojo/edk/js/threading.h delete mode 100644 mojo/edk/js/waiting_callback.cc delete mode 100644 mojo/edk/js/waiting_callback.h delete mode 100644 mojo/edk/system/BUILD.gn delete mode 100644 mojo/edk/system/atomic_flag.h delete mode 100644 mojo/edk/system/broker.h delete mode 100644 mojo/edk/system/broker_host.cc delete mode 100644 mojo/edk/system/broker_host.h delete mode 100644 mojo/edk/system/broker_messages.h delete mode 100644 mojo/edk/system/broker_posix.cc delete mode 100644 mojo/edk/system/broker_win.cc delete mode 100644 mojo/edk/system/channel.cc delete mode 100644 mojo/edk/system/channel.h delete mode 100644 mojo/edk/system/channel_posix.cc delete mode 100644 mojo/edk/system/channel_unittest.cc delete mode 100644 mojo/edk/system/channel_win.cc delete mode 100644 mojo/edk/system/configuration.cc delete mode 100644 mojo/edk/system/configuration.h delete mode 100644 mojo/edk/system/core.cc delete mode 100644 mojo/edk/system/core.h delete mode 100644 mojo/edk/system/core_test_base.cc delete mode 100644 mojo/edk/system/core_test_base.h delete mode 100644 mojo/edk/system/core_unittest.cc delete mode 100644 mojo/edk/system/data_pipe_consumer_dispatcher.cc delete mode 100644 mojo/edk/system/data_pipe_consumer_dispatcher.h delete mode 100644 mojo/edk/system/data_pipe_control_message.cc delete mode 100644 mojo/edk/system/data_pipe_control_message.h delete mode 100644 mojo/edk/system/data_pipe_producer_dispatcher.cc delete mode 100644 mojo/edk/system/data_pipe_producer_dispatcher.h delete mode 100644 mojo/edk/system/data_pipe_unittest.cc delete mode 100644 mojo/edk/system/dispatcher.cc delete mode 100644 mojo/edk/system/dispatcher.h delete mode 100644 mojo/edk/system/handle_signals_state.h delete mode 100644 mojo/edk/system/handle_table.cc delete mode 100644 mojo/edk/system/handle_table.h delete mode 100644 mojo/edk/system/mach_port_relay.cc delete mode 100644 mojo/edk/system/mach_port_relay.h delete mode 100644 mojo/edk/system/mapping_table.cc delete mode 100644 mojo/edk/system/mapping_table.h delete mode 100644 mojo/edk/system/message_for_transit.cc delete mode 100644 mojo/edk/system/message_for_transit.h delete mode 100644 mojo/edk/system/message_pipe_dispatcher.cc delete mode 100644 mojo/edk/system/message_pipe_dispatcher.h delete mode 100644 mojo/edk/system/message_pipe_perftest.cc delete mode 100644 mojo/edk/system/message_pipe_unittest.cc delete mode 100644 mojo/edk/system/multiprocess_message_pipe_unittest.cc delete mode 100644 mojo/edk/system/node_channel.cc delete mode 100644 mojo/edk/system/node_channel.h delete mode 100644 mojo/edk/system/node_controller.cc delete mode 100644 mojo/edk/system/node_controller.h delete mode 100644 mojo/edk/system/options_validation.h delete mode 100644 mojo/edk/system/options_validation_unittest.cc delete mode 100644 mojo/edk/system/platform_handle_dispatcher.cc delete mode 100644 mojo/edk/system/platform_handle_dispatcher.h delete mode 100644 mojo/edk/system/platform_handle_dispatcher_unittest.cc delete mode 100644 mojo/edk/system/platform_wrapper_unittest.cc delete mode 100644 mojo/edk/system/ports/BUILD.gn delete mode 100644 mojo/edk/system/ports/event.cc delete mode 100644 mojo/edk/system/ports/event.h delete mode 100644 mojo/edk/system/ports/message.cc delete mode 100644 mojo/edk/system/ports/message.h delete mode 100644 mojo/edk/system/ports/message_filter.h delete mode 100644 mojo/edk/system/ports/message_queue.cc delete mode 100644 mojo/edk/system/ports/message_queue.h delete mode 100644 mojo/edk/system/ports/name.cc delete mode 100644 mojo/edk/system/ports/name.h delete mode 100644 mojo/edk/system/ports/node.cc delete mode 100644 mojo/edk/system/ports/node.h delete mode 100644 mojo/edk/system/ports/node_delegate.h delete mode 100644 mojo/edk/system/ports/port.cc delete mode 100644 mojo/edk/system/ports/port.h delete mode 100644 mojo/edk/system/ports/port_ref.cc delete mode 100644 mojo/edk/system/ports/port_ref.h delete mode 100644 mojo/edk/system/ports/ports_unittest.cc delete mode 100644 mojo/edk/system/ports/user_data.h delete mode 100644 mojo/edk/system/ports_message.cc delete mode 100644 mojo/edk/system/ports_message.h delete mode 100644 mojo/edk/system/request_context.cc delete mode 100644 mojo/edk/system/request_context.h delete mode 100644 mojo/edk/system/shared_buffer_dispatcher.cc delete mode 100644 mojo/edk/system/shared_buffer_dispatcher.h delete mode 100644 mojo/edk/system/shared_buffer_dispatcher_unittest.cc delete mode 100644 mojo/edk/system/shared_buffer_unittest.cc delete mode 100644 mojo/edk/system/signals_unittest.cc delete mode 100644 mojo/edk/system/system_impl_export.h delete mode 100644 mojo/edk/system/test_utils.cc delete mode 100644 mojo/edk/system/test_utils.h delete mode 100644 mojo/edk/system/watch.cc delete mode 100644 mojo/edk/system/watch.h delete mode 100644 mojo/edk/system/watcher_dispatcher.cc delete mode 100644 mojo/edk/system/watcher_dispatcher.h delete mode 100644 mojo/edk/system/watcher_set.cc delete mode 100644 mojo/edk/system/watcher_set.h delete mode 100644 mojo/edk/system/watcher_unittest.cc delete mode 100644 mojo/edk/test/BUILD.gn delete mode 100644 mojo/edk/test/mojo_test_base.cc delete mode 100644 mojo/edk/test/mojo_test_base.h delete mode 100644 mojo/edk/test/multiprocess_test_helper.cc delete mode 100644 mojo/edk/test/multiprocess_test_helper.h delete mode 100644 mojo/edk/test/multiprocess_test_helper_unittest.cc delete mode 100644 mojo/edk/test/run_all_perftests.cc delete mode 100644 mojo/edk/test/run_all_unittests.cc delete mode 100644 mojo/edk/test/test_support_impl.cc delete mode 100644 mojo/edk/test/test_support_impl.h delete mode 100644 mojo/edk/test/test_utils.h delete mode 100644 mojo/edk/test/test_utils_posix.cc delete mode 100644 mojo/edk/test/test_utils_win.cc delete mode 100644 mojo/public/BUILD.gn delete mode 100644 mojo/public/DEPS delete mode 100644 mojo/public/LICENSE delete mode 100644 mojo/public/c/system/BUILD.gn delete mode 100644 mojo/public/c/system/README.md delete mode 100644 mojo/public/c/system/buffer.h delete mode 100644 mojo/public/c/system/core.h delete mode 100644 mojo/public/c/system/data_pipe.h delete mode 100644 mojo/public/c/system/functions.h delete mode 100644 mojo/public/c/system/macros.h delete mode 100644 mojo/public/c/system/message_pipe.h delete mode 100644 mojo/public/c/system/platform_handle.h delete mode 100644 mojo/public/c/system/set_thunks_for_app.cc delete mode 100644 mojo/public/c/system/system_export.h delete mode 100644 mojo/public/c/system/tests/BUILD.gn delete mode 100644 mojo/public/c/system/tests/core_perftest.cc delete mode 100644 mojo/public/c/system/tests/core_unittest.cc delete mode 100644 mojo/public/c/system/tests/core_unittest_pure_c.c delete mode 100644 mojo/public/c/system/tests/macros_unittest.cc delete mode 100644 mojo/public/c/system/thunks.cc delete mode 100644 mojo/public/c/system/thunks.h delete mode 100644 mojo/public/c/system/types.h delete mode 100644 mojo/public/c/system/watcher.h delete mode 100644 mojo/public/c/test_support/BUILD.gn delete mode 100644 mojo/public/c/test_support/test_support.h delete mode 100644 mojo/public/cpp/bindings/BUILD.gn delete mode 100644 mojo/public/cpp/bindings/DEPS delete mode 100644 mojo/public/cpp/bindings/README.md delete mode 100644 mojo/public/cpp/bindings/array_data_view.h delete mode 100644 mojo/public/cpp/bindings/array_traits.h delete mode 100644 mojo/public/cpp/bindings/array_traits_carray.h delete mode 100644 mojo/public/cpp/bindings/array_traits_stl.h delete mode 100644 mojo/public/cpp/bindings/array_traits_wtf_vector.h delete mode 100644 mojo/public/cpp/bindings/associated_binding.h delete mode 100644 mojo/public/cpp/bindings/associated_binding_set.h delete mode 100644 mojo/public/cpp/bindings/associated_group.h delete mode 100644 mojo/public/cpp/bindings/associated_group_controller.h delete mode 100644 mojo/public/cpp/bindings/associated_interface_ptr.h delete mode 100644 mojo/public/cpp/bindings/associated_interface_ptr_info.h delete mode 100644 mojo/public/cpp/bindings/associated_interface_request.h delete mode 100644 mojo/public/cpp/bindings/binding.h delete mode 100644 mojo/public/cpp/bindings/binding_set.h delete mode 100644 mojo/public/cpp/bindings/bindings_export.h delete mode 100644 mojo/public/cpp/bindings/clone_traits.h delete mode 100644 mojo/public/cpp/bindings/connection_error_callback.h delete mode 100644 mojo/public/cpp/bindings/connector.h delete mode 100644 mojo/public/cpp/bindings/disconnect_reason.h delete mode 100644 mojo/public/cpp/bindings/enum_traits.h delete mode 100644 mojo/public/cpp/bindings/filter_chain.h delete mode 100644 mojo/public/cpp/bindings/interface_data_view.h delete mode 100644 mojo/public/cpp/bindings/interface_endpoint_client.h delete mode 100644 mojo/public/cpp/bindings/interface_endpoint_controller.h delete mode 100644 mojo/public/cpp/bindings/interface_id.h delete mode 100644 mojo/public/cpp/bindings/interface_ptr.h delete mode 100644 mojo/public/cpp/bindings/interface_ptr_info.h delete mode 100644 mojo/public/cpp/bindings/interface_ptr_set.h delete mode 100644 mojo/public/cpp/bindings/interface_request.h delete mode 100644 mojo/public/cpp/bindings/lib/array_internal.cc delete mode 100644 mojo/public/cpp/bindings/lib/array_internal.h delete mode 100644 mojo/public/cpp/bindings/lib/array_serialization.h delete mode 100644 mojo/public/cpp/bindings/lib/associated_binding.cc delete mode 100644 mojo/public/cpp/bindings/lib/associated_group.cc delete mode 100644 mojo/public/cpp/bindings/lib/associated_group_controller.cc delete mode 100644 mojo/public/cpp/bindings/lib/associated_interface_ptr.cc delete mode 100644 mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h delete mode 100644 mojo/public/cpp/bindings/lib/binding_state.cc delete mode 100644 mojo/public/cpp/bindings/lib/binding_state.h delete mode 100644 mojo/public/cpp/bindings/lib/bindings_internal.h delete mode 100644 mojo/public/cpp/bindings/lib/buffer.h delete mode 100644 mojo/public/cpp/bindings/lib/connector.cc delete mode 100644 mojo/public/cpp/bindings/lib/control_message_handler.cc delete mode 100644 mojo/public/cpp/bindings/lib/control_message_handler.h delete mode 100644 mojo/public/cpp/bindings/lib/control_message_proxy.cc delete mode 100644 mojo/public/cpp/bindings/lib/control_message_proxy.h delete mode 100644 mojo/public/cpp/bindings/lib/equals_traits.h delete mode 100644 mojo/public/cpp/bindings/lib/filter_chain.cc delete mode 100644 mojo/public/cpp/bindings/lib/fixed_buffer.cc delete mode 100644 mojo/public/cpp/bindings/lib/fixed_buffer.h delete mode 100644 mojo/public/cpp/bindings/lib/handle_interface_serialization.h delete mode 100644 mojo/public/cpp/bindings/lib/hash_util.h delete mode 100644 mojo/public/cpp/bindings/lib/interface_endpoint_client.cc delete mode 100644 mojo/public/cpp/bindings/lib/interface_ptr_state.h delete mode 100644 mojo/public/cpp/bindings/lib/map_data_internal.h delete mode 100644 mojo/public/cpp/bindings/lib/map_serialization.h delete mode 100644 mojo/public/cpp/bindings/lib/may_auto_lock.h delete mode 100644 mojo/public/cpp/bindings/lib/message.cc delete mode 100644 mojo/public/cpp/bindings/lib/message_buffer.cc delete mode 100644 mojo/public/cpp/bindings/lib/message_buffer.h delete mode 100644 mojo/public/cpp/bindings/lib/message_builder.cc delete mode 100644 mojo/public/cpp/bindings/lib/message_builder.h delete mode 100644 mojo/public/cpp/bindings/lib/message_header_validator.cc delete mode 100644 mojo/public/cpp/bindings/lib/message_internal.h delete mode 100644 mojo/public/cpp/bindings/lib/multiplex_router.cc delete mode 100644 mojo/public/cpp/bindings/lib/multiplex_router.h delete mode 100644 mojo/public/cpp/bindings/lib/native_enum_data.h delete mode 100644 mojo/public/cpp/bindings/lib/native_enum_serialization.h delete mode 100644 mojo/public/cpp/bindings/lib/native_struct.cc delete mode 100644 mojo/public/cpp/bindings/lib/native_struct_data.cc delete mode 100644 mojo/public/cpp/bindings/lib/native_struct_data.h delete mode 100644 mojo/public/cpp/bindings/lib/native_struct_serialization.cc delete mode 100644 mojo/public/cpp/bindings/lib/native_struct_serialization.h delete mode 100644 mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc delete mode 100644 mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc delete mode 100644 mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc delete mode 100644 mojo/public/cpp/bindings/lib/serialization.h delete mode 100644 mojo/public/cpp/bindings/lib/serialization_context.cc delete mode 100644 mojo/public/cpp/bindings/lib/serialization_context.h delete mode 100644 mojo/public/cpp/bindings/lib/serialization_forward.h delete mode 100644 mojo/public/cpp/bindings/lib/serialization_util.h delete mode 100644 mojo/public/cpp/bindings/lib/string_serialization.h delete mode 100644 mojo/public/cpp/bindings/lib/string_traits_string16.cc delete mode 100644 mojo/public/cpp/bindings/lib/string_traits_wtf.cc delete mode 100644 mojo/public/cpp/bindings/lib/sync_call_restrictions.cc delete mode 100644 mojo/public/cpp/bindings/lib/sync_event_watcher.cc delete mode 100644 mojo/public/cpp/bindings/lib/sync_handle_registry.cc delete mode 100644 mojo/public/cpp/bindings/lib/sync_handle_watcher.cc delete mode 100644 mojo/public/cpp/bindings/lib/template_util.h delete mode 100644 mojo/public/cpp/bindings/lib/union_accessor.h delete mode 100644 mojo/public/cpp/bindings/lib/validate_params.h delete mode 100644 mojo/public/cpp/bindings/lib/validation_context.cc delete mode 100644 mojo/public/cpp/bindings/lib/validation_context.h delete mode 100644 mojo/public/cpp/bindings/lib/validation_errors.cc delete mode 100644 mojo/public/cpp/bindings/lib/validation_errors.h delete mode 100644 mojo/public/cpp/bindings/lib/validation_util.cc delete mode 100644 mojo/public/cpp/bindings/lib/validation_util.h delete mode 100644 mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h delete mode 100644 mojo/public/cpp/bindings/lib/wtf_hash_util.h delete mode 100644 mojo/public/cpp/bindings/lib/wtf_serialization.h delete mode 100644 mojo/public/cpp/bindings/map.h delete mode 100644 mojo/public/cpp/bindings/map_data_view.h delete mode 100644 mojo/public/cpp/bindings/map_traits.h delete mode 100644 mojo/public/cpp/bindings/map_traits_stl.h delete mode 100644 mojo/public/cpp/bindings/map_traits_wtf_hash_map.h delete mode 100644 mojo/public/cpp/bindings/message.h delete mode 100644 mojo/public/cpp/bindings/message_header_validator.h delete mode 100644 mojo/public/cpp/bindings/native_enum.h delete mode 100644 mojo/public/cpp/bindings/native_struct.h delete mode 100644 mojo/public/cpp/bindings/native_struct_data_view.h delete mode 100644 mojo/public/cpp/bindings/pipe_control_message_handler.h delete mode 100644 mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h delete mode 100644 mojo/public/cpp/bindings/pipe_control_message_proxy.h delete mode 100644 mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h delete mode 100644 mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h delete mode 100644 mojo/public/cpp/bindings/string_data_view.h delete mode 100644 mojo/public/cpp/bindings/string_traits.h delete mode 100644 mojo/public/cpp/bindings/string_traits_stl.h delete mode 100644 mojo/public/cpp/bindings/string_traits_string16.h delete mode 100644 mojo/public/cpp/bindings/string_traits_string_piece.h delete mode 100644 mojo/public/cpp/bindings/string_traits_wtf.h delete mode 100644 mojo/public/cpp/bindings/strong_associated_binding.h delete mode 100644 mojo/public/cpp/bindings/strong_binding.h delete mode 100644 mojo/public/cpp/bindings/strong_binding_set.h delete mode 100644 mojo/public/cpp/bindings/struct_ptr.h delete mode 100644 mojo/public/cpp/bindings/struct_traits.h delete mode 100644 mojo/public/cpp/bindings/sync_call_restrictions.h delete mode 100644 mojo/public/cpp/bindings/sync_event_watcher.h delete mode 100644 mojo/public/cpp/bindings/sync_handle_registry.h delete mode 100644 mojo/public/cpp/bindings/sync_handle_watcher.h delete mode 100644 mojo/public/cpp/bindings/tests/BUILD.gn delete mode 100644 mojo/public/cpp/bindings/tests/associated_interface_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/bind_task_runner_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/binding_callback_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/binding_set_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/binding_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/bindings_perftest.cc delete mode 100644 mojo/public/cpp/bindings/tests/blink_typemaps.gni delete mode 100644 mojo/public/cpp/bindings/tests/buffer_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/chromium_typemaps.gni delete mode 100644 mojo/public/cpp/bindings/tests/connector_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/constant_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/container_test_util.cc delete mode 100644 mojo/public/cpp/bindings/tests/container_test_util.h delete mode 100644 mojo/public/cpp/bindings/tests/data_view_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/e2e_perftest.cc delete mode 100644 mojo/public/cpp/bindings/tests/equals_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/handle_passing_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/hash_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/map_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/message_queue.cc delete mode 100644 mojo/public/cpp/bindings/tests/message_queue.h delete mode 100644 mojo/public/cpp/bindings/tests/mojo_test_blink_export.h delete mode 100644 mojo/public/cpp/bindings/tests/mojo_test_export.h delete mode 100644 mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/pickle_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/pickled_types_blink.cc delete mode 100644 mojo/public/cpp/bindings/tests/pickled_types_blink.h delete mode 100644 mojo/public/cpp/bindings/tests/pickled_types_chromium.cc delete mode 100644 mojo/public/cpp/bindings/tests/pickled_types_chromium.h delete mode 100644 mojo/public/cpp/bindings/tests/rect_blink.h delete mode 100644 mojo/public/cpp/bindings/tests/rect_blink.typemap delete mode 100644 mojo/public/cpp/bindings/tests/rect_blink_traits.h delete mode 100644 mojo/public/cpp/bindings/tests/rect_chromium.h delete mode 100644 mojo/public/cpp/bindings/tests/rect_chromium.typemap delete mode 100644 mojo/public/cpp/bindings/tests/rect_chromium_traits.h delete mode 100644 mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/request_response_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/router_test_util.cc delete mode 100644 mojo/public/cpp/bindings/tests/router_test_util.h delete mode 100644 mojo/public/cpp/bindings/tests/sample_service_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/shared_rect.h delete mode 100644 mojo/public/cpp/bindings/tests/shared_rect_traits.h delete mode 100644 mojo/public/cpp/bindings/tests/struct_traits_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/struct_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/struct_with_traits.typemap delete mode 100644 mojo/public/cpp/bindings/tests/struct_with_traits_impl.cc delete mode 100644 mojo/public/cpp/bindings/tests/struct_with_traits_impl.h delete mode 100644 mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.cc delete mode 100644 mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h delete mode 100644 mojo/public/cpp/bindings/tests/sync_method_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/test_native_types_blink.typemap delete mode 100644 mojo/public/cpp/bindings/tests/test_native_types_chromium.typemap delete mode 100644 mojo/public/cpp/bindings/tests/type_conversion_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/union_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/validation_context_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/validation_test_input_parser.cc delete mode 100644 mojo/public/cpp/bindings/tests/validation_test_input_parser.h delete mode 100644 mojo/public/cpp/bindings/tests/validation_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/variant_test_util.h delete mode 100644 mojo/public/cpp/bindings/tests/versioning_apptest.cc delete mode 100644 mojo/public/cpp/bindings/tests/versioning_test_service.cc delete mode 100644 mojo/public/cpp/bindings/tests/wtf_hash_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/wtf_map_unittest.cc delete mode 100644 mojo/public/cpp/bindings/tests/wtf_types_unittest.cc delete mode 100644 mojo/public/cpp/bindings/thread_safe_interface_ptr.h delete mode 100644 mojo/public/cpp/bindings/type_converter.h delete mode 100644 mojo/public/cpp/bindings/union_traits.h delete mode 100644 mojo/public/cpp/bindings/unique_ptr_impl_ref_traits.h delete mode 100644 mojo/public/cpp/system/BUILD.gn delete mode 100644 mojo/public/cpp/system/README.md delete mode 100644 mojo/public/cpp/system/buffer.cc delete mode 100644 mojo/public/cpp/system/buffer.h delete mode 100644 mojo/public/cpp/system/core.h delete mode 100644 mojo/public/cpp/system/data_pipe.h delete mode 100644 mojo/public/cpp/system/functions.h delete mode 100644 mojo/public/cpp/system/handle.h delete mode 100644 mojo/public/cpp/system/handle_signals_state.h delete mode 100644 mojo/public/cpp/system/message.cc delete mode 100644 mojo/public/cpp/system/message.h delete mode 100644 mojo/public/cpp/system/message_pipe.h delete mode 100644 mojo/public/cpp/system/platform_handle.cc delete mode 100644 mojo/public/cpp/system/platform_handle.h delete mode 100644 mojo/public/cpp/system/simple_watcher.cc delete mode 100644 mojo/public/cpp/system/simple_watcher.h delete mode 100644 mojo/public/cpp/system/system_export.h delete mode 100644 mojo/public/cpp/system/tests/BUILD.gn delete mode 100644 mojo/public/cpp/system/tests/core_unittest.cc delete mode 100644 mojo/public/cpp/system/tests/handle_signals_state_unittest.cc delete mode 100644 mojo/public/cpp/system/tests/simple_watcher_unittest.cc delete mode 100644 mojo/public/cpp/system/tests/wait_set_unittest.cc delete mode 100644 mojo/public/cpp/system/tests/wait_unittest.cc delete mode 100644 mojo/public/cpp/system/wait.cc delete mode 100644 mojo/public/cpp/system/wait.h delete mode 100644 mojo/public/cpp/system/wait_set.cc delete mode 100644 mojo/public/cpp/system/wait_set.h delete mode 100644 mojo/public/cpp/system/watcher.cc delete mode 100644 mojo/public/cpp/system/watcher.h delete mode 100644 mojo/public/cpp/test_support/BUILD.gn delete mode 100644 mojo/public/cpp/test_support/lib/test_support.cc delete mode 100644 mojo/public/cpp/test_support/lib/test_utils.cc delete mode 100644 mojo/public/cpp/test_support/test_support.h delete mode 100644 mojo/public/cpp/test_support/test_utils.h delete mode 100644 mojo/public/interfaces/BUILD.gn delete mode 100644 mojo/public/interfaces/bindings/BUILD.gn delete mode 100644 mojo/public/interfaces/bindings/interface_control_messages.mojom delete mode 100644 mojo/public/interfaces/bindings/new_bindings/interface_control_messages.mojom delete mode 100644 mojo/public/interfaces/bindings/new_bindings/pipe_control_messages.mojom delete mode 100644 mojo/public/interfaces/bindings/pipe_control_messages.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/BUILD.gn delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_illegal_invalid_interface_id.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_illegal_invalid_interface_id.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_illegal_master_interface_id.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_illegal_master_interface_id.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_interface_id_index_out_of_range.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_interface_id_index_out_of_range.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_unexpected_invalid_associated_interface.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd0_unexpected_invalid_associated_interface.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd1_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd1_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd1_unexpected_invalid_associated_request.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd1_unexpected_invalid_associated_request.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd2_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd2_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd3_collided_interface_id_indices.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd3_collided_interface_id_indices.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd3_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd3_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd3_unexpected_invalid_associated_interface_in_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd3_unexpected_invalid_associated_interface_in_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd3_wrong_interface_id_index_order.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/associated_conformance_mthd3_wrong_interface_id_index_order.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/boundscheck_msghdr_no_such_method.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/boundscheck_msghdr_no_such_method.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_empty.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_empty.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_incomplete_struct.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_incomplete_struct.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_incomplete_struct_header.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_incomplete_struct_header.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flag_combo.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_invalid_flag_combo.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_missing_request_id.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_missing_request_id.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_no_such_method.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_huge.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_huge.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_less_than_min_requirement.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_less_than_min_requirement.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_less_than_struct_header.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_less_than_struct_header.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_version_mismatch_1.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_version_mismatch_1.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_version_mismatch_2.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_version_mismatch_2.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_version_mismatch_3.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_msghdr_num_bytes_version_mismatch_3.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_incomplete_struct.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_incomplete_struct.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_incomplete_struct_header.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_incomplete_struct_header.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_invalid_request_flags2.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_struct_num_bytes_huge.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_struct_num_bytes_huge.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_struct_num_bytes_less_than_min_requirement.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_struct_num_bytes_less_than_min_requirement.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_struct_num_bytes_less_than_struct_header.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd0_struct_num_bytes_less_than_struct_header.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_good_non_unique_keys.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_good_non_unique_keys.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_null_keys.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_null_keys.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_null_values.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_null_values.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_one_null_key.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_one_null_key.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_unequal_array_size.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd10_unequal_array_size.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version0.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version0.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version1.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version1.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version2.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version2.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version3.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version3.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version_newer_than_known_1.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version_newer_than_known_1.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version_newer_than_known_2.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_good_version_newer_than_known_2.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_num_bytes_version_mismatch_1.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_num_bytes_version_mismatch_1.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_num_bytes_version_mismatch_2.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd11_num_bytes_version_mismatch_2.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd12_invalid_request_flags.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd13_good_1.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd13_good_1.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd13_good_2.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd13_good_2.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd14_good_known_enum_values.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd14_good_known_enum_values.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd14_good_uknown_extensible_enum_value.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd14_good_uknown_extensible_enum_value.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd14_uknown_non_extensible_enum_value.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd14_uknown_non_extensible_enum_value.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd15_good_empy_enum_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd15_good_empy_enum_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd15_good_known_enum_array_values.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd15_good_known_enum_array_values.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd15_good_uknown_extensible_enum_array_value.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd15_good_uknown_extensible_enum_array_value.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd15_uknown_non_extensible_enum_array_value.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd15_uknown_non_extensible_enum_array_value.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd16_uknown_non_extensible_enum_map_key.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd16_uknown_non_extensible_enum_map_key.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd16_uknown_non_extensible_enum_map_value.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd16_uknown_non_extensible_enum_map_value.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd17_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd17_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd17_interface_handle_out_of_range_in_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd17_interface_handle_out_of_range_in_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd17_unexpected_invalid_interface_in_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd17_unexpected_invalid_interface_in_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd18_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd18_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd19_exceed_recursion_limit.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd19_exceed_recursion_limit.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd1_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd1_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd1_misaligned_struct.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd1_misaligned_struct.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd1_struct_pointer_overflow.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd1_struct_pointer_overflow.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd1_unexpected_null_struct.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd1_unexpected_null_struct.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd20_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd20_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd21_empty_extensible_enum_accepts_any_value.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd21_empty_extensible_enum_accepts_any_value.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd22_empty_nonextensible_enum_accepts_no_values.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd22_empty_nonextensible_enum_accepts_no_values.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd2_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd2_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd2_multiple_pointers_to_same_struct.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd2_multiple_pointers_to_same_struct.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd2_overlapped_objects.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd2_overlapped_objects.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd2_wrong_layout_order.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd2_wrong_layout_order.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_array_num_bytes_huge.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_array_num_bytes_huge.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_array_num_bytes_less_than_array_header.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_array_num_bytes_less_than_array_header.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_array_num_bytes_less_than_necessary_size.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_array_num_bytes_less_than_necessary_size.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_array_pointer_overflow.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_array_pointer_overflow.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_incomplete_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_incomplete_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_incomplete_array_header.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_incomplete_array_header.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_misaligned_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_misaligned_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_unexpected_null_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd3_unexpected_null_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd4_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd4_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd4_multiple_pointers_to_same_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd4_multiple_pointers_to_same_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd4_overlapped_objects.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd4_overlapped_objects.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd4_wrong_layout_order.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd4_wrong_layout_order.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_handle_out_of_range.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_1.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_multiple_handles_with_same_value_2.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_unexpected_invalid_handle.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_unexpected_invalid_handle.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd5_wrong_handle_order.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd6_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd6_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd6_nested_array_num_bytes_less_than_necessary_size.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd6_nested_array_num_bytes_less_than_necessary_size.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_unexpected_null_fixed_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_unexpected_null_fixed_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_unmatched_array_elements.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_unmatched_array_elements.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_unmatched_array_elements_nested.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd7_unmatched_array_elements_nested.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd8_array_num_bytes_overflow.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd8_array_num_bytes_overflow.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd8_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd8_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd8_unexpected_null_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd8_unexpected_null_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd8_unexpected_null_string.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd8_unexpected_null_string.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd9_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd9_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd9_good_null_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd9_good_null_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd9_unexpected_null_array.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/conformance_mthd9_unexpected_null_array.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_unexpected_array_header.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_intf_resp_mthd0_unexpected_array_header.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_good.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_good.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_unexpected_struct_header.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_intf_rqst_mthd0_unexpected_struct_header.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_msghdr_invalid_flags.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/integration_msghdr_invalid_flags.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/resp_boundscheck_msghdr_no_such_method.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/resp_boundscheck_msghdr_no_such_method.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags1.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_invalid_response_flags2.expected delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.data delete mode 100644 mojo/public/interfaces/bindings/tests/data/validation/resp_conformance_msghdr_no_such_method.expected delete mode 100644 mojo/public/interfaces/bindings/tests/echo.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/echo_import.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/math_calculator.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/no_module.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/ping_service.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/rect.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/regression_tests.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/sample_factory.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/sample_import.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/sample_import2.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/sample_interfaces.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/sample_service.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/scoping.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/struct_with_traits.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_bad_messages.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_constants.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_data_view.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_export.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_export2.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_import.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_native_types.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_structs.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_sync_methods.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_unions.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/test_wtf_types.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/validation_test_associated_interfaces.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/versioning_test_client.mojom delete mode 100644 mojo/public/interfaces/bindings/tests/versioning_test_service.mojom delete mode 100644 mojo/public/java/BUILD.gn delete mode 100644 mojo/public/java/bindings/README.md delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/AssociatedInterfaceNotSupported.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/AssociatedInterfaceRequestNotSupported.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/AutoCloseableRouter.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/BindingsHelper.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Callbacks.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/ConnectionErrorHandler.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Connector.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/DataHeader.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/DelegatingConnectionErrorHandler.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/DeserializationException.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/ExecutorFactory.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/HandleOwner.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/InterfaceControlMessagesHelper.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/InterfaceRequest.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Message.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageHeader.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageReceiver.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageReceiverWithResponder.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Router.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/RouterImpl.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/SerializationException.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/ServiceMessage.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/SideEffectFreeCloseable.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Struct.java delete mode 100644 mojo/public/java/bindings/src/org/chromium/mojo/bindings/Union.java delete mode 100644 mojo/public/java/system/README.md delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/Core.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/DataPipe.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/Flags.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/Handle.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/InvalidHandle.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/MessagePipeHandle.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/MojoException.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/MojoResult.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/Pair.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/ResultAnd.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/RunLoop.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/SharedBufferHandle.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/UntypedHandle.java delete mode 100644 mojo/public/java/system/src/org/chromium/mojo/system/Watcher.java delete mode 100644 mojo/public/js/BUILD.gn delete mode 100644 mojo/public/js/README.md delete mode 100644 mojo/public/js/bindings.js delete mode 100644 mojo/public/js/buffer.js delete mode 100644 mojo/public/js/codec.js delete mode 100644 mojo/public/js/connector.js delete mode 100644 mojo/public/js/constants.cc delete mode 100644 mojo/public/js/constants.h delete mode 100644 mojo/public/js/core.js delete mode 100644 mojo/public/js/interface_types.js delete mode 100644 mojo/public/js/lib/control_message_handler.js delete mode 100644 mojo/public/js/lib/control_message_proxy.js delete mode 100644 mojo/public/js/lib/interface_endpoint_client.js delete mode 100644 mojo/public/js/lib/interface_endpoint_handle.js delete mode 100644 mojo/public/js/lib/pipe_control_message_handler.js delete mode 100644 mojo/public/js/lib/pipe_control_message_proxy.js delete mode 100644 mojo/public/js/new_bindings/base.js delete mode 100644 mojo/public/js/new_bindings/bindings.js delete mode 100644 mojo/public/js/new_bindings/buffer.js delete mode 100644 mojo/public/js/new_bindings/codec.js delete mode 100644 mojo/public/js/new_bindings/connector.js delete mode 100644 mojo/public/js/new_bindings/interface_types.js delete mode 100644 mojo/public/js/new_bindings/lib/control_message_handler.js delete mode 100644 mojo/public/js/new_bindings/lib/control_message_proxy.js delete mode 100644 mojo/public/js/new_bindings/router.js delete mode 100644 mojo/public/js/new_bindings/unicode.js delete mode 100644 mojo/public/js/new_bindings/validator.js delete mode 100644 mojo/public/js/router.js delete mode 100644 mojo/public/js/support.js delete mode 100644 mojo/public/js/tests/core_unittest.js delete mode 100644 mojo/public/js/tests/validation_test_input_parser.js delete mode 100644 mojo/public/js/tests/validation_unittest.js delete mode 100644 mojo/public/js/threading.js delete mode 100644 mojo/public/js/unicode.js delete mode 100644 mojo/public/js/validator.js delete mode 100644 mojo/public/tests/test_support_private.cc delete mode 100644 mojo/public/tests/test_support_private.h delete mode 100644 mojo/public/tools/bindings/BUILD.gn delete mode 100644 mojo/public/tools/bindings/README.md delete mode 100644 mojo/public/tools/bindings/blink_bindings_configuration.gni delete mode 100644 mojo/public/tools/bindings/chromium_bindings_configuration.gni delete mode 100755 mojo/public/tools/bindings/format_typemap_generator_args.py delete mode 100755 mojo/public/tools/bindings/generate_type_mappings.py delete mode 100644 mojo/public/tools/bindings/generators/__init__.py delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/enum_serialization_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/interface_proxy_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/interface_request_validator_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/interface_response_validator_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/interface_stub_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/struct_data_view_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/struct_traits_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/struct_traits_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/union_data_view_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/union_data_view_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/union_traits_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/union_traits_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/validation_macros.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_template_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_template_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/constant_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/constants.java.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/enum.java.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/enum_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/header.java.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/interface.java.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/interface_internal.java.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/struct.java.tmpl delete mode 100644 mojo/public/tools/bindings/generators/java_templates/union.java.tmpl delete mode 100644 mojo/public/tools/bindings/generators/js_templates/enum_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/js_templates/interface_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/js_templates/module.amd.tmpl delete mode 100644 mojo/public/tools/bindings/generators/js_templates/module_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl delete mode 100644 mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl delete mode 100644 mojo/public/tools/bindings/generators/mojom_cpp_generator.py delete mode 100644 mojo/public/tools/bindings/generators/mojom_java_generator.py delete mode 100644 mojo/public/tools/bindings/generators/mojom_js_generator.py delete mode 100644 mojo/public/tools/bindings/mojom.gni delete mode 100755 mojo/public/tools/bindings/mojom_bindings_generator.py delete mode 100644 mojo/public/tools/bindings/mojom_bindings_generator_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/__init__.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/error.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/fileutil.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/__init__.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/constant_resolver.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/generator.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/generator_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/module.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/module_tests.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/pack.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/pack_tests.py delete mode 100755 mojo/public/tools/bindings/pylib/mojom/generate/run_tests.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/template_expander.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/test_support.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/generate/translate.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/parse/__init__.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/parse/ast.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/parse/lexer.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom/parse/parser.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/__init__.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/fileutil_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/generate/__init__.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/generate/data_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/generate/generator_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/generate/module_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/generate/pack_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/parse/__init__.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/parse/ast_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/parse/lexer_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/parse/parser_unittest.py delete mode 100755 mojo/public/tools/bindings/pylib/mojom_tests/parse/run_parser.py delete mode 100755 mojo/public/tools/bindings/pylib/mojom_tests/parse/run_translate.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/parse/translate_unittest.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/support/__init__.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/support/find_files.py delete mode 100644 mojo/public/tools/bindings/pylib/mojom_tests/support/run_bindings_generator.py delete mode 100755 mojo/public/tools/chrome_ipc/generate_mojom.py delete mode 100755 mojo/public/tools/gn/zip.py delete mode 100755 soong/jni_generator_helper.sh delete mode 100755 soong/mojom_source_generator.sh delete mode 100644 third_party/catapult/LICENSE delete mode 100644 third_party/catapult/devil/PRESUBMIT.py delete mode 100644 third_party/catapult/devil/README.md delete mode 100755 third_party/catapult/devil/bin/generate_md_docs delete mode 100755 third_party/catapult/devil/bin/run_py_devicetests delete mode 100755 third_party/catapult/devil/bin/run_py_tests delete mode 100644 third_party/catapult/devil/devil/__init__.py delete mode 100644 third_party/catapult/devil/devil/android/__init__.py delete mode 100644 third_party/catapult/devil/devil/android/apk_helper.py delete mode 100755 third_party/catapult/devil/devil/android/apk_helper_test.py delete mode 100644 third_party/catapult/devil/devil/android/app_ui.py delete mode 100644 third_party/catapult/devil/devil/android/app_ui_test.py delete mode 100644 third_party/catapult/devil/devil/android/battery_utils.py delete mode 100755 third_party/catapult/devil/devil/android/battery_utils_test.py delete mode 100644 third_party/catapult/devil/devil/android/constants/__init__.py delete mode 100644 third_party/catapult/devil/devil/android/constants/chrome.py delete mode 100644 third_party/catapult/devil/devil/android/constants/file_system.py delete mode 100644 third_party/catapult/devil/devil/android/decorators.py delete mode 100644 third_party/catapult/devil/devil/android/decorators_test.py delete mode 100644 third_party/catapult/devil/devil/android/device_blacklist.py delete mode 100644 third_party/catapult/devil/devil/android/device_blacklist_test.py delete mode 100644 third_party/catapult/devil/devil/android/device_errors.py delete mode 100755 third_party/catapult/devil/devil/android/device_errors_test.py delete mode 100644 third_party/catapult/devil/devil/android/device_list.py delete mode 100644 third_party/catapult/devil/devil/android/device_signal.py delete mode 100644 third_party/catapult/devil/devil/android/device_temp_file.py delete mode 100644 third_party/catapult/devil/devil/android/device_test_case.py delete mode 100644 third_party/catapult/devil/devil/android/device_utils.py delete mode 100755 third_party/catapult/devil/devil/android/device_utils_devicetest.py delete mode 100755 third_party/catapult/devil/devil/android/device_utils_test.py delete mode 100644 third_party/catapult/devil/devil/android/fastboot_utils.py delete mode 100755 third_party/catapult/devil/devil/android/fastboot_utils_test.py delete mode 100644 third_party/catapult/devil/devil/android/flag_changer.py delete mode 100644 third_party/catapult/devil/devil/android/flag_changer_devicetest.py delete mode 100755 third_party/catapult/devil/devil/android/flag_changer_test.py delete mode 100644 third_party/catapult/devil/devil/android/forwarder.py delete mode 100644 third_party/catapult/devil/devil/android/install_commands.py delete mode 100644 third_party/catapult/devil/devil/android/logcat_monitor.py delete mode 100755 third_party/catapult/devil/devil/android/logcat_monitor_test.py delete mode 100644 third_party/catapult/devil/devil/android/md5sum.py delete mode 100755 third_party/catapult/devil/devil/android/md5sum_test.py delete mode 100644 third_party/catapult/devil/devil/android/perf/__init__.py delete mode 100644 third_party/catapult/devil/devil/android/perf/cache_control.py delete mode 100644 third_party/catapult/devil/devil/android/perf/perf_control.py delete mode 100644 third_party/catapult/devil/devil/android/perf/perf_control_devicetest.py delete mode 100644 third_party/catapult/devil/devil/android/perf/surface_stats_collector.py delete mode 100644 third_party/catapult/devil/devil/android/perf/thermal_throttle.py delete mode 100644 third_party/catapult/devil/devil/android/ports.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/__init__.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/aapt.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/adb_compatibility_devicetest.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/adb_wrapper.py delete mode 100755 third_party/catapult/devil/devil/android/sdk/adb_wrapper_devicetest.py delete mode 100755 third_party/catapult/devil/devil/android/sdk/adb_wrapper_test.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/build_tools.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/dexdump.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/fastboot.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/gce_adb_wrapper.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/intent.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/keyevent.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/shared_prefs.py delete mode 100755 third_party/catapult/devil/devil/android/sdk/shared_prefs_test.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/split_select.py delete mode 100644 third_party/catapult/devil/devil/android/sdk/test/data/push_directory/push_directory_contents.txt delete mode 100644 third_party/catapult/devil/devil/android/sdk/test/data/push_file.txt delete mode 100644 third_party/catapult/devil/devil/android/sdk/version_codes.py delete mode 100644 third_party/catapult/devil/devil/android/settings.py delete mode 100644 third_party/catapult/devil/devil/android/tools/__init__.py delete mode 100755 third_party/catapult/devil/devil/android/tools/adb_run_shell_cmd.py delete mode 100755 third_party/catapult/devil/devil/android/tools/cpufreq.py delete mode 100755 third_party/catapult/devil/devil/android/tools/device_monitor.py delete mode 100755 third_party/catapult/devil/devil/android/tools/device_monitor_test.py delete mode 100755 third_party/catapult/devil/devil/android/tools/device_recovery.py delete mode 100755 third_party/catapult/devil/devil/android/tools/device_status.py delete mode 100755 third_party/catapult/devil/devil/android/tools/flash_device.py delete mode 100755 third_party/catapult/devil/devil/android/tools/keyboard.py delete mode 100755 third_party/catapult/devil/devil/android/tools/provision_devices.py delete mode 100755 third_party/catapult/devil/devil/android/tools/screenshot.py delete mode 100644 third_party/catapult/devil/devil/android/tools/script_common.py delete mode 100755 third_party/catapult/devil/devil/android/tools/script_common_test.py delete mode 100755 third_party/catapult/devil/devil/android/tools/video_recorder.py delete mode 100755 third_party/catapult/devil/devil/android/tools/wait_for_devices.py delete mode 100644 third_party/catapult/devil/devil/android/valgrind_tools/__init__.py delete mode 100644 third_party/catapult/devil/devil/android/valgrind_tools/base_tool.py delete mode 100644 third_party/catapult/devil/devil/base_error.py delete mode 100644 third_party/catapult/devil/devil/constants/__init__.py delete mode 100644 third_party/catapult/devil/devil/constants/exit_codes.py delete mode 100644 third_party/catapult/devil/devil/devil_dependencies.json delete mode 100644 third_party/catapult/devil/devil/devil_env.py delete mode 100755 third_party/catapult/devil/devil/devil_env_test.py delete mode 100644 third_party/catapult/devil/devil/utils/__init__.py delete mode 100755 third_party/catapult/devil/devil/utils/battor_device_mapping.py delete mode 100644 third_party/catapult/devil/devil/utils/cmd_helper.py delete mode 100755 third_party/catapult/devil/devil/utils/cmd_helper_test.py delete mode 100644 third_party/catapult/devil/devil/utils/file_utils.py delete mode 100755 third_party/catapult/devil/devil/utils/find_usb_devices.py delete mode 100755 third_party/catapult/devil/devil/utils/find_usb_devices_test.py delete mode 100644 third_party/catapult/devil/devil/utils/geometry.py delete mode 100644 third_party/catapult/devil/devil/utils/geometry_test.py delete mode 100644 third_party/catapult/devil/devil/utils/host_utils.py delete mode 100644 third_party/catapult/devil/devil/utils/lazy/__init__.py delete mode 100644 third_party/catapult/devil/devil/utils/lazy/weak_constant.py delete mode 100644 third_party/catapult/devil/devil/utils/lsusb.py delete mode 100755 third_party/catapult/devil/devil/utils/lsusb_test.py delete mode 100755 third_party/catapult/devil/devil/utils/markdown.py delete mode 100755 third_party/catapult/devil/devil/utils/markdown_test.py delete mode 100644 third_party/catapult/devil/devil/utils/mock_calls.py delete mode 100755 third_party/catapult/devil/devil/utils/mock_calls_test.py delete mode 100644 third_party/catapult/devil/devil/utils/parallelizer.py delete mode 100644 third_party/catapult/devil/devil/utils/parallelizer_test.py delete mode 100644 third_party/catapult/devil/devil/utils/reraiser_thread.py delete mode 100644 third_party/catapult/devil/devil/utils/reraiser_thread_unittest.py delete mode 100755 third_party/catapult/devil/devil/utils/reset_usb.py delete mode 100644 third_party/catapult/devil/devil/utils/run_tests_helper.py delete mode 100644 third_party/catapult/devil/devil/utils/signal_handler.py delete mode 100644 third_party/catapult/devil/devil/utils/test/data/test_serial_map.json delete mode 100644 third_party/catapult/devil/devil/utils/timeout_retry.py delete mode 100755 third_party/catapult/devil/devil/utils/timeout_retry_unittest.py delete mode 100755 third_party/catapult/devil/devil/utils/update_mapping.py delete mode 100644 third_party/catapult/devil/devil/utils/usb_hubs.py delete mode 100644 third_party/catapult/devil/devil/utils/watchdog_timer.py delete mode 100644 third_party/catapult/devil/devil/utils/zip_utils.py delete mode 100644 third_party/catapult/devil/docs/adb_wrapper.md delete mode 100644 third_party/catapult/devil/docs/device_blacklist.md delete mode 100644 third_party/catapult/devil/docs/device_utils.md delete mode 100644 third_party/catapult/devil/docs/markdown.md delete mode 100644 third_party/catapult/devil/docs/persistent_device_list.md delete mode 100644 third_party/catapult/devil/pylintrc delete mode 100644 third_party/jinja2/AUTHORS delete mode 100644 third_party/jinja2/Jinja2-2.8.tar.gz.md5 delete mode 100644 third_party/jinja2/Jinja2-2.8.tar.gz.sha512 delete mode 100644 third_party/jinja2/LICENSE delete mode 100644 third_party/jinja2/README.chromium delete mode 100644 third_party/jinja2/__init__.py delete mode 100644 third_party/jinja2/_compat.py delete mode 100644 third_party/jinja2/_stringdefs.py delete mode 100644 third_party/jinja2/bccache.py delete mode 100644 third_party/jinja2/compiler.py delete mode 100644 third_party/jinja2/constants.py delete mode 100644 third_party/jinja2/debug.py delete mode 100644 third_party/jinja2/defaults.py delete mode 100644 third_party/jinja2/environment.py delete mode 100644 third_party/jinja2/exceptions.py delete mode 100644 third_party/jinja2/ext.py delete mode 100644 third_party/jinja2/filters.py delete mode 100755 third_party/jinja2/get_jinja2.sh delete mode 100644 third_party/jinja2/lexer.py delete mode 100644 third_party/jinja2/loaders.py delete mode 100644 third_party/jinja2/meta.py delete mode 100644 third_party/jinja2/nodes.py delete mode 100644 third_party/jinja2/optimizer.py delete mode 100644 third_party/jinja2/parser.py delete mode 100644 third_party/jinja2/runtime.py delete mode 100644 third_party/jinja2/sandbox.py delete mode 100644 third_party/jinja2/tests.py delete mode 100644 third_party/jinja2/utils.py delete mode 100644 third_party/jinja2/visitor.py delete mode 100644 third_party/markupsafe/AUTHORS delete mode 100644 third_party/markupsafe/LICENSE delete mode 100644 third_party/markupsafe/MarkupSafe-0.18.tar.gz.md5 delete mode 100644 third_party/markupsafe/MarkupSafe-0.18.tar.gz.sha512 delete mode 100644 third_party/markupsafe/README.chromium delete mode 100644 third_party/markupsafe/__init__.py delete mode 100644 third_party/markupsafe/_compat.py delete mode 100644 third_party/markupsafe/_constants.py delete mode 100644 third_party/markupsafe/_native.py delete mode 100644 third_party/markupsafe/_speedups.c delete mode 100755 third_party/markupsafe/get_markupsafe.sh delete mode 100644 third_party/ply/LICENSE delete mode 100644 third_party/ply/README delete mode 100644 third_party/ply/README.chromium delete mode 100644 third_party/ply/__init__.py delete mode 100644 third_party/ply/lex.py delete mode 100644 third_party/ply/license.patch delete mode 100644 third_party/ply/yacc.py delete mode 100644 ui/gfx/geometry/mojo/BUILD.gn delete mode 100644 ui/gfx/geometry/mojo/DEPS delete mode 100644 ui/gfx/geometry/mojo/geometry.mojom delete mode 100644 ui/gfx/geometry/mojo/geometry.typemap delete mode 100644 ui/gfx/geometry/mojo/geometry_struct_traits.h delete mode 100644 ui/gfx/geometry/mojo/geometry_struct_traits_unittest.cc delete mode 100644 ui/gfx/geometry/mojo/geometry_traits_test_service.mojom delete mode 100644 ui/gfx/range/mojo/BUILD.gn delete mode 100644 ui/gfx/range/mojo/DEPS delete mode 100644 ui/gfx/range/mojo/range.mojom delete mode 100644 ui/gfx/range/mojo/range.typemap delete mode 100644 ui/gfx/range/mojo/range_struct_traits.h delete mode 100644 ui/gfx/range/mojo/range_struct_traits_unittest.cc delete mode 100644 ui/gfx/range/mojo/range_traits_test_service.mojom diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0d20b64..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.pyc diff --git a/Android.bp b/Android.bp deleted file mode 100644 index 24f235a..0000000 --- a/Android.bp +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright 2017 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -filegroup { - name: "libmojo_mojom_files", - srcs: [ - "ipc/ipc.mojom", - "mojo/common/file.mojom", - "mojo/common/file_path.mojom", - "mojo/common/string16.mojom", - "mojo/common/text_direction.mojom", - "mojo/common/time.mojom", - "mojo/common/unguessable_token.mojom", - "mojo/common/values.mojom", - "mojo/common/version.mojom", - "mojo/public/interfaces/bindings/interface_control_messages.mojom", - "mojo/public/interfaces/bindings/pipe_control_messages.mojom", - "ui/gfx/geometry/mojo/geometry.mojom", - "ui/gfx/range/mojo/range.mojom", - ], -} - -filegroup { - name: "mojo_sources", - srcs: [ - "mojo/**/*.cc", - ], - exclude_srcs: [ - // Unused in Chrome. Looks like mistakenly checked in. - // TODO(hidehiko): Remove this after the file is removed in Chrome - // repository. http://crrev.com/c/644531 - "mojo/public/cpp/system/message.cc", - - // No WTF support. - "mojo/public/cpp/bindings/lib/string_traits_wtf.cc", - - // Exclude windows/mac/ios files. - "**/*_win.cc", - "mojo/edk/system/mach_port_relay.cc", - - // Exclude js binding related files. - "mojo/edk/js/**/*", - "mojo/public/js/**/*", - - // Exclude tests. - // Note that mojo/edk/embedder/test_embedder.cc needs to be included - // for Mojo support. cf) b/62071944. - "**/*_unittest.cc", - "**/*_unittests.cc", - "**/*_perftest.cc", - "mojo/android/javatests/**/*", - "mojo/edk/system/core_test_base.cc", - "mojo/edk/system/test_utils.cc", - "mojo/edk/test/**/*", - "mojo/public/c/system/tests/**/*", - "mojo/public/cpp/bindings/tests/**/*", - "mojo/public/cpp/system/tests/**/*", - "mojo/public/cpp/test_support/**/*", - "mojo/public/tests/**/*", - ], -} - -// Python in Chrome repository requires still Python 2. -python_defaults { - name: "libmojo_scripts", - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, -} - -python_binary_host { - name: "jni_generator", - main: "base/android/jni_generator/jni_generator.py", - srcs: [ - "base/android/jni_generator/jni_generator.py", - "build/**/*.py", - "third_party/catapult/devil/devil/**/*.py", - ], - defaults: ["libmojo_scripts"], -} - -python_binary_host { - name: "mojom_bindings_generator", - main: "mojo/public/tools/bindings/mojom_bindings_generator.py", - srcs: [ - "mojo/public/tools/bindings/**/*.py", - "build/**/*.py", - "third_party/catapult/devil/**/*.py", - "third_party/jinja2/**/*.py", - "third_party/markupsafe/**/*.py", - "third_party/ply/**/*.py", - ], - data: [ - "mojo/public/tools/bindings/generators/cpp_templates/*.tmpl", - "mojo/public/tools/bindings/generators/java_templates/*.tmpl", - "mojo/public/tools/bindings/generators/js_templates/*.tmpl", - ], - defaults: ["libmojo_scripts"], -} - -cc_prebuilt_binary { - name: "mojom_source_generator_sh", - srcs: ["soong/mojom_source_generator.sh"], - host_supported: true, -} - -genrule { - name: "libmojo_mojom_headers", - cmd: "$(location mojom_source_generator_sh)" + - " --mojom_bindings_generator=$(location mojom_bindings_generator)" + - " --package=external/libmojo" + - " --output_dir=$(genDir)" + - " --bytecode_path=$(genDir)" + - " --typemap=$(location gen/mojo/common/common_custom_types__type_mappings)" + - " --generators=c++" + - " --use_new_wrapper_types" + - " $(in)", - - tools: [ - "mojom_bindings_generator", - "mojom_source_generator_sh", - ], - - tool_files: [ - // This file was copied from out/Release in a Chrome checkout. - // TODO(lhchavez): Generate this file instead of hardcoding it. - "gen/mojo/common/common_custom_types__type_mappings", - ], - - srcs: [":libmojo_mojom_files"], - - out: [ - "ipc/ipc.mojom.h", - "ipc/ipc.mojom-shared.h", - "ipc/ipc.mojom-shared-internal.h", - "mojo/common/file.mojom.h", - "mojo/common/file.mojom-shared.h", - "mojo/common/file.mojom-shared-internal.h", - "mojo/common/file_path.mojom.h", - "mojo/common/file_path.mojom-shared.h", - "mojo/common/file_path.mojom-shared-internal.h", - "mojo/common/string16.mojom.h", - "mojo/common/string16.mojom-shared.h", - "mojo/common/string16.mojom-shared-internal.h", - "mojo/common/text_direction.mojom.h", - "mojo/common/text_direction.mojom-shared.h", - "mojo/common/text_direction.mojom-shared-internal.h", - "mojo/common/time.mojom.h", - "mojo/common/time.mojom-shared.h", - "mojo/common/time.mojom-shared-internal.h", - "mojo/common/unguessable_token.mojom.h", - "mojo/common/unguessable_token.mojom-shared.h", - "mojo/common/unguessable_token.mojom-shared-internal.h", - "mojo/common/values.mojom.h", - "mojo/common/values.mojom-shared.h", - "mojo/common/values.mojom-shared-internal.h", - "mojo/common/version.mojom.h", - "mojo/common/version.mojom-shared.h", - "mojo/common/version.mojom-shared-internal.h", - "mojo/public/interfaces/bindings/interface_control_messages.mojom.h", - "mojo/public/interfaces/bindings/interface_control_messages.mojom-shared.h", - "mojo/public/interfaces/bindings/interface_control_messages.mojom-shared-internal.h", - "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h", - "mojo/public/interfaces/bindings/pipe_control_messages.mojom-shared.h", - "mojo/public/interfaces/bindings/pipe_control_messages.mojom-shared-internal.h", - "ui/gfx/geometry/mojo/geometry.mojom.h", - "ui/gfx/geometry/mojo/geometry.mojom-shared.h", - "ui/gfx/geometry/mojo/geometry.mojom-shared-internal.h", - "ui/gfx/range/mojo/range.mojom.h", - "ui/gfx/range/mojo/range.mojom-shared.h", - "ui/gfx/range/mojo/range.mojom-shared-internal.h", - ], -} - -genrule { - name: "libmojo_mojom_srcs", - cmd: "$(location mojom_source_generator_sh)" + - " --mojom_bindings_generator=$(location mojom_bindings_generator)" + - " --package=external/libmojo" + - " --output_dir=$(genDir)" + - " --bytecode_path=$(genDir)" + - " --typemap=$(location gen/mojo/common/common_custom_types__type_mappings)" + - " --generators=c++" + - " --use_new_wrapper_types" + - " $(in)", - - tools: [ - "mojom_bindings_generator", - "mojom_source_generator_sh", - ], - - tool_files: [ - // This file was copied from out/Release in a Chrome checkout. - // TODO(lhchavez): Generate this file instead of hardcoding it. - "gen/mojo/common/common_custom_types__type_mappings", - "soong/mojom_source_generator.sh", - ], - - srcs: [":libmojo_mojom_files"], - - out: [ - "ipc/ipc.mojom.cc", - "ipc/ipc.mojom-shared.cc", - "mojo/common/file.mojom.cc", - "mojo/common/file.mojom-shared.cc", - "mojo/common/string16.mojom.cc", - "mojo/common/string16.mojom-shared.cc", - "mojo/common/text_direction.mojom.cc", - "mojo/common/text_direction.mojom-shared.cc", - "mojo/common/time.mojom.cc", - "mojo/common/time.mojom-shared.cc", - "mojo/common/unguessable_token.mojom.cc", - "mojo/common/unguessable_token.mojom-shared.cc", - "mojo/common/version.mojom.cc", - "mojo/common/version.mojom-shared.cc", - "mojo/public/interfaces/bindings/interface_control_messages.mojom.cc", - "mojo/public/interfaces/bindings/interface_control_messages.mojom-shared.cc", - "mojo/public/interfaces/bindings/pipe_control_messages.mojom.cc", - "mojo/public/interfaces/bindings/pipe_control_messages.mojom-shared.cc", - "ui/gfx/geometry/mojo/geometry.mojom.cc", - "ui/gfx/geometry/mojo/geometry.mojom-shared.cc", - "ui/gfx/range/mojo/range.mojom.cc", - "ui/gfx/range/mojo/range.mojom-shared.cc", - ], -} - -// TODO(hidehiko): Remove JNI for ContextUtils, after cleaning up the -// depended code. -genrule { - name: "libmojo_jni_headers", - cmd: "$(location soong/jni_generator_helper.sh)" + - " --jni_generator=$(location jni_generator)" + - " --output_dir=$(genDir)/jni" + - " --includes=base/android/jni_generator/jni_generator_helper.h" + - " --ptr_type=long" + - " --native_exports_optional" + - " $(in)", - - tools: [ - "jni_generator", - ], - - tool_files: [ - "soong/jni_generator_helper.sh", - ], - - srcs: [ - "base/android/java/src/org/chromium/base/BuildInfo.java", - "base/android/java/src/org/chromium/base/ContextUtils.java", - "mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java", - "mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java", - "mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java", - ], - - out: [ - "jni/BuildInfo_jni.h", - "jni/ContextUtils_jni.h", - "jni/BaseRunLoop_jni.h", - "jni/CoreImpl_jni.h", - "jni/WatcherImpl_jni.h", - ], -} - -cc_library_shared { - name: "libmojo", - - generated_headers: [ - "libmojo_jni_headers", - "libmojo_mojom_headers", - ], - - generated_sources: [ - "libmojo_mojom_srcs", - ], - - export_generated_headers: [ - "libmojo_jni_headers", - "libmojo_mojom_headers", - ], - - srcs: [ - "base/android/build_info.cc", - "base/android/context_utils.cc", - "base/android/jni_android.cc", - "base/android/jni_string.cc", - "base/android/scoped_java_ref.cc", - "ipc/ipc_message.cc", - "ipc/ipc_message_attachment.cc", - "ipc/ipc_message_attachment_set.cc", - "ipc/ipc_message_utils.cc", - "ipc/ipc_mojo_handle_attachment.cc", - "ipc/ipc_mojo_message_helper.cc", - "ipc/ipc_mojo_param_traits.cc", - "ipc/ipc_platform_file_attachment_posix.cc", - ":mojo_sources", - ], - - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - "-Wno-missing-field-initializers", - "-DMOJO_EDK_LEGACY_PROTOCOL", - ], - - // We also pass NO_ASHMEM to make base::SharedMemory avoid using it and prefer - // the POSIX versions. - cppflags: [ - "-Wno-sign-promo", - "-Wno-non-virtual-dtor", - "-Wno-ignored-qualifiers", - "-Wno-extra", - "-DNO_ASHMEM", - ], - - shared_libs: [ - "libevent", - "liblog", - "libchrome", - "libchrome-crypto", - ], - - export_include_dirs: ["."], -} - -genrule { - name: "libmojo_mojom_java_srcs", - cmd: "$(location mojom_source_generator_sh)" + - " --mojom_bindings_generator=$(location mojom_bindings_generator)" + - " --package=external/libmojo" + - " --output_dir=$(genDir)" + - " --bytecode_path=$(genDir)" + - " --typemap=$(location gen/mojo/common/common_custom_types__type_mappings)" + - " --generators=java" + - " --use_new_wrapper_types" + - " $(in)", - - tools: [ - "mojom_bindings_generator", - "mojom_source_generator_sh", - ], - - tool_files: [ - // This file was copied from out/Release in a Chrome checkout. - // TODO(lhchavez): Generate this file instead of hardcoding it. - "gen/mojo/common/common_custom_types__type_mappings", - ], - - srcs: [":libmojo_mojom_files"], - - out: [ - "src/org/chromium/gfx/mojom/InsetsF.java", - "src/org/chromium/gfx/mojom/Insets.java", - "src/org/chromium/gfx/mojom/PointF.java", - "src/org/chromium/gfx/mojom/Point.java", - "src/org/chromium/gfx/mojom/RangeF.java", - "src/org/chromium/gfx/mojom/Range.java", - "src/org/chromium/gfx/mojom/RectF.java", - "src/org/chromium/gfx/mojom/Rect.java", - "src/org/chromium/gfx/mojom/SizeF.java", - "src/org/chromium/gfx/mojom/Size.java", - "src/org/chromium/gfx/mojom/Vector2dF.java", - "src/org/chromium/gfx/mojom/Vector2d.java", - "src/org/chromium/IPC/mojom/ChannelBootstrap_Internal.java", - "src/org/chromium/IPC/mojom/ChannelBootstrap.java", - "src/org/chromium/IPC/mojom/Channel_Internal.java", - "src/org/chromium/IPC/mojom/Channel.java", - "src/org/chromium/IPC/mojom/GenericInterface_Internal.java", - "src/org/chromium/IPC/mojom/GenericInterface.java", - "src/org/chromium/IPC/mojom/IpcConstants.java", - "src/org/chromium/IPC/mojom/SerializedHandle.java", - "src/org/chromium/mojo/bindings/interfacecontrol/FlushForTesting.java", - "src/org/chromium/mojo/bindings/interfacecontrol/InterfaceControlMessagesConstants.java", - "src/org/chromium/mojo/bindings/interfacecontrol/QueryVersion.java", - "src/org/chromium/mojo/bindings/interfacecontrol/QueryVersionResult.java", - "src/org/chromium/mojo/bindings/interfacecontrol/RequireVersion.java", - "src/org/chromium/mojo/bindings/interfacecontrol/RunInput.java", - "src/org/chromium/mojo/bindings/interfacecontrol/RunMessageParams.java", - "src/org/chromium/mojo/bindings/interfacecontrol/RunOrClosePipeInput.java", - "src/org/chromium/mojo/bindings/interfacecontrol/RunOrClosePipeMessageParams.java", - "src/org/chromium/mojo/bindings/interfacecontrol/RunOutput.java", - "src/org/chromium/mojo/bindings/interfacecontrol/RunResponseMessageParams.java", - "src/org/chromium/mojo/bindings/pipecontrol/DisconnectReason.java", - "src/org/chromium/mojo/bindings/pipecontrol/PeerAssociatedEndpointClosedEvent.java", - "src/org/chromium/mojo/bindings/pipecontrol/PipeControlMessagesConstants.java", - "src/org/chromium/mojo/bindings/pipecontrol/RunOrClosePipeInput.java", - "src/org/chromium/mojo/bindings/pipecontrol/RunOrClosePipeMessageParams.java", - "src/org/chromium/mojo/common/mojom/File.java", - "src/org/chromium/mojo/common/mojom/String16.java", - "src/org/chromium/mojo/common/mojom/TextDirection.java", - "src/org/chromium/mojo/common/mojom/TimeDelta.java", - "src/org/chromium/mojo/common/mojom/Time.java", - "src/org/chromium/mojo/common/mojom/TimeTicks.java", - "src/org/chromium/mojo/common/mojom/UnguessableToken.java", - "src/org/chromium/mojo/common/mojom/Version.java", - ], -} - -java_library { - name: "android.mojo", - - srcs: [ - ":libmojo_mojom_java_srcs", - "base/android/java/src/**/*.java", - "mojo/android/system/src/**/*.java", - "mojo/public/java/system/src/**/*.java", - "mojo/public/java/bindings/src/**/*.java", - ], -} diff --git a/CleanSpec.mk b/CleanSpec.mk deleted file mode 100644 index da5b4d1..0000000 --- a/CleanSpec.mk +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (C) 2018 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# If you don't need to do a full clean build but would like to touch -# a file or delete some intermediate files, add a clean step to the end -# of the list. These steps will only be run once, if they haven't been -# run before. -# -# E.g.: -# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) -# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) -# -# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with -# files that are missing or have been moved. -# -# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. -# Use $(OUT_DIR) to refer to the "out" directory. -# -# If you need to re-do something that's already mentioned, just copy -# the command and add it to the bottom of the list. E.g., if a change -# that you made last week required touching a file and a change you -# made today requires touching the same file, just copy the old -# touch step and add it to the end of the list. -# -# ************************************************ -# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST -# ************************************************ - -# For example: -#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) -#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) -#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) -#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) - -$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/generic/system/framework/*_bp.jar) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj_x86/SHARED_LIBRARIES/*_bp_intermediates) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/*_bp_intermediates) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/*_bp.so) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/*_bp.so) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/arm/*_bp.so) - -# ************************************************ -# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST -# ************************************************ diff --git a/README.md b/README.md new file mode 100644 index 0000000..602ddf9 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +This repository was migrated into libchrome. diff --git a/base/android/build_info.cc b/base/android/build_info.cc deleted file mode 100644 index 869c703..0000000 --- a/base/android/build_info.cc +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/build_info.h" - -#include - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/android/scoped_java_ref.h" -#include "base/logging.h" -#include "base/memory/singleton.h" -#include "jni/BuildInfo_jni.h" - -namespace { - -// We are leaking these strings. -const char* StrDupJString(const base::android::JavaRef& java_string) { - std::string str = ConvertJavaStringToUTF8(java_string); - return strdup(str.c_str()); -} - -} // namespace - -namespace base { -namespace android { - -struct BuildInfoSingletonTraits { - static BuildInfo* New() { - return new BuildInfo(AttachCurrentThread()); - } - - static void Delete(BuildInfo* x) { - // We're leaking this type, see kRegisterAtExit. - NOTREACHED(); - } - - static const bool kRegisterAtExit = false; -#if DCHECK_IS_ON() - static const bool kAllowedToAccessOnNonjoinableThread = true; -#endif -}; - -BuildInfo::BuildInfo(JNIEnv* env) - : device_(StrDupJString(Java_BuildInfo_getDevice(env))), - manufacturer_(StrDupJString(Java_BuildInfo_getDeviceManufacturer(env))), - model_(StrDupJString(Java_BuildInfo_getDeviceModel(env))), - brand_(StrDupJString(Java_BuildInfo_getBrand(env))), - android_build_id_(StrDupJString(Java_BuildInfo_getAndroidBuildId(env))), - android_build_fp_( - StrDupJString(Java_BuildInfo_getAndroidBuildFingerprint(env))), - gms_version_code_(StrDupJString(Java_BuildInfo_getGMSVersionCode(env))), - package_version_code_( - StrDupJString(Java_BuildInfo_getPackageVersionCode(env))), - package_version_name_( - StrDupJString(Java_BuildInfo_getPackageVersionName(env))), - package_label_(StrDupJString(Java_BuildInfo_getPackageLabel(env))), - package_name_(StrDupJString(Java_BuildInfo_getPackageName(env))), - build_type_(StrDupJString(Java_BuildInfo_getBuildType(env))), - sdk_int_(Java_BuildInfo_getSdkInt(env)), - java_exception_info_(NULL) {} - -// static -BuildInfo* BuildInfo::GetInstance() { - return Singleton::get(); -} - -void BuildInfo::SetJavaExceptionInfo(const std::string& info) { - DCHECK(!java_exception_info_) << "info should be set only once."; - java_exception_info_ = strndup(info.c_str(), 4096); -} - -void BuildInfo::ClearJavaExceptionInfo() { - delete java_exception_info_; - java_exception_info_ = nullptr; -} - -} // namespace android -} // namespace base diff --git a/base/android/build_info.h b/base/android/build_info.h deleted file mode 100644 index cce74f4..0000000 --- a/base/android/build_info.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2012 The Chromium 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 BASE_ANDROID_BUILD_INFO_H_ -#define BASE_ANDROID_BUILD_INFO_H_ - -#include - -#include - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/memory/singleton.h" - -namespace base { -namespace android { - -// This enumeration maps to the values returned by BuildInfo::sdk_int(), -// indicating the Android release associated with a given SDK version. -enum SdkVersion { - SDK_VERSION_JELLY_BEAN = 16, - SDK_VERSION_JELLY_BEAN_MR1 = 17, - SDK_VERSION_JELLY_BEAN_MR2 = 18, - SDK_VERSION_KITKAT = 19, - SDK_VERSION_KITKAT_WEAR = 20, - SDK_VERSION_LOLLIPOP = 21, - SDK_VERSION_LOLLIPOP_MR1 = 22, - SDK_VERSION_MARSHMALLOW = 23, - SDK_VERSION_NOUGAT = 24 -}; - -// BuildInfo is a singleton class that stores android build and device -// information. It will be called from Android specific code and gets used -// primarily in crash reporting. - -// It is also used to store the last java exception seen during JNI. -// TODO(nileshagrawal): Find a better place to store this info. -class BASE_EXPORT BuildInfo { - public: - - ~BuildInfo() {} - - // Static factory method for getting the singleton BuildInfo instance. - // Note that ownership is not conferred on the caller and the BuildInfo in - // question isn't actually freed until shutdown. This is ok because there - // should only be one instance of BuildInfo ever created. - static BuildInfo* GetInstance(); - - // Const char* is used instead of std::strings because these values must be - // available even if the process is in a crash state. Sadly - // std::string.c_str() doesn't guarantee that memory won't be allocated when - // it is called. - const char* device() const { - return device_; - } - - const char* manufacturer() const { - return manufacturer_; - } - - const char* model() const { - return model_; - } - - const char* brand() const { - return brand_; - } - - const char* android_build_id() const { - return android_build_id_; - } - - const char* android_build_fp() const { - return android_build_fp_; - } - - const char* gms_version_code() const { - return gms_version_code_; - } - - const char* package_version_code() const { - return package_version_code_; - } - - const char* package_version_name() const { - return package_version_name_; - } - - const char* package_label() const { - return package_label_; - } - - const char* package_name() const { - return package_name_; - } - - const char* build_type() const { - return build_type_; - } - - int sdk_int() const { - return sdk_int_; - } - - const char* java_exception_info() const { - return java_exception_info_; - } - - void SetJavaExceptionInfo(const std::string& info); - - void ClearJavaExceptionInfo(); - - private: - friend struct BuildInfoSingletonTraits; - - explicit BuildInfo(JNIEnv* env); - - // Const char* is used instead of std::strings because these values must be - // available even if the process is in a crash state. Sadly - // std::string.c_str() doesn't guarantee that memory won't be allocated when - // it is called. - const char* const device_; - const char* const manufacturer_; - const char* const model_; - const char* const brand_; - const char* const android_build_id_; - const char* const android_build_fp_; - const char* const gms_version_code_; - const char* const package_version_code_; - const char* const package_version_name_; - const char* const package_label_; - const char* const package_name_; - const char* const build_type_; - const int sdk_int_; - // This is set via set_java_exception_info, not at constructor time. - const char* java_exception_info_; - - DISALLOW_COPY_AND_ASSIGN(BuildInfo); -}; - -} // namespace android -} // namespace base - -#endif // BASE_ANDROID_BUILD_INFO_H_ diff --git a/base/android/context_utils.cc b/base/android/context_utils.cc deleted file mode 100644 index e2c4ed0..0000000 --- a/base/android/context_utils.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/context_utils.h" - -#include - -#include "base/android/scoped_java_ref.h" -#include "base/lazy_instance.h" -#include "jni/ContextUtils_jni.h" - -using base::android::JavaRef; - -namespace base { -namespace android { - -namespace { - -// Leak the global app context, as it is used from a non-joinable worker thread -// that may still be running at shutdown. There is no harm in doing this. -base::LazyInstance>::Leaky - g_application_context = LAZY_INSTANCE_INITIALIZER; - -void SetNativeApplicationContext(JNIEnv* env, const JavaRef& context) { - if (env->IsSameObject(g_application_context.Get().obj(), context.obj())) { - // It's safe to set the context more than once if it's the same context. - return; - } - DCHECK(g_application_context.Get().is_null()); - g_application_context.Get().Reset(context); -} - -} // namespace - -const JavaRef& GetApplicationContext() { - DCHECK(!g_application_context.Get().is_null()); - return g_application_context.Get(); -} - -static void InitNativeSideApplicationContext( - JNIEnv* env, - const JavaParamRef& clazz, - const JavaParamRef& context) { - SetNativeApplicationContext(env, context); -} - -bool RegisterContextUtils(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace android -} // namespace base diff --git a/base/android/context_utils.h b/base/android/context_utils.h deleted file mode 100644 index c5289f1..0000000 --- a/base/android/context_utils.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_ANDROID_CONTEXT_UTILS_H_ -#define BASE_ANDROID_CONTEXT_UTILS_H_ - -#include - -#include "base/android/scoped_java_ref.h" -#include "base/base_export.h" - -namespace base { -namespace android { - -// Gets a global ref to the application context set with -// InitApplicationContext(). Ownership is retained by the function - the caller -// must NOT release it. -BASE_EXPORT const JavaRef& GetApplicationContext(); - -bool RegisterContextUtils(JNIEnv* env); - -} // namespace android -} // namespace base - -#endif // BASE_ANDROID_CONTEXT_UTILS_H_ diff --git a/base/android/java/src/org/chromium/base/BuildInfo.java b/base/android/java/src/org/chromium/base/BuildInfo.java deleted file mode 100644 index de4ad08..0000000 --- a/base/android/java/src/org/chromium/base/BuildInfo.java +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2012 The Chromium 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.base; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Build; -import android.os.StrictMode; - -import org.chromium.base.annotations.CalledByNative; - -/** - * BuildInfo is a utility class providing easy access to {@link PackageInfo} information. This is - * primarily of use for accessing package information from native code. - */ -public class BuildInfo { - private static final String TAG = "BuildInfo"; - private static final int MAX_FINGERPRINT_LENGTH = 128; - - /** - * BuildInfo is a static utility class and therefore shouldn't be instantiated. - */ - private BuildInfo() {} - - @CalledByNative - public static String getDevice() { - return Build.DEVICE; - } - - @CalledByNative - public static String getBrand() { - return Build.BRAND; - } - - @CalledByNative - public static String getAndroidBuildId() { - return Build.ID; - } - - /** - * @return The build fingerprint for the current Android install. The value is truncated to a - * 128 characters as this is used for crash and UMA reporting, which should avoid huge - * strings. - */ - @CalledByNative - public static String getAndroidBuildFingerprint() { - return Build.FINGERPRINT.substring( - 0, Math.min(Build.FINGERPRINT.length(), MAX_FINGERPRINT_LENGTH)); - } - - @CalledByNative - public static String getDeviceManufacturer() { - return Build.MANUFACTURER; - } - - @CalledByNative - public static String getDeviceModel() { - return Build.MODEL; - } - - @CalledByNative - public static String getGMSVersionCode() { - String msg = "gms versionCode not available."; - try { - PackageManager packageManager = - ContextUtils.getApplicationContext().getPackageManager(); - PackageInfo packageInfo = packageManager.getPackageInfo("com.google.android.gms", 0); - msg = Integer.toString(packageInfo.versionCode); - } catch (NameNotFoundException e) { - Log.d(TAG, "GMS package is not found.", e); - } - return msg; - } - - @CalledByNative - public static String getPackageVersionCode() { - String msg = "versionCode not available."; - try { - PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); - PackageInfo pi = pm.getPackageInfo(getPackageName(), 0); - msg = ""; - if (pi.versionCode > 0) { - msg = Integer.toString(pi.versionCode); - } - } catch (NameNotFoundException e) { - Log.d(TAG, msg); - } - return msg; - } - - @CalledByNative - public static String getPackageVersionName() { - String msg = "versionName not available"; - try { - PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); - PackageInfo pi = pm.getPackageInfo(getPackageName(), 0); - msg = ""; - if (pi.versionName != null) { - msg = pi.versionName; - } - } catch (NameNotFoundException e) { - Log.d(TAG, msg); - } - return msg; - } - - @CalledByNative - public static String getPackageLabel() { - // Third-party code does disk read on the getApplicationInfo call. http://crbug.com/614343 - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - try { - PackageManager packageManager = - ContextUtils.getApplicationContext().getPackageManager(); - ApplicationInfo appInfo = packageManager.getApplicationInfo( - getPackageName(), PackageManager.GET_META_DATA); - CharSequence label = packageManager.getApplicationLabel(appInfo); - return label != null ? label.toString() : ""; - } catch (NameNotFoundException e) { - return ""; - } finally { - StrictMode.setThreadPolicy(oldPolicy); - } - } - - @CalledByNative - public static String getPackageName() { - if (ContextUtils.getApplicationContext() == null) { - return ""; - } - return ContextUtils.getApplicationContext().getPackageName(); - } - - @CalledByNative - public static String getBuildType() { - return Build.TYPE; - } - - /** - * Check if this is a debuggable build of Android. Use this to enable developer-only features. - */ - public static boolean isDebugAndroid() { - return "eng".equals(Build.TYPE) || "userdebug".equals(Build.TYPE); - } - - @CalledByNative - public static int getSdkInt() { - return Build.VERSION.SDK_INT; - } - - /** - * @return Whether the current device is running Android O release or newer. - */ - public static boolean isAtLeastO() { - return !"REL".equals(Build.VERSION.CODENAME) - && ("O".equals(Build.VERSION.CODENAME) || Build.VERSION.CODENAME.startsWith("OMR")); - } - - /** - * @return Whether the current app targets the SDK for at least O - */ - public static boolean targetsAtLeastO(Context appContext) { - return isAtLeastO() - && appContext.getApplicationInfo().targetSdkVersion - == Build.VERSION_CODES.CUR_DEVELOPMENT; - } -} diff --git a/base/android/java/src/org/chromium/base/ContextUtils.java b/base/android/java/src/org/chromium/base/ContextUtils.java deleted file mode 100644 index 448eff9..0000000 --- a/base/android/java/src/org/chromium/base/ContextUtils.java +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import org.chromium.base.annotations.JNINamespace; -import org.chromium.base.annotations.MainDex; - -/** - * This class provides Android application context related utility methods. - */ -@JNINamespace("base::android") -@MainDex -public class ContextUtils { - private static final String TAG = "ContextUtils"; - private static Context sApplicationContext; - - /** - * Initialization-on-demand holder. This exists for thread-safe lazy initialization. - */ - private static class Holder { - // Not final for tests. - private static SharedPreferences sSharedPreferences = fetchAppSharedPreferences(); - } - - /** - * Get the Android application context. - * - * Under normal circumstances there is only one application context in a process, so it's safe - * to treat this as a global. In WebView it's possible for more than one app using WebView to be - * running in a single process, but this mechanism is rarely used and this is not the only - * problem in that scenario, so we don't currently forbid using it as a global. - * - * Do not downcast the context returned by this method to Application (or any subclass). It may - * not be an Application object; it may be wrapped in a ContextWrapper. The only assumption you - * may make is that it is a Context whose lifetime is the same as the lifetime of the process. - */ - public static Context getApplicationContext() { - return sApplicationContext; - } - - /** - * Initializes the java application context. - * - * This should be called exactly once early on during startup, before native is loaded and - * before any other clients make use of the application context through this class. - * - * @param appContext The application context. - */ - public static void initApplicationContext(Context appContext) { - // Conceding that occasionally in tests, native is loaded before the browser process is - // started, in which case the browser process re-sets the application context. - if (sApplicationContext != null && sApplicationContext != appContext) { - throw new RuntimeException("Attempting to set multiple global application contexts."); - } - initJavaSideApplicationContext(appContext); - } - - /** - * Initialize the native Android application context to be the same as the java counter-part. - */ - public static void initApplicationContextForNative() { - if (sApplicationContext == null) { - throw new RuntimeException("Cannot have native global application context be null."); - } - nativeInitNativeSideApplicationContext(sApplicationContext); - } - - /** - * Only called by the static holder class and tests. - * - * @return The application-wide shared preferences. - */ - private static SharedPreferences fetchAppSharedPreferences() { - return PreferenceManager.getDefaultSharedPreferences(sApplicationContext); - } - - /** - * This is used to ensure that we always use the application context to fetch the default shared - * preferences. This avoids needless I/O for android N and above. It also makes it clear that - * the app-wide shared preference is desired, rather than the potentially context-specific one. - * - * @return application-wide shared preferences. - */ - public static SharedPreferences getAppSharedPreferences() { - return Holder.sSharedPreferences; - } - - /** - * Occasionally tests cannot ensure the application context doesn't change between tests (junit) - * and sometimes specific tests has its own special needs, initApplicationContext should be used - * as much as possible, but this method can be used to override it. - * - * @param appContext The new application context. - */ - @VisibleForTesting - public static void initApplicationContextForTests(Context appContext) { - initJavaSideApplicationContext(appContext); - Holder.sSharedPreferences = fetchAppSharedPreferences(); - } - - private static void initJavaSideApplicationContext(Context appContext) { - if (appContext == null) { - throw new RuntimeException("Global application context cannot be set to null."); - } - sApplicationContext = appContext; - } - - private static native void nativeInitNativeSideApplicationContext(Context appContext); -} diff --git a/base/android/java/src/org/chromium/base/Log.java b/base/android/java/src/org/chromium/base/Log.java deleted file mode 100644 index 399f16d..0000000 --- a/base/android/java/src/org/chromium/base/Log.java +++ /dev/null @@ -1,387 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base; - -import org.chromium.base.annotations.RemovableInRelease; - -import java.util.Locale; - -/** - * Utility class for Logging. - * - *

- * Defines logging access points for each feature. They format and forward the logs to - * {@link android.util.Log}, allowing to standardize the output, to make it easy to identify - * the origin of logs, and enable or disable logging in different parts of the code. - *

- *

- * Usage documentation: {@code //docs/android_logging.md}. - *

- */ -public class Log { - /** Convenience property, same as {@link android.util.Log#ASSERT}. */ - public static final int ASSERT = android.util.Log.ASSERT; - - /** Convenience property, same as {@link android.util.Log#DEBUG}. */ - public static final int DEBUG = android.util.Log.DEBUG; - - /** Convenience property, same as {@link android.util.Log#ERROR}. */ - public static final int ERROR = android.util.Log.ERROR; - - /** Convenience property, same as {@link android.util.Log#INFO}. */ - public static final int INFO = android.util.Log.INFO; - - /** Convenience property, same as {@link android.util.Log#VERBOSE}. */ - public static final int VERBOSE = android.util.Log.VERBOSE; - - /** Convenience property, same as {@link android.util.Log#WARN}. */ - public static final int WARN = android.util.Log.WARN; - - private static final String sTagPrefix = "cr_"; - private static final String sDeprecatedTagPrefix = "cr."; - - private Log() { - // Static only access - } - - /** Returns a formatted log message, using the supplied format and arguments.*/ - private static String formatLog(String messageTemplate, Object... params) { - if (params != null && params.length != 0) { - messageTemplate = String.format(Locale.US, messageTemplate, params); - } - - return messageTemplate; - } - - /** - * Returns a normalized tag that will be in the form: "cr_foo". This function is called by the - * various Log overrides. If using {@link #isLoggable(String, int)}, you might want to call it - * to get the tag that will actually be used. - * @see #sTagPrefix - */ - public static String normalizeTag(String tag) { - if (tag.startsWith(sTagPrefix)) return tag; - - // TODO(dgn) simplify this once 'cr.' is out of the repo (http://crbug.com/533072) - int unprefixedTagStart = 0; - if (tag.startsWith(sDeprecatedTagPrefix)) { - unprefixedTagStart = sDeprecatedTagPrefix.length(); - } - - return sTagPrefix + tag.substring(unprefixedTagStart, tag.length()); - } - - /** - * Returns a formatted log message, using the supplied format and arguments. - * The message will be prepended with the filename and line number of the call. - */ - private static String formatLogWithStack(String messageTemplate, Object... params) { - return "[" + getCallOrigin() + "] " + formatLog(messageTemplate, params); - } - - /** - * Convenience function, forwards to {@link android.util.Log#isLoggable(String, int)}. - * - * Note: Has no effect on whether logs are sent or not. Use a method with - * {@link RemovableInRelease} to log something in Debug builds only. - */ - public static boolean isLoggable(String tag, int level) { - return android.util.Log.isLoggable(tag, level); - } - - /** - * Sends a {@link android.util.Log#VERBOSE} log message. - * - * For optimization purposes, only the fixed parameters versions are visible. If you need more - * than 7 parameters, consider building your log message using a function annotated with - * {@link RemovableInRelease}. - * - * @param tag Used to identify the source of a log message. Might be modified in the output - * (see {@link #normalizeTag(String)}) - * @param messageTemplate The message you would like logged. It is to be specified as a format - * string. - * @param args Arguments referenced by the format specifiers in the format string. If the last - * one is a {@link Throwable}, its trace will be printed. - */ - private static void verbose(String tag, String messageTemplate, Object... args) { - String message = formatLogWithStack(messageTemplate, args); - Throwable tr = getThrowableToLog(args); - if (tr != null) { - android.util.Log.v(normalizeTag(tag), message, tr); - } else { - android.util.Log.v(normalizeTag(tag), message); - } - } - - /** Sends a {@link android.util.Log#VERBOSE} log message. 0 args version. */ - @RemovableInRelease - @VisibleForTesting - public static void v(String tag, String message) { - verbose(tag, message); - } - - /** Sends a {@link android.util.Log#VERBOSE} log message. 1 arg version. */ - @RemovableInRelease - @VisibleForTesting - public static void v(String tag, String messageTemplate, Object arg1) { - verbose(tag, messageTemplate, arg1); - } - - /** Sends a {@link android.util.Log#VERBOSE} log message. 2 args version */ - @RemovableInRelease - @VisibleForTesting - public static void v(String tag, String messageTemplate, Object arg1, Object arg2) { - verbose(tag, messageTemplate, arg1, arg2); - } - - /** Sends a {@link android.util.Log#VERBOSE} log message. 3 args version */ - @RemovableInRelease - @VisibleForTesting - public static void v( - String tag, String messageTemplate, Object arg1, Object arg2, Object arg3) { - verbose(tag, messageTemplate, arg1, arg2, arg3); - } - - /** Sends a {@link android.util.Log#VERBOSE} log message. 4 args version */ - @RemovableInRelease - @VisibleForTesting - public static void v(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, - Object arg4) { - verbose(tag, messageTemplate, arg1, arg2, arg3, arg4); - } - - /** Sends a {@link android.util.Log#VERBOSE} log message. 5 args version */ - @RemovableInRelease - @VisibleForTesting - public static void v(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, - Object arg4, Object arg5) { - verbose(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5); - } - - /** Sends a {@link android.util.Log#VERBOSE} log message. 6 args version */ - @RemovableInRelease - @VisibleForTesting - public static void v(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, - Object arg4, Object arg5, Object arg6) { - verbose(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6); - } - - /** Sends a {@link android.util.Log#VERBOSE} log message. 7 args version */ - @RemovableInRelease - @VisibleForTesting - public static void v(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, - Object arg4, Object arg5, Object arg6, Object arg7) { - verbose(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - - /** - * Sends a {@link android.util.Log#DEBUG} log message. - * - * For optimization purposes, only the fixed parameters versions are visible. If you need more - * than 7 parameters, consider building your log message using a function annotated with - * {@link RemovableInRelease}. - * - * @param tag Used to identify the source of a log message. Might be modified in the output - * (see {@link #normalizeTag(String)}) - * @param messageTemplate The message you would like logged. It is to be specified as a format - * string. - * @param args Arguments referenced by the format specifiers in the format string. If the last - * one is a {@link Throwable}, its trace will be printed. - */ - private static void debug(String tag, String messageTemplate, Object... args) { - String message = formatLogWithStack(messageTemplate, args); - Throwable tr = getThrowableToLog(args); - if (tr != null) { - android.util.Log.d(normalizeTag(tag), message, tr); - } else { - android.util.Log.d(normalizeTag(tag), message); - } - } - - /** Sends a {@link android.util.Log#DEBUG} log message. 0 args version. */ - @RemovableInRelease - @VisibleForTesting - public static void d(String tag, String message) { - debug(tag, message); - } - - /** Sends a {@link android.util.Log#DEBUG} log message. 1 arg version. */ - @RemovableInRelease - @VisibleForTesting - public static void d(String tag, String messageTemplate, Object arg1) { - debug(tag, messageTemplate, arg1); - } - /** Sends a {@link android.util.Log#DEBUG} log message. 2 args version */ - @RemovableInRelease - @VisibleForTesting - public static void d(String tag, String messageTemplate, Object arg1, Object arg2) { - debug(tag, messageTemplate, arg1, arg2); - } - /** Sends a {@link android.util.Log#DEBUG} log message. 3 args version */ - @RemovableInRelease - @VisibleForTesting - public static void d( - String tag, String messageTemplate, Object arg1, Object arg2, Object arg3) { - debug(tag, messageTemplate, arg1, arg2, arg3); - } - - /** Sends a {@link android.util.Log#DEBUG} log message. 4 args version */ - @RemovableInRelease - @VisibleForTesting - public static void d(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, - Object arg4) { - debug(tag, messageTemplate, arg1, arg2, arg3, arg4); - } - - /** Sends a {@link android.util.Log#DEBUG} log message. 5 args version */ - @RemovableInRelease - @VisibleForTesting - public static void d(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, - Object arg4, Object arg5) { - debug(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5); - } - - /** Sends a {@link android.util.Log#DEBUG} log message. 6 args version */ - @RemovableInRelease - @VisibleForTesting - public static void d(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, - Object arg4, Object arg5, Object arg6) { - debug(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6); - } - - /** Sends a {@link android.util.Log#DEBUG} log message. 7 args version */ - @RemovableInRelease - @VisibleForTesting - public static void d(String tag, String messageTemplate, Object arg1, Object arg2, Object arg3, - Object arg4, Object arg5, Object arg6, Object arg7) { - debug(tag, messageTemplate, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - - /** - * Sends an {@link android.util.Log#INFO} log message. - * - * @param tag Used to identify the source of a log message. Might be modified in the output - * (see {@link #normalizeTag(String)}) - * @param messageTemplate The message you would like logged. It is to be specified as a format - * string. - * @param args Arguments referenced by the format specifiers in the format string. If the last - * one is a {@link Throwable}, its trace will be printed. - */ - @VisibleForTesting - public static void i(String tag, String messageTemplate, Object... args) { - String message = formatLog(messageTemplate, args); - Throwable tr = getThrowableToLog(args); - if (tr != null) { - android.util.Log.i(normalizeTag(tag), message, tr); - } else { - android.util.Log.i(normalizeTag(tag), message); - } - } - - /** - * Sends a {@link android.util.Log#WARN} log message. - * - * @param tag Used to identify the source of a log message. Might be modified in the output - * (see {@link #normalizeTag(String)}) - * @param messageTemplate The message you would like logged. It is to be specified as a format - * string. - * @param args Arguments referenced by the format specifiers in the format string. If the last - * one is a {@link Throwable}, its trace will be printed. - */ - @VisibleForTesting - public static void w(String tag, String messageTemplate, Object... args) { - String message = formatLog(messageTemplate, args); - Throwable tr = getThrowableToLog(args); - if (tr != null) { - android.util.Log.w(normalizeTag(tag), message, tr); - } else { - android.util.Log.w(normalizeTag(tag), message); - } - } - - /** - * Sends an {@link android.util.Log#ERROR} log message. - * - * @param tag Used to identify the source of a log message. Might be modified in the output - * (see {@link #normalizeTag(String)}) - * @param messageTemplate The message you would like logged. It is to be specified as a format - * string. - * @param args Arguments referenced by the format specifiers in the format string. If the last - * one is a {@link Throwable}, its trace will be printed. - */ - @VisibleForTesting - public static void e(String tag, String messageTemplate, Object... args) { - String message = formatLog(messageTemplate, args); - Throwable tr = getThrowableToLog(args); - if (tr != null) { - android.util.Log.e(normalizeTag(tag), message, tr); - } else { - android.util.Log.e(normalizeTag(tag), message); - } - } - - /** - * What a Terrible Failure: Used for conditions that should never happen, and logged at - * the {@link android.util.Log#ASSERT} level. Depending on the configuration, it might - * terminate the process. - * - * @see android.util.Log#wtf(String, String, Throwable) - * - * @param tag Used to identify the source of a log message. Might be modified in the output - * (see {@link #normalizeTag(String)}) - * @param messageTemplate The message you would like logged. It is to be specified as a format - * string. - * @param args Arguments referenced by the format specifiers in the format string. If the last - * one is a {@link Throwable}, its trace will be printed. - */ - @VisibleForTesting - public static void wtf(String tag, String messageTemplate, Object... args) { - String message = formatLog(messageTemplate, args); - Throwable tr = getThrowableToLog(args); - if (tr != null) { - android.util.Log.wtf(normalizeTag(tag), message, tr); - } else { - android.util.Log.wtf(normalizeTag(tag), message); - } - } - - /** Handy function to get a loggable stack trace from a Throwable. */ - public static String getStackTraceString(Throwable tr) { - return android.util.Log.getStackTraceString(tr); - } - - private static Throwable getThrowableToLog(Object[] args) { - if (args == null || args.length == 0) return null; - - Object lastArg = args[args.length - 1]; - - if (!(lastArg instanceof Throwable)) return null; - return (Throwable) lastArg; - } - - /** Returns a string form of the origin of the log call, to be used as secondary tag.*/ - private static String getCallOrigin() { - StackTraceElement[] st = Thread.currentThread().getStackTrace(); - - // The call stack should look like: - // n [a variable number of calls depending on the vm used] - // +0 getCallOrigin() - // +1 privateLogFunction: verbose or debug - // +2 formatLogWithStack() - // +3 logFunction: v or d - // +4 caller - - int callerStackIndex; - String logClassName = Log.class.getName(); - for (callerStackIndex = 0; callerStackIndex < st.length; callerStackIndex++) { - if (st[callerStackIndex].getClassName().equals(logClassName)) { - callerStackIndex += 4; - break; - } - } - - return st[callerStackIndex].getFileName() + ":" + st[callerStackIndex].getLineNumber(); - } -} diff --git a/base/android/java/src/org/chromium/base/PackageUtils.java b/base/android/java/src/org/chromium/base/PackageUtils.java deleted file mode 100644 index ab554cd..0000000 --- a/base/android/java/src/org/chromium/base/PackageUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; - -/** - * This class provides package checking related methods. - */ -public class PackageUtils { - /** - * Retrieves the version of the given package installed on the device. - * - * @param context Any context. - * @param packageName Name of the package to find. - * @return The package's version code if found, -1 otherwise. - */ - public static int getPackageVersion(Context context, String packageName) { - int versionCode = -1; - PackageManager pm = context.getPackageManager(); - try { - PackageInfo packageInfo = pm.getPackageInfo(packageName, 0); - if (packageInfo != null) versionCode = packageInfo.versionCode; - } catch (PackageManager.NameNotFoundException e) { - // Do nothing, versionCode stays -1 - } - return versionCode; - } - - private PackageUtils() { - // Hide constructor - } -} diff --git a/base/android/java/src/org/chromium/base/VisibleForTesting.java b/base/android/java/src/org/chromium/base/VisibleForTesting.java deleted file mode 100644 index 24cbfad..0000000 --- a/base/android/java/src/org/chromium/base/VisibleForTesting.java +++ /dev/null @@ -1,12 +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.base; - -/** - * Annotation used to mark code that has wider visibility or present for testing code. - */ -public @interface VisibleForTesting { - -} diff --git a/base/android/java/src/org/chromium/base/annotations/AccessedByNative.java b/base/android/java/src/org/chromium/base/annotations/AccessedByNative.java deleted file mode 100644 index 6df7c11..0000000 --- a/base/android/java/src/org/chromium/base/annotations/AccessedByNative.java +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Chromium 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.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @AccessedByNative is used to ensure proguard will keep this field, since it's - * only accessed by native. - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.CLASS) -public @interface AccessedByNative { - public String value() default ""; -} diff --git a/base/android/java/src/org/chromium/base/annotations/CalledByNative.java b/base/android/java/src/org/chromium/base/annotations/CalledByNative.java deleted file mode 100644 index 94ef3fa..0000000 --- a/base/android/java/src/org/chromium/base/annotations/CalledByNative.java +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 The Chromium 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.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @CalledByNative is used by the JNI generator to create the necessary JNI - * bindings and expose this method to native code. - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.CLASS) -public @interface CalledByNative { - /* - * If present, tells which inner class the method belongs to. - */ - public String value() default ""; -} diff --git a/base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java b/base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java deleted file mode 100644 index c0abcbe..0000000 --- a/base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2012 The Chromium 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.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @CalledByNativeUnchecked is used to generate JNI bindings that do not check for exceptions. - * It only makes sense to use this annotation on methods that declare a throws... spec. - * However, note that the exception received native side maybe an 'unchecked' (RuntimeExpception) - * such as NullPointerException, so the native code should differentiate these cases. - * Usage of this should be very rare; where possible handle exceptions in the Java side and use a - * return value to indicate success / failure. - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.CLASS) -public @interface CalledByNativeUnchecked { - /* - * If present, tells which inner class the method belongs to. - */ - public String value() default ""; -} diff --git a/base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java b/base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java deleted file mode 100644 index f1bf85e..0000000 --- a/base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * JNIAdditionalImport is used by the JNI generator to qualify inner types used on JNI methods. Must - * be used when an inner class is used from a class within the same package. Example: - * - *
- * @JNIAdditionImport(Foo.class)
- * public class Bar {
- *     @CalledByNative static void doSomethingWithInner(Foo.Inner inner) {
- *     ...
- *     }
- * }
- * 
- * 

- * Notes: - * 1) Foo must be in the same package as Bar - * 2) For classes in different packages, they should be imported as: - * import other.package.Foo; - * and this annotation should not be used. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) -public @interface JNIAdditionalImport { - Class[] value(); -} diff --git a/base/android/java/src/org/chromium/base/annotations/JNINamespace.java b/base/android/java/src/org/chromium/base/annotations/JNINamespace.java deleted file mode 100644 index 4cd5531..0000000 --- a/base/android/java/src/org/chromium/base/annotations/JNINamespace.java +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2012 The Chromium 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.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @JNINamespace is used by the JNI generator to create the necessary JNI - * bindings and expose this method to native code using the specified namespace. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface JNINamespace { - public String value(); -} diff --git a/base/android/java/src/org/chromium/base/annotations/MainDex.java b/base/android/java/src/org/chromium/base/annotations/MainDex.java deleted file mode 100644 index 0b35ade..0000000 --- a/base/android/java/src/org/chromium/base/annotations/MainDex.java +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * An annotation that signals that a class should be kept in the main dex file. - * - * This generally means it's used by renderer processes, which can't load secondary dexes - * on K and below. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) -public @interface MainDex { -} diff --git a/base/android/java/src/org/chromium/base/annotations/NativeCall.java b/base/android/java/src/org/chromium/base/annotations/NativeCall.java deleted file mode 100644 index b69cd17..0000000 --- a/base/android/java/src/org/chromium/base/annotations/NativeCall.java +++ /dev/null @@ -1,24 +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.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @NativeCall is used by the JNI generator to create the necessary JNI bindings - * so a native function can be bound to a Java inner class. The native class for - * which the JNI method will be generated is specified by the first parameter. - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.CLASS) -public @interface NativeCall { - /* - * Value determines which native class the method should map to. - */ - public String value() default ""; -} diff --git a/base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java b/base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java deleted file mode 100644 index afbc368..0000000 --- a/base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Chromium 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.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @NativeClassQualifiedName is used by the JNI generator to create the necessary JNI - * bindings to call into the specified native class name. - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface NativeClassQualifiedName { - /* - * Tells which native class the method is going to be bound to. - * The first parameter of the annotated method must be an int nativePtr pointing to - * an instance of this class. - */ - public String value(); -} diff --git a/base/android/java/src/org/chromium/base/annotations/RemovableInRelease.java b/base/android/java/src/org/chromium/base/annotations/RemovableInRelease.java deleted file mode 100644 index 2191334..0000000 --- a/base/android/java/src/org/chromium/base/annotations/RemovableInRelease.java +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - -/** - * The annotated function can be removed in release builds. - * - * Calls to this function will be removed if its return value is not used. If all calls are removed, - * the function definition itself will be candidate for removal. - * It works by indicating to Proguard that the function has no side effects. - */ -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface RemovableInRelease {} diff --git a/base/android/java/src/org/chromium/base/annotations/SuppressFBWarnings.java b/base/android/java/src/org/chromium/base/annotations/SuppressFBWarnings.java deleted file mode 100644 index 89068ac..0000000 --- a/base/android/java/src/org/chromium/base/annotations/SuppressFBWarnings.java +++ /dev/null @@ -1,20 +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.base.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * @SuppressFBWarnings is used to suppress FindBugs warnings. - * - * The long name of FindBugs warnings can be found at - * http://findbugs.sourceforge.net/bugDescriptions.html - */ -@Retention(RetentionPolicy.CLASS) -public @interface SuppressFBWarnings { - String[] value() default {}; - String justification() default ""; -} diff --git a/base/android/java/src/org/chromium/base/annotations/UsedByReflection.java b/base/android/java/src/org/chromium/base/annotations/UsedByReflection.java deleted file mode 100644 index a2af704..0000000 --- a/base/android/java/src/org/chromium/base/annotations/UsedByReflection.java +++ /dev/null @@ -1,24 +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.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; - -/** - * Annotation used for marking methods and fields that are called by reflection. - * Useful for keeping components that would otherwise be removed by Proguard. - * Use the value parameter to mention a file that calls this method. - * - * Note that adding this annotation to a method is not enough to guarantee that - * it is kept - either its class must be referenced elsewhere in the program, or - * the class must be annotated with this as well. - */ -@Target({ - ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, - ElementType.CONSTRUCTOR }) -public @interface UsedByReflection { - String value(); -} diff --git a/base/android/java_runtime.cc b/base/android/java_runtime.cc deleted file mode 100644 index 5fae49a..0000000 --- a/base/android/java_runtime.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/java_runtime.h" - -#include "jni/Runtime_jni.h" - -namespace base { -namespace android { - -void JavaRuntime::GetMemoryUsage(long* total_memory, long* free_memory) { - JNIEnv* env = base::android::AttachCurrentThread(); - base::android::ScopedJavaLocalRef runtime = - JNI_Runtime::Java_Runtime_getRuntime(env); - *total_memory = JNI_Runtime::Java_Runtime_totalMemory(env, runtime); - *free_memory = JNI_Runtime::Java_Runtime_freeMemory(env, runtime); -} - -} // namespace android -} // namespace base diff --git a/base/android/java_runtime.h b/base/android/java_runtime.h deleted file mode 100644 index 2034fb9..0000000 --- a/base/android/java_runtime.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_ANDROID_JAVA_RUNTIME_H_ -#define BASE_ANDROID_JAVA_RUNTIME_H_ - -#include "base/android/scoped_java_ref.h" -#include "base/base_export.h" - -namespace base { -namespace android { - -// Wrapper class for using the java.lang.Runtime object from jni. -class BASE_EXPORT JavaRuntime { - public: - // Fills the total memory used and memory allocated for objects by the java - // heap in the current process. Returns true on success. - static void GetMemoryUsage(long* total_memory, long* free_memory); -}; - -} // namespace android -} // namespace base - -#endif // BASE_ANDROID_JAVA_RUNTIME_H_ diff --git a/base/android/jni_android.cc b/base/android/jni_android.cc deleted file mode 100644 index 2b5869f..0000000 --- a/base/android/jni_android.cc +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/jni_android.h" - -#include - -#include - -#include "base/android/build_info.h" -#include "base/android/jni_string.h" -// Removed unused headers. TODO(hidehiko): Upstream. -// #include "base/android/jni_utils.h" -#include "base/debug/debugging_flags.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/threading/thread_local.h" - -namespace { -using base::android::GetClass; -using base::android::MethodID; -using base::android::ScopedJavaLocalRef; - -base::android::JniRegistrationType g_jni_registration_type = - base::android::ALL_JNI_REGISTRATION; - -JavaVM* g_jvm = NULL; -base::LazyInstance>::Leaky - g_class_loader = LAZY_INSTANCE_INITIALIZER; -jmethodID g_class_loader_load_class_method_id = 0; - -#if BUILDFLAG(ENABLE_PROFILING) && HAVE_TRACE_STACK_FRAME_POINTERS -base::LazyInstance>::Leaky - g_stack_frame_pointer = LAZY_INSTANCE_INITIALIZER; -#endif - -} // namespace - -namespace base { -namespace android { - -JniRegistrationType GetJniRegistrationType() { - return g_jni_registration_type; -} - -void SetJniRegistrationType(JniRegistrationType jni_registration_type) { - g_jni_registration_type = jni_registration_type; -} - -JNIEnv* AttachCurrentThread() { - DCHECK(g_jvm); - JNIEnv* env = NULL; - jint ret = g_jvm->AttachCurrentThread(&env, NULL); - DCHECK_EQ(JNI_OK, ret); - return env; -} - -JNIEnv* AttachCurrentThreadWithName(const std::string& thread_name) { - DCHECK(g_jvm); - JavaVMAttachArgs args; - args.version = JNI_VERSION_1_2; - args.name = thread_name.c_str(); - args.group = NULL; - JNIEnv* env = NULL; - jint ret = g_jvm->AttachCurrentThread(&env, &args); - DCHECK_EQ(JNI_OK, ret); - return env; -} - -void DetachFromVM() { - // Ignore the return value, if the thread is not attached, DetachCurrentThread - // will fail. But it is ok as the native thread may never be attached. - if (g_jvm) - g_jvm->DetachCurrentThread(); -} - -void InitVM(JavaVM* vm) { - DCHECK(!g_jvm || g_jvm == vm); - g_jvm = vm; -} - -bool IsVMInitialized() { - return g_jvm != NULL; -} - -void InitReplacementClassLoader(JNIEnv* env, - const JavaRef& class_loader) { - DCHECK(g_class_loader.Get().is_null()); - DCHECK(!class_loader.is_null()); - - ScopedJavaLocalRef class_loader_clazz = - GetClass(env, "java/lang/ClassLoader"); - CHECK(!ClearException(env)); - g_class_loader_load_class_method_id = - env->GetMethodID(class_loader_clazz.obj(), - "loadClass", - "(Ljava/lang/String;)Ljava/lang/Class;"); - CHECK(!ClearException(env)); - - DCHECK(env->IsInstanceOf(class_loader.obj(), class_loader_clazz.obj())); - g_class_loader.Get().Reset(class_loader); -} - -ScopedJavaLocalRef GetClass(JNIEnv* env, const char* class_name) { - jclass clazz; - if (!g_class_loader.Get().is_null()) { - // ClassLoader.loadClass expects a classname with components separated by - // dots instead of the slashes that JNIEnv::FindClass expects. The JNI - // generator generates names with slashes, so we have to replace them here. - // TODO(torne): move to an approach where we always use ClassLoader except - // for the special case of base::android::GetClassLoader(), and change the - // JNI generator to generate dot-separated names. http://crbug.com/461773 - size_t bufsize = strlen(class_name) + 1; - char dotted_name[bufsize]; - memmove(dotted_name, class_name, bufsize); - for (size_t i = 0; i < bufsize; ++i) { - if (dotted_name[i] == '/') { - dotted_name[i] = '.'; - } - } - - clazz = static_cast( - env->CallObjectMethod(g_class_loader.Get().obj(), - g_class_loader_load_class_method_id, - ConvertUTF8ToJavaString(env, dotted_name).obj())); - } else { - clazz = env->FindClass(class_name); - } - if (ClearException(env) || !clazz) { - LOG(FATAL) << "Failed to find class " << class_name; - } - return ScopedJavaLocalRef(env, clazz); -} - -jclass LazyGetClass( - JNIEnv* env, - const char* class_name, - base::subtle::AtomicWord* atomic_class_id) { - static_assert(sizeof(subtle::AtomicWord) >= sizeof(jclass), - "AtomicWord can't be smaller than jclass"); - subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_class_id); - if (value) - return reinterpret_cast(value); - ScopedJavaGlobalRef clazz; - clazz.Reset(GetClass(env, class_name)); - subtle::AtomicWord null_aw = reinterpret_cast(NULL); - subtle::AtomicWord cas_result = base::subtle::Release_CompareAndSwap( - atomic_class_id, - null_aw, - reinterpret_cast(clazz.obj())); - if (cas_result == null_aw) { - // We intentionally leak the global ref since we now storing it as a raw - // pointer in |atomic_class_id|. - return clazz.Release(); - } else { - return reinterpret_cast(cas_result); - } -} - -template -jmethodID MethodID::Get(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature) { - jmethodID id = type == TYPE_STATIC ? - env->GetStaticMethodID(clazz, method_name, jni_signature) : - env->GetMethodID(clazz, method_name, jni_signature); - if (base::android::ClearException(env) || !id) { - LOG(FATAL) << "Failed to find " << - (type == TYPE_STATIC ? "static " : "") << - "method " << method_name << " " << jni_signature; - } - return id; -} - -// If |atomic_method_id| set, it'll return immediately. Otherwise, it'll call -// into ::Get() above. If there's a race, it's ok since the values are the same -// (and the duplicated effort will happen only once). -template -jmethodID MethodID::LazyGet(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature, - base::subtle::AtomicWord* atomic_method_id) { - static_assert(sizeof(subtle::AtomicWord) >= sizeof(jmethodID), - "AtomicWord can't be smaller than jMethodID"); - subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_method_id); - if (value) - return reinterpret_cast(value); - jmethodID id = MethodID::Get(env, clazz, method_name, jni_signature); - base::subtle::Release_Store( - atomic_method_id, reinterpret_cast(id)); - return id; -} - -// Various template instantiations. -template jmethodID MethodID::Get( - JNIEnv* env, jclass clazz, const char* method_name, - const char* jni_signature); - -template jmethodID MethodID::Get( - JNIEnv* env, jclass clazz, const char* method_name, - const char* jni_signature); - -template jmethodID MethodID::LazyGet( - JNIEnv* env, jclass clazz, const char* method_name, - const char* jni_signature, base::subtle::AtomicWord* atomic_method_id); - -template jmethodID MethodID::LazyGet( - JNIEnv* env, jclass clazz, const char* method_name, - const char* jni_signature, base::subtle::AtomicWord* atomic_method_id); - -bool HasException(JNIEnv* env) { - return env->ExceptionCheck() != JNI_FALSE; -} - -bool ClearException(JNIEnv* env) { - if (!HasException(env)) - return false; - env->ExceptionDescribe(); - env->ExceptionClear(); - return true; -} - -void CheckException(JNIEnv* env) { - if (!HasException(env)) - return; - - // Exception has been found, might as well tell breakpad about it. - jthrowable java_throwable = env->ExceptionOccurred(); - if (java_throwable) { - // Clear the pending exception, since a local reference is now held. - env->ExceptionDescribe(); - env->ExceptionClear(); - - // Set the exception_string in BuildInfo so that breakpad can read it. - // RVO should avoid any extra copies of the exception string. - base::android::BuildInfo::GetInstance()->SetJavaExceptionInfo( - GetJavaExceptionInfo(env, java_throwable)); - } - - // Now, feel good about it and die. - // TODO(lhchavez): Remove this hack. See b/28814913 for details. - // We're using BuildInfo's java_exception_info() instead of storing the - // exception info a few lines above to avoid extra copies. It will be - // truncated to 1024 bytes anyways. - const char* exception_string = - base::android::BuildInfo::GetInstance()->java_exception_info(); - if (exception_string) - LOG(FATAL) << exception_string; - else - LOG(FATAL) << "Unhandled exception"; -} - -std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) { - ScopedJavaLocalRef throwable_clazz = - GetClass(env, "java/lang/Throwable"); - jmethodID throwable_printstacktrace = - MethodID::Get( - env, throwable_clazz.obj(), "printStackTrace", - "(Ljava/io/PrintStream;)V"); - - // Create an instance of ByteArrayOutputStream. - ScopedJavaLocalRef bytearray_output_stream_clazz = - GetClass(env, "java/io/ByteArrayOutputStream"); - jmethodID bytearray_output_stream_constructor = - MethodID::Get( - env, bytearray_output_stream_clazz.obj(), "", "()V"); - jmethodID bytearray_output_stream_tostring = - MethodID::Get( - env, bytearray_output_stream_clazz.obj(), "toString", - "()Ljava/lang/String;"); - ScopedJavaLocalRef bytearray_output_stream(env, - env->NewObject(bytearray_output_stream_clazz.obj(), - bytearray_output_stream_constructor)); - - // Create an instance of PrintStream. - ScopedJavaLocalRef printstream_clazz = - GetClass(env, "java/io/PrintStream"); - jmethodID printstream_constructor = - MethodID::Get( - env, printstream_clazz.obj(), "", - "(Ljava/io/OutputStream;)V"); - ScopedJavaLocalRef printstream(env, - env->NewObject(printstream_clazz.obj(), printstream_constructor, - bytearray_output_stream.obj())); - - // Call Throwable.printStackTrace(PrintStream) - env->CallVoidMethod(java_throwable, throwable_printstacktrace, - printstream.obj()); - - // Call ByteArrayOutputStream.toString() - ScopedJavaLocalRef exception_string( - env, static_cast( - env->CallObjectMethod(bytearray_output_stream.obj(), - bytearray_output_stream_tostring))); - - return ConvertJavaStringToUTF8(exception_string); -} - -#if BUILDFLAG(ENABLE_PROFILING) && HAVE_TRACE_STACK_FRAME_POINTERS - -JNIStackFrameSaver::JNIStackFrameSaver(void* current_fp) { - previous_fp_ = g_stack_frame_pointer.Pointer()->Get(); - g_stack_frame_pointer.Pointer()->Set(current_fp); -} - -JNIStackFrameSaver::~JNIStackFrameSaver() { - g_stack_frame_pointer.Pointer()->Set(previous_fp_); -} - -void* JNIStackFrameSaver::SavedFrame() { - return g_stack_frame_pointer.Pointer()->Get(); -} - -#endif // ENABLE_PROFILING && HAVE_TRACE_STACK_FRAME_POINTERS - -} // namespace android -} // namespace base diff --git a/base/android/jni_android.h b/base/android/jni_android.h deleted file mode 100644 index de53c10..0000000 --- a/base/android/jni_android.h +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) 2012 The Chromium 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 BASE_ANDROID_JNI_ANDROID_H_ -#define BASE_ANDROID_JNI_ANDROID_H_ - -#include -#include - -#include - -#include "base/android/scoped_java_ref.h" -#include "base/atomicops.h" -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/debug/stack_trace.h" -#include "base/macros.h" - -#if HAVE_TRACE_STACK_FRAME_POINTERS - -// When profiling is enabled (enable_profiling=true) this macro is added to -// all generated JNI stubs so that it becomes the last thing that runs before -// control goes into Java. -// -// This macro saves stack frame pointer of the current function. Saved value -// used later by JNI_LINK_SAVED_FRAME_POINTER. -#define JNI_SAVE_FRAME_POINTER \ - base::android::JNIStackFrameSaver jni_frame_saver(__builtin_frame_address(0)) - -// When profiling is enabled (enable_profiling=true) this macro is added to -// all generated JNI callbacks so that it becomes the first thing that runs -// after control returns from Java. -// -// This macro links stack frame of the current function to the stack frame -// saved by JNI_SAVE_FRAME_POINTER, allowing frame-based unwinding -// (used by the heap profiler) to produce complete traces. -#define JNI_LINK_SAVED_FRAME_POINTER \ - base::debug::ScopedStackFrameLinker jni_frame_linker( \ - __builtin_frame_address(0), \ - base::android::JNIStackFrameSaver::SavedFrame()) - -#else - -// Frame-based stack unwinding is not supported, do nothing. -#define JNI_SAVE_FRAME_POINTER -#define JNI_LINK_SAVED_FRAME_POINTER - -#endif // HAVE_TRACE_STACK_FRAME_POINTERS - -namespace base { -namespace android { - -// Used to mark symbols to be exported in a shared library's symbol table. -#define JNI_EXPORT __attribute__ ((visibility("default"))) - -// The level of JNI registration required for the current process. -enum JniRegistrationType { - // Register all native methods. - ALL_JNI_REGISTRATION, - // Register some native methods, as controlled by the jni_generator. - SELECTIVE_JNI_REGISTRATION, - // Do not register any native methods. - NO_JNI_REGISTRATION, -}; - -BASE_EXPORT JniRegistrationType GetJniRegistrationType(); - -// Set the JniRegistrationType for this process (defaults to -// ALL_JNI_REGISTRATION). This should be called in the JNI_OnLoad function -// which is called when the native library is first loaded. -BASE_EXPORT void SetJniRegistrationType( - JniRegistrationType jni_registration_type); - -// Contains the registration method information for initializing JNI bindings. -struct RegistrationMethod { - const char* name; - bool (*func)(JNIEnv* env); -}; - -// Attaches the current thread to the VM (if necessary) and return the JNIEnv*. -BASE_EXPORT JNIEnv* AttachCurrentThread(); - -// Same to AttachCurrentThread except that thread name will be set to -// |thread_name| if it is the first call. Otherwise, thread_name won't be -// changed. AttachCurrentThread() doesn't regard underlying platform thread -// name, but just resets it to "Thread-???". This function should be called -// right after new thread is created if it is important to keep thread name. -BASE_EXPORT JNIEnv* AttachCurrentThreadWithName(const std::string& thread_name); - -// Detaches the current thread from VM if it is attached. -BASE_EXPORT void DetachFromVM(); - -// Initializes the global JVM. -BASE_EXPORT void InitVM(JavaVM* vm); - -// Returns true if the global JVM has been initialized. -BASE_EXPORT bool IsVMInitialized(); - -// Initializes the global ClassLoader used by the GetClass and LazyGetClass -// methods. This is needed because JNI will use the base ClassLoader when there -// is no Java code on the stack. The base ClassLoader doesn't know about any of -// the application classes and will fail to lookup anything other than system -// classes. -BASE_EXPORT void InitReplacementClassLoader( - JNIEnv* env, - const JavaRef& class_loader); - -// Finds the class named |class_name| and returns it. -// Use this method instead of invoking directly the JNI FindClass method (to -// prevent leaking local references). -// This method triggers a fatal assertion if the class could not be found. -// Use HasClass if you need to check whether the class exists. -BASE_EXPORT ScopedJavaLocalRef GetClass(JNIEnv* env, - const char* class_name); - -// The method will initialize |atomic_class_id| to contain a global ref to the -// class. And will return that ref on subsequent calls. It's the caller's -// responsibility to release the ref when it is no longer needed. -// The caller is responsible to zero-initialize |atomic_method_id|. -// It's fine to simultaneously call this on multiple threads referencing the -// same |atomic_method_id|. -BASE_EXPORT jclass LazyGetClass( - JNIEnv* env, - const char* class_name, - base::subtle::AtomicWord* atomic_class_id); - -// This class is a wrapper for JNIEnv Get(Static)MethodID. -class BASE_EXPORT MethodID { - public: - enum Type { - TYPE_STATIC, - TYPE_INSTANCE, - }; - - // Returns the method ID for the method with the specified name and signature. - // This method triggers a fatal assertion if the method could not be found. - template - static jmethodID Get(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature); - - // The caller is responsible to zero-initialize |atomic_method_id|. - // It's fine to simultaneously call this on multiple threads referencing the - // same |atomic_method_id|. - template - static jmethodID LazyGet(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature, - base::subtle::AtomicWord* atomic_method_id); -}; - -// Returns true if an exception is pending in the provided JNIEnv*. -BASE_EXPORT bool HasException(JNIEnv* env); - -// If an exception is pending in the provided JNIEnv*, this function clears it -// and returns true. -BASE_EXPORT bool ClearException(JNIEnv* env); - -// This function will call CHECK() macro if there's any pending exception. -BASE_EXPORT void CheckException(JNIEnv* env); - -// This returns a string representation of the java stack trace. -BASE_EXPORT std::string GetJavaExceptionInfo(JNIEnv* env, - jthrowable java_throwable); - -#if HAVE_TRACE_STACK_FRAME_POINTERS - -// Saves caller's PC and stack frame in a thread-local variable. -// Implemented only when profiling is enabled (enable_profiling=true). -class BASE_EXPORT JNIStackFrameSaver { - public: - JNIStackFrameSaver(void* current_fp); - ~JNIStackFrameSaver(); - static void* SavedFrame(); - - private: - void* previous_fp_; - - DISALLOW_COPY_AND_ASSIGN(JNIStackFrameSaver); -}; - -#endif // HAVE_TRACE_STACK_FRAME_POINTERS - -} // namespace android -} // namespace base - -#endif // BASE_ANDROID_JNI_ANDROID_H_ diff --git a/base/android/jni_android_unittest.cc b/base/android/jni_android_unittest.cc deleted file mode 100644 index dabd480..0000000 --- a/base/android/jni_android_unittest.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/jni_android.h" - -#include "base/at_exit.h" -#include "base/logging.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace android { - -namespace { - -base::subtle::AtomicWord g_atomic_id = 0; -int LazyMethodIDCall(JNIEnv* env, jclass clazz, int p) { - jmethodID id = base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, clazz, - "abs", - "(I)I", - &g_atomic_id); - - return env->CallStaticIntMethod(clazz, id, p); -} - -int MethodIDCall(JNIEnv* env, jclass clazz, jmethodID id, int p) { - return env->CallStaticIntMethod(clazz, id, p); -} - -} // namespace - -TEST(JNIAndroidMicrobenchmark, MethodId) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef clazz(GetClass(env, "java/lang/Math")); - base::Time start_lazy = base::Time::Now(); - int o = 0; - for (int i = 0; i < 1024; ++i) - o += LazyMethodIDCall(env, clazz.obj(), i); - base::Time end_lazy = base::Time::Now(); - - jmethodID id = reinterpret_cast(g_atomic_id); - base::Time start = base::Time::Now(); - for (int i = 0; i < 1024; ++i) - o += MethodIDCall(env, clazz.obj(), id, i); - base::Time end = base::Time::Now(); - - // On a Galaxy Nexus, results were in the range of: - // JNI LazyMethodIDCall (us) 1984 - // JNI MethodIDCall (us) 1861 - LOG(ERROR) << "JNI LazyMethodIDCall (us) " << - base::TimeDelta(end_lazy - start_lazy).InMicroseconds(); - LOG(ERROR) << "JNI MethodIDCall (us) " << - base::TimeDelta(end - start).InMicroseconds(); - LOG(ERROR) << "JNI " << o; -} - - -} // namespace android -} // namespace base diff --git a/base/android/jni_generator/android_jar.classes b/base/android/jni_generator/android_jar.classes deleted file mode 100644 index 7d412ce..0000000 --- a/base/android/jni_generator/android_jar.classes +++ /dev/null @@ -1,98 +0,0 @@ -java/lang/AbstractMethodError.class -java/lang/AbstractStringBuilder.class -java/lang/Appendable.class -java/lang/ArithmeticException.class -java/lang/ArrayIndexOutOfBoundsException.class -java/lang/ArrayStoreException.class -java/lang/AssertionError.class -java/lang/AutoCloseable.class -java/lang/Boolean.class -java/lang/Byte.class -java/lang/Character.class -java/lang/Character$Subset.class -java/lang/Character$UnicodeBlock.class -java/lang/CharSequence.class -java/lang/ClassCastException.class -java/lang/ClassCircularityError.class -java/lang/Class.class -java/lang/ClassFormatError.class -java/lang/ClassLoader.class -java/lang/ClassNotFoundException.class -java/lang/Cloneable.class -java/lang/CloneNotSupportedException.class -java/lang/Comparable.class -java/lang/Compiler.class -java/lang/Deprecated.class -java/lang/Double.class -java/lang/Enum.class -java/lang/EnumConstantNotPresentException.class -java/lang/Error.class -java/lang/Exception.class -java/lang/ExceptionInInitializerError.class -java/lang/Float.class -java/lang/IllegalAccessError.class -java/lang/IllegalAccessException.class -java/lang/IllegalArgumentException.class -java/lang/IllegalMonitorStateException.class -java/lang/IllegalStateException.class -java/lang/IncompatibleClassChangeError.class -java/lang/IndexOutOfBoundsException.class -java/lang/InheritableThreadLocal.class -java/lang/InstantiationError.class -java/lang/InstantiationException.class -java/lang/Integer.class -java/lang/InternalError.class -java/lang/InterruptedException.class -java/lang/Iterable.class -java/lang/LinkageError.class -java/lang/Long.class -java/lang/Math.class -java/lang/NegativeArraySizeException.class -java/lang/NoClassDefFoundError.class -java/lang/NoSuchFieldError.class -java/lang/NoSuchFieldException.class -java/lang/NoSuchMethodError.class -java/lang/NoSuchMethodException.class -java/lang/NullPointerException.class -java/lang/Number.class -java/lang/NumberFormatException.class -java/lang/Object.class -java/lang/OutOfMemoryError.class -java/lang/Override.class -java/lang/Package.class -java/lang/ProcessBuilder.class -java/lang/Process.class -java/lang/Readable.class -java/lang/ReflectiveOperationException.class -java/lang/Runnable.class -java/lang/Runtime.class -java/lang/RuntimeException.class -java/lang/RuntimePermission.class -java/lang/SafeVarargs.class -java/lang/SecurityException.class -java/lang/SecurityManager.class -java/lang/Short.class -java/lang/StackOverflowError.class -java/lang/StackTraceElement.class -java/lang/StrictMath.class -java/lang/StringBuffer.class -java/lang/StringBuilder.class -java/lang/String.class -java/lang/StringIndexOutOfBoundsException.class -java/lang/SuppressWarnings.class -java/lang/System.class -java/lang/Thread.class -java/lang/ThreadDeath.class -java/lang/ThreadGroup.class -java/lang/ThreadLocal.class -java/lang/Thread$State.class -java/lang/Thread$UncaughtExceptionHandler.class -java/lang/Throwable.class -java/lang/TypeNotPresentException.class -java/lang/UnknownError.class -java/lang/UnsatisfiedLinkError.class -java/lang/UnsupportedClassVersionError.class -java/lang/UnsupportedOperationException.class -java/lang/VerifyError.class -java/lang/VirtualMachineError.class -java/lang/Void.class diff --git a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java deleted file mode 100644 index 42d8e56..0000000 --- a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForTests.java +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright 2012 The Chromium 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.example.jni_generator; - -import android.graphics.Rect; - -import org.chromium.base.annotations.AccessedByNative; -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.CalledByNativeUnchecked; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.base.annotations.NativeCall; -import org.chromium.base.annotations.NativeClassQualifiedName; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -// This class serves as a reference test for the bindings generator, and as example documentation -// for how to use the jni generator. -// The C++ counter-part is sample_for_tests.cc. -// jni_generator/BUILD.gn has a jni_generator_tests target that will: -// * Generate a header file for the JNI bindings based on this file. -// * Compile sample_for_tests.cc using the generated header file. -// * link a native executable to prove the generated header + cc file are self-contained. -// All comments are informational only, and are ignored by the jni generator. -// -// Binding C/C++ with Java is not trivial, specially when ownership and object lifetime -// semantics needs to be managed across boundaries. -// Following a few guidelines will make the code simpler and less buggy: -// -// - Never write any JNI "by hand". Rely on the bindings generator to have a thin -// layer of type-safety. -// -// - Treat the types from the other side as "opaque" as possible. Do not inspect any -// object directly, but rather, rely on well-defined getters / setters. -// -// - Minimize the surface API between the two sides, and rather than calling multiple -// functions across boundaries, call only one (and then, internally in the other side, -// call as many little functions as required). -// -// - If a Java object "owns" a native object, stash the pointer in a "long mNativeClassName". -// Note that it needs to have a "destruction path", i.e., it must eventually call a method -// to delete the native object (for example, the java object has a "close()" method that -// in turn deletes the native object). Avoid relying on finalizers: those run in a different -// thread and makes the native lifetime management more difficult. -// -// - For native object "owning" java objects: -// - If there's a strong 1:1 to relationship between native and java, the best way is to -// stash the java object into a base::android::ScopedJavaGlobalRef. This will ensure the -// java object can be GC'd once the native object is destroyed but note that this global strong -// ref implies a new GC root, so be sure it will not leak and it must never rely on being -// triggered (transitively) from a java side GC. -// - In all other cases, the native side should keep a JavaObjectWeakGlobalRef, and check whether -// that reference is still valid before de-referencing it. Note that you will need another -// java-side object to be holding a strong reference to this java object while it is in use, to -// avoid unpredictable GC of the object before native side has finished with it. -// -// - The best way to pass "compound" datatypes across in either direction is to create an inner -// class with PODs and a factory function. If possible, make it immutable (i.e., mark all the -// fields as "final"). See examples with "InnerStructB" below. -// -// - It's simpler to create thin wrappers with a well defined JNI interface than to -// expose a lot of internal details. This is specially significant for system classes where it's -// simpler to wrap factory methods and a few getters / setters than expose the entire class. -// -// - Use static factory functions annotated with @CalledByNative rather than calling the -// constructors directly. -// -// - Iterate over containers where they are originally owned, then create inner structs or -// directly call methods on the other side. It's much simpler than trying to amalgamate -// java and stl containers. -// -// An important note about qualified class name resolution: -// The generator doesn't compile the class and have little context about the -// classes being passed through the JNI layers. It adds a few simple rules: -// -// - all classes are either explicitly imported, or they are assumed to be in -// the same package. -// -// - Inner class needs to be done through an import and usage of the -// outer class, so that the generator knows how to qualify it: -// import foo.bar.Zoo; -// void call(Zoo.Inner); -// -// - implicitly imported classes aren't supported, so in order to pass -// things like Runnable, please import java.lang.Runnable; -// -// This JNINamespace annotation indicates that all native methods should be -// generated inside this namespace, including the native class that this -// object binds to. -@JNINamespace("base::android") -class SampleForTests { - // Classes can store their C++ pointer counter part as an int that is normally initialized by - // calling out a nativeInit() function. Replace "CPPClass" with your particular class name! - long mNativeCPPObject; - - // You can define methods and attributes on the java class just like any other. - // Methods without the @CalledByNative annotation won't be exposed to JNI. - public SampleForTests() { - } - - public void startExample() { - // Calls C++ Init(...) method and holds a pointer to the C++ class. - mNativeCPPObject = nativeInit("myParam"); - } - - public void doStuff() { - // This will call CPPClass::Method() using nativePtr as a pointer to the object. This must - // be done to: - // * avoid leaks. - // * using finalizers are not allowed to destroy the cpp class. - nativeMethod(mNativeCPPObject); - } - - public void finishExample() { - // We're done, so let's destroy nativePtr object. - nativeDestroy(mNativeCPPObject); - } - - // --------------------------------------------------------------------------------------------- - // The following methods demonstrate exporting Java methods for invocation from C++ code. - // Java functions are mapping into C global functions by prefixing the method name with - // "Java__" - // This is triggered by the @CalledByNative annotation; the methods may be named as you wish. - - // Exported to C++ as: - // Java_SampleForTests_javaMethod(JNIEnv* env, jobject caller, jint foo, jint bar) - // Typically the C++ code would have obtained the jobject via the Init() call described above. - @CalledByNative - public int javaMethod(int foo, int bar) { - return 0; - } - - // Exported to C++ as Java_SampleForTests_staticJavaMethod(JNIEnv* env) - // Note no jobject argument, as it is static. - @CalledByNative - public static boolean staticJavaMethod() { - return true; - } - - // No prefix, so this method is package private. It will still be exported. - @CalledByNative - void packagePrivateJavaMethod() { - } - - // Note the "Unchecked" suffix. By default, @CalledByNative will always generate bindings that - // call CheckException(). With "@CalledByNativeUnchecked", the client C++ code is responsible to - // call ClearException() and act as appropriate. - // See more details at the "@CalledByNativeUnchecked" annotation. - @CalledByNativeUnchecked - void methodThatThrowsException() throws Exception {} - - // The generator is not confused by inline comments: - // @CalledByNative void thisShouldNotAppearInTheOutput(); - // @CalledByNativeUnchecked public static void neitherShouldThis(int foo); - - /** - * The generator is not confused by block comments: - * @CalledByNative void thisShouldNotAppearInTheOutputEither(); - * @CalledByNativeUnchecked public static void andDefinitelyNotThis(int foo); - */ - - // String constants that look like comments don't confuse the generator: - private String mArrgh = "*/*"; - - private @interface SomeAnnotation {} - - // The generator is not confused by @Annotated parameters. - @CalledByNative - void javaMethodWithAnnotatedParam(@SomeAnnotation int foo) { - } - - // --------------------------------------------------------------------------------------------- - // Java fields which are accessed from C++ code only must be annotated with @AccessedByNative to - // prevent them being eliminated when unreferenced code is stripped. - @AccessedByNative - private int mJavaField; - - // --------------------------------------------------------------------------------------------- - // The following methods demonstrate declaring methods to call into C++ from Java. - // The generator detects the "native" and "static" keywords, the type and name of the first - // parameter, and the "native" prefix to the function name to determine the C++ function - // signatures. Besides these constraints the methods can be freely named. - - // This declares a C++ function which the application code must implement: - // static jint Init(JNIEnv* env, jobject caller); - // The jobject parameter refers back to this java side object instance. - // The implementation must return the pointer to the C++ object cast to jint. - // The caller of this method should store it, and supply it as a the nativeCPPClass param to - // subsequent native method calls (see the methods below that take an "int native..." as first - // param). - private native long nativeInit(String param); - - // This defines a function binding to the associated C++ class member function. The name is - // derived from |nativeDestroy| and |nativeCPPClass| to arrive at CPPClass::Destroy() (i.e. - // native prefixes stripped). - // - // The |nativeCPPClass| is automatically cast to type CPPClass*, in order to obtain the object - // on - // which to invoke the member function. Replace "CPPClass" with your particular class name! - private native void nativeDestroy(long nativeCPPClass); - - // This declares a C++ function which the application code must implement: - // static jdouble GetDoubleFunction(JNIEnv* env, jobject caller); - // The jobject parameter refers back to this java side object instance. - private native double nativeGetDoubleFunction(); - - // Similar to nativeGetDoubleFunction(), but here the C++ side will receive a jclass rather than - // jobject param, as the function is declared static. - private static native float nativeGetFloatFunction(); - - // This function takes a non-POD datatype. We have a list mapping them to their full classpath - // in jni_generator.py JavaParamToJni. If you require a new datatype, make sure you add to that - // function. - private native void nativeSetNonPODDatatype(Rect rect); - - // This declares a C++ function which the application code must implement: - // static ScopedJavaLocalRef GetNonPODDatatype(JNIEnv* env, jobject caller); - // The jobject parameter refers back to this java side object instance. - // Note that it returns a ScopedJavaLocalRef so that you don' have to worry about - // deleting the JNI local reference. This is similar with Strings and arrays. - private native Object nativeGetNonPODDatatype(); - - // Similar to nativeDestroy above, this will cast nativeCPPClass into pointer of CPPClass type - // and call its Method member function. Replace "CPPClass" with your particular class name! - private native int nativeMethod(long nativeCPPClass); - - // Similar to nativeMethod above, but here the C++ fully qualified class name is taken from the - // annotation rather than parameter name, which can thus be chosen freely. - @NativeClassQualifiedName("CPPClass::InnerClass") - private native double nativeMethodOtherP0(long nativePtr); - - // This "struct" will be created by the native side using |createInnerStructA|, - // and used by the java-side somehow. - // Note that |@CalledByNative| has to contain the inner class name. - static class InnerStructA { - private final long mLong; - private final int mInt; - private final String mString; - - private InnerStructA(long l, int i, String s) { - mLong = l; - mInt = i; - mString = s; - } - - @CalledByNative("InnerStructA") - private static InnerStructA create(long l, int i, String s) { - return new InnerStructA(l, i, s); - } - } - - private List mListInnerStructA = new ArrayList(); - - @CalledByNative - private void addStructA(InnerStructA a) { - // Called by the native side to append another element. - mListInnerStructA.add(a); - } - - @CalledByNative - private void iterateAndDoSomething() { - Iterator it = mListInnerStructA.iterator(); - while (it.hasNext()) { - InnerStructA element = it.next(); - // Now, do something with element. - } - // Done, clear the list. - mListInnerStructA.clear(); - } - - // This "struct" will be created by the java side passed to native, which - // will use its getters. - // Note that |@CalledByNative| has to contain the inner class name. - static class InnerStructB { - private final long mKey; - private final String mValue; - - private InnerStructB(long k, String v) { - mKey = k; - mValue = v; - } - - @CalledByNative("InnerStructB") - private long getKey() { - return mKey; - } - - @CalledByNative("InnerStructB") - private String getValue() { - return mValue; - } - } - - List mListInnerStructB = new ArrayList(); - - void iterateAndDoSomethingWithMap() { - Iterator it = mListInnerStructB.iterator(); - while (it.hasNext()) { - InnerStructB element = it.next(); - // Now, do something with element. - nativeAddStructB(mNativeCPPObject, element); - } - nativeIterateAndDoSomethingWithStructB(mNativeCPPObject); - } - - native void nativeAddStructB(long nativeCPPClass, InnerStructB b); - native void nativeIterateAndDoSomethingWithStructB(long nativeCPPClass); - native String nativeReturnAString(long nativeCPPClass); - - // This inner class shows how to annotate native methods on inner classes. - static class InnerClass { - @NativeCall("InnerClass") - private static native int nativeGetInnerIntFunction(); - } -} diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py deleted file mode 100755 index 99d8b42..0000000 --- a/base/android/jni_generator/jni_generator.py +++ /dev/null @@ -1,1418 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Extracts native methods from a Java file and generates the JNI bindings. -If you change this, please run and update the tests.""" - -import collections -import errno -import optparse -import os -import re -import string -from string import Template -import subprocess -import sys -import textwrap -import zipfile - -CHROMIUM_SRC = os.path.join( - os.path.dirname(__file__), os.pardir, os.pardir, os.pardir) -BUILD_ANDROID_GYP = os.path.join( - CHROMIUM_SRC, 'build', 'android', 'gyp') - -sys.path.append(BUILD_ANDROID_GYP) - -from util import build_utils - - -class ParseError(Exception): - """Exception thrown when we can't parse the input file.""" - - def __init__(self, description, *context_lines): - Exception.__init__(self) - self.description = description - self.context_lines = context_lines - - def __str__(self): - context = '\n'.join(self.context_lines) - return '***\nERROR: %s\n\n%s\n***' % (self.description, context) - - -class Param(object): - """Describes a param for a method, either java or native.""" - - def __init__(self, **kwargs): - self.datatype = kwargs['datatype'] - self.name = kwargs['name'] - - -class NativeMethod(object): - """Describes a C/C++ method that is called by Java code""" - - def __init__(self, **kwargs): - self.static = kwargs['static'] - self.java_class_name = kwargs['java_class_name'] - self.return_type = kwargs['return_type'] - self.name = kwargs['name'] - self.params = kwargs['params'] - if self.params: - assert type(self.params) is list - assert type(self.params[0]) is Param - if (self.params and - self.params[0].datatype == kwargs.get('ptr_type', 'int') and - self.params[0].name.startswith('native')): - self.type = 'method' - self.p0_type = self.params[0].name[len('native'):] - if kwargs.get('native_class_name'): - self.p0_type = kwargs['native_class_name'] - else: - self.type = 'function' - self.method_id_var_name = kwargs.get('method_id_var_name', None) - - -class CalledByNative(object): - """Describes a java method exported to c/c++""" - - def __init__(self, **kwargs): - self.system_class = kwargs['system_class'] - self.unchecked = kwargs['unchecked'] - self.static = kwargs['static'] - self.java_class_name = kwargs['java_class_name'] - self.return_type = kwargs['return_type'] - self.name = kwargs['name'] - self.params = kwargs['params'] - self.method_id_var_name = kwargs.get('method_id_var_name', None) - self.signature = kwargs.get('signature') - self.is_constructor = kwargs.get('is_constructor', False) - self.env_call = GetEnvCall(self.is_constructor, self.static, - self.return_type) - self.static_cast = GetStaticCastForReturnType(self.return_type) - - -class ConstantField(object): - def __init__(self, **kwargs): - self.name = kwargs['name'] - self.value = kwargs['value'] - - -def JavaDataTypeToC(java_type): - """Returns a C datatype for the given java type.""" - java_pod_type_map = { - 'int': 'jint', - 'byte': 'jbyte', - 'char': 'jchar', - 'short': 'jshort', - 'boolean': 'jboolean', - 'long': 'jlong', - 'double': 'jdouble', - 'float': 'jfloat', - } - java_type_map = { - 'void': 'void', - 'String': 'jstring', - 'Throwable': 'jthrowable', - 'java/lang/String': 'jstring', - 'java/lang/Class': 'jclass', - 'java/lang/Throwable': 'jthrowable', - } - - if java_type in java_pod_type_map: - return java_pod_type_map[java_type] - elif java_type in java_type_map: - return java_type_map[java_type] - elif java_type.endswith('[]'): - if java_type[:-2] in java_pod_type_map: - return java_pod_type_map[java_type[:-2]] + 'Array' - return 'jobjectArray' - elif java_type.startswith('Class'): - # Checking just the start of the name, rather than a direct comparison, - # in order to handle generics. - return 'jclass' - else: - return 'jobject' - - -def WrapCTypeForDeclaration(c_type): - """Wrap the C datatype in a JavaRef if required.""" - if re.match(RE_SCOPED_JNI_TYPES, c_type): - return 'const base::android::JavaParamRef<' + c_type + '>&' - else: - return c_type - - -def JavaDataTypeToCForDeclaration(java_type): - """Returns a JavaRef-wrapped C datatype for the given java type.""" - return WrapCTypeForDeclaration(JavaDataTypeToC(java_type)) - - -def JavaDataTypeToCForCalledByNativeParam(java_type): - """Returns a C datatype to be when calling from native.""" - if java_type == 'int': - return 'JniIntWrapper' - else: - c_type = JavaDataTypeToC(java_type) - if re.match(RE_SCOPED_JNI_TYPES, c_type): - return 'const base::android::JavaRefOrBare<' + c_type + '>&' - else: - return c_type - - -def JavaReturnValueToC(java_type): - """Returns a valid C return value for the given java type.""" - java_pod_type_map = { - 'int': '0', - 'byte': '0', - 'char': '0', - 'short': '0', - 'boolean': 'false', - 'long': '0', - 'double': '0', - 'float': '0', - 'void': '' - } - return java_pod_type_map.get(java_type, 'NULL') - - -class JniParams(object): - _imports = [] - _fully_qualified_class = '' - _package = '' - _inner_classes = [] - _implicit_imports = [] - - @staticmethod - def SetFullyQualifiedClass(fully_qualified_class): - JniParams._fully_qualified_class = 'L' + fully_qualified_class - JniParams._package = '/'.join(fully_qualified_class.split('/')[:-1]) - - @staticmethod - def AddAdditionalImport(class_name): - assert class_name.endswith('.class') - raw_class_name = class_name[:-len('.class')] - if '.' in raw_class_name: - raise SyntaxError('%s cannot be used in @JNIAdditionalImport. ' - 'Only import unqualified outer classes.' % class_name) - new_import = 'L%s/%s' % (JniParams._package, raw_class_name) - if new_import in JniParams._imports: - raise SyntaxError('Do not use JNIAdditionalImport on an already ' - 'imported class: %s' % (new_import.replace('/', '.'))) - JniParams._imports += [new_import] - - @staticmethod - def ExtractImportsAndInnerClasses(contents): - if not JniParams._package: - raise RuntimeError('SetFullyQualifiedClass must be called before ' - 'ExtractImportsAndInnerClasses') - contents = contents.replace('\n', '') - re_import = re.compile(r'import.*?(?P\S*?);') - for match in re.finditer(re_import, contents): - JniParams._imports += ['L' + match.group('class').replace('.', '/')] - - re_inner = re.compile(r'(class|interface)\s+?(?P\w+?)\W') - for match in re.finditer(re_inner, contents): - inner = match.group('name') - if not JniParams._fully_qualified_class.endswith(inner): - JniParams._inner_classes += [JniParams._fully_qualified_class + '$' + - inner] - - re_additional_imports = re.compile( - r'@JNIAdditionalImport\(\s*{?(?P.*?)}?\s*\)') - for match in re.finditer(re_additional_imports, contents): - for class_name in match.group('class_names').split(','): - JniParams.AddAdditionalImport(class_name.strip()) - - @staticmethod - def ParseJavaPSignature(signature_line): - prefix = 'Signature: ' - index = signature_line.find(prefix) - if index == -1: - prefix = 'descriptor: ' - index = signature_line.index(prefix) - return '"%s"' % signature_line[index + len(prefix):] - - @staticmethod - def JavaToJni(param): - """Converts a java param into a JNI signature type.""" - pod_param_map = { - 'int': 'I', - 'boolean': 'Z', - 'char': 'C', - 'short': 'S', - 'long': 'J', - 'double': 'D', - 'float': 'F', - 'byte': 'B', - 'void': 'V', - } - object_param_list = [ - 'Ljava/lang/Boolean', - 'Ljava/lang/Integer', - 'Ljava/lang/Long', - 'Ljava/lang/Object', - 'Ljava/lang/String', - 'Ljava/lang/Class', - 'Ljava/lang/CharSequence', - 'Ljava/lang/Runnable', - 'Ljava/lang/Throwable', - ] - - prefix = '' - # Array? - while param[-2:] == '[]': - prefix += '[' - param = param[:-2] - # Generic? - if '<' in param: - param = param[:param.index('<')] - if param in pod_param_map: - return prefix + pod_param_map[param] - if '/' in param: - # Coming from javap, use the fully qualified param directly. - return prefix + 'L' + param + ';' - - for qualified_name in (object_param_list + - [JniParams._fully_qualified_class] + - JniParams._inner_classes): - if (qualified_name.endswith('/' + param) or - qualified_name.endswith('$' + param.replace('.', '$')) or - qualified_name == 'L' + param): - return prefix + qualified_name + ';' - - # Is it from an import? (e.g. referecing Class from import pkg.Class; - # note that referencing an inner class Inner from import pkg.Class.Inner - # is not supported). - for qualified_name in JniParams._imports: - if qualified_name.endswith('/' + param): - # Ensure it's not an inner class. - components = qualified_name.split('/') - if len(components) > 2 and components[-2][0].isupper(): - raise SyntaxError('Inner class (%s) can not be imported ' - 'and used by JNI (%s). Please import the outer ' - 'class and use Outer.Inner instead.' % - (qualified_name, param)) - return prefix + qualified_name + ';' - - # Is it an inner class from an outer class import? (e.g. referencing - # Class.Inner from import pkg.Class). - if '.' in param: - components = param.split('.') - outer = '/'.join(components[:-1]) - inner = components[-1] - for qualified_name in JniParams._imports: - if qualified_name.endswith('/' + outer): - return (prefix + qualified_name + '$' + inner + ';') - raise SyntaxError('Inner class (%s) can not be ' - 'used directly by JNI. Please import the outer ' - 'class, probably:\n' - 'import %s.%s;' % - (param, JniParams._package.replace('/', '.'), - outer.replace('/', '.'))) - - JniParams._CheckImplicitImports(param) - - # Type not found, falling back to same package as this class. - return (prefix + 'L' + JniParams._package + '/' + param + ';') - - @staticmethod - def _CheckImplicitImports(param): - # Ensure implicit imports, such as java.lang.*, are not being treated - # as being in the same package. - if not JniParams._implicit_imports: - # This file was generated from android.jar and lists - # all classes that are implicitly imported. - with file(os.path.join(os.path.dirname(sys.argv[0]), - 'android_jar.classes'), 'r') as f: - JniParams._implicit_imports = f.readlines() - for implicit_import in JniParams._implicit_imports: - implicit_import = implicit_import.strip().replace('.class', '') - implicit_import = implicit_import.replace('/', '.') - if implicit_import.endswith('.' + param): - raise SyntaxError('Ambiguous class (%s) can not be used directly ' - 'by JNI.\nPlease import it, probably:\n\n' - 'import %s;' % - (param, implicit_import)) - - - @staticmethod - def Signature(params, returns, wrap): - """Returns the JNI signature for the given datatypes.""" - items = ['('] - items += [JniParams.JavaToJni(param.datatype) for param in params] - items += [')'] - items += [JniParams.JavaToJni(returns)] - if wrap: - return '\n' + '\n'.join(['"' + item + '"' for item in items]) - else: - return '"' + ''.join(items) + '"' - - @staticmethod - def Parse(params): - """Parses the params into a list of Param objects.""" - if not params: - return [] - ret = [] - for p in [p.strip() for p in params.split(',')]: - items = p.split(' ') - - # Remove @Annotations from parameters. - while items[0].startswith('@'): - del items[0] - - if 'final' in items: - items.remove('final') - - param = Param( - datatype=items[0], - name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), - ) - ret += [param] - return ret - - -def ExtractJNINamespace(contents): - re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') - m = re.findall(re_jni_namespace, contents) - if not m: - return '' - return m[0] - - -def ExtractFullyQualifiedJavaClassName(java_file_name, contents): - re_package = re.compile('.*?package (.*?);') - matches = re.findall(re_package, contents) - if not matches: - raise SyntaxError('Unable to find "package" line in %s' % java_file_name) - return (matches[0].replace('.', '/') + '/' + - os.path.splitext(os.path.basename(java_file_name))[0]) - - -def ExtractNatives(contents, ptr_type): - """Returns a list of dict containing information about a native method.""" - contents = contents.replace('\n', '') - natives = [] - re_native = re.compile(r'(@NativeClassQualifiedName' - '\(\"(?P.*?)\"\)\s+)?' - '(@NativeCall(\(\"(?P.*?)\"\))\s+)?' - '(?P\w+\s\w+|\w+|\s+)\s*native ' - '(?P\S*) ' - '(?Pnative\w+)\((?P.*?)\);') - for match in re.finditer(re_native, contents): - native = NativeMethod( - static='static' in match.group('qualifiers'), - java_class_name=match.group('java_class_name'), - native_class_name=match.group('native_class_name'), - return_type=match.group('return_type'), - name=match.group('name').replace('native', ''), - params=JniParams.Parse(match.group('params')), - ptr_type=ptr_type) - natives += [native] - return natives - - -def IsMainDexJavaClass(contents): - """Returns "true" if the class is annotated with "@MainDex", "false" if not. - - JNI registration doesn't always need to be completed for non-browser processes - since most Java code is only used by the browser process. Classes that are - needed by non-browser processes must explicitly be annotated with @MainDex - to force JNI registration. - """ - re_maindex = re.compile(r'@MainDex[\s\S]*class\s+\w+\s*{') - found = re.search(re_maindex, contents) - return 'true' if found else 'false' - - -def GetStaticCastForReturnType(return_type): - type_map = { 'String' : 'jstring', - 'java/lang/String' : 'jstring', - 'Throwable': 'jthrowable', - 'java/lang/Throwable': 'jthrowable', - 'boolean[]': 'jbooleanArray', - 'byte[]': 'jbyteArray', - 'char[]': 'jcharArray', - 'short[]': 'jshortArray', - 'int[]': 'jintArray', - 'long[]': 'jlongArray', - 'float[]': 'jfloatArray', - 'double[]': 'jdoubleArray' } - ret = type_map.get(return_type, None) - if ret: - return ret - if return_type.endswith('[]'): - return 'jobjectArray' - return None - - -def GetEnvCall(is_constructor, is_static, return_type): - """Maps the types availabe via env->Call__Method.""" - if is_constructor: - return 'NewObject' - env_call_map = {'boolean': 'Boolean', - 'byte': 'Byte', - 'char': 'Char', - 'short': 'Short', - 'int': 'Int', - 'long': 'Long', - 'float': 'Float', - 'void': 'Void', - 'double': 'Double', - 'Object': 'Object', - } - call = env_call_map.get(return_type, 'Object') - if is_static: - call = 'Static' + call - return 'Call' + call + 'Method' - - -def GetMangledParam(datatype): - """Returns a mangled identifier for the datatype.""" - if len(datatype) <= 2: - return datatype.replace('[', 'A') - ret = '' - for i in range(1, len(datatype)): - c = datatype[i] - if c == '[': - ret += 'A' - elif c.isupper() or datatype[i - 1] in ['/', 'L']: - ret += c.upper() - return ret - - -def GetMangledMethodName(name, params, return_type): - """Returns a mangled method name for the given signature. - - The returned name can be used as a C identifier and will be unique for all - valid overloads of the same method. - - Args: - name: string. - params: list of Param. - return_type: string. - - Returns: - A mangled name. - """ - mangled_items = [] - for datatype in [return_type] + [x.datatype for x in params]: - mangled_items += [GetMangledParam(JniParams.JavaToJni(datatype))] - mangled_name = name + '_'.join(mangled_items) - assert re.match(r'[0-9a-zA-Z_]+', mangled_name) - return mangled_name - - -def MangleCalledByNatives(called_by_natives): - """Mangles all the overloads from the call_by_natives list.""" - method_counts = collections.defaultdict( - lambda: collections.defaultdict(lambda: 0)) - for called_by_native in called_by_natives: - java_class_name = called_by_native.java_class_name - name = called_by_native.name - method_counts[java_class_name][name] += 1 - for called_by_native in called_by_natives: - java_class_name = called_by_native.java_class_name - method_name = called_by_native.name - method_id_var_name = method_name - if method_counts[java_class_name][method_name] > 1: - method_id_var_name = GetMangledMethodName(method_name, - called_by_native.params, - called_by_native.return_type) - called_by_native.method_id_var_name = method_id_var_name - return called_by_natives - - -# Regex to match the JNI types that should be wrapped in a JavaRef. -RE_SCOPED_JNI_TYPES = re.compile('jobject|jclass|jstring|jthrowable|.*Array') - - -# Regex to match a string like "@CalledByNative public void foo(int bar)". -RE_CALLED_BY_NATIVE = re.compile( - '@CalledByNative(?P(Unchecked)*?)(?:\("(?P.*)"\))?' - '\s+(?P[\w ]*?)' - '(:?\s*@\w+)?' # Ignore annotations in return types. - '\s*(?P\S+?)' - '\s+(?P\w+)' - '\s*\((?P[^\)]*)\)') - - -# Removes empty lines that are indented (i.e. start with 2x spaces). -def RemoveIndentedEmptyLines(string): - return re.sub('^(?: {2})+$\n', '', string, flags=re.MULTILINE) - - -def ExtractCalledByNatives(contents): - """Parses all methods annotated with @CalledByNative. - - Args: - contents: the contents of the java file. - - Returns: - A list of dict with information about the annotated methods. - TODO(bulach): return a CalledByNative object. - - Raises: - ParseError: if unable to parse. - """ - called_by_natives = [] - for match in re.finditer(RE_CALLED_BY_NATIVE, contents): - called_by_natives += [CalledByNative( - system_class=False, - unchecked='Unchecked' in match.group('Unchecked'), - static='static' in match.group('prefix'), - java_class_name=match.group('annotation') or '', - return_type=match.group('return_type'), - name=match.group('name'), - params=JniParams.Parse(match.group('params')))] - # Check for any @CalledByNative occurrences that weren't matched. - unmatched_lines = re.sub(RE_CALLED_BY_NATIVE, '', contents).split('\n') - for line1, line2 in zip(unmatched_lines, unmatched_lines[1:]): - if '@CalledByNative' in line1: - raise ParseError('could not parse @CalledByNative method signature', - line1, line2) - return MangleCalledByNatives(called_by_natives) - - -class JNIFromJavaP(object): - """Uses 'javap' to parse a .class file and generate the JNI header file.""" - - def __init__(self, contents, options): - self.contents = contents - self.namespace = options.namespace - for line in contents: - class_name = re.match( - '.*?(public).*?(class|interface) (?P\S+?)( |\Z)', - line) - if class_name: - self.fully_qualified_class = class_name.group('class_name') - break - self.fully_qualified_class = self.fully_qualified_class.replace('.', '/') - # Java 7's javap includes type parameters in output, like HashSet. Strip - # away the <...> and use the raw class name that Java 6 would've given us. - self.fully_qualified_class = self.fully_qualified_class.split('<', 1)[0] - JniParams.SetFullyQualifiedClass(self.fully_qualified_class) - self.java_class_name = self.fully_qualified_class.split('/')[-1] - if not self.namespace: - self.namespace = 'JNI_' + self.java_class_name - re_method = re.compile('(?P.*?)(?P\S+?) (?P\w+?)' - '\((?P.*?)\)') - self.called_by_natives = [] - for lineno, content in enumerate(contents[2:], 2): - match = re.match(re_method, content) - if not match: - continue - self.called_by_natives += [CalledByNative( - system_class=True, - unchecked=False, - static='static' in match.group('prefix'), - java_class_name='', - return_type=match.group('return_type').replace('.', '/'), - name=match.group('name'), - params=JniParams.Parse(match.group('params').replace('.', '/')), - signature=JniParams.ParseJavaPSignature(contents[lineno + 1]))] - re_constructor = re.compile('(.*?)public ' + - self.fully_qualified_class.replace('/', '.') + - '\((?P.*?)\)') - for lineno, content in enumerate(contents[2:], 2): - match = re.match(re_constructor, content) - if not match: - continue - self.called_by_natives += [CalledByNative( - system_class=True, - unchecked=False, - static=False, - java_class_name='', - return_type=self.fully_qualified_class, - name='Constructor', - params=JniParams.Parse(match.group('params').replace('.', '/')), - signature=JniParams.ParseJavaPSignature(contents[lineno + 1]), - is_constructor=True)] - self.called_by_natives = MangleCalledByNatives(self.called_by_natives) - - self.constant_fields = [] - re_constant_field = re.compile('.*?public static final int (?P.*?);') - re_constant_field_value = re.compile( - '.*?Constant(Value| value): int (?P(-*[0-9]+)?)') - for lineno, content in enumerate(contents[2:], 2): - match = re.match(re_constant_field, content) - if not match: - continue - value = re.match(re_constant_field_value, contents[lineno + 2]) - if not value: - value = re.match(re_constant_field_value, contents[lineno + 3]) - if value: - self.constant_fields.append( - ConstantField(name=match.group('name'), - value=value.group('value'))) - - self.inl_header_file_generator = InlHeaderFileGenerator( - self.namespace, self.fully_qualified_class, [], self.called_by_natives, - self.constant_fields, options) - - def GetContent(self): - return self.inl_header_file_generator.GetContent() - - @staticmethod - def CreateFromClass(class_file, options): - class_name = os.path.splitext(os.path.basename(class_file))[0] - p = subprocess.Popen(args=[options.javap, '-c', '-verbose', - '-s', class_name], - cwd=os.path.dirname(class_file), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, _ = p.communicate() - jni_from_javap = JNIFromJavaP(stdout.split('\n'), options) - return jni_from_javap - - -class JNIFromJavaSource(object): - """Uses the given java source file to generate the JNI header file.""" - - # Match single line comments, multiline comments, character literals, and - # double-quoted strings. - _comment_remover_regex = re.compile( - r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', - re.DOTALL | re.MULTILINE) - - def __init__(self, contents, fully_qualified_class, options): - contents = self._RemoveComments(contents) - JniParams.SetFullyQualifiedClass(fully_qualified_class) - JniParams.ExtractImportsAndInnerClasses(contents) - jni_namespace = ExtractJNINamespace(contents) or options.namespace - natives = ExtractNatives(contents, options.ptr_type) - called_by_natives = ExtractCalledByNatives(contents) - maindex = IsMainDexJavaClass(contents) - if len(natives) == 0 and len(called_by_natives) == 0: - raise SyntaxError('Unable to find any JNI methods for %s.' % - fully_qualified_class) - inl_header_file_generator = InlHeaderFileGenerator( - jni_namespace, fully_qualified_class, natives, called_by_natives, [], - options, maindex) - self.content = inl_header_file_generator.GetContent() - - @classmethod - def _RemoveComments(cls, contents): - # We need to support both inline and block comments, and we need to handle - # strings that contain '//' or '/*'. - # TODO(bulach): This is a bit hacky. It would be cleaner to use a real Java - # parser. Maybe we could ditch JNIFromJavaSource and just always use - # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT. - # http://code.google.com/p/chromium/issues/detail?id=138941 - def replacer(match): - # Replace matches that are comments with nothing; return literals/strings - # unchanged. - s = match.group(0) - if s.startswith('/'): - return '' - else: - return s - return cls._comment_remover_regex.sub(replacer, contents) - - def GetContent(self): - return self.content - - @staticmethod - def CreateFromFile(java_file_name, options): - contents = file(java_file_name).read() - fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name, - contents) - return JNIFromJavaSource(contents, fully_qualified_class, options) - - -class InlHeaderFileGenerator(object): - """Generates an inline header file for JNI integration.""" - - def __init__(self, namespace, fully_qualified_class, natives, - called_by_natives, constant_fields, options, maindex='false'): - self.namespace = namespace - self.fully_qualified_class = fully_qualified_class - self.class_name = self.fully_qualified_class.split('/')[-1] - self.natives = natives - self.called_by_natives = called_by_natives - self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' - self.constant_fields = constant_fields - self.maindex = maindex - self.options = options - - - def GetContent(self): - """Returns the content of the JNI binding file.""" - template = Template("""\ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -// This file is autogenerated by -// ${SCRIPT_NAME} -// For -// ${FULLY_QUALIFIED_CLASS} - -#ifndef ${HEADER_GUARD} -#define ${HEADER_GUARD} - -#include - -${INCLUDES} - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -$CLASS_PATH_DEFINITIONS - -} // namespace - -$OPEN_NAMESPACE - -$CONSTANT_FIELDS - -// Step 2: method stubs. -$METHOD_STUBS - -// Step 3: RegisterNatives. -$JNI_NATIVE_METHODS -$REGISTER_NATIVES -$CLOSE_NAMESPACE - -#endif // ${HEADER_GUARD} -""") - values = { - 'SCRIPT_NAME': self.options.script_name, - 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, - 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), - 'CONSTANT_FIELDS': self.GetConstantFieldsString(), - 'METHOD_STUBS': self.GetMethodStubsString(), - 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), - 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), - 'REGISTER_NATIVES': self.GetRegisterNativesString(), - 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), - 'HEADER_GUARD': self.header_guard, - 'INCLUDES': self.GetIncludesString(), - } - assert ((values['JNI_NATIVE_METHODS'] == '') == - (values['REGISTER_NATIVES'] == '')) - return WrapOutput(template.substitute(values)) - - def GetClassPathDefinitionsString(self): - ret = [] - ret += [self.GetClassPathDefinitions()] - return '\n'.join(ret) - - def GetConstantFieldsString(self): - if not self.constant_fields: - return '' - ret = ['enum Java_%s_constant_fields {' % self.class_name] - for c in self.constant_fields: - ret += [' %s = %s,' % (c.name, c.value)] - ret += ['};'] - return '\n'.join(ret) - - def GetMethodStubsString(self): - """Returns the code corresponding to method stubs.""" - ret = [] - for native in self.natives: - ret += [self.GetNativeStub(native)] - ret += self.GetLazyCalledByNativeMethodStubs() - return '\n'.join(ret) - - def GetLazyCalledByNativeMethodStubs(self): - return [self.GetLazyCalledByNativeMethodStub(called_by_native) - for called_by_native in self.called_by_natives] - - def GetIncludesString(self): - if not self.options.includes: - return '' - includes = self.options.includes.split(',') - return '\n'.join('#include "%s"' % x for x in includes) - - def GetKMethodsString(self, clazz): - ret = [] - for native in self.natives: - if (native.java_class_name == clazz or - (not native.java_class_name and clazz == self.class_name)): - ret += [self.GetKMethodArrayEntry(native)] - return '\n'.join(ret) - - def SubstituteNativeMethods(self, template): - """Substitutes JAVA_CLASS and KMETHODS in the provided template.""" - ret = [] - all_classes = self.GetUniqueClasses(self.natives) - all_classes[self.class_name] = self.fully_qualified_class - for clazz in all_classes: - kmethods = self.GetKMethodsString(clazz) - if kmethods: - values = {'JAVA_CLASS': clazz, - 'KMETHODS': kmethods} - ret += [template.substitute(values)] - if not ret: return '' - return '\n' + '\n'.join(ret) - - def GetJNINativeMethodsString(self): - """Returns the implementation of the array of native methods.""" - if not self.options.native_exports_optional: - return '' - template = Template("""\ -static const JNINativeMethod kMethods${JAVA_CLASS}[] = { -${KMETHODS} -}; -""") - return self.SubstituteNativeMethods(template) - - def GetRegisterNativesString(self): - """Returns the code for RegisterNatives.""" - natives = self.GetRegisterNativesImplString() - if not natives: - return '' - - template = Template("""\ -${REGISTER_NATIVES_SIGNATURE} { -${EARLY_EXIT} -${NATIVES} - return true; -} -""") - signature = 'static bool RegisterNativesImpl(JNIEnv* env)' - early_exit = '' - if self.options.native_exports_optional: - early_exit = """\ - if (jni_generator::ShouldSkipJniRegistration(%s)) - return true; -""" % self.maindex - - values = {'REGISTER_NATIVES_SIGNATURE': signature, - 'EARLY_EXIT': early_exit, - 'NATIVES': natives, - } - - return template.substitute(values) - - def GetRegisterNativesImplString(self): - """Returns the shared implementation for RegisterNatives.""" - if not self.options.native_exports_optional: - return '' - - template = Template("""\ - const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); - - if (env->RegisterNatives(${JAVA_CLASS}_clazz(env), - kMethods${JAVA_CLASS}, - kMethods${JAVA_CLASS}Size) < 0) { - jni_generator::HandleRegistrationError( - env, ${JAVA_CLASS}_clazz(env), __FILE__); - return false; - } -""") - return self.SubstituteNativeMethods(template) - - def GetOpenNamespaceString(self): - if self.namespace: - all_namespaces = ['namespace %s {' % ns - for ns in self.namespace.split('::')] - return '\n'.join(all_namespaces) - return '' - - def GetCloseNamespaceString(self): - if self.namespace: - all_namespaces = ['} // namespace %s' % ns - for ns in self.namespace.split('::')] - all_namespaces.reverse() - return '\n'.join(all_namespaces) + '\n' - return '' - - def GetJNIFirstParamType(self, native): - if native.type == 'method': - return 'jobject' - elif native.type == 'function': - if native.static: - return 'jclass' - else: - return 'jobject' - - def GetJNIFirstParam(self, native, for_declaration): - c_type = self.GetJNIFirstParamType(native) - if for_declaration: - c_type = WrapCTypeForDeclaration(c_type) - return [c_type + ' jcaller'] - - def GetParamsInDeclaration(self, native): - """Returns the params for the forward declaration. - - Args: - native: the native dictionary describing the method. - - Returns: - A string containing the params. - """ - return ',\n '.join(self.GetJNIFirstParam(native, True) + - [JavaDataTypeToCForDeclaration(param.datatype) + ' ' + - param.name - for param in native.params]) - - def GetParamsInStub(self, native): - """Returns the params for the stub declaration. - - Args: - native: the native dictionary describing the method. - - Returns: - A string containing the params. - """ - return ',\n '.join(self.GetJNIFirstParam(native, False) + - [JavaDataTypeToC(param.datatype) + ' ' + - param.name - for param in native.params]) - - def GetCalledByNativeParamsInDeclaration(self, called_by_native): - return ',\n '.join([ - JavaDataTypeToCForCalledByNativeParam(param.datatype) + ' ' + - param.name - for param in called_by_native.params]) - - def GetStubName(self, native): - """Return the name of the stub function for this native method. - - Args: - native: the native dictionary describing the method. - - Returns: - A string with the stub function name (used by the JVM). - """ - template = Template("Java_${JAVA_NAME}_native${NAME}") - - java_name = self.fully_qualified_class.replace('_', '_1').replace('/', '_') - if native.java_class_name: - java_name += '_00024' + native.java_class_name - - values = {'NAME': native.name, - 'JAVA_NAME': java_name} - return template.substitute(values) - - def GetJavaParamRefForCall(self, c_type, name): - return Template( - 'base::android::JavaParamRef<${TYPE}>(env, ${NAME})').substitute({ - 'TYPE': c_type, - 'NAME': name, - }) - - def GetJNIFirstParamForCall(self, native): - c_type = self.GetJNIFirstParamType(native) - return [self.GetJavaParamRefForCall(c_type, 'jcaller')] - - def GetNativeStub(self, native): - is_method = native.type == 'method' - - if is_method: - params = native.params[1:] - else: - params = native.params - params_in_call = ['env'] + self.GetJNIFirstParamForCall(native) - for p in params: - c_type = JavaDataTypeToC(p.datatype) - if re.match(RE_SCOPED_JNI_TYPES, c_type): - params_in_call.append(self.GetJavaParamRefForCall(c_type, p.name)) - else: - params_in_call.append(p.name) - params_in_call = ', '.join(params_in_call) - - return_type = return_declaration = JavaDataTypeToC(native.return_type) - post_call = '' - if re.match(RE_SCOPED_JNI_TYPES, return_type): - post_call = '.Release()' - return_declaration = ('base::android::ScopedJavaLocalRef<' + return_type + - '>') - profiling_entered_native = '' - if self.options.enable_profiling: - profiling_entered_native = 'JNI_LINK_SAVED_FRAME_POINTER;' - values = { - 'RETURN': return_type, - 'RETURN_DECLARATION': return_declaration, - 'NAME': native.name, - 'PARAMS': self.GetParamsInDeclaration(native), - 'PARAMS_IN_STUB': self.GetParamsInStub(native), - 'PARAMS_IN_CALL': params_in_call, - 'POST_CALL': post_call, - 'STUB_NAME': self.GetStubName(native), - 'PROFILING_ENTERED_NATIVE': profiling_entered_native, - } - - if is_method: - optional_error_return = JavaReturnValueToC(native.return_type) - if optional_error_return: - optional_error_return = ', ' + optional_error_return - values.update({ - 'OPTIONAL_ERROR_RETURN': optional_error_return, - 'PARAM0_NAME': native.params[0].name, - 'P0_TYPE': native.p0_type, - }) - template = Template("""\ -JNI_GENERATOR_EXPORT ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { - ${PROFILING_ENTERED_NATIVE} - ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); - CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); - return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; -} -""") - else: - template = Template(""" -static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS}); - -JNI_GENERATOR_EXPORT ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { - ${PROFILING_ENTERED_NATIVE} - return ${NAME}(${PARAMS_IN_CALL})${POST_CALL}; -} -""") - - return RemoveIndentedEmptyLines(template.substitute(values)) - - def GetArgument(self, param): - if param.datatype == 'int': - return 'as_jint(' + param.name + ')' - elif re.match(RE_SCOPED_JNI_TYPES, JavaDataTypeToC(param.datatype)): - return param.name + '.obj()' - else: - return param.name - - def GetArgumentsInCall(self, params): - """Return a string of arguments to call from native into Java""" - return [self.GetArgument(p) for p in params] - - def GetCalledByNativeValues(self, called_by_native): - """Fills in necessary values for the CalledByNative methods.""" - java_class = called_by_native.java_class_name or self.class_name - if called_by_native.static or called_by_native.is_constructor: - first_param_in_declaration = '' - first_param_in_call = ('%s_clazz(env)' % java_class) - else: - first_param_in_declaration = ( - ', const base::android::JavaRefOrBare& obj') - first_param_in_call = 'obj.obj()' - params_in_declaration = self.GetCalledByNativeParamsInDeclaration( - called_by_native) - if params_in_declaration: - params_in_declaration = ', ' + params_in_declaration - params_in_call = ', '.join(self.GetArgumentsInCall(called_by_native.params)) - if params_in_call: - params_in_call = ', ' + params_in_call - pre_call = '' - post_call = '' - if called_by_native.static_cast: - pre_call = 'static_cast<%s>(' % called_by_native.static_cast - post_call = ')' - check_exception = '' - if not called_by_native.unchecked: - check_exception = 'jni_generator::CheckException(env);' - return_type = JavaDataTypeToC(called_by_native.return_type) - optional_error_return = JavaReturnValueToC(called_by_native.return_type) - if optional_error_return: - optional_error_return = ', ' + optional_error_return - return_declaration = '' - return_clause = '' - if return_type != 'void': - pre_call = ' ' + pre_call - return_declaration = return_type + ' ret =' - if re.match(RE_SCOPED_JNI_TYPES, return_type): - return_type = 'base::android::ScopedJavaLocalRef<' + return_type + '>' - return_clause = 'return ' + return_type + '(env, ret);' - else: - return_clause = 'return ret;' - profiling_leaving_native = '' - if self.options.enable_profiling: - profiling_leaving_native = 'JNI_SAVE_FRAME_POINTER;' - return { - 'JAVA_CLASS': java_class, - 'RETURN_TYPE': return_type, - 'OPTIONAL_ERROR_RETURN': optional_error_return, - 'RETURN_DECLARATION': return_declaration, - 'RETURN_CLAUSE': return_clause, - 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration, - 'PARAMS_IN_DECLARATION': params_in_declaration, - 'PRE_CALL': pre_call, - 'POST_CALL': post_call, - 'ENV_CALL': called_by_native.env_call, - 'FIRST_PARAM_IN_CALL': first_param_in_call, - 'PARAMS_IN_CALL': params_in_call, - 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, - 'CHECK_EXCEPTION': check_exception, - 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native), - 'PROFILING_LEAVING_NATIVE': profiling_leaving_native, - } - - - def GetLazyCalledByNativeMethodStub(self, called_by_native): - """Returns a string.""" - function_signature_template = Template("""\ -static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ -JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") - function_header_template = Template("""\ -${FUNCTION_SIGNATURE} {""") - function_header_with_unused_template = Template("""\ -${FUNCTION_SIGNATURE} __attribute__ ((unused)); -${FUNCTION_SIGNATURE} {""") - template = Template(""" -static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0; -${FUNCTION_HEADER} - CHECK_CLAZZ(env, ${FIRST_PARAM_IN_CALL}, - ${JAVA_CLASS}_clazz(env)${OPTIONAL_ERROR_RETURN}); - jmethodID method_id = - ${GET_METHOD_ID_IMPL} - ${PROFILING_LEAVING_NATIVE} - ${RETURN_DECLARATION} - ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, - method_id${PARAMS_IN_CALL})${POST_CALL}; - ${CHECK_EXCEPTION} - ${RETURN_CLAUSE} -}""") - values = self.GetCalledByNativeValues(called_by_native) - values['FUNCTION_SIGNATURE'] = ( - function_signature_template.substitute(values)) - if called_by_native.system_class: - values['FUNCTION_HEADER'] = ( - function_header_with_unused_template.substitute(values)) - else: - values['FUNCTION_HEADER'] = function_header_template.substitute(values) - return RemoveIndentedEmptyLines(template.substitute(values)) - - def GetKMethodArrayEntry(self, native): - template = Template(' { "native${NAME}", ${JNI_SIGNATURE}, ' + - 'reinterpret_cast(${STUB_NAME}) },') - values = {'NAME': native.name, - 'JNI_SIGNATURE': JniParams.Signature(native.params, - native.return_type, - True), - 'STUB_NAME': self.GetStubName(native)} - return template.substitute(values) - - def GetUniqueClasses(self, origin): - ret = {self.class_name: self.fully_qualified_class} - for entry in origin: - class_name = self.class_name - jni_class_path = self.fully_qualified_class - if entry.java_class_name: - class_name = entry.java_class_name - jni_class_path = self.fully_qualified_class + '$' + class_name - ret[class_name] = jni_class_path - return ret - - def GetClassPathDefinitions(self): - """Returns the ClassPath constants.""" - ret = [] - template = Template("""\ -const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""") - all_classes = self.GetUniqueClasses(self.called_by_natives) - if self.options.native_exports_optional: - all_classes.update(self.GetUniqueClasses(self.natives)) - - for clazz in all_classes: - values = { - 'JAVA_CLASS': clazz, - 'JNI_CLASS_PATH': all_classes[clazz], - } - ret += [template.substitute(values)] - ret += '' - - template = Template("""\ -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_${JAVA_CLASS}_clazz __attribute__((unused)) = 0; -#define ${JAVA_CLASS}_clazz(env) \ -base::android::LazyGetClass(env, k${JAVA_CLASS}ClassPath, \ -&g_${JAVA_CLASS}_clazz)""") - - for clazz in all_classes: - values = { - 'JAVA_CLASS': clazz, - } - ret += [template.substitute(values)] - - return '\n'.join(ret) - - def GetMethodIDImpl(self, called_by_native): - """Returns the implementation of GetMethodID.""" - template = Template("""\ - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_${STATIC}>( - env, ${JAVA_CLASS}_clazz(env), - "${JNI_NAME}", - ${JNI_SIGNATURE}, - &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); -""") - jni_name = called_by_native.name - jni_return_type = called_by_native.return_type - if called_by_native.is_constructor: - jni_name = '' - jni_return_type = 'void' - if called_by_native.signature: - signature = called_by_native.signature - else: - signature = JniParams.Signature(called_by_native.params, - jni_return_type, - True) - values = { - 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, - 'JNI_NAME': jni_name, - 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, - 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', - 'JNI_SIGNATURE': signature, - } - return template.substitute(values) - - -def WrapOutput(output): - ret = [] - for line in output.splitlines(): - # Do not wrap lines under 80 characters or preprocessor directives. - if len(line) < 80 or line.lstrip()[:1] == '#': - stripped = line.rstrip() - if len(ret) == 0 or len(ret[-1]) or len(stripped): - ret.append(stripped) - else: - first_line_indent = ' ' * (len(line) - len(line.lstrip())) - subsequent_indent = first_line_indent + ' ' * 4 - if line.startswith('//'): - subsequent_indent = '//' + subsequent_indent - wrapper = textwrap.TextWrapper(width=80, - subsequent_indent=subsequent_indent, - break_long_words=False) - ret += [wrapped.rstrip() for wrapped in wrapper.wrap(line)] - ret += [''] - return '\n'.join(ret) - - -def ExtractJarInputFile(jar_file, input_file, out_dir): - """Extracts input file from jar and returns the filename. - - The input file is extracted to the same directory that the generated jni - headers will be placed in. This is passed as an argument to script. - - Args: - jar_file: the jar file containing the input files to extract. - input_files: the list of files to extract from the jar file. - out_dir: the name of the directories to extract to. - - Returns: - the name of extracted input file. - """ - jar_file = zipfile.ZipFile(jar_file) - - out_dir = os.path.join(out_dir, os.path.dirname(input_file)) - try: - os.makedirs(out_dir) - except OSError as e: - if e.errno != errno.EEXIST: - raise - extracted_file_name = os.path.join(out_dir, os.path.basename(input_file)) - with open(extracted_file_name, 'w') as outfile: - outfile.write(jar_file.read(input_file)) - - return extracted_file_name - - -def GenerateJNIHeader(input_file, output_file, options): - try: - if os.path.splitext(input_file)[1] == '.class': - jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, options) - content = jni_from_javap.GetContent() - else: - jni_from_java_source = JNIFromJavaSource.CreateFromFile( - input_file, options) - content = jni_from_java_source.GetContent() - except ParseError, e: - print e - sys.exit(1) - if output_file: - if not os.path.exists(os.path.dirname(os.path.abspath(output_file))): - os.makedirs(os.path.dirname(os.path.abspath(output_file))) - if options.optimize_generation and os.path.exists(output_file): - with file(output_file, 'r') as f: - existing_content = f.read() - if existing_content == content: - return - with file(output_file, 'w') as f: - f.write(content) - else: - print content - - -def GetScriptName(): - script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) - base_index = 0 - for idx, value in enumerate(script_components): - if value == 'base' or value == 'third_party': - base_index = idx - break - return os.sep.join(script_components[base_index:]) - - -def main(argv): - usage = """usage: %prog [OPTIONS] -This script will parse the given java source code extracting the native -declarations and print the header file to stdout (or a file). -See SampleForTests.java for more details. - """ - option_parser = optparse.OptionParser(usage=usage) - build_utils.AddDepfileOption(option_parser) - - option_parser.add_option('-j', '--jar_file', dest='jar_file', - help='Extract the list of input files from' - ' a specified jar file.' - ' Uses javap to extract the methods from a' - ' pre-compiled class. --input should point' - ' to pre-compiled Java .class files.') - option_parser.add_option('-n', dest='namespace', - help='Uses as a namespace in the generated header ' - 'instead of the javap class name, or when there is ' - 'no JNINamespace annotation in the java source.') - option_parser.add_option('--input_file', - help='Single input file name. The output file name ' - 'will be derived from it. Must be used with ' - '--output_dir.') - option_parser.add_option('--output_dir', - help='The output directory. Must be used with ' - '--input') - option_parser.add_option('--optimize_generation', type="int", - default=0, help='Whether we should optimize JNI ' - 'generation by not regenerating files if they have ' - 'not changed.') - option_parser.add_option('--script_name', default=GetScriptName(), - help='The name of this script in the generated ' - 'header.') - option_parser.add_option('--includes', - help='The comma-separated list of header files to ' - 'include in the generated header.') - option_parser.add_option('--ptr_type', default='int', - type='choice', choices=['int', 'long'], - help='The type used to represent native pointers in ' - 'Java code. For 32-bit, use int; ' - 'for 64-bit, use long.') - option_parser.add_option('--cpp', default='cpp', - help='The path to cpp command.') - option_parser.add_option('--javap', default='javap', - help='The path to javap command.') - option_parser.add_option('--native_exports_optional', action='store_true', - help='Support both explicit and native method' - 'registration.') - option_parser.add_option('--enable_profiling', action='store_true', - help='Add additional profiling instrumentation.') - options, args = option_parser.parse_args(argv) - if options.jar_file: - input_file = ExtractJarInputFile(options.jar_file, options.input_file, - options.output_dir) - elif options.input_file: - input_file = options.input_file - else: - option_parser.print_help() - print '\nError: Must specify --jar_file or --input_file.' - return 1 - output_file = None - if options.output_dir: - root_name = os.path.splitext(os.path.basename(input_file))[0] - output_file = os.path.join(options.output_dir, root_name) + '_jni.h' - GenerateJNIHeader(input_file, output_file, options) - - if options.depfile: - build_utils.WriteDepfile(options.depfile, output_file) - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/base/android/jni_generator/jni_generator_helper.h b/base/android/jni_generator/jni_generator_helper.h deleted file mode 100644 index 3062806..0000000 --- a/base/android/jni_generator/jni_generator_helper.h +++ /dev/null @@ -1,62 +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 BASE_ANDROID_JNI_GENERATOR_JNI_GENERATOR_HELPER_H_ -#define BASE_ANDROID_JNI_GENERATOR_JNI_GENERATOR_HELPER_H_ - -#include - -#include "base/android/jni_android.h" -#include "base/android/scoped_java_ref.h" -#include "base/logging.h" -#include "build/build_config.h" - -// Project-specific macros used by the header files generated by -// jni_generator.py. Different projects can then specify their own -// implementation for this file. -#define CHECK_NATIVE_PTR(env, jcaller, native_ptr, method_name, ...) \ - DCHECK(native_ptr) << method_name; - -#define CHECK_CLAZZ(env, jcaller, clazz, ...) DCHECK(clazz); - -#if defined(ARCH_CPU_X86) -// Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on -// x86 - use force_align_arg_pointer to realign the stack at the JNI -// boundary. crbug.com/655248 -#define JNI_GENERATOR_EXPORT \ - extern "C" __attribute__((visibility("default"), force_align_arg_pointer)) -#else -#define JNI_GENERATOR_EXPORT extern "C" __attribute__((visibility("default"))) -#endif - -namespace jni_generator { - -inline void HandleRegistrationError(JNIEnv* env, - jclass clazz, - const char* filename) { - LOG(ERROR) << "RegisterNatives failed in " << filename; -} - -inline void CheckException(JNIEnv* env) { - base::android::CheckException(env); -} - -inline bool ShouldSkipJniRegistration(bool is_maindex_class) { - switch (base::android::GetJniRegistrationType()) { - case base::android::ALL_JNI_REGISTRATION: - return false; - case base::android::NO_JNI_REGISTRATION: - // TODO(estevenson): Change this to a DCHECK. - return true; - case base::android::SELECTIVE_JNI_REGISTRATION: - return !is_maindex_class; - default: - NOTREACHED(); - return false; - } -} - -} // namespace jni_generator - -#endif // BASE_ANDROID_JNI_GENERATOR_JNI_GENERATOR_HELPER_H_ diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py deleted file mode 100755 index c0c8238..0000000 --- a/base/android/jni_generator/jni_generator_tests.py +++ /dev/null @@ -1,1097 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Tests for jni_generator.py. - -This test suite contains various tests for the JNI generator. -It exercises the low-level parser all the way up to the -code generator and ensures the output matches a golden -file. -""" - -import difflib -import inspect -import optparse -import os -import sys -import unittest -import jni_generator -from jni_generator import CalledByNative, JniParams, NativeMethod, Param - - -SCRIPT_NAME = 'base/android/jni_generator/jni_generator.py' -INCLUDES = ( - 'base/android/jni_generator/jni_generator_helper.h' -) - -# Set this environment variable in order to regenerate the golden text -# files. -REBASELINE_ENV = 'REBASELINE' - -class TestOptions(object): - """The mock options object which is passed to the jni_generator.py script.""" - - def __init__(self): - self.namespace = None - self.script_name = SCRIPT_NAME - self.includes = INCLUDES - self.ptr_type = 'long' - self.cpp = 'cpp' - self.javap = 'javap' - self.native_exports_optional = True - self.enable_profiling = False - -class TestGenerator(unittest.TestCase): - def assertObjEquals(self, first, second): - dict_first = first.__dict__ - dict_second = second.__dict__ - self.assertEquals(dict_first.keys(), dict_second.keys()) - for key, value in dict_first.iteritems(): - if (type(value) is list and len(value) and - isinstance(type(value[0]), object)): - self.assertListEquals(value, second.__getattribute__(key)) - else: - actual = second.__getattribute__(key) - self.assertEquals(value, actual, - 'Key ' + key + ': ' + str(value) + '!=' + str(actual)) - - def assertListEquals(self, first, second): - self.assertEquals(len(first), len(second)) - for i in xrange(len(first)): - if isinstance(first[i], object): - self.assertObjEquals(first[i], second[i]) - else: - self.assertEquals(first[i], second[i]) - - def assertTextEquals(self, golden_text, generated_text): - if not self.compareText(golden_text, generated_text): - self.fail('Golden text mismatch.') - - def compareText(self, golden_text, generated_text): - def FilterText(text): - return [ - l.strip() for l in text.split('\n') - if not l.startswith('// Copyright') - ] - stripped_golden = FilterText(golden_text) - stripped_generated = FilterText(generated_text) - if stripped_golden == stripped_generated: - return True - print self.id() - for line in difflib.context_diff(stripped_golden, stripped_generated): - print line - print '\n\nGenerated' - print '=' * 80 - print generated_text - print '=' * 80 - print 'Run with:' - print 'REBASELINE=1', sys.argv[0] - print 'to regenerate the data files.' - - def _ReadGoldenFile(self, golden_file): - if not os.path.exists(golden_file): - return None - with file(golden_file, 'r') as f: - return f.read() - - def assertGoldenTextEquals(self, generated_text): - script_dir = os.path.dirname(sys.argv[0]) - # This is the caller test method. - caller = inspect.stack()[1][3] - self.assertTrue(caller.startswith('test'), - 'assertGoldenTextEquals can only be called from a ' - 'test* method, not %s' % caller) - golden_file = os.path.join(script_dir, caller + '.golden') - golden_text = self._ReadGoldenFile(golden_file) - if os.environ.get(REBASELINE_ENV): - if golden_text != generated_text: - with file(golden_file, 'w') as f: - f.write(generated_text) - return - self.assertTextEquals(golden_text, generated_text) - - def testInspectCaller(self): - def willRaise(): - # This function can only be called from a test* method. - self.assertGoldenTextEquals('') - self.assertRaises(AssertionError, willRaise) - - def testNatives(self): - test_data = """" - interface OnFrameAvailableListener {} - private native int nativeInit(); - private native void nativeDestroy(int nativeChromeBrowserProvider); - private native long nativeAddBookmark( - int nativeChromeBrowserProvider, - String url, String title, boolean isFolder, long parentId); - private static native String nativeGetDomainAndRegistry(String url); - private static native void nativeCreateHistoricalTabFromState( - byte[] state, int tab_index); - private native byte[] nativeGetStateAsByteArray(View view); - private static native String[] nativeGetAutofillProfileGUIDs(); - private native void nativeSetRecognitionResults( - int sessionId, String[] results); - private native long nativeAddBookmarkFromAPI( - int nativeChromeBrowserProvider, - String url, Long created, Boolean isBookmark, - Long date, byte[] favicon, String title, Integer visits); - native int nativeFindAll(String find); - private static native OnFrameAvailableListener nativeGetInnerClass(); - private native Bitmap nativeQueryBitmap( - int nativeChromeBrowserProvider, - String[] projection, String selection, - String[] selectionArgs, String sortOrder); - private native void nativeGotOrientation( - int nativeDataFetcherImplAndroid, - double alpha, double beta, double gamma); - private static native Throwable nativeMessWithJavaException(Throwable e); - """ - jni_generator.JniParams.SetFullyQualifiedClass( - 'org/chromium/example/jni_generator/SampleForTests') - jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data) - natives = jni_generator.ExtractNatives(test_data, 'int') - golden_natives = [ - NativeMethod(return_type='int', static=False, - name='Init', - params=[], - java_class_name=None, - type='function'), - NativeMethod(return_type='void', static=False, name='Destroy', - params=[Param(datatype='int', - name='nativeChromeBrowserProvider')], - java_class_name=None, - type='method', - p0_type='ChromeBrowserProvider'), - NativeMethod(return_type='long', static=False, name='AddBookmark', - params=[Param(datatype='int', - name='nativeChromeBrowserProvider'), - Param(datatype='String', - name='url'), - Param(datatype='String', - name='title'), - Param(datatype='boolean', - name='isFolder'), - Param(datatype='long', - name='parentId')], - java_class_name=None, - type='method', - p0_type='ChromeBrowserProvider'), - NativeMethod(return_type='String', static=True, - name='GetDomainAndRegistry', - params=[Param(datatype='String', - name='url')], - java_class_name=None, - type='function'), - NativeMethod(return_type='void', static=True, - name='CreateHistoricalTabFromState', - params=[Param(datatype='byte[]', - name='state'), - Param(datatype='int', - name='tab_index')], - java_class_name=None, - type='function'), - NativeMethod(return_type='byte[]', static=False, - name='GetStateAsByteArray', - params=[Param(datatype='View', name='view')], - java_class_name=None, - type='function'), - NativeMethod(return_type='String[]', static=True, - name='GetAutofillProfileGUIDs', params=[], - java_class_name=None, - type='function'), - NativeMethod(return_type='void', static=False, - name='SetRecognitionResults', - params=[Param(datatype='int', name='sessionId'), - Param(datatype='String[]', name='results')], - java_class_name=None, - type='function'), - NativeMethod(return_type='long', static=False, - name='AddBookmarkFromAPI', - params=[Param(datatype='int', - name='nativeChromeBrowserProvider'), - Param(datatype='String', - name='url'), - Param(datatype='Long', - name='created'), - Param(datatype='Boolean', - name='isBookmark'), - Param(datatype='Long', - name='date'), - Param(datatype='byte[]', - name='favicon'), - Param(datatype='String', - name='title'), - Param(datatype='Integer', - name='visits')], - java_class_name=None, - type='method', - p0_type='ChromeBrowserProvider'), - NativeMethod(return_type='int', static=False, - name='FindAll', - params=[Param(datatype='String', - name='find')], - java_class_name=None, - type='function'), - NativeMethod(return_type='OnFrameAvailableListener', static=True, - name='GetInnerClass', - params=[], - java_class_name=None, - type='function'), - NativeMethod(return_type='Bitmap', - static=False, - name='QueryBitmap', - params=[Param(datatype='int', - name='nativeChromeBrowserProvider'), - Param(datatype='String[]', - name='projection'), - Param(datatype='String', - name='selection'), - Param(datatype='String[]', - name='selectionArgs'), - Param(datatype='String', - name='sortOrder'), - ], - java_class_name=None, - type='method', - p0_type='ChromeBrowserProvider'), - NativeMethod(return_type='void', static=False, - name='GotOrientation', - params=[Param(datatype='int', - name='nativeDataFetcherImplAndroid'), - Param(datatype='double', - name='alpha'), - Param(datatype='double', - name='beta'), - Param(datatype='double', - name='gamma'), - ], - java_class_name=None, - type='method', - p0_type='content::DataFetcherImplAndroid'), - NativeMethod(return_type='Throwable', static=True, - name='MessWithJavaException', - params=[Param(datatype='Throwable', name='e')], - java_class_name=None, - type='function') - ] - self.assertListEquals(golden_natives, natives) - h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, [], [], TestOptions()) - self.assertGoldenTextEquals(h.GetContent()) - - def testInnerClassNatives(self): - test_data = """ - class MyInnerClass { - @NativeCall("MyInnerClass") - private native int nativeInit(); - } - """ - natives = jni_generator.ExtractNatives(test_data, 'int') - golden_natives = [ - NativeMethod(return_type='int', static=False, - name='Init', params=[], - java_class_name='MyInnerClass', - type='function') - ] - self.assertListEquals(golden_natives, natives) - h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, [], [], TestOptions()) - self.assertGoldenTextEquals(h.GetContent()) - - def testInnerClassNativesMultiple(self): - test_data = """ - class MyInnerClass { - @NativeCall("MyInnerClass") - private native int nativeInit(); - } - class MyOtherInnerClass { - @NativeCall("MyOtherInnerClass") - private native int nativeInit(); - } - """ - natives = jni_generator.ExtractNatives(test_data, 'int') - golden_natives = [ - NativeMethod(return_type='int', static=False, - name='Init', params=[], - java_class_name='MyInnerClass', - type='function'), - NativeMethod(return_type='int', static=False, - name='Init', params=[], - java_class_name='MyOtherInnerClass', - type='function') - ] - self.assertListEquals(golden_natives, natives) - h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, [], [], TestOptions()) - self.assertGoldenTextEquals(h.GetContent()) - - def testInnerClassNativesBothInnerAndOuter(self): - test_data = """ - class MyOuterClass { - private native int nativeInit(); - class MyOtherInnerClass { - @NativeCall("MyOtherInnerClass") - private native int nativeInit(); - } - } - """ - natives = jni_generator.ExtractNatives(test_data, 'int') - golden_natives = [ - NativeMethod(return_type='int', static=False, - name='Init', params=[], - java_class_name=None, - type='function'), - NativeMethod(return_type='int', static=False, - name='Init', params=[], - java_class_name='MyOtherInnerClass', - type='function') - ] - self.assertListEquals(golden_natives, natives) - h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, [], [], TestOptions()) - self.assertGoldenTextEquals(h.GetContent()) - - def testCalledByNatives(self): - test_data = """" - import android.graphics.Bitmap; - import android.view.View; - import java.io.InputStream; - import java.util.List; - - class InnerClass {} - - @CalledByNative - InnerClass showConfirmInfoBar(int nativeInfoBar, - String buttonOk, String buttonCancel, String title, Bitmap icon) { - InfoBar infobar = new ConfirmInfoBar(nativeInfoBar, mContext, - buttonOk, buttonCancel, - title, icon); - return infobar; - } - @CalledByNative - InnerClass showAutoLoginInfoBar(int nativeInfoBar, - String realm, String account, String args) { - AutoLoginInfoBar infobar = new AutoLoginInfoBar(nativeInfoBar, mContext, - realm, account, args); - if (infobar.displayedAccountCount() == 0) - infobar = null; - return infobar; - } - @CalledByNative("InfoBar") - void dismiss(); - @SuppressWarnings("unused") - @CalledByNative - private static boolean shouldShowAutoLogin(View view, - String realm, String account, String args) { - AccountManagerContainer accountManagerContainer = - new AccountManagerContainer((Activity)contentView.getContext(), - realm, account, args); - String[] logins = accountManagerContainer.getAccountLogins(null); - return logins.length != 0; - } - @CalledByNative - static InputStream openUrl(String url) { - return null; - } - @CalledByNative - private void activateHardwareAcceleration(final boolean activated, - final int iPid, final int iType, - final int iPrimaryID, final int iSecondaryID) { - if (!activated) { - return - } - } - @CalledByNative - public static @Status int updateStatus(@Status int status) { - return getAndUpdateStatus(status); - } - @CalledByNativeUnchecked - private void uncheckedCall(int iParam); - - @CalledByNative - public byte[] returnByteArray(); - - @CalledByNative - public boolean[] returnBooleanArray(); - - @CalledByNative - public char[] returnCharArray(); - - @CalledByNative - public short[] returnShortArray(); - - @CalledByNative - public int[] returnIntArray(); - - @CalledByNative - public long[] returnLongArray(); - - @CalledByNative - public double[] returnDoubleArray(); - - @CalledByNative - public Object[] returnObjectArray(); - - @CalledByNative - public byte[][] returnArrayOfByteArray(); - - @CalledByNative - public Bitmap.CompressFormat getCompressFormat(); - - @CalledByNative - public List getCompressFormatList(); - """ - jni_generator.JniParams.SetFullyQualifiedClass('org/chromium/Foo') - jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data) - called_by_natives = jni_generator.ExtractCalledByNatives(test_data) - golden_called_by_natives = [ - CalledByNative( - return_type='InnerClass', - system_class=False, - static=False, - name='showConfirmInfoBar', - method_id_var_name='showConfirmInfoBar', - java_class_name='', - params=[Param(datatype='int', name='nativeInfoBar'), - Param(datatype='String', name='buttonOk'), - Param(datatype='String', name='buttonCancel'), - Param(datatype='String', name='title'), - Param(datatype='Bitmap', name='icon')], - env_call=('Object', ''), - unchecked=False, - ), - CalledByNative( - return_type='InnerClass', - system_class=False, - static=False, - name='showAutoLoginInfoBar', - method_id_var_name='showAutoLoginInfoBar', - java_class_name='', - params=[Param(datatype='int', name='nativeInfoBar'), - Param(datatype='String', name='realm'), - Param(datatype='String', name='account'), - Param(datatype='String', name='args')], - env_call=('Object', ''), - unchecked=False, - ), - CalledByNative( - return_type='void', - system_class=False, - static=False, - name='dismiss', - method_id_var_name='dismiss', - java_class_name='InfoBar', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='boolean', - system_class=False, - static=True, - name='shouldShowAutoLogin', - method_id_var_name='shouldShowAutoLogin', - java_class_name='', - params=[Param(datatype='View', name='view'), - Param(datatype='String', name='realm'), - Param(datatype='String', name='account'), - Param(datatype='String', name='args')], - env_call=('Boolean', ''), - unchecked=False, - ), - CalledByNative( - return_type='InputStream', - system_class=False, - static=True, - name='openUrl', - method_id_var_name='openUrl', - java_class_name='', - params=[Param(datatype='String', name='url')], - env_call=('Object', ''), - unchecked=False, - ), - CalledByNative( - return_type='void', - system_class=False, - static=False, - name='activateHardwareAcceleration', - method_id_var_name='activateHardwareAcceleration', - java_class_name='', - params=[Param(datatype='boolean', name='activated'), - Param(datatype='int', name='iPid'), - Param(datatype='int', name='iType'), - Param(datatype='int', name='iPrimaryID'), - Param(datatype='int', name='iSecondaryID'), - ], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='int', - system_class=False, - static=True, - name='updateStatus', - method_id_var_name='updateStatus', - java_class_name='', - params=[Param(datatype='int', name='status')], - env_call=('Integer', ''), - unchecked=False, - ), - CalledByNative( - return_type='void', - system_class=False, - static=False, - name='uncheckedCall', - method_id_var_name='uncheckedCall', - java_class_name='', - params=[Param(datatype='int', name='iParam')], - env_call=('Void', ''), - unchecked=True, - ), - CalledByNative( - return_type='byte[]', - system_class=False, - static=False, - name='returnByteArray', - method_id_var_name='returnByteArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='boolean[]', - system_class=False, - static=False, - name='returnBooleanArray', - method_id_var_name='returnBooleanArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='char[]', - system_class=False, - static=False, - name='returnCharArray', - method_id_var_name='returnCharArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='short[]', - system_class=False, - static=False, - name='returnShortArray', - method_id_var_name='returnShortArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='int[]', - system_class=False, - static=False, - name='returnIntArray', - method_id_var_name='returnIntArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='long[]', - system_class=False, - static=False, - name='returnLongArray', - method_id_var_name='returnLongArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='double[]', - system_class=False, - static=False, - name='returnDoubleArray', - method_id_var_name='returnDoubleArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='Object[]', - system_class=False, - static=False, - name='returnObjectArray', - method_id_var_name='returnObjectArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='byte[][]', - system_class=False, - static=False, - name='returnArrayOfByteArray', - method_id_var_name='returnArrayOfByteArray', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='Bitmap.CompressFormat', - system_class=False, - static=False, - name='getCompressFormat', - method_id_var_name='getCompressFormat', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - CalledByNative( - return_type='List', - system_class=False, - static=False, - name='getCompressFormatList', - method_id_var_name='getCompressFormatList', - java_class_name='', - params=[], - env_call=('Void', ''), - unchecked=False, - ), - ] - self.assertListEquals(golden_called_by_natives, called_by_natives) - h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - [], called_by_natives, [], - TestOptions()) - self.assertGoldenTextEquals(h.GetContent()) - - def testCalledByNativeParseError(self): - try: - jni_generator.ExtractCalledByNatives(""" -@CalledByNative -public static int foo(); // This one is fine - -@CalledByNative -scooby doo -""") - self.fail('Expected a ParseError') - except jni_generator.ParseError, e: - self.assertEquals(('@CalledByNative', 'scooby doo'), e.context_lines) - - def testFullyQualifiedClassName(self): - contents = """ -// Copyright (c) 2010 The Chromium 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.content.browser; - -import org.chromium.base.BuildInfo; -""" - self.assertEquals('org/chromium/content/browser/Foo', - jni_generator.ExtractFullyQualifiedJavaClassName( - 'org/chromium/content/browser/Foo.java', contents)) - self.assertEquals('org/chromium/content/browser/Foo', - jni_generator.ExtractFullyQualifiedJavaClassName( - 'frameworks/Foo.java', contents)) - self.assertRaises(SyntaxError, - jni_generator.ExtractFullyQualifiedJavaClassName, - 'com/foo/Bar', 'no PACKAGE line') - - def testMethodNameMangling(self): - self.assertEquals('closeV', - jni_generator.GetMangledMethodName('close', [], 'void')) - self.assertEquals('readI_AB_I_I', - jni_generator.GetMangledMethodName('read', - [Param(name='p1', - datatype='byte[]'), - Param(name='p2', - datatype='int'), - Param(name='p3', - datatype='int'),], - 'int')) - self.assertEquals('openJIIS_JLS', - jni_generator.GetMangledMethodName('open', - [Param(name='p1', - datatype='java/lang/String'),], - 'java/io/InputStream')) - - def testFromJavaPGenerics(self): - contents = """ -public abstract class java.util.HashSet extends java.util.AbstractSet - implements java.util.Set, java.lang.Cloneable, java.io.Serializable { - public void dummy(); - Signature: ()V -} -""" - jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), - TestOptions()) - self.assertEquals(1, len(jni_from_javap.called_by_natives)) - self.assertGoldenTextEquals(jni_from_javap.GetContent()) - - def testSnippnetJavap6_7_8(self): - content_javap6 = """ -public class java.util.HashSet { -public boolean add(java.lang.Object); - Signature: (Ljava/lang/Object;)Z -} -""" - - content_javap7 = """ -public class java.util.HashSet { -public boolean add(E); - Signature: (Ljava/lang/Object;)Z -} -""" - - content_javap8 = """ -public class java.util.HashSet { - public boolean add(E); - descriptor: (Ljava/lang/Object;)Z -} -""" - - jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'), - TestOptions()) - jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'), - TestOptions()) - jni_from_javap8 = jni_generator.JNIFromJavaP(content_javap8.split('\n'), - TestOptions()) - self.assertTrue(jni_from_javap6.GetContent()) - self.assertTrue(jni_from_javap7.GetContent()) - self.assertTrue(jni_from_javap8.GetContent()) - # Ensure the javap7 is correctly parsed and uses the Signature field rather - # than the "E" parameter. - self.assertTextEquals(jni_from_javap6.GetContent(), - jni_from_javap7.GetContent()) - # Ensure the javap8 is correctly parsed and uses the descriptor field. - self.assertTextEquals(jni_from_javap7.GetContent(), - jni_from_javap8.GetContent()) - - def testFromJavaP(self): - contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]), - 'testInputStream.javap')) - jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), - TestOptions()) - self.assertEquals(10, len(jni_from_javap.called_by_natives)) - self.assertGoldenTextEquals(jni_from_javap.GetContent()) - - def testConstantsFromJavaP(self): - for f in ['testMotionEvent.javap', 'testMotionEvent.javap7']: - contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]), - f)) - jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), - TestOptions()) - self.assertEquals(86, len(jni_from_javap.called_by_natives)) - self.assertGoldenTextEquals(jni_from_javap.GetContent()) - - def testREForNatives(self): - # We should not match "native SyncSetupFlow" inside the comment. - test_data = """ - /** - * Invoked when the setup process is complete so we can disconnect from the - * native-side SyncSetupFlowHandler. - */ - public void destroy() { - Log.v(TAG, "Destroying native SyncSetupFlow"); - if (mNativeSyncSetupFlow != 0) { - nativeSyncSetupEnded(mNativeSyncSetupFlow); - mNativeSyncSetupFlow = 0; - } - } - private native void nativeSyncSetupEnded( - int nativeAndroidSyncSetupFlowHandler); - """ - jni_from_java = jni_generator.JNIFromJavaSource( - test_data, 'foo/bar', TestOptions()) - - def testRaisesOnNonJNIMethod(self): - test_data = """ - class MyInnerClass { - private int Foo(int p0) { - } - } - """ - self.assertRaises(SyntaxError, - jni_generator.JNIFromJavaSource, - test_data, 'foo/bar', TestOptions()) - - def testJniSelfDocumentingExample(self): - script_dir = os.path.dirname(sys.argv[0]) - content = file(os.path.join(script_dir, - 'java/src/org/chromium/example/jni_generator/SampleForTests.java') - ).read() - golden_file = os.path.join(script_dir, 'SampleForTests_jni.golden') - golden_content = file(golden_file).read() - jni_from_java = jni_generator.JNIFromJavaSource( - content, 'org/chromium/example/jni_generator/SampleForTests', - TestOptions()) - generated_text = jni_from_java.GetContent() - if not self.compareText(golden_content, generated_text): - if os.environ.get(REBASELINE_ENV): - with file(golden_file, 'w') as f: - f.write(generated_text) - return - self.fail('testJniSelfDocumentingExample') - - def testNoWrappingPreprocessorLines(self): - test_data = """ - package com.google.lookhowextremelylongiam.snarf.icankeepthisupallday; - - class ReallyLongClassNamesAreAllTheRage { - private static native int nativeTest(); - } - """ - jni_from_java = jni_generator.JNIFromJavaSource( - test_data, ('com/google/lookhowextremelylongiam/snarf/' - 'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'), - TestOptions()) - jni_lines = jni_from_java.GetContent().split('\n') - line = filter(lambda line: line.lstrip().startswith('#ifndef'), - jni_lines)[0] - self.assertTrue(len(line) > 80, - ('Expected #ifndef line to be > 80 chars: ', line)) - - def testImports(self): - import_header = """ -// Copyright (c) 2012 The Chromium 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.content.app; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.graphics.SurfaceTexture; -import android.os.Bundle; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.Process; -import android.os.RemoteException; -import android.util.Log; -import android.view.Surface; - -import java.util.ArrayList; - -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.content.app.ContentMain; -import org.chromium.content.browser.SandboxedProcessConnection; -import org.chromium.content.common.ISandboxedProcessCallback; -import org.chromium.content.common.ISandboxedProcessService; -import org.chromium.content.common.WillNotRaise.AnException; -import org.chromium.content.common.WillRaise.AnException; - -import static org.chromium.Bar.Zoo; - -class Foo { - public static class BookmarkNode implements Parcelable { - } - public interface PasswordListObserver { - } -} - """ - jni_generator.JniParams.SetFullyQualifiedClass( - 'org/chromium/content/app/Foo') - jni_generator.JniParams.ExtractImportsAndInnerClasses(import_header) - self.assertTrue('Lorg/chromium/content/common/ISandboxedProcessService' in - jni_generator.JniParams._imports) - self.assertTrue('Lorg/chromium/Bar/Zoo' in - jni_generator.JniParams._imports) - self.assertTrue('Lorg/chromium/content/app/Foo$BookmarkNode' in - jni_generator.JniParams._inner_classes) - self.assertTrue('Lorg/chromium/content/app/Foo$PasswordListObserver' in - jni_generator.JniParams._inner_classes) - self.assertEquals('Lorg/chromium/content/app/ContentMain$Inner;', - jni_generator.JniParams.JavaToJni('ContentMain.Inner')) - self.assertRaises(SyntaxError, - jni_generator.JniParams.JavaToJni, - 'AnException') - - def testJniParamsJavaToJni(self): - self.assertTextEquals('I', JniParams.JavaToJni('int')) - self.assertTextEquals('[B', JniParams.JavaToJni('byte[]')) - self.assertTextEquals( - '[Ljava/nio/ByteBuffer;', JniParams.JavaToJni('java/nio/ByteBuffer[]')) - - def testNativesLong(self): - test_options = TestOptions() - test_options.ptr_type = 'long' - test_data = """" - private native void nativeDestroy(long nativeChromeBrowserProvider); - """ - jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data) - natives = jni_generator.ExtractNatives(test_data, test_options.ptr_type) - golden_natives = [ - NativeMethod(return_type='void', static=False, name='Destroy', - params=[Param(datatype='long', - name='nativeChromeBrowserProvider')], - java_class_name=None, - type='method', - p0_type='ChromeBrowserProvider', - ptr_type=test_options.ptr_type), - ] - self.assertListEquals(golden_natives, natives) - h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', - natives, [], [], test_options) - self.assertGoldenTextEquals(h.GetContent()) - - def testMainDexFile(self): - test_data = """ - package org.chromium.example.jni_generator; - - @MainDex - class Test { - private static native int nativeStaticMethod(long nativeTest, int arg1); - } - """ - options = TestOptions() - jni_from_java = jni_generator.JNIFromJavaSource( - test_data, 'org/chromium/foo/Bar', options) - self.assertGoldenTextEquals(jni_from_java.GetContent()) - - def testNonMainDexFile(self): - test_data = """ - package org.chromium.example.jni_generator; - - class Test { - private static native int nativeStaticMethod(long nativeTest, int arg1); - } - """ - options = TestOptions() - jni_from_java = jni_generator.JNIFromJavaSource( - test_data, 'org/chromium/foo/Bar', options) - self.assertGoldenTextEquals(jni_from_java.GetContent()) - - def testNativeExportsOnlyOption(self): - test_data = """ - package org.chromium.example.jni_generator; - - /** The pointer to the native Test. */ - long nativeTest; - - class Test { - private static native int nativeStaticMethod(long nativeTest, int arg1); - private native int nativeMethod(long nativeTest, int arg1); - @CalledByNative - private void testMethodWithParam(int iParam); - @CalledByNative - private String testMethodWithParamAndReturn(int iParam); - @CalledByNative - private static int testStaticMethodWithParam(int iParam); - @CalledByNative - private static double testMethodWithNoParam(); - @CalledByNative - private static String testStaticMethodWithNoParam(); - - class MyInnerClass { - @NativeCall("MyInnerClass") - private native int nativeInit(); - } - class MyOtherInnerClass { - @NativeCall("MyOtherInnerClass") - private native int nativeInit(); - } - } - """ - options = TestOptions() - options.native_exports_optional = False - jni_from_java = jni_generator.JNIFromJavaSource( - test_data, 'org/chromium/example/jni_generator/SampleForTests', options) - self.assertGoldenTextEquals(jni_from_java.GetContent()) - - def testOuterInnerRaises(self): - test_data = """ - package org.chromium.media; - - @CalledByNative - static int getCaptureFormatWidth(VideoCapture.CaptureFormat format) { - return format.getWidth(); - } - """ - def willRaise(): - jni_generator.JNIFromJavaSource( - test_data, - 'org/chromium/media/VideoCaptureFactory', - TestOptions()) - self.assertRaises(SyntaxError, willRaise) - - def testSingleJNIAdditionalImport(self): - test_data = """ - package org.chromium.foo; - - @JNIAdditionalImport(Bar.class) - class Foo { - - @CalledByNative - private static void calledByNative(Bar.Callback callback) { - } - - private static native void nativeDoSomething(Bar.Callback callback); - } - """ - jni_from_java = jni_generator.JNIFromJavaSource(test_data, - 'org/chromium/foo/Foo', - TestOptions()) - self.assertGoldenTextEquals(jni_from_java.GetContent()) - - def testMultipleJNIAdditionalImport(self): - test_data = """ - package org.chromium.foo; - - @JNIAdditionalImport({Bar1.class, Bar2.class}) - class Foo { - - @CalledByNative - private static void calledByNative(Bar1.Callback callback1, - Bar2.Callback callback2) { - } - - private static native void nativeDoSomething(Bar1.Callback callback1, - Bar2.Callback callback2); - } - """ - jni_from_java = jni_generator.JNIFromJavaSource(test_data, - 'org/chromium/foo/Foo', - TestOptions()) - self.assertGoldenTextEquals(jni_from_java.GetContent()) - - -def TouchStamp(stamp_path): - dir_name = os.path.dirname(stamp_path) - if not os.path.isdir(dir_name): - os.makedirs(dir_name) - - with open(stamp_path, 'a'): - os.utime(stamp_path, None) - - -def main(argv): - parser = optparse.OptionParser() - parser.add_option('--stamp', help='Path to touch on success.') - options, _ = parser.parse_args(argv[1:]) - - test_result = unittest.main(argv=argv[0:1], exit=False) - - if test_result.result.wasSuccessful() and options.stamp: - TouchStamp(options.stamp) - - return not test_result.result.wasSuccessful() - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/base/android/jni_generator/sample_for_tests.cc b/base/android/jni_generator/sample_for_tests.cc deleted file mode 100644 index 42b2143..0000000 --- a/base/android/jni_generator/sample_for_tests.cc +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include "base/android/jni_generator/sample_for_tests.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/android/scoped_java_ref.h" -// Generated file for JNI bindings from C++ to Java @CalledByNative methods. -// Only to be included in one .cc file. -// Name is based on the java file name: *.java -> jni/*_jni.h -#include "jni/SampleForTests_jni.h" // Generated by JNI. - -using base::android::AttachCurrentThread; -using base::android::ConvertJavaStringToUTF8; -using base::android::ConvertUTF8ToJavaString; -using base::android::ScopedJavaLocalRef; - -namespace base { -namespace android { - -jdouble CPPClass::InnerClass::MethodOtherP0( - JNIEnv* env, - const JavaParamRef& caller) { - return 0.0; -} - -CPPClass::CPPClass() { -} - -CPPClass::~CPPClass() { -} - -// static -bool CPPClass::RegisterJNI(JNIEnv* env) { - return RegisterNativesImpl(env); // Generated in SampleForTests_jni.h -} - -void CPPClass::Destroy(JNIEnv* env, const JavaParamRef& caller) { - delete this; -} - -jint CPPClass::Method(JNIEnv* env, const JavaParamRef& caller) { - return 0; -} - -void CPPClass::AddStructB(JNIEnv* env, - const JavaParamRef& caller, - const JavaParamRef& structb) { - long key = Java_InnerStructB_getKey(env, structb); - std::string value = - ConvertJavaStringToUTF8(env, Java_InnerStructB_getValue(env, structb)); - map_[key] = value; -} - -void CPPClass::IterateAndDoSomethingWithStructB( - JNIEnv* env, - const JavaParamRef& caller) { - // Iterate over the elements and do something with them. - for (std::map::const_iterator it = map_.begin(); - it != map_.end(); ++it) { - long key = it->first; - std::string value = it->second; - std::cout << key << value; - } - map_.clear(); -} - -ScopedJavaLocalRef CPPClass::ReturnAString( - JNIEnv* env, - const JavaParamRef& caller) { - return ConvertUTF8ToJavaString(env, "test"); -} - -// Static free functions declared and called directly from java. -static jlong Init(JNIEnv* env, - const JavaParamRef& caller, - const JavaParamRef& param) { - return 0; -} - -static jdouble GetDoubleFunction(JNIEnv*, const JavaParamRef&) { - return 0; -} - -static jfloat GetFloatFunction(JNIEnv*, const JavaParamRef&) { - return 0; -} - -static void SetNonPODDatatype(JNIEnv*, - const JavaParamRef&, - const JavaParamRef&) {} - -static ScopedJavaLocalRef GetNonPODDatatype( - JNIEnv*, - const JavaParamRef&) { - return ScopedJavaLocalRef(); -} - -static jint GetInnerIntFunction(JNIEnv*, const JavaParamRef&) { - return 0; -} - -} // namespace android -} // namespace base - -int main() { - // On a regular application, you'd call AttachCurrentThread(). This sample is - // not yet linking with all the libraries. - JNIEnv* env = /* AttachCurrentThread() */ NULL; - - // This is how you call a java static method from C++. - bool foo = base::android::Java_SampleForTests_staticJavaMethod(env); - - // This is how you call a java method from C++. Note that you must have - // obtained the jobject somehow. - ScopedJavaLocalRef my_java_object; - int bar = base::android::Java_SampleForTests_javaMethod( - env, my_java_object, 1, 2); - - std::cout << foo << bar; - - for (int i = 0; i < 10; ++i) { - // Creates a "struct" that will then be used by the java side. - ScopedJavaLocalRef struct_a = - base::android::Java_InnerStructA_create( - env, 0, 1, ConvertUTF8ToJavaString(env, "test")); - base::android::Java_SampleForTests_addStructA(env, my_java_object, - struct_a); - } - base::android::Java_SampleForTests_iterateAndDoSomething(env, my_java_object); - base::android::Java_SampleForTests_packagePrivateJavaMethod(env, - my_java_object); - base::android::Java_SampleForTests_methodThatThrowsException(env, - my_java_object); - base::android::Java_SampleForTests_javaMethodWithAnnotatedParam( - env, my_java_object, 42); - return 0; -} diff --git a/base/android/jni_generator/sample_for_tests.h b/base/android/jni_generator/sample_for_tests.h deleted file mode 100644 index a9cf7b0..0000000 --- a/base/android/jni_generator/sample_for_tests.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_ -#define BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_ - -#include -#include -#include - -#include "base/android/jni_android.h" - -namespace base { -namespace android { - -// This file is used to: -// - document the best practices and guidelines on JNI usage. -// - ensure sample_for_tests_jni.h compiles and the functions declared in it -// as expected. -// -// Methods are called directly from Java (except RegisterJNI). More -// documentation in SampleForTests.java -// -// For C++ to access Java methods: -// - GN Build must be configured to generate bindings: -// # Add import at top of file: -// if (is_android) { -// import("//build/config/android/rules.gni") # For generate_jni(). -// } -// # ... -// # An example target that will rely on JNI: -// component("foo") { -// # ... normal sources, defines, deps. -// # For each jni generated .java -> .h header file in jni_headers -// # target there will be a single .cc file here that includes it. -// # -// # Add a dep for JNI: -// if (is_android) { -// deps += [ ":foo_jni" ] -// } -// } -// # ... -// # Create target for JNI: -// if (is_android) { -// generate_jni("jni_headers") { -// sources = [ -// "java/src/org/chromium/example/jni_generator/SampleForTests.java", -// ] -// jni_package = "foo" -// } -// android_library("java") { -// java_files = [ -// "java/src/org/chromium/example/jni_generator/SampleForTests.java", -// "java/src/org/chromium/example/jni_generator/NonJniFile.java", -// ] -// } -// } -// -// For C++ methods to be exposed to Java: -// - The generated RegisterNativesImpl method must be called, this is typically -// done by having a static RegisterJNI method in the C++ class. -// - The RegisterJNI method is added to a module's collection of register -// methods, such as: example_jni_registrar.h/cc files which call -// base::android::RegisterNativeMethods. -// An example_jni_registstrar.cc: -// -// namespace { -// const base::android::RegistrationMethod kRegisteredMethods[] = { -// // Initial string is for debugging only. -// { "ExampleName", base::ExampleNameAndroid::RegisterJNI }, -// { "ExampleName2", base::ExampleName2Android::RegisterJNI }, -// }; -// } // namespace -// -// bool RegisterModuleNameJni(JNIEnv* env) { -// return RegisterNativeMethods(env, kRegisteredMethods, -// arraysize(kRegisteredMethods)); -// } -// -// - Each module's RegisterModuleNameJni must be called by a larger module, -// or application during startup. -// -class CPPClass { - public: - CPPClass(); - ~CPPClass(); - - // Register C++ methods exposed to Java using JNI. - static bool RegisterJNI(JNIEnv* env); - - // Java @CalledByNative methods implicitly available to C++ via the _jni.h - // file included in the .cc file. - - class InnerClass { - public: - jdouble MethodOtherP0(JNIEnv* env, - const base::android::JavaParamRef& caller); - }; - - void Destroy(JNIEnv* env, const base::android::JavaParamRef& caller); - - jint Method(JNIEnv* env, const base::android::JavaParamRef& caller); - - void AddStructB(JNIEnv* env, - const base::android::JavaParamRef& caller, - const base::android::JavaParamRef& structb); - - void IterateAndDoSomethingWithStructB( - JNIEnv* env, - const base::android::JavaParamRef& caller); - - base::android::ScopedJavaLocalRef ReturnAString( - JNIEnv* env, - const base::android::JavaParamRef& caller); - - private: - std::map map_; - - DISALLOW_COPY_AND_ASSIGN(CPPClass); -}; - -} // namespace android -} // namespace base - -#endif // BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_ diff --git a/base/android/jni_generator/testCalledByNatives.golden b/base/android/jni_generator/testCalledByNatives.golden deleted file mode 100644 index ac86b2e..0000000 --- a/base/android/jni_generator/testCalledByNatives.golden +++ /dev/null @@ -1,497 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// org/chromium/TestJni - -#ifndef org_chromium_TestJni_JNI -#define org_chromium_TestJni_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kTestJniClassPath[] = "org/chromium/TestJni"; -const char kInfoBarClassPath[] = "org/chromium/TestJni$InfoBar"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_TestJni_clazz __attribute__((unused)) = 0; -#define TestJni_clazz(env) base::android::LazyGetClass(env, kTestJniClassPath, &g_TestJni_clazz) -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_InfoBar_clazz __attribute__((unused)) = 0; -#define InfoBar_clazz(env) base::android::LazyGetClass(env, kInfoBarClassPath, &g_InfoBar_clazz) - -} // namespace - -// Step 2: method stubs. - -static base::subtle::AtomicWord g_TestJni_showConfirmInfoBar = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_showConfirmInfoBar(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper nativeInfoBar, - const base::android::JavaRefOrBare& buttonOk, - const base::android::JavaRefOrBare& buttonCancel, - const base::android::JavaRefOrBare& title, - const base::android::JavaRefOrBare& icon) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "showConfirmInfoBar", -"(" -"I" -"Ljava/lang/String;" -"Ljava/lang/String;" -"Ljava/lang/String;" -"Landroid/graphics/Bitmap;" -")" -"Lorg/chromium/Foo$InnerClass;", - &g_TestJni_showConfirmInfoBar); - - jobject ret = - env->CallObjectMethod(obj.obj(), - method_id, as_jint(nativeInfoBar), buttonOk.obj(), buttonCancel.obj(), - title.obj(), icon.obj()); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_showAutoLoginInfoBar = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_showAutoLoginInfoBar(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper nativeInfoBar, - const base::android::JavaRefOrBare& realm, - const base::android::JavaRefOrBare& account, - const base::android::JavaRefOrBare& args) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "showAutoLoginInfoBar", -"(" -"I" -"Ljava/lang/String;" -"Ljava/lang/String;" -"Ljava/lang/String;" -")" -"Lorg/chromium/Foo$InnerClass;", - &g_TestJni_showAutoLoginInfoBar); - - jobject ret = - env->CallObjectMethod(obj.obj(), - method_id, as_jint(nativeInfoBar), realm.obj(), account.obj(), - args.obj()); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_InfoBar_dismiss = 0; -static void Java_InfoBar_dismiss(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - InfoBar_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InfoBar_clazz(env), - "dismiss", -"(" -")" -"V", - &g_InfoBar_dismiss); - - env->CallVoidMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_TestJni_shouldShowAutoLogin = 0; -static jboolean Java_TestJni_shouldShowAutoLogin(JNIEnv* env, const - base::android::JavaRefOrBare& view, - const base::android::JavaRefOrBare& realm, - const base::android::JavaRefOrBare& account, - const base::android::JavaRefOrBare& args) { - CHECK_CLAZZ(env, TestJni_clazz(env), - TestJni_clazz(env), false); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, TestJni_clazz(env), - "shouldShowAutoLogin", -"(" -"Landroid/view/View;" -"Ljava/lang/String;" -"Ljava/lang/String;" -"Ljava/lang/String;" -")" -"Z", - &g_TestJni_shouldShowAutoLogin); - - jboolean ret = - env->CallStaticBooleanMethod(TestJni_clazz(env), - method_id, view.obj(), realm.obj(), account.obj(), args.obj()); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_TestJni_openUrl = 0; -static base::android::ScopedJavaLocalRef Java_TestJni_openUrl(JNIEnv* - env, const base::android::JavaRefOrBare& url) { - CHECK_CLAZZ(env, TestJni_clazz(env), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, TestJni_clazz(env), - "openUrl", -"(" -"Ljava/lang/String;" -")" -"Ljava/io/InputStream;", - &g_TestJni_openUrl); - - jobject ret = - env->CallStaticObjectMethod(TestJni_clazz(env), - method_id, url.obj()); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_activateHardwareAcceleration = 0; -static void Java_TestJni_activateHardwareAcceleration(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jboolean activated, - JniIntWrapper iPid, - JniIntWrapper iType, - JniIntWrapper iPrimaryID, - JniIntWrapper iSecondaryID) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "activateHardwareAcceleration", -"(" -"Z" -"I" -"I" -"I" -"I" -")" -"V", - &g_TestJni_activateHardwareAcceleration); - - env->CallVoidMethod(obj.obj(), - method_id, activated, as_jint(iPid), as_jint(iType), - as_jint(iPrimaryID), as_jint(iSecondaryID)); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_TestJni_updateStatus = 0; -static jint Java_TestJni_updateStatus(JNIEnv* env, JniIntWrapper status) { - CHECK_CLAZZ(env, TestJni_clazz(env), - TestJni_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, TestJni_clazz(env), - "updateStatus", -"(" -"I" -")" -"I", - &g_TestJni_updateStatus); - - jint ret = - env->CallStaticIntMethod(TestJni_clazz(env), - method_id, as_jint(status)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_TestJni_uncheckedCall = 0; -static void Java_TestJni_uncheckedCall(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper iParam) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "uncheckedCall", -"(" -"I" -")" -"V", - &g_TestJni_uncheckedCall); - - env->CallVoidMethod(obj.obj(), - method_id, as_jint(iParam)); -} - -static base::subtle::AtomicWord g_TestJni_returnByteArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnByteArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnByteArray", -"(" -")" -"[B", - &g_TestJni_returnByteArray); - - jbyteArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_returnBooleanArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnBooleanArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnBooleanArray", -"(" -")" -"[Z", - &g_TestJni_returnBooleanArray); - - jbooleanArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_returnCharArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnCharArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnCharArray", -"(" -")" -"[C", - &g_TestJni_returnCharArray); - - jcharArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_returnShortArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnShortArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnShortArray", -"(" -")" -"[S", - &g_TestJni_returnShortArray); - - jshortArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_returnIntArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnIntArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnIntArray", -"(" -")" -"[I", - &g_TestJni_returnIntArray); - - jintArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_returnLongArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnLongArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnLongArray", -"(" -")" -"[J", - &g_TestJni_returnLongArray); - - jlongArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_returnDoubleArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnDoubleArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnDoubleArray", -"(" -")" -"[D", - &g_TestJni_returnDoubleArray); - - jdoubleArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_returnObjectArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnObjectArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnObjectArray", -"(" -")" -"[Ljava/lang/Object;", - &g_TestJni_returnObjectArray); - - jobjectArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_returnArrayOfByteArray = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_returnArrayOfByteArray(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "returnArrayOfByteArray", -"(" -")" -"[[B", - &g_TestJni_returnArrayOfByteArray); - - jobjectArray ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_getCompressFormat = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_getCompressFormat(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "getCompressFormat", -"(" -")" -"Landroid/graphics/Bitmap$CompressFormat;", - &g_TestJni_getCompressFormat); - - jobject ret = - env->CallObjectMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_TestJni_getCompressFormatList = 0; -static base::android::ScopedJavaLocalRef - Java_TestJni_getCompressFormatList(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - TestJni_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, TestJni_clazz(env), - "getCompressFormatList", -"(" -")" -"Ljava/util/List;", - &g_TestJni_getCompressFormatList); - - jobject ret = - env->CallObjectMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -// Step 3: RegisterNatives. - -#endif // org_chromium_TestJni_JNI diff --git a/base/android/jni_generator/testConstantsFromJavaP.golden b/base/android/jni_generator/testConstantsFromJavaP.golden deleted file mode 100644 index b16956f..0000000 --- a/base/android/jni_generator/testConstantsFromJavaP.golden +++ /dev/null @@ -1,2195 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// android/view/MotionEvent - -#ifndef android_view_MotionEvent_JNI -#define android_view_MotionEvent_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kMotionEventClassPath[] = "android/view/MotionEvent"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_MotionEvent_clazz __attribute__((unused)) = 0; -#define MotionEvent_clazz(env) base::android::LazyGetClass(env, kMotionEventClassPath, &g_MotionEvent_clazz) - -} // namespace - -namespace JNI_MotionEvent { - -enum Java_MotionEvent_constant_fields { - INVALID_POINTER_ID = -1, - ACTION_MASK = 255, - ACTION_DOWN = 0, - ACTION_UP = 1, - ACTION_MOVE = 2, - ACTION_CANCEL = 3, - ACTION_OUTSIDE = 4, - ACTION_POINTER_DOWN = 5, - ACTION_POINTER_UP = 6, - ACTION_HOVER_MOVE = 7, - ACTION_SCROLL = 8, - ACTION_HOVER_ENTER = 9, - ACTION_HOVER_EXIT = 10, - ACTION_POINTER_INDEX_MASK = 65280, - ACTION_POINTER_INDEX_SHIFT = 8, - ACTION_POINTER_1_DOWN = 5, - ACTION_POINTER_2_DOWN = 261, - ACTION_POINTER_3_DOWN = 517, - ACTION_POINTER_1_UP = 6, - ACTION_POINTER_2_UP = 262, - ACTION_POINTER_3_UP = 518, - ACTION_POINTER_ID_MASK = 65280, - ACTION_POINTER_ID_SHIFT = 8, - FLAG_WINDOW_IS_OBSCURED = 1, - EDGE_TOP = 1, - EDGE_BOTTOM = 2, - EDGE_LEFT = 4, - EDGE_RIGHT = 8, - AXIS_X = 0, - AXIS_Y = 1, - AXIS_PRESSURE = 2, - AXIS_SIZE = 3, - AXIS_TOUCH_MAJOR = 4, - AXIS_TOUCH_MINOR = 5, - AXIS_TOOL_MAJOR = 6, - AXIS_TOOL_MINOR = 7, - AXIS_ORIENTATION = 8, - AXIS_VSCROLL = 9, - AXIS_HSCROLL = 10, - AXIS_Z = 11, - AXIS_RX = 12, - AXIS_RY = 13, - AXIS_RZ = 14, - AXIS_HAT_X = 15, - AXIS_HAT_Y = 16, - AXIS_LTRIGGER = 17, - AXIS_RTRIGGER = 18, - AXIS_THROTTLE = 19, - AXIS_RUDDER = 20, - AXIS_WHEEL = 21, - AXIS_GAS = 22, - AXIS_BRAKE = 23, - AXIS_DISTANCE = 24, - AXIS_TILT = 25, - AXIS_GENERIC_1 = 32, - AXIS_GENERIC_2 = 33, - AXIS_GENERIC_3 = 34, - AXIS_GENERIC_4 = 35, - AXIS_GENERIC_5 = 36, - AXIS_GENERIC_6 = 37, - AXIS_GENERIC_7 = 38, - AXIS_GENERIC_8 = 39, - AXIS_GENERIC_9 = 40, - AXIS_GENERIC_10 = 41, - AXIS_GENERIC_11 = 42, - AXIS_GENERIC_12 = 43, - AXIS_GENERIC_13 = 44, - AXIS_GENERIC_14 = 45, - AXIS_GENERIC_15 = 46, - AXIS_GENERIC_16 = 47, - BUTTON_PRIMARY = 1, - BUTTON_SECONDARY = 2, - BUTTON_TERTIARY = 4, - BUTTON_BACK = 8, - BUTTON_FORWARD = 16, - TOOL_TYPE_UNKNOWN = 0, - TOOL_TYPE_FINGER = 1, - TOOL_TYPE_STYLUS = 2, - TOOL_TYPE_MOUSE = 3, - TOOL_TYPE_ERASER = 4, -}; - -// Step 2: method stubs. - -static base::subtle::AtomicWord g_MotionEvent_finalize = 0; -static void Java_MotionEvent_finalize(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static void Java_MotionEvent_finalize(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "finalize", - "()V", - &g_MotionEvent_finalize); - - env->CallVoidMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord - g_MotionEvent_obtainAVME_J_J_I_I_LAVMEPP_LAVMEPC_I_I_F_F_I_I_I_I = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_I_LAVMEPP_LAVMEPC_I_I_F_F_I_I_I_I(JNIEnv* - env, jlong p0, - jlong p1, - JniIntWrapper p2, - JniIntWrapper p3, - const base::android::JavaRefOrBare& p4, - const base::android::JavaRefOrBare& p5, - JniIntWrapper p6, - JniIntWrapper p7, - jfloat p8, - jfloat p9, - JniIntWrapper p10, - JniIntWrapper p11, - JniIntWrapper p12, - JniIntWrapper p13) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_I_LAVMEPP_LAVMEPC_I_I_F_F_I_I_I_I(JNIEnv* - env, jlong p0, - jlong p1, - JniIntWrapper p2, - JniIntWrapper p3, - const base::android::JavaRefOrBare& p4, - const base::android::JavaRefOrBare& p5, - JniIntWrapper p6, - JniIntWrapper p7, - jfloat p8, - jfloat p9, - JniIntWrapper p10, - JniIntWrapper p11, - JniIntWrapper p12, - JniIntWrapper p13) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "obtain", -"(JJII[Landroid/view/MotionEvent$PointerProperties;[Landroid/view/MotionEvent$PointerCoords;IIFFIIII)Landroid/view/MotionEvent;", - &g_MotionEvent_obtainAVME_J_J_I_I_LAVMEPP_LAVMEPC_I_I_F_F_I_I_I_I); - - jobject ret = - env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, p0, p1, as_jint(p2), as_jint(p3), p4.obj(), p5.obj(), - as_jint(p6), as_jint(p7), p8, p9, as_jint(p10), as_jint(p11), - as_jint(p12), as_jint(p13)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord - g_MotionEvent_obtainAVME_J_J_I_I_AI_LAVMEPC_I_F_F_I_I_I_I = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_I_AI_LAVMEPC_I_F_F_I_I_I_I(JNIEnv* env, - jlong p0, - jlong p1, - JniIntWrapper p2, - JniIntWrapper p3, - const base::android::JavaRefOrBare& p4, - const base::android::JavaRefOrBare& p5, - JniIntWrapper p6, - jfloat p7, - jfloat p8, - JniIntWrapper p9, - JniIntWrapper p10, - JniIntWrapper p11, - JniIntWrapper p12) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_I_AI_LAVMEPC_I_F_F_I_I_I_I(JNIEnv* env, - jlong p0, - jlong p1, - JniIntWrapper p2, - JniIntWrapper p3, - const base::android::JavaRefOrBare& p4, - const base::android::JavaRefOrBare& p5, - JniIntWrapper p6, - jfloat p7, - jfloat p8, - JniIntWrapper p9, - JniIntWrapper p10, - JniIntWrapper p11, - JniIntWrapper p12) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "obtain", -"(JJII[I[Landroid/view/MotionEvent$PointerCoords;IFFIIII)Landroid/view/MotionEvent;", - &g_MotionEvent_obtainAVME_J_J_I_I_AI_LAVMEPC_I_F_F_I_I_I_I); - - jobject ret = - env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, p0, p1, as_jint(p2), as_jint(p3), p4.obj(), p5.obj(), - as_jint(p6), p7, p8, as_jint(p9), as_jint(p10), as_jint(p11), - as_jint(p12)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_MotionEvent_obtainAVME_J_J_I_F_F_F_F_I_F_F_I_I - = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_F_F_F_F_I_F_F_I_I(JNIEnv* env, jlong p0, - jlong p1, - JniIntWrapper p2, - jfloat p3, - jfloat p4, - jfloat p5, - jfloat p6, - JniIntWrapper p7, - jfloat p8, - jfloat p9, - JniIntWrapper p10, - JniIntWrapper p11) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_F_F_F_F_I_F_F_I_I(JNIEnv* env, jlong p0, - jlong p1, - JniIntWrapper p2, - jfloat p3, - jfloat p4, - jfloat p5, - jfloat p6, - JniIntWrapper p7, - jfloat p8, - jfloat p9, - JniIntWrapper p10, - JniIntWrapper p11) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "obtain", - "(JJIFFFFIFFII)Landroid/view/MotionEvent;", - &g_MotionEvent_obtainAVME_J_J_I_F_F_F_F_I_F_F_I_I); - - jobject ret = - env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, p0, p1, as_jint(p2), p3, p4, p5, p6, as_jint(p7), p8, p9, - as_jint(p10), as_jint(p11)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord - g_MotionEvent_obtainAVME_J_J_I_I_F_F_F_F_I_F_F_I_I = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_I_F_F_F_F_I_F_F_I_I(JNIEnv* env, jlong p0, - jlong p1, - JniIntWrapper p2, - JniIntWrapper p3, - jfloat p4, - jfloat p5, - jfloat p6, - jfloat p7, - JniIntWrapper p8, - jfloat p9, - jfloat p10, - JniIntWrapper p11, - JniIntWrapper p12) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_I_F_F_F_F_I_F_F_I_I(JNIEnv* env, jlong p0, - jlong p1, - JniIntWrapper p2, - JniIntWrapper p3, - jfloat p4, - jfloat p5, - jfloat p6, - jfloat p7, - JniIntWrapper p8, - jfloat p9, - jfloat p10, - JniIntWrapper p11, - JniIntWrapper p12) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "obtain", - "(JJIIFFFFIFFII)Landroid/view/MotionEvent;", - &g_MotionEvent_obtainAVME_J_J_I_I_F_F_F_F_I_F_F_I_I); - - jobject ret = - env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, p0, p1, as_jint(p2), as_jint(p3), p4, p5, p6, p7, - as_jint(p8), p9, p10, as_jint(p11), as_jint(p12)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_MotionEvent_obtainAVME_J_J_I_F_F_I = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_F_F_I(JNIEnv* env, jlong p0, - jlong p1, - JniIntWrapper p2, - jfloat p3, - jfloat p4, - JniIntWrapper p5) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_J_J_I_F_F_I(JNIEnv* env, jlong p0, - jlong p1, - JniIntWrapper p2, - jfloat p3, - jfloat p4, - JniIntWrapper p5) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "obtain", - "(JJIFFI)Landroid/view/MotionEvent;", - &g_MotionEvent_obtainAVME_J_J_I_F_F_I); - - jobject ret = - env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, p0, p1, as_jint(p2), p3, p4, as_jint(p5)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_MotionEvent_obtainAVME_AVME = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_AVME(JNIEnv* env, const - base::android::JavaRefOrBare& p0) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainAVME_AVME(JNIEnv* env, const - base::android::JavaRefOrBare& p0) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "obtain", - "(Landroid/view/MotionEvent;)Landroid/view/MotionEvent;", - &g_MotionEvent_obtainAVME_AVME); - - jobject ret = - env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, p0.obj()); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_MotionEvent_obtainNoHistory = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainNoHistory(JNIEnv* env, const - base::android::JavaRefOrBare& p0) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_obtainNoHistory(JNIEnv* env, const - base::android::JavaRefOrBare& p0) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "obtainNoHistory", - "(Landroid/view/MotionEvent;)Landroid/view/MotionEvent;", - &g_MotionEvent_obtainNoHistory); - - jobject ret = - env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, p0.obj()); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_MotionEvent_recycle = 0; -static void Java_MotionEvent_recycle(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static void Java_MotionEvent_recycle(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "recycle", - "()V", - &g_MotionEvent_recycle); - - env->CallVoidMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_getDeviceId = 0; -static jint Java_MotionEvent_getDeviceId(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getDeviceId(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getDeviceId", - "()I", - &g_MotionEvent_getDeviceId); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getSource = 0; -static jint Java_MotionEvent_getSource(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getSource(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getSource", - "()I", - &g_MotionEvent_getSource); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_setSource = 0; -static void Java_MotionEvent_setSource(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static void Java_MotionEvent_setSource(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "setSource", - "(I)V", - &g_MotionEvent_setSource); - - env->CallVoidMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_getAction = 0; -static jint Java_MotionEvent_getAction(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getAction(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getAction", - "()I", - &g_MotionEvent_getAction); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getActionMasked = 0; -static jint Java_MotionEvent_getActionMasked(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getActionMasked(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getActionMasked", - "()I", - &g_MotionEvent_getActionMasked); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getActionIndex = 0; -static jint Java_MotionEvent_getActionIndex(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getActionIndex(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getActionIndex", - "()I", - &g_MotionEvent_getActionIndex); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getFlags = 0; -static jint Java_MotionEvent_getFlags(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getFlags(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getFlags", - "()I", - &g_MotionEvent_getFlags); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getDownTime = 0; -static jlong Java_MotionEvent_getDownTime(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jlong Java_MotionEvent_getDownTime(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getDownTime", - "()J", - &g_MotionEvent_getDownTime); - - jlong ret = - env->CallLongMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getEventTime = 0; -static jlong Java_MotionEvent_getEventTime(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jlong Java_MotionEvent_getEventTime(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getEventTime", - "()J", - &g_MotionEvent_getEventTime); - - jlong ret = - env->CallLongMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getXF = 0; -static jfloat Java_MotionEvent_getXF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getXF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getX", - "()F", - &g_MotionEvent_getXF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getYF = 0; -static jfloat Java_MotionEvent_getYF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getYF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getY", - "()F", - &g_MotionEvent_getYF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getPressureF = 0; -static jfloat Java_MotionEvent_getPressureF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getPressureF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getPressure", - "()F", - &g_MotionEvent_getPressureF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getSizeF = 0; -static jfloat Java_MotionEvent_getSizeF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getSizeF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getSize", - "()F", - &g_MotionEvent_getSizeF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getTouchMajorF = 0; -static jfloat Java_MotionEvent_getTouchMajorF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getTouchMajorF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getTouchMajor", - "()F", - &g_MotionEvent_getTouchMajorF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getTouchMinorF = 0; -static jfloat Java_MotionEvent_getTouchMinorF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getTouchMinorF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getTouchMinor", - "()F", - &g_MotionEvent_getTouchMinorF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getToolMajorF = 0; -static jfloat Java_MotionEvent_getToolMajorF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getToolMajorF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getToolMajor", - "()F", - &g_MotionEvent_getToolMajorF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getToolMinorF = 0; -static jfloat Java_MotionEvent_getToolMinorF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getToolMinorF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getToolMinor", - "()F", - &g_MotionEvent_getToolMinorF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getOrientationF = 0; -static jfloat Java_MotionEvent_getOrientationF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getOrientationF(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getOrientation", - "()F", - &g_MotionEvent_getOrientationF); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getAxisValueF_I = 0; -static jfloat Java_MotionEvent_getAxisValueF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getAxisValueF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getAxisValue", - "(I)F", - &g_MotionEvent_getAxisValueF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getPointerCount = 0; -static jint Java_MotionEvent_getPointerCount(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getPointerCount(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getPointerCount", - "()I", - &g_MotionEvent_getPointerCount); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getPointerId = 0; -static jint Java_MotionEvent_getPointerId(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jint Java_MotionEvent_getPointerId(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getPointerId", - "(I)I", - &g_MotionEvent_getPointerId); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getToolType = 0; -static jint Java_MotionEvent_getToolType(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jint Java_MotionEvent_getToolType(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getToolType", - "(I)I", - &g_MotionEvent_getToolType); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_findPointerIndex = 0; -static jint Java_MotionEvent_findPointerIndex(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jint Java_MotionEvent_findPointerIndex(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "findPointerIndex", - "(I)I", - &g_MotionEvent_findPointerIndex); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getXF_I = 0; -static jfloat Java_MotionEvent_getXF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getXF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getX", - "(I)F", - &g_MotionEvent_getXF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getYF_I = 0; -static jfloat Java_MotionEvent_getYF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getYF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getY", - "(I)F", - &g_MotionEvent_getYF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getPressureF_I = 0; -static jfloat Java_MotionEvent_getPressureF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getPressureF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getPressure", - "(I)F", - &g_MotionEvent_getPressureF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getSizeF_I = 0; -static jfloat Java_MotionEvent_getSizeF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getSizeF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getSize", - "(I)F", - &g_MotionEvent_getSizeF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getTouchMajorF_I = 0; -static jfloat Java_MotionEvent_getTouchMajorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getTouchMajorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getTouchMajor", - "(I)F", - &g_MotionEvent_getTouchMajorF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getTouchMinorF_I = 0; -static jfloat Java_MotionEvent_getTouchMinorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getTouchMinorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getTouchMinor", - "(I)F", - &g_MotionEvent_getTouchMinorF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getToolMajorF_I = 0; -static jfloat Java_MotionEvent_getToolMajorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getToolMajorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getToolMajor", - "(I)F", - &g_MotionEvent_getToolMajorF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getToolMinorF_I = 0; -static jfloat Java_MotionEvent_getToolMinorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getToolMinorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getToolMinor", - "(I)F", - &g_MotionEvent_getToolMinorF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getOrientationF_I = 0; -static jfloat Java_MotionEvent_getOrientationF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getOrientationF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getOrientation", - "(I)F", - &g_MotionEvent_getOrientationF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getAxisValueF_I_I = 0; -static jfloat Java_MotionEvent_getAxisValueF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getAxisValueF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getAxisValue", - "(II)F", - &g_MotionEvent_getAxisValueF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getPointerCoords = 0; -static void Java_MotionEvent_getPointerCoords(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - const base::android::JavaRefOrBare& p1) __attribute__ ((unused)); -static void Java_MotionEvent_getPointerCoords(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - const base::android::JavaRefOrBare& p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getPointerCoords", - "(ILandroid/view/MotionEvent$PointerCoords;)V", - &g_MotionEvent_getPointerCoords); - - env->CallVoidMethod(obj.obj(), - method_id, as_jint(p0), p1.obj()); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_getPointerProperties = 0; -static void Java_MotionEvent_getPointerProperties(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - const base::android::JavaRefOrBare& p1) __attribute__ ((unused)); -static void Java_MotionEvent_getPointerProperties(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - const base::android::JavaRefOrBare& p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getPointerProperties", - "(ILandroid/view/MotionEvent$PointerProperties;)V", - &g_MotionEvent_getPointerProperties); - - env->CallVoidMethod(obj.obj(), - method_id, as_jint(p0), p1.obj()); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_getMetaState = 0; -static jint Java_MotionEvent_getMetaState(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getMetaState(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getMetaState", - "()I", - &g_MotionEvent_getMetaState); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getButtonState = 0; -static jint Java_MotionEvent_getButtonState(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getButtonState(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getButtonState", - "()I", - &g_MotionEvent_getButtonState); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getRawX = 0; -static jfloat Java_MotionEvent_getRawX(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getRawX(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getRawX", - "()F", - &g_MotionEvent_getRawX); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getRawY = 0; -static jfloat Java_MotionEvent_getRawY(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getRawY(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getRawY", - "()F", - &g_MotionEvent_getRawY); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getXPrecision = 0; -static jfloat Java_MotionEvent_getXPrecision(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getXPrecision(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getXPrecision", - "()F", - &g_MotionEvent_getXPrecision); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getYPrecision = 0; -static jfloat Java_MotionEvent_getYPrecision(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getYPrecision(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getYPrecision", - "()F", - &g_MotionEvent_getYPrecision); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistorySize = 0; -static jint Java_MotionEvent_getHistorySize(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getHistorySize(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistorySize", - "()I", - &g_MotionEvent_getHistorySize); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalEventTime = 0; -static jlong Java_MotionEvent_getHistoricalEventTime(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jlong Java_MotionEvent_getHistoricalEventTime(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalEventTime", - "(I)J", - &g_MotionEvent_getHistoricalEventTime); - - jlong ret = - env->CallLongMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalXF_I = 0; -static jfloat Java_MotionEvent_getHistoricalXF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalXF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalX", - "(I)F", - &g_MotionEvent_getHistoricalXF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalYF_I = 0; -static jfloat Java_MotionEvent_getHistoricalYF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalYF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalY", - "(I)F", - &g_MotionEvent_getHistoricalYF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalPressureF_I = 0; -static jfloat Java_MotionEvent_getHistoricalPressureF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalPressureF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalPressure", - "(I)F", - &g_MotionEvent_getHistoricalPressureF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalSizeF_I = 0; -static jfloat Java_MotionEvent_getHistoricalSizeF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalSizeF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalSize", - "(I)F", - &g_MotionEvent_getHistoricalSizeF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalTouchMajorF_I = 0; -static jfloat Java_MotionEvent_getHistoricalTouchMajorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalTouchMajorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalTouchMajor", - "(I)F", - &g_MotionEvent_getHistoricalTouchMajorF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalTouchMinorF_I = 0; -static jfloat Java_MotionEvent_getHistoricalTouchMinorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalTouchMinorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalTouchMinor", - "(I)F", - &g_MotionEvent_getHistoricalTouchMinorF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalToolMajorF_I = 0; -static jfloat Java_MotionEvent_getHistoricalToolMajorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalToolMajorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalToolMajor", - "(I)F", - &g_MotionEvent_getHistoricalToolMajorF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalToolMinorF_I = 0; -static jfloat Java_MotionEvent_getHistoricalToolMinorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalToolMinorF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalToolMinor", - "(I)F", - &g_MotionEvent_getHistoricalToolMinorF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalOrientationF_I = 0; -static jfloat Java_MotionEvent_getHistoricalOrientationF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static jfloat Java_MotionEvent_getHistoricalOrientationF_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalOrientation", - "(I)F", - &g_MotionEvent_getHistoricalOrientationF_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalAxisValueF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalAxisValueF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalAxisValueF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalAxisValue", - "(II)F", - &g_MotionEvent_getHistoricalAxisValueF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalXF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalXF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalXF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalX", - "(II)F", - &g_MotionEvent_getHistoricalXF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalYF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalYF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalYF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalY", - "(II)F", - &g_MotionEvent_getHistoricalYF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalPressureF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalPressureF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalPressureF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalPressure", - "(II)F", - &g_MotionEvent_getHistoricalPressureF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalSizeF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalSizeF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalSizeF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalSize", - "(II)F", - &g_MotionEvent_getHistoricalSizeF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalTouchMajorF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalTouchMajorF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalTouchMajorF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalTouchMajor", - "(II)F", - &g_MotionEvent_getHistoricalTouchMajorF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalTouchMinorF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalTouchMinorF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalTouchMinorF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalTouchMinor", - "(II)F", - &g_MotionEvent_getHistoricalTouchMinorF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalToolMajorF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalToolMajorF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalToolMajorF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalToolMajor", - "(II)F", - &g_MotionEvent_getHistoricalToolMajorF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalToolMinorF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalToolMinorF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalToolMinorF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalToolMinor", - "(II)F", - &g_MotionEvent_getHistoricalToolMinorF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalOrientationF_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalOrientationF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalOrientationF_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalOrientation", - "(II)F", - &g_MotionEvent_getHistoricalOrientationF_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalAxisValueF_I_I_I = 0; -static jfloat Java_MotionEvent_getHistoricalAxisValueF_I_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1, - JniIntWrapper p2) __attribute__ ((unused)); -static jfloat Java_MotionEvent_getHistoricalAxisValueF_I_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1, - JniIntWrapper p2) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalAxisValue", - "(III)F", - &g_MotionEvent_getHistoricalAxisValueF_I_I_I); - - jfloat ret = - env->CallFloatMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1), as_jint(p2)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_getHistoricalPointerCoords = 0; -static void Java_MotionEvent_getHistoricalPointerCoords(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1, - const base::android::JavaRefOrBare& p2) __attribute__ ((unused)); -static void Java_MotionEvent_getHistoricalPointerCoords(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0, - JniIntWrapper p1, - const base::android::JavaRefOrBare& p2) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getHistoricalPointerCoords", - "(IILandroid/view/MotionEvent$PointerCoords;)V", - &g_MotionEvent_getHistoricalPointerCoords); - - env->CallVoidMethod(obj.obj(), - method_id, as_jint(p0), as_jint(p1), p2.obj()); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_getEdgeFlags = 0; -static jint Java_MotionEvent_getEdgeFlags(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_MotionEvent_getEdgeFlags(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "getEdgeFlags", - "()I", - &g_MotionEvent_getEdgeFlags); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_setEdgeFlags = 0; -static void Java_MotionEvent_setEdgeFlags(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static void Java_MotionEvent_setEdgeFlags(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "setEdgeFlags", - "(I)V", - &g_MotionEvent_setEdgeFlags); - - env->CallVoidMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_setAction = 0; -static void Java_MotionEvent_setAction(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static void Java_MotionEvent_setAction(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "setAction", - "(I)V", - &g_MotionEvent_setAction); - - env->CallVoidMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_offsetLocation = 0; -static void Java_MotionEvent_offsetLocation(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jfloat p0, - jfloat p1) __attribute__ ((unused)); -static void Java_MotionEvent_offsetLocation(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jfloat p0, - jfloat p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "offsetLocation", - "(FF)V", - &g_MotionEvent_offsetLocation); - - env->CallVoidMethod(obj.obj(), - method_id, p0, p1); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_setLocation = 0; -static void Java_MotionEvent_setLocation(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jfloat p0, - jfloat p1) __attribute__ ((unused)); -static void Java_MotionEvent_setLocation(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jfloat p0, - jfloat p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "setLocation", - "(FF)V", - &g_MotionEvent_setLocation); - - env->CallVoidMethod(obj.obj(), - method_id, p0, p1); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_transform = 0; -static void Java_MotionEvent_transform(JNIEnv* env, const - base::android::JavaRefOrBare& obj, const - base::android::JavaRefOrBare& p0) __attribute__ ((unused)); -static void Java_MotionEvent_transform(JNIEnv* env, const - base::android::JavaRefOrBare& obj, const - base::android::JavaRefOrBare& p0) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "transform", - "(Landroid/graphics/Matrix;)V", - &g_MotionEvent_transform); - - env->CallVoidMethod(obj.obj(), - method_id, p0.obj()); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_addBatchV_J_F_F_F_F_I = 0; -static void Java_MotionEvent_addBatchV_J_F_F_F_F_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jlong p0, - jfloat p1, - jfloat p2, - jfloat p3, - jfloat p4, - JniIntWrapper p5) __attribute__ ((unused)); -static void Java_MotionEvent_addBatchV_J_F_F_F_F_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jlong p0, - jfloat p1, - jfloat p2, - jfloat p3, - jfloat p4, - JniIntWrapper p5) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "addBatch", - "(JFFFFI)V", - &g_MotionEvent_addBatchV_J_F_F_F_F_I); - - env->CallVoidMethod(obj.obj(), - method_id, p0, p1, p2, p3, p4, as_jint(p5)); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_addBatchV_J_LAVMEPC_I = 0; -static void Java_MotionEvent_addBatchV_J_LAVMEPC_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jlong p0, - const base::android::JavaRefOrBare& p1, - JniIntWrapper p2) __attribute__ ((unused)); -static void Java_MotionEvent_addBatchV_J_LAVMEPC_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jlong p0, - const base::android::JavaRefOrBare& p1, - JniIntWrapper p2) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "addBatch", - "(J[Landroid/view/MotionEvent$PointerCoords;I)V", - &g_MotionEvent_addBatchV_J_LAVMEPC_I); - - env->CallVoidMethod(obj.obj(), - method_id, p0, p1.obj(), as_jint(p2)); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_MotionEvent_toString = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_toString(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_toString(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "toString", - "()Ljava/lang/String;", - &g_MotionEvent_toString); - - jstring ret = - static_cast(env->CallObjectMethod(obj.obj(), - method_id)); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_MotionEvent_actionToString = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_actionToString(JNIEnv* env, JniIntWrapper p0) __attribute__ - ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_actionToString(JNIEnv* env, JniIntWrapper p0) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "actionToString", - "(I)Ljava/lang/String;", - &g_MotionEvent_actionToString); - - jstring ret = - static_cast(env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, as_jint(p0))); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_MotionEvent_axisToString = 0; -static base::android::ScopedJavaLocalRef - Java_MotionEvent_axisToString(JNIEnv* env, JniIntWrapper p0) __attribute__ - ((unused)); -static base::android::ScopedJavaLocalRef - Java_MotionEvent_axisToString(JNIEnv* env, JniIntWrapper p0) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "axisToString", - "(I)Ljava/lang/String;", - &g_MotionEvent_axisToString); - - jstring ret = - static_cast(env->CallStaticObjectMethod(MotionEvent_clazz(env), - method_id, as_jint(p0))); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -static base::subtle::AtomicWord g_MotionEvent_axisFromString = 0; -static jint Java_MotionEvent_axisFromString(JNIEnv* env, const - base::android::JavaRefOrBare& p0) __attribute__ ((unused)); -static jint Java_MotionEvent_axisFromString(JNIEnv* env, const - base::android::JavaRefOrBare& p0) { - CHECK_CLAZZ(env, MotionEvent_clazz(env), - MotionEvent_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, MotionEvent_clazz(env), - "axisFromString", - "(Ljava/lang/String;)I", - &g_MotionEvent_axisFromString); - - jint ret = - env->CallStaticIntMethod(MotionEvent_clazz(env), - method_id, p0.obj()); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_MotionEvent_writeToParcel = 0; -static void Java_MotionEvent_writeToParcel(JNIEnv* env, const - base::android::JavaRefOrBare& obj, const - base::android::JavaRefOrBare& p0, - JniIntWrapper p1) __attribute__ ((unused)); -static void Java_MotionEvent_writeToParcel(JNIEnv* env, const - base::android::JavaRefOrBare& obj, const - base::android::JavaRefOrBare& p0, - JniIntWrapper p1) { - CHECK_CLAZZ(env, obj.obj(), - MotionEvent_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, MotionEvent_clazz(env), - "writeToParcel", - "(Landroid/os/Parcel;I)V", - &g_MotionEvent_writeToParcel); - - env->CallVoidMethod(obj.obj(), - method_id, p0.obj(), as_jint(p1)); - jni_generator::CheckException(env); -} - -// Step 3: RegisterNatives. - -} // namespace JNI_MotionEvent - -#endif // android_view_MotionEvent_JNI diff --git a/base/android/jni_generator/testFromJavaP.golden b/base/android/jni_generator/testFromJavaP.golden deleted file mode 100644 index 18a9430..0000000 --- a/base/android/jni_generator/testFromJavaP.golden +++ /dev/null @@ -1,260 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// java/io/InputStream - -#ifndef java_io_InputStream_JNI -#define java_io_InputStream_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kInputStreamClassPath[] = "java/io/InputStream"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_InputStream_clazz __attribute__((unused)) = 0; -#define InputStream_clazz(env) base::android::LazyGetClass(env, kInputStreamClassPath, &g_InputStream_clazz) - -} // namespace - -namespace JNI_InputStream { - -// Step 2: method stubs. - -static base::subtle::AtomicWord g_InputStream_available = 0; -static jint Java_InputStream_available(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_InputStream_available(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "available", - "()I", - &g_InputStream_available); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_InputStream_close = 0; -static void Java_InputStream_close(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static void Java_InputStream_close(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "close", - "()V", - &g_InputStream_close); - - env->CallVoidMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_InputStream_mark = 0; -static void Java_InputStream_mark(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) __attribute__ - ((unused)); -static void Java_InputStream_mark(JNIEnv* env, const - base::android::JavaRefOrBare& obj, JniIntWrapper p0) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "mark", - "(I)V", - &g_InputStream_mark); - - env->CallVoidMethod(obj.obj(), - method_id, as_jint(p0)); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_InputStream_markSupported = 0; -static jboolean Java_InputStream_markSupported(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jboolean Java_InputStream_markSupported(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env), false); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "markSupported", - "()Z", - &g_InputStream_markSupported); - - jboolean ret = - env->CallBooleanMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_InputStream_readI = 0; -static jint Java_InputStream_readI(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static jint Java_InputStream_readI(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "read", - "()I", - &g_InputStream_readI); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_InputStream_readI_AB = 0; -static jint Java_InputStream_readI_AB(JNIEnv* env, const - base::android::JavaRefOrBare& obj, const - base::android::JavaRefOrBare& p0) __attribute__ ((unused)); -static jint Java_InputStream_readI_AB(JNIEnv* env, const - base::android::JavaRefOrBare& obj, const - base::android::JavaRefOrBare& p0) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "read", - "([B)I", - &g_InputStream_readI_AB); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id, p0.obj()); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_InputStream_readI_AB_I_I = 0; -static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, const - base::android::JavaRefOrBare& p0, - JniIntWrapper p1, - JniIntWrapper p2) __attribute__ ((unused)); -static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, const - base::android::JavaRefOrBare& obj, const - base::android::JavaRefOrBare& p0, - JniIntWrapper p1, - JniIntWrapper p2) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "read", - "([BII)I", - &g_InputStream_readI_AB_I_I); - - jint ret = - env->CallIntMethod(obj.obj(), - method_id, p0.obj(), as_jint(p1), as_jint(p2)); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_InputStream_reset = 0; -static void Java_InputStream_reset(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static void Java_InputStream_reset(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "reset", - "()V", - &g_InputStream_reset); - - env->CallVoidMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); -} - -static base::subtle::AtomicWord g_InputStream_skip = 0; -static jlong Java_InputStream_skip(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jlong p0) __attribute__ - ((unused)); -static jlong Java_InputStream_skip(JNIEnv* env, const - base::android::JavaRefOrBare& obj, jlong p0) { - CHECK_CLAZZ(env, obj.obj(), - InputStream_clazz(env), 0); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "skip", - "(J)J", - &g_InputStream_skip); - - jlong ret = - env->CallLongMethod(obj.obj(), - method_id, p0); - jni_generator::CheckException(env); - return ret; -} - -static base::subtle::AtomicWord g_InputStream_Constructor = 0; -static base::android::ScopedJavaLocalRef - Java_InputStream_Constructor(JNIEnv* env) __attribute__ ((unused)); -static base::android::ScopedJavaLocalRef - Java_InputStream_Constructor(JNIEnv* env) { - CHECK_CLAZZ(env, InputStream_clazz(env), - InputStream_clazz(env), NULL); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, InputStream_clazz(env), - "", - "()V", - &g_InputStream_Constructor); - - jobject ret = - env->NewObject(InputStream_clazz(env), - method_id); - jni_generator::CheckException(env); - return base::android::ScopedJavaLocalRef(env, ret); -} - -// Step 3: RegisterNatives. - -} // namespace JNI_InputStream - -#endif // java_io_InputStream_JNI diff --git a/base/android/jni_generator/testFromJavaPGenerics.golden b/base/android/jni_generator/testFromJavaPGenerics.golden deleted file mode 100644 index c076c39..0000000 --- a/base/android/jni_generator/testFromJavaPGenerics.golden +++ /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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// java/util/HashSet - -#ifndef java_util_HashSet_JNI -#define java_util_HashSet_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kHashSetClassPath[] = "java/util/HashSet"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_HashSet_clazz __attribute__((unused)) = 0; -#define HashSet_clazz(env) base::android::LazyGetClass(env, kHashSetClassPath, &g_HashSet_clazz) - -} // namespace - -namespace JNI_HashSet { - -// Step 2: method stubs. - -static base::subtle::AtomicWord g_HashSet_dummy = 0; -static void Java_HashSet_dummy(JNIEnv* env, const - base::android::JavaRefOrBare& obj) __attribute__ ((unused)); -static void Java_HashSet_dummy(JNIEnv* env, const - base::android::JavaRefOrBare& obj) { - CHECK_CLAZZ(env, obj.obj(), - HashSet_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_INSTANCE>( - env, HashSet_clazz(env), - "dummy", - "()V", - &g_HashSet_dummy); - - env->CallVoidMethod(obj.obj(), - method_id); - jni_generator::CheckException(env); -} - -// Step 3: RegisterNatives. - -} // namespace JNI_HashSet - -#endif // java_util_HashSet_JNI diff --git a/base/android/jni_generator/testInnerClassNatives.golden b/base/android/jni_generator/testInnerClassNatives.golden deleted file mode 100644 index 20b8830..0000000 --- a/base/android/jni_generator/testInnerClassNatives.golden +++ /dev/null @@ -1,71 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// org/chromium/TestJni - -#ifndef org_chromium_TestJni_JNI -#define org_chromium_TestJni_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kTestJniClassPath[] = "org/chromium/TestJni"; -const char kMyInnerClassClassPath[] = "org/chromium/TestJni$MyInnerClass"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_TestJni_clazz __attribute__((unused)) = 0; -#define TestJni_clazz(env) base::android::LazyGetClass(env, kTestJniClassPath, &g_TestJni_clazz) -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_MyInnerClass_clazz __attribute__((unused)) = 0; -#define MyInnerClass_clazz(env) base::android::LazyGetClass(env, kMyInnerClassClassPath, &g_MyInnerClass_clazz) - -} // namespace - -// Step 2: method stubs. - -static jint Init(JNIEnv* env, const base::android::JavaParamRef& - jcaller); - -JNI_GENERATOR_EXPORT jint - Java_org_chromium_TestJni_00024MyInnerClass_nativeInit(JNIEnv* env, jobject - jcaller) { - return Init(env, base::android::JavaParamRef(env, jcaller)); -} - -// Step 3: RegisterNatives. - -static const JNINativeMethod kMethodsMyInnerClass[] = { - { "nativeInit", -"(" -")" -"I", - reinterpret_cast(Java_org_chromium_TestJni_00024MyInnerClass_nativeInit) - }, -}; - -static bool RegisterNativesImpl(JNIEnv* env) { - if (jni_generator::ShouldSkipJniRegistration(false)) - return true; - - const int kMethodsMyInnerClassSize = arraysize(kMethodsMyInnerClass); - - if (env->RegisterNatives(MyInnerClass_clazz(env), - kMethodsMyInnerClass, - kMethodsMyInnerClassSize) < 0) { - jni_generator::HandleRegistrationError( - env, MyInnerClass_clazz(env), __FILE__); - return false; - } - - return true; -} - -#endif // org_chromium_TestJni_JNI diff --git a/base/android/jni_generator/testInnerClassNativesBothInnerAndOuter.golden b/base/android/jni_generator/testInnerClassNativesBothInnerAndOuter.golden deleted file mode 100644 index 67352e7..0000000 --- a/base/android/jni_generator/testInnerClassNativesBothInnerAndOuter.golden +++ /dev/null @@ -1,98 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// org/chromium/TestJni - -#ifndef org_chromium_TestJni_JNI -#define org_chromium_TestJni_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kMyOtherInnerClassClassPath[] = - "org/chromium/TestJni$MyOtherInnerClass"; -const char kTestJniClassPath[] = "org/chromium/TestJni"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_MyOtherInnerClass_clazz __attribute__((unused)) = 0; -#define MyOtherInnerClass_clazz(env) base::android::LazyGetClass(env, kMyOtherInnerClassClassPath, &g_MyOtherInnerClass_clazz) -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_TestJni_clazz __attribute__((unused)) = 0; -#define TestJni_clazz(env) base::android::LazyGetClass(env, kTestJniClassPath, &g_TestJni_clazz) - -} // namespace - -// Step 2: method stubs. - -static jint Init(JNIEnv* env, const base::android::JavaParamRef& - jcaller); - -JNI_GENERATOR_EXPORT jint Java_org_chromium_TestJni_nativeInit(JNIEnv* env, - jobject jcaller) { - return Init(env, base::android::JavaParamRef(env, jcaller)); -} - -static jint Init(JNIEnv* env, const base::android::JavaParamRef& - jcaller); - -JNI_GENERATOR_EXPORT jint - Java_org_chromium_TestJni_00024MyOtherInnerClass_nativeInit(JNIEnv* env, - jobject jcaller) { - return Init(env, base::android::JavaParamRef(env, jcaller)); -} - -// Step 3: RegisterNatives. - -static const JNINativeMethod kMethodsMyOtherInnerClass[] = { - { "nativeInit", -"(" -")" -"I", - reinterpret_cast(Java_org_chromium_TestJni_00024MyOtherInnerClass_nativeInit) - }, -}; - -static const JNINativeMethod kMethodsTestJni[] = { - { "nativeInit", -"(" -")" -"I", reinterpret_cast(Java_org_chromium_TestJni_nativeInit) }, -}; - -static bool RegisterNativesImpl(JNIEnv* env) { - if (jni_generator::ShouldSkipJniRegistration(false)) - return true; - - const int kMethodsMyOtherInnerClassSize = - arraysize(kMethodsMyOtherInnerClass); - - if (env->RegisterNatives(MyOtherInnerClass_clazz(env), - kMethodsMyOtherInnerClass, - kMethodsMyOtherInnerClassSize) < 0) { - jni_generator::HandleRegistrationError( - env, MyOtherInnerClass_clazz(env), __FILE__); - return false; - } - - const int kMethodsTestJniSize = arraysize(kMethodsTestJni); - - if (env->RegisterNatives(TestJni_clazz(env), - kMethodsTestJni, - kMethodsTestJniSize) < 0) { - jni_generator::HandleRegistrationError( - env, TestJni_clazz(env), __FILE__); - return false; - } - - return true; -} - -#endif // org_chromium_TestJni_JNI diff --git a/base/android/jni_generator/testInnerClassNativesMultiple.golden b/base/android/jni_generator/testInnerClassNativesMultiple.golden deleted file mode 100644 index 7807efa..0000000 --- a/base/android/jni_generator/testInnerClassNativesMultiple.golden +++ /dev/null @@ -1,105 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// org/chromium/TestJni - -#ifndef org_chromium_TestJni_JNI -#define org_chromium_TestJni_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kMyOtherInnerClassClassPath[] = - "org/chromium/TestJni$MyOtherInnerClass"; -const char kTestJniClassPath[] = "org/chromium/TestJni"; -const char kMyInnerClassClassPath[] = "org/chromium/TestJni$MyInnerClass"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_MyOtherInnerClass_clazz __attribute__((unused)) = 0; -#define MyOtherInnerClass_clazz(env) base::android::LazyGetClass(env, kMyOtherInnerClassClassPath, &g_MyOtherInnerClass_clazz) -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_TestJni_clazz __attribute__((unused)) = 0; -#define TestJni_clazz(env) base::android::LazyGetClass(env, kTestJniClassPath, &g_TestJni_clazz) -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_MyInnerClass_clazz __attribute__((unused)) = 0; -#define MyInnerClass_clazz(env) base::android::LazyGetClass(env, kMyInnerClassClassPath, &g_MyInnerClass_clazz) - -} // namespace - -// Step 2: method stubs. - -static jint Init(JNIEnv* env, const base::android::JavaParamRef& - jcaller); - -JNI_GENERATOR_EXPORT jint - Java_org_chromium_TestJni_00024MyInnerClass_nativeInit(JNIEnv* env, jobject - jcaller) { - return Init(env, base::android::JavaParamRef(env, jcaller)); -} - -static jint Init(JNIEnv* env, const base::android::JavaParamRef& - jcaller); - -JNI_GENERATOR_EXPORT jint - Java_org_chromium_TestJni_00024MyOtherInnerClass_nativeInit(JNIEnv* env, - jobject jcaller) { - return Init(env, base::android::JavaParamRef(env, jcaller)); -} - -// Step 3: RegisterNatives. - -static const JNINativeMethod kMethodsMyOtherInnerClass[] = { - { "nativeInit", -"(" -")" -"I", - reinterpret_cast(Java_org_chromium_TestJni_00024MyOtherInnerClass_nativeInit) - }, -}; - -static const JNINativeMethod kMethodsMyInnerClass[] = { - { "nativeInit", -"(" -")" -"I", - reinterpret_cast(Java_org_chromium_TestJni_00024MyInnerClass_nativeInit) - }, -}; - -static bool RegisterNativesImpl(JNIEnv* env) { - if (jni_generator::ShouldSkipJniRegistration(false)) - return true; - - const int kMethodsMyOtherInnerClassSize = - arraysize(kMethodsMyOtherInnerClass); - - if (env->RegisterNatives(MyOtherInnerClass_clazz(env), - kMethodsMyOtherInnerClass, - kMethodsMyOtherInnerClassSize) < 0) { - jni_generator::HandleRegistrationError( - env, MyOtherInnerClass_clazz(env), __FILE__); - return false; - } - - const int kMethodsMyInnerClassSize = arraysize(kMethodsMyInnerClass); - - if (env->RegisterNatives(MyInnerClass_clazz(env), - kMethodsMyInnerClass, - kMethodsMyInnerClassSize) < 0) { - jni_generator::HandleRegistrationError( - env, MyInnerClass_clazz(env), __FILE__); - return false; - } - - return true; -} - -#endif // org_chromium_TestJni_JNI diff --git a/base/android/jni_generator/testInputStream.javap b/base/android/jni_generator/testInputStream.javap deleted file mode 100644 index 50ab617..0000000 --- a/base/android/jni_generator/testInputStream.javap +++ /dev/null @@ -1,228 +0,0 @@ -Compiled from "InputStream.java" -public abstract class java.io.InputStream extends java.lang.Object implements java.io.Closeable - SourceFile: "InputStream.java" - minor version: 0 - major version: 49 - Constant pool: -const #1 = Method #6.#39; // java/lang/Object."":()V -const #2 = class #40; // java/lang/RuntimeException -const #3 = String #41; // Stub! -const #4 = Method #2.#42; // java/lang/RuntimeException."":(Ljava/lang/String;)V -const #5 = class #43; // java/io/InputStream -const #6 = class #44; // java/lang/Object -const #7 = class #45; // java/io/Closeable -const #8 = Asciz ; -const #9 = Asciz ()V; -const #10 = Asciz Code; -const #11 = Asciz LineNumberTable; -const #12 = Asciz LocalVariableTable; -const #13 = Asciz this; -const #14 = Asciz Ljava/io/InputStream;; -const #15 = Asciz available; -const #16 = Asciz ()I; -const #17 = Asciz Exceptions; -const #18 = class #46; // java/io/IOException -const #19 = Asciz close; -const #20 = Asciz mark; -const #21 = Asciz (I)V; -const #22 = Asciz readlimit; -const #23 = Asciz I; -const #24 = Asciz markSupported; -const #25 = Asciz ()Z; -const #26 = Asciz read; -const #27 = Asciz ([B)I; -const #28 = Asciz buffer; -const #29 = Asciz [B; -const #30 = Asciz ([BII)I; -const #31 = Asciz byteOffset; -const #32 = Asciz byteCount; -const #33 = Asciz reset; -const #34 = Asciz skip; -const #35 = Asciz (J)J; -const #36 = Asciz J; -const #37 = Asciz SourceFile; -const #38 = Asciz InputStream.java; -const #39 = NameAndType #8:#9;// "":()V -const #40 = Asciz java/lang/RuntimeException; -const #41 = Asciz Stub!; -const #42 = NameAndType #8:#47;// "":(Ljava/lang/String;)V -const #43 = Asciz java/io/InputStream; -const #44 = Asciz java/lang/Object; -const #45 = Asciz java/io/Closeable; -const #46 = Asciz java/io/IOException; -const #47 = Asciz (Ljava/lang/String;)V; - -{ -public java.io.InputStream(); - Signature: ()V - Code: - Stack=3, Locals=1, Args_size=1 - 0: aload_0 - 1: invokespecial #1; //Method java/lang/Object."":()V - 4: new #2; //class java/lang/RuntimeException - 7: dup - 8: ldc #3; //String Stub! - 10: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 13: athrow - LineNumberTable: - line 5: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 14 0 this Ljava/io/InputStream; - - -public int available() throws java.io.IOException; - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 6: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Ljava/io/InputStream; - - Exceptions: - throws java.io.IOException -public void close() throws java.io.IOException; - Signature: ()V - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 7: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Ljava/io/InputStream; - - Exceptions: - throws java.io.IOException -public void mark(int); - Signature: (I)V - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 8: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Ljava/io/InputStream; - 0 10 1 readlimit I - - -public boolean markSupported(); - Signature: ()Z - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 9: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Ljava/io/InputStream; - - -public abstract int read() throws java.io.IOException; - Signature: ()I - Exceptions: - throws java.io.IOException -public int read(byte[]) throws java.io.IOException; - Signature: ([B)I - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 11: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Ljava/io/InputStream; - 0 10 1 buffer [B - - Exceptions: - throws java.io.IOException -public int read(byte[], int, int) throws java.io.IOException; - Signature: ([BII)I - Code: - Stack=3, Locals=4, Args_size=4 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 12: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Ljava/io/InputStream; - 0 10 1 buffer [B - 0 10 2 byteOffset I - 0 10 3 byteCount I - - Exceptions: - throws java.io.IOException -public synchronized void reset() throws java.io.IOException; - Signature: ()V - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 13: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Ljava/io/InputStream; - - Exceptions: - throws java.io.IOException -public long skip(long) throws java.io.IOException; - Signature: (J)J - Code: - Stack=3, Locals=3, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 14: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Ljava/io/InputStream; - 0 10 1 byteCount J - - Exceptions: - throws java.io.IOException -} - diff --git a/base/android/jni_generator/testMotionEvent.javap b/base/android/jni_generator/testMotionEvent.javap deleted file mode 100644 index 0746943..0000000 --- a/base/android/jni_generator/testMotionEvent.javap +++ /dev/null @@ -1,2295 +0,0 @@ -Compiled from "MotionEvent.java" -public final class android.view.MotionEvent extends android.view.InputEvent implements android.os.Parcelable - SourceFile: "MotionEvent.java" - InnerClass: - public final #10= #9 of #6; //PointerProperties=class android/view/MotionEvent$PointerProperties of class android/view/MotionEvent - public final #13= #12 of #6; //PointerCoords=class android/view/MotionEvent$PointerCoords of class android/view/MotionEvent - public abstract #150= #149 of #8; //Creator=class android/os/Parcelable$Creator of class android/os/Parcelable - minor version: 0 - major version: 49 - Constant pool: -const #1 = Method #7.#293; // android/view/InputEvent."":()V -const #2 = class #294; // java/lang/RuntimeException -const #3 = String #295; // Stub! -const #4 = Method #2.#296; // java/lang/RuntimeException."":(Ljava/lang/String;)V -const #5 = Field #6.#297; // android/view/MotionEvent.CREATOR:Landroid/os/Parcelable$Creator; -const #6 = class #298; // android/view/MotionEvent -const #7 = class #299; // android/view/InputEvent -const #8 = class #300; // android/os/Parcelable -const #9 = class #301; // android/view/MotionEvent$PointerProperties -const #10 = Asciz PointerProperties; -const #11 = Asciz InnerClasses; -const #12 = class #302; // android/view/MotionEvent$PointerCoords -const #13 = Asciz PointerCoords; -const #14 = Asciz INVALID_POINTER_ID; -const #15 = Asciz I; -const #16 = Asciz ConstantValue; -const #17 = int -1; -const #18 = Asciz ACTION_MASK; -const #19 = int 255; -const #20 = Asciz ACTION_DOWN; -const #21 = int 0; -const #22 = Asciz ACTION_UP; -const #23 = int 1; -const #24 = Asciz ACTION_MOVE; -const #25 = int 2; -const #26 = Asciz ACTION_CANCEL; -const #27 = int 3; -const #28 = Asciz ACTION_OUTSIDE; -const #29 = int 4; -const #30 = Asciz ACTION_POINTER_DOWN; -const #31 = int 5; -const #32 = Asciz ACTION_POINTER_UP; -const #33 = int 6; -const #34 = Asciz ACTION_HOVER_MOVE; -const #35 = int 7; -const #36 = Asciz ACTION_SCROLL; -const #37 = int 8; -const #38 = Asciz ACTION_HOVER_ENTER; -const #39 = int 9; -const #40 = Asciz ACTION_HOVER_EXIT; -const #41 = int 10; -const #42 = Asciz ACTION_POINTER_INDEX_MASK; -const #43 = int 65280; -const #44 = Asciz ACTION_POINTER_INDEX_SHIFT; -const #45 = Asciz ACTION_POINTER_1_DOWN; -const #46 = Asciz Deprecated; -const #47 = Asciz RuntimeVisibleAnnotations; -const #48 = Asciz Ljava/lang/Deprecated;; -const #49 = Asciz ACTION_POINTER_2_DOWN; -const #50 = int 261; -const #51 = Asciz ACTION_POINTER_3_DOWN; -const #52 = int 517; -const #53 = Asciz ACTION_POINTER_1_UP; -const #54 = Asciz ACTION_POINTER_2_UP; -const #55 = int 262; -const #56 = Asciz ACTION_POINTER_3_UP; -const #57 = int 518; -const #58 = Asciz ACTION_POINTER_ID_MASK; -const #59 = Asciz ACTION_POINTER_ID_SHIFT; -const #60 = Asciz FLAG_WINDOW_IS_OBSCURED; -const #61 = Asciz EDGE_TOP; -const #62 = Asciz EDGE_BOTTOM; -const #63 = Asciz EDGE_LEFT; -const #64 = Asciz EDGE_RIGHT; -const #65 = Asciz AXIS_X; -const #66 = Asciz AXIS_Y; -const #67 = Asciz AXIS_PRESSURE; -const #68 = Asciz AXIS_SIZE; -const #69 = Asciz AXIS_TOUCH_MAJOR; -const #70 = Asciz AXIS_TOUCH_MINOR; -const #71 = Asciz AXIS_TOOL_MAJOR; -const #72 = Asciz AXIS_TOOL_MINOR; -const #73 = Asciz AXIS_ORIENTATION; -const #74 = Asciz AXIS_VSCROLL; -const #75 = Asciz AXIS_HSCROLL; -const #76 = Asciz AXIS_Z; -const #77 = int 11; -const #78 = Asciz AXIS_RX; -const #79 = int 12; -const #80 = Asciz AXIS_RY; -const #81 = int 13; -const #82 = Asciz AXIS_RZ; -const #83 = int 14; -const #84 = Asciz AXIS_HAT_X; -const #85 = int 15; -const #86 = Asciz AXIS_HAT_Y; -const #87 = int 16; -const #88 = Asciz AXIS_LTRIGGER; -const #89 = int 17; -const #90 = Asciz AXIS_RTRIGGER; -const #91 = int 18; -const #92 = Asciz AXIS_THROTTLE; -const #93 = int 19; -const #94 = Asciz AXIS_RUDDER; -const #95 = int 20; -const #96 = Asciz AXIS_WHEEL; -const #97 = int 21; -const #98 = Asciz AXIS_GAS; -const #99 = int 22; -const #100 = Asciz AXIS_BRAKE; -const #101 = int 23; -const #102 = Asciz AXIS_DISTANCE; -const #103 = int 24; -const #104 = Asciz AXIS_TILT; -const #105 = int 25; -const #106 = Asciz AXIS_GENERIC_1; -const #107 = int 32; -const #108 = Asciz AXIS_GENERIC_2; -const #109 = int 33; -const #110 = Asciz AXIS_GENERIC_3; -const #111 = int 34; -const #112 = Asciz AXIS_GENERIC_4; -const #113 = int 35; -const #114 = Asciz AXIS_GENERIC_5; -const #115 = int 36; -const #116 = Asciz AXIS_GENERIC_6; -const #117 = int 37; -const #118 = Asciz AXIS_GENERIC_7; -const #119 = int 38; -const #120 = Asciz AXIS_GENERIC_8; -const #121 = int 39; -const #122 = Asciz AXIS_GENERIC_9; -const #123 = int 40; -const #124 = Asciz AXIS_GENERIC_10; -const #125 = int 41; -const #126 = Asciz AXIS_GENERIC_11; -const #127 = int 42; -const #128 = Asciz AXIS_GENERIC_12; -const #129 = int 43; -const #130 = Asciz AXIS_GENERIC_13; -const #131 = int 44; -const #132 = Asciz AXIS_GENERIC_14; -const #133 = int 45; -const #134 = Asciz AXIS_GENERIC_15; -const #135 = int 46; -const #136 = Asciz AXIS_GENERIC_16; -const #137 = int 47; -const #138 = Asciz BUTTON_PRIMARY; -const #139 = Asciz BUTTON_SECONDARY; -const #140 = Asciz BUTTON_TERTIARY; -const #141 = Asciz BUTTON_BACK; -const #142 = Asciz BUTTON_FORWARD; -const #143 = Asciz TOOL_TYPE_UNKNOWN; -const #144 = Asciz TOOL_TYPE_FINGER; -const #145 = Asciz TOOL_TYPE_STYLUS; -const #146 = Asciz TOOL_TYPE_MOUSE; -const #147 = Asciz TOOL_TYPE_ERASER; -const #148 = Asciz CREATOR; -const #149 = class #303; // android/os/Parcelable$Creator -const #150 = Asciz Creator; -const #151 = Asciz Landroid/os/Parcelable$Creator;; -const #152 = Asciz Signature; -const #153 = Asciz Landroid/os/Parcelable$Creator;; -const #154 = Asciz ; -const #155 = Asciz ()V; -const #156 = Asciz Code; -const #157 = Asciz LineNumberTable; -const #158 = Asciz LocalVariableTable; -const #159 = Asciz this; -const #160 = Asciz Landroid/view/MotionEvent;; -const #161 = Asciz finalize; -const #162 = Asciz Exceptions; -const #163 = class #304; // java/lang/Throwable -const #164 = Asciz obtain; -const #165 = Asciz (JJII[Landroid/view/MotionEvent$PointerProperties;[Landroid/view/MotionEvent$PointerCoords;IIFFIIII)Landroid/view/MotionEvent;; -const #166 = Asciz downTime; -const #167 = Asciz J; -const #168 = Asciz eventTime; -const #169 = Asciz action; -const #170 = Asciz pointerCount; -const #171 = Asciz pointerProperties; -const #172 = Asciz [Landroid/view/MotionEvent$PointerProperties;; -const #173 = Asciz pointerCoords; -const #174 = Asciz [Landroid/view/MotionEvent$PointerCoords;; -const #175 = Asciz metaState; -const #176 = Asciz buttonState; -const #177 = Asciz xPrecision; -const #178 = Asciz F; -const #179 = Asciz yPrecision; -const #180 = Asciz deviceId; -const #181 = Asciz edgeFlags; -const #182 = Asciz source; -const #183 = Asciz flags; -const #184 = Asciz (JJII[I[Landroid/view/MotionEvent$PointerCoords;IFFIIII)Landroid/view/MotionEvent;; -const #185 = Asciz pointerIds; -const #186 = Asciz [I; -const #187 = Asciz (JJIFFFFIFFII)Landroid/view/MotionEvent;; -const #188 = Asciz x; -const #189 = Asciz y; -const #190 = Asciz pressure; -const #191 = Asciz size; -const #192 = Asciz (JJIIFFFFIFFII)Landroid/view/MotionEvent;; -const #193 = Asciz (JJIFFI)Landroid/view/MotionEvent;; -const #194 = Asciz (Landroid/view/MotionEvent;)Landroid/view/MotionEvent;; -const #195 = Asciz other; -const #196 = Asciz obtainNoHistory; -const #197 = Asciz recycle; -const #198 = Asciz getDeviceId; -const #199 = Asciz ()I; -const #200 = Asciz getSource; -const #201 = Asciz setSource; -const #202 = Asciz (I)V; -const #203 = Asciz getAction; -const #204 = Asciz getActionMasked; -const #205 = Asciz getActionIndex; -const #206 = Asciz getFlags; -const #207 = Asciz getDownTime; -const #208 = Asciz ()J; -const #209 = Asciz getEventTime; -const #210 = Asciz getX; -const #211 = Asciz ()F; -const #212 = Asciz getY; -const #213 = Asciz getPressure; -const #214 = Asciz getSize; -const #215 = Asciz getTouchMajor; -const #216 = Asciz getTouchMinor; -const #217 = Asciz getToolMajor; -const #218 = Asciz getToolMinor; -const #219 = Asciz getOrientation; -const #220 = Asciz getAxisValue; -const #221 = Asciz (I)F; -const #222 = Asciz axis; -const #223 = Asciz getPointerCount; -const #224 = Asciz getPointerId; -const #225 = Asciz (I)I; -const #226 = Asciz pointerIndex; -const #227 = Asciz getToolType; -const #228 = Asciz findPointerIndex; -const #229 = Asciz pointerId; -const #230 = Asciz (II)F; -const #231 = Asciz getPointerCoords; -const #232 = Asciz (ILandroid/view/MotionEvent$PointerCoords;)V; -const #233 = Asciz outPointerCoords; -const #234 = Asciz Landroid/view/MotionEvent$PointerCoords;; -const #235 = Asciz getPointerProperties; -const #236 = Asciz (ILandroid/view/MotionEvent$PointerProperties;)V; -const #237 = Asciz outPointerProperties; -const #238 = Asciz Landroid/view/MotionEvent$PointerProperties;; -const #239 = Asciz getMetaState; -const #240 = Asciz getButtonState; -const #241 = Asciz getRawX; -const #242 = Asciz getRawY; -const #243 = Asciz getXPrecision; -const #244 = Asciz getYPrecision; -const #245 = Asciz getHistorySize; -const #246 = Asciz getHistoricalEventTime; -const #247 = Asciz (I)J; -const #248 = Asciz pos; -const #249 = Asciz getHistoricalX; -const #250 = Asciz getHistoricalY; -const #251 = Asciz getHistoricalPressure; -const #252 = Asciz getHistoricalSize; -const #253 = Asciz getHistoricalTouchMajor; -const #254 = Asciz getHistoricalTouchMinor; -const #255 = Asciz getHistoricalToolMajor; -const #256 = Asciz getHistoricalToolMinor; -const #257 = Asciz getHistoricalOrientation; -const #258 = Asciz getHistoricalAxisValue; -const #259 = Asciz (III)F; -const #260 = Asciz getHistoricalPointerCoords; -const #261 = Asciz (IILandroid/view/MotionEvent$PointerCoords;)V; -const #262 = Asciz getEdgeFlags; -const #263 = Asciz setEdgeFlags; -const #264 = Asciz setAction; -const #265 = Asciz offsetLocation; -const #266 = Asciz (FF)V; -const #267 = Asciz deltaX; -const #268 = Asciz deltaY; -const #269 = Asciz setLocation; -const #270 = Asciz transform; -const #271 = Asciz (Landroid/graphics/Matrix;)V; -const #272 = Asciz matrix; -const #273 = Asciz Landroid/graphics/Matrix;; -const #274 = Asciz addBatch; -const #275 = Asciz (JFFFFI)V; -const #276 = Asciz (J[Landroid/view/MotionEvent$PointerCoords;I)V; -const #277 = Asciz toString; -const #278 = Asciz ()Ljava/lang/String;; -const #279 = Asciz actionToString; -const #280 = Asciz (I)Ljava/lang/String;; -const #281 = Asciz axisToString; -const #282 = Asciz axisFromString; -const #283 = Asciz (Ljava/lang/String;)I; -const #284 = Asciz symbolicName; -const #285 = Asciz Ljava/lang/String;; -const #286 = Asciz writeToParcel; -const #287 = Asciz (Landroid/os/Parcel;I)V; -const #288 = Asciz out; -const #289 = Asciz Landroid/os/Parcel;; -const #290 = Asciz ; -const #291 = Asciz SourceFile; -const #292 = Asciz MotionEvent.java; -const #293 = NameAndType #154:#155;// "":()V -const #294 = Asciz java/lang/RuntimeException; -const #295 = Asciz Stub!; -const #296 = NameAndType #154:#305;// "":(Ljava/lang/String;)V -const #297 = NameAndType #148:#151;// CREATOR:Landroid/os/Parcelable$Creator; -const #298 = Asciz android/view/MotionEvent; -const #299 = Asciz android/view/InputEvent; -const #300 = Asciz android/os/Parcelable; -const #301 = Asciz android/view/MotionEvent$PointerProperties; -const #302 = Asciz android/view/MotionEvent$PointerCoords; -const #303 = Asciz android/os/Parcelable$Creator; -const #304 = Asciz java/lang/Throwable; -const #305 = Asciz (Ljava/lang/String;)V; - -{ -public static final int INVALID_POINTER_ID; - Signature: I - Constant value: int -1 - -public static final int ACTION_MASK; - Signature: I - Constant value: int 255 - -public static final int ACTION_DOWN; - Signature: I - Constant value: int 0 - -public static final int ACTION_UP; - Signature: I - Constant value: int 1 - -public static final int ACTION_MOVE; - Signature: I - Constant value: int 2 - -public static final int ACTION_CANCEL; - Signature: I - Constant value: int 3 - -public static final int ACTION_OUTSIDE; - Signature: I - Constant value: int 4 - -public static final int ACTION_POINTER_DOWN; - Signature: I - Constant value: int 5 - -public static final int ACTION_POINTER_UP; - Signature: I - Constant value: int 6 - -public static final int ACTION_HOVER_MOVE; - Signature: I - Constant value: int 7 - -public static final int ACTION_SCROLL; - Signature: I - Constant value: int 8 - -public static final int ACTION_HOVER_ENTER; - Signature: I - Constant value: int 9 - -public static final int ACTION_HOVER_EXIT; - Signature: I - Constant value: int 10 - -public static final int ACTION_POINTER_INDEX_MASK; - Signature: I - Constant value: int 65280 - -public static final int ACTION_POINTER_INDEX_SHIFT; - Signature: I - Constant value: int 8 - -public static final int ACTION_POINTER_1_DOWN; - Signature: I - Constant value: int 5Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - - -public static final int ACTION_POINTER_2_DOWN; - Signature: I - Constant value: int 261Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - - -public static final int ACTION_POINTER_3_DOWN; - Signature: I - Constant value: int 517Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - - -public static final int ACTION_POINTER_1_UP; - Signature: I - Constant value: int 6Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - - -public static final int ACTION_POINTER_2_UP; - Signature: I - Constant value: int 262Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - - -public static final int ACTION_POINTER_3_UP; - Signature: I - Constant value: int 518Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - - -public static final int ACTION_POINTER_ID_MASK; - Signature: I - Constant value: int 65280Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - - -public static final int ACTION_POINTER_ID_SHIFT; - Signature: I - Constant value: int 8Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - - -public static final int FLAG_WINDOW_IS_OBSCURED; - Signature: I - Constant value: int 1 - -public static final int EDGE_TOP; - Signature: I - Constant value: int 1 - -public static final int EDGE_BOTTOM; - Signature: I - Constant value: int 2 - -public static final int EDGE_LEFT; - Signature: I - Constant value: int 4 - -public static final int EDGE_RIGHT; - Signature: I - Constant value: int 8 - -public static final int AXIS_X; - Signature: I - Constant value: int 0 - -public static final int AXIS_Y; - Signature: I - Constant value: int 1 - -public static final int AXIS_PRESSURE; - Signature: I - Constant value: int 2 - -public static final int AXIS_SIZE; - Signature: I - Constant value: int 3 - -public static final int AXIS_TOUCH_MAJOR; - Signature: I - Constant value: int 4 - -public static final int AXIS_TOUCH_MINOR; - Signature: I - Constant value: int 5 - -public static final int AXIS_TOOL_MAJOR; - Signature: I - Constant value: int 6 - -public static final int AXIS_TOOL_MINOR; - Signature: I - Constant value: int 7 - -public static final int AXIS_ORIENTATION; - Signature: I - Constant value: int 8 - -public static final int AXIS_VSCROLL; - Signature: I - Constant value: int 9 - -public static final int AXIS_HSCROLL; - Signature: I - Constant value: int 10 - -public static final int AXIS_Z; - Signature: I - Constant value: int 11 - -public static final int AXIS_RX; - Signature: I - Constant value: int 12 - -public static final int AXIS_RY; - Signature: I - Constant value: int 13 - -public static final int AXIS_RZ; - Signature: I - Constant value: int 14 - -public static final int AXIS_HAT_X; - Signature: I - Constant value: int 15 - -public static final int AXIS_HAT_Y; - Signature: I - Constant value: int 16 - -public static final int AXIS_LTRIGGER; - Signature: I - Constant value: int 17 - -public static final int AXIS_RTRIGGER; - Signature: I - Constant value: int 18 - -public static final int AXIS_THROTTLE; - Signature: I - Constant value: int 19 - -public static final int AXIS_RUDDER; - Signature: I - Constant value: int 20 - -public static final int AXIS_WHEEL; - Signature: I - Constant value: int 21 - -public static final int AXIS_GAS; - Signature: I - Constant value: int 22 - -public static final int AXIS_BRAKE; - Signature: I - Constant value: int 23 - -public static final int AXIS_DISTANCE; - Signature: I - Constant value: int 24 - -public static final int AXIS_TILT; - Signature: I - Constant value: int 25 - -public static final int AXIS_GENERIC_1; - Signature: I - Constant value: int 32 - -public static final int AXIS_GENERIC_2; - Signature: I - Constant value: int 33 - -public static final int AXIS_GENERIC_3; - Signature: I - Constant value: int 34 - -public static final int AXIS_GENERIC_4; - Signature: I - Constant value: int 35 - -public static final int AXIS_GENERIC_5; - Signature: I - Constant value: int 36 - -public static final int AXIS_GENERIC_6; - Signature: I - Constant value: int 37 - -public static final int AXIS_GENERIC_7; - Signature: I - Constant value: int 38 - -public static final int AXIS_GENERIC_8; - Signature: I - Constant value: int 39 - -public static final int AXIS_GENERIC_9; - Signature: I - Constant value: int 40 - -public static final int AXIS_GENERIC_10; - Signature: I - Constant value: int 41 - -public static final int AXIS_GENERIC_11; - Signature: I - Constant value: int 42 - -public static final int AXIS_GENERIC_12; - Signature: I - Constant value: int 43 - -public static final int AXIS_GENERIC_13; - Signature: I - Constant value: int 44 - -public static final int AXIS_GENERIC_14; - Signature: I - Constant value: int 45 - -public static final int AXIS_GENERIC_15; - Signature: I - Constant value: int 46 - -public static final int AXIS_GENERIC_16; - Signature: I - Constant value: int 47 - -public static final int BUTTON_PRIMARY; - Signature: I - Constant value: int 1 - -public static final int BUTTON_SECONDARY; - Signature: I - Constant value: int 2 - -public static final int BUTTON_TERTIARY; - Signature: I - Constant value: int 4 - -public static final int BUTTON_BACK; - Signature: I - Constant value: int 8 - -public static final int BUTTON_FORWARD; - Signature: I - Constant value: int 16 - -public static final int TOOL_TYPE_UNKNOWN; - Signature: I - Constant value: int 0 - -public static final int TOOL_TYPE_FINGER; - Signature: I - Constant value: int 1 - -public static final int TOOL_TYPE_STYLUS; - Signature: I - Constant value: int 2 - -public static final int TOOL_TYPE_MOUSE; - Signature: I - Constant value: int 3 - -public static final int TOOL_TYPE_ERASER; - Signature: I - Constant value: int 4 - -public static final android.os.Parcelable$Creator CREATOR; - Signature: Landroid/os/Parcelable$Creator; - Signature: length = 0x2 - 00 FFFFFF99 - - -android.view.MotionEvent(); - Signature: ()V - Code: - Stack=3, Locals=1, Args_size=1 - 0: aload_0 - 1: invokespecial #1; //Method android/view/InputEvent."":()V - 4: new #2; //class java/lang/RuntimeException - 7: dup - 8: ldc #3; //String Stub! - 10: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 13: athrow - LineNumberTable: - line 35: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 14 0 this Landroid/view/MotionEvent; - - -protected void finalize() throws java.lang.Throwable; - Signature: ()V - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 36: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - Exceptions: - throws java.lang.Throwable -public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent$PointerProperties[], android.view.MotionEvent$PointerCoords[], int, int, float, float, int, int, int, int); - Signature: (JJII[Landroid/view/MotionEvent$PointerProperties;[Landroid/view/MotionEvent$PointerCoords;IIFFIIII)Landroid/view/MotionEvent; - Code: - Stack=3, Locals=16, Args_size=14 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 37: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 pointerCount I - 0 10 6 pointerProperties [Landroid/view/MotionEvent$PointerProperties; - 0 10 7 pointerCoords [Landroid/view/MotionEvent$PointerCoords; - 0 10 8 metaState I - 0 10 9 buttonState I - 0 10 10 xPrecision F - 0 10 11 yPrecision F - 0 10 12 deviceId I - 0 10 13 edgeFlags I - 0 10 14 source I - 0 10 15 flags I - - -public static android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent$PointerCoords[], int, float, float, int, int, int, int); - Signature: (JJII[I[Landroid/view/MotionEvent$PointerCoords;IFFIIII)Landroid/view/MotionEvent; - Code: - Stack=3, Locals=15, Args_size=13 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 39: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 pointerCount I - 0 10 6 pointerIds [I - 0 10 7 pointerCoords [Landroid/view/MotionEvent$PointerCoords; - 0 10 8 metaState I - 0 10 9 xPrecision F - 0 10 10 yPrecision F - 0 10 11 deviceId I - 0 10 12 edgeFlags I - 0 10 13 source I - 0 10 14 flags I - - Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - -public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int); - Signature: (JJIFFFFIFFII)Landroid/view/MotionEvent; - Code: - Stack=3, Locals=14, Args_size=12 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 40: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 x F - 0 10 6 y F - 0 10 7 pressure F - 0 10 8 size F - 0 10 9 metaState I - 0 10 10 xPrecision F - 0 10 11 yPrecision F - 0 10 12 deviceId I - 0 10 13 edgeFlags I - - -public static android.view.MotionEvent obtain(long, long, int, int, float, float, float, float, int, float, float, int, int); - Signature: (JJIIFFFFIFFII)Landroid/view/MotionEvent; - Code: - Stack=3, Locals=15, Args_size=13 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 42: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 pointerCount I - 0 10 6 x F - 0 10 7 y F - 0 10 8 pressure F - 0 10 9 size F - 0 10 10 metaState I - 0 10 11 xPrecision F - 0 10 12 yPrecision F - 0 10 13 deviceId I - 0 10 14 edgeFlags I - - Deprecated: true - RuntimeVisibleAnnotations: length = 0x6 - 00 01 00 30 00 00 - -public static android.view.MotionEvent obtain(long, long, int, float, float, int); - Signature: (JJIFFI)Landroid/view/MotionEvent; - Code: - Stack=3, Locals=8, Args_size=6 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 43: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 x F - 0 10 6 y F - 0 10 7 metaState I - - -public static android.view.MotionEvent obtain(android.view.MotionEvent); - Signature: (Landroid/view/MotionEvent;)Landroid/view/MotionEvent; - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 44: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 other Landroid/view/MotionEvent; - - -public static android.view.MotionEvent obtainNoHistory(android.view.MotionEvent); - Signature: (Landroid/view/MotionEvent;)Landroid/view/MotionEvent; - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 45: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 other Landroid/view/MotionEvent; - - -public final void recycle(); - Signature: ()V - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 46: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final int getDeviceId(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 47: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final int getSource(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 48: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final void setSource(int); - Signature: (I)V - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 49: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 source I - - -public final int getAction(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 50: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final int getActionMasked(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 51: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final int getActionIndex(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 52: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final int getFlags(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 53: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final long getDownTime(); - Signature: ()J - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 54: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final long getEventTime(); - Signature: ()J - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 55: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getX(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 56: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getY(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 57: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getPressure(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 58: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getSize(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 59: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getTouchMajor(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 60: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getTouchMinor(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 61: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getToolMajor(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 62: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getToolMinor(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 63: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getOrientation(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 64: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getAxisValue(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 65: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 axis I - - -public final int getPointerCount(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 66: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final int getPointerId(int); - Signature: (I)I - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 67: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final int getToolType(int); - Signature: (I)I - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 68: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final int findPointerIndex(int); - Signature: (I)I - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 69: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerId I - - -public final float getX(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 70: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getY(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 71: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getPressure(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 72: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getSize(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 73: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getTouchMajor(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 74: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getTouchMinor(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 75: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getToolMajor(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 76: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getToolMinor(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 77: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getOrientation(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 78: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - -public final float getAxisValue(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 79: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 axis I - 0 10 2 pointerIndex I - - -public final void getPointerCoords(int, android.view.MotionEvent$PointerCoords); - Signature: (ILandroid/view/MotionEvent$PointerCoords;)V - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 80: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 outPointerCoords Landroid/view/MotionEvent$PointerCoords; - - -public final void getPointerProperties(int, android.view.MotionEvent$PointerProperties); - Signature: (ILandroid/view/MotionEvent$PointerProperties;)V - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 81: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 outPointerProperties Landroid/view/MotionEvent$PointerProperties; - - -public final int getMetaState(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 82: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final int getButtonState(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 83: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getRawX(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 84: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getRawY(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 85: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getXPrecision(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 86: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final float getYPrecision(); - Signature: ()F - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 87: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final int getHistorySize(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 88: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final long getHistoricalEventTime(int); - Signature: (I)J - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 89: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalX(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 90: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalY(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 91: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalPressure(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 92: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalSize(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 93: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalTouchMajor(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 94: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalTouchMinor(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 95: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalToolMajor(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 96: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalToolMinor(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 97: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalOrientation(int); - Signature: (I)F - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 98: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - -public final float getHistoricalAxisValue(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 99: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 axis I - 0 10 2 pos I - - -public final float getHistoricalX(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 100: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalY(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 101: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalPressure(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 102: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalSize(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 103: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalTouchMajor(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 104: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalTouchMinor(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 105: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalToolMajor(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 106: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalToolMinor(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 107: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalOrientation(int, int); - Signature: (II)F - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 108: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - -public final float getHistoricalAxisValue(int, int, int); - Signature: (III)F - Code: - Stack=3, Locals=4, Args_size=4 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 109: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 axis I - 0 10 2 pointerIndex I - 0 10 3 pos I - - -public final void getHistoricalPointerCoords(int, int, android.view.MotionEvent$PointerCoords); - Signature: (IILandroid/view/MotionEvent$PointerCoords;)V - Code: - Stack=3, Locals=4, Args_size=4 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 110: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - 0 10 3 outPointerCoords Landroid/view/MotionEvent$PointerCoords; - - -public final int getEdgeFlags(); - Signature: ()I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 111: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public final void setEdgeFlags(int); - Signature: (I)V - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 112: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 flags I - - -public final void setAction(int); - Signature: (I)V - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 113: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 action I - - -public final void offsetLocation(float, float); - Signature: (FF)V - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 114: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 deltaX F - 0 10 2 deltaY F - - -public final void setLocation(float, float); - Signature: (FF)V - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 115: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 x F - 0 10 2 y F - - -public final void transform(android.graphics.Matrix); - Signature: (Landroid/graphics/Matrix;)V - Code: - Stack=3, Locals=2, Args_size=2 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 116: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 matrix Landroid/graphics/Matrix; - - -public final void addBatch(long, float, float, float, float, int); - Signature: (JFFFFI)V - Code: - Stack=3, Locals=8, Args_size=7 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 117: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 eventTime J - 0 10 3 x F - 0 10 4 y F - 0 10 5 pressure F - 0 10 6 size F - 0 10 7 metaState I - - -public final void addBatch(long, android.view.MotionEvent$PointerCoords[], int); - Signature: (J[Landroid/view/MotionEvent$PointerCoords;I)V - Code: - Stack=3, Locals=5, Args_size=4 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 118: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 eventTime J - 0 10 3 pointerCoords [Landroid/view/MotionEvent$PointerCoords; - 0 10 4 metaState I - - -public java.lang.String toString(); - Signature: ()Ljava/lang/String; - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 119: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - -public static java.lang.String actionToString(int); - Signature: (I)Ljava/lang/String; - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 120: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 action I - - -public static java.lang.String axisToString(int); - Signature: (I)Ljava/lang/String; - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 121: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 axis I - - -public static int axisFromString(java.lang.String); - Signature: (Ljava/lang/String;)I - Code: - Stack=3, Locals=1, Args_size=1 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 122: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 symbolicName Ljava/lang/String; - - -public void writeToParcel(android.os.Parcel, int); - Signature: (Landroid/os/Parcel;I)V - Code: - Stack=3, Locals=3, Args_size=3 - 0: new #2; //class java/lang/RuntimeException - 3: dup - 4: ldc #3; //String Stub! - 6: invokespecial #4; //Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 123: 0 - - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 out Landroid/os/Parcel; - 0 10 2 flags I - - -static {}; - Signature: ()V - Code: - Stack=1, Locals=0, Args_size=0 - 0: aconst_null - 1: putstatic #5; //Field CREATOR:Landroid/os/Parcelable$Creator; - 4: return - LineNumberTable: - line 213: 0 - - -} - diff --git a/base/android/jni_generator/testMotionEvent.javap7 b/base/android/jni_generator/testMotionEvent.javap7 deleted file mode 100644 index f4f5444..0000000 --- a/base/android/jni_generator/testMotionEvent.javap7 +++ /dev/null @@ -1,2370 +0,0 @@ -Classfile out_android/Debug/gen/content/jni/android/view/MotionEvent.class - Last modified Feb 27, 2014; size 13369 bytes - MD5 checksum 3718d77a994cb8aceb7b35c5df3c4dd1 - Compiled from "MotionEvent.java" -public final class android.view.MotionEvent extends android.view.InputEvent implements android.os.Parcelable - SourceFile: "MotionEvent.java" - InnerClasses: - public static final #10= #9 of #6; //PointerProperties=class android/view/MotionEvent$PointerProperties of class android/view/MotionEvent - public static final #13= #12 of #6; //PointerCoords=class android/view/MotionEvent$PointerCoords of class android/view/MotionEvent - public static #150= #149 of #8; //Creator=class android/os/Parcelable$Creator of class android/os/Parcelable - minor version: 0 - major version: 49 - flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER -Constant pool: - #1 = Methodref #7.#293 // android/view/InputEvent."":()V - #2 = Class #294 // java/lang/RuntimeException - #3 = String #295 // Stub! - #4 = Methodref #2.#296 // java/lang/RuntimeException."":(Ljava/lang/String;)V - #5 = Fieldref #6.#297 // android/view/MotionEvent.CREATOR:Landroid/os/Parcelable$Creator; - #6 = Class #298 // android/view/MotionEvent - #7 = Class #299 // android/view/InputEvent - #8 = Class #300 // android/os/Parcelable - #9 = Class #301 // android/view/MotionEvent$PointerProperties - #10 = Utf8 PointerProperties - #11 = Utf8 InnerClasses - #12 = Class #302 // android/view/MotionEvent$PointerCoords - #13 = Utf8 PointerCoords - #14 = Utf8 INVALID_POINTER_ID - #15 = Utf8 I - #16 = Utf8 ConstantValue - #17 = Integer -1 - #18 = Utf8 ACTION_MASK - #19 = Integer 255 - #20 = Utf8 ACTION_DOWN - #21 = Integer 0 - #22 = Utf8 ACTION_UP - #23 = Integer 1 - #24 = Utf8 ACTION_MOVE - #25 = Integer 2 - #26 = Utf8 ACTION_CANCEL - #27 = Integer 3 - #28 = Utf8 ACTION_OUTSIDE - #29 = Integer 4 - #30 = Utf8 ACTION_POINTER_DOWN - #31 = Integer 5 - #32 = Utf8 ACTION_POINTER_UP - #33 = Integer 6 - #34 = Utf8 ACTION_HOVER_MOVE - #35 = Integer 7 - #36 = Utf8 ACTION_SCROLL - #37 = Integer 8 - #38 = Utf8 ACTION_HOVER_ENTER - #39 = Integer 9 - #40 = Utf8 ACTION_HOVER_EXIT - #41 = Integer 10 - #42 = Utf8 ACTION_POINTER_INDEX_MASK - #43 = Integer 65280 - #44 = Utf8 ACTION_POINTER_INDEX_SHIFT - #45 = Utf8 ACTION_POINTER_1_DOWN - #46 = Utf8 Deprecated - #47 = Utf8 RuntimeVisibleAnnotations - #48 = Utf8 Ljava/lang/Deprecated; - #49 = Utf8 ACTION_POINTER_2_DOWN - #50 = Integer 261 - #51 = Utf8 ACTION_POINTER_3_DOWN - #52 = Integer 517 - #53 = Utf8 ACTION_POINTER_1_UP - #54 = Utf8 ACTION_POINTER_2_UP - #55 = Integer 262 - #56 = Utf8 ACTION_POINTER_3_UP - #57 = Integer 518 - #58 = Utf8 ACTION_POINTER_ID_MASK - #59 = Utf8 ACTION_POINTER_ID_SHIFT - #60 = Utf8 FLAG_WINDOW_IS_OBSCURED - #61 = Utf8 EDGE_TOP - #62 = Utf8 EDGE_BOTTOM - #63 = Utf8 EDGE_LEFT - #64 = Utf8 EDGE_RIGHT - #65 = Utf8 AXIS_X - #66 = Utf8 AXIS_Y - #67 = Utf8 AXIS_PRESSURE - #68 = Utf8 AXIS_SIZE - #69 = Utf8 AXIS_TOUCH_MAJOR - #70 = Utf8 AXIS_TOUCH_MINOR - #71 = Utf8 AXIS_TOOL_MAJOR - #72 = Utf8 AXIS_TOOL_MINOR - #73 = Utf8 AXIS_ORIENTATION - #74 = Utf8 AXIS_VSCROLL - #75 = Utf8 AXIS_HSCROLL - #76 = Utf8 AXIS_Z - #77 = Integer 11 - #78 = Utf8 AXIS_RX - #79 = Integer 12 - #80 = Utf8 AXIS_RY - #81 = Integer 13 - #82 = Utf8 AXIS_RZ - #83 = Integer 14 - #84 = Utf8 AXIS_HAT_X - #85 = Integer 15 - #86 = Utf8 AXIS_HAT_Y - #87 = Integer 16 - #88 = Utf8 AXIS_LTRIGGER - #89 = Integer 17 - #90 = Utf8 AXIS_RTRIGGER - #91 = Integer 18 - #92 = Utf8 AXIS_THROTTLE - #93 = Integer 19 - #94 = Utf8 AXIS_RUDDER - #95 = Integer 20 - #96 = Utf8 AXIS_WHEEL - #97 = Integer 21 - #98 = Utf8 AXIS_GAS - #99 = Integer 22 - #100 = Utf8 AXIS_BRAKE - #101 = Integer 23 - #102 = Utf8 AXIS_DISTANCE - #103 = Integer 24 - #104 = Utf8 AXIS_TILT - #105 = Integer 25 - #106 = Utf8 AXIS_GENERIC_1 - #107 = Integer 32 - #108 = Utf8 AXIS_GENERIC_2 - #109 = Integer 33 - #110 = Utf8 AXIS_GENERIC_3 - #111 = Integer 34 - #112 = Utf8 AXIS_GENERIC_4 - #113 = Integer 35 - #114 = Utf8 AXIS_GENERIC_5 - #115 = Integer 36 - #116 = Utf8 AXIS_GENERIC_6 - #117 = Integer 37 - #118 = Utf8 AXIS_GENERIC_7 - #119 = Integer 38 - #120 = Utf8 AXIS_GENERIC_8 - #121 = Integer 39 - #122 = Utf8 AXIS_GENERIC_9 - #123 = Integer 40 - #124 = Utf8 AXIS_GENERIC_10 - #125 = Integer 41 - #126 = Utf8 AXIS_GENERIC_11 - #127 = Integer 42 - #128 = Utf8 AXIS_GENERIC_12 - #129 = Integer 43 - #130 = Utf8 AXIS_GENERIC_13 - #131 = Integer 44 - #132 = Utf8 AXIS_GENERIC_14 - #133 = Integer 45 - #134 = Utf8 AXIS_GENERIC_15 - #135 = Integer 46 - #136 = Utf8 AXIS_GENERIC_16 - #137 = Integer 47 - #138 = Utf8 BUTTON_PRIMARY - #139 = Utf8 BUTTON_SECONDARY - #140 = Utf8 BUTTON_TERTIARY - #141 = Utf8 BUTTON_BACK - #142 = Utf8 BUTTON_FORWARD - #143 = Utf8 TOOL_TYPE_UNKNOWN - #144 = Utf8 TOOL_TYPE_FINGER - #145 = Utf8 TOOL_TYPE_STYLUS - #146 = Utf8 TOOL_TYPE_MOUSE - #147 = Utf8 TOOL_TYPE_ERASER - #148 = Utf8 CREATOR - #149 = Class #303 // android/os/Parcelable$Creator - #150 = Utf8 Creator - #151 = Utf8 Landroid/os/Parcelable$Creator; - #152 = Utf8 Signature - #153 = Utf8 Landroid/os/Parcelable$Creator; - #154 = Utf8 - #155 = Utf8 ()V - #156 = Utf8 Code - #157 = Utf8 LineNumberTable - #158 = Utf8 LocalVariableTable - #159 = Utf8 this - #160 = Utf8 Landroid/view/MotionEvent; - #161 = Utf8 finalize - #162 = Utf8 Exceptions - #163 = Class #304 // java/lang/Throwable - #164 = Utf8 obtain - #165 = Utf8 (JJII[Landroid/view/MotionEvent$PointerProperties;[Landroid/view/MotionEvent$PointerCoords;IIFFIIII)Landroid/view/MotionEvent; - #166 = Utf8 downTime - #167 = Utf8 J - #168 = Utf8 eventTime - #169 = Utf8 action - #170 = Utf8 pointerCount - #171 = Utf8 pointerProperties - #172 = Utf8 [Landroid/view/MotionEvent$PointerProperties; - #173 = Utf8 pointerCoords - #174 = Utf8 [Landroid/view/MotionEvent$PointerCoords; - #175 = Utf8 metaState - #176 = Utf8 buttonState - #177 = Utf8 xPrecision - #178 = Utf8 F - #179 = Utf8 yPrecision - #180 = Utf8 deviceId - #181 = Utf8 edgeFlags - #182 = Utf8 source - #183 = Utf8 flags - #184 = Utf8 (JJII[I[Landroid/view/MotionEvent$PointerCoords;IFFIIII)Landroid/view/MotionEvent; - #185 = Utf8 pointerIds - #186 = Utf8 [I - #187 = Utf8 (JJIFFFFIFFII)Landroid/view/MotionEvent; - #188 = Utf8 x - #189 = Utf8 y - #190 = Utf8 pressure - #191 = Utf8 size - #192 = Utf8 (JJIIFFFFIFFII)Landroid/view/MotionEvent; - #193 = Utf8 (JJIFFI)Landroid/view/MotionEvent; - #194 = Utf8 (Landroid/view/MotionEvent;)Landroid/view/MotionEvent; - #195 = Utf8 other - #196 = Utf8 obtainNoHistory - #197 = Utf8 recycle - #198 = Utf8 getDeviceId - #199 = Utf8 ()I - #200 = Utf8 getSource - #201 = Utf8 setSource - #202 = Utf8 (I)V - #203 = Utf8 getAction - #204 = Utf8 getActionMasked - #205 = Utf8 getActionIndex - #206 = Utf8 getFlags - #207 = Utf8 getDownTime - #208 = Utf8 ()J - #209 = Utf8 getEventTime - #210 = Utf8 getX - #211 = Utf8 ()F - #212 = Utf8 getY - #213 = Utf8 getPressure - #214 = Utf8 getSize - #215 = Utf8 getTouchMajor - #216 = Utf8 getTouchMinor - #217 = Utf8 getToolMajor - #218 = Utf8 getToolMinor - #219 = Utf8 getOrientation - #220 = Utf8 getAxisValue - #221 = Utf8 (I)F - #222 = Utf8 axis - #223 = Utf8 getPointerCount - #224 = Utf8 getPointerId - #225 = Utf8 (I)I - #226 = Utf8 pointerIndex - #227 = Utf8 getToolType - #228 = Utf8 findPointerIndex - #229 = Utf8 pointerId - #230 = Utf8 (II)F - #231 = Utf8 getPointerCoords - #232 = Utf8 (ILandroid/view/MotionEvent$PointerCoords;)V - #233 = Utf8 outPointerCoords - #234 = Utf8 Landroid/view/MotionEvent$PointerCoords; - #235 = Utf8 getPointerProperties - #236 = Utf8 (ILandroid/view/MotionEvent$PointerProperties;)V - #237 = Utf8 outPointerProperties - #238 = Utf8 Landroid/view/MotionEvent$PointerProperties; - #239 = Utf8 getMetaState - #240 = Utf8 getButtonState - #241 = Utf8 getRawX - #242 = Utf8 getRawY - #243 = Utf8 getXPrecision - #244 = Utf8 getYPrecision - #245 = Utf8 getHistorySize - #246 = Utf8 getHistoricalEventTime - #247 = Utf8 (I)J - #248 = Utf8 pos - #249 = Utf8 getHistoricalX - #250 = Utf8 getHistoricalY - #251 = Utf8 getHistoricalPressure - #252 = Utf8 getHistoricalSize - #253 = Utf8 getHistoricalTouchMajor - #254 = Utf8 getHistoricalTouchMinor - #255 = Utf8 getHistoricalToolMajor - #256 = Utf8 getHistoricalToolMinor - #257 = Utf8 getHistoricalOrientation - #258 = Utf8 getHistoricalAxisValue - #259 = Utf8 (III)F - #260 = Utf8 getHistoricalPointerCoords - #261 = Utf8 (IILandroid/view/MotionEvent$PointerCoords;)V - #262 = Utf8 getEdgeFlags - #263 = Utf8 setEdgeFlags - #264 = Utf8 setAction - #265 = Utf8 offsetLocation - #266 = Utf8 (FF)V - #267 = Utf8 deltaX - #268 = Utf8 deltaY - #269 = Utf8 setLocation - #270 = Utf8 transform - #271 = Utf8 (Landroid/graphics/Matrix;)V - #272 = Utf8 matrix - #273 = Utf8 Landroid/graphics/Matrix; - #274 = Utf8 addBatch - #275 = Utf8 (JFFFFI)V - #276 = Utf8 (J[Landroid/view/MotionEvent$PointerCoords;I)V - #277 = Utf8 toString - #278 = Utf8 ()Ljava/lang/String; - #279 = Utf8 actionToString - #280 = Utf8 (I)Ljava/lang/String; - #281 = Utf8 axisToString - #282 = Utf8 axisFromString - #283 = Utf8 (Ljava/lang/String;)I - #284 = Utf8 symbolicName - #285 = Utf8 Ljava/lang/String; - #286 = Utf8 writeToParcel - #287 = Utf8 (Landroid/os/Parcel;I)V - #288 = Utf8 out - #289 = Utf8 Landroid/os/Parcel; - #290 = Utf8 - #291 = Utf8 SourceFile - #292 = Utf8 MotionEvent.java - #293 = NameAndType #154:#155 // "":()V - #294 = Utf8 java/lang/RuntimeException - #295 = Utf8 Stub! - #296 = NameAndType #154:#305 // "":(Ljava/lang/String;)V - #297 = NameAndType #148:#151 // CREATOR:Landroid/os/Parcelable$Creator; - #298 = Utf8 android/view/MotionEvent - #299 = Utf8 android/view/InputEvent - #300 = Utf8 android/os/Parcelable - #301 = Utf8 android/view/MotionEvent$PointerProperties - #302 = Utf8 android/view/MotionEvent$PointerCoords - #303 = Utf8 android/os/Parcelable$Creator - #304 = Utf8 java/lang/Throwable - #305 = Utf8 (Ljava/lang/String;)V -{ - public static final int INVALID_POINTER_ID; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int -1 - - - public static final int ACTION_MASK; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 255 - - - public static final int ACTION_DOWN; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 0 - - - public static final int ACTION_UP; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 1 - - - public static final int ACTION_MOVE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 2 - - - public static final int ACTION_CANCEL; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 3 - - - public static final int ACTION_OUTSIDE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 4 - - - public static final int ACTION_POINTER_DOWN; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 5 - - - public static final int ACTION_POINTER_UP; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 6 - - - public static final int ACTION_HOVER_MOVE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 7 - - - public static final int ACTION_SCROLL; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 8 - - - public static final int ACTION_HOVER_ENTER; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 9 - - - public static final int ACTION_HOVER_EXIT; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 10 - - - public static final int ACTION_POINTER_INDEX_MASK; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 65280 - - - public static final int ACTION_POINTER_INDEX_SHIFT; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 8 - - - public static final int ACTION_POINTER_1_DOWN; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 5 - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - - public static final int ACTION_POINTER_2_DOWN; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 261 - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - - public static final int ACTION_POINTER_3_DOWN; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 517 - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - - public static final int ACTION_POINTER_1_UP; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 6 - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - - public static final int ACTION_POINTER_2_UP; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 262 - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - - public static final int ACTION_POINTER_3_UP; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 518 - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - - public static final int ACTION_POINTER_ID_MASK; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 65280 - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - - public static final int ACTION_POINTER_ID_SHIFT; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 8 - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - - public static final int FLAG_WINDOW_IS_OBSCURED; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 1 - - - public static final int EDGE_TOP; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 1 - - - public static final int EDGE_BOTTOM; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 2 - - - public static final int EDGE_LEFT; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 4 - - - public static final int EDGE_RIGHT; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 8 - - - public static final int AXIS_X; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 0 - - - public static final int AXIS_Y; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 1 - - - public static final int AXIS_PRESSURE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 2 - - - public static final int AXIS_SIZE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 3 - - - public static final int AXIS_TOUCH_MAJOR; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 4 - - - public static final int AXIS_TOUCH_MINOR; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 5 - - - public static final int AXIS_TOOL_MAJOR; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 6 - - - public static final int AXIS_TOOL_MINOR; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 7 - - - public static final int AXIS_ORIENTATION; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 8 - - - public static final int AXIS_VSCROLL; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 9 - - - public static final int AXIS_HSCROLL; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 10 - - - public static final int AXIS_Z; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 11 - - - public static final int AXIS_RX; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 12 - - - public static final int AXIS_RY; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 13 - - - public static final int AXIS_RZ; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 14 - - - public static final int AXIS_HAT_X; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 15 - - - public static final int AXIS_HAT_Y; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 16 - - - public static final int AXIS_LTRIGGER; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 17 - - - public static final int AXIS_RTRIGGER; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 18 - - - public static final int AXIS_THROTTLE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 19 - - - public static final int AXIS_RUDDER; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 20 - - - public static final int AXIS_WHEEL; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 21 - - - public static final int AXIS_GAS; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 22 - - - public static final int AXIS_BRAKE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 23 - - - public static final int AXIS_DISTANCE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 24 - - - public static final int AXIS_TILT; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 25 - - - public static final int AXIS_GENERIC_1; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 32 - - - public static final int AXIS_GENERIC_2; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 33 - - - public static final int AXIS_GENERIC_3; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 34 - - - public static final int AXIS_GENERIC_4; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 35 - - - public static final int AXIS_GENERIC_5; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 36 - - - public static final int AXIS_GENERIC_6; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 37 - - - public static final int AXIS_GENERIC_7; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 38 - - - public static final int AXIS_GENERIC_8; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 39 - - - public static final int AXIS_GENERIC_9; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 40 - - - public static final int AXIS_GENERIC_10; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 41 - - - public static final int AXIS_GENERIC_11; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 42 - - - public static final int AXIS_GENERIC_12; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 43 - - - public static final int AXIS_GENERIC_13; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 44 - - - public static final int AXIS_GENERIC_14; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 45 - - - public static final int AXIS_GENERIC_15; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 46 - - - public static final int AXIS_GENERIC_16; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 47 - - - public static final int BUTTON_PRIMARY; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 1 - - - public static final int BUTTON_SECONDARY; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 2 - - - public static final int BUTTON_TERTIARY; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 4 - - - public static final int BUTTON_BACK; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 8 - - - public static final int BUTTON_FORWARD; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 16 - - - public static final int TOOL_TYPE_UNKNOWN; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 0 - - - public static final int TOOL_TYPE_FINGER; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 1 - - - public static final int TOOL_TYPE_STYLUS; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 2 - - - public static final int TOOL_TYPE_MOUSE; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 3 - - - public static final int TOOL_TYPE_ERASER; - Signature: I - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - ConstantValue: int 4 - - - public static final android.os.Parcelable$Creator CREATOR; - Signature: Landroid/os/Parcelable$Creator; - flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL - Signature: #153 // Landroid/os/Parcelable$Creator; - - - android.view.MotionEvent(); - Signature: ()V - flags: - Code: - stack=3, locals=1, args_size=1 - 0: aload_0 - 1: invokespecial #1 // Method android/view/InputEvent."":()V - 4: new #2 // class java/lang/RuntimeException - 7: dup - 8: ldc #3 // String Stub! - 10: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 13: athrow - LineNumberTable: - line 35: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 14 0 this Landroid/view/MotionEvent; - - protected void finalize() throws java.lang.Throwable; - Signature: ()V - flags: ACC_PROTECTED - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 36: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - Exceptions: - throws java.lang.Throwable - - public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent$PointerProperties[], android.view.MotionEvent$PointerCoords[], int, int, float, float, int, int, int, int); - Signature: (JJII[Landroid/view/MotionEvent$PointerProperties;[Landroid/view/MotionEvent$PointerCoords;IIFFIIII)Landroid/view/MotionEvent; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=16, args_size=14 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 37: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 pointerCount I - 0 10 6 pointerProperties [Landroid/view/MotionEvent$PointerProperties; - 0 10 7 pointerCoords [Landroid/view/MotionEvent$PointerCoords; - 0 10 8 metaState I - 0 10 9 buttonState I - 0 10 10 xPrecision F - 0 10 11 yPrecision F - 0 10 12 deviceId I - 0 10 13 edgeFlags I - 0 10 14 source I - 0 10 15 flags I - - public static android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent$PointerCoords[], int, float, float, int, int, int, int); - Signature: (JJII[I[Landroid/view/MotionEvent$PointerCoords;IFFIIII)Landroid/view/MotionEvent; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=15, args_size=13 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 39: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 pointerCount I - 0 10 6 pointerIds [I - 0 10 7 pointerCoords [Landroid/view/MotionEvent$PointerCoords; - 0 10 8 metaState I - 0 10 9 xPrecision F - 0 10 10 yPrecision F - 0 10 11 deviceId I - 0 10 12 edgeFlags I - 0 10 13 source I - 0 10 14 flags I - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int); - Signature: (JJIFFFFIFFII)Landroid/view/MotionEvent; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=14, args_size=12 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 40: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 x F - 0 10 6 y F - 0 10 7 pressure F - 0 10 8 size F - 0 10 9 metaState I - 0 10 10 xPrecision F - 0 10 11 yPrecision F - 0 10 12 deviceId I - 0 10 13 edgeFlags I - - public static android.view.MotionEvent obtain(long, long, int, int, float, float, float, float, int, float, float, int, int); - Signature: (JJIIFFFFIFFII)Landroid/view/MotionEvent; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=15, args_size=13 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 42: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 pointerCount I - 0 10 6 x F - 0 10 7 y F - 0 10 8 pressure F - 0 10 9 size F - 0 10 10 metaState I - 0 10 11 xPrecision F - 0 10 12 yPrecision F - 0 10 13 deviceId I - 0 10 14 edgeFlags I - Deprecated: true - RuntimeVisibleAnnotations: - 0: #48() - - public static android.view.MotionEvent obtain(long, long, int, float, float, int); - Signature: (JJIFFI)Landroid/view/MotionEvent; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=8, args_size=6 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 43: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 downTime J - 0 10 2 eventTime J - 0 10 4 action I - 0 10 5 x F - 0 10 6 y F - 0 10 7 metaState I - - public static android.view.MotionEvent obtain(android.view.MotionEvent); - Signature: (Landroid/view/MotionEvent;)Landroid/view/MotionEvent; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 44: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 other Landroid/view/MotionEvent; - - public static android.view.MotionEvent obtainNoHistory(android.view.MotionEvent); - Signature: (Landroid/view/MotionEvent;)Landroid/view/MotionEvent; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 45: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 other Landroid/view/MotionEvent; - - public final void recycle(); - Signature: ()V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 46: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final int getDeviceId(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 47: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final int getSource(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 48: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final void setSource(int); - Signature: (I)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 49: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 source I - - public final int getAction(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 50: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final int getActionMasked(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 51: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final int getActionIndex(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 52: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final int getFlags(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 53: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final long getDownTime(); - Signature: ()J - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 54: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final long getEventTime(); - Signature: ()J - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 55: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getX(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 56: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getY(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 57: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getPressure(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 58: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getSize(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 59: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getTouchMajor(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 60: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getTouchMinor(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 61: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getToolMajor(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 62: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getToolMinor(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 63: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getOrientation(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 64: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getAxisValue(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 65: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 axis I - - public final int getPointerCount(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 66: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final int getPointerId(int); - Signature: (I)I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 67: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final int getToolType(int); - Signature: (I)I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 68: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final int findPointerIndex(int); - Signature: (I)I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 69: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerId I - - public final float getX(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 70: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getY(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 71: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getPressure(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 72: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getSize(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 73: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getTouchMajor(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 74: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getTouchMinor(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 75: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getToolMajor(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 76: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getToolMinor(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 77: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getOrientation(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 78: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - - public final float getAxisValue(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 79: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 axis I - 0 10 2 pointerIndex I - - public final void getPointerCoords(int, android.view.MotionEvent$PointerCoords); - Signature: (ILandroid/view/MotionEvent$PointerCoords;)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 80: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 outPointerCoords Landroid/view/MotionEvent$PointerCoords; - - public final void getPointerProperties(int, android.view.MotionEvent$PointerProperties); - Signature: (ILandroid/view/MotionEvent$PointerProperties;)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 81: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 outPointerProperties Landroid/view/MotionEvent$PointerProperties; - - public final int getMetaState(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 82: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final int getButtonState(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 83: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getRawX(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 84: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getRawY(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 85: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getXPrecision(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 86: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final float getYPrecision(); - Signature: ()F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 87: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final int getHistorySize(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 88: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final long getHistoricalEventTime(int); - Signature: (I)J - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 89: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalX(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 90: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalY(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 91: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalPressure(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 92: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalSize(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 93: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalTouchMajor(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 94: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalTouchMinor(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 95: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalToolMajor(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 96: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalToolMinor(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 97: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalOrientation(int); - Signature: (I)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 98: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pos I - - public final float getHistoricalAxisValue(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 99: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 axis I - 0 10 2 pos I - - public final float getHistoricalX(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 100: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalY(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 101: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalPressure(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 102: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalSize(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 103: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalTouchMajor(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 104: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalTouchMinor(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 105: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalToolMajor(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 106: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalToolMinor(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 107: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalOrientation(int, int); - Signature: (II)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 108: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - - public final float getHistoricalAxisValue(int, int, int); - Signature: (III)F - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=4, args_size=4 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 109: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 axis I - 0 10 2 pointerIndex I - 0 10 3 pos I - - public final void getHistoricalPointerCoords(int, int, android.view.MotionEvent$PointerCoords); - Signature: (IILandroid/view/MotionEvent$PointerCoords;)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=4, args_size=4 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 110: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 pointerIndex I - 0 10 2 pos I - 0 10 3 outPointerCoords Landroid/view/MotionEvent$PointerCoords; - - public final int getEdgeFlags(); - Signature: ()I - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 111: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public final void setEdgeFlags(int); - Signature: (I)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 112: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 flags I - - public final void setAction(int); - Signature: (I)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 113: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 action I - - public final void offsetLocation(float, float); - Signature: (FF)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 114: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 deltaX F - 0 10 2 deltaY F - - public final void setLocation(float, float); - Signature: (FF)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 115: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 x F - 0 10 2 y F - - public final void transform(android.graphics.Matrix); - Signature: (Landroid/graphics/Matrix;)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=2, args_size=2 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 116: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 matrix Landroid/graphics/Matrix; - - public final void addBatch(long, float, float, float, float, int); - Signature: (JFFFFI)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=8, args_size=7 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 117: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 eventTime J - 0 10 3 x F - 0 10 4 y F - 0 10 5 pressure F - 0 10 6 size F - 0 10 7 metaState I - - public final void addBatch(long, android.view.MotionEvent$PointerCoords[], int); - Signature: (J[Landroid/view/MotionEvent$PointerCoords;I)V - flags: ACC_PUBLIC, ACC_FINAL - Code: - stack=3, locals=5, args_size=4 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 118: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 eventTime J - 0 10 3 pointerCoords [Landroid/view/MotionEvent$PointerCoords; - 0 10 4 metaState I - - public java.lang.String toString(); - Signature: ()Ljava/lang/String; - flags: ACC_PUBLIC - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 119: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - - public static java.lang.String actionToString(int); - Signature: (I)Ljava/lang/String; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 120: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 action I - - public static java.lang.String axisToString(int); - Signature: (I)Ljava/lang/String; - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 121: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 axis I - - public static int axisFromString(java.lang.String); - Signature: (Ljava/lang/String;)I - flags: ACC_PUBLIC, ACC_STATIC - Code: - stack=3, locals=1, args_size=1 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 122: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 symbolicName Ljava/lang/String; - - public void writeToParcel(android.os.Parcel, int); - Signature: (Landroid/os/Parcel;I)V - flags: ACC_PUBLIC - Code: - stack=3, locals=3, args_size=3 - 0: new #2 // class java/lang/RuntimeException - 3: dup - 4: ldc #3 // String Stub! - 6: invokespecial #4 // Method java/lang/RuntimeException."":(Ljava/lang/String;)V - 9: athrow - LineNumberTable: - line 123: 0 - LocalVariableTable: - Start Length Slot Name Signature - 0 10 0 this Landroid/view/MotionEvent; - 0 10 1 out Landroid/os/Parcel; - 0 10 2 flags I - - static {}; - Signature: ()V - flags: ACC_STATIC - Code: - stack=1, locals=0, args_size=0 - 0: aconst_null - 1: putstatic #5 // Field CREATOR:Landroid/os/Parcelable$Creator; - 4: return - LineNumberTable: - line 213: 0 -} diff --git a/base/android/jni_generator/testMultipleJNIAdditionalImport.golden b/base/android/jni_generator/testMultipleJNIAdditionalImport.golden deleted file mode 100644 index 0eecb5a..0000000 --- a/base/android/jni_generator/testMultipleJNIAdditionalImport.golden +++ /dev/null @@ -1,95 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// org/chromium/foo/Foo - -#ifndef org_chromium_foo_Foo_JNI -#define org_chromium_foo_Foo_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kFooClassPath[] = "org/chromium/foo/Foo"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_Foo_clazz __attribute__((unused)) = 0; -#define Foo_clazz(env) base::android::LazyGetClass(env, kFooClassPath, &g_Foo_clazz) - -} // namespace - -// Step 2: method stubs. - -static void DoSomething(JNIEnv* env, const base::android::JavaParamRef& - jcaller, - const base::android::JavaParamRef& callback1, - const base::android::JavaParamRef& callback2); - -JNI_GENERATOR_EXPORT void Java_org_chromium_foo_Foo_nativeDoSomething(JNIEnv* - env, jclass jcaller, - jobject callback1, - jobject callback2) { - return DoSomething(env, base::android::JavaParamRef(env, jcaller), - base::android::JavaParamRef(env, callback1), - base::android::JavaParamRef(env, callback2)); -} - -static base::subtle::AtomicWord g_Foo_calledByNative = 0; -static void Java_Foo_calledByNative(JNIEnv* env, const - base::android::JavaRefOrBare& callback1, - const base::android::JavaRefOrBare& callback2) { - CHECK_CLAZZ(env, Foo_clazz(env), - Foo_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, Foo_clazz(env), - "calledByNative", -"(" -"Lorg/chromium/foo/Bar1$Callback;" -"Lorg/chromium/foo/Bar2$Callback;" -")" -"V", - &g_Foo_calledByNative); - - env->CallStaticVoidMethod(Foo_clazz(env), - method_id, callback1.obj(), callback2.obj()); - jni_generator::CheckException(env); -} - -// Step 3: RegisterNatives. - -static const JNINativeMethod kMethodsFoo[] = { - { "nativeDoSomething", -"(" -"Lorg/chromium/foo/Bar1$Callback;" -"Lorg/chromium/foo/Bar2$Callback;" -")" -"V", reinterpret_cast(Java_org_chromium_foo_Foo_nativeDoSomething) }, -}; - -static bool RegisterNativesImpl(JNIEnv* env) { - if (jni_generator::ShouldSkipJniRegistration(false)) - return true; - - const int kMethodsFooSize = arraysize(kMethodsFoo); - - if (env->RegisterNatives(Foo_clazz(env), - kMethodsFoo, - kMethodsFooSize) < 0) { - jni_generator::HandleRegistrationError( - env, Foo_clazz(env), __FILE__); - return false; - } - - return true; -} - -#endif // org_chromium_foo_Foo_JNI diff --git a/base/android/jni_generator/testNatives.golden b/base/android/jni_generator/testNatives.golden deleted file mode 100644 index 3362c92..0000000 --- a/base/android/jni_generator/testNatives.golden +++ /dev/null @@ -1,340 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// org/chromium/TestJni - -#ifndef org_chromium_TestJni_JNI -#define org_chromium_TestJni_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kTestJniClassPath[] = "org/chromium/TestJni"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_TestJni_clazz __attribute__((unused)) = 0; -#define TestJni_clazz(env) base::android::LazyGetClass(env, kTestJniClassPath, &g_TestJni_clazz) - -} // namespace - -// Step 2: method stubs. - -static jint Init(JNIEnv* env, const base::android::JavaParamRef& - jcaller); - -JNI_GENERATOR_EXPORT jint Java_org_chromium_TestJni_nativeInit(JNIEnv* env, - jobject jcaller) { - return Init(env, base::android::JavaParamRef(env, jcaller)); -} - -JNI_GENERATOR_EXPORT void Java_org_chromium_TestJni_nativeDestroy(JNIEnv* env, - jobject jcaller, - jint nativeChromeBrowserProvider) { - ChromeBrowserProvider* native = - reinterpret_cast(nativeChromeBrowserProvider); - CHECK_NATIVE_PTR(env, jcaller, native, "Destroy"); - return native->Destroy(env, base::android::JavaParamRef(env, - jcaller)); -} - -JNI_GENERATOR_EXPORT jlong Java_org_chromium_TestJni_nativeAddBookmark(JNIEnv* - env, jobject jcaller, - jint nativeChromeBrowserProvider, - jstring url, - jstring title, - jboolean isFolder, - jlong parentId) { - ChromeBrowserProvider* native = - reinterpret_cast(nativeChromeBrowserProvider); - CHECK_NATIVE_PTR(env, jcaller, native, "AddBookmark", 0); - return native->AddBookmark(env, base::android::JavaParamRef(env, - jcaller), base::android::JavaParamRef(env, url), - base::android::JavaParamRef(env, title), isFolder, parentId); -} - -static base::android::ScopedJavaLocalRef GetDomainAndRegistry(JNIEnv* - env, const base::android::JavaParamRef& jcaller, - const base::android::JavaParamRef& url); - -JNI_GENERATOR_EXPORT jstring - Java_org_chromium_TestJni_nativeGetDomainAndRegistry(JNIEnv* env, jclass - jcaller, - jstring url) { - return GetDomainAndRegistry(env, base::android::JavaParamRef(env, - jcaller), base::android::JavaParamRef(env, url)).Release(); -} - -static void CreateHistoricalTabFromState(JNIEnv* env, const - base::android::JavaParamRef& jcaller, - const base::android::JavaParamRef& state, - jint tab_index); - -JNI_GENERATOR_EXPORT void - Java_org_chromium_TestJni_nativeCreateHistoricalTabFromState(JNIEnv* env, - jclass jcaller, - jbyteArray state, - jint tab_index) { - return CreateHistoricalTabFromState(env, - base::android::JavaParamRef(env, jcaller), - base::android::JavaParamRef(env, state), tab_index); -} - -static base::android::ScopedJavaLocalRef GetStateAsByteArray(JNIEnv* - env, const base::android::JavaParamRef& jcaller, - const base::android::JavaParamRef& view); - -JNI_GENERATOR_EXPORT jbyteArray - Java_org_chromium_TestJni_nativeGetStateAsByteArray(JNIEnv* env, jobject - jcaller, - jobject view) { - return GetStateAsByteArray(env, base::android::JavaParamRef(env, - jcaller), base::android::JavaParamRef(env, view)).Release(); -} - -static base::android::ScopedJavaLocalRef - GetAutofillProfileGUIDs(JNIEnv* env, const - base::android::JavaParamRef& jcaller); - -JNI_GENERATOR_EXPORT jobjectArray - Java_org_chromium_TestJni_nativeGetAutofillProfileGUIDs(JNIEnv* env, jclass - jcaller) { - return GetAutofillProfileGUIDs(env, base::android::JavaParamRef(env, - jcaller)).Release(); -} - -static void SetRecognitionResults(JNIEnv* env, const - base::android::JavaParamRef& jcaller, - jint sessionId, - const base::android::JavaParamRef& results); - -JNI_GENERATOR_EXPORT void - Java_org_chromium_TestJni_nativeSetRecognitionResults(JNIEnv* env, jobject - jcaller, - jint sessionId, - jobjectArray results) { - return SetRecognitionResults(env, base::android::JavaParamRef(env, - jcaller), sessionId, base::android::JavaParamRef(env, - results)); -} - -JNI_GENERATOR_EXPORT jlong - Java_org_chromium_TestJni_nativeAddBookmarkFromAPI(JNIEnv* env, jobject - jcaller, - jint nativeChromeBrowserProvider, - jstring url, - jobject created, - jobject isBookmark, - jobject date, - jbyteArray favicon, - jstring title, - jobject visits) { - ChromeBrowserProvider* native = - reinterpret_cast(nativeChromeBrowserProvider); - CHECK_NATIVE_PTR(env, jcaller, native, "AddBookmarkFromAPI", 0); - return native->AddBookmarkFromAPI(env, - base::android::JavaParamRef(env, jcaller), - base::android::JavaParamRef(env, url), - base::android::JavaParamRef(env, created), - base::android::JavaParamRef(env, isBookmark), - base::android::JavaParamRef(env, date), - base::android::JavaParamRef(env, favicon), - base::android::JavaParamRef(env, title), - base::android::JavaParamRef(env, visits)); -} - -static jint FindAll(JNIEnv* env, const base::android::JavaParamRef& - jcaller, - const base::android::JavaParamRef& find); - -JNI_GENERATOR_EXPORT jint Java_org_chromium_TestJni_nativeFindAll(JNIEnv* env, - jobject jcaller, - jstring find) { - return FindAll(env, base::android::JavaParamRef(env, jcaller), - base::android::JavaParamRef(env, find)); -} - -static base::android::ScopedJavaLocalRef GetInnerClass(JNIEnv* env, - const base::android::JavaParamRef& jcaller); - -JNI_GENERATOR_EXPORT jobject - Java_org_chromium_TestJni_nativeGetInnerClass(JNIEnv* env, jclass jcaller) { - return GetInnerClass(env, base::android::JavaParamRef(env, - jcaller)).Release(); -} - -JNI_GENERATOR_EXPORT jobject Java_org_chromium_TestJni_nativeQueryBitmap(JNIEnv* - env, jobject jcaller, - jint nativeChromeBrowserProvider, - jobjectArray projection, - jstring selection, - jobjectArray selectionArgs, - jstring sortOrder) { - ChromeBrowserProvider* native = - reinterpret_cast(nativeChromeBrowserProvider); - CHECK_NATIVE_PTR(env, jcaller, native, "QueryBitmap", NULL); - return native->QueryBitmap(env, base::android::JavaParamRef(env, - jcaller), base::android::JavaParamRef(env, projection), - base::android::JavaParamRef(env, selection), - base::android::JavaParamRef(env, selectionArgs), - base::android::JavaParamRef(env, sortOrder)).Release(); -} - -JNI_GENERATOR_EXPORT void Java_org_chromium_TestJni_nativeGotOrientation(JNIEnv* - env, jobject jcaller, - jint nativeDataFetcherImplAndroid, - jdouble alpha, - jdouble beta, - jdouble gamma) { - DataFetcherImplAndroid* native = - reinterpret_cast(nativeDataFetcherImplAndroid); - CHECK_NATIVE_PTR(env, jcaller, native, "GotOrientation"); - return native->GotOrientation(env, base::android::JavaParamRef(env, - jcaller), alpha, beta, gamma); -} - -static base::android::ScopedJavaLocalRef - MessWithJavaException(JNIEnv* env, const - base::android::JavaParamRef& jcaller, - const base::android::JavaParamRef& e); - -JNI_GENERATOR_EXPORT jthrowable - Java_org_chromium_TestJni_nativeMessWithJavaException(JNIEnv* env, jclass - jcaller, - jthrowable e) { - return MessWithJavaException(env, base::android::JavaParamRef(env, - jcaller), base::android::JavaParamRef(env, e)).Release(); -} - -// Step 3: RegisterNatives. - -static const JNINativeMethod kMethodsTestJni[] = { - { "nativeInit", -"(" -")" -"I", reinterpret_cast(Java_org_chromium_TestJni_nativeInit) }, - { "nativeDestroy", -"(" -"I" -")" -"V", reinterpret_cast(Java_org_chromium_TestJni_nativeDestroy) }, - { "nativeAddBookmark", -"(" -"I" -"Ljava/lang/String;" -"Ljava/lang/String;" -"Z" -"J" -")" -"J", reinterpret_cast(Java_org_chromium_TestJni_nativeAddBookmark) }, - { "nativeGetDomainAndRegistry", -"(" -"Ljava/lang/String;" -")" -"Ljava/lang/String;", - reinterpret_cast(Java_org_chromium_TestJni_nativeGetDomainAndRegistry) - }, - { "nativeCreateHistoricalTabFromState", -"(" -"[B" -"I" -")" -"V", - reinterpret_cast(Java_org_chromium_TestJni_nativeCreateHistoricalTabFromState) - }, - { "nativeGetStateAsByteArray", -"(" -"Landroid/view/View;" -")" -"[B", - reinterpret_cast(Java_org_chromium_TestJni_nativeGetStateAsByteArray) - }, - { "nativeGetAutofillProfileGUIDs", -"(" -")" -"[Ljava/lang/String;", - reinterpret_cast(Java_org_chromium_TestJni_nativeGetAutofillProfileGUIDs) - }, - { "nativeSetRecognitionResults", -"(" -"I" -"[Ljava/lang/String;" -")" -"V", - reinterpret_cast(Java_org_chromium_TestJni_nativeSetRecognitionResults) - }, - { "nativeAddBookmarkFromAPI", -"(" -"I" -"Ljava/lang/String;" -"Ljava/lang/Long;" -"Ljava/lang/Boolean;" -"Ljava/lang/Long;" -"[B" -"Ljava/lang/String;" -"Ljava/lang/Integer;" -")" -"J", reinterpret_cast(Java_org_chromium_TestJni_nativeAddBookmarkFromAPI) - }, - { "nativeFindAll", -"(" -"Ljava/lang/String;" -")" -"I", reinterpret_cast(Java_org_chromium_TestJni_nativeFindAll) }, - { "nativeGetInnerClass", -"(" -")" -"Lorg/chromium/example/jni_generator/SampleForTests$OnFrameAvailableListener;", - reinterpret_cast(Java_org_chromium_TestJni_nativeGetInnerClass) }, - { "nativeQueryBitmap", -"(" -"I" -"[Ljava/lang/String;" -"Ljava/lang/String;" -"[Ljava/lang/String;" -"Ljava/lang/String;" -")" -"Landroid/graphics/Bitmap;", - reinterpret_cast(Java_org_chromium_TestJni_nativeQueryBitmap) }, - { "nativeGotOrientation", -"(" -"I" -"D" -"D" -"D" -")" -"V", reinterpret_cast(Java_org_chromium_TestJni_nativeGotOrientation) }, - { "nativeMessWithJavaException", -"(" -"Ljava/lang/Throwable;" -")" -"Ljava/lang/Throwable;", - reinterpret_cast(Java_org_chromium_TestJni_nativeMessWithJavaException) - }, -}; - -static bool RegisterNativesImpl(JNIEnv* env) { - if (jni_generator::ShouldSkipJniRegistration(false)) - return true; - - const int kMethodsTestJniSize = arraysize(kMethodsTestJni); - - if (env->RegisterNatives(TestJni_clazz(env), - kMethodsTestJni, - kMethodsTestJniSize) < 0) { - jni_generator::HandleRegistrationError( - env, TestJni_clazz(env), __FILE__); - return false; - } - - return true; -} - -#endif // org_chromium_TestJni_JNI diff --git a/base/android/jni_generator/testNativesLong.golden b/base/android/jni_generator/testNativesLong.golden deleted file mode 100644 index ec029ce..0000000 --- a/base/android/jni_generator/testNativesLong.golden +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// org/chromium/TestJni - -#ifndef org_chromium_TestJni_JNI -#define org_chromium_TestJni_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kTestJniClassPath[] = "org/chromium/TestJni"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_TestJni_clazz __attribute__((unused)) = 0; -#define TestJni_clazz(env) base::android::LazyGetClass(env, kTestJniClassPath, &g_TestJni_clazz) - -} // namespace - -// Step 2: method stubs. -JNI_GENERATOR_EXPORT void Java_org_chromium_TestJni_nativeDestroy(JNIEnv* env, - jobject jcaller, - jlong nativeChromeBrowserProvider) { - ChromeBrowserProvider* native = - reinterpret_cast(nativeChromeBrowserProvider); - CHECK_NATIVE_PTR(env, jcaller, native, "Destroy"); - return native->Destroy(env, base::android::JavaParamRef(env, - jcaller)); -} - -// Step 3: RegisterNatives. - -static const JNINativeMethod kMethodsTestJni[] = { - { "nativeDestroy", -"(" -"J" -")" -"V", reinterpret_cast(Java_org_chromium_TestJni_nativeDestroy) }, -}; - -static bool RegisterNativesImpl(JNIEnv* env) { - if (jni_generator::ShouldSkipJniRegistration(false)) - return true; - - const int kMethodsTestJniSize = arraysize(kMethodsTestJni); - - if (env->RegisterNatives(TestJni_clazz(env), - kMethodsTestJni, - kMethodsTestJniSize) < 0) { - jni_generator::HandleRegistrationError( - env, TestJni_clazz(env), __FILE__); - return false; - } - - return true; -} - -#endif // org_chromium_TestJni_JNI diff --git a/base/android/jni_generator/testSingleJNIAdditionalImport.golden b/base/android/jni_generator/testSingleJNIAdditionalImport.golden deleted file mode 100644 index ef618da..0000000 --- a/base/android/jni_generator/testSingleJNIAdditionalImport.golden +++ /dev/null @@ -1,89 +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. - -// This file is autogenerated by -// base/android/jni_generator/jni_generator.py -// For -// org/chromium/foo/Foo - -#ifndef org_chromium_foo_Foo_JNI -#define org_chromium_foo_Foo_JNI - -#include - -#include "base/android/jni_generator/jni_generator_helper.h" - -#include "base/android/jni_int_wrapper.h" - -// Step 1: forward declarations. -namespace { -const char kFooClassPath[] = "org/chromium/foo/Foo"; -// Leaking this jclass as we cannot use LazyInstance from some threads. -base::subtle::AtomicWord g_Foo_clazz __attribute__((unused)) = 0; -#define Foo_clazz(env) base::android::LazyGetClass(env, kFooClassPath, &g_Foo_clazz) - -} // namespace - -// Step 2: method stubs. - -static void DoSomething(JNIEnv* env, const base::android::JavaParamRef& - jcaller, - const base::android::JavaParamRef& callback); - -JNI_GENERATOR_EXPORT void Java_org_chromium_foo_Foo_nativeDoSomething(JNIEnv* - env, jclass jcaller, - jobject callback) { - return DoSomething(env, base::android::JavaParamRef(env, jcaller), - base::android::JavaParamRef(env, callback)); -} - -static base::subtle::AtomicWord g_Foo_calledByNative = 0; -static void Java_Foo_calledByNative(JNIEnv* env, const - base::android::JavaRefOrBare& callback) { - CHECK_CLAZZ(env, Foo_clazz(env), - Foo_clazz(env)); - jmethodID method_id = - base::android::MethodID::LazyGet< - base::android::MethodID::TYPE_STATIC>( - env, Foo_clazz(env), - "calledByNative", -"(" -"Lorg/chromium/foo/Bar$Callback;" -")" -"V", - &g_Foo_calledByNative); - - env->CallStaticVoidMethod(Foo_clazz(env), - method_id, callback.obj()); - jni_generator::CheckException(env); -} - -// Step 3: RegisterNatives. - -static const JNINativeMethod kMethodsFoo[] = { - { "nativeDoSomething", -"(" -"Lorg/chromium/foo/Bar$Callback;" -")" -"V", reinterpret_cast(Java_org_chromium_foo_Foo_nativeDoSomething) }, -}; - -static bool RegisterNativesImpl(JNIEnv* env) { - if (jni_generator::ShouldSkipJniRegistration(false)) - return true; - - const int kMethodsFooSize = arraysize(kMethodsFoo); - - if (env->RegisterNatives(Foo_clazz(env), - kMethodsFoo, - kMethodsFooSize) < 0) { - jni_generator::HandleRegistrationError( - env, Foo_clazz(env), __FILE__); - return false; - } - - return true; -} - -#endif // org_chromium_foo_Foo_JNI diff --git a/base/android/jni_int_wrapper.h b/base/android/jni_int_wrapper.h deleted file mode 100644 index fa0f3d5..0000000 --- a/base/android/jni_int_wrapper.h +++ /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. - -#ifndef BASE_ANDROID_JNI_INT_WRAPPER_H_ -#define BASE_ANDROID_JNI_INT_WRAPPER_H_ - -// Wrapper used to receive int when calling Java from native. -// The wrapper disallows automatic conversion of long to int. -// This is to avoid a common anti-pattern where a Java int is used -// to receive a native pointer. Please use a Java long to receive -// native pointers, so that the code works on both 32-bit and 64-bit -// platforms. Note the wrapper allows other lossy conversions into -// jint that could be consider anti-patterns, such as from size_t. - -// Checking is only done in debugging builds. - -#ifdef NDEBUG - -typedef jint JniIntWrapper; - -// This inline is sufficiently trivial that it does not change the -// final code generated by g++. -inline jint as_jint(JniIntWrapper wrapper) { - return wrapper; -} - -#else - -class JniIntWrapper { - public: - JniIntWrapper() : i_(0) {} - JniIntWrapper(int i) : i_(i) {} - JniIntWrapper(const JniIntWrapper& ji) : i_(ji.i_) {} - template JniIntWrapper(const T& t) : i_(t) {} - jint as_jint() const { return i_; } - private: - // If you get an "is private" error at the line below it is because you used - // an implicit conversion to convert a long to an int when calling Java. - // We disallow this, as a common anti-pattern allows converting a native - // pointer (intptr_t) to a Java int. Please use a Java long to represent - // a native pointer. If you want a lossy conversion, please use an - // explicit conversion in your C++ code. Note an error is only seen when - // compiling on a 64-bit platform, as intptr_t is indistinguishable from - // int on 32-bit platforms. - JniIntWrapper(long); - jint i_; -}; - -inline jint as_jint(const JniIntWrapper& wrapper) { - return wrapper.as_jint(); -} - -#endif // NDEBUG - -#endif // BASE_ANDROID_JNI_INT_WRAPPER_H_ diff --git a/base/android/jni_string.cc b/base/android/jni_string.cc deleted file mode 100644 index f28f649..0000000 --- a/base/android/jni_string.cc +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/jni_string.h" - -#include "base/android/jni_android.h" -#include "base/logging.h" -#include "base/strings/utf_string_conversions.h" - -namespace { - -// Internal version that does not use a scoped local pointer. -jstring ConvertUTF16ToJavaStringImpl(JNIEnv* env, - const base::StringPiece16& str) { - jstring result = env->NewString(str.data(), str.length()); - base::android::CheckException(env); - return result; -} - -} // namespace - -namespace base { -namespace android { - -void ConvertJavaStringToUTF8(JNIEnv* env, jstring str, std::string* result) { - DCHECK(str); - if (!str) { - LOG(WARNING) << "ConvertJavaStringToUTF8 called with null string."; - result->clear(); - return; - } - const jsize length = env->GetStringLength(str); - if (!length) { - result->clear(); - CheckException(env); - return; - } - // JNI's GetStringUTFChars() returns strings in Java "modified" UTF8, so - // instead get the String in UTF16 and convert using chromium's conversion - // function that yields plain (non Java-modified) UTF8. - const jchar* chars = env->GetStringChars(str, NULL); - DCHECK(chars); - UTF16ToUTF8(chars, length, result); - env->ReleaseStringChars(str, chars); - CheckException(env); -} - -std::string ConvertJavaStringToUTF8(JNIEnv* env, jstring str) { - std::string result; - ConvertJavaStringToUTF8(env, str, &result); - return result; -} - -std::string ConvertJavaStringToUTF8(const JavaRef& str) { - return ConvertJavaStringToUTF8(AttachCurrentThread(), str.obj()); -} - -std::string ConvertJavaStringToUTF8(JNIEnv* env, const JavaRef& str) { - return ConvertJavaStringToUTF8(env, str.obj()); -} - -ScopedJavaLocalRef ConvertUTF8ToJavaString( - JNIEnv* env, - const base::StringPiece& str) { - // JNI's NewStringUTF expects "modified" UTF8 so instead create the string - // via our own UTF16 conversion utility. - // Further, Dalvik requires the string passed into NewStringUTF() to come from - // a trusted source. We can't guarantee that all UTF8 will be sanitized before - // it gets here, so constructing via UTF16 side-steps this issue. - // (Dalvik stores strings internally as UTF16 anyway, so there shouldn't be - // a significant performance hit by doing it this way). - return ScopedJavaLocalRef(env, ConvertUTF16ToJavaStringImpl( - env, UTF8ToUTF16(str))); -} - -void ConvertJavaStringToUTF16(JNIEnv* env, jstring str, string16* result) { - DCHECK(str); - if (!str) { - LOG(WARNING) << "ConvertJavaStringToUTF16 called with null string."; - result->clear(); - return; - } - const jsize length = env->GetStringLength(str); - if (!length) { - result->clear(); - CheckException(env); - return; - } - const jchar* chars = env->GetStringChars(str, NULL); - DCHECK(chars); - // GetStringChars isn't required to NULL-terminate the strings - // it returns, so the length must be explicitly checked. - result->assign(chars, length); - env->ReleaseStringChars(str, chars); - CheckException(env); -} - -string16 ConvertJavaStringToUTF16(JNIEnv* env, jstring str) { - string16 result; - ConvertJavaStringToUTF16(env, str, &result); - return result; -} - -string16 ConvertJavaStringToUTF16(const JavaRef& str) { - return ConvertJavaStringToUTF16(AttachCurrentThread(), str.obj()); -} - -string16 ConvertJavaStringToUTF16(JNIEnv* env, const JavaRef& str) { - return ConvertJavaStringToUTF16(env, str.obj()); -} - -ScopedJavaLocalRef ConvertUTF16ToJavaString( - JNIEnv* env, - const base::StringPiece16& str) { - return ScopedJavaLocalRef(env, - ConvertUTF16ToJavaStringImpl(env, str)); -} - -} // namespace android -} // namespace base diff --git a/base/android/jni_string.h b/base/android/jni_string.h deleted file mode 100644 index 09e85f3..0000000 --- a/base/android/jni_string.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2012 The Chromium 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 BASE_ANDROID_JNI_STRING_H_ -#define BASE_ANDROID_JNI_STRING_H_ - -#include -#include - -#include "base/android/scoped_java_ref.h" -#include "base/base_export.h" -#include "base/strings/string_piece.h" - -namespace base { -namespace android { - -// Convert a Java string to UTF8. Returns a std string. -BASE_EXPORT void ConvertJavaStringToUTF8(JNIEnv* env, - jstring str, - std::string* result); -BASE_EXPORT std::string ConvertJavaStringToUTF8(JNIEnv* env, jstring str); -BASE_EXPORT std::string ConvertJavaStringToUTF8(const JavaRef& str); -BASE_EXPORT std::string ConvertJavaStringToUTF8(JNIEnv* env, - const JavaRef& str); - -// Convert a std string to Java string. -BASE_EXPORT ScopedJavaLocalRef ConvertUTF8ToJavaString( - JNIEnv* env, - const base::StringPiece& str); - -// Convert a Java string to UTF16. Returns a string16. -BASE_EXPORT void ConvertJavaStringToUTF16(JNIEnv* env, - jstring str, - string16* result); -BASE_EXPORT string16 ConvertJavaStringToUTF16(JNIEnv* env, jstring str); -BASE_EXPORT string16 ConvertJavaStringToUTF16(const JavaRef& str); -BASE_EXPORT string16 ConvertJavaStringToUTF16(JNIEnv* env, - const JavaRef& str); - -// Convert a string16 to a Java string. -BASE_EXPORT ScopedJavaLocalRef ConvertUTF16ToJavaString( - JNIEnv* env, - const base::StringPiece16& str); - -} // namespace android -} // namespace base - -#endif // BASE_ANDROID_JNI_STRING_H_ diff --git a/base/android/jni_string_unittest.cc b/base/android/jni_string_unittest.cc deleted file mode 100644 index 3da8b87..0000000 --- a/base/android/jni_string_unittest.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/jni_string.h" - -#include "base/android/jni_android.h" -#include "base/android/scoped_java_ref.h" -#include "base/strings/utf_string_conversions.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace android { - -TEST(JniString, BasicConversionsUTF8) { - const std::string kSimpleString = "SimpleTest8"; - JNIEnv* env = AttachCurrentThread(); - std::string result = - ConvertJavaStringToUTF8(ConvertUTF8ToJavaString(env, kSimpleString)); - EXPECT_EQ(kSimpleString, result); -} - -TEST(JniString, BasicConversionsUTF16) { - const string16 kSimpleString = UTF8ToUTF16("SimpleTest16"); - JNIEnv* env = AttachCurrentThread(); - string16 result = - ConvertJavaStringToUTF16(ConvertUTF16ToJavaString(env, kSimpleString)); - EXPECT_EQ(kSimpleString, result); -} - -TEST(JniString, EmptyConversionUTF8) { - const std::string kEmptyString = ""; - JNIEnv* env = AttachCurrentThread(); - std::string result = - ConvertJavaStringToUTF8(ConvertUTF8ToJavaString(env, kEmptyString)); - EXPECT_EQ(kEmptyString, result); -} - -TEST(JniString, EmptyConversionUTF16) { - const string16 kEmptyString = UTF8ToUTF16(""); - JNIEnv* env = AttachCurrentThread(); - string16 result = - ConvertJavaStringToUTF16(ConvertUTF16ToJavaString(env, kEmptyString)); - EXPECT_EQ(kEmptyString, result); -} - -} // namespace android -} // namespace base diff --git a/base/android/scoped_java_ref.cc b/base/android/scoped_java_ref.cc deleted file mode 100644 index 7d31a75..0000000 --- a/base/android/scoped_java_ref.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/scoped_java_ref.h" - -#include "base/android/jni_android.h" -#include "base/logging.h" - -namespace base { -namespace android { -namespace { - -const int kDefaultLocalFrameCapacity = 16; - -} // namespace - -ScopedJavaLocalFrame::ScopedJavaLocalFrame(JNIEnv* env) : env_(env) { - int failed = env_->PushLocalFrame(kDefaultLocalFrameCapacity); - DCHECK(!failed); -} - -ScopedJavaLocalFrame::ScopedJavaLocalFrame(JNIEnv* env, int capacity) - : env_(env) { - int failed = env_->PushLocalFrame(capacity); - DCHECK(!failed); -} - -ScopedJavaLocalFrame::~ScopedJavaLocalFrame() { - env_->PopLocalFrame(nullptr); -} - -#if DCHECK_IS_ON() -// This constructor is inlined when DCHECKs are disabled; don't add anything -// else here. -JavaRef::JavaRef(JNIEnv* env, jobject obj) : obj_(obj) { - if (obj) { - DCHECK(env && env->GetObjectRefType(obj) == JNILocalRefType); - } -} -#endif - -JNIEnv* JavaRef::SetNewLocalRef(JNIEnv* env, jobject obj) { - if (!env) { - env = AttachCurrentThread(); - } else { - DCHECK_EQ(env, AttachCurrentThread()); // Is |env| on correct thread. - } - if (obj) - obj = env->NewLocalRef(obj); - if (obj_) - env->DeleteLocalRef(obj_); - obj_ = obj; - return env; -} - -void JavaRef::SetNewGlobalRef(JNIEnv* env, jobject obj) { - if (!env) { - env = AttachCurrentThread(); - } else { - DCHECK_EQ(env, AttachCurrentThread()); // Is |env| on correct thread. - } - if (obj) - obj = env->NewGlobalRef(obj); - if (obj_) - env->DeleteGlobalRef(obj_); - obj_ = obj; -} - -void JavaRef::ResetLocalRef(JNIEnv* env) { - if (obj_) { - DCHECK_EQ(env, AttachCurrentThread()); // Is |env| on correct thread. - env->DeleteLocalRef(obj_); - obj_ = nullptr; - } -} - -void JavaRef::ResetGlobalRef() { - if (obj_) { - AttachCurrentThread()->DeleteGlobalRef(obj_); - obj_ = nullptr; - } -} - -jobject JavaRef::ReleaseInternal() { - jobject obj = obj_; - obj_ = nullptr; - return obj; -} - -} // namespace android -} // namespace base diff --git a/base/android/scoped_java_ref.h b/base/android/scoped_java_ref.h deleted file mode 100644 index 6d728e9..0000000 --- a/base/android/scoped_java_ref.h +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (c) 2012 The Chromium 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 BASE_ANDROID_SCOPED_JAVA_REF_H_ -#define BASE_ANDROID_SCOPED_JAVA_REF_H_ - -#include -#include - -#include -#include - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" - -namespace base { -namespace android { - -// Creates a new local reference frame, in which at least a given number of -// local references can be created. Note that local references already created -// in previous local frames are still valid in the current local frame. -class BASE_EXPORT ScopedJavaLocalFrame { - public: - explicit ScopedJavaLocalFrame(JNIEnv* env); - ScopedJavaLocalFrame(JNIEnv* env, int capacity); - ~ScopedJavaLocalFrame(); - - private: - // This class is only good for use on the thread it was created on so - // it's safe to cache the non-threadsafe JNIEnv* inside this object. - JNIEnv* env_; - - DISALLOW_COPY_AND_ASSIGN(ScopedJavaLocalFrame); -}; - -// Forward declare the generic java reference template class. -template class JavaRef; - -// Template specialization of JavaRef, which acts as the base class for all -// other JavaRef<> template types. This allows you to e.g. pass -// ScopedJavaLocalRef into a function taking const JavaRef& -template<> -class BASE_EXPORT JavaRef { - public: - // Initializes a null reference. Don't add anything else here; it's inlined. - JavaRef() : obj_(nullptr) {} - - // Allow nullptr to be converted to JavaRef. This avoids having to declare an - // empty JavaRef just to pass null to a function, and makes C++ "nullptr" and - // Java "null" equivalent. - JavaRef(std::nullptr_t) : JavaRef() {} - - // Public to allow destruction of null JavaRef objects. - // Don't add anything else here; it's inlined. - ~JavaRef() {} - - jobject obj() const { return obj_; } - - bool is_null() const { return obj_ == nullptr; } - - protected: - // Takes ownership of the |obj| reference passed; requires it to be a local - // reference type. -#if DCHECK_IS_ON() - // Implementation contains a DCHECK; implement out-of-line when DCHECK_IS_ON. - JavaRef(JNIEnv* env, jobject obj); -#else - // Don't add anything else here; it's inlined. - JavaRef(JNIEnv* env, jobject obj) : obj_(obj) {} -#endif - - void swap(JavaRef& other) { std::swap(obj_, other.obj_); } - - // The following are implementation detail convenience methods, for - // use by the sub-classes. - JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj); - void SetNewGlobalRef(JNIEnv* env, jobject obj); - void ResetLocalRef(JNIEnv* env); - void ResetGlobalRef(); - jobject ReleaseInternal(); - - private: - jobject obj_; - - DISALLOW_COPY_AND_ASSIGN(JavaRef); -}; - -// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful -// for allowing functions to accept a reference without having to mandate -// whether it is a local or global type. -template -class JavaRef : public JavaRef { - public: - JavaRef() {} - JavaRef(std::nullptr_t) : JavaRef(nullptr) {} - ~JavaRef() {} - - T obj() const { return static_cast(JavaRef::obj()); } - - protected: - JavaRef(JNIEnv* env, T obj) : JavaRef(env, obj) {} - - private: - DISALLOW_COPY_AND_ASSIGN(JavaRef); -}; - -// Holds a local reference to a JNI method parameter. -// Method parameters should not be deleted, and so this class exists purely to -// wrap them as a JavaRef in the JNI binding generator. Do not create -// instances manually. -template -class JavaParamRef : public JavaRef { - public: - // Assumes that |obj| is a parameter passed to a JNI method from Java. - // Does not assume ownership as parameters should not be deleted. - JavaParamRef(JNIEnv* env, T obj) : JavaRef(env, obj) {} - - // Allow nullptr to be converted to JavaParamRef. Some unit tests call JNI - // methods directly from C++ and pass null for objects which are not actually - // used by the implementation (e.g. the caller object); allow this to keep - // working. - JavaParamRef(std::nullptr_t) : JavaRef(nullptr) {} - - ~JavaParamRef() {} - - // TODO(torne): remove this cast once we're using JavaRef consistently. - // http://crbug.com/506850 - operator T() const { return JavaRef::obj(); } - - private: - DISALLOW_COPY_AND_ASSIGN(JavaParamRef); -}; - -// Holds a local reference to a Java object. The local reference is scoped -// to the lifetime of this object. -// Instances of this class may hold onto any JNIEnv passed into it until -// destroyed. Therefore, since a JNIEnv is only suitable for use on a single -// thread, objects of this class must be created, used, and destroyed, on a -// single thread. -// Therefore, this class should only be used as a stack-based object and from a -// single thread. If you wish to have the reference outlive the current -// callstack (e.g. as a class member) or you wish to pass it across threads, -// use a ScopedJavaGlobalRef instead. -template -class ScopedJavaLocalRef : public JavaRef { - public: - ScopedJavaLocalRef() : env_(nullptr) {} - ScopedJavaLocalRef(std::nullptr_t) : env_(nullptr) {} - - // Non-explicit copy constructor, to allow ScopedJavaLocalRef to be returned - // by value as this is the normal usage pattern. - ScopedJavaLocalRef(const ScopedJavaLocalRef& other) - : env_(other.env_) { - this->SetNewLocalRef(env_, other.obj()); - } - - ScopedJavaLocalRef(ScopedJavaLocalRef&& other) : env_(other.env_) { - this->swap(other); - } - - explicit ScopedJavaLocalRef(const JavaRef& other) : env_(nullptr) { - this->Reset(other); - } - - // Assumes that |obj| is a local reference to a Java object and takes - // ownership of this local reference. - // TODO(torne): this shouldn't be used outside of JNI helper functions but - // there are currently some cases where there aren't helpers for things. - ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef(env, obj), env_(env) {} - - ~ScopedJavaLocalRef() { - this->Reset(); - } - - // Overloaded assignment operator defined for consistency with the implicit - // copy constructor. - void operator=(const ScopedJavaLocalRef& other) { - this->Reset(other); - } - - void operator=(ScopedJavaLocalRef&& other) { - env_ = other.env_; - this->swap(other); - } - - void Reset() { - this->ResetLocalRef(env_); - } - - void Reset(const ScopedJavaLocalRef& other) { - // We can copy over env_ here as |other| instance must be from the same - // thread as |this| local ref. (See class comment for multi-threading - // limitations, and alternatives). - this->Reset(other.env_, other.obj()); - } - - void Reset(const JavaRef& other) { - // If |env_| was not yet set (is still null) it will be attached to the - // current thread in SetNewLocalRef(). - this->Reset(env_, other.obj()); - } - - // Creates a new local reference to the Java object, unlike the constructor - // with the same parameters that takes ownership of the existing reference. - // TODO(torne): these should match as this is confusing. - void Reset(JNIEnv* env, T obj) { env_ = this->SetNewLocalRef(env, obj); } - - // Releases the local reference to the caller. The caller *must* delete the - // local reference when it is done with it. Note that calling a Java method - // is *not* a transfer of ownership and Release() should not be used. - T Release() { - return static_cast(this->ReleaseInternal()); - } - - private: - // This class is only good for use on the thread it was created on so - // it's safe to cache the non-threadsafe JNIEnv* inside this object. - JNIEnv* env_; - - // Prevent ScopedJavaLocalRef(JNIEnv*, T obj) from being used to take - // ownership of a JavaParamRef's underlying object - parameters are not - // allowed to be deleted and so should not be owned by ScopedJavaLocalRef. - // TODO(torne): this can be removed once JavaParamRef no longer has an - // implicit conversion back to T. - ScopedJavaLocalRef(JNIEnv* env, const JavaParamRef& other); -}; - -// Holds a global reference to a Java object. The global reference is scoped -// to the lifetime of this object. This class does not hold onto any JNIEnv* -// passed to it, hence it is safe to use across threads (within the constraints -// imposed by the underlying Java object that it references). -template -class ScopedJavaGlobalRef : public JavaRef { - public: - ScopedJavaGlobalRef() {} - ScopedJavaGlobalRef(std::nullptr_t) {} - - ScopedJavaGlobalRef(const ScopedJavaGlobalRef& other) { - this->Reset(other); - } - - ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other) { this->swap(other); } - - ScopedJavaGlobalRef(JNIEnv* env, T obj) { this->Reset(env, obj); } - - explicit ScopedJavaGlobalRef(const JavaRef& other) { this->Reset(other); } - - ~ScopedJavaGlobalRef() { - this->Reset(); - } - - // Overloaded assignment operator defined for consistency with the implicit - // copy constructor. - void operator=(const ScopedJavaGlobalRef& other) { - this->Reset(other); - } - - void operator=(ScopedJavaGlobalRef&& other) { this->swap(other); } - - void Reset() { - this->ResetGlobalRef(); - } - - void Reset(const JavaRef& other) { this->Reset(nullptr, other.obj()); } - - void Reset(JNIEnv* env, const JavaParamRef& other) { - this->Reset(env, other.obj()); - } - - void Reset(JNIEnv* env, T obj) { this->SetNewGlobalRef(env, obj); } - - // Releases the global reference to the caller. The caller *must* delete the - // global reference when it is done with it. Note that calling a Java method - // is *not* a transfer of ownership and Release() should not be used. - T Release() { - return static_cast(this->ReleaseInternal()); - } -}; - -// Temporary type for parameters to Java functions, to allow incremental -// migration from bare jobject to JavaRef. Don't use outside JNI generator. -template -class JavaRefOrBare { - public: - JavaRefOrBare(std::nullptr_t) : obj_(nullptr) {} - JavaRefOrBare(const JavaRef& ref) : obj_(ref.obj()) {} - JavaRefOrBare(T obj) : obj_(obj) {} - T obj() const { return obj_; } - - private: - T obj_; - - DISALLOW_COPY_AND_ASSIGN(JavaRefOrBare); -}; - -} // namespace android -} // namespace base - -#endif // BASE_ANDROID_SCOPED_JAVA_REF_H_ diff --git a/base/android/scoped_java_ref_unittest.cc b/base/android/scoped_java_ref_unittest.cc deleted file mode 100644 index 99d035b..0000000 --- a/base/android/scoped_java_ref_unittest.cc +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/scoped_java_ref.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace android { - -namespace { -int g_local_refs = 0; -int g_global_refs = 0; - -const JNINativeInterface* g_previous_functions; - -jobject NewGlobalRef(JNIEnv* env, jobject obj) { - ++g_global_refs; - return g_previous_functions->NewGlobalRef(env, obj); -} - -void DeleteGlobalRef(JNIEnv* env, jobject obj) { - --g_global_refs; - return g_previous_functions->DeleteGlobalRef(env, obj); -} - -jobject NewLocalRef(JNIEnv* env, jobject obj) { - ++g_local_refs; - return g_previous_functions->NewLocalRef(env, obj); -} - -void DeleteLocalRef(JNIEnv* env, jobject obj) { - --g_local_refs; - return g_previous_functions->DeleteLocalRef(env, obj); -} -} // namespace - -class ScopedJavaRefTest : public testing::Test { - protected: - void SetUp() override { - g_local_refs = 0; - g_global_refs = 0; - JNIEnv* env = AttachCurrentThread(); - g_previous_functions = env->functions; - hooked_functions = *g_previous_functions; - env->functions = &hooked_functions; - // We inject our own functions in JNINativeInterface so we can keep track - // of the reference counting ourselves. - hooked_functions.NewGlobalRef = &NewGlobalRef; - hooked_functions.DeleteGlobalRef = &DeleteGlobalRef; - hooked_functions.NewLocalRef = &NewLocalRef; - hooked_functions.DeleteLocalRef = &DeleteLocalRef; - } - - void TearDown() override { - JNIEnv* env = AttachCurrentThread(); - env->functions = g_previous_functions; - } - // From JellyBean release, the instance of this struct provided in JNIEnv is - // read-only, so we deep copy it to allow individual functions to be hooked. - JNINativeInterface hooked_functions; -}; - -// The main purpose of this is testing the various conversions compile. -TEST_F(ScopedJavaRefTest, Conversions) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef str = ConvertUTF8ToJavaString(env, "string"); - ScopedJavaGlobalRef global(str); - { - ScopedJavaGlobalRef global_obj(str); - ScopedJavaLocalRef local_obj(global); - const JavaRef& obj_ref1(str); - const JavaRef& obj_ref2(global); - EXPECT_TRUE(env->IsSameObject(obj_ref1.obj(), obj_ref2.obj())); - EXPECT_TRUE(env->IsSameObject(global_obj.obj(), obj_ref2.obj())); - } - global.Reset(str); - const JavaRef& str_ref = str; - EXPECT_EQ("string", ConvertJavaStringToUTF8(str_ref)); - str.Reset(); -} - -TEST_F(ScopedJavaRefTest, RefCounts) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef str; - // The ConvertJavaStringToUTF8 below creates a new string that would normally - // return a local ref. We simulate that by starting the g_local_refs count at - // 1. - g_local_refs = 1; - str.Reset(ConvertUTF8ToJavaString(env, "string")); - EXPECT_EQ(1, g_local_refs); - EXPECT_EQ(0, g_global_refs); - { - ScopedJavaGlobalRef global_str(str); - ScopedJavaGlobalRef global_obj(global_str); - EXPECT_EQ(1, g_local_refs); - EXPECT_EQ(2, g_global_refs); - - ScopedJavaLocalRef str2(env, str.Release()); - EXPECT_EQ(1, g_local_refs); - { - ScopedJavaLocalRef str3(str2); - EXPECT_EQ(2, g_local_refs); - } - EXPECT_EQ(1, g_local_refs); - { - ScopedJavaLocalRef str4((ScopedJavaLocalRef(str2))); - EXPECT_EQ(2, g_local_refs); - } - EXPECT_EQ(1, g_local_refs); - { - ScopedJavaLocalRef str5; - str5 = ScopedJavaLocalRef(str2); - EXPECT_EQ(2, g_local_refs); - } - EXPECT_EQ(1, g_local_refs); - str2.Reset(); - EXPECT_EQ(0, g_local_refs); - global_str.Reset(); - EXPECT_EQ(1, g_global_refs); - ScopedJavaGlobalRef global_obj2(global_obj); - EXPECT_EQ(2, g_global_refs); - } - - EXPECT_EQ(0, g_local_refs); - EXPECT_EQ(0, g_global_refs); -} - -} // namespace android -} // namespace base diff --git a/build/android/gyp/util/__init__.py b/build/android/gyp/util/__init__.py deleted file mode 100644 index 727e987..0000000 --- a/build/android/gyp/util/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2012 The Chromium 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/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py deleted file mode 100644 index abd2dfc..0000000 --- a/build/android/gyp/util/build_utils.py +++ /dev/null @@ -1,589 +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. - -import ast -import contextlib -import fnmatch -import json -import os -import pipes -import re -import shlex -import shutil -import stat -import subprocess -import sys -import tempfile -import zipfile - -# Some clients do not add //build/android/gyp to PYTHONPATH. -import md5_check # pylint: disable=relative-import - -# pylib conflicts with mojo/public/tools/bindings/pylib. Prioritize -# build/android/pylib. -# PYTHONPATH wouldn't help in this case, because soong put source files under -# temp directory for each build, so the abspath is unknown until the -# execution. -# sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) -sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) -from pylib.constants import host_paths - -sys.path.append(os.path.join(os.path.dirname(__file__), - os.pardir, os.pardir, os.pardir)) -import gn_helpers - -COLORAMA_ROOT = os.path.join(host_paths.DIR_SOURCE_ROOT, - 'third_party', 'colorama', 'src') -# aapt should ignore OWNERS files in addition the default ignore pattern. -AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:

_*:' + - '!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp') -HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) -_HERMETIC_FILE_ATTR = (0644 << 16L) - - -@contextlib.contextmanager -def TempDir(): - dirname = tempfile.mkdtemp() - try: - yield dirname - finally: - shutil.rmtree(dirname) - - -def MakeDirectory(dir_path): - try: - os.makedirs(dir_path) - except OSError: - pass - - -def DeleteDirectory(dir_path): - if os.path.exists(dir_path): - shutil.rmtree(dir_path) - - -def Touch(path, fail_if_missing=False): - if fail_if_missing and not os.path.exists(path): - raise Exception(path + ' doesn\'t exist.') - - MakeDirectory(os.path.dirname(path)) - with open(path, 'a'): - os.utime(path, None) - - -def FindInDirectory(directory, filename_filter): - files = [] - for root, _dirnames, filenames in os.walk(directory): - matched_files = fnmatch.filter(filenames, filename_filter) - files.extend((os.path.join(root, f) for f in matched_files)) - return files - - -def FindInDirectories(directories, filename_filter): - all_files = [] - for directory in directories: - all_files.extend(FindInDirectory(directory, filename_filter)) - return all_files - - -def ParseGnList(gn_string): - """Converts a command-line parameter into a list. - - If the input starts with a '[' it is assumed to be a GN-formatted list and - it will be parsed accordingly. When empty an empty list will be returned. - Otherwise, the parameter will be treated as a single raw string (not - GN-formatted in that it's not assumed to have literal quotes that must be - removed) and a list will be returned containing that string. - - The common use for this behavior is in the Android build where things can - take lists of @FileArg references that are expanded via ExpandFileArgs. - """ - if gn_string.startswith('['): - parser = gn_helpers.GNValueParser(gn_string) - return parser.ParseList() - if len(gn_string): - return [ gn_string ] - return [] - - -def CheckOptions(options, parser, required=None): - if not required: - return - for option_name in required: - if getattr(options, option_name) is None: - parser.error('--%s is required' % option_name.replace('_', '-')) - - -def WriteJson(obj, path, only_if_changed=False): - old_dump = None - if os.path.exists(path): - with open(path, 'r') as oldfile: - old_dump = oldfile.read() - - new_dump = json.dumps(obj, sort_keys=True, indent=2, separators=(',', ': ')) - - if not only_if_changed or old_dump != new_dump: - with open(path, 'w') as outfile: - outfile.write(new_dump) - - -def ReadJson(path): - with open(path, 'r') as jsonfile: - return json.load(jsonfile) - - -class CalledProcessError(Exception): - """This exception is raised when the process run by CheckOutput - exits with a non-zero exit code.""" - - def __init__(self, cwd, args, output): - super(CalledProcessError, self).__init__() - self.cwd = cwd - self.args = args - self.output = output - - def __str__(self): - # A user should be able to simply copy and paste the command that failed - # into their shell. - copyable_command = '( cd {}; {} )'.format(os.path.abspath(self.cwd), - ' '.join(map(pipes.quote, self.args))) - return 'Command failed: {}\n{}'.format(copyable_command, self.output) - - -# This can be used in most cases like subprocess.check_output(). The output, -# particularly when the command fails, better highlights the command's failure. -# If the command fails, raises a build_utils.CalledProcessError. -def CheckOutput(args, cwd=None, env=None, - print_stdout=False, print_stderr=True, - stdout_filter=None, - stderr_filter=None, - fail_func=lambda returncode, stderr: returncode != 0): - if not cwd: - cwd = os.getcwd() - - child = subprocess.Popen(args, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env) - stdout, stderr = child.communicate() - - if stdout_filter is not None: - stdout = stdout_filter(stdout) - - if stderr_filter is not None: - stderr = stderr_filter(stderr) - - if fail_func(child.returncode, stderr): - raise CalledProcessError(cwd, args, stdout + stderr) - - if print_stdout: - sys.stdout.write(stdout) - if print_stderr: - sys.stderr.write(stderr) - - return stdout - - -def GetModifiedTime(path): - # For a symlink, the modified time should be the greater of the link's - # modified time and the modified time of the target. - return max(os.lstat(path).st_mtime, os.stat(path).st_mtime) - - -def IsTimeStale(output, inputs): - if not os.path.exists(output): - return True - - output_time = GetModifiedTime(output) - for i in inputs: - if GetModifiedTime(i) > output_time: - return True - return False - - -def IsDeviceReady(): - device_state = CheckOutput(['adb', 'get-state']) - return device_state.strip() == 'device' - - -def CheckZipPath(name): - if os.path.normpath(name) != name: - raise Exception('Non-canonical zip path: %s' % name) - if os.path.isabs(name): - raise Exception('Absolute zip path: %s' % name) - - -def IsSymlink(zip_file, name): - zi = zip_file.getinfo(name) - - # The two high-order bytes of ZipInfo.external_attr represent - # UNIX permissions and file type bits. - return stat.S_ISLNK(zi.external_attr >> 16L) - - -def ExtractAll(zip_path, path=None, no_clobber=True, pattern=None, - predicate=None): - if path is None: - path = os.getcwd() - elif not os.path.exists(path): - MakeDirectory(path) - - if not zipfile.is_zipfile(zip_path): - raise Exception('Invalid zip file: %s' % zip_path) - - extracted = [] - with zipfile.ZipFile(zip_path) as z: - for name in z.namelist(): - if name.endswith('/'): - continue - if pattern is not None: - if not fnmatch.fnmatch(name, pattern): - continue - if predicate and not predicate(name): - continue - CheckZipPath(name) - if no_clobber: - output_path = os.path.join(path, name) - if os.path.exists(output_path): - raise Exception( - 'Path already exists from zip: %s %s %s' - % (zip_path, name, output_path)) - if IsSymlink(z, name): - dest = os.path.join(path, name) - MakeDirectory(os.path.dirname(dest)) - os.symlink(z.read(name), dest) - extracted.append(dest) - else: - z.extract(name, path) - extracted.append(os.path.join(path, name)) - - return extracted - - -def AddToZipHermetic(zip_file, zip_path, src_path=None, data=None, - compress=None): - """Adds a file to the given ZipFile with a hard-coded modified time. - - Args: - zip_file: ZipFile instance to add the file to. - zip_path: Destination path within the zip file. - src_path: Path of the source file. Mutually exclusive with |data|. - data: File data as a string. - compress: Whether to enable compression. Default is take from ZipFile - constructor. - """ - assert (src_path is None) != (data is None), ( - '|src_path| and |data| are mutually exclusive.') - CheckZipPath(zip_path) - zipinfo = zipfile.ZipInfo(filename=zip_path, date_time=HERMETIC_TIMESTAMP) - zipinfo.external_attr = _HERMETIC_FILE_ATTR - - if src_path and os.path.islink(src_path): - zipinfo.filename = zip_path - zipinfo.external_attr |= stat.S_IFLNK << 16L # mark as a symlink - zip_file.writestr(zipinfo, os.readlink(src_path)) - return - - if src_path: - with file(src_path) as f: - data = f.read() - - # zipfile will deflate even when it makes the file bigger. To avoid - # growing files, disable compression at an arbitrary cut off point. - if len(data) < 16: - compress = False - - # None converts to ZIP_STORED, when passed explicitly rather than the - # default passed to the ZipFile constructor. - compress_type = zip_file.compression - if compress is not None: - compress_type = zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED - zip_file.writestr(zipinfo, data, compress_type) - - -def DoZip(inputs, output, base_dir=None): - """Creates a zip file from a list of files. - - Args: - inputs: A list of paths to zip, or a list of (zip_path, fs_path) tuples. - output: Destination .zip file. - base_dir: Prefix to strip from inputs. - """ - input_tuples = [] - for tup in inputs: - if isinstance(tup, basestring): - tup = (os.path.relpath(tup, base_dir), tup) - input_tuples.append(tup) - - # Sort by zip path to ensure stable zip ordering. - input_tuples.sort(key=lambda tup: tup[0]) - with zipfile.ZipFile(output, 'w') as outfile: - for zip_path, fs_path in input_tuples: - AddToZipHermetic(outfile, zip_path, src_path=fs_path) - - -def ZipDir(output, base_dir): - """Creates a zip file from a directory.""" - inputs = [] - for root, _, files in os.walk(base_dir): - for f in files: - inputs.append(os.path.join(root, f)) - DoZip(inputs, output, base_dir) - - -def MatchesGlob(path, filters): - """Returns whether the given path matches any of the given glob patterns.""" - return filters and any(fnmatch.fnmatch(path, f) for f in filters) - - -def MergeZips(output, inputs, exclude_patterns=None, path_transform=None): - path_transform = path_transform or (lambda p, z: p) - added_names = set() - - output_is_already_open = not isinstance(output, basestring) - if output_is_already_open: - assert isinstance(output, zipfile.ZipFile) - out_zip = output - else: - out_zip = zipfile.ZipFile(output, 'w') - - try: - for in_file in inputs: - with zipfile.ZipFile(in_file, 'r') as in_zip: - in_zip._expected_crc = None - for info in in_zip.infolist(): - # Ignore directories. - if info.filename[-1] == '/': - continue - dst_name = path_transform(info.filename, in_file) - already_added = dst_name in added_names - if not already_added and not MatchesGlob(dst_name, exclude_patterns): - AddToZipHermetic(out_zip, dst_name, data=in_zip.read(info), - compress=info.compress_type != zipfile.ZIP_STORED) - added_names.add(dst_name) - finally: - if not output_is_already_open: - out_zip.close() - - -def PrintWarning(message): - print 'WARNING: ' + message - - -def PrintBigWarning(message): - print '***** ' * 8 - PrintWarning(message) - print '***** ' * 8 - - -def GetSortedTransitiveDependencies(top, deps_func): - """Gets the list of all transitive dependencies in sorted order. - - There should be no cycles in the dependency graph. - - Args: - top: a list of the top level nodes - deps_func: A function that takes a node and returns its direct dependencies. - Returns: - A list of all transitive dependencies of nodes in top, in order (a node will - appear in the list at a higher index than all of its dependencies). - """ - def Node(dep): - return (dep, deps_func(dep)) - - # First: find all deps - unchecked_deps = list(top) - all_deps = set(top) - while unchecked_deps: - dep = unchecked_deps.pop() - new_deps = deps_func(dep).difference(all_deps) - unchecked_deps.extend(new_deps) - all_deps = all_deps.union(new_deps) - - # Then: simple, slow topological sort. - sorted_deps = [] - unsorted_deps = dict(map(Node, all_deps)) - while unsorted_deps: - for library, dependencies in unsorted_deps.items(): - if not dependencies.intersection(unsorted_deps.keys()): - sorted_deps.append(library) - del unsorted_deps[library] - - return sorted_deps - - -def GetPythonDependencies(): - """Gets the paths of imported non-system python modules. - - A path is assumed to be a "system" import if it is outside of chromium's - src/. The paths will be relative to the current directory. - """ - module_paths = GetModulePaths() - - abs_module_paths = map(os.path.abspath, module_paths) - - assert os.path.isabs(host_paths.DIR_SOURCE_ROOT) - non_system_module_paths = [ - p for p in abs_module_paths if p.startswith(host_paths.DIR_SOURCE_ROOT)] - def ConvertPycToPy(s): - if s.endswith('.pyc'): - return s[:-1] - return s - - non_system_module_paths = map(ConvertPycToPy, non_system_module_paths) - non_system_module_paths = map(os.path.relpath, non_system_module_paths) - return sorted(set(non_system_module_paths)) - - -def GetModulePaths(): - """Returns the paths to all of the modules in sys.modules.""" - ForceLazyModulesToLoad() - return (m.__file__ for m in sys.modules.itervalues() - if m is not None and hasattr(m, '__file__')) - - -def ForceLazyModulesToLoad(): - """Forces any lazily imported modules to fully load themselves. - - Inspecting the modules' __file__ attribute causes lazily imported modules - (e.g. from email) to get fully imported and update sys.modules. Iterate - over the values until sys.modules stabilizes so that no modules are missed. - """ - while True: - num_modules_before = len(sys.modules.keys()) - for m in sys.modules.values(): - if m is not None and hasattr(m, '__file__'): - _ = m.__file__ - num_modules_after = len(sys.modules.keys()) - if num_modules_before == num_modules_after: - break - - -def AddDepfileOption(parser): - # TODO(agrieve): Get rid of this once we've moved to argparse. - if hasattr(parser, 'add_option'): - func = parser.add_option - else: - func = parser.add_argument - func('--depfile', - help='Path to depfile (refer to `gn help depfile`)') - - -def WriteDepfile(depfile_path, first_gn_output, inputs=None, add_pydeps=True): - assert depfile_path != first_gn_output # http://crbug.com/646165 - inputs = inputs or [] - if add_pydeps: - inputs = GetPythonDependencies() + inputs - MakeDirectory(os.path.dirname(depfile_path)) - # Ninja does not support multiple outputs in depfiles. - with open(depfile_path, 'w') as depfile: - depfile.write(first_gn_output.replace(' ', '\\ ')) - depfile.write(': ') - depfile.write(' '.join(i.replace(' ', '\\ ') for i in inputs)) - depfile.write('\n') - - -def ExpandFileArgs(args): - """Replaces file-arg placeholders in args. - - These placeholders have the form: - @FileArg(filename:key1:key2:...:keyn) - - The value of such a placeholder is calculated by reading 'filename' as json. - And then extracting the value at [key1][key2]...[keyn]. - - Note: This intentionally does not return the list of files that appear in such - placeholders. An action that uses file-args *must* know the paths of those - files prior to the parsing of the arguments (typically by explicitly listing - them in the action's inputs in build files). - """ - new_args = list(args) - file_jsons = dict() - r = re.compile('@FileArg\((.*?)\)') - for i, arg in enumerate(args): - match = r.search(arg) - if not match: - continue - - if match.end() != len(arg): - raise Exception('Unexpected characters after FileArg: ' + arg) - - lookup_path = match.group(1).split(':') - file_path = lookup_path[0] - if not file_path in file_jsons: - file_jsons[file_path] = ReadJson(file_path) - - expansion = file_jsons[file_path] - for k in lookup_path[1:]: - expansion = expansion[k] - - # This should match ParseGNList. The output is either a GN-formatted list - # or a literal (with no quotes). - if isinstance(expansion, list): - new_args[i] = arg[:match.start()] + gn_helpers.ToGNString(expansion) - else: - new_args[i] = arg[:match.start()] + str(expansion) - - return new_args - - -def ReadSourcesList(sources_list_file_name): - """Reads a GN-written file containing list of file names and returns a list. - - Note that this function should not be used to parse response files. - """ - with open(sources_list_file_name) as f: - return [file_name.strip() for file_name in f] - - -def CallAndWriteDepfileIfStale(function, options, record_path=None, - input_paths=None, input_strings=None, - output_paths=None, force=False, - pass_changes=False, - depfile_deps=None): - """Wraps md5_check.CallAndRecordIfStale() and also writes dep & stamp files. - - Depfiles and stamp files are automatically added to output_paths when present - in the |options| argument. They are then created after |function| is called. - - By default, only python dependencies are added to the depfile. If there are - other input paths that are not captured by GN deps, then they should be listed - in depfile_deps. It's important to write paths to the depfile that are already - captured by GN deps since GN args can cause GN deps to change, and such - changes are not immediately reflected in depfiles (http://crbug.com/589311). - """ - if not output_paths: - raise Exception('At least one output_path must be specified.') - input_paths = list(input_paths or []) - input_strings = list(input_strings or []) - output_paths = list(output_paths or []) - - python_deps = None - if hasattr(options, 'depfile') and options.depfile: - python_deps = GetPythonDependencies() - input_paths += python_deps - output_paths += [options.depfile] - - stamp_file = hasattr(options, 'stamp') and options.stamp - if stamp_file: - output_paths += [stamp_file] - - def on_stale_md5(changes): - args = (changes,) if pass_changes else () - function(*args) - if python_deps is not None: - all_depfile_deps = list(python_deps) - if depfile_deps: - all_depfile_deps.extend(depfile_deps) - WriteDepfile(options.depfile, output_paths[0], all_depfile_deps, - add_pydeps=False) - if stamp_file: - Touch(stamp_file) - - md5_check.CallAndRecordIfStale( - on_stale_md5, - record_path=record_path, - input_paths=input_paths, - input_strings=input_strings, - output_paths=output_paths, - force=force, - pass_changes=True) diff --git a/build/android/gyp/util/md5_check.py b/build/android/gyp/util/md5_check.py deleted file mode 100644 index 7659124..0000000 --- a/build/android/gyp/util/md5_check.py +++ /dev/null @@ -1,410 +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. - -import difflib -import hashlib -import itertools -import json -import os -import sys -import zipfile - - -# When set and a difference is detected, a diff of what changed is printed. -PRINT_EXPLANATIONS = int(os.environ.get('PRINT_BUILD_EXPLANATIONS', 0)) - -# An escape hatch that causes all targets to be rebuilt. -_FORCE_REBUILD = int(os.environ.get('FORCE_REBUILD', 0)) - - -def CallAndRecordIfStale( - function, record_path=None, input_paths=None, input_strings=None, - output_paths=None, force=False, pass_changes=False): - """Calls function if outputs are stale. - - Outputs are considered stale if: - - any output_paths are missing, or - - the contents of any file within input_paths has changed, or - - the contents of input_strings has changed. - - To debug which files are out-of-date, set the environment variable: - PRINT_MD5_DIFFS=1 - - Args: - function: The function to call. - record_path: Path to record metadata. - Defaults to output_paths[0] + '.md5.stamp' - input_paths: List of paths to calcualte an md5 sum on. - input_strings: List of strings to record verbatim. - output_paths: List of output paths. - force: Whether to treat outputs as missing regardless of whether they - actually are. - pass_changes: Whether to pass a Changes instance to |function|. - """ - assert record_path or output_paths - input_paths = input_paths or [] - input_strings = input_strings or [] - output_paths = output_paths or [] - record_path = record_path or output_paths[0] + '.md5.stamp' - - assert record_path.endswith('.stamp'), ( - 'record paths must end in \'.stamp\' so that they are easy to find ' - 'and delete') - - new_metadata = _Metadata() - new_metadata.AddStrings(input_strings) - - for path in input_paths: - if _IsZipFile(path): - entries = _ExtractZipEntries(path) - new_metadata.AddZipFile(path, entries) - else: - new_metadata.AddFile(path, _Md5ForPath(path)) - - old_metadata = None - force = force or _FORCE_REBUILD - missing_outputs = [x for x in output_paths if force or not os.path.exists(x)] - # When outputs are missing, don't bother gathering change information. - if not missing_outputs and os.path.exists(record_path): - with open(record_path, 'r') as jsonfile: - try: - old_metadata = _Metadata.FromFile(jsonfile) - except: # pylint: disable=bare-except - pass # Not yet using new file format. - - changes = Changes(old_metadata, new_metadata, force, missing_outputs) - if not changes.HasChanges(): - return - - if PRINT_EXPLANATIONS: - print '=' * 80 - print 'Target is stale: %s' % record_path - print changes.DescribeDifference() - print '=' * 80 - - args = (changes,) if pass_changes else () - function(*args) - - with open(record_path, 'w') as f: - new_metadata.ToFile(f) - - -class Changes(object): - """Provides and API for querying what changed between runs.""" - - def __init__(self, old_metadata, new_metadata, force, missing_outputs): - self.old_metadata = old_metadata - self.new_metadata = new_metadata - self.force = force - self.missing_outputs = missing_outputs - - def _GetOldTag(self, path, subpath=None): - return self.old_metadata and self.old_metadata.GetTag(path, subpath) - - def HasChanges(self): - """Returns whether any changes exist.""" - return (self.force or - not self.old_metadata or - self.old_metadata.StringsMd5() != self.new_metadata.StringsMd5() or - self.old_metadata.FilesMd5() != self.new_metadata.FilesMd5()) - - def AddedOrModifiedOnly(self): - """Returns whether the only changes were from added or modified (sub)files. - - No missing outputs, no removed paths/subpaths. - """ - if (self.force or - not self.old_metadata or - self.old_metadata.StringsMd5() != self.new_metadata.StringsMd5()): - return False - if any(self.IterRemovedPaths()): - return False - for path in self.IterModifiedPaths(): - if any(self.IterRemovedSubpaths(path)): - return False - return True - - def IterAllPaths(self): - """Generator for paths.""" - return self.new_metadata.IterPaths(); - - def IterAllSubpaths(self, path): - """Generator for subpaths.""" - return self.new_metadata.IterSubpaths(path); - - def IterAddedPaths(self): - """Generator for paths that were added.""" - for path in self.new_metadata.IterPaths(): - if self._GetOldTag(path) is None: - yield path - - def IterAddedSubpaths(self, path): - """Generator for paths that were added within the given zip file.""" - for subpath in self.new_metadata.IterSubpaths(path): - if self._GetOldTag(path, subpath) is None: - yield subpath - - def IterRemovedPaths(self): - """Generator for paths that were removed.""" - if self.old_metadata: - for path in self.old_metadata.IterPaths(): - if self.new_metadata.GetTag(path) is None: - yield path - - def IterRemovedSubpaths(self, path): - """Generator for paths that were removed within the given zip file.""" - if self.old_metadata: - for subpath in self.old_metadata.IterSubpaths(path): - if self.new_metadata.GetTag(path, subpath) is None: - yield subpath - - def IterModifiedPaths(self): - """Generator for paths whose contents have changed.""" - for path in self.new_metadata.IterPaths(): - old_tag = self._GetOldTag(path) - new_tag = self.new_metadata.GetTag(path) - if old_tag is not None and old_tag != new_tag: - yield path - - def IterModifiedSubpaths(self, path): - """Generator for paths within a zip file whose contents have changed.""" - for subpath in self.new_metadata.IterSubpaths(path): - old_tag = self._GetOldTag(path, subpath) - new_tag = self.new_metadata.GetTag(path, subpath) - if old_tag is not None and old_tag != new_tag: - yield subpath - - def IterChangedPaths(self): - """Generator for all changed paths (added/removed/modified).""" - return itertools.chain(self.IterRemovedPaths(), - self.IterModifiedPaths(), - self.IterAddedPaths()) - - def IterChangedSubpaths(self, path): - """Generator for paths within a zip that were added/removed/modified.""" - return itertools.chain(self.IterRemovedSubpaths(path), - self.IterModifiedSubpaths(path), - self.IterAddedSubpaths(path)) - - def DescribeDifference(self): - """Returns a human-readable description of what changed.""" - if self.force: - return 'force=True' - elif self.missing_outputs: - return 'Outputs do not exist:\n ' + '\n '.join(self.missing_outputs) - elif self.old_metadata is None: - return 'Previous stamp file not found.' - - if self.old_metadata.StringsMd5() != self.new_metadata.StringsMd5(): - ndiff = difflib.ndiff(self.old_metadata.GetStrings(), - self.new_metadata.GetStrings()) - changed = [s for s in ndiff if not s.startswith(' ')] - return 'Input strings changed:\n ' + '\n '.join(changed) - - if self.old_metadata.FilesMd5() == self.new_metadata.FilesMd5(): - return "There's no difference." - - lines = [] - lines.extend('Added: ' + p for p in self.IterAddedPaths()) - lines.extend('Removed: ' + p for p in self.IterRemovedPaths()) - for path in self.IterModifiedPaths(): - lines.append('Modified: ' + path) - lines.extend(' -> Subpath added: ' + p - for p in self.IterAddedSubpaths(path)) - lines.extend(' -> Subpath removed: ' + p - for p in self.IterRemovedSubpaths(path)) - lines.extend(' -> Subpath modified: ' + p - for p in self.IterModifiedSubpaths(path)) - if lines: - return 'Input files changed:\n ' + '\n '.join(lines) - return 'I have no idea what changed (there is a bug).' - - -class _Metadata(object): - """Data model for tracking change metadata.""" - # Schema: - # { - # "files-md5": "VALUE", - # "strings-md5": "VALUE", - # "input-files": [ - # { - # "path": "path.jar", - # "tag": "{MD5 of entries}", - # "entries": [ - # { "path": "org/chromium/base/Foo.class", "tag": "{CRC32}" }, ... - # ] - # }, { - # "path": "path.txt", - # "tag": "{MD5}", - # } - # ], - # "input-strings": ["a", "b", ...], - # } - def __init__(self): - self._files_md5 = None - self._strings_md5 = None - self._files = [] - self._strings = [] - # Map of (path, subpath) -> entry. Created upon first call to _GetEntry(). - self._file_map = None - - @classmethod - def FromFile(cls, fileobj): - """Returns a _Metadata initialized from a file object.""" - ret = cls() - obj = json.load(fileobj) - ret._files_md5 = obj['files-md5'] - ret._strings_md5 = obj['strings-md5'] - ret._files = obj['input-files'] - ret._strings = obj['input-strings'] - return ret - - def ToFile(self, fileobj): - """Serializes metadata to the given file object.""" - obj = { - "files-md5": self.FilesMd5(), - "strings-md5": self.StringsMd5(), - "input-files": self._files, - "input-strings": self._strings, - } - json.dump(obj, fileobj, indent=2) - - def _AssertNotQueried(self): - assert self._files_md5 is None - assert self._strings_md5 is None - assert self._file_map is None - - def AddStrings(self, values): - self._AssertNotQueried() - self._strings.extend(str(v) for v in values) - - def AddFile(self, path, tag): - """Adds metadata for a non-zip file. - - Args: - path: Path to the file. - tag: A short string representative of the file contents. - """ - self._AssertNotQueried() - self._files.append({ - 'path': path, - 'tag': tag, - }) - - def AddZipFile(self, path, entries): - """Adds metadata for a zip file. - - Args: - path: Path to the file. - entries: List of (subpath, tag) tuples for entries within the zip. - """ - self._AssertNotQueried() - tag = _ComputeInlineMd5(itertools.chain((e[0] for e in entries), - (e[1] for e in entries))) - self._files.append({ - 'path': path, - 'tag': tag, - 'entries': [{"path": e[0], "tag": e[1]} for e in entries], - }) - - def GetStrings(self): - """Returns the list of input strings.""" - return self._strings - - def FilesMd5(self): - """Lazily computes and returns the aggregate md5 of input files.""" - if self._files_md5 is None: - # Omit paths from md5 since temporary files have random names. - self._files_md5 = _ComputeInlineMd5( - self.GetTag(p) for p in sorted(self.IterPaths())) - return self._files_md5 - - def StringsMd5(self): - """Lazily computes and returns the aggregate md5 of input strings.""" - if self._strings_md5 is None: - self._strings_md5 = _ComputeInlineMd5(self._strings) - return self._strings_md5 - - def _GetEntry(self, path, subpath=None): - """Returns the JSON entry for the given path / subpath.""" - if self._file_map is None: - self._file_map = {} - for entry in self._files: - self._file_map[(entry['path'], None)] = entry - for subentry in entry.get('entries', ()): - self._file_map[(entry['path'], subentry['path'])] = subentry - return self._file_map.get((path, subpath)) - - def GetTag(self, path, subpath=None): - """Returns the tag for the given path / subpath.""" - ret = self._GetEntry(path, subpath) - return ret and ret['tag'] - - def IterPaths(self): - """Returns a generator for all top-level paths.""" - return (e['path'] for e in self._files) - - def IterSubpaths(self, path): - """Returns a generator for all subpaths in the given zip. - - If the given path is not a zip file or doesn't exist, returns an empty - iterable. - """ - outer_entry = self._GetEntry(path) - if not outer_entry: - return () - subentries = outer_entry.get('entries', []) - return (entry['path'] for entry in subentries) - - -def _UpdateMd5ForFile(md5, path, block_size=2**16): - with open(path, 'rb') as infile: - while True: - data = infile.read(block_size) - if not data: - break - md5.update(data) - - -def _UpdateMd5ForDirectory(md5, dir_path): - for root, _, files in os.walk(dir_path): - for f in files: - _UpdateMd5ForFile(md5, os.path.join(root, f)) - - -def _Md5ForPath(path): - md5 = hashlib.md5() - if os.path.isdir(path): - _UpdateMd5ForDirectory(md5, path) - else: - _UpdateMd5ForFile(md5, path) - return md5.hexdigest() - - -def _ComputeInlineMd5(iterable): - """Computes the md5 of the concatenated parameters.""" - md5 = hashlib.md5() - for item in iterable: - md5.update(str(item)) - return md5.hexdigest() - - -def _IsZipFile(path): - """Returns whether to treat the given file as a zip file.""" - # ijar doesn't set the CRC32 field. - if path.endswith('.interface.jar'): - return False - return path[-4:] in ('.zip', '.apk', '.jar') or path.endswith('.srcjar') - - -def _ExtractZipEntries(path): - """Returns a list of (path, CRC32) of all files within |path|.""" - entries = [] - with zipfile.ZipFile(path) as zip_file: - for zip_info in zip_file.infolist(): - # Skip directories and empty files. - if zip_info.CRC: - entries.append( - (zip_info.filename, zip_info.CRC + zip_info.compress_type)) - return entries diff --git a/build/android/pylib/__init__.py b/build/android/pylib/__init__.py deleted file mode 100644 index b93eb4f..0000000 --- a/build/android/pylib/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2012 The Chromium 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 sys - - -_CATAPULT_PATH = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..', 'third_party', 'catapult')) - -_DEVIL_PATH = os.path.join(_CATAPULT_PATH, 'devil') - -_PYTRACE_PATH = os.path.join(_CATAPULT_PATH, 'common', 'py_trace_event') - -_PY_UTILS_PATH = os.path.join(_CATAPULT_PATH, 'common', 'py_utils') - -_TRACE2HTML_PATH = os.path.join(_CATAPULT_PATH, 'tracing') - - -if _DEVIL_PATH not in sys.path: - sys.path.append(_DEVIL_PATH) - -if _PYTRACE_PATH not in sys.path: - sys.path.append(_PYTRACE_PATH) - -if _PY_UTILS_PATH not in sys.path: - sys.path.append(_PY_UTILS_PATH) - -if _TRACE2HTML_PATH not in sys.path: - sys.path.append(_TRACE2HTML_PATH) diff --git a/build/android/pylib/constants/__init__.py b/build/android/pylib/constants/__init__.py deleted file mode 100644 index 916ee27..0000000 --- a/build/android/pylib/constants/__init__.py +++ /dev/null @@ -1,225 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Defines a set of constants shared by test runners and other scripts.""" - -# TODO(jbudorick): Split these constants into coherent modules. - -# pylint: disable=W0212 - -import collections -import glob -import logging -import os -import subprocess - -import devil.android.sdk.keyevent -from devil.android.constants import chrome -from devil.android.sdk import version_codes -from devil.constants import exit_codes - - -keyevent = devil.android.sdk.keyevent - - -DIR_SOURCE_ROOT = os.environ.get('CHECKOUT_SOURCE_ROOT', - os.path.abspath(os.path.join(os.path.dirname(__file__), - os.pardir, os.pardir, os.pardir, os.pardir))) - -PACKAGE_INFO = dict(chrome.PACKAGE_INFO) -PACKAGE_INFO.update({ - 'legacy_browser': chrome.PackageInfo( - 'com.google.android.browser', - 'com.android.browser.BrowserActivity', - None, - None), - 'chromecast_shell': chrome.PackageInfo( - 'com.google.android.apps.mediashell', - 'com.google.android.apps.mediashell.MediaShellActivity', - 'castshell-command-line', - None), - 'android_webview_shell': chrome.PackageInfo( - 'org.chromium.android_webview.shell', - 'org.chromium.android_webview.shell.AwShellActivity', - 'android-webview-command-line', - None), - 'gtest': chrome.PackageInfo( - 'org.chromium.native_test', - 'org.chromium.native_test.NativeUnitTestActivity', - 'chrome-native-tests-command-line', - None), - 'components_browsertests': chrome.PackageInfo( - 'org.chromium.components_browsertests_apk', - ('org.chromium.components_browsertests_apk' + - '.ComponentsBrowserTestsActivity'), - 'chrome-native-tests-command-line', - None), - 'content_browsertests': chrome.PackageInfo( - 'org.chromium.content_browsertests_apk', - 'org.chromium.content_browsertests_apk.ContentBrowserTestsActivity', - 'chrome-native-tests-command-line', - None), - 'chromedriver_webview_shell': chrome.PackageInfo( - 'org.chromium.chromedriver_webview_shell', - 'org.chromium.chromedriver_webview_shell.Main', - None, - None), -}) - - -# Ports arrangement for various test servers used in Chrome for Android. -# Lighttpd server will attempt to use 9000 as default port, if unavailable it -# will find a free port from 8001 - 8999. -LIGHTTPD_DEFAULT_PORT = 9000 -LIGHTTPD_RANDOM_PORT_FIRST = 8001 -LIGHTTPD_RANDOM_PORT_LAST = 8999 -TEST_SYNC_SERVER_PORT = 9031 -TEST_SEARCH_BY_IMAGE_SERVER_PORT = 9041 -TEST_POLICY_SERVER_PORT = 9051 - - -TEST_EXECUTABLE_DIR = '/data/local/tmp' -# Directories for common java libraries for SDK build. -# These constants are defined in build/android/ant/common.xml -SDK_BUILD_JAVALIB_DIR = 'lib.java' -SDK_BUILD_TEST_JAVALIB_DIR = 'test.lib.java' -SDK_BUILD_APKS_DIR = 'apks' - -ADB_KEYS_FILE = '/data/misc/adb/adb_keys' - -PERF_OUTPUT_DIR = os.path.join(DIR_SOURCE_ROOT, 'out', 'step_results') -# The directory on the device where perf test output gets saved to. -DEVICE_PERF_OUTPUT_DIR = ( - '/data/data/' + PACKAGE_INFO['chrome'].package + '/files') - -SCREENSHOTS_DIR = os.path.join(DIR_SOURCE_ROOT, 'out_screenshots') - -ANDROID_SDK_VERSION = version_codes.MARSHMALLOW -ANDROID_SDK_BUILD_TOOLS_VERSION = '24.0.2' -ANDROID_SDK_ROOT = os.path.join(DIR_SOURCE_ROOT, - 'third_party', 'android_tools', 'sdk') -ANDROID_SDK_TOOLS = os.path.join(ANDROID_SDK_ROOT, - 'build-tools', ANDROID_SDK_BUILD_TOOLS_VERSION) -ANDROID_NDK_ROOT = os.path.join(DIR_SOURCE_ROOT, - 'third_party', 'android_tools', 'ndk') - -PROGUARD_SCRIPT_PATH = os.path.join( - ANDROID_SDK_ROOT, 'tools', 'proguard', 'bin', 'proguard.sh') - -PROGUARD_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'proguard') - -BAD_DEVICES_JSON = os.path.join(DIR_SOURCE_ROOT, - os.environ.get('CHROMIUM_OUT_DIR', 'out'), - 'bad_devices.json') - -UPSTREAM_FLAKINESS_SERVER = 'test-results.appspot.com' - -# TODO(jbudorick): Remove once unused. -DEVICE_LOCAL_PROPERTIES_PATH = '/data/local.prop' - -# TODO(jbudorick): Rework this into testing/buildbot/ -PYTHON_UNIT_TEST_SUITES = { - 'pylib_py_unittests': { - 'path': os.path.join(DIR_SOURCE_ROOT, 'build', 'android'), - 'test_modules': [ - 'devil.android.device_utils_test', - 'devil.android.md5sum_test', - 'devil.utils.cmd_helper_test', - 'pylib.results.json_results_test', - 'pylib.utils.proguard_test', - ] - }, - 'gyp_py_unittests': { - 'path': os.path.join(DIR_SOURCE_ROOT, 'build', 'android', 'gyp'), - 'test_modules': [ - 'java_cpp_enum_tests', - 'java_google_api_keys_tests', - ] - }, -} - -LOCAL_MACHINE_TESTS = ['junit', 'python'] -VALID_ENVIRONMENTS = ['local'] -VALID_TEST_TYPES = ['gtest', 'instrumentation', 'junit', 'linker', 'monkey', - 'perf', 'python'] -VALID_DEVICE_TYPES = ['Android', 'iOS'] - - -def GetBuildType(): - try: - return os.environ['BUILDTYPE'] - except KeyError: - raise EnvironmentError( - 'The BUILDTYPE environment variable has not been set') - - -def SetBuildType(build_type): - os.environ['BUILDTYPE'] = build_type - - -def SetBuildDirectory(build_directory): - os.environ['CHROMIUM_OUT_DIR'] = build_directory - - -def SetOutputDirectory(output_directory): - os.environ['CHROMIUM_OUTPUT_DIR'] = output_directory - - -def GetOutDirectory(build_type=None): - """Returns the out directory where the output binaries are built. - - Args: - build_type: Build type, generally 'Debug' or 'Release'. Defaults to the - globally set build type environment variable BUILDTYPE. - """ - if 'CHROMIUM_OUTPUT_DIR' in os.environ: - return os.path.abspath(os.path.join( - DIR_SOURCE_ROOT, os.environ.get('CHROMIUM_OUTPUT_DIR'))) - - return os.path.abspath(os.path.join( - DIR_SOURCE_ROOT, os.environ.get('CHROMIUM_OUT_DIR', 'out'), - GetBuildType() if build_type is None else build_type)) - - -def CheckOutputDirectory(): - """Checks that CHROMIUM_OUT_DIR or CHROMIUM_OUTPUT_DIR is set. - - If neither are set, but the current working directory is a build directory, - then CHROMIUM_OUTPUT_DIR is set to the current working directory. - - Raises: - Exception: If no output directory is detected. - """ - output_dir = os.environ.get('CHROMIUM_OUTPUT_DIR') - out_dir = os.environ.get('CHROMIUM_OUT_DIR') - if not output_dir and not out_dir: - # If CWD is an output directory, then assume it's the desired one. - if os.path.exists('build.ninja'): - output_dir = os.getcwd() - SetOutputDirectory(output_dir) - elif os.environ.get('CHROME_HEADLESS'): - # When running on bots, see if the output directory is obvious. - dirs = glob.glob(os.path.join(DIR_SOURCE_ROOT, 'out', '*', 'build.ninja')) - if len(dirs) == 1: - SetOutputDirectory(dirs[0]) - else: - raise Exception('Neither CHROMIUM_OUTPUT_DIR nor CHROMIUM_OUT_DIR ' - 'has been set. CHROME_HEADLESS detected, but multiple ' - 'out dirs exist: %r' % dirs) - else: - raise Exception('Neither CHROMIUM_OUTPUT_DIR nor CHROMIUM_OUT_DIR ' - 'has been set') - - -# TODO(jbudorick): Convert existing callers to AdbWrapper.GetAdbPath() and -# remove this. -def GetAdbPath(): - from devil.android.sdk import adb_wrapper - return adb_wrapper.AdbWrapper.GetAdbPath() - - -# Exit codes -ERROR_EXIT_CODE = exit_codes.ERROR -INFRA_EXIT_CODE = exit_codes.INFRA -WARNING_EXIT_CODE = exit_codes.WARNING diff --git a/build/android/pylib/constants/host_paths.py b/build/android/pylib/constants/host_paths.py deleted file mode 100644 index 98aa53d..0000000 --- a/build/android/pylib/constants/host_paths.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import contextlib -import os -import sys - -DIR_SOURCE_ROOT = os.environ.get( - 'CHECKOUT_SOURCE_ROOT', - os.path.abspath(os.path.join(os.path.dirname(__file__), - os.pardir, os.pardir, os.pardir, os.pardir))) - -BUILD_COMMON_PATH = os.path.join( - DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common') - -# third-party libraries -ANDROID_PLATFORM_DEVELOPMENT_SCRIPTS_PATH = os.path.join( - DIR_SOURCE_ROOT, 'third_party', 'android_platform', 'development', - 'scripts') -DEVIL_PATH = os.path.join( - DIR_SOURCE_ROOT, 'third_party', 'catapult', 'devil') -PYMOCK_PATH = os.path.join( - DIR_SOURCE_ROOT, 'third_party', 'pymock') - -@contextlib.contextmanager -def SysPath(path, position=None): - if position is None: - sys.path.append(path) - else: - sys.path.insert(position, path) - try: - yield - finally: - if sys.path[-1] == path: - sys.path.pop() - else: - sys.path.remove(path) diff --git a/build/build_config.h b/build/build_config.h deleted file mode 100644 index 5ee96b1..0000000 --- a/build/build_config.h +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file adds defines about the platform we're currently building on. -// Operating System: -// OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) / -// OS_NACL (NACL_SFI or NACL_NONSFI) / OS_NACL_SFI / OS_NACL_NONSFI -// OS_CHROMEOS is set by the build system -// Compiler: -// COMPILER_MSVC / COMPILER_GCC -// Processor: -// ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64) -// ARCH_CPU_32_BITS / ARCH_CPU_64_BITS - -#ifndef BUILD_BUILD_CONFIG_H_ -#define BUILD_BUILD_CONFIG_H_ - -// A brief primer on #defines: -// -// - __ANDROID__ is automatically defined by the Android toolchain (see -// https://goo.gl/v61lXa). It's not defined when building host code. -// - __ANDROID_HOST__ is defined via -D by Android.mk when building host code -// within an Android checkout. -// - ANDROID is defined via -D when building code for either Android targets or -// hosts. Use __ANDROID__ and __ANDROID_HOST__ instead. -// - OS_ANDROID is a Chrome-specific define used to build Chrome for Android -// within the NDK. - -// Android targets and hosts don't use tcmalloc. -#if defined(__ANDROID__) || defined(__ANDROID_HOST__) -#define NO_TCMALLOC -#endif // defined(__ANDROID__) || defined(__ANDROID_HOST__) - -// Use the Chrome OS version of the code for both Android targets and Chrome OS builds. -#if !defined(__ANDROID_HOST__) -#define OS_CHROMEOS 1 -#endif // !defined(__ANDROID_HOST__) - -#if defined(__ANDROID__) // Android targets - -#define __linux__ 1 - -#elif !defined(__ANDROID_HOST__) // Chrome OS - -// TODO: Remove these once the GLib MessageLoopForUI isn't being used: -// https://crbug.com/361635 -#define USE_GLIB 1 -#define USE_OZONE 1 - -#endif // defined(__ANDROID__) - -// A set of macros to use for platform detection. -#if defined(__native_client__) -// __native_client__ must be first, so that other OS_ defines are not set. -#define OS_NACL 1 -// OS_NACL comes in two sandboxing technology flavors, SFI or Non-SFI. -// PNaCl toolchain defines __native_client_nonsfi__ macro in Non-SFI build -// mode, while it does not in SFI build mode. -#if defined(__native_client_nonsfi__) -#define OS_NACL_NONSFI -#else -#define OS_NACL_SFI -#endif -// Don't set OS_ANDROID; it's only used when building Chrome for Android. -#elif defined(__APPLE__) -// only include TargetConditions after testing ANDROID as some android builds -// on mac don't have this header available and it's not needed unless the target -// is really mac/ios. -#include -#define OS_MACOSX 1 -#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE -#define OS_IOS 1 -#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE -#elif defined(__linux__) -#define OS_LINUX 1 -// include a system header to pull in features.h for glibc/uclibc macros. -#include -#if defined(__GLIBC__) && !defined(__UCLIBC__) -// we really are using glibc, not uClibc pretending to be glibc -#define LIBC_GLIBC 1 -#endif -#elif defined(_WIN32) -#define OS_WIN 1 -#elif defined(__FreeBSD__) -#define OS_FREEBSD 1 -#elif defined(__NetBSD__) -#define OS_NETBSD 1 -#elif defined(__OpenBSD__) -#define OS_OPENBSD 1 -#elif defined(__sun) -#define OS_SOLARIS 1 -#elif defined(__QNXNTO__) -#define OS_QNX 1 -#else -#error Please add support for your platform in build/build_config.h -#endif - -#if defined(USE_OPENSSL_CERTS) && defined(USE_NSS_CERTS) -#error Cannot use both OpenSSL and NSS for certificates -#endif - -// For access to standard BSD features, use OS_BSD instead of a -// more specific macro. -#if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) -#define OS_BSD 1 -#endif - -// For access to standard POSIXish features, use OS_POSIX instead of a -// more specific macro. -#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \ - defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_SOLARIS) || \ - defined(OS_ANDROID) || defined(OS_OPENBSD) || defined(OS_SOLARIS) || \ - defined(OS_ANDROID) || defined(OS_NACL) || defined(OS_QNX) -#define OS_POSIX 1 -#endif - -// Use tcmalloc -#if (defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)) && \ - !defined(NO_TCMALLOC) -#define USE_TCMALLOC 1 -#endif - -// Compiler detection. -#if defined(__GNUC__) -#define COMPILER_GCC 1 -#elif defined(_MSC_VER) -#define COMPILER_MSVC 1 -#else -#error Please add support for your compiler in build/build_config.h -#endif - -// Processor architecture detection. For more info on what's defined, see: -// http://msdn.microsoft.com/en-us/library/b0084kay.aspx -// http://www.agner.org/optimize/calling_conventions.pdf -// or with gcc, run: "echo | gcc -E -dM -" -#if defined(_M_X64) || defined(__x86_64__) -#define ARCH_CPU_X86_FAMILY 1 -#define ARCH_CPU_X86_64 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(_M_IX86) || defined(__i386__) -#define ARCH_CPU_X86_FAMILY 1 -#define ARCH_CPU_X86 1 -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__s390x__) -#define ARCH_CPU_S390_FAMILY 1 -#define ARCH_CPU_S390X 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_BIG_ENDIAN 1 -#elif defined(__s390__) -#define ARCH_CPU_S390_FAMILY 1 -#define ARCH_CPU_S390 1 -#define ARCH_CPU_31_BITS 1 -#define ARCH_CPU_BIG_ENDIAN 1 -#elif defined(__PPC64__) && defined(__BIG_ENDIAN__) -#define ARCH_CPU_PPC64_FAMILY 1 -#define ARCH_CPU_PPC64 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_BIG_ENDIAN 1 -#elif defined(__PPC64__) && defined(__LITTLE_ENDIAN__) -#define ARCH_CPU_PPC64_FAMILY 1 -#define ARCH_CPU_PPC64 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__PPC__) -#define ARCH_CPU_PPC_FAMILY 1 -#define ARCH_CPU_PPC 1 -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_BIG_ENDIAN 1 -#elif defined(__ARMEL__) -#define ARCH_CPU_ARM_FAMILY 1 -#define ARCH_CPU_ARMEL 1 -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__aarch64__) -#define ARCH_CPU_ARM_FAMILY 1 -#define ARCH_CPU_ARM64 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__pnacl__) -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__MIPSEL__) -#if defined(__LP64__) -#define ARCH_CPU_MIPS_FAMILY 1 -#define ARCH_CPU_MIPS64EL 1 -#define ARCH_CPU_64_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#else -#define ARCH_CPU_MIPS_FAMILY 1 -#define ARCH_CPU_MIPSEL 1 -#define ARCH_CPU_32_BITS 1 -#define ARCH_CPU_LITTLE_ENDIAN 1 -#endif -#else -#error Please add support for your architecture in build/build_config.h -#endif - -// Type detection for wchar_t. -#if defined(OS_WIN) -#define WCHAR_T_IS_UTF16 -#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \ - defined(__WCHAR_MAX__) && \ - (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) -#define WCHAR_T_IS_UTF32 -#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \ - defined(__WCHAR_MAX__) && \ - (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff) -// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to -// compile in this mode (in particular, Chrome doesn't). This is intended for -// other projects using base who manage their own dependencies and make sure -// short wchar works for them. -#define WCHAR_T_IS_UTF16 -#else -#error Please add support for your compiler in build/build_config.h -#endif - -#if defined(OS_ANDROID) -// The compiler thinks std::string::const_iterator and "const char*" are -// equivalent types. -#define STD_STRING_ITERATOR_IS_CHAR_POINTER -// The compiler thinks base::string16::const_iterator and "char16*" are -// equivalent types. -#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER -#endif - -#endif // BUILD_BUILD_CONFIG_H_ diff --git a/build/gn_helpers.py b/build/gn_helpers.py deleted file mode 100644 index 33cc578..0000000 --- a/build/gn_helpers.py +++ /dev/null @@ -1,351 +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. - -"""Helper functions useful when writing scripts that integrate with GN. - -The main functions are ToGNString and FromGNString which convert between -serialized GN veriables and Python variables. - -To use in a random python file in the build: - - import os - import sys - - sys.path.append(os.path.join(os.path.dirname(__file__), - os.pardir, os.pardir, "build")) - import gn_helpers - -Where the sequence of parameters to join is the relative path from your source -file to the build directory.""" - -class GNException(Exception): - pass - - -def ToGNString(value, allow_dicts = True): - """Returns a stringified GN equivalent of the Python value. - - allow_dicts indicates if this function will allow converting dictionaries - to GN scopes. This is only possible at the top level, you can't nest a - GN scope in a list, so this should be set to False for recursive calls.""" - if isinstance(value, basestring): - if value.find('\n') >= 0: - raise GNException("Trying to print a string with a newline in it.") - return '"' + \ - value.replace('\\', '\\\\').replace('"', '\\"').replace('$', '\\$') + \ - '"' - - if isinstance(value, unicode): - return ToGNString(value.encode('utf-8')) - - if isinstance(value, bool): - if value: - return "true" - return "false" - - if isinstance(value, list): - return '[ %s ]' % ', '.join(ToGNString(v) for v in value) - - if isinstance(value, dict): - if not allow_dicts: - raise GNException("Attempting to recursively print a dictionary.") - result = "" - for key in sorted(value): - if not isinstance(key, basestring): - raise GNException("Dictionary key is not a string.") - result += "%s = %s\n" % (key, ToGNString(value[key], False)) - return result - - if isinstance(value, int): - return str(value) - - raise GNException("Unsupported type when printing to GN.") - - -def FromGNString(input_string): - """Converts the input string from a GN serialized value to Python values. - - For details on supported types see GNValueParser.Parse() below. - - If your GN script did: - something = [ "file1", "file2" ] - args = [ "--values=$something" ] - The command line would look something like: - --values="[ \"file1\", \"file2\" ]" - Which when interpreted as a command line gives the value: - [ "file1", "file2" ] - - You can parse this into a Python list using GN rules with: - input_values = FromGNValues(options.values) - Although the Python 'ast' module will parse many forms of such input, it - will not handle GN escaping properly, nor GN booleans. You should use this - function instead. - - - A NOTE ON STRING HANDLING: - - If you just pass a string on the command line to your Python script, or use - string interpolation on a string variable, the strings will not be quoted: - str = "asdf" - args = [ str, "--value=$str" ] - Will yield the command line: - asdf --value=asdf - The unquoted asdf string will not be valid input to this function, which - accepts only quoted strings like GN scripts. In such cases, you can just use - the Python string literal directly. - - The main use cases for this is for other types, in particular lists. When - using string interpolation on a list (as in the top example) the embedded - strings will be quoted and escaped according to GN rules so the list can be - re-parsed to get the same result.""" - parser = GNValueParser(input_string) - return parser.Parse() - - -def FromGNArgs(input_string): - """Converts a string with a bunch of gn arg assignments into a Python dict. - - Given a whitespace-separated list of - - = (integer | string | boolean | ) - - gn assignments, this returns a Python dict, i.e.: - - FromGNArgs("foo=true\nbar=1\n") -> { 'foo': True, 'bar': 1 }. - - Only simple types and lists supported; variables, structs, calls - and other, more complicated things are not. - - This routine is meant to handle only the simple sorts of values that - arise in parsing --args. - """ - parser = GNValueParser(input_string) - return parser.ParseArgs() - - -def UnescapeGNString(value): - """Given a string with GN escaping, returns the unescaped string. - - Be careful not to feed with input from a Python parsing function like - 'ast' because it will do Python unescaping, which will be incorrect when - fed into the GN unescaper.""" - result = '' - i = 0 - while i < len(value): - if value[i] == '\\': - if i < len(value) - 1: - next_char = value[i + 1] - if next_char in ('$', '"', '\\'): - # These are the escaped characters GN supports. - result += next_char - i += 1 - else: - # Any other backslash is a literal. - result += '\\' - else: - result += value[i] - i += 1 - return result - - -def _IsDigitOrMinus(char): - return char in "-0123456789" - - -class GNValueParser(object): - """Duplicates GN parsing of values and converts to Python types. - - Normally you would use the wrapper function FromGNValue() below. - - If you expect input as a specific type, you can also call one of the Parse* - functions directly. All functions throw GNException on invalid input. """ - def __init__(self, string): - self.input = string - self.cur = 0 - - def IsDone(self): - return self.cur == len(self.input) - - def ConsumeWhitespace(self): - while not self.IsDone() and self.input[self.cur] in ' \t\n': - self.cur += 1 - - def Parse(self): - """Converts a string representing a printed GN value to the Python type. - - See additional usage notes on FromGNString above. - - - GN booleans ('true', 'false') will be converted to Python booleans. - - - GN numbers ('123') will be converted to Python numbers. - - - GN strings (double-quoted as in '"asdf"') will be converted to Python - strings with GN escaping rules. GN string interpolation (embedded - variables preceeded by $) are not supported and will be returned as - literals. - - - GN lists ('[1, "asdf", 3]') will be converted to Python lists. - - - GN scopes ('{ ... }') are not supported.""" - result = self._ParseAllowTrailing() - self.ConsumeWhitespace() - if not self.IsDone(): - raise GNException("Trailing input after parsing:\n " + - self.input[self.cur:]) - return result - - def ParseArgs(self): - """Converts a whitespace-separated list of ident=literals to a dict. - - See additional usage notes on FromGNArgs, above. - """ - d = {} - - self.ConsumeWhitespace() - while not self.IsDone(): - ident = self._ParseIdent() - self.ConsumeWhitespace() - if self.input[self.cur] != '=': - raise GNException("Unexpected token: " + self.input[self.cur:]) - self.cur += 1 - self.ConsumeWhitespace() - val = self._ParseAllowTrailing() - self.ConsumeWhitespace() - d[ident] = val - - return d - - def _ParseAllowTrailing(self): - """Internal version of Parse that doesn't check for trailing stuff.""" - self.ConsumeWhitespace() - if self.IsDone(): - raise GNException("Expected input to parse.") - - next_char = self.input[self.cur] - if next_char == '[': - return self.ParseList() - elif _IsDigitOrMinus(next_char): - return self.ParseNumber() - elif next_char == '"': - return self.ParseString() - elif self._ConstantFollows('true'): - return True - elif self._ConstantFollows('false'): - return False - else: - raise GNException("Unexpected token: " + self.input[self.cur:]) - - def _ParseIdent(self): - ident = '' - - next_char = self.input[self.cur] - if not next_char.isalpha() and not next_char=='_': - raise GNException("Expected an identifier: " + self.input[self.cur:]) - - ident += next_char - self.cur += 1 - - next_char = self.input[self.cur] - while next_char.isalpha() or next_char.isdigit() or next_char=='_': - ident += next_char - self.cur += 1 - next_char = self.input[self.cur] - - return ident - - def ParseNumber(self): - self.ConsumeWhitespace() - if self.IsDone(): - raise GNException('Expected number but got nothing.') - - begin = self.cur - - # The first character can include a negative sign. - if not self.IsDone() and _IsDigitOrMinus(self.input[self.cur]): - self.cur += 1 - while not self.IsDone() and self.input[self.cur].isdigit(): - self.cur += 1 - - number_string = self.input[begin:self.cur] - if not len(number_string) or number_string == '-': - raise GNException("Not a valid number.") - return int(number_string) - - def ParseString(self): - self.ConsumeWhitespace() - if self.IsDone(): - raise GNException('Expected string but got nothing.') - - if self.input[self.cur] != '"': - raise GNException('Expected string beginning in a " but got:\n ' + - self.input[self.cur:]) - self.cur += 1 # Skip over quote. - - begin = self.cur - while not self.IsDone() and self.input[self.cur] != '"': - if self.input[self.cur] == '\\': - self.cur += 1 # Skip over the backslash. - if self.IsDone(): - raise GNException("String ends in a backslash in:\n " + - self.input) - self.cur += 1 - - if self.IsDone(): - raise GNException('Unterminated string:\n ' + self.input[begin:]) - - end = self.cur - self.cur += 1 # Consume trailing ". - - return UnescapeGNString(self.input[begin:end]) - - def ParseList(self): - self.ConsumeWhitespace() - if self.IsDone(): - raise GNException('Expected list but got nothing.') - - # Skip over opening '['. - if self.input[self.cur] != '[': - raise GNException("Expected [ for list but got:\n " + - self.input[self.cur:]) - self.cur += 1 - self.ConsumeWhitespace() - if self.IsDone(): - raise GNException("Unterminated list:\n " + self.input) - - list_result = [] - previous_had_trailing_comma = True - while not self.IsDone(): - if self.input[self.cur] == ']': - self.cur += 1 # Skip over ']'. - return list_result - - if not previous_had_trailing_comma: - raise GNException("List items not separated by comma.") - - list_result += [ self._ParseAllowTrailing() ] - self.ConsumeWhitespace() - if self.IsDone(): - break - - # Consume comma if there is one. - previous_had_trailing_comma = self.input[self.cur] == ',' - if previous_had_trailing_comma: - # Consume comma. - self.cur += 1 - self.ConsumeWhitespace() - - raise GNException("Unterminated list:\n " + self.input) - - def _ConstantFollows(self, constant): - """Returns true if the given constant follows immediately at the current - location in the input. If it does, the text is consumed and the function - returns true. Otherwise, returns false and the current position is - unchanged.""" - end = self.cur + len(constant) - if end > len(self.input): - return False # Not enough room. - if self.input[self.cur:end] == constant: - self.cur = end - return True - return False diff --git a/gen/mojo/common/common_custom_types__type_mappings b/gen/mojo/common/common_custom_types__type_mappings deleted file mode 100644 index 1906049..0000000 --- a/gen/mojo/common/common_custom_types__type_mappings +++ /dev/null @@ -1,193 +0,0 @@ -{ - "c++": { - "mojo.common.mojom.Value": { - "hashable": false, - "typename": "std::unique_ptr", - "traits_headers": [ - "ipc/ipc_message_utils.h", - "mojo/common/values_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": true, - "nullable_is_same_type": true, - "non_copyable_non_movable": false, - "public_headers": [ - "base/values.h" - ] - }, - "mojo.common.mojom.UnguessableToken": { - "hashable": false, - "typename": "base::UnguessableToken", - "traits_headers": [ - "mojo/common/common_custom_types_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": false, - "public_headers": [ - "base/unguessable_token.h" - ] - }, - "mojo.common.mojom.TextDirection": { - "hashable": false, - "typename": "base::i18n::TextDirection", - "traits_headers": [ - "mojo/common/common_custom_types_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": false, - "public_headers": [ - "base/i18n/rtl.h" - ] - }, - "mojo.common.mojom.ListValue": { - "hashable": false, - "typename": "std::unique_ptr", - "traits_headers": [ - "ipc/ipc_message_utils.h", - "mojo/common/values_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": true, - "nullable_is_same_type": true, - "non_copyable_non_movable": false, - "public_headers": [ - "base/values.h" - ] - }, - "mojo.common.mojom.String16": { - "hashable": false, - "typename": "base::string16", - "traits_headers": [ - "mojo/common/common_custom_types_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": false, - "public_headers": [ - "base/strings/string16.h" - ] - }, - "mojo.common.mojom.Time": { - "hashable": false, - "typename": "base::Time", - "traits_headers": [ - "ipc/ipc_message_utils.h", - "mojo/common/common_custom_types_struct_traits.h" - ], - "copyable_pass_by_value": true, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": false, - "public_headers": [ - "base/time/time.h" - ] - }, - "mojo.common.mojom.TimeDelta": { - "hashable": false, - "typename": "base::TimeDelta", - "traits_headers": [ - "ipc/ipc_message_utils.h", - "mojo/common/common_custom_types_struct_traits.h" - ], - "copyable_pass_by_value": true, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": false, - "public_headers": [ - "base/time/time.h" - ] - }, - "mojo.common.mojom.TimeTicks": { - "hashable": false, - "typename": "base::TimeTicks", - "traits_headers": [ - "ipc/ipc_message_utils.h", - "mojo/common/common_custom_types_struct_traits.h" - ], - "copyable_pass_by_value": true, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": false, - "public_headers": [ - "base/time/time.h" - ] - }, - "mojo.common.mojom.LegacyListValue": { - "hashable": false, - "typename": "base::ListValue", - "traits_headers": [ - "ipc/ipc_message_utils.h", - "mojo/common/values_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": true, - "public_headers": [ - "base/values.h" - ] - }, - "mojo.common.mojom.File": { - "hashable": false, - "typename": "base::File", - "traits_headers": [ - "mojo/common/common_custom_types_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": true, - "nullable_is_same_type": true, - "non_copyable_non_movable": false, - "public_headers": [ - "base/files/file.h" - ] - }, - "mojo.common.mojom.FilePath": { - "hashable": false, - "typename": "base::FilePath", - "traits_headers": [ - "ipc/ipc_message_utils.h" - ], - "copyable_pass_by_value": false, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": false, - "public_headers": [ - "base/files/file_path.h" - ] - }, - "mojo.common.mojom.DictionaryValue": { - "hashable": false, - "typename": "std::unique_ptr", - "traits_headers": [ - "ipc/ipc_message_utils.h", - "mojo/common/values_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": true, - "nullable_is_same_type": true, - "non_copyable_non_movable": false, - "public_headers": [ - "base/values.h" - ] - }, - "mojo.common.mojom.Version": { - "hashable": false, - "typename": "base::Version", - "traits_headers": [ - "mojo/common/common_custom_types_struct_traits.h" - ], - "copyable_pass_by_value": false, - "move_only": false, - "nullable_is_same_type": false, - "non_copyable_non_movable": false, - "public_headers": [ - "base/version.h" - ] - } - } -} \ No newline at end of file diff --git a/ipc/ipc.mojom b/ipc/ipc.mojom deleted file mode 100644 index 0a4fcfa..0000000 --- a/ipc/ipc.mojom +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module IPC.mojom; - -// NOTE: This MUST match the value of MSG_ROUTING_NONE in src/ipc/ipc_message.h. -const int32 kRoutingIdNone = -2; - -struct SerializedHandle { - handle the_handle; - - enum Type { - MOJO_HANDLE, - PLATFORM_FILE, - WIN_HANDLE, - MACH_PORT, - }; - - Type type; -}; - -// A placeholder interface type since we don't yet support generic associated -// message pipe handles. -interface GenericInterface {}; - -interface Channel { - // Informs the remote end of this client's PID. Must be called exactly once, - // before any calls to Receive() below. - SetPeerPid(int32 pid); - - // Transmits a classical Chrome IPC message. - Receive(array data, array? handles); - - // Requests a Channel-associated interface. - GetAssociatedInterface(string name, associated GenericInterface& request); -}; - -// A strictly nominal interface used to identify Channel bootstrap requests. -interface ChannelBootstrap {}; diff --git a/ipc/ipc_channel_handle.h b/ipc/ipc_channel_handle.h deleted file mode 100644 index ef31b84..0000000 --- a/ipc/ipc_channel_handle.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2012 The Chromium 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_IPC_CHANNEL_HANDLE_H_ -#define IPC_IPC_CHANNEL_HANDLE_H_ - -#include - -#include "build/build_config.h" -#include "mojo/public/cpp/system/message_pipe.h" - -#if defined(OS_NACL_SFI) -#include "base/file_descriptor_posix.h" -#endif // defined (OS_NACL_SFI) - -namespace IPC { - -// Note that serialization for this object is defined in the ParamTraits -// template specialization in ipc_message_utils.h. -#if defined(OS_NACL_SFI) -struct ChannelHandle { - ChannelHandle() {} - explicit ChannelHandle(const base::FileDescriptor& s) : socket(s) {} - - base::FileDescriptor socket; -}; -#else -struct ChannelHandle { - ChannelHandle() {} - ChannelHandle(mojo::MessagePipeHandle h) : mojo_handle(h) {} - - bool is_mojo_channel_handle() const { return mojo_handle.is_valid(); } - - mojo::MessagePipeHandle mojo_handle; -}; -#endif // defined(OS_NACL_SFI) - -} // namespace IPC - -#endif // IPC_IPC_CHANNEL_HANDLE_H_ diff --git a/ipc/ipc_export.h b/ipc/ipc_export.h deleted file mode 100644 index e1cbe88..0000000 --- a/ipc/ipc_export.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011 The Chromium 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_IPC_EXPORT_H_ -#define IPC_IPC_EXPORT_H_ - -// Defines IPC_EXPORT so that functionality implemented by the IPC module can be -// exported to consumers. - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(IPC_IMPLEMENTATION) -#define IPC_EXPORT __declspec(dllexport) -#else -#define IPC_EXPORT __declspec(dllimport) -#endif // defined(IPC_IMPLEMENTATION) - -#else // defined(WIN32) - -#if defined(IPC_IMPLEMENTATION) -#define IPC_EXPORT __attribute__((visibility("default"))) -#else -#define IPC_EXPORT -#endif - -#endif - -#else // defined(COMPONENT_BUILD) -#define IPC_EXPORT -#endif - -#endif // IPC_IPC_EXPORT_H_ diff --git a/ipc/ipc_listener.h b/ipc/ipc_listener.h deleted file mode 100644 index d7ad75c..0000000 --- a/ipc/ipc_listener.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 The Chromium 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_IPC_LISTENER_H_ -#define IPC_IPC_LISTENER_H_ - -#include - -#include - -#include "build/build_config.h" -#include "ipc/ipc_export.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace IPC { - -class Message; - -// Implemented by consumers of a Channel to receive messages. -class IPC_EXPORT Listener { - public: - // Called when a message is received. Returns true iff the message was - // handled. - virtual bool OnMessageReceived(const Message& message) = 0; - - // Called when the channel is connected and we have received the internal - // Hello message from the peer. - virtual void OnChannelConnected(int32_t peer_pid) {} - - // Called when an error is detected that causes the channel to close. - // This method is not called when a channel is closed normally. - virtual void OnChannelError() {} - - // Called when a message's deserialization failed. - virtual void OnBadMessageReceived(const Message& message) {} - - // Called when an associated interface request is received on a Channel and - // the Channel has no registered handler for it. - virtual void OnAssociatedInterfaceRequest( - const std::string& interface_name, - mojo::ScopedInterfaceEndpointHandle handle) {} - -#if defined(OS_POSIX) - // Called on the server side when a channel that listens for connections - // denies an attempt to connect. - virtual void OnChannelDenied() {} - - // Called on the server side when a channel that listens for connections - // has an error that causes the listening channel to close. - virtual void OnChannelListenError() {} -#endif // OS_POSIX - - protected: - virtual ~Listener() {} -}; - -} // namespace IPC - -#endif // IPC_IPC_LISTENER_H_ diff --git a/ipc/ipc_message.cc b/ipc/ipc_message.cc deleted file mode 100644 index f5e9ac7..0000000 --- a/ipc/ipc_message.cc +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright (c) 2012 The Chromium 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/ipc_message.h" - -#include -#include -#include - -#include "base/atomic_sequence_num.h" -#include "base/logging.h" -#include "build/build_config.h" -#include "ipc/ipc_message_attachment.h" -#include "ipc/ipc_message_attachment_set.h" - -#if defined(OS_POSIX) -#include "base/file_descriptor_posix.h" -#include "ipc/ipc_platform_file_attachment_posix.h" -#endif - -namespace { - -base::StaticAtomicSequenceNumber g_ref_num; - -// Create a reference number for identifying IPC messages in traces. The return -// values has the reference number stored in the upper 24 bits, leaving the low -// 8 bits set to 0 for use as flags. -inline uint32_t GetRefNumUpper24() { - base::trace_event::TraceLog* trace_log = - base::trace_event::TraceLog::GetInstance(); - uint32_t pid = trace_log ? trace_log->process_id() : 0; - uint32_t count = g_ref_num.GetNext(); - // The 24 bit hash is composed of 14 bits of the count and 10 bits of the - // Process ID. With the current trace event buffer cap, the 14-bit count did - // not appear to wrap during a trace. Note that it is not a big deal if - // collisions occur, as this is only used for debugging and trace analysis. - return ((pid << 14) | (count & 0x3fff)) << 8; -} - -} // namespace - -namespace IPC { - -//------------------------------------------------------------------------------ - -Message::~Message() { -} - -Message::Message() : base::Pickle(sizeof(Header)) { - header()->routing = header()->type = 0; - header()->flags = GetRefNumUpper24(); -#if defined(OS_POSIX) - header()->num_fds = 0; - header()->pad = 0; -#endif - Init(); -} - -Message::Message(int32_t routing_id, uint32_t type, PriorityValue priority) - : base::Pickle(sizeof(Header)) { - header()->routing = routing_id; - header()->type = type; - DCHECK((priority & 0xffffff00) == 0); - header()->flags = priority | GetRefNumUpper24(); -#if defined(OS_POSIX) - header()->num_fds = 0; - header()->pad = 0; -#endif - Init(); -} - -Message::Message(const char* data, int data_len) - : base::Pickle(data, data_len) { - Init(); -} - -Message::Message(const Message& other) : base::Pickle(other) { - Init(); - attachment_set_ = other.attachment_set_; -} - -void Message::Init() { - dispatch_error_ = false; -#ifdef IPC_MESSAGE_LOG_ENABLED - received_time_ = 0; - dont_log_ = false; - log_data_ = NULL; -#endif -} - -Message& Message::operator=(const Message& other) { - *static_cast(this) = other; - attachment_set_ = other.attachment_set_; - return *this; -} - -void Message::SetHeaderValues(int32_t routing, uint32_t type, uint32_t flags) { - // This should only be called when the message is already empty. - DCHECK(payload_size() == 0); - - header()->routing = routing; - header()->type = type; - header()->flags = flags; -} - -void Message::EnsureMessageAttachmentSet() { - if (attachment_set_.get() == NULL) - attachment_set_ = new MessageAttachmentSet; -} - -#ifdef IPC_MESSAGE_LOG_ENABLED -void Message::set_sent_time(int64_t time) { - DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0); - header()->flags |= HAS_SENT_TIME_BIT; - WriteInt64(time); -} - -int64_t Message::sent_time() const { - if ((header()->flags & HAS_SENT_TIME_BIT) == 0) - return 0; - - const char* data = end_of_payload(); - data -= sizeof(int64_t); - return *(reinterpret_cast(data)); -} - -void Message::set_received_time(int64_t time) const { - received_time_ = time; -} -#endif - -Message::NextMessageInfo::NextMessageInfo() - : message_size(0), message_found(false), pickle_end(nullptr), - message_end(nullptr) {} -Message::NextMessageInfo::~NextMessageInfo() {} - -// static -void Message::FindNext(const char* range_start, - const char* range_end, - NextMessageInfo* info) { - DCHECK(info); - info->message_found = false; - info->message_size = 0; - - size_t pickle_size = 0; - if (!base::Pickle::PeekNext(sizeof(Header), - range_start, range_end, &pickle_size)) - return; - - bool have_entire_pickle = - static_cast(range_end - range_start) >= pickle_size; - - info->message_size = pickle_size; - - if (!have_entire_pickle) - return; - - const char* pickle_end = range_start + pickle_size; - - info->message_end = pickle_end; - - info->pickle_end = pickle_end; - info->message_found = true; -} - -bool Message::WriteAttachment( - scoped_refptr attachment) { - size_t index; - bool success = attachment_set()->AddAttachment( - make_scoped_refptr(static_cast(attachment.get())), - &index); - DCHECK(success); - - // NOTE: If you add more data to the pickle, make sure to update - // PickleSizer::AddAttachment. - - // Write the index of the descriptor so that we don't have to - // keep the current descriptor as extra decoding state when deserialising. - WriteInt(static_cast(index)); - - return success; -} - -bool Message::ReadAttachment( - base::PickleIterator* iter, - scoped_refptr* attachment) const { - int index; - if (!iter->ReadInt(&index)) - return false; - - MessageAttachmentSet* attachment_set = attachment_set_.get(); - if (!attachment_set) - return false; - - *attachment = attachment_set->GetAttachmentAt(index); - - return nullptr != attachment->get(); -} - -bool Message::HasAttachments() const { - return attachment_set_.get() && !attachment_set_->empty(); -} - -} // namespace IPC diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h deleted file mode 100644 index 43e9ae3..0000000 --- a/ipc/ipc_message.h +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright (c) 2012 The Chromium 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_IPC_MESSAGE_H_ -#define IPC_IPC_MESSAGE_H_ - -#include -#include - -#include - -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" -#include "base/pickle.h" -#include "base/trace_event/trace_event.h" -#include "build/build_config.h" -#include "ipc/ipc_export.h" - -#if !defined(NDEBUG) -#define IPC_MESSAGE_LOG_ENABLED -#endif - -namespace IPC { - -namespace internal { -class ChannelReader; -} // namespace internal - -//------------------------------------------------------------------------------ - -struct LogData; -class MessageAttachmentSet; - -class IPC_EXPORT Message : public base::Pickle { - public: - enum PriorityValue { - PRIORITY_LOW = 1, - PRIORITY_NORMAL, - PRIORITY_HIGH - }; - - // Bit values used in the flags field. - // Upper 24 bits of flags store a reference number, so this enum is limited to - // 8 bits. - enum { - PRIORITY_MASK = 0x03, // Low 2 bits of store the priority value. - SYNC_BIT = 0x04, - REPLY_BIT = 0x08, - REPLY_ERROR_BIT = 0x10, - UNBLOCK_BIT = 0x20, - PUMPING_MSGS_BIT = 0x40, - HAS_SENT_TIME_BIT = 0x80, - }; - - ~Message() override; - - Message(); - - // Initialize a message with a user-defined type, priority value, and - // destination WebView ID. - Message(int32_t routing_id, uint32_t type, PriorityValue priority); - - // Initializes a message from a const block of data. The data is not copied; - // instead the data is merely referenced by this message. Only const methods - // should be used on the message when initialized this way. - Message(const char* data, int data_len); - - Message(const Message& other); - Message& operator=(const Message& other); - - PriorityValue priority() const { - return static_cast(header()->flags & PRIORITY_MASK); - } - - // True if this is a synchronous message. - void set_sync() { - header()->flags |= SYNC_BIT; - } - bool is_sync() const { - return (header()->flags & SYNC_BIT) != 0; - } - - // Set this on a reply to a synchronous message. - void set_reply() { - header()->flags |= REPLY_BIT; - } - - bool is_reply() const { - return (header()->flags & REPLY_BIT) != 0; - } - - // Set this on a reply to a synchronous message to indicate that no receiver - // was found. - void set_reply_error() { - header()->flags |= REPLY_ERROR_BIT; - } - - bool is_reply_error() const { - return (header()->flags & REPLY_ERROR_BIT) != 0; - } - - // Normally when a receiver gets a message and they're blocked on a - // synchronous message Send, they buffer a message. Setting this flag causes - // the receiver to be unblocked and the message to be dispatched immediately. - void set_unblock(bool unblock) { - if (unblock) { - header()->flags |= UNBLOCK_BIT; - } else { - header()->flags &= ~UNBLOCK_BIT; - } - } - - bool should_unblock() const { - return (header()->flags & UNBLOCK_BIT) != 0; - } - - // Tells the receiver that the caller is pumping messages while waiting - // for the result. - bool is_caller_pumping_messages() const { - return (header()->flags & PUMPING_MSGS_BIT) != 0; - } - - void set_dispatch_error() const { - dispatch_error_ = true; - } - - bool dispatch_error() const { - return dispatch_error_; - } - - uint32_t type() const { - return header()->type; - } - - int32_t routing_id() const { - return header()->routing; - } - - void set_routing_id(int32_t new_id) { - header()->routing = new_id; - } - - uint32_t flags() const { - return header()->flags; - } - - // Sets all the given header values. The message should be empty at this - // call. - void SetHeaderValues(int32_t routing, uint32_t type, uint32_t flags); - - template - static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, - void (T::*func)()) { - (obj->*func)(); - return true; - } - - template - static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter, - void (T::*func)(P*)) { - (obj->*func)(parameter); - return true; - } - - // Used for async messages with no parameters. - static void Log(std::string* name, const Message* msg, std::string* l) { - } - - // The static method FindNext() returns several pieces of information, which - // are aggregated into an instance of this struct. - struct IPC_EXPORT NextMessageInfo { - NextMessageInfo(); - ~NextMessageInfo(); - - // Total message size. Always valid if |message_found| is true. - // If |message_found| is false but we could determine message size - // from the header, this field is non-zero. Otherwise it's zero. - size_t message_size; - // Whether an entire message was found in the given memory range. - bool message_found; - // Only filled in if |message_found| is true. - // The start address is passed into FindNext() by the caller, so isn't - // repeated in this struct. The end address of the pickle should be used to - // construct a base::Pickle. - const char* pickle_end; - // Only filled in if |message_found| is true. - // The end address of the message should be used to determine the start - // address of the next message. - const char* message_end; - }; - - // |info| is an output parameter and must not be nullptr. - static void FindNext(const char* range_start, - const char* range_end, - NextMessageInfo* info); - - // WriteAttachment appends |attachment| to the end of the set. It returns - // false iff the set is full. - bool WriteAttachment( - scoped_refptr attachment) override; - // ReadAttachment parses an attachment given the parsing state |iter| and - // writes it to |*attachment|. It returns true on success. - bool ReadAttachment( - base::PickleIterator* iter, - scoped_refptr* attachment) const override; - // Returns true if there are any attachment in this message. - bool HasAttachments() const override; - -#ifdef IPC_MESSAGE_LOG_ENABLED - // Adds the outgoing time from Time::Now() at the end of the message and sets - // a bit to indicate that it's been added. - void set_sent_time(int64_t time); - int64_t sent_time() const; - - void set_received_time(int64_t time) const; - int64_t received_time() const { return received_time_; } - void set_output_params(const std::string& op) const { output_params_ = op; } - const std::string& output_params() const { return output_params_; } - // The following four functions are needed so we can log sync messages with - // delayed replies. We stick the log data from the sent message into the - // reply message, so that when it's sent and we have the output parameters - // we can log it. As such, we set a flag on the sent message to not log it. - void set_sync_log_data(LogData* data) const { log_data_ = data; } - LogData* sync_log_data() const { return log_data_; } - void set_dont_log() const { dont_log_ = true; } - bool dont_log() const { return dont_log_; } -#endif - - protected: - friend class Channel; - friend class ChannelMojo; - friend class ChannelNacl; - friend class ChannelPosix; - friend class ChannelWin; - friend class internal::ChannelReader; - friend class MessageReplyDeserializer; - friend class SyncMessage; - -#pragma pack(push, 4) - struct Header : base::Pickle::Header { - int32_t routing; // ID of the view that this message is destined for - uint32_t type; // specifies the user-defined message type - uint32_t flags; // specifies control flags for the message -#if defined(OS_POSIX) - uint16_t num_fds; // the number of descriptors included with this message - uint16_t pad; // explicitly initialize this to appease valgrind -#endif - }; -#pragma pack(pop) - - Header* header() { - return headerT
(); - } - const Header* header() const { - return headerT
(); - } - - void Init(); - - // Used internally to support IPC::Listener::OnBadMessageReceived. - mutable bool dispatch_error_; - - // The set of file descriptors associated with this message. - scoped_refptr attachment_set_; - - // Ensure that a MessageAttachmentSet is allocated - void EnsureMessageAttachmentSet(); - - MessageAttachmentSet* attachment_set() { - EnsureMessageAttachmentSet(); - return attachment_set_.get(); - } - const MessageAttachmentSet* attachment_set() const { - return attachment_set_.get(); - } - -#ifdef IPC_MESSAGE_LOG_ENABLED - // Used for logging. - mutable int64_t received_time_; - mutable std::string output_params_; - mutable LogData* log_data_; - mutable bool dont_log_; -#endif - - FRIEND_TEST_ALL_PREFIXES(IPCMessageTest, FindNext); - FRIEND_TEST_ALL_PREFIXES(IPCMessageTest, FindNextOverflow); -}; - -//------------------------------------------------------------------------------ - -} // namespace IPC - -enum SpecialRoutingIDs { - // indicates that we don't have a routing ID yet. - MSG_ROUTING_NONE = -2, - - // indicates a general message not sent to a particular tab. - MSG_ROUTING_CONTROL = INT32_MAX, -}; - -#define IPC_REPLY_ID 0xFFFFFFF0 // Special message id for replies -#define IPC_LOGGING_ID 0xFFFFFFF1 // Special message id for logging - -#endif // IPC_IPC_MESSAGE_H_ diff --git a/ipc/ipc_message_attachment.cc b/ipc/ipc_message_attachment.cc deleted file mode 100644 index 83440ae..0000000 --- a/ipc/ipc_message_attachment.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 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/ipc_message_attachment.h" - -namespace IPC { - -MessageAttachment::MessageAttachment() { -} - -MessageAttachment::~MessageAttachment() { -} - -} // namespace IPC diff --git a/ipc/ipc_message_attachment.h b/ipc/ipc_message_attachment.h deleted file mode 100644 index 9ff1de8..0000000 --- a/ipc/ipc_message_attachment.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 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_IPC_MESSAGE_ATTACHMENT_H_ -#define IPC_IPC_MESSAGE_ATTACHMENT_H_ - -#include "base/files/file.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/pickle.h" -#include "build/build_config.h" -#include "ipc/ipc.mojom.h" -#include "ipc/ipc_export.h" - -namespace IPC { - -// Auxiliary data sent with |Message|. This can be a platform file descriptor -// or a mojo |MessagePipe|. |GetType()| returns the type of the subclass. -class IPC_EXPORT MessageAttachment : public base::Pickle::Attachment { - public: - using Type = mojom::SerializedHandle::Type; - - virtual Type GetType() const = 0; - - protected: - friend class base::RefCountedThreadSafe; - MessageAttachment(); - ~MessageAttachment() override; - - DISALLOW_COPY_AND_ASSIGN(MessageAttachment); -}; - -} // namespace IPC - -#endif // IPC_IPC_MESSAGE_ATTACHMENT_H_ diff --git a/ipc/ipc_message_attachment_set.cc b/ipc/ipc_message_attachment_set.cc deleted file mode 100644 index b9a990d..0000000 --- a/ipc/ipc_message_attachment_set.cc +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) 2011 The Chromium 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/ipc_message_attachment_set.h" - -#include - -#include - -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "build/build_config.h" -#include "ipc/ipc_message_attachment.h" - -namespace IPC { - -namespace { - -unsigned count_attachments_of_type( - const std::vector>& attachments, - MessageAttachment::Type type) { - unsigned count = 0; - for (const scoped_refptr& attachment : attachments) { - if (attachment->GetType() == type) - ++count; - } - return count; -} - -} // namespace - -MessageAttachmentSet::MessageAttachmentSet() - : consumed_descriptor_highwater_(0) { -} - -MessageAttachmentSet::~MessageAttachmentSet() { - if (consumed_descriptor_highwater_ == size()) - return; - - // We close all the owning descriptors. If this message should have - // been transmitted, then closing those with close flags set mirrors - // the expected behaviour. - // - // If this message was received with more descriptors than expected - // (which could a DOS against the browser by a rogue renderer) then all - // the descriptors have their close flag set and we free all the extra - // kernel resources. - LOG(WARNING) << "MessageAttachmentSet destroyed with unconsumed attachments: " - << consumed_descriptor_highwater_ << "/" << size(); -} - -unsigned MessageAttachmentSet::num_descriptors() const { - return count_attachments_of_type(attachments_, - MessageAttachment::Type::PLATFORM_FILE); -} - -unsigned MessageAttachmentSet::size() const { - return static_cast(attachments_.size()); -} - -bool MessageAttachmentSet::AddAttachment( - scoped_refptr attachment, - size_t* index) { -#if defined(OS_POSIX) - if (attachment->GetType() == MessageAttachment::Type::PLATFORM_FILE && - num_descriptors() == kMaxDescriptorsPerMessage) { - DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full."; - return false; - } -#endif - - switch (attachment->GetType()) { - case MessageAttachment::Type::PLATFORM_FILE: - case MessageAttachment::Type::MOJO_HANDLE: - case MessageAttachment::Type::WIN_HANDLE: - case MessageAttachment::Type::MACH_PORT: - attachments_.push_back(attachment); - *index = attachments_.size() - 1; - return true; - } - return false; -} - -bool MessageAttachmentSet::AddAttachment( - scoped_refptr attachment) { - size_t index; - return AddAttachment(attachment, &index); -} - -scoped_refptr MessageAttachmentSet::GetAttachmentAt( - unsigned index) { - if (index >= size()) { - DLOG(WARNING) << "Accessing out of bound index:" << index << "/" << size(); - return scoped_refptr(); - } - - // We should always walk the descriptors in order, so it's reasonable to - // enforce this. Consider the case where a compromised renderer sends us - // the following message: - // - // ExampleMsg: - // num_fds:2 msg:FD(index = 1) control:SCM_RIGHTS {n, m} - // - // Here the renderer sent us a message which should have a descriptor, but - // actually sent two in an attempt to fill our fd table and kill us. By - // setting the index of the descriptor in the message to 1 (it should be - // 0), we would record a highwater of 1 and then consider all the - // descriptors to have been used. - // - // So we can either track of the use of each descriptor in a bitset, or we - // can enforce that we walk the indexes strictly in order. - // - // There's one more wrinkle: When logging messages, we may reparse them. So - // we have an exception: When the consumed_descriptor_highwater_ is at the - // end of the array and index 0 is requested, we reset the highwater value. - // TODO(morrita): This is absurd. This "wringle" disallow to introduce clearer - // ownership model. Only client is NaclIPCAdapter. See crbug.com/415294 - if (index == 0 && consumed_descriptor_highwater_ == size()) { - consumed_descriptor_highwater_ = 0; - } - - if (index != consumed_descriptor_highwater_) - return scoped_refptr(); - - consumed_descriptor_highwater_ = index + 1; - - return attachments_[index]; -} - -void MessageAttachmentSet::CommitAllDescriptors() { - attachments_.clear(); - consumed_descriptor_highwater_ = 0; -} - -} // namespace IPC diff --git a/ipc/ipc_message_attachment_set.h b/ipc/ipc_message_attachment_set.h deleted file mode 100644 index de37211..0000000 --- a/ipc/ipc_message_attachment_set.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2011 The Chromium 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_IPC_MESSAGE_ATTACHMENT_SET_H_ -#define IPC_IPC_MESSAGE_ATTACHMENT_SET_H_ - -#include - -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "build/build_config.h" -#include "ipc/ipc_export.h" - -namespace IPC { - -class MessageAttachment; - -// ----------------------------------------------------------------------------- -// A MessageAttachmentSet is an ordered set of MessageAttachment objects -// associated with an IPC message. All attachments are wrapped in a mojo handle -// if necessary and sent over the mojo message pipe. -// -// For ChannelNacl under SFI NaCl, only Type::PLATFORM_FILE is supported. In -// that case, the FD is sent over socket. -// ----------------------------------------------------------------------------- -class IPC_EXPORT MessageAttachmentSet - : public base::RefCountedThreadSafe { - public: - MessageAttachmentSet(); - - // Return the number of attachments - unsigned size() const; - - // Return true if no unconsumed descriptors remain - bool empty() const { return attachments_.empty(); } - - // Returns whether the attachment was successfully added. - // |index| is an output variable. On success, it contains the index of the - // newly added attachment. - bool AddAttachment(scoped_refptr attachment, - size_t* index); - - // Similar to the above method, but without output variables. - bool AddAttachment(scoped_refptr attachment); - - // Take the nth from the beginning of the vector, Code using this /must/ - // access the attachments in order, and must do it at most once. - // - // This interface is designed for the deserialising code as it doesn't - // support close flags. - // returns: an attachment, or nullptr on error - scoped_refptr GetAttachmentAt(unsigned index); - - // Marks all the descriptors as consumed and closes those which are - // auto-close. - void CommitAllDescriptors(); - -#if defined(OS_POSIX) - // This is the maximum number of descriptors per message. We need to know this - // because the control message kernel interface has to be given a buffer which - // is large enough to store all the descriptor numbers. Otherwise the kernel - // tells us that it truncated the control data and the extra descriptors are - // lost. - // - // In debugging mode, it's a fatal error to try and add more than this number - // of descriptors to a MessageAttachmentSet. - static const size_t kMaxDescriptorsPerMessage = 7; -#endif // OS_POSIX - - // --------------------------------------------------------------------------- - - private: - friend class base::RefCountedThreadSafe; - - ~MessageAttachmentSet(); - - // Return the number of file descriptors - unsigned num_descriptors() const; - - std::vector> attachments_; - - // This contains the index of the next descriptor which should be consumed. - // It's used in a couple of ways. Firstly, at destruction we can check that - // all the descriptors have been read (with GetNthDescriptor). Secondly, we - // can check that they are read in order. - unsigned consumed_descriptor_highwater_; - - DISALLOW_COPY_AND_ASSIGN(MessageAttachmentSet); -}; - -} // namespace IPC - -#endif // IPC_IPC_MESSAGE_ATTACHMENT_SET_H_ diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h deleted file mode 100644 index 1368635..0000000 --- a/ipc/ipc_message_start.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2012 The Chromium 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_IPC_MESSAGE_START_H_ -#define IPC_IPC_MESSAGE_START_H_ - -// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique -// base. Messages have unique IDs across channels in order for the IPC logging -// code to figure out the message class from its ID. -enum IPCMessageStart { - AutomationMsgStart = 0, - FrameMsgStart, - PageMsgStart, - ViewMsgStart, - InputMsgStart, - ProfileImportMsgStart, - TestMsgStart, - DevToolsMsgStart, - WorkerMsgStart, - NaClMsgStart, - UtilityMsgStart, - GpuChannelMsgStart, - GpuMsgStart, - MediaMsgStart, - ServiceMsgStart, - PpapiMsgStart, - FirefoxImporterUnittestMsgStart, - FileUtilitiesMsgStart, - DatabaseMsgStart, - DOMStorageMsgStart, - SpeechRecognitionMsgStart, - SafeBrowsingMsgStart, - P2PMsgStart, - ResourceMsgStart, - FileSystemMsgStart, - ChildProcessMsgStart, - ClipboardMsgStart, - BlobMsgStart, - AppCacheMsgStart, - AudioMsgStart, - MidiMsgStart, - ChromeMsgStart, - DragMsgStart, - PrintMsgStart, - SpellCheckMsgStart, - ExtensionMsgStart, - VideoCaptureMsgStart, - QuotaMsgStart, - TextInputClientMsgStart, - ChromeUtilityMsgStart, - MediaStreamMsgStart, - ChromeBenchmarkingMsgStart, - JavaBridgeMsgStart, - GamepadMsgStart, - ShellMsgStart, - AccessibilityMsgStart, - PrefetchMsgStart, - PrerenderMsgStart, - ChromotingMsgStart, - BrowserPluginMsgStart, - AndroidWebViewMsgStart, - MetroViewerMsgStart, - CCMsgStart, - MediaPlayerMsgStart, - TracingMsgStart, - PeerConnectionTrackerMsgStart, - VisitedLinkMsgStart, - AppShimMsgStart, - WebRtcLoggingMsgStart, - TtsMsgStart, - WebSocketMsgStart, - NaClHostMsgStart, - WebRTCIdentityMsgStart, - PowerMonitorMsgStart, - EncryptedMediaMsgStart, - CacheStorageMsgStart, - ServiceWorkerMsgStart, - MessagePortMsgStart, - EmbeddedWorkerMsgStart, - EmbeddedWorkerContextMsgStart, - CastMsgStart, - CdmMsgStart, - MediaStreamTrackMetricsHostMsgStart, - ChromeExtensionMsgStart, - PushMessagingMsgStart, - GinJavaBridgeMsgStart, - ChromeUtilityPrintingMsgStart, - AecDumpMsgStart, - OzoneGpuMsgStart, - ChromeUtilityExtensionsMsgStart, - PlatformNotificationMsgStart, - PDFMsgStart, - ManifestManagerMsgStart, - LayoutTestMsgStart, - NetworkHintsMsgStart, - BluetoothMsgStart, - CastMediaMsgStart, - AwMessagePortMsgStart, - SyncCompositorMsgStart, - ExtensionsGuestViewMsgStart, - GuestViewMsgStart, - // Note: CastCryptoMsgStart and CastChannelMsgStart reserved for Chromecast - // internal code. Contact gunsch@ before changing/removing. - CastCryptoMsgStart, - CastChannelMsgStart, - DataReductionProxyStart, - ChromeAppBannerMsgStart, - AttachmentBrokerMsgStart, - RenderProcessMsgStart, - PageLoadMetricsMsgStart, - MemoryMsgStart, - IPCTestMsgStart, - ArcInstanceMsgStart, - ArcInstanceHostMsgStart, - DistillerMsgStart, - ArcCameraMsgStart, - DWriteFontProxyMsgStart, - MediaPlayerDelegateMsgStart, - SurfaceViewManagerMsgStart, - ExtensionWorkerMsgStart, - SubresourceFilterMsgStart, - LastIPCMsgStart // Must come last. -}; - -#endif // IPC_IPC_MESSAGE_START_H_ diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc deleted file mode 100644 index bf8daa5..0000000 --- a/ipc/ipc_message_utils.cc +++ /dev/null @@ -1,1238 +0,0 @@ -// Copyright (c) 2012 The Chromium 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/ipc_message_utils.h" - -#include -#include - -#include "base/files/file_path.h" -#include "base/json/json_writer.h" -#include "base/strings/nullable_string16.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "base/unguessable_token.h" -#include "base/values.h" -#include "build/build_config.h" -#include "ipc/ipc_channel_handle.h" -#include "ipc/ipc_message_attachment.h" -#include "ipc/ipc_message_attachment_set.h" -#include "ipc/ipc_mojo_param_traits.h" - -#if defined(OS_POSIX) -#include "base/file_descriptor_posix.h" -#include "ipc/ipc_platform_file_attachment_posix.h" -#endif - -#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) -#include "base/memory/shared_memory_handle.h" -#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include "ipc/mach_port_mac.h" -#endif - -#if defined(OS_WIN) -#include -#include "ipc/handle_win.h" -#endif - -namespace IPC { - -namespace { - -const int kMaxRecursionDepth = 200; - -template -void LogBytes(const std::vector& data, std::string* out) { -#if defined(OS_WIN) - // Windows has a GUI for logging, which can handle arbitrary binary data. - for (size_t i = 0; i < data.size(); ++i) - out->push_back(data[i]); -#else - // On POSIX, we log to stdout, which we assume can display ASCII. - static const size_t kMaxBytesToLog = 100; - for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) { - if (isprint(data[i])) - out->push_back(data[i]); - else - out->append( - base::StringPrintf("[%02X]", static_cast(data[i]))); - } - if (data.size() > kMaxBytesToLog) { - out->append(base::StringPrintf( - " and %u more bytes", - static_cast(data.size() - kMaxBytesToLog))); - } -#endif -} - -bool ReadValue(const base::Pickle* m, - base::PickleIterator* iter, - base::Value** value, - int recursion); - -void GetValueSize(base::PickleSizer* sizer, - const base::Value* value, - int recursion) { - if (recursion > kMaxRecursionDepth) { - LOG(ERROR) << "Max recursion depth hit in GetValueSize."; - return; - } - - sizer->AddInt(); - switch (value->GetType()) { - case base::Value::Type::NONE: - break; - case base::Value::Type::BOOLEAN: - sizer->AddBool(); - break; - case base::Value::Type::INTEGER: - sizer->AddInt(); - break; - case base::Value::Type::DOUBLE: - sizer->AddDouble(); - break; - case base::Value::Type::STRING: { - const base::Value* result; - value->GetAsString(&result); - if (value->GetAsString(&result)) { - DCHECK(result); - GetParamSize(sizer, result->GetString()); - } else { - std::string str; - bool as_string_result = value->GetAsString(&str); - DCHECK(as_string_result); - GetParamSize(sizer, str); - } - break; - } - case base::Value::Type::BINARY: { - sizer->AddData(static_cast(value->GetSize())); - break; - } - case base::Value::Type::DICTIONARY: { - sizer->AddInt(); - const base::DictionaryValue* dict = - static_cast(value); - for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); - it.Advance()) { - GetParamSize(sizer, it.key()); - GetValueSize(sizer, &it.value(), recursion + 1); - } - break; - } - case base::Value::Type::LIST: { - sizer->AddInt(); - const base::ListValue* list = static_cast(value); - for (const auto& entry : *list) { - GetValueSize(sizer, entry.get(), recursion + 1); - } - break; - } - default: - NOTREACHED() << "Invalid base::Value type."; - } -} - -void WriteValue(base::Pickle* m, const base::Value* value, int recursion) { - bool result; - if (recursion > kMaxRecursionDepth) { - LOG(ERROR) << "Max recursion depth hit in WriteValue."; - return; - } - - m->WriteInt(static_cast(value->GetType())); - - switch (value->GetType()) { - case base::Value::Type::NONE: - break; - case base::Value::Type::BOOLEAN: { - bool val; - result = value->GetAsBoolean(&val); - DCHECK(result); - WriteParam(m, val); - break; - } - case base::Value::Type::INTEGER: { - int val; - result = value->GetAsInteger(&val); - DCHECK(result); - WriteParam(m, val); - break; - } - case base::Value::Type::DOUBLE: { - double val; - result = value->GetAsDouble(&val); - DCHECK(result); - WriteParam(m, val); - break; - } - case base::Value::Type::STRING: { - std::string val; - result = value->GetAsString(&val); - DCHECK(result); - WriteParam(m, val); - break; - } - case base::Value::Type::BINARY: { - m->WriteData(value->GetBuffer(), static_cast(value->GetSize())); - break; - } - case base::Value::Type::DICTIONARY: { - const base::DictionaryValue* dict = - static_cast(value); - - WriteParam(m, static_cast(dict->size())); - - for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); - it.Advance()) { - WriteParam(m, it.key()); - WriteValue(m, &it.value(), recursion + 1); - } - break; - } - case base::Value::Type::LIST: { - const base::ListValue* list = static_cast(value); - WriteParam(m, static_cast(list->GetSize())); - for (const auto& entry : *list) { - WriteValue(m, entry.get(), recursion + 1); - } - break; - } - } -} - -// Helper for ReadValue that reads a DictionaryValue into a pre-allocated -// object. -bool ReadDictionaryValue(const base::Pickle* m, - base::PickleIterator* iter, - base::DictionaryValue* value, - int recursion) { - int size; - if (!ReadParam(m, iter, &size)) - return false; - - for (int i = 0; i < size; ++i) { - std::string key; - base::Value* subval; - if (!ReadParam(m, iter, &key) || - !ReadValue(m, iter, &subval, recursion + 1)) - return false; - value->SetWithoutPathExpansion(key, subval); - } - - return true; -} - -// Helper for ReadValue that reads a ReadListValue into a pre-allocated -// object. -bool ReadListValue(const base::Pickle* m, - base::PickleIterator* iter, - base::ListValue* value, - int recursion) { - int size; - if (!ReadParam(m, iter, &size)) - return false; - - for (int i = 0; i < size; ++i) { - base::Value* subval; - if (!ReadValue(m, iter, &subval, recursion + 1)) - return false; - value->Set(i, subval); - } - - return true; -} - -bool ReadValue(const base::Pickle* m, - base::PickleIterator* iter, - base::Value** value, - int recursion) { - if (recursion > kMaxRecursionDepth) { - LOG(ERROR) << "Max recursion depth hit in ReadValue."; - return false; - } - - int type; - if (!ReadParam(m, iter, &type)) - return false; - - switch (static_cast(type)) { - case base::Value::Type::NONE: - *value = base::Value::CreateNullValue().release(); - break; - case base::Value::Type::BOOLEAN: { - bool val; - if (!ReadParam(m, iter, &val)) - return false; - *value = new base::Value(val); - break; - } - case base::Value::Type::INTEGER: { - int val; - if (!ReadParam(m, iter, &val)) - return false; - *value = new base::Value(val); - break; - } - case base::Value::Type::DOUBLE: { - double val; - if (!ReadParam(m, iter, &val)) - return false; - *value = new base::Value(val); - break; - } - case base::Value::Type::STRING: { - std::string val; - if (!ReadParam(m, iter, &val)) - return false; - *value = new base::Value(val); - break; - } - case base::Value::Type::BINARY: { - const char* data; - int length; - if (!iter->ReadData(&data, &length)) - return false; - std::unique_ptr val = - base::BinaryValue::CreateWithCopiedBuffer(data, length); - *value = val.release(); - break; - } - case base::Value::Type::DICTIONARY: { - std::unique_ptr val(new base::DictionaryValue()); - if (!ReadDictionaryValue(m, iter, val.get(), recursion)) - return false; - *value = val.release(); - break; - } - case base::Value::Type::LIST: { - std::unique_ptr val(new base::ListValue()); - if (!ReadListValue(m, iter, val.get(), recursion)) - return false; - *value = val.release(); - break; - } - default: - return false; - } - - return true; -} - -} // namespace - -// ----------------------------------------------------------------------------- - -LogData::LogData() - : routing_id(0), - type(0), - sent(0), - receive(0), - dispatch(0) { -} - -LogData::LogData(const LogData& other) = default; - -LogData::~LogData() { -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(p ? "true" : "false"); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddBytes(sizeof(param_type)); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - m->WriteBytes(&p, sizeof(param_type)); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - const char* data; - if (!iter->ReadBytes(&data, sizeof(param_type))) - return false; - memcpy(r, data, sizeof(param_type)); - return true; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::IntToString(p)); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddBytes(sizeof(param_type)); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - m->WriteBytes(&p, sizeof(param_type)); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - const char* data; - if (!iter->ReadBytes(&data, sizeof(param_type))) - return false; - memcpy(r, data, sizeof(param_type)); - return true; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::UintToString(p)); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddBytes(sizeof(param_type)); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - m->WriteBytes(&p, sizeof(param_type)); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - const char* data; - if (!iter->ReadBytes(&data, sizeof(param_type))) - return false; - memcpy(r, data, sizeof(param_type)); - return true; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::UintToString(p)); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::IntToString(p)); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::UintToString(p)); -} - -#if defined(OS_WIN) || defined(OS_LINUX) || \ - (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS)) -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::Int64ToString(static_cast(p))); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::Uint64ToString(static_cast(p))); -} -#endif - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::Int64ToString(static_cast(p))); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::Uint64ToString(p)); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::StringPrintf("%e", p)); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddBytes(sizeof(param_type)); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - m->WriteBytes(reinterpret_cast(&p), sizeof(param_type)); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - const char *data; - if (!iter->ReadBytes(&data, sizeof(*r))) { - NOTREACHED(); - return false; - } - memcpy(r, data, sizeof(param_type)); - return true; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::StringPrintf("%e", p)); -} - - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(p); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::UTF16ToUTF8(p)); -} - -void ParamTraits>::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddData(static_cast(p.size())); -} - -void ParamTraits>::Write(base::Pickle* m, - const param_type& p) { - if (p.empty()) { - m->WriteData(NULL, 0); - } else { - m->WriteData(&p.front(), static_cast(p.size())); - } -} - -bool ParamTraits>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - const char *data; - int data_size = 0; - if (!iter->ReadData(&data, &data_size) || data_size < 0) - return false; - r->resize(data_size); - if (data_size) - memcpy(&r->front(), data, data_size); - return true; -} - -void ParamTraits >::Log(const param_type& p, std::string* l) { - LogBytes(p, l); -} - -void ParamTraits>::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddData(static_cast(p.size())); -} - -void ParamTraits>::Write(base::Pickle* m, - const param_type& p) { - if (p.empty()) { - m->WriteData(NULL, 0); - } else { - m->WriteData(reinterpret_cast(&p.front()), - static_cast(p.size())); - } -} - -bool ParamTraits>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - const char *data; - int data_size = 0; - if (!iter->ReadData(&data, &data_size) || data_size < 0) - return false; - r->resize(data_size); - if (data_size) - memcpy(&r->front(), data, data_size); - return true; -} - -void ParamTraits >::Log(const param_type& p, - std::string* l) { - LogBytes(p, l); -} - -void ParamTraits>::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetParamSize(sizer, static_cast(p.size())); - for (size_t i = 0; i < p.size(); ++i) - GetParamSize(sizer, static_cast(p[i])); -} - -void ParamTraits>::Write(base::Pickle* m, - const param_type& p) { - WriteParam(m, static_cast(p.size())); - // Cast to bool below is required because libc++'s - // vector::const_reference is different from bool, and we want to avoid - // writing an extra specialization of ParamTraits for it. - for (size_t i = 0; i < p.size(); i++) - WriteParam(m, static_cast(p[i])); -} - -bool ParamTraits>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int size; - // ReadLength() checks for < 0 itself. - if (!iter->ReadLength(&size)) - return false; - r->resize(size); - for (int i = 0; i < size; i++) { - bool value; - if (!ReadParam(m, iter, &value)) - return false; - (*r)[i] = value; - } - return true; -} - -void ParamTraits >::Log(const param_type& p, std::string* l) { - for (size_t i = 0; i < p.size(); ++i) { - if (i != 0) - l->push_back(' '); - LogParam(static_cast(p[i]), l); - } -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetValueSize(sizer, &p, 0); -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { - WriteValue(m, &p, 0); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int type; - if (!ReadParam(m, iter, &type) || - type != static_cast(base::Value::Type::DICTIONARY)) - return false; - - return ReadDictionaryValue(m, iter, r, 0); -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - std::string json; - base::JSONWriter::Write(p, &json); - l->append(json); -} - -#if defined(OS_POSIX) -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetParamSize(sizer, p.fd >= 0); - if (p.fd >= 0) - sizer->AddAttachment(); -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { - const bool valid = p.fd >= 0; - WriteParam(m, valid); - - if (!valid) - return; - - if (p.auto_close) { - if (!m->WriteAttachment( - new internal::PlatformFileAttachment(base::ScopedFD(p.fd)))) - NOTREACHED(); - } else { - if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd))) - NOTREACHED(); - } -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - *r = base::FileDescriptor(); - - bool valid; - if (!ReadParam(m, iter, &valid)) - return false; - - // TODO(morrita): Seems like this should return false. - if (!valid) - return true; - - scoped_refptr attachment; - if (!m->ReadAttachment(iter, &attachment)) - return false; - - if (static_cast(attachment.get())->GetType() != - MessageAttachment::Type::PLATFORM_FILE) { - return false; - } - - *r = base::FileDescriptor( - static_cast(attachment.get()) - ->TakePlatformFile(), - true); - return true; -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - if (p.auto_close) { - l->append(base::StringPrintf("FD(%d auto-close)", p.fd)); - } else { - l->append(base::StringPrintf("FD(%d)", p.fd)); - } -} -#endif // defined(OS_POSIX) - -#if defined(OS_MACOSX) && !defined(OS_IOS) -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetParamSize(sizer, p.GetMemoryObject()); - uint32_t dummy = 0; - GetParamSize(sizer, dummy); -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { - MachPortMac mach_port_mac(p.GetMemoryObject()); - ParamTraits::Write(m, mach_port_mac); - size_t size = 0; - bool result = p.GetSize(&size); - DCHECK(result); - ParamTraits::Write(m, static_cast(size)); - - // If the caller intended to pass ownership to the IPC stack, release a - // reference. - if (p.OwnershipPassesToIPC()) - p.Close(); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - MachPortMac mach_port_mac; - if (!ParamTraits::Read(m, iter, &mach_port_mac)) - return false; - - uint32_t size; - if (!ParamTraits::Read(m, iter, &size)) - return false; - - *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(), - static_cast(size), - base::GetCurrentProcId()); - return true; -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - l->append("Mach port: "); - LogParam(p.GetMemoryObject(), l); -} - -#elif defined(OS_WIN) -void ParamTraits::GetSize(base::PickleSizer* s, - const param_type& p) { - GetParamSize(s, p.NeedsBrokering()); - if (p.NeedsBrokering()) { - GetParamSize(s, p.GetHandle()); - } else { - GetParamSize(s, HandleToLong(p.GetHandle())); - } -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { - m->WriteBool(p.NeedsBrokering()); - - if (p.NeedsBrokering()) { - HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE); - ParamTraits::Write(m, handle_win); - - // If the caller intended to pass ownership to the IPC stack, release a - // reference. - if (p.OwnershipPassesToIPC() && p.BelongsToCurrentProcess()) - p.Close(); - } else { - m->WriteInt(HandleToLong(p.GetHandle())); - } -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - bool needs_brokering; - if (!iter->ReadBool(&needs_brokering)) - return false; - - if (needs_brokering) { - HandleWin handle_win; - if (!ParamTraits::Read(m, iter, &handle_win)) - return false; - *r = base::SharedMemoryHandle(handle_win.get_handle(), - base::GetCurrentProcId()); - return true; - } - - int handle_int; - if (!iter->ReadInt(&handle_int)) - return false; - HANDLE handle = LongToHandle(handle_int); - *r = base::SharedMemoryHandle(handle, base::GetCurrentProcId()); - return true; -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - LogParam(p.GetHandle(), l); - l->append(" needs brokering: "); - LogParam(p.NeedsBrokering(), l); -} -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - p.GetSizeForPickle(sizer); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - p.WriteToPickle(m); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return r->ReadFromPickle(iter); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - ParamTraits::Log(p.value(), l); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetValueSize(sizer, &p, 0); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - WriteValue(m, &p, 0); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int type; - if (!ReadParam(m, iter, &type) || - type != static_cast(base::Value::Type::LIST)) - return false; - - return ReadListValue(m, iter, r, 0); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - std::string json; - base::JSONWriter::Write(p, &json); - l->append(json); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetParamSize(sizer, p.string()); - GetParamSize(sizer, p.is_null()); -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { - WriteParam(m, p.string()); - WriteParam(m, p.is_null()); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - base::string16 string; - if (!ReadParam(m, iter, &string)) - return false; - bool is_null; - if (!ReadParam(m, iter, &is_null)) - return false; - *r = base::NullableString16(string, is_null); - return true; -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - l->append("("); - LogParam(p.string(), l); - l->append(", "); - LogParam(p.is_null(), l); - l->append(")"); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetParamSize(sizer, p.size); - GetParamSize(sizer, p.is_directory); - GetParamSize(sizer, p.last_modified.ToDoubleT()); - GetParamSize(sizer, p.last_accessed.ToDoubleT()); - GetParamSize(sizer, p.creation_time.ToDoubleT()); -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { - WriteParam(m, p.size); - WriteParam(m, p.is_directory); - WriteParam(m, p.last_modified.ToDoubleT()); - WriteParam(m, p.last_accessed.ToDoubleT()); - WriteParam(m, p.creation_time.ToDoubleT()); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* p) { - double last_modified, last_accessed, creation_time; - if (!ReadParam(m, iter, &p->size) || - !ReadParam(m, iter, &p->is_directory) || - !ReadParam(m, iter, &last_modified) || - !ReadParam(m, iter, &last_accessed) || - !ReadParam(m, iter, &creation_time)) - return false; - p->last_modified = base::Time::FromDoubleT(last_modified); - p->last_accessed = base::Time::FromDoubleT(last_accessed); - p->creation_time = base::Time::FromDoubleT(creation_time); - return true; -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - l->append("("); - LogParam(p.size, l); - l->append(","); - LogParam(p.is_directory, l); - l->append(","); - LogParam(p.last_modified.ToDoubleT(), l); - l->append(","); - LogParam(p.last_accessed.ToDoubleT(), l); - l->append(","); - LogParam(p.creation_time.ToDoubleT(), l); - l->append(")"); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddInt64(); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - ParamTraits::Write(m, p.ToInternalValue()); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int64_t value; - if (!ParamTraits::Read(m, iter, &value)) - return false; - *r = base::Time::FromInternalValue(value); - return true; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - ParamTraits::Log(p.ToInternalValue(), l); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddInt64(); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - ParamTraits::Write(m, p.ToInternalValue()); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int64_t value; - bool ret = ParamTraits::Read(m, iter, &value); - if (ret) - *r = base::TimeDelta::FromInternalValue(value); - - return ret; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - ParamTraits::Log(p.ToInternalValue(), l); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddInt64(); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - ParamTraits::Write(m, p.ToInternalValue()); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int64_t value; - bool ret = ParamTraits::Read(m, iter, &value); - if (ret) - *r = base::TimeTicks::FromInternalValue(value); - - return ret; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - ParamTraits::Log(p.ToInternalValue(), l); -} - -// If base::UnguessableToken is no longer 128 bits, the IPC serialization logic -// below should be updated. -static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t), - "base::UnguessableToken should be of size 2 * sizeof(uint64_t)."); - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddBytes(2 * sizeof(uint64_t)); -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { - DCHECK(!p.is_empty()); - - ParamTraits::Write(m, p.GetHighForSerialization()); - ParamTraits::Write(m, p.GetLowForSerialization()); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - uint64_t high, low; - if (!ParamTraits::Read(m, iter, &high) || - !ParamTraits::Read(m, iter, &low)) - return false; - - // Receiving a zeroed UnguessableToken is a security issue. - if (high == 0 && low == 0) - return false; - - *r = base::UnguessableToken::Deserialize(high, low); - return true; -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - l->append(p.ToString()); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { -#if defined(OS_NACL_SFI) - GetParamSize(sizer, p.socket); -#else - GetParamSize(sizer, p.mojo_handle); -#endif -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { -#if defined(OS_NACL_SFI) - WriteParam(m, p.socket); -#else - WriteParam(m, p.mojo_handle); -#endif -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { -#if defined(OS_NACL_SFI) - return ReadParam(m, iter, &r->socket); -#else - return ReadParam(m, iter, &r->mojo_handle); -#endif -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - l->append("ChannelHandle("); -#if defined(OS_NACL_SFI) - ParamTraits::Log(p.socket, l); -#else - LogParam(p.mojo_handle, l); -#endif - l->append(")"); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetParamSize(sizer, p.channel); - GetParamSize(sizer, p.routing_id); - GetParamSize(sizer, p.type); - GetParamSize(sizer, p.flags); - GetParamSize(sizer, p.sent); - GetParamSize(sizer, p.receive); - GetParamSize(sizer, p.dispatch); - GetParamSize(sizer, p.message_name); - GetParamSize(sizer, p.params); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - WriteParam(m, p.channel); - WriteParam(m, p.routing_id); - WriteParam(m, p.type); - WriteParam(m, p.flags); - WriteParam(m, p.sent); - WriteParam(m, p.receive); - WriteParam(m, p.dispatch); - WriteParam(m, p.message_name); - WriteParam(m, p.params); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return - ReadParam(m, iter, &r->channel) && - ReadParam(m, iter, &r->routing_id) && - ReadParam(m, iter, &r->type) && - ReadParam(m, iter, &r->flags) && - ReadParam(m, iter, &r->sent) && - ReadParam(m, iter, &r->receive) && - ReadParam(m, iter, &r->dispatch) && - ReadParam(m, iter, &r->message_name) && - ReadParam(m, iter, &r->params); -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - // Doesn't make sense to implement this! -} - -void ParamTraits::Write(base::Pickle* m, const Message& p) { -#if defined(OS_POSIX) - // We don't serialize the file descriptors in the nested message, so there - // better not be any. - DCHECK(!p.HasAttachments()); -#endif - - // Don't just write out the message. This is used to send messages between - // NaCl (Posix environment) and the browser (could be on Windows). The message - // header formats differ between these systems (so does handle sharing, but - // we already asserted we don't have any handles). So just write out the - // parts of the header we use. - // - // Be careful also to use only explicitly-sized types. The NaCl environment - // could be 64-bit and the host browser could be 32-bits. The nested message - // may or may not be safe to send between 32-bit and 64-bit systems, but we - // leave that up to the code sending the message to ensure. - m->WriteUInt32(static_cast(p.routing_id())); - m->WriteUInt32(p.type()); - m->WriteUInt32(p.flags()); - m->WriteData(p.payload(), static_cast(p.payload_size())); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - Message* r) { - uint32_t routing_id, type, flags; - if (!iter->ReadUInt32(&routing_id) || - !iter->ReadUInt32(&type) || - !iter->ReadUInt32(&flags)) - return false; - - int payload_size; - const char* payload; - if (!iter->ReadData(&payload, &payload_size)) - return false; - - r->SetHeaderValues(static_cast(routing_id), type, flags); - return r->WriteBytes(payload, payload_size); -} - -void ParamTraits::Log(const Message& p, std::string* l) { - l->append(""); -} - -#if defined(OS_WIN) -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddInt(); -} - -// Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64 -// bit systems. That's why we use the Windows macros to convert to 32 bits. -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - m->WriteInt(HandleToLong(p)); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int32_t temp; - if (!iter->ReadInt(&temp)) - return false; - *r = LongToHandle(temp); - return true; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::StringPrintf("0x%p", p)); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - sizer->AddData(sizeof(LOGFONT)); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - m->WriteData(reinterpret_cast(&p), sizeof(LOGFONT)); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - const char *data; - int data_size = 0; - if (iter->ReadData(&data, &data_size) && data_size == sizeof(LOGFONT)) { - const LOGFONT *font = reinterpret_cast(const_cast(data)); - if (_tcsnlen(font->lfFaceName, LF_FACESIZE) < LF_FACESIZE) { - memcpy(r, data, sizeof(LOGFONT)); - return true; - } - } - - NOTREACHED(); - return false; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(base::StringPrintf("")); -} - -void ParamTraits::GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddData(sizeof(MSG)); -} - -void ParamTraits::Write(base::Pickle* m, const param_type& p) { - m->WriteData(reinterpret_cast(&p), sizeof(MSG)); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - const char *data; - int data_size = 0; - bool result = iter->ReadData(&data, &data_size); - if (result && data_size == sizeof(MSG)) { - memcpy(r, data, sizeof(MSG)); - } else { - result = false; - NOTREACHED(); - } - - return result; -} - -void ParamTraits::Log(const param_type& p, std::string* l) { - l->append(""); -} - -#endif // OS_WIN - -} // namespace IPC diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h deleted file mode 100644 index 2d51c98..0000000 --- a/ipc/ipc_message_utils.h +++ /dev/null @@ -1,1145 +0,0 @@ -// Copyright (c) 2012 The Chromium 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_IPC_MESSAGE_UTILS_H_ -#define IPC_IPC_MESSAGE_UTILS_H_ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "base/containers/small_map.h" -#include "base/containers/stack_container.h" -#include "base/files/file.h" -#include "base/format_macros.h" -#include "base/optional.h" -#include "base/strings/string16.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "build/build_config.h" -#include "ipc/ipc_message_start.h" -#include "ipc/ipc_param_traits.h" -#include "ipc/ipc_sync_message.h" - -namespace base { -class DictionaryValue; -class FilePath; -class ListValue; -class NullableString16; -class Time; -class TimeDelta; -class TimeTicks; -class UnguessableToken; -struct FileDescriptor; - -#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) -class SharedMemoryHandle; -#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) -} - -namespace IPC { - -struct ChannelHandle; - -// ----------------------------------------------------------------------------- -// How we send IPC message logs across channels. -struct IPC_EXPORT LogData { - LogData(); - LogData(const LogData& other); - ~LogData(); - - std::string channel; - int32_t routing_id; - uint32_t type; // "User-defined" message type, from ipc_message.h. - std::string flags; - int64_t sent; // Time that the message was sent (i.e. at Send()). - int64_t receive; // Time before it was dispatched (i.e. before calling - // OnMessageReceived). - int64_t dispatch; // Time after it was dispatched (i.e. after calling - // OnMessageReceived). - std::string message_name; - std::string params; -}; - -//----------------------------------------------------------------------------- - -// A dummy struct to place first just to allow leading commas for all -// members in the macro-generated constructor initializer lists. -struct NoParams { -}; - -// Specializations are checked by 'IPC checker' part of find-bad-constructs -// Clang plugin (see WriteParam() below for the details). -template -struct CheckedTuple { - typedef std::tuple Tuple; -}; - -template -static inline void GetParamSize(base::PickleSizer* sizer, const P& p) { - typedef typename SimilarTypeTraits

::Type Type; - ParamTraits::GetSize(sizer, static_cast(p)); -} - -// This function is checked by 'IPC checker' part of find-bad-constructs -// Clang plugin to make it's not called on the following types: -// 1. long / unsigned long (but not typedefs to) -// 2. intmax_t, uintmax_t, intptr_t, uintptr_t, wint_t, -// size_t, rsize_t, ssize_t, ptrdiff_t, dev_t, off_t, clock_t, -// time_t, suseconds_t (including typedefs to) -// 3. Any template referencing types above (e.g. std::vector) -template -static inline void WriteParam(base::Pickle* m, const P& p) { - typedef typename SimilarTypeTraits

::Type Type; - ParamTraits::Write(m, static_cast(p)); -} - -template -static inline bool WARN_UNUSED_RESULT ReadParam(const base::Pickle* m, - base::PickleIterator* iter, - P* p) { - typedef typename SimilarTypeTraits

::Type Type; - return ParamTraits::Read(m, iter, reinterpret_cast(p)); -} - -template -static inline void LogParam(const P& p, std::string* l) { - typedef typename SimilarTypeTraits

::Type Type; - ParamTraits::Log(static_cast(p), l); -} - -// Primitive ParamTraits ------------------------------------------------------- - -template <> -struct ParamTraits { - typedef bool param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddBool(); - } - static void Write(base::Pickle* m, const param_type& p) { m->WriteBool(p); } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadBool(r); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef signed char param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef unsigned char param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef unsigned short param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct ParamTraits { - typedef int param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddInt(); - } - static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadInt(r); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; - -template <> -struct ParamTraits { - typedef unsigned int param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddInt(); - } - static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadInt(reinterpret_cast(r)); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; - -// long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but -// 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel -// that would cause problem. -// We need to keep this on for a few configs: -// 1) Windows because DWORD is typedef'd to it, which is fine because we have -// very few IPCs that cross this boundary. -// 2) We also need to keep it for Linux for two reasons: int64_t is typedef'd -// to long, and gfx::PluginWindow is long and is used in one GPU IPC. -// 3) Android 64 bit also has int64_t typedef'd to long. -// Since we want to support Android 32<>64 bit IPC, as long as we don't have -// these traits for 32 bit ARM then that'll catch any errors. -#if defined(OS_WIN) || defined(OS_LINUX) || \ - (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS)) -template <> -struct ParamTraits { - typedef long param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddLong(); - } - static void Write(base::Pickle* m, const param_type& p) { - m->WriteLong(p); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadLong(r); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; - -template <> -struct ParamTraits { - typedef unsigned long param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddLong(); - } - static void Write(base::Pickle* m, const param_type& p) { - m->WriteLong(p); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadLong(reinterpret_cast(r)); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; -#endif - -template <> -struct ParamTraits { - typedef long long param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddInt64(); - } - static void Write(base::Pickle* m, const param_type& p) { - m->WriteInt64(static_cast(p)); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadInt64(reinterpret_cast(r)); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; - -template <> -struct ParamTraits { - typedef unsigned long long param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddInt64(); - } - static void Write(base::Pickle* m, const param_type& p) { m->WriteInt64(p); } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadInt64(reinterpret_cast(r)); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; - -// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients -// should be sure to check the sanity of these values after receiving them over -// IPC. -template <> -struct IPC_EXPORT ParamTraits { - typedef float param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddFloat(); - } - static void Write(base::Pickle* m, const param_type& p) { m->WriteFloat(p); } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadFloat(r); - } - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef double param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template -struct ParamTraits { - using param_type = P[Size]; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - for (const P& element : p) - GetParamSize(sizer, element); - } - static void Write(base::Pickle* m, const param_type& p) { - for (const P& element : p) - WriteParam(m, element); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - for (P& element : *r) { - if (!ReadParam(m, iter, &element)) - return false; - } - return true; - } - static void Log(const param_type& p, std::string* l) { - l->append("["); - for (const P& element : p) { - if (&element != &p[0]) - l->append(" "); - LogParam(element, l); - } - l->append("]"); - } -}; - -// STL ParamTraits ------------------------------------------------------------- - -template <> -struct ParamTraits { - typedef std::string param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddString(p); - } - static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadString(r); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; - -template <> -struct ParamTraits { - typedef base::string16 param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddString16(p); - } - static void Write(base::Pickle* m, const param_type& p) { - m->WriteString16(p); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return iter->ReadString16(r); - } - IPC_EXPORT static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits > { - typedef std::vector param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle*, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits > { - typedef std::vector param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits > { - typedef std::vector param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template -struct ParamTraits> { - typedef std::vector

param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, static_cast(p.size())); - for (size_t i = 0; i < p.size(); i++) - GetParamSize(sizer, p[i]); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, static_cast(p.size())); - for (size_t i = 0; i < p.size(); i++) - WriteParam(m, p[i]); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int size; - // ReadLength() checks for < 0 itself. - if (!iter->ReadLength(&size)) - return false; - // Resizing beforehand is not safe, see BUG 1006367 for details. - if (INT_MAX / sizeof(P) <= static_cast(size)) - return false; - r->resize(size); - for (int i = 0; i < size; i++) { - if (!ReadParam(m, iter, &(*r)[i])) - return false; - } - return true; - } - static void Log(const param_type& p, std::string* l) { - for (size_t i = 0; i < p.size(); ++i) { - if (i != 0) - l->append(" "); - LogParam((p[i]), l); - } - } -}; - -template -struct ParamTraits > { - typedef std::set

param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, static_cast(p.size())); - typename param_type::const_iterator iter; - for (iter = p.begin(); iter != p.end(); ++iter) - GetParamSize(sizer, *iter); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, static_cast(p.size())); - typename param_type::const_iterator iter; - for (iter = p.begin(); iter != p.end(); ++iter) - WriteParam(m, *iter); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int size; - if (!iter->ReadLength(&size)) - return false; - for (int i = 0; i < size; ++i) { - P item; - if (!ReadParam(m, iter, &item)) - return false; - r->insert(item); - } - return true; - } - static void Log(const param_type& p, std::string* l) { - l->append(""); - } -}; - -template -struct ParamTraits > { - typedef std::map param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, static_cast(p.size())); - typename param_type::const_iterator iter; - for (iter = p.begin(); iter != p.end(); ++iter) { - GetParamSize(sizer, iter->first); - GetParamSize(sizer, iter->second); - } - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, static_cast(p.size())); - typename param_type::const_iterator iter; - for (iter = p.begin(); iter != p.end(); ++iter) { - WriteParam(m, iter->first); - WriteParam(m, iter->second); - } - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int size; - if (!ReadParam(m, iter, &size) || size < 0) - return false; - for (int i = 0; i < size; ++i) { - K k; - if (!ReadParam(m, iter, &k)) - return false; - V& value = (*r)[k]; - if (!ReadParam(m, iter, &value)) - return false; - } - return true; - } - static void Log(const param_type& p, std::string* l) { - l->append(""); - } -}; - -template -struct ParamTraits > { - typedef std::pair param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, p.first); - GetParamSize(sizer, p.second); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, p.first); - WriteParam(m, p.second); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second); - } - static void Log(const param_type& p, std::string* l) { - l->append("("); - LogParam(p.first, l); - l->append(", "); - LogParam(p.second, l); - l->append(")"); - } -}; - -// Base ParamTraits ------------------------------------------------------------ - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::DictionaryValue param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -#if defined(OS_POSIX) -// FileDescriptors may be serialised over IPC channels on POSIX. On the -// receiving side, the FileDescriptor is a valid duplicate of the file -// descriptor which was transmitted: *it is not just a copy of the integer like -// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In -// this case, the receiving end will see a value of -1. *Zero is a valid file -// descriptor*. -// -// The received file descriptor will have the |auto_close| flag set to true. The -// code which handles the message is responsible for taking ownership of it. -// File descriptors are OS resources and must be closed when no longer needed. -// -// When sending a file descriptor, the file descriptor must be valid at the time -// of transmission. Since transmission is not synchronous, one should consider -// dup()ing any file descriptors to be transmitted and setting the |auto_close| -// flag, which causes the file descriptor to be closed after writing. -template<> -struct IPC_EXPORT ParamTraits { - typedef base::FileDescriptor param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; -#endif // defined(OS_POSIX) - -#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) -template <> -struct IPC_EXPORT ParamTraits { - typedef base::SharedMemoryHandle param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; -#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::FilePath param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::ListValue param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::NullableString16 param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::File::Info param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct SimilarTypeTraits { - typedef int Type; -}; - -#if defined(OS_WIN) -template <> -struct SimilarTypeTraits { - typedef HANDLE Type; -}; -#endif // defined(OS_WIN) - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::Time param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::TimeDelta param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::TimeTicks param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef base::UnguessableToken param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct ParamTraits> { - typedef std::tuple<> param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) {} - static void Write(base::Pickle* m, const param_type& p) {} - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return true; - } - static void Log(const param_type& p, std::string* l) { - } -}; - -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return ReadParam(m, iter, &std::get<0>(*r)); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - } -}; - -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - GetParamSize(sizer, std::get<1>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - WriteParam(m, std::get<1>(p)); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return (ReadParam(m, iter, &std::get<0>(*r)) && - ReadParam(m, iter, &std::get<1>(*r))); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - l->append(", "); - LogParam(std::get<1>(p), l); - } -}; - -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - GetParamSize(sizer, std::get<1>(p)); - GetParamSize(sizer, std::get<2>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - WriteParam(m, std::get<1>(p)); - WriteParam(m, std::get<2>(p)); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return (ReadParam(m, iter, &std::get<0>(*r)) && - ReadParam(m, iter, &std::get<1>(*r)) && - ReadParam(m, iter, &std::get<2>(*r))); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - l->append(", "); - LogParam(std::get<1>(p), l); - l->append(", "); - LogParam(std::get<2>(p), l); - } -}; - -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - GetParamSize(sizer, std::get<1>(p)); - GetParamSize(sizer, std::get<2>(p)); - GetParamSize(sizer, std::get<3>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - WriteParam(m, std::get<1>(p)); - WriteParam(m, std::get<2>(p)); - WriteParam(m, std::get<3>(p)); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return (ReadParam(m, iter, &std::get<0>(*r)) && - ReadParam(m, iter, &std::get<1>(*r)) && - ReadParam(m, iter, &std::get<2>(*r)) && - ReadParam(m, iter, &std::get<3>(*r))); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - l->append(", "); - LogParam(std::get<1>(p), l); - l->append(", "); - LogParam(std::get<2>(p), l); - l->append(", "); - LogParam(std::get<3>(p), l); - } -}; - -template -struct ParamTraits> { - typedef std::tuple param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, std::get<0>(p)); - GetParamSize(sizer, std::get<1>(p)); - GetParamSize(sizer, std::get<2>(p)); - GetParamSize(sizer, std::get<3>(p)); - GetParamSize(sizer, std::get<4>(p)); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, std::get<0>(p)); - WriteParam(m, std::get<1>(p)); - WriteParam(m, std::get<2>(p)); - WriteParam(m, std::get<3>(p)); - WriteParam(m, std::get<4>(p)); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - return (ReadParam(m, iter, &std::get<0>(*r)) && - ReadParam(m, iter, &std::get<1>(*r)) && - ReadParam(m, iter, &std::get<2>(*r)) && - ReadParam(m, iter, &std::get<3>(*r)) && - ReadParam(m, iter, &std::get<4>(*r))); - } - static void Log(const param_type& p, std::string* l) { - LogParam(std::get<0>(p), l); - l->append(", "); - LogParam(std::get<1>(p), l); - l->append(", "); - LogParam(std::get<2>(p), l); - l->append(", "); - LogParam(std::get<3>(p), l); - l->append(", "); - LogParam(std::get<4>(p), l); - } -}; - -template -struct ParamTraits > { - typedef base::StackVector param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, static_cast(p->size())); - for (size_t i = 0; i < p->size(); i++) - GetParamSize(sizer, p[i]); - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, static_cast(p->size())); - for (size_t i = 0; i < p->size(); i++) - WriteParam(m, p[i]); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int size; - // ReadLength() checks for < 0 itself. - if (!iter->ReadLength(&size)) - return false; - // Sanity check for the vector size. - if (INT_MAX / sizeof(P) <= static_cast(size)) - return false; - P value; - for (int i = 0; i < size; i++) { - if (!ReadParam(m, iter, &value)) - return false; - (*r)->push_back(value); - } - return true; - } - static void Log(const param_type& p, std::string* l) { - for (size_t i = 0; i < p->size(); ++i) { - if (i != 0) - l->append(" "); - LogParam((p[i]), l); - } - } -}; - -template -struct ParamTraits > { - typedef base::SmallMap param_type; - typedef typename param_type::key_type K; - typedef typename param_type::data_type V; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - GetParamSize(sizer, static_cast(p.size())); - typename param_type::const_iterator iter; - for (iter = p.begin(); iter != p.end(); ++iter) { - GetParamSize(sizer, iter->first); - GetParamSize(sizer, iter->second); - } - } - static void Write(base::Pickle* m, const param_type& p) { - WriteParam(m, static_cast(p.size())); - typename param_type::const_iterator iter; - for (iter = p.begin(); iter != p.end(); ++iter) { - WriteParam(m, iter->first); - WriteParam(m, iter->second); - } - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - int size; - if (!iter->ReadLength(&size)) - return false; - for (int i = 0; i < size; ++i) { - K key; - if (!ReadParam(m, iter, &key)) - return false; - V& value = (*r)[key]; - if (!ReadParam(m, iter, &value)) - return false; - } - return true; - } - static void Log(const param_type& p, std::string* l) { - l->append(""); - } -}; - -template -struct ParamTraits> { - typedef std::unique_ptr

param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - bool valid = !!p; - GetParamSize(sizer, valid); - if (valid) - GetParamSize(sizer, *p); - } - static void Write(base::Pickle* m, const param_type& p) { - bool valid = !!p; - WriteParam(m, valid); - if (valid) - WriteParam(m, *p); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - bool valid = false; - if (!ReadParam(m, iter, &valid)) - return false; - - if (!valid) { - r->reset(); - return true; - } - - param_type temp(new P()); - if (!ReadParam(m, iter, temp.get())) - return false; - - r->swap(temp); - return true; - } - static void Log(const param_type& p, std::string* l) { - if (p) - LogParam(*p, l); - else - l->append("NULL"); - } -}; - -template -struct ParamTraits> { - typedef base::Optional

param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p) { - const bool is_set = static_cast(p); - GetParamSize(sizer, is_set); - if (is_set) - GetParamSize(sizer, p.value()); - } - static void Write(base::Pickle* m, const param_type& p) { - const bool is_set = static_cast(p); - WriteParam(m, is_set); - if (is_set) - WriteParam(m, p.value()); - } - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - bool is_set = false; - if (!iter->ReadBool(&is_set)) - return false; - if (is_set) { - P value; - if (!ReadParam(m, iter, &value)) - return false; - *r = std::move(value); - } - return true; - } - static void Log(const param_type& p, std::string* l) { - if (p) - LogParam(p.value(), l); - else - l->append("(unset)"); - } -}; - -// IPC types ParamTraits ------------------------------------------------------- - -// A ChannelHandle is basically a platform-inspecific wrapper around the -// fact that IPC endpoints are handled specially on POSIX. See above comments -// on FileDescriptor for more background. -template<> -struct IPC_EXPORT ParamTraits { - typedef ChannelHandle param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef LogData param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - static void Write(base::Pickle* m, const Message& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - Message* r); - static void Log(const Message& p, std::string* l); -}; - -// Windows ParamTraits --------------------------------------------------------- - -#if defined(OS_WIN) -template <> -struct IPC_EXPORT ParamTraits { - typedef HANDLE param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef LOGFONT param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -template <> -struct IPC_EXPORT ParamTraits { - typedef MSG param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; -#endif // defined(OS_WIN) - -//----------------------------------------------------------------------------- -// Generic message subclasses - -// defined in ipc_logging.cc -IPC_EXPORT void GenerateLogData(const Message& message, - LogData* data, - bool get_params); - -#if defined(IPC_MESSAGE_LOG_ENABLED) -inline void AddOutputParamsToLog(const Message* msg, std::string* l) { - const std::string& output_params = msg->output_params(); - if (!l->empty() && !output_params.empty()) - l->append(", "); - - l->append(output_params); -} - -template -inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, - const Message* msg) { - if (msg->received_time() != 0) { - std::string output_params; - LogParam(reply_params, &output_params); - msg->set_output_params(output_params); - } -} - -inline void ConnectMessageAndReply(const Message* msg, Message* reply) { - if (msg->sent_time()) { - // Don't log the sync message after dispatch, as we don't have the - // output parameters at that point. Instead, save its data and log it - // with the outgoing reply message when it's sent. - LogData* data = new LogData; - GenerateLogData(*msg, data, true); - msg->set_dont_log(); - reply->set_sync_log_data(data); - } -} -#else -inline void AddOutputParamsToLog(const Message* msg, std::string* l) {} - -template -inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, - const Message* msg) {} - -inline void ConnectMessageAndReply(const Message* msg, Message* reply) {} -#endif - -} // namespace IPC - -#endif // IPC_IPC_MESSAGE_UTILS_H_ diff --git a/ipc/ipc_mojo_handle_attachment.cc b/ipc/ipc_mojo_handle_attachment.cc deleted file mode 100644 index e3421c3..0000000 --- a/ipc/ipc_mojo_handle_attachment.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 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/ipc_mojo_handle_attachment.h" - -#include - -#include "build/build_config.h" - -namespace IPC { -namespace internal { - -MojoHandleAttachment::MojoHandleAttachment(mojo::ScopedHandle handle) - : handle_(std::move(handle)) {} - -MojoHandleAttachment::~MojoHandleAttachment() { -} - -MessageAttachment::Type MojoHandleAttachment::GetType() const { - return Type::MOJO_HANDLE; -} - -mojo::ScopedHandle MojoHandleAttachment::TakeHandle() { - return std::move(handle_); -} - -} // namespace internal -} // namespace IPC diff --git a/ipc/ipc_mojo_handle_attachment.h b/ipc/ipc_mojo_handle_attachment.h deleted file mode 100644 index d615276..0000000 --- a/ipc/ipc_mojo_handle_attachment.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 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_IPC_MOJO_HANDLE_ATTACHMENT_H_ -#define IPC_IPC_MOJO_HANDLE_ATTACHMENT_H_ - -#include "base/files/file.h" -#include "base/macros.h" -#include "build/build_config.h" -#include "ipc/ipc_export.h" -#include "ipc/ipc_message_attachment.h" -#include "mojo/public/cpp/system/handle.h" - -namespace IPC { - -namespace internal { - -// A MessageAttachment that holds a MojoHandle. -// This can hold any type of transferrable Mojo handle (i.e. message pipe, data -// pipe, etc), but the receiver is expected to know what type of handle to -// expect. -class IPC_EXPORT MojoHandleAttachment : public MessageAttachment { - public: - explicit MojoHandleAttachment(mojo::ScopedHandle handle); - - Type GetType() const override; - - // Returns the owning handle transferring the ownership. - mojo::ScopedHandle TakeHandle(); - - private: - ~MojoHandleAttachment() override; - mojo::ScopedHandle handle_; - - DISALLOW_COPY_AND_ASSIGN(MojoHandleAttachment); -}; - -} // namespace internal -} // namespace IPC - -#endif // IPC_IPC_MOJO_HANDLE_ATTACHMENT_H_ diff --git a/ipc/ipc_mojo_message_helper.cc b/ipc/ipc_mojo_message_helper.cc deleted file mode 100644 index a87a2d6..0000000 --- a/ipc/ipc_mojo_message_helper.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 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/ipc_mojo_message_helper.h" - -#include - -#include "ipc/ipc_mojo_handle_attachment.h" - -namespace IPC { - -// static -bool MojoMessageHelper::WriteMessagePipeTo( - base::Pickle* message, - mojo::ScopedMessagePipeHandle handle) { - message->WriteAttachment(new internal::MojoHandleAttachment( - mojo::ScopedHandle::From(std::move(handle)))); - return true; -} - -// static -bool MojoMessageHelper::ReadMessagePipeFrom( - const base::Pickle* message, - base::PickleIterator* iter, - mojo::ScopedMessagePipeHandle* handle) { - scoped_refptr attachment; - if (!message->ReadAttachment(iter, &attachment)) { - LOG(ERROR) << "Failed to read attachment for message pipe."; - return false; - } - - MessageAttachment::Type type = - static_cast(attachment.get())->GetType(); - if (type != MessageAttachment::Type::MOJO_HANDLE) { - LOG(ERROR) << "Unxpected attachment type:" << type; - return false; - } - - handle->reset(mojo::MessagePipeHandle( - static_cast(attachment.get()) - ->TakeHandle() - .release() - .value())); - return true; -} - -MojoMessageHelper::MojoMessageHelper() { -} - -} // namespace IPC diff --git a/ipc/ipc_mojo_message_helper.h b/ipc/ipc_mojo_message_helper.h deleted file mode 100644 index 4a71b5c..0000000 --- a/ipc/ipc_mojo_message_helper.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 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_IPC_MOJO_MESSAGE_HELPER_H_ -#define IPC_IPC_MOJO_MESSAGE_HELPER_H_ - -#include "ipc/ipc_export.h" -#include "ipc/ipc_message.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace IPC { - -// Reads and writes |mojo::MessagePipe| from/to |Message|. -class IPC_EXPORT MojoMessageHelper { - public: - static bool WriteMessagePipeTo(base::Pickle* message, - mojo::ScopedMessagePipeHandle handle); - static bool ReadMessagePipeFrom(const base::Pickle* message, - base::PickleIterator* iter, - mojo::ScopedMessagePipeHandle* handle); - - private: - MojoMessageHelper(); -}; - -} // namespace IPC - -#endif // IPC_IPC_MOJO_MESSAGE_HELPER_H_ diff --git a/ipc/ipc_mojo_param_traits.cc b/ipc/ipc_mojo_param_traits.cc deleted file mode 100644 index 189af35..0000000 --- a/ipc/ipc_mojo_param_traits.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ipc/ipc_mojo_param_traits.h" - -#include "ipc/ipc_message_utils.h" -#include "ipc/ipc_mojo_message_helper.h" - -namespace IPC { - -void ParamTraits::GetSize(base::PickleSizer* sizer, - const param_type& p) { - GetParamSize(sizer, p.is_valid()); - if (p.is_valid()) - sizer->AddAttachment(); -} - -void ParamTraits::Write(base::Pickle* m, - const param_type& p) { - WriteParam(m, p.is_valid()); - if (p.is_valid()) - MojoMessageHelper::WriteMessagePipeTo(m, mojo::ScopedMessagePipeHandle(p)); -} - -bool ParamTraits::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - bool is_valid; - if (!ReadParam(m, iter, &is_valid)) - return false; - if (!is_valid) - return true; - - mojo::ScopedMessagePipeHandle handle; - if (!MojoMessageHelper::ReadMessagePipeFrom(m, iter, &handle)) - return false; - DCHECK(handle.is_valid()); - *r = handle.release(); - return true; -} - -void ParamTraits::Log(const param_type& p, - std::string* l) { - l->append("mojo::MessagePipeHandle("); - LogParam(p.value(), l); - l->append(")"); -} - -} // namespace IPC diff --git a/ipc/ipc_mojo_param_traits.h b/ipc/ipc_mojo_param_traits.h deleted file mode 100644 index 39be43e..0000000 --- a/ipc/ipc_mojo_param_traits.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IPC_IPC_MOJO_PARAM_TRAITS_H_ -#define IPC_IPC_MOJO_PARAM_TRAITS_H_ - -#include - -#include "ipc/ipc_export.h" -#include "ipc/ipc_param_traits.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace base { -class Pickle; -class PickleIterator; -class PickleSizer; -} - -namespace IPC { - -template <> -struct IPC_EXPORT ParamTraits { - typedef mojo::MessagePipeHandle param_type; - static void GetSize(base::PickleSizer* sizer, const param_type& p); - static void Write(base::Pickle* m, const param_type& p); - static bool Read(const base::Pickle* m, base::PickleIterator* iter, - param_type* r); - static void Log(const param_type& p, std::string* l); -}; - -} // namespace IPC - -#endif // IPC_IPC_MOJO_PARAM_TRAITS_H_ diff --git a/ipc/ipc_param_traits.h b/ipc/ipc_param_traits.h deleted file mode 100644 index 45e975c..0000000 --- a/ipc/ipc_param_traits.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2010 The Chromium 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_IPC_PARAM_TRAITS_H_ -#define IPC_IPC_PARAM_TRAITS_H_ - -// Our IPC system uses the following partially specialized header to define how -// a data type is read, written and logged in the IPC system. - -namespace IPC { - -template struct ParamTraits { -}; - -template -struct SimilarTypeTraits { - typedef P Type; -}; - -} // namespace IPC - -#endif // IPC_IPC_PARAM_TRAITS_H_ diff --git a/ipc/ipc_platform_file_attachment_posix.cc b/ipc/ipc_platform_file_attachment_posix.cc deleted file mode 100644 index 7111cfa..0000000 --- a/ipc/ipc_platform_file_attachment_posix.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 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/ipc_platform_file_attachment_posix.h" - -#include - -namespace IPC { -namespace internal { - -PlatformFileAttachment::PlatformFileAttachment(base::PlatformFile file) - : file_(file) { -} - -PlatformFileAttachment::PlatformFileAttachment(base::ScopedFD file) - : file_(file.get()), owning_(std::move(file)) {} - -PlatformFileAttachment::~PlatformFileAttachment() { -} - -MessageAttachment::Type PlatformFileAttachment::GetType() const { - return Type::PLATFORM_FILE; -} - -base::PlatformFile PlatformFileAttachment::TakePlatformFile() { - ignore_result(owning_.release()); - return file_; -} - -base::PlatformFile GetPlatformFile( - scoped_refptr attachment) { - DCHECK_EQ(attachment->GetType(), MessageAttachment::Type::PLATFORM_FILE); - return static_cast(attachment.get())->file(); -} - -} // namespace internal -} // namespace IPC diff --git a/ipc/ipc_platform_file_attachment_posix.h b/ipc/ipc_platform_file_attachment_posix.h deleted file mode 100644 index 9b07900..0000000 --- a/ipc/ipc_platform_file_attachment_posix.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 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_IPC_PLATFORM_FILE_ATTACHMENT_H_ -#define IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_ - -#include "ipc/ipc_export.h" -#include "ipc/ipc_message_attachment.h" - -namespace IPC { -namespace internal { - -// A platform file that is sent over |Channel| as a part of |Message|. -// PlatformFileAttachment optionally owns the file and |owning_| is set in that -// case. Also, |file_| is not cleared even after the ownership is taken. -// Some old clients require this strange behavior. -class IPC_EXPORT PlatformFileAttachment : public MessageAttachment { - public: - // Non-owning constructor - explicit PlatformFileAttachment(base::PlatformFile file); - // Owning constructor - explicit PlatformFileAttachment(base::ScopedFD file); - - Type GetType() const override; - base::PlatformFile TakePlatformFile(); - - base::PlatformFile file() const { return file_; } - bool Owns() const { return owning_.is_valid(); } - - private: - ~PlatformFileAttachment() override; - - base::PlatformFile file_; - base::ScopedFD owning_; -}; - -base::PlatformFile GetPlatformFile(scoped_refptr attachment); - -} // namespace internal -} // namespace IPC - -#endif // IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_ diff --git a/ipc/ipc_sync_message.h b/ipc/ipc_sync_message.h deleted file mode 100644 index 7f05551..0000000 --- a/ipc/ipc_sync_message.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2012 The Chromium 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_IPC_SYNC_MESSAGE_H_ -#define IPC_IPC_SYNC_MESSAGE_H_ - -#include - -#if defined(OS_WIN) -#include -#endif - -#include -#include - -#include "build/build_config.h" -#include "ipc/ipc_message.h" - -namespace base { -class WaitableEvent; -} - -namespace IPC { - -class MessageReplyDeserializer; - -class IPC_EXPORT SyncMessage : public Message { - public: - SyncMessage(int32_t routing_id, - uint32_t type, - PriorityValue priority, - MessageReplyDeserializer* deserializer); - ~SyncMessage() override; - - // Call this to get a deserializer for the output parameters. - // Note that this can only be called once, and the caller is responsible - // for deleting the deserializer when they're done. - MessageReplyDeserializer* GetReplyDeserializer(); - - // If this message can cause the receiver to block while waiting for user - // input (i.e. by calling MessageBox), then the caller needs to pump window - // messages and dispatch asynchronous messages while waiting for the reply. - // This call enables message pumping behavior while waiting for a reply to - // this message. - void EnableMessagePumping() { - header()->flags |= PUMPING_MSGS_BIT; - } - - // Indicates whether window messages should be pumped while waiting for a - // reply to this message. - bool ShouldPumpMessages() const { - return (header()->flags & PUMPING_MSGS_BIT) != 0; - } - - // Returns true if the message is a reply to the given request id. - static bool IsMessageReplyTo(const Message& msg, int request_id); - - // Given a reply message, returns an iterator to the beginning of the data - // (i.e. skips over the synchronous specific data). - static base::PickleIterator GetDataIterator(const Message* msg); - - // Given a synchronous message (or its reply), returns its id. - static int GetMessageId(const Message& msg); - - // Generates a reply message to the given message. - static Message* GenerateReply(const Message* msg); - - private: - struct SyncHeader { - // unique ID (unique per sender) - int message_id; - }; - - static bool ReadSyncHeader(const Message& msg, SyncHeader* header); - static bool WriteSyncHeader(Message* msg, const SyncHeader& header); - - std::unique_ptr deserializer_; -}; - -// Used to deserialize parameters from a reply to a synchronous message -class IPC_EXPORT MessageReplyDeserializer { - public: - virtual ~MessageReplyDeserializer() {} - bool SerializeOutputParameters(const Message& msg); - private: - // Derived classes need to implement this, using the given iterator (which - // is skipped past the header for synchronous messages). - virtual bool SerializeOutputParameters(const Message& msg, - base::PickleIterator iter) = 0; -}; - -// When sending a synchronous message, this structure contains an object -// that knows how to deserialize the response. -struct PendingSyncMsg { - PendingSyncMsg(int id, MessageReplyDeserializer* d, base::WaitableEvent* e) - : id(id), deserializer(d), done_event(e), send_result(false) {} - - int id; - MessageReplyDeserializer* deserializer; - base::WaitableEvent* done_event; - bool send_result; -}; - -} // namespace IPC - -#endif // IPC_IPC_SYNC_MESSAGE_H_ diff --git a/libmojo.pc.in b/libmojo.pc.in deleted file mode 100644 index a750bdd..0000000 --- a/libmojo.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -bslot=@BSLOT@ -prefix=/usr -exec_prefix=${prefix} -libdir=${exec_prefix}/@LIB@ -includedir=${prefix}/include - -Name: libmojo -Description: Chrome Mojo IPC library -Requires.private: -Version: ${bslot} -Libs: -lmojo-${bslot}.pic -Libs.private: -Cflags: -I${includedir}/libmojo-${bslot} -Wno-cast-qual -Wno-cast-align diff --git a/mojo/BUILD.gn b/mojo/BUILD.gn deleted file mode 100644 index 070e2d1..0000000 --- a/mojo/BUILD.gn +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/ui.gni") - -group("mojo") { - # Meta-target, don't link into production code. - testonly = true - deps = [ - ":tests", - "//mojo/common", - ] - - if (!(is_linux && current_cpu == "x86")) { - deps += [ "//mojo/public" ] - } - - if (is_android) { - deps += [ "//mojo/android" ] - } - - deps += [ "//services/service_manager:all" ] -} - -group("tests") { - testonly = true - deps = [ - "//ipc:ipc_tests", - "//mojo/common:mojo_common_unittests", - "//mojo/edk/js/tests", - "//mojo/edk/system:mojo_message_pipe_perftests", - "//mojo/edk/system:mojo_system_unittests", - "//mojo/edk/test:mojo_public_bindings_perftests", - "//mojo/edk/test:mojo_public_bindings_unittests", - "//mojo/edk/test:mojo_public_system_perftests", - "//mojo/edk/test:mojo_public_system_unittests", - "//services/service_manager/public/cpp/tests:mojo_public_application_unittests", - "//services/service_manager/tests", - ] -} diff --git a/mojo/DEPS b/mojo/DEPS deleted file mode 100644 index 49d7fd3..0000000 --- a/mojo/DEPS +++ /dev/null @@ -1,7 +0,0 @@ -include_rules = [ - "+base", - "+build", - "+testing", - - "+services/service_manager", -] diff --git a/mojo/PRESUBMIT.py b/mojo/PRESUBMIT.py deleted file mode 100644 index 2766055..0000000 --- a/mojo/PRESUBMIT.py +++ /dev/null @@ -1,44 +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. - -"""Presubmit script for mojo - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts -for more details about the presubmit API built into depot_tools. -""" - -import os.path - -def CheckChangeOnUpload(input_api, output_api): - # Additional python module paths (we're in src/mojo/); not everyone needs - # them, but it's easiest to add them to everyone's path. - # For ply and jinja2: - third_party_path = os.path.join( - input_api.PresubmitLocalPath(), "..", "third_party") - # For the bindings generator: - mojo_public_bindings_pylib_path = os.path.join( - input_api.PresubmitLocalPath(), "public", "tools", "bindings", "pylib") - # For the python bindings: - mojo_python_bindings_path = os.path.join( - input_api.PresubmitLocalPath(), "public", "python") - # TODO(vtl): Don't lint these files until the (many) problems are fixed - # (possibly by deleting/rewriting some files). - temporary_black_list = input_api.DEFAULT_BLACK_LIST + \ - (r".*\bpublic[\\\/]tools[\\\/]bindings[\\\/]pylib[\\\/]mojom[\\\/]" - r"generate[\\\/].+\.py$", - r".*\bpublic[\\\/]tools[\\\/]bindings[\\\/]generators[\\\/].+\.py$", - r".*\bspy[\\\/]ui[\\\/].+\.py$", - r".*\btools[\\\/]pylib[\\\/]transitive_hash\.py$", - r".*\btools[\\\/]test_runner\.py$") - - results = [] - pylint_extra_paths = [ - third_party_path, - mojo_public_bindings_pylib_path, - mojo_python_bindings_path, - ] - results += input_api.canned_checks.RunPylint( - input_api, output_api, extra_paths_list=pylint_extra_paths, - black_list=temporary_black_list) - return results diff --git a/mojo/README.md b/mojo/README.md deleted file mode 100644 index e1e7583..0000000 --- a/mojo/README.md +++ /dev/null @@ -1,142 +0,0 @@ -# ![Mojo Graphic](https://goo.gl/6CdlbH) Mojo -This document is a subset of the [Mojo documentation](/mojo). - -[TOC] - -## Getting Started With Mojo - -To get started using Mojo in applications which already support it (such as -Chrome), the fastest path forward will be to look at the bindings documentation -for your language of choice ([**C++**](#C_Bindings), -[**JavaScript**](#JavaScript-Bindings), or [**Java**](#Java-Bindings)) as well -as the documentation for the -[**Mojom IDL and bindings generator**](/mojo/public/tools/bindings). - -If you're looking for information on creating and/or connecting to services, see -the top-level [Services documentation](/services). - -For specific details regarding the conversion of old things to new things, check -out [Converting Legacy Chrome IPC To Mojo](/ipc). - -## System Overview - -Mojo is a layered collection of runtime libraries providing a platform-agnostic -abstraction of common IPC primitives, a message IDL format, and a bindings -library with code generation for multiple target languages to facilitate -convenient message passing across arbitrary inter- and intra-process boundaries. - -The documentation here is segmented according to the different isolated layers -and libraries comprising the system. The basic hierarchy of features is as -follows: - -![Mojo Library Layering: EDK on bottom, different language bindings on top, public system support APIs in the middle](https://docs.google.com/drawings/d/1aNbLfF-fejgzxCxH_b8xAaCVvftW8BGTH_EHD7nvU1w/pub?w=570&h=327) - -## Embedder Development Kit (EDK) -Every process to be interconnected via Mojo IPC is called a **Mojo embedder** -and needs to embed the -[**Embedder Development Kit (EDK)**](/mojo/edk/embedder) library. The EDK -exposes the means for an embedder to physically connect one process to another -using any supported native IPC primitive (*e.g.,* a UNIX domain socket or -Windows named pipe) on the host platform. - -Details regarding where and how an application process actually embeds and -configures the EDK are generaly hidden from the rest of the application code, -and applications instead use the public System and Bindings APIs to get things -done within processes that embed Mojo. - -## C System API -Once the EDK is initialized within a process, the public -[**C System API**](/mojo/public/c/system) is usable on any thread for the -remainder of the process's lifetime. This is a lightweight API with a relatively -small (and eventually stable) ABI. Typically this API is not used directly, but -it is the foundation upon which all remaining upper layers are built. It exposes -the fundamental capabilities to create and interact with various types of Mojo -handles including **message pipes**, **data pipes**, and **shared buffers**. - -## High-Level System APIs - -There is a relatively small, higher-level system API for each supported -language, built upon the low-level C API. Like the C API, direct usage of these -system APIs is rare compared to the bindings APIs, but it is sometimes desirable -or necessary. - -### C++ -The [**C++ System API**](/mojo/public/cpp/system) provides a layer of -C++ helper classes and functions to make safe System API usage easier: -strongly-typed handle scopers, synchronous waiting operations, system handle -wrapping and unwrapping helpers, common handle operations, and utilities for -more easily watching handle state changes. - -### JavaScript -The [**JavaScript APIs**](/mojo/public/js) are WIP. :) - -### Java -The [**Java System API**](/mojo/public/java/system) provides helper classes for -working with Mojo primitives, covering all basic functionality of the low-level -C API. - -## High-Level Bindings APIs -Typically developers do not use raw message pipe I/O directly, but instead -define some set of interfaces which are used to generate code that message pipe -usage feel like a more idiomatic method-calling interface in the target -language of choice. This is the bindings layer. - -### Mojom IDL and Bindings Generator -Interfaces are defined using the [**Mojom IDL**](/mojo/public/tools/bindings), -which can be fed to the [**bindings generator**](/mojo/public/tools/bindings) to -generate code in various supported languages. Generated code manages -serialization and deserialization of messages between interface clients and -implementations, simplifying the code -- and ultimately hiding the message pipe --- on either side of an interface connection. - -### C++ Bindings -By far the most commonly used API defined by Mojo, the -[**C++ Bindings API**](/mojo/public/cpp/bindings) exposes a robust set of -features for interacting with message pipes via generated C++ bindings code, -including support for sets of related bindings endpoints, associated interfaces, -nested sync IPC, versioning, bad-message reporting, arbitrary message filter -injection, and convenient test facilities. - -### JavaScript Bindings -The [**JavaScript APIs**](/mojo/public/js) are WIP. :) - -### Java Bindings -The [**Java Bindings API**](/mojo/public/java/bindings) provides helper classes -for working with Java code emitted by the bindings generator. - -## FAQ - -### Why not protobuf? Why a new thing? -There are number of potentially decent answers to this question, but the -deal-breaker is that a useful IPC mechanism must support transfer of native -object handles (*e.g.* file descriptors) across process boundaries. Other -non-new IPC things that do support this capability (*e.g.* D-Bus) have their own -substantial deficiencies. - -### Are message pipes expensive? -No. As an implementation detail, creating a message pipe is essentially -generating two random numbers and stuffing them into a hash table, along with a -few tiny heap allocations. - -### So really, can I create like, thousands of them? -Yes! Nobody will mind. Create millions if you like. (OK but maybe don't.) - -### Can I use in-process message pipes? -Yes, and message pipe usage is identical regardless of whether the pipe actually -crosses a process boundary -- in fact this detail is intentionally obscured. - -Message pipes which don't cross a process boundary are efficient: sent messages -are never copied, and a write on one end will synchronously modify the message -queue on the other end. When working with generated C++ bindings, for example, -the net result is that an `InterfacePtr` on one thread sending a message to a -`Binding` on another thread (or even the same thread) is effectively a -`PostTask` to the `Binding`'s `TaskRunner` with the added -- but often small -- -costs of serialization, deserialization, validation, and some internal routing -logic. - -### What about ____? - -Please post questions to -[`chromium-mojo@chromium.org`](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)! -The list is quite responsive. - diff --git a/mojo/android/BUILD.gn b/mojo/android/BUILD.gn deleted file mode 100644 index 1a8cdbd..0000000 --- a/mojo/android/BUILD.gn +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/rules.gni") - -group("android") { - testonly = true - deps = [ - ":mojo_javatests", - ":mojo_test_apk", - ":system_java", - ] -} - -generate_jni("jni_headers") { - sources = [ - "javatests/src/org/chromium/mojo/MojoTestCase.java", - "javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java", - ] - public_deps = [ - ":system_java_jni_headers", - ] - - jni_package = "mojo" -} - -generate_jni("system_java_jni_headers") { - sources = [ - "system/src/org/chromium/mojo/system/impl/BaseRunLoop.java", - "system/src/org/chromium/mojo/system/impl/CoreImpl.java", - "system/src/org/chromium/mojo/system/impl/WatcherImpl.java", - ] - - jni_package = "mojo" -} - -source_set("libsystem_java") { - sources = [ - "system/base_run_loop.cc", - "system/base_run_loop.h", - "system/core_impl.cc", - "system/core_impl.h", - "system/watcher_impl.cc", - "system/watcher_impl.h", - ] - - deps = [ - ":system_java_jni_headers", - "//base", - "//mojo/public/c/system", - "//mojo/public/cpp/system", - ] -} - -android_library("system_java") { - java_files = [ - "system/src/org/chromium/mojo/system/impl/BaseRunLoop.java", - "system/src/org/chromium/mojo/system/impl/CoreImpl.java", - "system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java", - "system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java", - "system/src/org/chromium/mojo/system/impl/HandleBase.java", - "system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java", - "system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java", - "system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java", - "system/src/org/chromium/mojo/system/impl/WatcherImpl.java", - ] - - deps = [ - "//base:base_java", - "//mojo/public/java:system_java", - ] -} - -android_library("mojo_javatests") { - testonly = true - java_files = [ - "javatests/src/org/chromium/mojo/HandleMock.java", - "javatests/src/org/chromium/mojo/MojoTestCase.java", - "javatests/src/org/chromium/mojo/TestUtils.java", - "javatests/src/org/chromium/mojo/bindings/BindingsHelperTest.java", - "javatests/src/org/chromium/mojo/bindings/BindingsTest.java", - "javatests/src/org/chromium/mojo/bindings/BindingsTestUtils.java", - "javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java", - "javatests/src/org/chromium/mojo/bindings/CallbacksTest.java", - "javatests/src/org/chromium/mojo/bindings/ConnectorTest.java", - "javatests/src/org/chromium/mojo/bindings/ExecutorFactoryTest.java", - "javatests/src/org/chromium/mojo/bindings/InterfacesTest.java", - "javatests/src/org/chromium/mojo/bindings/MessageHeaderTest.java", - "javatests/src/org/chromium/mojo/bindings/ReadAndDispatchMessageTest.java", - "javatests/src/org/chromium/mojo/bindings/RouterTest.java", - "javatests/src/org/chromium/mojo/bindings/SerializationTest.java", - "javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterfaceTestHelper.java", - "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/system/impl/CoreImplTest.java", - "javatests/src/org/chromium/mojo/system/impl/WatcherImplTest.java", - ] - - deps = [ - ":system_java", - "//base:base_java", - "//base:base_java_test_support", - "//mojo/public/interfaces/bindings/tests:test_interfaces_java", - "//mojo/public/interfaces/bindings/tests:test_mojom_import2_java", - "//mojo/public/interfaces/bindings/tests:test_mojom_import_java", - "//mojo/public/java:bindings_java", - "//mojo/public/java:system_java", - "//third_party/android_support_test_runner:runner_java", - ] - - data = [ - "//mojo/public/interfaces/bindings/tests/data/validation/", - ] -} - -shared_library("mojo_java_unittests") { - testonly = true - - sources = [ - "javatests/init_library.cc", - "javatests/mojo_test_case.cc", - "javatests/mojo_test_case.h", - "javatests/validation_test_util.cc", - "javatests/validation_test_util.h", - ] - - deps = [ - ":jni_headers", - ":libsystem_java", - ":system_java_jni_headers", - "//base", - "//base/test:test_support", - "//build/config/sanitizers:deps", - "//mojo/edk/system", - "//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils", - "//mojo/public/cpp/test_support:test_utils", - ] - defines = [ "UNIT_TEST" ] -} - -instrumentation_test_apk("mojo_test_apk") { - deps = [ - ":mojo_javatests", - ":system_java", - "//base:base_java", - "//mojo/public/interfaces/bindings/tests:test_interfaces", - "//mojo/public/java:bindings_java", - "//third_party/android_support_test_runner:runner_java", - ] - shared_libraries = [ ":mojo_java_unittests" ] - apk_name = "MojoTest" - android_manifest = "javatests/AndroidManifest.xml" -} diff --git a/mojo/android/DEPS b/mojo/android/DEPS deleted file mode 100644 index c80012b..0000000 --- a/mojo/android/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+jni", -] diff --git a/mojo/android/javatests/AndroidManifest.xml b/mojo/android/javatests/AndroidManifest.xml deleted file mode 100644 index 32a3927..0000000 --- a/mojo/android/javatests/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/mojo/android/javatests/DEPS b/mojo/android/javatests/DEPS deleted file mode 100644 index 78cf465..0000000 --- a/mojo/android/javatests/DEPS +++ /dev/null @@ -1,4 +0,0 @@ -include_rules = [ - # out should be allowed by default, but bots are failing on this. - "+out", -] diff --git a/mojo/android/javatests/apk/.empty b/mojo/android/javatests/apk/.empty deleted file mode 100644 index e69de29..0000000 diff --git a/mojo/android/javatests/init_library.cc b/mojo/android/javatests/init_library.cc deleted file mode 100644 index 9e1a593..0000000 --- a/mojo/android/javatests/init_library.cc +++ /dev/null @@ -1,50 +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 "base/android/base_jni_onload.h" -#include "base/android/base_jni_registrar.h" -#include "base/android/jni_android.h" -#include "base/android/jni_registrar.h" -#include "base/android/library_loader/library_loader_hooks.h" -#include "base/bind.h" -#include "mojo/android/javatests/mojo_test_case.h" -#include "mojo/android/javatests/validation_test_util.h" -#include "mojo/android/system/core_impl.h" -#include "mojo/android/system/watcher_impl.h" -#include "mojo/edk/embedder/embedder.h" - -namespace { - -base::android::RegistrationMethod kMojoRegisteredMethods[] = { - {"CoreImpl", mojo::android::RegisterCoreImpl}, - {"MojoTestCase", mojo::android::RegisterMojoTestCase}, - {"ValidationTestUtil", mojo::android::RegisterValidationTestUtil}, - {"WatcherImpl", mojo::android::RegisterWatcherImpl}, -}; - -bool RegisterJNI(JNIEnv* env) { - return base::android::RegisterJni(env) && - RegisterNativeMethods(env, kMojoRegisteredMethods, - arraysize(kMojoRegisteredMethods)); -} - -bool NativeInit() { - if (!base::android::OnJNIOnLoadInit()) - return false; - - mojo::edk::Init(); - return true; -} - -} // namespace - -JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { - base::android::InitVM(vm); - JNIEnv* env = base::android::AttachCurrentThread(); - if (!base::android::OnJNIOnLoadRegisterJNI(env) || !RegisterJNI(env) || - !NativeInit()) { - return -1; - } - return JNI_VERSION_1_4; -} diff --git a/mojo/android/javatests/mojo_test_case.cc b/mojo/android/javatests/mojo_test_case.cc deleted file mode 100644 index fc59009..0000000 --- a/mojo/android/javatests/mojo_test_case.cc +++ /dev/null @@ -1,70 +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/android/javatests/mojo_test_case.h" - -#include "base/android/jni_android.h" -#include "base/android/scoped_java_ref.h" -#include "base/at_exit.h" -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/test/test_support_android.h" -#include "base/threading/thread_task_runner_handle.h" -#include "jni/MojoTestCase_jni.h" - -using base::android::JavaParamRef; - -namespace { - -struct TestEnvironment { - TestEnvironment() {} - - base::ShadowingAtExitManager at_exit; - base::MessageLoop message_loop; -}; - -} // namespace - -namespace mojo { -namespace android { - -static void Init(JNIEnv* env, const JavaParamRef& jcaller) { - base::InitAndroidTestMessageLoop(); -} - -static jlong SetupTestEnvironment(JNIEnv* env, - const JavaParamRef& jcaller) { - return reinterpret_cast(new TestEnvironment()); -} - -static void TearDownTestEnvironment(JNIEnv* env, - const JavaParamRef& jcaller, - jlong test_environment) { - delete reinterpret_cast(test_environment); -} - -static void RunLoop(JNIEnv* env, - const JavaParamRef& jcaller, - jlong timeout_ms) { - base::RunLoop run_loop; - if (timeout_ms) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), - base::TimeDelta::FromMilliseconds(timeout_ms)); - run_loop.Run(); - } else { - run_loop.RunUntilIdle(); - } -} - -bool RegisterMojoTestCase(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace android -} // namespace mojo diff --git a/mojo/android/javatests/mojo_test_case.h b/mojo/android/javatests/mojo_test_case.h deleted file mode 100644 index 2ce3428..0000000 --- a/mojo/android/javatests/mojo_test_case.h +++ /dev/null @@ -1,20 +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_ANDROID_JAVATESTS_CORE_TEST_H_ -#define MOJO_ANDROID_JAVATESTS_CORE_TEST_H_ - -#include - -#include "base/android/jni_android.h" - -namespace mojo { -namespace android { - -JNI_EXPORT bool RegisterMojoTestCase(JNIEnv* env); - -} // namespace android -} // namespace mojo - -#endif // MOJO_SYSTEM_ANDROID_JAVATESTS_CORE_TEST_H_ diff --git a/mojo/android/javatests/src/org/chromium/mojo/HandleMock.java b/mojo/android/javatests/src/org/chromium/mojo/HandleMock.java deleted file mode 100644 index 1f8de94..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/HandleMock.java +++ /dev/null @@ -1,226 +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; - -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.Core.HandleSignalsState; -import org.chromium.mojo.system.DataPipe; -import org.chromium.mojo.system.DataPipe.ConsumerHandle; -import org.chromium.mojo.system.DataPipe.ProducerHandle; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojo.system.MojoResult; -import org.chromium.mojo.system.ResultAnd; -import org.chromium.mojo.system.SharedBufferHandle; -import org.chromium.mojo.system.UntypedHandle; -import org.chromium.mojo.system.impl.CoreImpl; - -import java.nio.ByteBuffer; -import java.util.List; - -/** - * A mock handle, that does nothing. - */ -public class HandleMock implements UntypedHandle, MessagePipeHandle, - ProducerHandle, ConsumerHandle, SharedBufferHandle { - - /** - * @see Handle#close() - */ - @Override - public void close() { - // Do nothing. - } - - /** - * @see Handle#querySignalsState() - */ - @Override - public HandleSignalsState querySignalsState() { - return null; - } - - /** - * @see Handle#isValid() - */ - @Override - public boolean isValid() { - return true; - } - - /** - * @see Handle#toUntypedHandle() - */ - @Override - public UntypedHandle toUntypedHandle() { - return this; - } - - /** - * @see org.chromium.mojo.system.Handle#getCore() - */ - @Override - public Core getCore() { - return CoreImpl.getInstance(); - } - - /** - * @see org.chromium.mojo.system.UntypedHandle#pass() - */ - @Override - public HandleMock pass() { - return this; - } - - /** - * @see Handle#releaseNativeHandle() - */ - @Override - public int releaseNativeHandle() { - return 0; - } - - /** - * @see ConsumerHandle#discardData(int, DataPipe.ReadFlags) - */ - @Override - public int discardData(int numBytes, DataPipe.ReadFlags flags) { - // Do nothing. - return 0; - } - - /** - * @see ConsumerHandle#readData(java.nio.ByteBuffer, DataPipe.ReadFlags) - */ - @Override - public ResultAnd readData(ByteBuffer elements, DataPipe.ReadFlags flags) { - // Do nothing. - return new ResultAnd(MojoResult.OK, 0); - } - - /** - * @see ConsumerHandle#beginReadData(int, DataPipe.ReadFlags) - */ - @Override - public ByteBuffer beginReadData(int numBytes, - DataPipe.ReadFlags flags) { - // Do nothing. - return null; - } - - /** - * @see ConsumerHandle#endReadData(int) - */ - @Override - public void endReadData(int numBytesRead) { - // Do nothing. - } - - /** - * @see ProducerHandle#writeData(java.nio.ByteBuffer, DataPipe.WriteFlags) - */ - @Override - public ResultAnd writeData(ByteBuffer elements, DataPipe.WriteFlags flags) { - // Do nothing. - return new ResultAnd(MojoResult.OK, 0); - } - - /** - * @see ProducerHandle#beginWriteData(int, DataPipe.WriteFlags) - */ - @Override - public ByteBuffer beginWriteData(int numBytes, - DataPipe.WriteFlags flags) { - // Do nothing. - return null; - } - - /** - * @see ProducerHandle#endWriteData(int) - */ - @Override - public void endWriteData(int numBytesWritten) { - // Do nothing. - } - - /** - * @see MessagePipeHandle#writeMessage(java.nio.ByteBuffer, java.util.List, - * MessagePipeHandle.WriteFlags) - */ - @Override - public void writeMessage(ByteBuffer bytes, List handles, - WriteFlags flags) { - // Do nothing. - } - - /** - * @see MessagePipeHandle#readMessage(java.nio.ByteBuffer, int, MessagePipeHandle.ReadFlags) - */ - @Override - public ResultAnd readMessage( - ByteBuffer bytes, int maxNumberOfHandles, ReadFlags flags) { - // Do nothing. - return new ResultAnd(MojoResult.OK, new ReadMessageResult()); - } - - /** - * @see UntypedHandle#toMessagePipeHandle() - */ - @Override - public MessagePipeHandle toMessagePipeHandle() { - return this; - } - - /** - * @see UntypedHandle#toDataPipeConsumerHandle() - */ - @Override - public ConsumerHandle toDataPipeConsumerHandle() { - return this; - } - - /** - * @see UntypedHandle#toDataPipeProducerHandle() - */ - @Override - public ProducerHandle toDataPipeProducerHandle() { - return this; - } - - /** - * @see UntypedHandle#toSharedBufferHandle() - */ - @Override - public SharedBufferHandle toSharedBufferHandle() { - return this; - } - - /** - * @see SharedBufferHandle#duplicate(SharedBufferHandle.DuplicateOptions) - */ - @Override - public SharedBufferHandle duplicate(DuplicateOptions options) { - // Do nothing. - return null; - } - - /** - * @see SharedBufferHandle#map(long, long, SharedBufferHandle.MapFlags) - */ - @Override - public ByteBuffer map(long offset, long numBytes, MapFlags flags) { - // Do nothing. - return null; - } - - /** - * @see SharedBufferHandle#unmap(java.nio.ByteBuffer) - */ - @Override - public void unmap(ByteBuffer buffer) { - // Do nothing. - } - -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java b/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java deleted file mode 100644 index f4d7ab7..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.mojo; - -import android.test.InstrumentationTestCase; - -import org.chromium.base.ContextUtils; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.base.library_loader.LibraryLoader; -import org.chromium.base.library_loader.LibraryProcessType; - -/** - * Base class to test mojo. Setup the environment. - */ -@JNINamespace("mojo::android") -public class MojoTestCase extends InstrumentationTestCase { - - private long mTestEnvironmentPointer; - - /** - * @see junit.framework.TestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - ContextUtils.initApplicationContext( - getInstrumentation().getTargetContext().getApplicationContext()); - LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized(); - nativeInit(); - mTestEnvironmentPointer = nativeSetupTestEnvironment(); - } - - /** - * @see android.test.InstrumentationTestCase#tearDown() - */ - @Override - protected void tearDown() throws Exception { - nativeTearDownTestEnvironment(mTestEnvironmentPointer); - super.tearDown(); - } - - /** - * Runs the run loop for the given time. - */ - protected void runLoop(long timeoutMS) { - nativeRunLoop(timeoutMS); - } - - /** - * Runs the run loop until no handle or task are immediately available. - */ - protected void runLoopUntilIdle() { - nativeRunLoop(0); - } - - private native void nativeInit(); - - private native long nativeSetupTestEnvironment(); - - private native void nativeTearDownTestEnvironment(long testEnvironment); - - private native void nativeRunLoop(long timeoutMS); - -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/TestUtils.java b/mojo/android/javatests/src/org/chromium/mojo/TestUtils.java deleted file mode 100644 index d10d0d7..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/TestUtils.java +++ /dev/null @@ -1,32 +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; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Random; - -/** - * Utilities methods for tests. - */ -public final class TestUtils { - - private static final Random RANDOM = new Random(); - - /** - * Returns a new direct ByteBuffer of the given size with random (but reproducible) data. - */ - public static ByteBuffer newRandomBuffer(int size) { - byte bytes[] = new byte[size]; - RANDOM.setSeed(size); - RANDOM.nextBytes(bytes); - ByteBuffer data = ByteBuffer.allocateDirect(size); - data.order(ByteOrder.LITTLE_ENDIAN); - data.put(bytes); - data.flip(); - return data; - } - -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsHelperTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsHelperTest.java deleted file mode 100644 index 38bd348..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsHelperTest.java +++ /dev/null @@ -1,55 +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 android.support.test.filters.SmallTest; - -import junit.framework.TestCase; - -import java.nio.charset.Charset; - -/** - * Testing {@link BindingsHelper}. - */ -public class BindingsHelperTest extends TestCase { - - /** - * Testing {@link BindingsHelper#utf8StringSizeInBytes(String)}. - */ - @SmallTest - public void testUTF8StringLength() { - String[] stringsToTest = { - "", - "a", - "hello world", - "éléphant", - "𠜎𠜱𠝹𠱓𠱸𠲖𠳏𠳕", - "你午饭想吃什么", - "你午饭想吃什么\0éléphant", - }; - for (String s : stringsToTest) { - assertEquals(s.getBytes(Charset.forName("utf8")).length, - BindingsHelper.utf8StringSizeInBytes(s)); - } - assertEquals(1, BindingsHelper.utf8StringSizeInBytes("\0")); - String s = new StringBuilder().appendCodePoint(0x0).appendCodePoint(0x80) - .appendCodePoint(0x800).appendCodePoint(0x10000).toString(); - assertEquals(10, BindingsHelper.utf8StringSizeInBytes(s)); - assertEquals(10, s.getBytes(Charset.forName("utf8")).length); - } - - /** - * Testing {@link BindingsHelper#align(int)}. - */ - @SmallTest - public void testAlign() { - for (int i = 0; i < 3 * BindingsHelper.ALIGNMENT; ++i) { - int j = BindingsHelper.align(i); - assertTrue(j >= i); - assertTrue(j % BindingsHelper.ALIGNMENT == 0); - assertTrue(j - i < BindingsHelper.ALIGNMENT); - } - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsTest.java deleted file mode 100644 index d280c77..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsTest.java +++ /dev/null @@ -1,241 +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 android.support.test.filters.SmallTest; - -import junit.framework.TestCase; - -import org.chromium.mojo.HandleMock; -import org.chromium.mojo.bindings.test.mojom.imported.Color; -import org.chromium.mojo.bindings.test.mojom.imported.Point; -import org.chromium.mojo.bindings.test.mojom.imported.Shape; -import org.chromium.mojo.bindings.test.mojom.imported.Thing; -import org.chromium.mojo.bindings.test.mojom.sample.Bar; -import org.chromium.mojo.bindings.test.mojom.sample.Bar.Type; -import org.chromium.mojo.bindings.test.mojom.sample.DefaultsTest; -import org.chromium.mojo.bindings.test.mojom.sample.Enum; -import org.chromium.mojo.bindings.test.mojom.sample.Foo; -import org.chromium.mojo.bindings.test.mojom.sample.InterfaceConstants; -import org.chromium.mojo.bindings.test.mojom.sample.SampleServiceConstants; -import org.chromium.mojo.bindings.test.mojom.test_structs.EmptyStruct; -import org.chromium.mojo.bindings.test.mojom.test_structs.Rect; -import org.chromium.mojo.system.DataPipe.ConsumerHandle; -import org.chromium.mojo.system.DataPipe.ProducerHandle; -import org.chromium.mojo.system.MessagePipeHandle; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.Map; - -/** - * Testing generated classes and associated features. - */ -public class BindingsTest extends TestCase { - - /** - * Create a new typical Bar instance. - */ - private static Bar newBar() { - Bar bar = new Bar(); - bar.alpha = (byte) 0x01; - bar.beta = (byte) 0x02; - bar.gamma = (byte) 0x03; - bar.type = Type.BOTH; - return bar; - } - - /** - * Create a new typical Foo instance. - */ - private static Foo createFoo() { - Foo foo = new Foo(); - foo.name = "HELLO WORLD"; - foo.arrayOfArrayOfBools = new boolean[][] { - { true, false, true }, { }, { }, { false }, { true } }; - foo.bar = newBar(); - foo.a = true; - foo.c = true; - foo.data = new byte[] { 0x01, 0x02, 0x03 }; - foo.extraBars = new Bar[] { newBar(), newBar() }; - String[][][] strings = new String[3][2][1]; - for (int i0 = 0; i0 < strings.length; ++i0) { - for (int i1 = 0; i1 < strings[i0].length; ++i1) { - for (int i2 = 0; i2 < strings[i0][i1].length; ++i2) { - strings[i0][i1][i2] = "Hello(" + i0 + ", " + i1 + ", " + i2 + ")"; - } - } - } - foo.multiArrayOfStrings = strings; - ConsumerHandle[] inputStreams = new ConsumerHandle[5]; - for (int i = 0; i < inputStreams.length; ++i) { - inputStreams[i] = new HandleMock(); - } - foo.inputStreams = inputStreams; - ProducerHandle[] outputStreams = new ProducerHandle[3]; - for (int i = 0; i < outputStreams.length; ++i) { - outputStreams[i] = new HandleMock(); - } - foo.outputStreams = outputStreams; - foo.source = new HandleMock(); - return foo; - } - - private static Rect createRect(int x, int y, int width, int height) { - Rect rect = new Rect(); - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - return rect; - } - - private static void checkConstantField( - Field field, Class expectedClass, T value) throws IllegalAccessException { - assertEquals(expectedClass, field.getType()); - assertEquals(Modifier.FINAL, field.getModifiers() & Modifier.FINAL); - assertEquals(Modifier.STATIC, field.getModifiers() & Modifier.STATIC); - assertEquals(value, field.get(null)); - } - - private static void checkField(Field field, Class expectedClass, - Object object, T value) throws IllegalArgumentException, IllegalAccessException { - assertEquals(expectedClass, field.getType()); - assertEquals(0, field.getModifiers() & Modifier.FINAL); - assertEquals(0, field.getModifiers() & Modifier.STATIC); - assertEquals(value, field.get(object)); - } - - /** - * Testing constants are correctly generated. - */ - @SmallTest - public void testConstants() throws NoSuchFieldException, SecurityException, - IllegalAccessException { - checkConstantField(SampleServiceConstants.class.getField("TWELVE"), byte.class, (byte) 12); - checkConstantField(InterfaceConstants.class.getField("LONG"), long.class, 4405L); - } - - /** - * Testing enums are correctly generated. - */ - @SmallTest - public void testEnums() throws NoSuchFieldException, SecurityException, - IllegalAccessException { - checkConstantField(Color.class.getField("RED"), int.class, 0); - checkConstantField(Color.class.getField("BLACK"), int.class, 1); - - checkConstantField(Enum.class.getField("VALUE"), int.class, 0); - - checkConstantField(Shape.class.getField("RECTANGLE"), int.class, 1); - checkConstantField(Shape.class.getField("CIRCLE"), int.class, 2); - checkConstantField(Shape.class.getField("TRIANGLE"), int.class, 3); - } - - /** - * Testing default values on structs. - * - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @SmallTest - public void testStructDefaults() throws NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - // Check default values. - DefaultsTest test = new DefaultsTest(); - - checkField(DefaultsTest.class.getField("a0"), byte.class, test, (byte) -12); - checkField(DefaultsTest.class.getField("a1"), byte.class, test, (byte) 12); - checkField(DefaultsTest.class.getField("a2"), short.class, test, (short) 1234); - checkField(DefaultsTest.class.getField("a3"), short.class, test, (short) 34567); - checkField(DefaultsTest.class.getField("a4"), int.class, test, 123456); - checkField(DefaultsTest.class.getField("a5"), int.class, test, (int) 3456789012L); - checkField(DefaultsTest.class.getField("a6"), long.class, test, -111111111111L); - // -8446744073709551617 == 9999999999999999999 - 2 ^ 64. - checkField(DefaultsTest.class.getField("a7"), long.class, test, -8446744073709551617L); - checkField(DefaultsTest.class.getField("a8"), int.class, test, 0x12345); - checkField(DefaultsTest.class.getField("a9"), int.class, test, -0x12345); - checkField(DefaultsTest.class.getField("a10"), int.class, test, 1234); - checkField(DefaultsTest.class.getField("a11"), boolean.class, test, true); - checkField(DefaultsTest.class.getField("a12"), boolean.class, test, false); - checkField(DefaultsTest.class.getField("a13"), float.class, test, (float) 123.25); - checkField(DefaultsTest.class.getField("a14"), double.class, test, 1234567890.123); - checkField(DefaultsTest.class.getField("a15"), double.class, test, 1E10); - checkField(DefaultsTest.class.getField("a16"), double.class, test, -1.2E+20); - checkField(DefaultsTest.class.getField("a17"), double.class, test, +1.23E-20); - checkField(DefaultsTest.class.getField("a18"), byte[].class, test, null); - checkField(DefaultsTest.class.getField("a19"), String.class, test, null); - checkField(DefaultsTest.class.getField("a20"), int.class, test, Bar.Type.BOTH); - checkField(DefaultsTest.class.getField("a21"), Point.class, test, null); - - assertNotNull(test.a22); - checkField(DefaultsTest.class.getField("a22"), Thing.class, test, test.a22); - checkField(DefaultsTest.class.getField("a23"), long.class, test, -1L); - checkField(DefaultsTest.class.getField("a24"), long.class, test, 0x123456789L); - checkField(DefaultsTest.class.getField("a25"), long.class, test, -0x123456789L); - } - - /** - * Testing generation of the Foo class. - * - * @throws IllegalAccessException - */ - @SmallTest - public void testFooGeneration() throws NoSuchFieldException, SecurityException, - IllegalAccessException { - // Checking Foo constants. - checkConstantField(Foo.class.getField("FOOBY"), String.class, "Fooby"); - - // Checking Foo default values. - Foo foo = new Foo(); - checkField(Foo.class.getField("name"), String.class, foo, Foo.FOOBY); - - assertNotNull(foo.source); - assertFalse(foo.source.isValid()); - checkField(Foo.class.getField("source"), MessagePipeHandle.class, foo, foo.source); - } - - /** - * Testing serialization of the Foo class. - */ - @SmallTest - public void testFooSerialization() { - // Checking serialization and deserialization of a Foo object. - Foo typicalFoo = createFoo(); - Message serializedFoo = typicalFoo.serialize(null); - Foo deserializedFoo = Foo.deserialize(serializedFoo); - assertEquals(typicalFoo, deserializedFoo); - } - - /** - * Testing serialization of the EmptyStruct class. - */ - @SmallTest - public void testEmptyStructSerialization() { - // Checking serialization and deserialization of a EmptyStruct object. - Message serializedStruct = new EmptyStruct().serialize(null); - EmptyStruct emptyStruct = EmptyStruct.deserialize(serializedStruct); - assertNotNull(emptyStruct); - } - - // In testing maps we want to make sure that the key used when inserting an - // item the key used when looking it up again are different objects. Java - // has default implementations of equals and hashCode that use reference - // equality and hashing, respectively, and that's not what we want for our - // mojom values. - @SmallTest - public void testHashMapStructKey() { - Map map = new HashMap<>(); - map.put(createRect(1, 2, 3, 4), 123); - - Rect key = createRect(1, 2, 3, 4); - assertNotNull(map.get(key)); - assertEquals(123, map.get(key).intValue()); - - map.remove(key); - assertTrue(map.isEmpty()); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsTestUtils.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsTestUtils.java deleted file mode 100644 index 5554f80..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsTestUtils.java +++ /dev/null @@ -1,108 +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.TestUtils; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojo.system.MojoException; -import org.chromium.mojo.system.Pair; -import org.chromium.mojo.system.impl.CoreImpl; - -import java.io.Closeable; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -/** - * Utility class for bindings tests. - */ -public class BindingsTestUtils { - - /** - * {@link MessageReceiver} that records any message it receives. - */ - public static class RecordingMessageReceiver extends SideEffectFreeCloseable - implements MessageReceiver { - - public final List messages = new ArrayList(); - - /** - * @see MessageReceiver#accept(Message) - */ - @Override - public boolean accept(Message message) { - messages.add(message); - return true; - } - } - - /** - * {@link MessageReceiverWithResponder} that records any message it receives. - */ - public static class RecordingMessageReceiverWithResponder extends RecordingMessageReceiver - implements MessageReceiverWithResponder { - - public final List> messagesWithReceivers = - new ArrayList>(); - - /** - * @see MessageReceiverWithResponder#acceptWithResponder(Message, MessageReceiver) - */ - @Override - public boolean acceptWithResponder(Message message, MessageReceiver responder) { - messagesWithReceivers.add(Pair.create(message, responder)); - return true; - } - } - - /** - * {@link ConnectionErrorHandler} that records any error it received. - */ - public static class CapturingErrorHandler implements ConnectionErrorHandler { - - private MojoException mLastMojoException = null; - - /** - * @see ConnectionErrorHandler#onConnectionError(MojoException) - */ - @Override - public void onConnectionError(MojoException e) { - mLastMojoException = e; - } - - /** - * Returns the last recorded exception. - */ - public MojoException getLastMojoException() { - return mLastMojoException; - } - - } - - /** - * Creates a new valid {@link Message}. The message will have a valid header. - */ - public static Message newRandomMessage(int size) { - assert size > 16; - ByteBuffer message = TestUtils.newRandomBuffer(size); - int[] headerAsInts = {16, 2, 0, 0}; - for (int i = 0; i < 4; ++i) { - message.putInt(4 * i, headerAsInts[i]); - } - message.position(0); - return new Message(message, new ArrayList()); - } - - public static P newProxyOverPipe( - Interface.Manager manager, I impl, List toClose) { - Pair handles = - CoreImpl.getInstance().createMessagePipe(null); - P proxy = manager.attachProxy(handles.first, 0); - toClose.add(proxy); - manager.bind(impl, handles.second); - return proxy; - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java deleted file mode 100644 index eea92ab..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.mojo.bindings; - -import android.support.test.filters.SmallTest; - -import org.chromium.mojo.MojoTestCase; -import org.chromium.mojo.bindings.test.mojom.test_structs.MultiVersionStruct; -import org.chromium.mojo.bindings.test.mojom.test_structs.MultiVersionStructV0; -import org.chromium.mojo.bindings.test.mojom.test_structs.MultiVersionStructV1; -import org.chromium.mojo.bindings.test.mojom.test_structs.MultiVersionStructV3; -import org.chromium.mojo.bindings.test.mojom.test_structs.MultiVersionStructV5; -import org.chromium.mojo.bindings.test.mojom.test_structs.MultiVersionStructV7; -import org.chromium.mojo.bindings.test.mojom.test_structs.Rect; -import org.chromium.mojo.system.impl.CoreImpl; - -/** - * Testing generated classes with the [MinVersion] annotation. Struct in this test are from: - * mojo/public/interfaces/bindings/tests/rect.mojom and - * mojo/public/interfaces/bindings/tests/test_structs.mojom - */ -public class BindingsVersioningTest extends MojoTestCase { - private static Rect newRect(int factor) { - Rect rect = new Rect(); - rect.x = factor; - rect.y = 2 * factor; - rect.width = 10 * factor; - rect.height = 20 * factor; - return rect; - } - - private static MultiVersionStruct newStruct() { - MultiVersionStruct struct = new MultiVersionStruct(); - struct.fInt32 = 123; - struct.fRect = newRect(5); - struct.fString = "hello"; - struct.fArray = new byte[] {10, 9, 8}; - struct.fBool = true; - struct.fInt16 = 256; - return struct; - } - - /** - * Testing serializing old struct version to newer one. - */ - @SmallTest - public void testOldToNew() { - { - MultiVersionStructV0 v0 = new MultiVersionStructV0(); - v0.fInt32 = 123; - MultiVersionStruct expected = new MultiVersionStruct(); - expected.fInt32 = 123; - - MultiVersionStruct output = MultiVersionStruct.deserialize(v0.serialize(null)); - assertEquals(expected, output); - assertEquals(0, v0.getVersion()); - assertEquals(0, output.getVersion()); - } - - { - MultiVersionStructV1 v1 = new MultiVersionStructV1(); - v1.fInt32 = 123; - v1.fRect = newRect(5); - MultiVersionStruct expected = new MultiVersionStruct(); - expected.fInt32 = 123; - expected.fRect = newRect(5); - - MultiVersionStruct output = MultiVersionStruct.deserialize(v1.serialize(null)); - assertEquals(expected, output); - assertEquals(1, v1.getVersion()); - assertEquals(1, output.getVersion()); - } - - { - MultiVersionStructV3 v3 = new MultiVersionStructV3(); - v3.fInt32 = 123; - v3.fRect = newRect(5); - v3.fString = "hello"; - MultiVersionStruct expected = new MultiVersionStruct(); - expected.fInt32 = 123; - expected.fRect = newRect(5); - expected.fString = "hello"; - - MultiVersionStruct output = MultiVersionStruct.deserialize(v3.serialize(null)); - assertEquals(expected, output); - assertEquals(3, v3.getVersion()); - assertEquals(3, output.getVersion()); - } - - { - MultiVersionStructV5 v5 = new MultiVersionStructV5(); - v5.fInt32 = 123; - v5.fRect = newRect(5); - v5.fString = "hello"; - v5.fArray = new byte[] {10, 9, 8}; - MultiVersionStruct expected = new MultiVersionStruct(); - expected.fInt32 = 123; - expected.fRect = newRect(5); - expected.fString = "hello"; - expected.fArray = new byte[] {10, 9, 8}; - - MultiVersionStruct output = MultiVersionStruct.deserialize(v5.serialize(null)); - assertEquals(expected, output); - assertEquals(5, v5.getVersion()); - assertEquals(5, output.getVersion()); - } - - { - int expectedHandle = 42; - MultiVersionStructV7 v7 = new MultiVersionStructV7(); - v7.fInt32 = 123; - v7.fRect = newRect(5); - v7.fString = "hello"; - v7.fArray = new byte[] {10, 9, 8}; - v7.fMessagePipe = CoreImpl.getInstance() - .acquireNativeHandle(expectedHandle) - .toMessagePipeHandle(); - v7.fBool = true; - MultiVersionStruct expected = new MultiVersionStruct(); - expected.fInt32 = 123; - expected.fRect = newRect(5); - expected.fString = "hello"; - expected.fArray = new byte[] {10, 9, 8}; - expected.fBool = true; - - MultiVersionStruct output = MultiVersionStruct.deserialize(v7.serialize(null)); - - // Handles must be tested separately. - assertEquals(expectedHandle, output.fMessagePipe.releaseNativeHandle()); - output.fMessagePipe = expected.fMessagePipe; - - assertEquals(expected, output); - assertEquals(7, v7.getVersion()); - assertEquals(7, output.getVersion()); - } - } - - /** - * Testing serializing new struct version to older one. - */ - @SmallTest - public void testNewToOld() { - MultiVersionStruct struct = newStruct(); - { - MultiVersionStructV0 expected = new MultiVersionStructV0(); - expected.fInt32 = 123; - - MultiVersionStructV0 output = MultiVersionStructV0.deserialize(struct.serialize(null)); - assertEquals(expected, output); - assertEquals(9, output.getVersion()); - } - - { - MultiVersionStructV1 expected = new MultiVersionStructV1(); - expected.fInt32 = 123; - expected.fRect = newRect(5); - - MultiVersionStructV1 output = MultiVersionStructV1.deserialize(struct.serialize(null)); - assertEquals(expected, output); - assertEquals(9, output.getVersion()); - } - - { - MultiVersionStructV3 expected = new MultiVersionStructV3(); - expected.fInt32 = 123; - expected.fRect = newRect(5); - expected.fString = "hello"; - - MultiVersionStructV3 output = MultiVersionStructV3.deserialize(struct.serialize(null)); - assertEquals(expected, output); - assertEquals(9, output.getVersion()); - } - - { - MultiVersionStructV5 expected = new MultiVersionStructV5(); - expected.fInt32 = 123; - expected.fRect = newRect(5); - expected.fString = "hello"; - expected.fArray = new byte[] {10, 9, 8}; - - MultiVersionStructV5 output = MultiVersionStructV5.deserialize(struct.serialize(null)); - assertEquals(expected, output); - assertEquals(9, output.getVersion()); - } - - { - int expectedHandle = 42; - MultiVersionStructV7 expected = new MultiVersionStructV7(); - expected.fInt32 = 123; - expected.fRect = newRect(5); - expected.fString = "hello"; - expected.fArray = new byte[] {10, 9, 8}; - expected.fBool = true; - - MultiVersionStruct input = struct; - input.fMessagePipe = CoreImpl.getInstance() - .acquireNativeHandle(expectedHandle) - .toMessagePipeHandle(); - - MultiVersionStructV7 output = MultiVersionStructV7.deserialize(input.serialize(null)); - - assertEquals(expectedHandle, output.fMessagePipe.releaseNativeHandle()); - output.fMessagePipe = expected.fMessagePipe; - - assertEquals(expected, output); - assertEquals(9, output.getVersion()); - } - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/CallbacksTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/CallbacksTest.java deleted file mode 100644 index 497be65..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/CallbacksTest.java +++ /dev/null @@ -1,59 +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 android.support.test.filters.SmallTest; - -import junit.framework.TestCase; - -import org.chromium.mojo.bindings.Callbacks.Callback1; -import org.chromium.mojo.bindings.Callbacks.Callback7; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Testing generated callbacks - */ -public class CallbacksTest extends TestCase { - - /** - * Testing {@link Callback1}. - */ - @SmallTest - public void testCallback1() { - final List parameters = new ArrayList(); - new Callback1() { - @Override - public void call(Integer i1) { - parameters.add(i1); - } - }.call(1); - assertEquals(Arrays.asList(1), parameters); - } - - /** - * Testing {@link Callback7}. - */ - @SmallTest - public void testCallback7() { - final List parameters = new ArrayList(); - new Callback7() { - @Override - public void call(Integer i1, Integer i2, Integer i3, Integer i4, Integer i5, Integer i6, - Integer i7) { - parameters.add(i1); - parameters.add(i2); - parameters.add(i3); - parameters.add(i4); - parameters.add(i5); - parameters.add(i6); - parameters.add(i7); - } - }.call(1, 2, 3, 4, 5, 6, 7); - assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6, 7), parameters); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/ConnectorTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/ConnectorTest.java deleted file mode 100644 index 15f9f1f..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/ConnectorTest.java +++ /dev/null @@ -1,108 +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 android.support.test.filters.SmallTest; - -import org.chromium.mojo.MojoTestCase; -import org.chromium.mojo.bindings.BindingsTestUtils.CapturingErrorHandler; -import org.chromium.mojo.bindings.BindingsTestUtils.RecordingMessageReceiver; -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojo.system.MojoResult; -import org.chromium.mojo.system.Pair; -import org.chromium.mojo.system.ResultAnd; -import org.chromium.mojo.system.impl.CoreImpl; - -import java.nio.ByteBuffer; -import java.util.ArrayList; - -/** - * Testing the {@link Connector} class. - */ -public class ConnectorTest extends MojoTestCase { - - private static final int DATA_LENGTH = 1024; - - private MessagePipeHandle mHandle; - private Connector mConnector; - private Message mTestMessage; - private RecordingMessageReceiver mReceiver; - private CapturingErrorHandler mErrorHandler; - - /** - * @see MojoTestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe( - new MessagePipeHandle.CreateOptions()); - mHandle = handles.first; - mConnector = new Connector(handles.second); - mReceiver = new RecordingMessageReceiver(); - mConnector.setIncomingMessageReceiver(mReceiver); - mErrorHandler = new CapturingErrorHandler(); - mConnector.setErrorHandler(mErrorHandler); - mConnector.start(); - mTestMessage = BindingsTestUtils.newRandomMessage(DATA_LENGTH); - assertNull(mErrorHandler.getLastMojoException()); - assertEquals(0, mReceiver.messages.size()); - } - - /** - * @see MojoTestCase#tearDown() - */ - @Override - protected void tearDown() throws Exception { - mConnector.close(); - mHandle.close(); - super.tearDown(); - } - - /** - * Test sending a message through a {@link Connector}. - */ - @SmallTest - public void testSendingMessage() { - mConnector.accept(mTestMessage); - assertNull(mErrorHandler.getLastMojoException()); - ByteBuffer received = ByteBuffer.allocateDirect(DATA_LENGTH); - ResultAnd result = - mHandle.readMessage(received, 0, MessagePipeHandle.ReadFlags.NONE); - assertEquals(MojoResult.OK, result.getMojoResult()); - assertEquals(DATA_LENGTH, result.getValue().getMessageSize()); - assertEquals(mTestMessage.getData(), received); - } - - /** - * Test receiving a message through a {@link Connector} - */ - @SmallTest - public void testReceivingMessage() { - mHandle.writeMessage(mTestMessage.getData(), new ArrayList(), - MessagePipeHandle.WriteFlags.NONE); - runLoopUntilIdle(); - assertNull(mErrorHandler.getLastMojoException()); - assertEquals(1, mReceiver.messages.size()); - Message received = mReceiver.messages.get(0); - assertEquals(0, received.getHandles().size()); - assertEquals(mTestMessage.getData(), received.getData()); - } - - /** - * Test receiving an error through a {@link Connector}. - */ - @SmallTest - public void testErrors() { - mHandle.close(); - runLoopUntilIdle(); - assertNotNull(mErrorHandler.getLastMojoException()); - assertEquals(MojoResult.FAILED_PRECONDITION, - mErrorHandler.getLastMojoException().getMojoResult()); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/ExecutorFactoryTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/ExecutorFactoryTest.java deleted file mode 100644 index cabe230..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/ExecutorFactoryTest.java +++ /dev/null @@ -1,104 +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 android.support.test.filters.SmallTest; - -import org.chromium.mojo.MojoTestCase; -import org.chromium.mojo.system.impl.CoreImpl; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Testing the executor factory. - */ -public class ExecutorFactoryTest extends MojoTestCase { - - private static final long RUN_LOOP_TIMEOUT_MS = 50; - private static final int CONCURRENCY_LEVEL = 5; - private static final ExecutorService WORKERS = Executors.newFixedThreadPool(CONCURRENCY_LEVEL); - - private Executor mExecutor; - private List mThreadContainer; - - /** - * @see MojoTestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - mExecutor = ExecutorFactory.getExecutorForCurrentThread(CoreImpl.getInstance()); - mThreadContainer = new ArrayList(); - } - - /** - * Testing the {@link Executor} when called from the executor thread. - */ - @SmallTest - public void testExecutorOnCurrentThread() { - Runnable action = new Runnable() { - @Override - public void run() { - mThreadContainer.add(Thread.currentThread()); - } - }; - mExecutor.execute(action); - mExecutor.execute(action); - assertEquals(0, mThreadContainer.size()); - runLoop(RUN_LOOP_TIMEOUT_MS); - assertEquals(2, mThreadContainer.size()); - for (Thread thread : mThreadContainer) { - assertEquals(Thread.currentThread(), thread); - } - } - - /** - * Testing the {@link Executor} when called from another thread. - */ - @SmallTest - public void testExecutorOnOtherThread() { - final CyclicBarrier barrier = new CyclicBarrier(CONCURRENCY_LEVEL + 1); - for (int i = 0; i < CONCURRENCY_LEVEL; ++i) { - WORKERS.execute(new Runnable() { - @Override - public void run() { - mExecutor.execute(new Runnable() { - - @Override - public void run() { - mThreadContainer.add(Thread.currentThread()); - } - }); - try { - barrier.await(); - } catch (InterruptedException e) { - fail("Unexpected exception: " + e.getMessage()); - } catch (BrokenBarrierException e) { - fail("Unexpected exception: " + e.getMessage()); - } - } - }); - } - try { - barrier.await(); - } catch (InterruptedException e) { - fail("Unexpected exception: " + e.getMessage()); - } catch (BrokenBarrierException e) { - fail("Unexpected exception: " + e.getMessage()); - } - assertEquals(0, mThreadContainer.size()); - runLoop(RUN_LOOP_TIMEOUT_MS); - assertEquals(CONCURRENCY_LEVEL, mThreadContainer.size()); - for (Thread thread : mThreadContainer) { - assertEquals(Thread.currentThread(), thread); - } - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfaceControlMessageTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfaceControlMessageTest.java deleted file mode 100644 index 8cdd4ab..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfaceControlMessageTest.java +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.mojo.bindings; - -import android.support.test.filters.SmallTest; - -import org.chromium.mojo.MojoTestCase; -import org.chromium.mojo.bindings.Callbacks.Callback1; -import org.chromium.mojo.bindings.test.mojom.sample.Enum; -import org.chromium.mojo.bindings.test.mojom.sample.IntegerAccessor; -import org.chromium.mojo.system.MojoException; - -import java.io.Closeable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Tests for interface control messages. - */ -public class InterfaceControlMessageTest extends MojoTestCase { - private final List mCloseablesToClose = new ArrayList(); - - /** - * See mojo/public/interfaces/bindings/tests/sample_interfaces.mojom. - */ - class IntegerAccessorImpl extends SideEffectFreeCloseable implements IntegerAccessor { - private long mValue = 0; - private int mEnum = 0; - private boolean mEncounteredError = false; - - /** - * @see ConnectionErrorHandler#onConnectionError(MojoException) - */ - @Override - public void onConnectionError(MojoException e) { - mEncounteredError = true; - } - - /** - * @see IntegerAccessor#getInteger(IntegerAccessor.GetIntegerResponse) - */ - @Override - public void getInteger(GetIntegerResponse response) { - response.call(mValue, mEnum); - } - - /** - * @see IntegerAccessor#setInteger(long, int) - */ - @Override - public void setInteger(long value, int enumValue) { - mValue = value; - mEnum = enumValue; - } - - public long getValue() { - return mValue; - } - - public boolean encounteredError() { - return mEncounteredError; - } - } - - /** - * @see MojoTestCase#tearDown() - */ - @Override - protected void tearDown() throws Exception { - // Close the elements in the reverse order they were added. This is needed because it is an - // error to close the handle of a proxy without closing the proxy first. - Collections.reverse(mCloseablesToClose); - for (Closeable c : mCloseablesToClose) { - c.close(); - } - super.tearDown(); - } - - @SmallTest - public void testQueryVersion() { - IntegerAccessor.Proxy p = BindingsTestUtils.newProxyOverPipe( - IntegerAccessor.MANAGER, new IntegerAccessorImpl(), mCloseablesToClose); - assertEquals(0, p.getProxyHandler().getVersion()); - p.getProxyHandler().queryVersion(new Callback1() { - @Override - public void call(Integer version) { - assertEquals(3, version.intValue()); - } - }); - runLoopUntilIdle(); - assertEquals(3, p.getProxyHandler().getVersion()); - } - - @SmallTest - public void testRequireVersion() { - IntegerAccessorImpl impl = new IntegerAccessorImpl(); - IntegerAccessor.Proxy p = BindingsTestUtils.newProxyOverPipe( - IntegerAccessor.MANAGER, impl, mCloseablesToClose); - - assertEquals(0, p.getProxyHandler().getVersion()); - - p.getProxyHandler().requireVersion(1); - assertEquals(1, p.getProxyHandler().getVersion()); - p.setInteger(123, Enum.VALUE); - runLoopUntilIdle(); - assertFalse(impl.encounteredError()); - assertEquals(123, impl.getValue()); - - p.getProxyHandler().requireVersion(3); - assertEquals(3, p.getProxyHandler().getVersion()); - p.setInteger(456, Enum.VALUE); - runLoopUntilIdle(); - assertFalse(impl.encounteredError()); - assertEquals(456, impl.getValue()); - - // Require a version that is not supported by the implementation side. - p.getProxyHandler().requireVersion(4); - // getVersion() is updated synchronously. - assertEquals(4, p.getProxyHandler().getVersion()); - p.setInteger(789, Enum.VALUE); - runLoopUntilIdle(); - assertTrue(impl.encounteredError()); - // The call to setInteger() after requireVersion() is ignored. - assertEquals(456, impl.getValue()); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java deleted file mode 100644 index d8bd3e8..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java +++ /dev/null @@ -1,284 +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 android.support.test.filters.SmallTest; - -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.NamedObject; -import org.chromium.mojo.bindings.test.mojom.sample.NamedObject.GetNameResponse; -import org.chromium.mojo.bindings.test.mojom.sample.Request; -import org.chromium.mojo.bindings.test.mojom.sample.Response; -import org.chromium.mojo.system.DataPipe.ConsumerHandle; -import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojo.system.Pair; -import org.chromium.mojo.system.impl.CoreImpl; - -import java.io.Closeable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Tests for interfaces / proxies / stubs generated for sample_factory.mojom. - */ -public class InterfacesTest extends MojoTestCase { - - private static final String OBJECT_NAME = "hello world"; - - private final List mCloseablesToClose = new ArrayList(); - - /** - * Basic implementation of {@link NamedObject}. - */ - public static class MockNamedObjectImpl extends CapturingErrorHandler implements NamedObject { - - private String mName = ""; - - /** - * @see org.chromium.mojo.bindings.Interface#close() - */ - @Override - public void close() { - } - - @Override - public void setName(String name) { - mName = name; - } - - @Override - public void getName(GetNameResponse callback) { - callback.call(mName); - } - - public String getNameSynchronously() { - return mName; - } - } - - /** - * Implementation of {@link GetNameResponse} keeping track of usage. - */ - public static class RecordingGetNameResponse implements GetNameResponse { - private String mName; - private boolean mCalled; - - public RecordingGetNameResponse() { - reset(); - } - - @Override - public void call(String name) { - mName = name; - mCalled = true; - } - - public String getName() { - return mName; - } - - public boolean wasCalled() { - return mCalled; - } - - public void reset() { - mName = null; - mCalled = false; - } - } - - /** - * Basic implementation of {@link Factory}. - */ - public class MockFactoryImpl extends CapturingErrorHandler implements Factory { - - private boolean mClosed = false; - - public boolean isClosed() { - return mClosed; - } - - /** - * @see org.chromium.mojo.bindings.Interface#close() - */ - @Override - public void close() { - mClosed = true; - } - - @Override - public void doStuff(Request request, MessagePipeHandle pipe, DoStuffResponse callback) { - if (pipe != null) { - pipe.close(); - } - Response response = new Response(); - response.x = 42; - callback.call(response, "Hello"); - } - - @Override - public void doStuff2(ConsumerHandle pipe, DoStuff2Response callback) { - callback.call("World"); - } - - @Override - public void createNamedObject(InterfaceRequest obj) { - NamedObject.MANAGER.bind(new MockNamedObjectImpl(), obj); - } - - @Override - public void requestImportedInterface(InterfaceRequest obj, - RequestImportedInterfaceResponse callback) { - throw new UnsupportedOperationException("Not implemented."); - } - - @Override - public void takeImportedInterface(ImportedInterface obj, - TakeImportedInterfaceResponse callback) { - throw new UnsupportedOperationException("Not implemented."); - } - } - - /** - * Implementation of DoStuffResponse that keeps track of if the response is called. - */ - public static class DoStuffResponseImpl implements Factory.DoStuffResponse { - private boolean mResponseCalled = false; - - public boolean wasResponseCalled() { - return mResponseCalled; - } - - @Override - public void call(Response response, String string) { - mResponseCalled = true; - } - } - - /** - * @see MojoTestCase#tearDown() - */ - @Override - protected void tearDown() throws Exception { - // Close the elements in the reverse order they were added. This is needed because it is an - // error to close the handle of a proxy without closing the proxy first. - Collections.reverse(mCloseablesToClose); - for (Closeable c : mCloseablesToClose) { - c.close(); - } - super.tearDown(); - } - - /** - * Check that the given proxy receives the calls. If |impl| is not null, also check that the - * calls are forwared to |impl|. - */ - private void checkProxy(NamedObject.Proxy proxy, MockNamedObjectImpl impl) { - RecordingGetNameResponse callback = new RecordingGetNameResponse(); - CapturingErrorHandler errorHandler = new CapturingErrorHandler(); - proxy.getProxyHandler().setErrorHandler(errorHandler); - - if (impl != null) { - assertNull(impl.getLastMojoException()); - assertEquals("", impl.getNameSynchronously()); - } - - proxy.getName(callback); - runLoopUntilIdle(); - - assertNull(errorHandler.getLastMojoException()); - assertTrue(callback.wasCalled()); - assertEquals("", callback.getName()); - - callback.reset(); - proxy.setName(OBJECT_NAME); - runLoopUntilIdle(); - - assertNull(errorHandler.getLastMojoException()); - if (impl != null) { - assertNull(impl.getLastMojoException()); - assertEquals(OBJECT_NAME, impl.getNameSynchronously()); - } - - proxy.getName(callback); - runLoopUntilIdle(); - - assertNull(errorHandler.getLastMojoException()); - assertTrue(callback.wasCalled()); - assertEquals(OBJECT_NAME, callback.getName()); - } - - @SmallTest - public void testName() { - assertEquals("sample::NamedObject", NamedObject.MANAGER.getName()); - } - - @SmallTest - public void testProxyAndStub() { - MockNamedObjectImpl impl = new MockNamedObjectImpl(); - NamedObject.Proxy proxy = - NamedObject.MANAGER.buildProxy(null, NamedObject.MANAGER.buildStub(null, impl)); - - checkProxy(proxy, impl); - } - - @SmallTest - public void testProxyAndStubOverPipe() { - MockNamedObjectImpl impl = new MockNamedObjectImpl(); - NamedObject.Proxy proxy = - BindingsTestUtils.newProxyOverPipe(NamedObject.MANAGER, impl, mCloseablesToClose); - - checkProxy(proxy, impl); - } - - @SmallTest - public void testFactoryOverPipe() { - Factory.Proxy proxy = BindingsTestUtils.newProxyOverPipe( - Factory.MANAGER, new MockFactoryImpl(), mCloseablesToClose); - Pair> request = - NamedObject.MANAGER.getInterfaceRequest(CoreImpl.getInstance()); - mCloseablesToClose.add(request.first); - proxy.createNamedObject(request.second); - - checkProxy(request.first, null); - } - - @SmallTest - public void testInterfaceClosing() { - MockFactoryImpl impl = new MockFactoryImpl(); - Factory.Proxy proxy = - BindingsTestUtils.newProxyOverPipe(Factory.MANAGER, impl, mCloseablesToClose); - - assertFalse(impl.isClosed()); - - proxy.close(); - runLoopUntilIdle(); - - assertTrue(impl.isClosed()); - } - - @SmallTest - public void testResponse() { - MockFactoryImpl impl = new MockFactoryImpl(); - Factory.Proxy proxy = - BindingsTestUtils.newProxyOverPipe(Factory.MANAGER, impl, mCloseablesToClose); - Request request = new Request(); - request.x = 42; - Pair handles = - CoreImpl.getInstance().createMessagePipe(null); - DoStuffResponseImpl response = new DoStuffResponseImpl(); - proxy.doStuff(request, handles.first, response); - - assertFalse(response.wasResponseCalled()); - - runLoopUntilIdle(); - - assertTrue(response.wasResponseCalled()); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/MessageHeaderTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/MessageHeaderTest.java deleted file mode 100644 index b2e6ac8..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/MessageHeaderTest.java +++ /dev/null @@ -1,69 +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 android.support.test.filters.SmallTest; - -import junit.framework.TestCase; - -import org.chromium.mojo.bindings.test.mojom.imported.Point; - -/** - * Testing internal classes of interfaces. - */ -public class MessageHeaderTest extends TestCase { - - /** - * Testing that headers are identical after being serialized/deserialized. - */ - @SmallTest - public void testSimpleMessageHeader() { - final int xValue = 1; - final int yValue = 2; - final int type = 6; - Point p = new Point(); - p.x = xValue; - p.y = yValue; - ServiceMessage message = p.serializeWithHeader(null, new MessageHeader(type)); - - MessageHeader header = message.getHeader(); - assertTrue(header.validateHeader(type, 0)); - assertEquals(type, header.getType()); - assertEquals(0, header.getFlags()); - - Point p2 = Point.deserialize(message.getPayload()); - assertNotNull(p2); - assertEquals(p.x, p2.x); - assertEquals(p.y, p2.y); - } - - /** - * Testing that headers are identical after being serialized/deserialized. - */ - @SmallTest - public void testMessageWithRequestIdHeader() { - final int xValue = 1; - final int yValue = 2; - final int type = 6; - final long requestId = 0x1deadbeafL; - Point p = new Point(); - p.x = xValue; - p.y = yValue; - ServiceMessage message = p.serializeWithHeader(null, - new MessageHeader(type, MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG, 0)); - message.setRequestId(requestId); - - MessageHeader header = message.getHeader(); - assertTrue(header.validateHeader(type, MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG)); - assertEquals(type, header.getType()); - assertEquals(MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG, header.getFlags()); - assertEquals(requestId, header.getRequestId()); - - Point p2 = Point.deserialize(message.getPayload()); - assertNotNull(p2); - assertEquals(p.x, p2.x); - assertEquals(p.y, p2.y); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/ReadAndDispatchMessageTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/ReadAndDispatchMessageTest.java deleted file mode 100644 index 51dbd22..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/ReadAndDispatchMessageTest.java +++ /dev/null @@ -1,109 +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 android.support.test.filters.SmallTest; - -import org.chromium.mojo.MojoTestCase; -import org.chromium.mojo.bindings.BindingsTestUtils.RecordingMessageReceiver; -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.DataPipe; -import org.chromium.mojo.system.Handle; -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.impl.CoreImpl; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Testing {@link Connector#readAndDispatchMessage}. - */ -public class ReadAndDispatchMessageTest extends MojoTestCase { - - private static final int DATA_SIZE = 1024; - - private ByteBuffer mData; - private Pair mHandles; - private List mHandlesToSend = new ArrayList(); - private List mHandlesToClose = new ArrayList(); - private RecordingMessageReceiver mMessageReceiver; - - /** - * @see org.chromium.mojo.MojoTestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - Core core = CoreImpl.getInstance(); - mData = BindingsTestUtils.newRandomMessage(DATA_SIZE).getData(); - mMessageReceiver = new RecordingMessageReceiver(); - mHandles = core.createMessagePipe(new MessagePipeHandle.CreateOptions()); - Pair datapipe = core.createDataPipe(null); - mHandlesToSend.addAll(Arrays.asList(datapipe.first, datapipe.second)); - mHandlesToClose.addAll(Arrays.asList(mHandles.first, mHandles.second)); - mHandlesToClose.addAll(mHandlesToSend); - } - - /** - * @see org.chromium.mojo.MojoTestCase#tearDown() - */ - @Override - protected void tearDown() throws Exception { - for (Handle handle : mHandlesToClose) { - handle.close(); - } - super.tearDown(); - } - - /** - * Testing {@link Connector#readAndDispatchMessage(MessagePipeHandle, MessageReceiver)} - */ - @SmallTest - public void testReadAndDispatchMessage() { - mHandles.first.writeMessage(mData, mHandlesToSend, MessagePipeHandle.WriteFlags.NONE); - assertEquals(MojoResult.OK, Connector.readAndDispatchMessage(mHandles.second, - mMessageReceiver).getMojoResult()); - assertEquals(1, mMessageReceiver.messages.size()); - Message message = mMessageReceiver.messages.get(0); - mHandlesToClose.addAll(message.getHandles()); - assertEquals(mData, message.getData()); - assertEquals(2, message.getHandles().size()); - for (Handle handle : message.getHandles()) { - assertTrue(handle.isValid()); - } - } - - /** - * Testing {@link Connector#readAndDispatchMessage(MessagePipeHandle, MessageReceiver)} - * with no message available. - */ - @SmallTest - public void testReadAndDispatchMessageOnEmptyHandle() { - assertEquals(MojoResult.SHOULD_WAIT, Connector.readAndDispatchMessage(mHandles.second, - mMessageReceiver).getMojoResult()); - assertEquals(0, mMessageReceiver.messages.size()); - } - - /** - * Testing {@link Connector#readAndDispatchMessage(MessagePipeHandle, MessageReceiver)} - * on closed handle. - */ - @SmallTest - public void testReadAndDispatchMessageOnClosedHandle() { - mHandles.first.close(); - try { - Connector.readAndDispatchMessage(mHandles.second, mMessageReceiver); - fail("MojoException should have been thrown"); - } catch (MojoException expected) { - assertEquals(MojoResult.FAILED_PRECONDITION, expected.getMojoResult()); - } - assertEquals(0, mMessageReceiver.messages.size()); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java deleted file mode 100644 index 6aa1726..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java +++ /dev/null @@ -1,231 +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 android.support.test.filters.SmallTest; - -import org.chromium.base.annotations.SuppressFBWarnings; -import org.chromium.mojo.MojoTestCase; -import org.chromium.mojo.bindings.BindingsTestUtils.CapturingErrorHandler; -import org.chromium.mojo.bindings.BindingsTestUtils.RecordingMessageReceiverWithResponder; -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.Core.HandleSignals; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojo.system.MojoResult; -import org.chromium.mojo.system.Pair; -import org.chromium.mojo.system.ResultAnd; -import org.chromium.mojo.system.impl.CoreImpl; - -import java.nio.ByteBuffer; -import java.util.ArrayList; - -/** - * Testing {@link Router} - */ -public class RouterTest extends MojoTestCase { - - private MessagePipeHandle mHandle; - private Router mRouter; - private RecordingMessageReceiverWithResponder mReceiver; - private CapturingErrorHandler mErrorHandler; - - /** - * @see MojoTestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe(null); - mHandle = handles.first; - mRouter = new RouterImpl(handles.second); - mReceiver = new RecordingMessageReceiverWithResponder(); - mRouter.setIncomingMessageReceiver(mReceiver); - mErrorHandler = new CapturingErrorHandler(); - mRouter.setErrorHandler(mErrorHandler); - mRouter.start(); - } - - /** - * Testing sending a message via the router that expected a response. - */ - @SmallTest - public void testSendingToRouterWithResponse() { - final int requestMessageType = 0xdead; - final int responseMessageType = 0xbeaf; - - // Sending a message expecting a response. - MessageHeader header = new MessageHeader(requestMessageType, - MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG, 0); - Encoder encoder = new Encoder(CoreImpl.getInstance(), header.getSize()); - header.encode(encoder); - mRouter.acceptWithResponder(encoder.getMessage(), mReceiver); - ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(header.getSize()); - ResultAnd result = - mHandle.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE); - - assertEquals(MojoResult.OK, result.getMojoResult()); - MessageHeader receivedHeader = new Message( - receiveBuffer, new ArrayList()).asServiceMessage().getHeader(); - - assertEquals(header.getType(), receivedHeader.getType()); - assertEquals(header.getFlags(), receivedHeader.getFlags()); - assertTrue(receivedHeader.getRequestId() != 0); - - // Sending the response. - MessageHeader responseHeader = new MessageHeader(responseMessageType, - MessageHeader.MESSAGE_IS_RESPONSE_FLAG, receivedHeader.getRequestId()); - encoder = new Encoder(CoreImpl.getInstance(), header.getSize()); - responseHeader.encode(encoder); - Message responseMessage = encoder.getMessage(); - mHandle.writeMessage(responseMessage.getData(), new ArrayList(), - MessagePipeHandle.WriteFlags.NONE); - runLoopUntilIdle(); - - assertEquals(1, mReceiver.messages.size()); - ServiceMessage receivedResponseMessage = mReceiver.messages.get(0).asServiceMessage(); - assertEquals(MessageHeader.MESSAGE_IS_RESPONSE_FLAG, - receivedResponseMessage.getHeader().getFlags()); - assertEquals(responseMessage.getData(), receivedResponseMessage.getData()); - } - - /** - * Sends a message to the Router. - * - * @param messageIndex Used when sending multiple messages to indicate the index of this - * message. - * @param requestMessageType The message type to use in the header of the sent message. - * @param requestId The requestId to use in the header of the sent message. - */ - private void sendMessageToRouter(int messageIndex, int requestMessageType, int requestId) { - MessageHeader header = new MessageHeader( - requestMessageType, MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG, requestId); - Encoder encoder = new Encoder(CoreImpl.getInstance(), header.getSize()); - header.encode(encoder); - Message headerMessage = encoder.getMessage(); - mHandle.writeMessage(headerMessage.getData(), new ArrayList(), - MessagePipeHandle.WriteFlags.NONE); - runLoopUntilIdle(); - - assertEquals(messageIndex + 1, mReceiver.messagesWithReceivers.size()); - Pair receivedMessage = - mReceiver.messagesWithReceivers.get(messageIndex); - assertEquals(headerMessage.getData(), receivedMessage.first.getData()); - } - - /** - * Sends a response message from the Router. - * - * @param messageIndex Used when sending responses to multiple messages to indicate the index - * of the message that this message is a response to. - * @param responseMessageType The message type to use in the header of the response message. - */ - private void sendResponseFromRouter(int messageIndex, int responseMessageType) { - Pair receivedMessage = - mReceiver.messagesWithReceivers.get(messageIndex); - - long requestId = receivedMessage.first.asServiceMessage().getHeader().getRequestId(); - - MessageHeader responseHeader = new MessageHeader( - responseMessageType, MessageHeader.MESSAGE_IS_RESPONSE_FLAG, requestId); - Encoder encoder = new Encoder(CoreImpl.getInstance(), responseHeader.getSize()); - responseHeader.encode(encoder); - Message message = encoder.getMessage(); - receivedMessage.second.accept(message); - - ByteBuffer receivedResponseMessage = ByteBuffer.allocateDirect(responseHeader.getSize()); - ResultAnd result = - mHandle.readMessage(receivedResponseMessage, 0, MessagePipeHandle.ReadFlags.NONE); - - assertEquals(MojoResult.OK, result.getMojoResult()); - assertEquals(message.getData(), receivedResponseMessage); - } - - /** - * Clears {@code mReceiver.messagesWithReceivers} allowing all message receivers to be - * finalized. - *

- * Since there is no way to force the Garbage Collector to actually call finalize and we want to - * test the effects of the finalize() method, we explicitly call finalize() on all of the - * message receivers. We do this in a custom thread to better approximate what the JVM does. - */ - private void clearAllMessageReceivers() { - Thread myFinalizerThread = new Thread() { - @Override - @SuppressFBWarnings("FI_EXPLICIT_INVOCATION") - public void run() { - for (Pair receivedMessage : - mReceiver.messagesWithReceivers) { - RouterImpl.ResponderThunk thunk = - (RouterImpl.ResponderThunk) receivedMessage.second; - try { - thunk.finalize(); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - } - }; - myFinalizerThread.start(); - try { - myFinalizerThread.join(); - } catch (InterruptedException e) { - // ignore. - } - mReceiver.messagesWithReceivers.clear(); - } - - /** - * Testing receiving a message via the router that expected a response. - */ - @SmallTest - public void testReceivingViaRouterWithResponse() { - final int requestMessageType = 0xdead; - final int responseMessageType = 0xbeef; - final int requestId = 0xdeadbeaf; - - // Send a message expecting a response. - sendMessageToRouter(0, requestMessageType, requestId); - - // Sending the response. - sendResponseFromRouter(0, responseMessageType); - } - - /** - * Tests that if a callback is dropped (i.e. becomes unreachable and is finalized - * without being used), then the message pipe will be closed. - */ - @SmallTest - public void testDroppingReceiverWithoutUsingIt() { - // Send 10 messages to the router without sending a response. - for (int i = 0; i < 10; i++) { - sendMessageToRouter(i, i, i); - } - - // Now send the 10 responses. This should work fine. - for (int i = 0; i < 10; i++) { - sendResponseFromRouter(i, i); - } - - // Clear all MessageRecievers so that the ResponderThunks will - // be finalized. - clearAllMessageReceivers(); - - // Send another message to the router without sending a response. - sendMessageToRouter(0, 0, 0); - - // Clear the MessageReciever so that the ResponderThunk will - // be finalized. Since the RespondeThunk was never used, this - // should close the pipe. - clearAllMessageReceivers(); - // The close() occurs asynchronously on this thread. - runLoopUntilIdle(); - - // Confirm that the pipe was closed on the Router side. - HandleSignals closedFlag = HandleSignals.none().setPeerClosed(true); - assertEquals(closedFlag, mHandle.querySignalsState().getSatisfiedSignals()); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/SerializationTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/SerializationTest.java deleted file mode 100644 index 2c17e3a..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/SerializationTest.java +++ /dev/null @@ -1,175 +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 android.support.test.filters.SmallTest; - -import junit.framework.TestCase; - -import org.chromium.mojo.HandleMock; -import org.chromium.mojo.bindings.test.mojom.mojo.Struct1; -import org.chromium.mojo.bindings.test.mojom.mojo.Struct2; -import org.chromium.mojo.bindings.test.mojom.mojo.Struct3; -import org.chromium.mojo.bindings.test.mojom.mojo.Struct4; -import org.chromium.mojo.bindings.test.mojom.mojo.Struct5; -import org.chromium.mojo.bindings.test.mojom.mojo.Struct6; -import org.chromium.mojo.bindings.test.mojom.mojo.StructOfNullables; - -import java.nio.ByteBuffer; - -/** - * Tests for the serialization logic of the generated structs, using structs defined in - * mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom . - */ -public class SerializationTest extends TestCase { - - private static void assertThrowsSerializationException(Struct struct) { - try { - struct.serialize(null); - fail("Serialization of invalid struct should have thrown an exception."); - } catch (SerializationException ex) { - // Expected. - } - } - - /** - * Verifies that serializing a struct with an invalid handle of a non-nullable type throws an - * exception. - */ - @SmallTest - public void testHandle() { - Struct2 struct = new Struct2(); - assertFalse(struct.hdl.isValid()); - assertThrowsSerializationException(struct); - - // Make the struct valid and verify that it serializes without an exception. - struct.hdl = new HandleMock(); - struct.serialize(null); - } - - /** - * Verifies that serializing a struct with a null struct pointer throws an exception. - */ - @SmallTest - public void testStructPointer() { - Struct3 struct = new Struct3(); - assertNull(struct.struct1); - assertThrowsSerializationException(struct); - - // Make the struct valid and verify that it serializes without an exception. - struct.struct1 = new Struct1(); - struct.serialize(null); - } - - /** - * Verifies that serializing a struct with an array of structs throws an exception when the - * struct is invalid. - */ - @SmallTest - public void testStructArray() { - Struct4 struct = new Struct4(); - assertNull(struct.data); - assertThrowsSerializationException(struct); - - // Create the (1-element) array but have the element null. - struct.data = new Struct1[1]; - assertThrowsSerializationException(struct); - - // Create the array element, struct should serialize now. - struct.data[0] = new Struct1(); - struct.serialize(null); - } - - /** - * Verifies that serializing a struct with a fixed-size array of incorrect length throws an - * exception. - */ - @SmallTest - public void testFixedSizeArray() { - Struct5 struct = new Struct5(); - assertNull(struct.pair); - assertThrowsSerializationException(struct); - - // Create the (1-element) array, 2-element array is required. - struct.pair = new Struct1[1]; - struct.pair[0] = new Struct1(); - assertThrowsSerializationException(struct); - - // Create the array of a correct size, struct should serialize now. - struct.pair = new Struct1[2]; - struct.pair[0] = new Struct1(); - struct.pair[1] = new Struct1(); - struct.serialize(null); - } - - /** - * Verifies that serializing a struct with a null string throws an exception. - */ - @SmallTest - public void testString() { - Struct6 struct = new Struct6(); - assertNull(struct.str); - assertThrowsSerializationException(struct); - - // Make the struct valid and verify that it serializes without an exception. - struct.str = ""; - struct.serialize(null); - } - - /** - * Verifies that a struct with an invalid nullable handle, null nullable struct pointer and null - * nullable string serializes without an exception. - */ - @SmallTest - public void testNullableFields() { - StructOfNullables struct = new StructOfNullables(); - assertFalse(struct.hdl.isValid()); - assertNull(struct.struct1); - assertNull(struct.str); - struct.serialize(null); - } - - /** - * Verifies that a struct can be serialized to and deserialized from a ByteBuffer. - */ - @SmallTest - public void testByteBufferSerialization() { - Struct1 input = new Struct1(); - input.i = 0x7F; - - ByteBuffer buf = input.serialize(); - - byte[] expected_raw_bytes = {16, 0, 0, 0, 0, 0, 0, 0, 0x7F, 0, 0, 0, 0, 0, 0, 0}; - ByteBuffer expected_buf = ByteBuffer.wrap(expected_raw_bytes); - assertEquals(expected_buf, buf); - - Struct1 output = Struct1.deserialize(buf); - assertEquals(0x7F, output.i); - } - - /** - * Verifies that a struct with handles cannot be serialized to a ByteBuffer. - */ - @SmallTest - public void testByteBufferSerializationWithHandles() { - StructOfNullables struct = new StructOfNullables(); - assertFalse(struct.hdl.isValid()); - assertNull(struct.struct1); - assertNull(struct.str); - - // It is okay to serialize invalid handles. - struct.serialize(); - - struct.hdl = new HandleMock(); - - try { - struct.serialize(); - fail("Serializing a struct with handles to a ByteBuffer should have thrown an " - + "exception."); - } catch (UnsupportedOperationException ex) { - // Expected. - } - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java deleted file mode 100644 index 8424618..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java +++ /dev/null @@ -1,237 +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 android.support.test.filters.SmallTest; - -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.IntegrationTestInterface; -import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterfaceTestHelper; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.impl.CoreImpl; - -import java.io.File; -import java.io.FileFilter; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; - -/** - * Testing validation upon deserialization using the interfaces defined in the - * mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom file. - *

- * One needs to pass '--test_data=bindings:{path to mojo/public/interfaces/bindings/tests/data}' to - * the test_runner script for this test to find the validation data it needs. - */ -public class ValidationTest extends MojoTestCase { - - /** - * The path where validation test data is. - */ - private static final File VALIDATION_TEST_DATA_PATH = - new File(UrlUtils.getIsolatedTestFilePath( - "mojo/public/interfaces/bindings/tests/data/validation")); - - /** - * The data needed for a validation test. - */ - private static class TestData { - public File dataFile; - public ValidationTestUtil.Data inputData; - public String expectedResult; - } - - private static class DataFileFilter implements FileFilter { - private final String mPrefix; - - public DataFileFilter(String prefix) { - this.mPrefix = prefix; - } - - @Override - public boolean accept(File pathname) { - // TODO(yzshen, qsr): skip some interface versioning tests. - if (pathname.getName().startsWith("conformance_mthd13_good_2")) { - return false; - } - return pathname.isFile() && pathname.getName().startsWith(mPrefix) - && pathname.getName().endsWith(".data"); - } - } - - private static String getStringContent(File f) throws FileNotFoundException { - try (Scanner scanner = new Scanner(f)) { - scanner.useDelimiter("\\Z"); - StringBuilder result = new StringBuilder(); - while (scanner.hasNext()) { - result.append(scanner.next()); - } - return result.toString().trim(); - } - } - - private static List getTestData(String prefix) - throws FileNotFoundException { - List results = new ArrayList(); - - // Fail if the test data is not present. - if (!VALIDATION_TEST_DATA_PATH.isDirectory()) { - fail("No test data directory found. " - + "Expected directory at: " + VALIDATION_TEST_DATA_PATH); - } - - File[] files = VALIDATION_TEST_DATA_PATH.listFiles(new DataFileFilter(prefix)); - if (files != null) { - for (File dataFile : files) { - File resultFile = new File(dataFile.getParent(), - dataFile.getName().replaceFirst("\\.data$", ".expected")); - TestData testData = new TestData(); - testData.dataFile = dataFile; - testData.inputData = ValidationTestUtil.parseData(getStringContent(dataFile)); - testData.expectedResult = getStringContent(resultFile); - results.add(testData); - } - } - return results; - } - - /** - * Runs all the test with the given prefix on the given {@link MessageReceiver}. - */ - private static void runTest(String prefix, MessageReceiver messageReceiver) - throws FileNotFoundException { - List testData = getTestData(prefix); - for (TestData test : testData) { - assertNull("Unable to read: " + test.dataFile.getName() - + ": " + test.inputData.getErrorMessage(), - test.inputData.getErrorMessage()); - List handles = new ArrayList(); - for (int i = 0; i < test.inputData.getHandlesCount(); ++i) { - handles.add(new HandleMock()); - } - Message message = new Message(test.inputData.getData(), handles); - boolean passed = messageReceiver.accept(message); - if (passed && !test.expectedResult.equals("PASS")) { - fail("Input: " + test.dataFile.getName() - + ": The message should have been refused. Expected error: " - + test.expectedResult); - } - if (!passed && test.expectedResult.equals("PASS")) { - fail("Input: " + test.dataFile.getName() - + ": The message should have been accepted."); - } - } - } - - private static class RoutingMessageReceiver implements MessageReceiver { - private final MessageReceiverWithResponder mRequest; - private final MessageReceiver mResponse; - - private RoutingMessageReceiver(MessageReceiverWithResponder 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.acceptWithResponder(message, new SinkMessageReceiver()); - } - } catch (DeserializationException e) { - return false; - } - } - - /** - * @see MessageReceiver#close() - */ - @Override - public void close() { - } - - } - - /** - * A trivial message receiver that refuses all messages it receives. - */ - private static class SinkMessageReceiver implements MessageReceiverWithResponder { - - @Override - public boolean accept(Message message) { - return true; - } - - @Override - public void close() { - } - - @Override - public boolean acceptWithResponder(Message message, MessageReceiver responder) { - return true; - } - } - - /** - * Testing the conformance suite. - */ - @SmallTest - public void testConformance() throws FileNotFoundException { - runTest("conformance_", - ConformanceTestInterface.MANAGER.buildStub(CoreImpl.getInstance(), - ConformanceTestInterface.MANAGER.buildProxy( - CoreImpl.getInstance(), new SinkMessageReceiver()))); - } - - /** - * Testing the integration suite for message headers. - */ - @SmallTest - public void testIntegrationMessageHeader() throws FileNotFoundException { - runTest("integration_msghdr_", - new RoutingMessageReceiver(IntegrationTestInterface.MANAGER.buildStub(null, - IntegrationTestInterface.MANAGER.buildProxy(null, - new SinkMessageReceiver())), - IntegrationTestInterfaceTestHelper - .newIntegrationTestInterfaceMethodCallback())); - } - - /** - * Testing the integration suite for request messages. - */ - @SmallTest - public void testIntegrationRequestMessage() throws FileNotFoundException { - runTest("integration_intf_rqst_", - new RoutingMessageReceiver(IntegrationTestInterface.MANAGER.buildStub(null, - IntegrationTestInterface.MANAGER.buildProxy(null, - new SinkMessageReceiver())), - IntegrationTestInterfaceTestHelper - .newIntegrationTestInterfaceMethodCallback())); - } - - /** - * Testing the integration suite for response messages. - */ - @SmallTest - public void testIntegrationResponseMessage() throws FileNotFoundException { - runTest("integration_intf_resp_", - new RoutingMessageReceiver(IntegrationTestInterface.MANAGER.buildStub(null, - IntegrationTestInterface.MANAGER.buildProxy(null, - new SinkMessageReceiver())), - IntegrationTestInterfaceTestHelper - .newIntegrationTestInterfaceMethodCallback())); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java deleted file mode 100644 index 91b993c..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java +++ /dev/null @@ -1,68 +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.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * Utility class for testing message validation. The file format used to describe a message is - * described in The format is described in - * mojo/public/cpp/bindings/tests/validation_test_input_parser.h - */ -@JNINamespace("mojo::android") -public class ValidationTestUtil { - - /** - * Content of a '.data' file. - */ - public static class Data { - private final ByteBuffer mData; - private final int mHandlesCount; - private final String mErrorMessage; - - public ByteBuffer getData() { - return mData; - } - - public int getHandlesCount() { - return mHandlesCount; - } - - public String getErrorMessage() { - return mErrorMessage; - } - - private Data(ByteBuffer data, int handlesCount, String errorMessage) { - this.mData = data; - this.mHandlesCount = handlesCount; - this.mErrorMessage = errorMessage; - } - } - - /** - * Parse a '.data' file. - */ - public static Data parseData(String dataAsString) { - return nativeParseData(dataAsString); - } - - private static native Data nativeParseData(String dataAsString); - - @CalledByNative - private static Data buildData(ByteBuffer data, int handlesCount, String errorMessage) { - ByteBuffer copiedData = null; - if (data != null) { - copiedData = ByteBuffer.allocateDirect(data.limit()); - copiedData.order(ByteOrder.LITTLE_ENDIAN); - copiedData.put(data); - copiedData.flip(); - } - return new Data(copiedData, handlesCount, errorMessage); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtilTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtilTest.java deleted file mode 100644 index 623abc3..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTestUtilTest.java +++ /dev/null @@ -1,151 +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 android.support.test.filters.SmallTest; - -import org.chromium.mojo.MojoTestCase; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * Testing {@link ValidationTestUtil}. - */ -public class ValidationTestUtilTest extends MojoTestCase { - - /** - * Check that the input parser is correct on a given input. - */ - public static void checkInputParser( - String input, boolean isInputValid, ByteBuffer expectedData, int expectedHandlesCount) { - ValidationTestUtil.Data data = ValidationTestUtil.parseData(input); - if (isInputValid) { - assertNull(data.getErrorMessage()); - assertEquals(expectedData, data.getData()); - assertEquals(expectedHandlesCount, data.getHandlesCount()); - } else { - assertNotNull(data.getErrorMessage()); - assertNull(data.getData()); - } - } - - /** - * Testing {@link ValidationTestUtil#parseData(String)}. - */ - @SmallTest - public void testCorrectMessageParsing() { - { - // Test empty input. - String input = ""; - ByteBuffer expected = ByteBuffer.allocateDirect(0); - expected.order(ByteOrder.LITTLE_ENDIAN); - - checkInputParser(input, true, expected, 0); - } - { - // Test input that only consists of comments and whitespaces. - String input = " \t // hello world \n\r \t// the answer is 42 "; - ByteBuffer expected = ByteBuffer.allocateDirect(0); - expected.order(ByteOrder.nativeOrder()); - - checkInputParser(input, true, expected, 0); - } - { - String input = "[u1]0x10// hello world !! \n\r \t [u2]65535 \n" - + "[u4]65536 [u8]0xFFFFFFFFFFFFFFFF 0 0Xff"; - ByteBuffer expected = ByteBuffer.allocateDirect(17); - expected.order(ByteOrder.nativeOrder()); - expected.put((byte) 0x10); - expected.putShort((short) 65535); - expected.putInt(65536); - expected.putLong(-1); - expected.put((byte) 0); - expected.put((byte) 0xff); - expected.flip(); - - checkInputParser(input, true, expected, 0); - } - { - String input = "[s8]-0x800 [s1]-128\t[s2]+0 [s4]-40"; - ByteBuffer expected = ByteBuffer.allocateDirect(15); - expected.order(ByteOrder.nativeOrder()); - expected.putLong(-0x800); - expected.put((byte) -128); - expected.putShort((short) 0); - expected.putInt(-40); - expected.flip(); - - checkInputParser(input, true, expected, 0); - } - { - String input = "[b]00001011 [b]10000000 // hello world\r [b]00000000"; - ByteBuffer expected = ByteBuffer.allocateDirect(3); - expected.order(ByteOrder.nativeOrder()); - expected.put((byte) 11); - expected.put((byte) 128); - expected.put((byte) 0); - expected.flip(); - - checkInputParser(input, true, expected, 0); - } - { - String input = "[f]+.3e9 [d]-10.03"; - ByteBuffer expected = ByteBuffer.allocateDirect(12); - expected.order(ByteOrder.nativeOrder()); - expected.putFloat(+.3e9f); - expected.putDouble(-10.03); - expected.flip(); - - checkInputParser(input, true, expected, 0); - } - { - String input = "[dist4]foo 0 [dist8]bar 0 [anchr]foo [anchr]bar"; - ByteBuffer expected = ByteBuffer.allocateDirect(14); - expected.order(ByteOrder.nativeOrder()); - expected.putInt(14); - expected.put((byte) 0); - expected.putLong(9); - expected.put((byte) 0); - expected.flip(); - - checkInputParser(input, true, expected, 0); - } - { - String input = "// This message has handles! \n[handles]50 [u8]2"; - ByteBuffer expected = ByteBuffer.allocateDirect(8); - expected.order(ByteOrder.nativeOrder()); - expected.putLong(2); - expected.flip(); - - checkInputParser(input, true, expected, 50); - } - - // Test some failure cases. - { - String error_inputs[] = { - "/ hello world", - "[u1]x", - "[u2]-1000", - "[u1]0x100", - "[s2]-0x8001", - "[b]1", - "[b]1111111k", - "[dist4]unmatched", - "[anchr]hello [dist8]hello", - "[dist4]a [dist4]a [anchr]a", - "[dist4]a [anchr]a [dist4]a [anchr]a", - "0 [handles]50" - }; - - for (String input : error_inputs) { - ByteBuffer expected = ByteBuffer.allocateDirect(0); - expected.order(ByteOrder.nativeOrder()); - checkInputParser(input, false, expected, 0); - } - } - - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterfaceTestHelper.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterfaceTestHelper.java deleted file mode 100644 index 8fb79d7..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterfaceTestHelper.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.IntegrationTestInterface.Method0Response; -import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterface_Internal.IntegrationTestInterfaceMethod0ResponseParamsForwardToCallback; - -/** - * Helper class to access {@link IntegrationTestInterface_Internal} package protected method for - * tests. - */ -public class IntegrationTestInterfaceTestHelper { - - private static final class SinkMethod0Response implements Method0Response { - @Override - public void call(byte[] arg1) { - } - } - - /** - * Creates a new {@link MessageReceiver} to use for the callback of - * |IntegrationTestInterface#method0(Method0Response)|. - */ - public static MessageReceiver newIntegrationTestInterfaceMethodCallback() { - return new IntegrationTestInterfaceMethod0ResponseParamsForwardToCallback( - new SinkMethod0Response()); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/system/impl/CoreImplTest.java b/mojo/android/javatests/src/org/chromium/mojo/system/impl/CoreImplTest.java deleted file mode 100644 index 5120198..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/system/impl/CoreImplTest.java +++ /dev/null @@ -1,545 +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.system.impl; - -import android.support.test.filters.SmallTest; - -import org.chromium.mojo.MojoTestCase; -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.Core.HandleSignals; -import org.chromium.mojo.system.DataPipe; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.InvalidHandle; -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.ResultAnd; -import org.chromium.mojo.system.SharedBufferHandle; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; - -/** - * Testing the core API. - */ -public class CoreImplTest extends MojoTestCase { - private static final long RUN_LOOP_TIMEOUT_MS = 5; - - private static final ScheduledExecutorService WORKER = - Executors.newSingleThreadScheduledExecutor(); - - private static final HandleSignals ALL_SIGNALS = - HandleSignals.none().setPeerClosed(true).setReadable(true).setWritable(true); - - private List mHandlesToClose = new ArrayList(); - - /** - * @see MojoTestCase#tearDown() - */ - @Override - protected void tearDown() throws Exception { - MojoException toThrow = null; - for (Handle handle : mHandlesToClose) { - try { - handle.close(); - } catch (MojoException e) { - if (toThrow == null) { - toThrow = e; - } - } - } - if (toThrow != null) { - throw toThrow; - } - super.tearDown(); - } - - private void addHandleToClose(Handle handle) { - mHandlesToClose.add(handle); - } - - private void addHandlePairToClose(Pair handles) { - mHandlesToClose.add(handles.first); - mHandlesToClose.add(handles.second); - } - - private static void checkSendingMessage(MessagePipeHandle in, MessagePipeHandle out) { - Random random = new Random(); - - // Writing a random 8 bytes message. - byte[] bytes = new byte[8]; - random.nextBytes(bytes); - ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); - buffer.put(bytes); - in.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.NONE); - - // Try to read into a small buffer. - ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length / 2); - ResultAnd result = - out.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE); - assertEquals(MojoResult.RESOURCE_EXHAUSTED, result.getMojoResult()); - assertEquals(bytes.length, result.getValue().getMessageSize()); - assertEquals(0, result.getValue().getHandlesCount()); - - // Read into a correct buffer. - receiveBuffer = ByteBuffer.allocateDirect(bytes.length); - result = out.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE); - assertEquals(MojoResult.OK, result.getMojoResult()); - assertEquals(bytes.length, result.getValue().getMessageSize()); - assertEquals(0, result.getValue().getHandlesCount()); - assertEquals(0, receiveBuffer.position()); - assertEquals(result.getValue().getMessageSize(), receiveBuffer.limit()); - byte[] receivedBytes = new byte[result.getValue().getMessageSize()]; - receiveBuffer.get(receivedBytes); - assertTrue(Arrays.equals(bytes, receivedBytes)); - } - - private static void checkSendingData(DataPipe.ProducerHandle in, DataPipe.ConsumerHandle out) { - Random random = new Random(); - - // Writing a random 8 bytes message. - byte[] bytes = new byte[8]; - random.nextBytes(bytes); - ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); - buffer.put(bytes); - ResultAnd result = in.writeData(buffer, DataPipe.WriteFlags.NONE); - assertEquals(MojoResult.OK, result.getMojoResult()); - assertEquals(bytes.length, result.getValue().intValue()); - - // Query number of bytes available. - ResultAnd readResult = out.readData(null, DataPipe.ReadFlags.none().query(true)); - assertEquals(MojoResult.OK, readResult.getMojoResult()); - assertEquals(bytes.length, readResult.getValue().intValue()); - - // Peek data into a buffer. - ByteBuffer peekBuffer = ByteBuffer.allocateDirect(bytes.length); - readResult = out.readData(peekBuffer, DataPipe.ReadFlags.none().peek(true)); - assertEquals(MojoResult.OK, readResult.getMojoResult()); - assertEquals(bytes.length, readResult.getValue().intValue()); - assertEquals(bytes.length, peekBuffer.limit()); - byte[] peekBytes = new byte[bytes.length]; - peekBuffer.get(peekBytes); - assertTrue(Arrays.equals(bytes, peekBytes)); - - // Read into a buffer. - ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length); - readResult = out.readData(receiveBuffer, DataPipe.ReadFlags.NONE); - assertEquals(MojoResult.OK, readResult.getMojoResult()); - assertEquals(bytes.length, readResult.getValue().intValue()); - assertEquals(0, receiveBuffer.position()); - assertEquals(bytes.length, receiveBuffer.limit()); - byte[] receivedBytes = new byte[bytes.length]; - receiveBuffer.get(receivedBytes); - assertTrue(Arrays.equals(bytes, receivedBytes)); - } - - private static void checkSharing(SharedBufferHandle in, SharedBufferHandle out) { - Random random = new Random(); - - ByteBuffer buffer1 = in.map(0, 8, SharedBufferHandle.MapFlags.NONE); - assertEquals(8, buffer1.capacity()); - ByteBuffer buffer2 = out.map(0, 8, SharedBufferHandle.MapFlags.NONE); - assertEquals(8, buffer2.capacity()); - - byte[] bytes = new byte[8]; - random.nextBytes(bytes); - buffer1.put(bytes); - - byte[] receivedBytes = new byte[bytes.length]; - buffer2.get(receivedBytes); - - assertTrue(Arrays.equals(bytes, receivedBytes)); - - in.unmap(buffer1); - out.unmap(buffer2); - } - - /** - * Testing that Core can be retrieved from a handle. - */ - @SmallTest - public void testGetCore() { - Core core = CoreImpl.getInstance(); - - Pair handles = core.createMessagePipe(null); - addHandlePairToClose(handles); - assertEquals(core, handles.first.getCore()); - assertEquals(core, handles.second.getCore()); - - handles = core.createDataPipe(null); - addHandlePairToClose(handles); - assertEquals(core, handles.first.getCore()); - assertEquals(core, handles.second.getCore()); - - SharedBufferHandle handle = core.createSharedBuffer(null, 100); - SharedBufferHandle handle2 = handle.duplicate(null); - addHandleToClose(handle); - addHandleToClose(handle2); - assertEquals(core, handle.getCore()); - assertEquals(core, handle2.getCore()); - } - - private static void createAndCloseMessagePipe(MessagePipeHandle.CreateOptions options) { - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe(options); - handles.first.close(); - handles.second.close(); - } - - /** - * Testing {@link MessagePipeHandle} creation. - */ - @SmallTest - public void testMessagePipeCreation() { - // Test creation with null options. - createAndCloseMessagePipe(null); - // Test creation with default options. - createAndCloseMessagePipe(new MessagePipeHandle.CreateOptions()); - } - - /** - * Testing {@link MessagePipeHandle}. - */ - @SmallTest - public void testMessagePipeEmpty() { - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe(null); - addHandlePairToClose(handles); - - // Testing read on an empty pipe. - ResultAnd readResult = - handles.first.readMessage(null, 0, MessagePipeHandle.ReadFlags.NONE); - assertEquals(MojoResult.SHOULD_WAIT, readResult.getMojoResult()); - - handles.first.close(); - handles.second.close(); - } - - /** - * Testing {@link MessagePipeHandle}. - */ - @SmallTest - public void testMessagePipeSend() { - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe(null); - addHandlePairToClose(handles); - - checkSendingMessage(handles.first, handles.second); - checkSendingMessage(handles.second, handles.first); - } - - /** - * Testing {@link MessagePipeHandle}. - */ - @SmallTest - public void testMessagePipeReceiveOnSmallBuffer() { - Random random = new Random(); - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe(null); - addHandlePairToClose(handles); - - // Writing a random 8 bytes message. - byte[] bytes = new byte[8]; - random.nextBytes(bytes); - ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); - buffer.put(bytes); - handles.first.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.NONE); - - ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(1); - ResultAnd result = - handles.second.readMessage(receiveBuffer, 0, MessagePipeHandle.ReadFlags.NONE); - assertEquals(MojoResult.RESOURCE_EXHAUSTED, result.getMojoResult()); - assertEquals(bytes.length, result.getValue().getMessageSize()); - assertEquals(0, result.getValue().getHandlesCount()); - } - - /** - * Testing {@link MessagePipeHandle}. - */ - @SmallTest - public void testMessagePipeSendHandles() { - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe(null); - Pair handlesToShare = core.createMessagePipe(null); - addHandlePairToClose(handles); - addHandlePairToClose(handlesToShare); - - handles.first.writeMessage(null, Collections.singletonList(handlesToShare.second), - MessagePipeHandle.WriteFlags.NONE); - assertFalse(handlesToShare.second.isValid()); - ResultAnd readMessageResult = - handles.second.readMessage(null, 1, MessagePipeHandle.ReadFlags.NONE); - assertEquals(1, readMessageResult.getValue().getHandlesCount()); - MessagePipeHandle newHandle = - readMessageResult.getValue().getHandles().get(0).toMessagePipeHandle(); - addHandleToClose(newHandle); - assertTrue(newHandle.isValid()); - checkSendingMessage(handlesToShare.first, newHandle); - checkSendingMessage(newHandle, handlesToShare.first); - } - - private static void createAndCloseDataPipe(DataPipe.CreateOptions options) { - Core core = CoreImpl.getInstance(); - Pair handles = - core.createDataPipe(options); - handles.first.close(); - handles.second.close(); - } - - /** - * Testing {@link DataPipe}. - */ - @SmallTest - public void testDataPipeCreation() { - // Create datapipe with null options. - createAndCloseDataPipe(null); - DataPipe.CreateOptions options = new DataPipe.CreateOptions(); - // Create datapipe with element size set. - options.setElementNumBytes(24); - createAndCloseDataPipe(options); - // Create datapipe with capacity set. - options.setCapacityNumBytes(1024 * options.getElementNumBytes()); - createAndCloseDataPipe(options); - } - - /** - * Testing {@link DataPipe}. - */ - @SmallTest - public void testDataPipeSend() { - Core core = CoreImpl.getInstance(); - - Pair handles = core.createDataPipe(null); - addHandlePairToClose(handles); - - checkSendingData(handles.first, handles.second); - } - - /** - * Testing {@link DataPipe}. - */ - @SmallTest - public void testDataPipeTwoPhaseSend() { - Random random = new Random(); - Core core = CoreImpl.getInstance(); - Pair handles = core.createDataPipe(null); - addHandlePairToClose(handles); - - // Writing a random 8 bytes message. - byte[] bytes = new byte[8]; - random.nextBytes(bytes); - ByteBuffer buffer = handles.first.beginWriteData(bytes.length, DataPipe.WriteFlags.NONE); - assertTrue(buffer.capacity() >= bytes.length); - buffer.put(bytes); - handles.first.endWriteData(bytes.length); - - // Read into a buffer. - ByteBuffer receiveBuffer = - handles.second.beginReadData(bytes.length, DataPipe.ReadFlags.NONE); - assertEquals(0, receiveBuffer.position()); - assertEquals(bytes.length, receiveBuffer.limit()); - byte[] receivedBytes = new byte[bytes.length]; - receiveBuffer.get(receivedBytes); - assertTrue(Arrays.equals(bytes, receivedBytes)); - handles.second.endReadData(bytes.length); - } - - /** - * Testing {@link DataPipe}. - */ - @SmallTest - public void testDataPipeDiscard() { - Random random = new Random(); - Core core = CoreImpl.getInstance(); - Pair handles = core.createDataPipe(null); - addHandlePairToClose(handles); - - // Writing a random 8 bytes message. - byte[] bytes = new byte[8]; - random.nextBytes(bytes); - ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length); - buffer.put(bytes); - ResultAnd result = handles.first.writeData(buffer, DataPipe.WriteFlags.NONE); - assertEquals(MojoResult.OK, result.getMojoResult()); - assertEquals(bytes.length, result.getValue().intValue()); - - // Discard bytes. - final int nbBytesToDiscard = 4; - assertEquals(nbBytesToDiscard, - handles.second.discardData(nbBytesToDiscard, DataPipe.ReadFlags.NONE)); - - // Read into a buffer. - ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length - nbBytesToDiscard); - ResultAnd readResult = - handles.second.readData(receiveBuffer, DataPipe.ReadFlags.NONE); - assertEquals(MojoResult.OK, readResult.getMojoResult()); - assertEquals(bytes.length - nbBytesToDiscard, readResult.getValue().intValue()); - assertEquals(0, receiveBuffer.position()); - assertEquals(bytes.length - nbBytesToDiscard, receiveBuffer.limit()); - byte[] receivedBytes = new byte[bytes.length - nbBytesToDiscard]; - receiveBuffer.get(receivedBytes); - assertTrue(Arrays.equals( - Arrays.copyOfRange(bytes, nbBytesToDiscard, bytes.length), receivedBytes)); - } - - /** - * Testing {@link SharedBufferHandle}. - */ - @SmallTest - public void testSharedBufferCreation() { - Core core = CoreImpl.getInstance(); - // Test creation with empty options. - core.createSharedBuffer(null, 8).close(); - // Test creation with default options. - core.createSharedBuffer(new SharedBufferHandle.CreateOptions(), 8).close(); - } - - /** - * Testing {@link SharedBufferHandle}. - */ - @SmallTest - public void testSharedBufferDuplication() { - Core core = CoreImpl.getInstance(); - SharedBufferHandle handle = core.createSharedBuffer(null, 8); - addHandleToClose(handle); - - // Test duplication with empty options. - handle.duplicate(null).close(); - // Test creation with default options. - handle.duplicate(new SharedBufferHandle.DuplicateOptions()).close(); - } - - /** - * Testing {@link SharedBufferHandle}. - */ - @SmallTest - public void testSharedBufferSending() { - Core core = CoreImpl.getInstance(); - SharedBufferHandle handle = core.createSharedBuffer(null, 8); - addHandleToClose(handle); - SharedBufferHandle newHandle = handle.duplicate(null); - addHandleToClose(newHandle); - - checkSharing(handle, newHandle); - checkSharing(newHandle, handle); - } - - /** - * Testing that invalid handle can be used with this implementation. - */ - @SmallTest - public void testInvalidHandle() { - Core core = CoreImpl.getInstance(); - Handle handle = InvalidHandle.INSTANCE; - - // Checking sending an invalid handle. - // Until the behavior is changed on the C++ side, handle gracefully 2 different use case: - // - Receive a INVALID_ARGUMENT exception - // - Receive an invalid handle on the other side. - Pair handles = core.createMessagePipe(null); - addHandlePairToClose(handles); - try { - handles.first.writeMessage(null, Collections.singletonList(handle), - MessagePipeHandle.WriteFlags.NONE); - ResultAnd readMessageResult = - handles.second.readMessage(null, 1, MessagePipeHandle.ReadFlags.NONE); - assertEquals(1, readMessageResult.getValue().getHandlesCount()); - assertFalse(readMessageResult.getValue().getHandles().get(0).isValid()); - } catch (MojoException e) { - assertEquals(MojoResult.INVALID_ARGUMENT, e.getMojoResult()); - } - } - - /** - * Testing the pass method on message pipes. - */ - @SmallTest - public void testMessagePipeHandlePass() { - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe(null); - addHandlePairToClose(handles); - - assertTrue(handles.first.isValid()); - MessagePipeHandle handleClone = handles.first.pass(); - - addHandleToClose(handleClone); - - assertFalse(handles.first.isValid()); - assertTrue(handleClone.isValid()); - checkSendingMessage(handleClone, handles.second); - checkSendingMessage(handles.second, handleClone); - } - - /** - * Testing the pass method on data pipes. - */ - @SmallTest - public void testDataPipeHandlePass() { - Core core = CoreImpl.getInstance(); - Pair handles = core.createDataPipe(null); - addHandlePairToClose(handles); - - DataPipe.ProducerHandle producerClone = handles.first.pass(); - DataPipe.ConsumerHandle consumerClone = handles.second.pass(); - - addHandleToClose(producerClone); - addHandleToClose(consumerClone); - - assertFalse(handles.first.isValid()); - assertFalse(handles.second.isValid()); - assertTrue(producerClone.isValid()); - assertTrue(consumerClone.isValid()); - checkSendingData(producerClone, consumerClone); - } - - /** - * Testing the pass method on shared buffers. - */ - @SmallTest - public void testSharedBufferPass() { - Core core = CoreImpl.getInstance(); - SharedBufferHandle handle = core.createSharedBuffer(null, 8); - addHandleToClose(handle); - SharedBufferHandle newHandle = handle.duplicate(null); - addHandleToClose(newHandle); - - SharedBufferHandle handleClone = handle.pass(); - SharedBufferHandle newHandleClone = newHandle.pass(); - - addHandleToClose(handleClone); - addHandleToClose(newHandleClone); - - assertFalse(handle.isValid()); - assertTrue(handleClone.isValid()); - checkSharing(handleClone, newHandleClone); - checkSharing(newHandleClone, handleClone); - } - - /** - * esting handle conversion to native and back. - */ - @SmallTest - public void testHandleConversion() { - Core core = CoreImpl.getInstance(); - Pair handles = core.createMessagePipe(null); - addHandlePairToClose(handles); - - MessagePipeHandle converted = - core.acquireNativeHandle(handles.first.releaseNativeHandle()).toMessagePipeHandle(); - addHandleToClose(converted); - - assertFalse(handles.first.isValid()); - - checkSendingMessage(converted, handles.second); - checkSendingMessage(handles.second, converted); - } -} diff --git a/mojo/android/javatests/src/org/chromium/mojo/system/impl/WatcherImplTest.java b/mojo/android/javatests/src/org/chromium/mojo/system/impl/WatcherImplTest.java deleted file mode 100644 index e14adb1..0000000 --- a/mojo/android/javatests/src/org/chromium/mojo/system/impl/WatcherImplTest.java +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.mojo.system.impl; - -import android.support.test.filters.SmallTest; - -import org.chromium.mojo.MojoTestCase; -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.InvalidHandle; -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.Watcher; -import org.chromium.mojo.system.Watcher.Callback; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -/** - * Testing the Watcher. - */ -public class WatcherImplTest extends MojoTestCase { - private List mHandlesToClose = new ArrayList(); - private Watcher mWatcher; - private Core mCore; - - /** - * @see MojoTestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - mWatcher = new WatcherImpl(); - mCore = CoreImpl.getInstance(); - } - - /** - * @see MojoTestCase#tearDown() - */ - @Override - protected void tearDown() throws Exception { - mWatcher.destroy(); - MojoException toThrow = null; - for (Handle handle : mHandlesToClose) { - try { - handle.close(); - } catch (MojoException e) { - if (toThrow == null) { - toThrow = e; - } - } - } - if (toThrow != null) { - throw toThrow; - } - super.tearDown(); - } - - private void addHandlePairToClose(Pair handles) { - mHandlesToClose.add(handles.first); - mHandlesToClose.add(handles.second); - } - - private static class WatcherResult implements Callback { - private int mResult = Integer.MIN_VALUE; - private MessagePipeHandle mReadPipe; - - /** - * @param readPipe A MessagePipeHandle to read from when onResult triggers success. - */ - public WatcherResult(MessagePipeHandle readPipe) { - mReadPipe = readPipe; - } - public WatcherResult() { - this(null); - } - - /** - * @see Callback#onResult(int) - */ - @Override - public void onResult(int result) { - this.mResult = result; - - if (result == MojoResult.OK && mReadPipe != null) { - mReadPipe.readMessage( - null, 0, MessagePipeHandle.ReadFlags.none().setMayDiscard(true)); - } - } - - /** - * @return the result - */ - public int getResult() { - return mResult; - } - } - - /** - * Testing {@link Watcher} implementation. - */ - @SmallTest - public void testCorrectResult() { - // Checking a correct result. - Pair handles = mCore.createMessagePipe(null); - addHandlePairToClose(handles); - final WatcherResult watcherResult = new WatcherResult(handles.first); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - mWatcher.start(handles.first, Core.HandleSignals.READABLE, watcherResult); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - handles.second.writeMessage( - ByteBuffer.allocateDirect(1), null, MessagePipeHandle.WriteFlags.NONE); - runLoopUntilIdle(); - assertEquals(MojoResult.OK, watcherResult.getResult()); - } - - /** - * Testing {@link Watcher} implementation. - */ - @SmallTest - public void testClosingPeerHandle() { - // Closing the peer handle. - Pair handles = mCore.createMessagePipe(null); - addHandlePairToClose(handles); - - final WatcherResult watcherResult = new WatcherResult(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - mWatcher.start(handles.first, Core.HandleSignals.READABLE, watcherResult); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - runLoopUntilIdle(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - handles.second.close(); - runLoopUntilIdle(); - assertEquals(MojoResult.FAILED_PRECONDITION, watcherResult.getResult()); - } - - /** - * Testing {@link Watcher} implementation. - */ - @SmallTest - public void testClosingWatchedHandle() { - // Closing the peer handle. - Pair handles = mCore.createMessagePipe(null); - addHandlePairToClose(handles); - - final WatcherResult watcherResult = new WatcherResult(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - mWatcher.start(handles.first, Core.HandleSignals.READABLE, watcherResult); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - runLoopUntilIdle(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - handles.first.close(); - runLoopUntilIdle(); - assertEquals(MojoResult.CANCELLED, watcherResult.getResult()); - } - - /** - * Testing {@link Watcher} implementation. - */ - @SmallTest - public void testInvalidHandle() { - // Closing the peer handle. - Pair handles = mCore.createMessagePipe(null); - addHandlePairToClose(handles); - - final WatcherResult watcherResult = new WatcherResult(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - handles.first.close(); - assertEquals(MojoResult.INVALID_ARGUMENT, - mWatcher.start(handles.first, Core.HandleSignals.READABLE, watcherResult)); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - runLoopUntilIdle(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - } - - /** - * Testing {@link Watcher} implementation. - */ - @SmallTest - public void testDefaultInvalidHandle() { - final WatcherResult watcherResult = new WatcherResult(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - assertEquals(MojoResult.INVALID_ARGUMENT, - mWatcher.start(InvalidHandle.INSTANCE, Core.HandleSignals.READABLE, watcherResult)); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - runLoopUntilIdle(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - } - - /** - * Testing {@link Watcher} implementation. - */ - @SmallTest - public void testCancel() { - // Closing the peer handle. - Pair handles = mCore.createMessagePipe(null); - addHandlePairToClose(handles); - - final WatcherResult watcherResult = new WatcherResult(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - mWatcher.start(handles.first, Core.HandleSignals.READABLE, watcherResult); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - runLoopUntilIdle(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - mWatcher.cancel(); - runLoopUntilIdle(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - handles.second.writeMessage( - ByteBuffer.allocateDirect(1), null, MessagePipeHandle.WriteFlags.NONE); - runLoopUntilIdle(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - } - - /** - * Testing {@link Watcher} implementation. - */ - @SmallTest - public void testImmediateCancelOnInvalidHandle() { - // Closing the peer handle. - Pair handles = mCore.createMessagePipe(null); - addHandlePairToClose(handles); - - final WatcherResult watcherResult = new WatcherResult(); - handles.first.close(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - - mWatcher.start(handles.first, Core.HandleSignals.READABLE, watcherResult); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - mWatcher.cancel(); - - runLoopUntilIdle(); - assertEquals(Integer.MIN_VALUE, watcherResult.getResult()); - } -} diff --git a/mojo/android/javatests/validation_test_util.cc b/mojo/android/javatests/validation_test_util.cc deleted file mode 100644 index 75f79b3..0000000 --- a/mojo/android/javatests/validation_test_util.cc +++ /dev/null @@ -1,54 +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/android/javatests/validation_test_util.h" - -#include -#include - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/android/scoped_java_ref.h" -#include "base/test/test_support_android.h" -#include "jni/ValidationTestUtil_jni.h" -#include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" - -using base::android::JavaParamRef; -using base::android::ScopedJavaLocalRef; - -namespace mojo { -namespace android { - -bool RegisterValidationTestUtil(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -ScopedJavaLocalRef ParseData( - JNIEnv* env, - const JavaParamRef& jcaller, - const JavaParamRef& data_as_string) { - std::string input = - base::android::ConvertJavaStringToUTF8(env, data_as_string); - std::vector data; - size_t num_handles; - std::string error_message; - if (!test::ParseValidationTestInput( - input, &data, &num_handles, &error_message)) { - ScopedJavaLocalRef j_error_message = - base::android::ConvertUTF8ToJavaString(env, error_message); - return Java_ValidationTestUtil_buildData(env, nullptr, 0, j_error_message); - } - void* data_ptr = &data[0]; - if (!data_ptr) { - DCHECK(!data.size()); - data_ptr = &data; - } - jobject byte_buffer = - env->NewDirectByteBuffer(data_ptr, data.size()); - return Java_ValidationTestUtil_buildData(env, byte_buffer, num_handles, - nullptr); -} - -} // namespace android -} // namespace mojo diff --git a/mojo/android/javatests/validation_test_util.h b/mojo/android/javatests/validation_test_util.h deleted file mode 100644 index f58dc07..0000000 --- a/mojo/android/javatests/validation_test_util.h +++ /dev/null @@ -1,20 +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_ANDROID_JAVATESTS_VALIDATION_TEST_UTIL_H_ -#define MOJO_ANDROID_JAVATESTS_VALIDATION_TEST_UTIL_H_ - -#include - -#include "base/android/jni_android.h" - -namespace mojo { -namespace android { - -JNI_EXPORT bool RegisterValidationTestUtil(JNIEnv* env); - -} // namespace android -} // namespace mojo - -#endif // MOJO_SYSTEM_ANDROID_JAVATESTS_VALIDATION_TEST_UTIL_H_ diff --git a/mojo/android/system/base_run_loop.cc b/mojo/android/system/base_run_loop.cc deleted file mode 100644 index 7993ba8..0000000 --- a/mojo/android/system/base_run_loop.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/android/system/base_run_loop.h" - -#include - -// Removed unused headers. TODO(hidehiko): Upstream. -// #include "base/android/base_jni_registrar.h" -#include "base/android/jni_android.h" -// #include "base/android/jni_registrar.h" -#include "base/bind.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "jni/BaseRunLoop_jni.h" - -using base::android::JavaParamRef; - -namespace mojo { -namespace android { - -static jlong CreateBaseRunLoop(JNIEnv* env, - const JavaParamRef& jcaller) { - base::MessageLoop* message_loop = new base::MessageLoop; - return reinterpret_cast(message_loop); -} - -static void Run(JNIEnv* env, - const JavaParamRef& jcaller) { - base::RunLoop().Run(); -} - -static void RunUntilIdle(JNIEnv* env, - const JavaParamRef& jcaller) { - base::RunLoop().RunUntilIdle(); -} - -static void Quit(JNIEnv* env, - const JavaParamRef& jcaller, - jlong runLoopID) { - reinterpret_cast(runLoopID)->QuitWhenIdle(); -} - -static void RunJavaRunnable( - const base::android::ScopedJavaGlobalRef& runnable_ref) { - Java_BaseRunLoop_runRunnable(base::android::AttachCurrentThread(), - runnable_ref); -} - -static void PostDelayedTask(JNIEnv* env, - const JavaParamRef& jcaller, - jlong runLoopID, - const JavaParamRef& runnable, - jlong delay) { - base::android::ScopedJavaGlobalRef runnable_ref; - // ScopedJavaGlobalRef do not hold onto the env reference, so it is safe to - // use it across threads. |RunJavaRunnable| will acquire a new JNIEnv before - // running the Runnable. - runnable_ref.Reset(env, runnable); - reinterpret_cast(runLoopID) - ->task_runner() - ->PostDelayedTask(FROM_HERE, base::Bind(&RunJavaRunnable, runnable_ref), - base::TimeDelta::FromMicroseconds(delay)); -} - -static void DeleteMessageLoop(JNIEnv* env, - const JavaParamRef& jcaller, - jlong runLoopID) { - base::MessageLoop* message_loop = - reinterpret_cast(runLoopID); - delete message_loop; -} - -bool RegisterBaseRunLoop(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace android -} // namespace mojo diff --git a/mojo/android/system/base_run_loop.h b/mojo/android/system/base_run_loop.h deleted file mode 100644 index f225c65..0000000 --- a/mojo/android/system/base_run_loop.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_ANDROID_SYSTEM_BASE_RUN_LOOP_H_ -#define MOJO_ANDROID_SYSTEM_BASE_RUN_LOOP_H_ - -#include - -#include "base/android/jni_android.h" - -namespace mojo { -namespace android { - -JNI_EXPORT bool RegisterBaseRunLoop(JNIEnv* env); - -} // namespace android -} // namespace mojo - -#endif // MOJO_ANDROID_SYSTEM_BASE_RUN_LOOP_H_ diff --git a/mojo/android/system/core_impl.cc b/mojo/android/system/core_impl.cc deleted file mode 100644 index 7d5a402..0000000 --- a/mojo/android/system/core_impl.cc +++ /dev/null @@ -1,310 +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/android/system/core_impl.h" - -#include -#include - -// Removed unused headers. TODO(hidehiko): Upstream. -// #include "base/android/base_jni_registrar.h" -#include "base/android/jni_android.h" -// #include "base/android/jni_registrar.h" -// #include "base/android/library_loader/library_loader_hooks.h" -#include "base/android/scoped_java_ref.h" -#include "jni/CoreImpl_jni.h" -#include "mojo/public/c/system/core.h" - -namespace mojo { -namespace android { - -using base::android::JavaParamRef; -using base::android::ScopedJavaLocalRef; - -static jlong GetTimeTicksNow(JNIEnv* env, - const JavaParamRef& jcaller) { - return MojoGetTimeTicksNow(); -} - -static ScopedJavaLocalRef CreateMessagePipe( - JNIEnv* env, - const JavaParamRef& jcaller, - const JavaParamRef& options_buffer) { - const MojoCreateMessagePipeOptions* options = NULL; - if (options_buffer) { - const void* buffer_start = env->GetDirectBufferAddress(options_buffer); - DCHECK(buffer_start); - DCHECK_EQ(reinterpret_cast(buffer_start) % 8, 0u); - const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); - DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions)); - options = static_cast(buffer_start); - DCHECK_EQ(options->struct_size, buffer_size); - } - MojoHandle handle1; - MojoHandle handle2; - MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2); - return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2); -} - -static ScopedJavaLocalRef CreateDataPipe( - JNIEnv* env, - const JavaParamRef& jcaller, - const JavaParamRef& options_buffer) { - const MojoCreateDataPipeOptions* options = NULL; - if (options_buffer) { - const void* buffer_start = env->GetDirectBufferAddress(options_buffer); - DCHECK(buffer_start); - DCHECK_EQ(reinterpret_cast(buffer_start) % 8, 0u); - const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); - DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions)); - options = static_cast(buffer_start); - DCHECK_EQ(options->struct_size, buffer_size); - } - MojoHandle handle1; - MojoHandle handle2; - MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2); - return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2); -} - -static ScopedJavaLocalRef CreateSharedBuffer( - JNIEnv* env, - const JavaParamRef& jcaller, - const JavaParamRef& options_buffer, - jlong num_bytes) { - const MojoCreateSharedBufferOptions* options = 0; - if (options_buffer) { - const void* buffer_start = env->GetDirectBufferAddress(options_buffer); - DCHECK(buffer_start); - DCHECK_EQ(reinterpret_cast(buffer_start) % 8, 0u); - const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); - DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions)); - options = static_cast(buffer_start); - DCHECK_EQ(options->struct_size, buffer_size); - } - MojoHandle handle; - MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle); - return Java_CoreImpl_newResultAndInteger(env, result, handle); -} - -static jint Close(JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle) { - return MojoClose(mojo_handle); -} - -static jint QueryHandleSignalsState(JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - const JavaParamRef& buffer) { - MojoHandleSignalsState* signals_state = - static_cast(env->GetDirectBufferAddress(buffer)); - DCHECK(signals_state); - DCHECK_EQ(sizeof(MojoHandleSignalsState), - static_cast(env->GetDirectBufferCapacity(buffer))); - return MojoQueryHandleSignalsState(mojo_handle, signals_state); -} - -static jint WriteMessage(JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - const JavaParamRef& bytes, - jint num_bytes, - const JavaParamRef& handles_buffer, - jint flags) { - const void* buffer_start = 0; - uint32_t buffer_size = 0; - if (bytes) { - buffer_start = env->GetDirectBufferAddress(bytes); - DCHECK(buffer_start); - DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes); - buffer_size = num_bytes; - } - const MojoHandle* handles = 0; - uint32_t num_handles = 0; - if (handles_buffer) { - handles = - static_cast(env->GetDirectBufferAddress(handles_buffer)); - num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; - } - // Java code will handle invalidating handles if the write succeeded. - return MojoWriteMessage( - mojo_handle, buffer_start, buffer_size, handles, num_handles, flags); -} - -static ScopedJavaLocalRef ReadMessage( - JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - const JavaParamRef& bytes, - const JavaParamRef& handles_buffer, - jint flags) { - void* buffer_start = 0; - uint32_t buffer_size = 0; - if (bytes) { - buffer_start = env->GetDirectBufferAddress(bytes); - DCHECK(buffer_start); - buffer_size = env->GetDirectBufferCapacity(bytes); - } - MojoHandle* handles = 0; - uint32_t num_handles = 0; - if (handles_buffer) { - handles = - static_cast(env->GetDirectBufferAddress(handles_buffer)); - num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; - } - MojoResult result = MojoReadMessage( - mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags); - // Jave code will handle taking ownership of any received handle. - return Java_CoreImpl_newReadMessageResult(env, result, buffer_size, - num_handles); -} - -static ScopedJavaLocalRef ReadData( - JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - const JavaParamRef& elements, - jint elements_capacity, - jint flags) { - void* buffer_start = 0; - uint32_t buffer_size = elements_capacity; - if (elements) { - buffer_start = env->GetDirectBufferAddress(elements); - DCHECK(buffer_start); - DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements)); - } - MojoResult result = - MojoReadData(mojo_handle, buffer_start, &buffer_size, flags); - return Java_CoreImpl_newResultAndInteger( - env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0); -} - -static ScopedJavaLocalRef BeginReadData( - JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - jint num_bytes, - jint flags) { - void const* buffer = 0; - uint32_t buffer_size = num_bytes; - MojoResult result = - MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags); - jobject byte_buffer = 0; - if (result == MOJO_RESULT_OK) { - byte_buffer = - env->NewDirectByteBuffer(const_cast(buffer), buffer_size); - } - return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); -} - -static jint EndReadData(JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - jint num_bytes_read) { - return MojoEndReadData(mojo_handle, num_bytes_read); -} - -static ScopedJavaLocalRef WriteData( - JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - const JavaParamRef& elements, - jint limit, - jint flags) { - void* buffer_start = env->GetDirectBufferAddress(elements); - DCHECK(buffer_start); - DCHECK(limit <= env->GetDirectBufferCapacity(elements)); - uint32_t buffer_size = limit; - MojoResult result = - MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags); - return Java_CoreImpl_newResultAndInteger( - env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0); -} - -static ScopedJavaLocalRef BeginWriteData( - JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - jint num_bytes, - jint flags) { - void* buffer = 0; - uint32_t buffer_size = num_bytes; - MojoResult result = - MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags); - jobject byte_buffer = 0; - if (result == MOJO_RESULT_OK) { - byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size); - } - return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); -} - -static jint EndWriteData(JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - jint num_bytes_written) { - return MojoEndWriteData(mojo_handle, num_bytes_written); -} - -static ScopedJavaLocalRef Duplicate( - JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - const JavaParamRef& options_buffer) { - const MojoDuplicateBufferHandleOptions* options = 0; - if (options_buffer) { - const void* buffer_start = env->GetDirectBufferAddress(options_buffer); - DCHECK(buffer_start); - const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); - DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions)); - options = - static_cast(buffer_start); - DCHECK_EQ(options->struct_size, buffer_size); - } - MojoHandle handle; - MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle); - return Java_CoreImpl_newResultAndInteger(env, result, handle); -} - -static ScopedJavaLocalRef Map(JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - jlong offset, - jlong num_bytes, - jint flags) { - void* buffer = 0; - MojoResult result = - MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags); - jobject byte_buffer = 0; - if (result == MOJO_RESULT_OK) { - byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes); - } - return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); -} - -static int Unmap(JNIEnv* env, - const JavaParamRef& jcaller, - const JavaParamRef& buffer) { - void* buffer_start = env->GetDirectBufferAddress(buffer); - DCHECK(buffer_start); - return MojoUnmapBuffer(buffer_start); -} - -static jint GetNativeBufferOffset(JNIEnv* env, - const JavaParamRef& jcaller, - const JavaParamRef& buffer, - jint alignment) { - jint offset = - reinterpret_cast(env->GetDirectBufferAddress(buffer)) % - alignment; - if (offset == 0) - return 0; - return alignment - offset; -} - -bool RegisterCoreImpl(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace android -} // namespace mojo diff --git a/mojo/android/system/core_impl.h b/mojo/android/system/core_impl.h deleted file mode 100644 index c624999..0000000 --- a/mojo/android/system/core_impl.h +++ /dev/null @@ -1,20 +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_ANDROID_SYSTEM_CORE_IMPL_H_ -#define MOJO_ANDROID_SYSTEM_CORE_IMPL_H_ - -#include - -#include "base/android/jni_android.h" - -namespace mojo { -namespace android { - -JNI_EXPORT bool RegisterCoreImpl(JNIEnv* env); - -} // namespace android -} // namespace mojo - -#endif // MOJO_ANDROID_SYSTEM_CORE_IMPL_H_ diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java b/mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java deleted file mode 100644 index 3db6670..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.mojo.system.impl; - -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.mojo.system.RunLoop; - -/** - * Implementation of {@link RunLoop} suitable for the base:: message loop implementation. - */ -@JNINamespace("mojo::android") -class BaseRunLoop implements RunLoop { - /** - * Pointer to the C run loop. - */ - private long mRunLoopID; - private final CoreImpl mCore; - - BaseRunLoop(CoreImpl core) { - this.mCore = core; - this.mRunLoopID = nativeCreateBaseRunLoop(); - } - - @Override - public void run() { - assert mRunLoopID != 0 : "The run loop cannot run once closed"; - nativeRun(); - } - - @Override - public void runUntilIdle() { - assert mRunLoopID != 0 : "The run loop cannot run once closed"; - nativeRunUntilIdle(); - } - - @Override - public void quit() { - assert mRunLoopID != 0 : "The run loop cannot be quitted run once closed"; - nativeQuit(mRunLoopID); - } - - @Override - public void postDelayedTask(Runnable runnable, long delay) { - assert mRunLoopID != 0 : "The run loop cannot run tasks once closed"; - nativePostDelayedTask(mRunLoopID, runnable, delay); - } - - @Override - public void close() { - if (mRunLoopID == 0) { - return; - } - // We don't want to de-register a different run loop! - assert mCore.getCurrentRunLoop() == this : "Only the current run loop can be closed"; - mCore.clearCurrentRunLoop(); - nativeDeleteMessageLoop(mRunLoopID); - mRunLoopID = 0; - } - - @CalledByNative - private static void runRunnable(Runnable runnable) { - runnable.run(); - } - - private native long nativeCreateBaseRunLoop(); - private native void nativeRun(); - private native void nativeRunUntilIdle(); - private native void nativeQuit(long runLoopID); - private native void nativePostDelayedTask(long runLoopID, Runnable runnable, long delay); - private native void nativeDeleteMessageLoop(long runLoopID); -} 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 deleted file mode 100644 index 173f801..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java +++ /dev/null @@ -1,522 +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.system.impl; - -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.base.annotations.MainDex; -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.Core.HandleSignalsState; -import org.chromium.mojo.system.DataPipe; -import org.chromium.mojo.system.DataPipe.ConsumerHandle; -import org.chromium.mojo.system.DataPipe.ProducerHandle; -import org.chromium.mojo.system.Handle; -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.ResultAnd; -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; -import org.chromium.mojo.system.UntypedHandle; -import org.chromium.mojo.system.Watcher; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.List; - -/** - * Implementation of {@link Core}. - */ -@JNINamespace("mojo::android") -@MainDex -public class CoreImpl implements Core { - /** - * Discard flag for the |MojoReadData| operation. - */ - private static final int MOJO_READ_DATA_FLAG_DISCARD = 1 << 1; - - /** - * the size of a handle, in bytes. - */ - private static final int HANDLE_SIZE = 4; - - /** - * the size of a flag, in bytes. - */ - private static final int FLAG_SIZE = 4; - - /** - * The mojo handle for an invalid handle. - */ - static final int INVALID_HANDLE = 0; - - private static class LazyHolder { private static final Core INSTANCE = new CoreImpl(); } - - /** - * The run loop for the current thread. - */ - private final ThreadLocal mCurrentRunLoop = new ThreadLocal(); - - /** - * The offset needed to get an aligned buffer. - */ - private final int mByteBufferOffset; - - /** - * @return the instance. - */ - public static Core getInstance() { - return LazyHolder.INSTANCE; - } - - private CoreImpl() { - // Fix for the ART runtime, before: - // https://android.googlesource.com/platform/libcore/+/fb6c80875a8a8d0a9628562f89c250b6a962e824%5E!/ - // This assumes consistent allocation. - mByteBufferOffset = nativeGetNativeBufferOffset(ByteBuffer.allocateDirect(8), 8); - } - - /** - * @see Core#getTimeTicksNow() - */ - @Override - public long getTimeTicksNow() { - return nativeGetTimeTicksNow(); - } - - /** - * @see Core#createMessagePipe(MessagePipeHandle.CreateOptions) - */ - @Override - public Pair createMessagePipe( - MessagePipeHandle.CreateOptions options) { - ByteBuffer optionsBuffer = null; - if (options != null) { - optionsBuffer = allocateDirectBuffer(8); - optionsBuffer.putInt(0, 8); - optionsBuffer.putInt(4, options.getFlags().getFlags()); - } - ResultAnd result = nativeCreateMessagePipe(optionsBuffer); - if (result.getMojoResult() != MojoResult.OK) { - throw new MojoException(result.getMojoResult()); - } - return Pair.create( - new MessagePipeHandleImpl(this, result.getValue().first), - new MessagePipeHandleImpl(this, result.getValue().second)); - } - - /** - * @see Core#createDataPipe(DataPipe.CreateOptions) - */ - @Override - public Pair createDataPipe(DataPipe.CreateOptions options) { - ByteBuffer optionsBuffer = null; - if (options != null) { - optionsBuffer = allocateDirectBuffer(16); - optionsBuffer.putInt(0, 16); - optionsBuffer.putInt(4, options.getFlags().getFlags()); - optionsBuffer.putInt(8, options.getElementNumBytes()); - optionsBuffer.putInt(12, options.getCapacityNumBytes()); - } - ResultAnd result = nativeCreateDataPipe(optionsBuffer); - if (result.getMojoResult() != MojoResult.OK) { - throw new MojoException(result.getMojoResult()); - } - return Pair.create( - new DataPipeProducerHandleImpl(this, result.getValue().first), - new DataPipeConsumerHandleImpl(this, result.getValue().second)); - } - - /** - * @see Core#createSharedBuffer(SharedBufferHandle.CreateOptions, long) - */ - @Override - public SharedBufferHandle createSharedBuffer( - SharedBufferHandle.CreateOptions options, long numBytes) { - ByteBuffer optionsBuffer = null; - if (options != null) { - optionsBuffer = allocateDirectBuffer(8); - optionsBuffer.putInt(0, 8); - optionsBuffer.putInt(4, options.getFlags().getFlags()); - } - ResultAnd result = nativeCreateSharedBuffer(optionsBuffer, numBytes); - if (result.getMojoResult() != MojoResult.OK) { - throw new MojoException(result.getMojoResult()); - } - return new SharedBufferHandleImpl(this, result.getValue()); - } - - /** - * @see org.chromium.mojo.system.Core#acquireNativeHandle(int) - */ - @Override - public UntypedHandle acquireNativeHandle(int handle) { - return new UntypedHandleImpl(this, handle); - } - - /** - * @see Core#getWatcher() - */ - @Override - public Watcher getWatcher() { - return new WatcherImpl(); - } - - /** - * @see Core#createDefaultRunLoop() - */ - @Override - public RunLoop createDefaultRunLoop() { - if (mCurrentRunLoop.get() != null) { - throw new MojoException(MojoResult.FAILED_PRECONDITION); - } - BaseRunLoop runLoop = new BaseRunLoop(this); - mCurrentRunLoop.set(runLoop); - return runLoop; - } - - /** - * @see Core#getCurrentRunLoop() - */ - @Override - public RunLoop getCurrentRunLoop() { - return mCurrentRunLoop.get(); - } - - /** - * Remove the current run loop. - */ - void clearCurrentRunLoop() { - mCurrentRunLoop.remove(); - } - - int closeWithResult(int mojoHandle) { - return nativeClose(mojoHandle); - } - - void close(int mojoHandle) { - int mojoResult = nativeClose(mojoHandle); - if (mojoResult != MojoResult.OK) { - throw new MojoException(mojoResult); - } - } - - HandleSignalsState queryHandleSignalsState(int mojoHandle) { - ByteBuffer buffer = allocateDirectBuffer(8); - int result = nativeQueryHandleSignalsState(mojoHandle, buffer); - if (result != MojoResult.OK) throw new MojoException(result); - return new HandleSignalsState( - new HandleSignals(buffer.getInt(0)), new HandleSignals(buffer.getInt(4))); - } - - /** - * @see MessagePipeHandle#writeMessage(ByteBuffer, List, MessagePipeHandle.WriteFlags) - */ - void writeMessage(MessagePipeHandleImpl pipeHandle, ByteBuffer bytes, - List handles, MessagePipeHandle.WriteFlags flags) { - ByteBuffer handlesBuffer = null; - if (handles != null && !handles.isEmpty()) { - handlesBuffer = allocateDirectBuffer(handles.size() * HANDLE_SIZE); - for (Handle handle : handles) { - handlesBuffer.putInt(getMojoHandle(handle)); - } - handlesBuffer.position(0); - } - int mojoResult = nativeWriteMessage(pipeHandle.getMojoHandle(), bytes, - bytes == null ? 0 : bytes.limit(), handlesBuffer, flags.getFlags()); - if (mojoResult != MojoResult.OK) { - throw new MojoException(mojoResult); - } - // Success means the handles have been invalidated. - if (handles != null) { - for (Handle handle : handles) { - if (handle.isValid()) { - ((HandleBase) handle).invalidateHandle(); - } - } - } - } - - /** - * @see MessagePipeHandle#readMessage(ByteBuffer, int, MessagePipeHandle.ReadFlags) - */ - ResultAnd readMessage(MessagePipeHandleImpl handle, - ByteBuffer bytes, int maxNumberOfHandles, MessagePipeHandle.ReadFlags flags) { - ByteBuffer handlesBuffer = null; - if (maxNumberOfHandles > 0) { - handlesBuffer = allocateDirectBuffer(maxNumberOfHandles * HANDLE_SIZE); - } - ResultAnd result = - nativeReadMessage(handle.getMojoHandle(), bytes, handlesBuffer, flags.getFlags()); - if (result.getMojoResult() != MojoResult.OK - && result.getMojoResult() != MojoResult.RESOURCE_EXHAUSTED - && result.getMojoResult() != MojoResult.SHOULD_WAIT) { - throw new MojoException(result.getMojoResult()); - } - - if (result.getMojoResult() == MojoResult.OK) { - MessagePipeHandle.ReadMessageResult readResult = result.getValue(); - if (bytes != null) { - bytes.position(0); - bytes.limit(readResult.getMessageSize()); - } - - List handles = - new ArrayList(readResult.getHandlesCount()); - for (int i = 0; i < readResult.getHandlesCount(); ++i) { - int mojoHandle = handlesBuffer.getInt(HANDLE_SIZE * i); - handles.add(new UntypedHandleImpl(this, mojoHandle)); - } - readResult.setHandles(handles); - } - return result; - } - - /** - * @see ConsumerHandle#discardData(int, DataPipe.ReadFlags) - */ - int discardData(DataPipeConsumerHandleImpl handle, int numBytes, DataPipe.ReadFlags flags) { - ResultAnd result = nativeReadData(handle.getMojoHandle(), null, numBytes, - flags.getFlags() | MOJO_READ_DATA_FLAG_DISCARD); - if (result.getMojoResult() != MojoResult.OK) { - throw new MojoException(result.getMojoResult()); - } - return result.getValue(); - } - - /** - * @see ConsumerHandle#readData(ByteBuffer, DataPipe.ReadFlags) - */ - ResultAnd readData( - DataPipeConsumerHandleImpl handle, ByteBuffer elements, DataPipe.ReadFlags flags) { - ResultAnd result = nativeReadData(handle.getMojoHandle(), elements, - elements == null ? 0 : elements.capacity(), flags.getFlags()); - if (result.getMojoResult() != MojoResult.OK - && result.getMojoResult() != MojoResult.SHOULD_WAIT) { - throw new MojoException(result.getMojoResult()); - } - if (result.getMojoResult() == MojoResult.OK) { - if (elements != null) { - elements.limit(result.getValue()); - } - } - return result; - } - - /** - * @see ConsumerHandle#beginReadData(int, DataPipe.ReadFlags) - */ - ByteBuffer beginReadData( - DataPipeConsumerHandleImpl handle, int numBytes, DataPipe.ReadFlags flags) { - ResultAnd result = - nativeBeginReadData(handle.getMojoHandle(), numBytes, flags.getFlags()); - if (result.getMojoResult() != MojoResult.OK) { - throw new MojoException(result.getMojoResult()); - } - return result.getValue().asReadOnlyBuffer(); - } - - /** - * @see ConsumerHandle#endReadData(int) - */ - void endReadData(DataPipeConsumerHandleImpl handle, int numBytesRead) { - int result = nativeEndReadData(handle.getMojoHandle(), numBytesRead); - if (result != MojoResult.OK) { - throw new MojoException(result); - } - } - - /** - * @see ProducerHandle#writeData(ByteBuffer, DataPipe.WriteFlags) - */ - ResultAnd writeData( - DataPipeProducerHandleImpl handle, ByteBuffer elements, DataPipe.WriteFlags flags) { - return nativeWriteData( - handle.getMojoHandle(), elements, elements.limit(), flags.getFlags()); - } - - /** - * @see ProducerHandle#beginWriteData(int, DataPipe.WriteFlags) - */ - ByteBuffer beginWriteData( - DataPipeProducerHandleImpl handle, int numBytes, DataPipe.WriteFlags flags) { - ResultAnd result = - nativeBeginWriteData(handle.getMojoHandle(), numBytes, flags.getFlags()); - if (result.getMojoResult() != MojoResult.OK) { - throw new MojoException(result.getMojoResult()); - } - return result.getValue(); - } - - /** - * @see ProducerHandle#endWriteData(int) - */ - void endWriteData(DataPipeProducerHandleImpl handle, int numBytesWritten) { - int result = nativeEndWriteData(handle.getMojoHandle(), numBytesWritten); - if (result != MojoResult.OK) { - throw new MojoException(result); - } - } - - /** - * @see SharedBufferHandle#duplicate(DuplicateOptions) - */ - SharedBufferHandle duplicate(SharedBufferHandleImpl handle, DuplicateOptions options) { - ByteBuffer optionsBuffer = null; - if (options != null) { - optionsBuffer = allocateDirectBuffer(8); - optionsBuffer.putInt(0, 8); - optionsBuffer.putInt(4, options.getFlags().getFlags()); - } - ResultAnd result = nativeDuplicate(handle.getMojoHandle(), optionsBuffer); - if (result.getMojoResult() != MojoResult.OK) { - throw new MojoException(result.getMojoResult()); - } - return new SharedBufferHandleImpl(this, result.getValue()); - } - - /** - * @see SharedBufferHandle#map(long, long, MapFlags) - */ - ByteBuffer map(SharedBufferHandleImpl handle, long offset, long numBytes, MapFlags flags) { - ResultAnd result = - nativeMap(handle.getMojoHandle(), offset, numBytes, flags.getFlags()); - if (result.getMojoResult() != MojoResult.OK) { - throw new MojoException(result.getMojoResult()); - } - return result.getValue(); - } - - /** - * @see SharedBufferHandle#unmap(ByteBuffer) - */ - void unmap(ByteBuffer buffer) { - int result = nativeUnmap(buffer); - if (result != MojoResult.OK) { - throw new MojoException(result); - } - } - - /** - * @return the mojo handle associated to the given handle, considering invalid handles. - */ - private int getMojoHandle(Handle handle) { - if (handle.isValid()) { - return ((HandleBase) handle).getMojoHandle(); - } - return 0; - } - - private static boolean isUnrecoverableError(int code) { - switch (code) { - case MojoResult.OK: - case MojoResult.DEADLINE_EXCEEDED: - case MojoResult.CANCELLED: - case MojoResult.FAILED_PRECONDITION: - return false; - default: - return true; - } - } - - private static int filterMojoResultForWait(int code) { - if (isUnrecoverableError(code)) { - throw new MojoException(code); - } - return code; - } - - private ByteBuffer allocateDirectBuffer(int capacity) { - ByteBuffer buffer = ByteBuffer.allocateDirect(capacity + mByteBufferOffset); - if (mByteBufferOffset != 0) { - buffer.position(mByteBufferOffset); - buffer = buffer.slice(); - } - return buffer.order(ByteOrder.nativeOrder()); - } - - @CalledByNative - private static ResultAnd newResultAndBuffer(int mojoResult, ByteBuffer buffer) { - return new ResultAnd<>(mojoResult, buffer); - } - - /** - * Trivial alias for Pair. This is needed because our jni generator is unable - * to handle class that contains space. - */ - private static final class IntegerPair extends Pair { - public IntegerPair(Integer first, Integer second) { - super(first, second); - } - } - - @CalledByNative - private static ResultAnd newReadMessageResult( - int mojoResult, int messageSize, int handlesCount) { - MessagePipeHandle.ReadMessageResult result = new MessagePipeHandle.ReadMessageResult(); - result.setMessageSize(messageSize); - result.setHandlesCount(handlesCount); - return new ResultAnd<>(mojoResult, result); - } - - @CalledByNative - private static ResultAnd newResultAndInteger(int mojoResult, int numBytesRead) { - return new ResultAnd<>(mojoResult, numBytesRead); - } - - @CalledByNative - private static ResultAnd newNativeCreationResult( - int mojoResult, int mojoHandle1, int mojoHandle2) { - return new ResultAnd<>(mojoResult, new IntegerPair(mojoHandle1, mojoHandle2)); - } - - private native long nativeGetTimeTicksNow(); - - private native ResultAnd nativeCreateMessagePipe(ByteBuffer optionsBuffer); - - private native ResultAnd nativeCreateDataPipe(ByteBuffer optionsBuffer); - - private native ResultAnd nativeCreateSharedBuffer( - ByteBuffer optionsBuffer, long numBytes); - - private native int nativeClose(int mojoHandle); - - private native int nativeQueryHandleSignalsState(int mojoHandle, ByteBuffer signalsStateBuffer); - - private native int nativeWriteMessage( - int mojoHandle, ByteBuffer bytes, int numBytes, ByteBuffer handlesBuffer, int flags); - - private native ResultAnd nativeReadMessage( - int mojoHandle, ByteBuffer bytes, ByteBuffer handlesBuffer, int flags); - - private native ResultAnd nativeReadData( - int mojoHandle, ByteBuffer elements, int elementsSize, int flags); - - private native ResultAnd nativeBeginReadData( - int mojoHandle, int numBytes, int flags); - - private native int nativeEndReadData(int mojoHandle, int numBytesRead); - - private native ResultAnd nativeWriteData( - int mojoHandle, ByteBuffer elements, int limit, int flags); - - private native ResultAnd nativeBeginWriteData( - int mojoHandle, int numBytes, int flags); - - private native int nativeEndWriteData(int mojoHandle, int numBytesWritten); - - private native ResultAnd nativeDuplicate(int mojoHandle, ByteBuffer optionsBuffer); - - private native ResultAnd nativeMap( - int mojoHandle, long offset, long numBytes, int flags); - - private native int nativeUnmap(ByteBuffer buffer); - - private native int nativeGetNativeBufferOffset(ByteBuffer buffer, int alignment); -} diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java deleted file mode 100644 index 83097d7..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java +++ /dev/null @@ -1,72 +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.system.impl; - -import org.chromium.mojo.system.DataPipe.ConsumerHandle; -import org.chromium.mojo.system.DataPipe.ReadFlags; -import org.chromium.mojo.system.ResultAnd; - -import java.nio.ByteBuffer; - -/** - * Implementation of {@link ConsumerHandle}. - */ -class DataPipeConsumerHandleImpl extends HandleBase implements ConsumerHandle { - - /** - * @see HandleBase#HandleBase(CoreImpl, int) - */ - DataPipeConsumerHandleImpl(CoreImpl core, int mojoHandle) { - super(core, mojoHandle); - } - - /** - * @see HandleBase#HandleBase(HandleBase) - */ - DataPipeConsumerHandleImpl(HandleBase other) { - super(other); - } - - /** - * @see org.chromium.mojo.system.Handle#pass() - */ - @Override - public ConsumerHandle pass() { - return new DataPipeConsumerHandleImpl(this); - } - - /** - * @see ConsumerHandle#discardData(int, ReadFlags) - */ - @Override - public int discardData(int numBytes, ReadFlags flags) { - return mCore.discardData(this, numBytes, flags); - } - - /** - * @see ConsumerHandle#readData(ByteBuffer, ReadFlags) - */ - @Override - public ResultAnd readData(ByteBuffer elements, ReadFlags flags) { - return mCore.readData(this, elements, flags); - } - - /** - * @see ConsumerHandle#beginReadData(int, ReadFlags) - */ - @Override - public ByteBuffer beginReadData(int numBytes, ReadFlags flags) { - return mCore.beginReadData(this, numBytes, flags); - } - - /** - * @see ConsumerHandle#endReadData(int) - */ - @Override - public void endReadData(int numBytesRead) { - mCore.endReadData(this, numBytesRead); - } - -} diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java deleted file mode 100644 index 901f26c..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java +++ /dev/null @@ -1,64 +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.system.impl; - -import org.chromium.mojo.system.DataPipe.ProducerHandle; -import org.chromium.mojo.system.DataPipe.WriteFlags; -import org.chromium.mojo.system.ResultAnd; - -import java.nio.ByteBuffer; - -/** - * Implementation of {@link ProducerHandle}. - */ -class DataPipeProducerHandleImpl extends HandleBase implements ProducerHandle { - - /** - * @see HandleBase#HandleBase(CoreImpl, int) - */ - DataPipeProducerHandleImpl(CoreImpl core, int mojoHandle) { - super(core, mojoHandle); - } - - /** - * @see HandleBase#HandleBase(HandleBase) - */ - DataPipeProducerHandleImpl(HandleBase handle) { - super(handle); - } - - /** - * @see org.chromium.mojo.system.DataPipe.ProducerHandle#pass() - */ - @Override - public ProducerHandle pass() { - return new DataPipeProducerHandleImpl(this); - } - - /** - * @see ProducerHandle#writeData(ByteBuffer, WriteFlags) - */ - @Override - public ResultAnd writeData(ByteBuffer elements, WriteFlags flags) { - return mCore.writeData(this, elements, flags); - } - - /** - * @see ProducerHandle#beginWriteData(int, WriteFlags) - */ - @Override - public ByteBuffer beginWriteData(int numBytes, WriteFlags flags) { - return mCore.beginWriteData(this, numBytes, flags); - } - - /** - * @see ProducerHandle#endWriteData(int) - */ - @Override - public void endWriteData(int numBytesWritten) { - mCore.endWriteData(this, numBytesWritten); - } - -} diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/HandleBase.java b/mojo/android/system/src/org/chromium/mojo/system/impl/HandleBase.java deleted file mode 100644 index 4d149a4..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/HandleBase.java +++ /dev/null @@ -1,140 +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.system.impl; - -import android.util.Log; - -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.Core.HandleSignalsState; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.UntypedHandle; - -/** - * Implementation of {@link Handle}. - */ -abstract class HandleBase implements Handle { - - private static final String TAG = "HandleImpl"; - - /** - * The pointer to the scoped handle owned by this object. - */ - private int mMojoHandle; - - /** - * The core implementation. Will be used to delegate all behavior. - */ - protected CoreImpl mCore; - - /** - * Base constructor. Takes ownership of the passed handle. - */ - HandleBase(CoreImpl core, int mojoHandle) { - mCore = core; - mMojoHandle = mojoHandle; - } - - /** - * Constructor for transforming {@link HandleBase} into a specific one. It is used to transform - * an {@link UntypedHandle} into a typed one, or any handle into an {@link UntypedHandle}. - */ - protected HandleBase(HandleBase other) { - mCore = other.mCore; - HandleBase otherAsHandleImpl = other; - int mojoHandle = otherAsHandleImpl.mMojoHandle; - otherAsHandleImpl.mMojoHandle = CoreImpl.INVALID_HANDLE; - mMojoHandle = mojoHandle; - } - - /** - * @see org.chromium.mojo.system.Handle#close() - */ - @Override - public void close() { - if (mMojoHandle != CoreImpl.INVALID_HANDLE) { - // After a close, the handle is invalid whether the close succeed or not. - int handle = mMojoHandle; - mMojoHandle = CoreImpl.INVALID_HANDLE; - mCore.close(handle); - } - } - - /** - * @see org.chromium.mojo.system.Handle#querySignalsState() - */ - @Override - public HandleSignalsState querySignalsState() { - return mCore.queryHandleSignalsState(mMojoHandle); - } - - /** - * @see org.chromium.mojo.system.Handle#isValid() - */ - @Override - public boolean isValid() { - return mMojoHandle != CoreImpl.INVALID_HANDLE; - } - - /** - * @see org.chromium.mojo.system.Handle#toUntypedHandle() - */ - @Override - public UntypedHandle toUntypedHandle() { - return new UntypedHandleImpl(this); - } - - /** - * @see org.chromium.mojo.system.Handle#getCore() - */ - @Override - public Core getCore() { - return mCore; - } - - /** - * @see Handle#releaseNativeHandle() - */ - @Override - public int releaseNativeHandle() { - int result = mMojoHandle; - mMojoHandle = CoreImpl.INVALID_HANDLE; - return result; - } - - /** - * Getter for the native scoped handle. - * - * @return the native scoped handle. - */ - int getMojoHandle() { - return mMojoHandle; - } - - /** - * invalidate the handle. The caller must ensures that the handle does not leak. - */ - void invalidateHandle() { - mMojoHandle = CoreImpl.INVALID_HANDLE; - } - - /** - * Close the handle if it is valid. Necessary because we cannot let handle leak, and we cannot - * ensure that every handle will be manually closed. - * - * @see java.lang.Object#finalize() - */ - @Override - protected final void finalize() throws Throwable { - if (isValid()) { - // This should not happen, as the user of this class should close the handle. Adding a - // warning. - Log.w(TAG, "Handle was not closed."); - // Ignore result at this point. - mCore.closeWithResult(mMojoHandle); - } - super.finalize(); - } - -} diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java deleted file mode 100644 index b3df0ae..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java +++ /dev/null @@ -1,58 +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.system.impl; - -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojo.system.ResultAnd; - -import java.nio.ByteBuffer; -import java.util.List; - -/** - * Implementation of {@link MessagePipeHandle}. - */ -class MessagePipeHandleImpl extends HandleBase implements MessagePipeHandle { - - /** - * @see HandleBase#HandleBase(CoreImpl, int) - */ - MessagePipeHandleImpl(CoreImpl core, int mojoHandle) { - super(core, mojoHandle); - } - - /** - * @see HandleBase#HandleBase(HandleBase) - */ - MessagePipeHandleImpl(HandleBase handle) { - super(handle); - } - - /** - * @see org.chromium.mojo.system.MessagePipeHandle#pass() - */ - @Override - public MessagePipeHandle pass() { - return new MessagePipeHandleImpl(this); - } - - /** - * @see MessagePipeHandle#writeMessage(ByteBuffer, List, WriteFlags) - */ - @Override - public void writeMessage(ByteBuffer bytes, List handles, WriteFlags flags) { - mCore.writeMessage(this, bytes, handles, flags); - } - - /** - * @see MessagePipeHandle#readMessage(ByteBuffer, int, ReadFlags) - */ - @Override - public ResultAnd readMessage( - ByteBuffer bytes, int maxNumberOfHandles, ReadFlags flags) { - return mCore.readMessage(this, bytes, maxNumberOfHandles, flags); - } - -} diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java deleted file mode 100644 index 76ef739..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java +++ /dev/null @@ -1,62 +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.system.impl; - -import org.chromium.mojo.system.SharedBufferHandle; - -import java.nio.ByteBuffer; - -/** - * Implementation of {@link SharedBufferHandle}. - */ -class SharedBufferHandleImpl extends HandleBase implements SharedBufferHandle { - - /** - * @see HandleBase#HandleBase(CoreImpl, int) - */ - SharedBufferHandleImpl(CoreImpl core, int mojoHandle) { - super(core, mojoHandle); - } - - /** - * @see HandleBase#HandleBase(HandleBase) - */ - SharedBufferHandleImpl(HandleBase handle) { - super(handle); - } - - /** - * @see org.chromium.mojo.system.SharedBufferHandle#pass() - */ - @Override - public SharedBufferHandle pass() { - return new SharedBufferHandleImpl(this); - } - - /** - * @see SharedBufferHandle#duplicate(DuplicateOptions) - */ - @Override - public SharedBufferHandle duplicate(DuplicateOptions options) { - return mCore.duplicate(this, options); - } - - /** - * @see SharedBufferHandle#map(long, long, MapFlags) - */ - @Override - public ByteBuffer map(long offset, long numBytes, MapFlags flags) { - return mCore.map(this, offset, numBytes, flags); - } - - /** - * @see SharedBufferHandle#unmap(ByteBuffer) - */ - @Override - public void unmap(ByteBuffer buffer) { - mCore.unmap(buffer); - } - -} diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java deleted file mode 100644 index 4774ab8..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java +++ /dev/null @@ -1,72 +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.system.impl; - -import org.chromium.mojo.system.DataPipe.ConsumerHandle; -import org.chromium.mojo.system.DataPipe.ProducerHandle; -import org.chromium.mojo.system.MessagePipeHandle; -import org.chromium.mojo.system.SharedBufferHandle; -import org.chromium.mojo.system.UntypedHandle; - -/** - * Implementation of {@link UntypedHandle}. - */ -class UntypedHandleImpl extends HandleBase implements UntypedHandle { - - /** - * @see HandleBase#HandleBase(CoreImpl, int) - */ - UntypedHandleImpl(CoreImpl core, int mojoHandle) { - super(core, mojoHandle); - } - - /** - * @see HandleBase#HandleBase(HandleBase) - */ - UntypedHandleImpl(HandleBase handle) { - super(handle); - } - - /** - * @see org.chromium.mojo.system.UntypedHandle#pass() - */ - @Override - public UntypedHandle pass() { - return new UntypedHandleImpl(this); - } - - /** - * @see org.chromium.mojo.system.UntypedHandle#toMessagePipeHandle() - */ - @Override - public MessagePipeHandle toMessagePipeHandle() { - return new MessagePipeHandleImpl(this); - } - - /** - * @see org.chromium.mojo.system.UntypedHandle#toDataPipeConsumerHandle() - */ - @Override - public ConsumerHandle toDataPipeConsumerHandle() { - return new DataPipeConsumerHandleImpl(this); - } - - /** - * @see org.chromium.mojo.system.UntypedHandle#toDataPipeProducerHandle() - */ - @Override - public ProducerHandle toDataPipeProducerHandle() { - return new DataPipeProducerHandleImpl(this); - } - - /** - * @see org.chromium.mojo.system.UntypedHandle#toSharedBufferHandle() - */ - @Override - public SharedBufferHandle toSharedBufferHandle() { - return new SharedBufferHandleImpl(this); - } - -} diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java deleted file mode 100644 index 094ad90..0000000 --- a/mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.mojo.system.impl; - -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.mojo.system.Core; -import org.chromium.mojo.system.Handle; -import org.chromium.mojo.system.MojoResult; -import org.chromium.mojo.system.Watcher; - -@JNINamespace("mojo::android") -class WatcherImpl implements Watcher { - private long mImplPtr = nativeCreateWatcher(); - private Callback mCallback; - - @Override - public int start(Handle handle, Core.HandleSignals signals, Callback callback) { - if (mImplPtr == 0) { - return MojoResult.INVALID_ARGUMENT; - } - if (!(handle instanceof HandleBase)) { - return MojoResult.INVALID_ARGUMENT; - } - int result = - nativeStart(mImplPtr, ((HandleBase) handle).getMojoHandle(), signals.getFlags()); - if (result == MojoResult.OK) mCallback = callback; - return result; - } - - @Override - public void cancel() { - if (mImplPtr == 0) { - return; - } - mCallback = null; - nativeCancel(mImplPtr); - } - - @Override - public void destroy() { - if (mImplPtr == 0) { - return; - } - nativeDelete(mImplPtr); - mImplPtr = 0; - } - - @CalledByNative - private void onHandleReady(int result) { - mCallback.onResult(result); - } - - private native long nativeCreateWatcher(); - - private native int nativeStart(long implPtr, int mojoHandle, int flags); - - private native void nativeCancel(long implPtr); - - private native void nativeDelete(long implPtr); -} diff --git a/mojo/android/system/watcher_impl.cc b/mojo/android/system/watcher_impl.cc deleted file mode 100644 index 3344447..0000000 --- a/mojo/android/system/watcher_impl.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/android/system/watcher_impl.h" - -#include -#include - -// Removed unused headers. TODO(hidehiko): Upstream. -// #include "base/android/base_jni_registrar.h" -#include "base/android/jni_android.h" -// #include "base/android/jni_registrar.h" -// #include "base/android/library_loader/library_loader_hooks.h" -#include "base/android/scoped_java_ref.h" -#include "base/bind.h" -#include "jni/WatcherImpl_jni.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/simple_watcher.h" - -namespace mojo { -namespace android { - -using base::android::JavaParamRef; - -namespace { - -class WatcherImpl { - public: - WatcherImpl() : watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC) {} - - ~WatcherImpl() = default; - - jint Start(JNIEnv* env, - const JavaParamRef& jcaller, - jint mojo_handle, - jint signals) { - java_watcher_.Reset(env, jcaller); - - auto ready_callback = - base::Bind(&WatcherImpl::OnHandleReady, base::Unretained(this)); - - MojoResult result = - watcher_.Watch(mojo::Handle(static_cast(mojo_handle)), - static_cast(signals), ready_callback); - if (result != MOJO_RESULT_OK) - java_watcher_.Reset(); - - return result; - } - - void Cancel() { - java_watcher_.Reset(); - watcher_.Cancel(); - } - - private: - void OnHandleReady(MojoResult result) { - DCHECK(!java_watcher_.is_null()); - - base::android::ScopedJavaGlobalRef java_watcher_preserver; - if (result == MOJO_RESULT_CANCELLED) - java_watcher_preserver = std::move(java_watcher_); - - Java_WatcherImpl_onHandleReady( - base::android::AttachCurrentThread(), - java_watcher_.is_null() ? java_watcher_preserver : java_watcher_, - result); - } - - SimpleWatcher watcher_; - base::android::ScopedJavaGlobalRef java_watcher_; - - DISALLOW_COPY_AND_ASSIGN(WatcherImpl); -}; - -} // namespace - -static jlong CreateWatcher(JNIEnv* env, const JavaParamRef& jcaller) { - return reinterpret_cast(new WatcherImpl); -} - -static jint Start(JNIEnv* env, - const JavaParamRef& jcaller, - jlong watcher_ptr, - jint mojo_handle, - jint signals) { - auto* watcher = reinterpret_cast(watcher_ptr); - return watcher->Start(env, jcaller, mojo_handle, signals); -} - -static void Cancel(JNIEnv* env, - const JavaParamRef& jcaller, - jlong watcher_ptr) { - reinterpret_cast(watcher_ptr)->Cancel(); -} - -static void Delete(JNIEnv* env, - const JavaParamRef& jcaller, - jlong watcher_ptr) { - delete reinterpret_cast(watcher_ptr); -} - -bool RegisterWatcherImpl(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace android -} // namespace mojo diff --git a/mojo/android/system/watcher_impl.h b/mojo/android/system/watcher_impl.h deleted file mode 100644 index 784f007..0000000 --- a/mojo/android/system/watcher_impl.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_ANDROID_SYSTEM_WATCHER_IMPL_H_ -#define MOJO_ANDROID_SYSTEM_WATCHER_IMPL_H_ - -#include - -#include "base/android/jni_android.h" - -namespace mojo { -namespace android { - -JNI_EXPORT bool RegisterWatcherImpl(JNIEnv* env); - -} // namespace android -} // namespace mojo - -#endif // MOJO_ANDROID_SYSTEM_WATCHER_IMPL_H_ diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn deleted file mode 100644 index 9e74e58..0000000 --- a/mojo/common/BUILD.gn +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/tools/bindings/mojom.gni") -import("//testing/test.gni") - -group("common") { - public_deps = [ - ":common_base", - ":common_custom_types", - ] -} - -mojom("common_custom_types") { - sources = [ - "file.mojom", - "file_path.mojom", - "string16.mojom", - "text_direction.mojom", - "time.mojom", - "unguessable_token.mojom", - "values.mojom", - "version.mojom", - ] -} - -component("common_base") { - output_name = "mojo_common_lib" - - sources = [ - "data_pipe_drainer.cc", - "data_pipe_drainer.h", - "data_pipe_utils.cc", - "data_pipe_utils.h", - ] - - defines = [ "MOJO_COMMON_IMPLEMENTATION" ] - - public_deps = [ - "//base", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - ] -} - -mojom("test_common_custom_types") { - sources = [ - "test_common_custom_types.mojom", - "traits_test_service.mojom", - ] - public_deps = [ - ":common_custom_types", - ] -} - -test("mojo_common_unittests") { - deps = [ - ":common", - ":common_custom_types", - ":struct_traits", - ":test_common_custom_types", - "//base", - "//base:message_loop_tests", - "//base/test:test_support", - "//mojo/edk/test:run_all_unittests", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/test_support:test_utils", - "//testing/gtest", - "//url", - ] - - sources = [ - "common_custom_types_unittest.cc", - "struct_traits_unittest.cc", - ] -} - -source_set("struct_traits") { - sources = [ - "common_custom_types_struct_traits.cc", - "common_custom_types_struct_traits.h", - ] - deps = [ - ":common_custom_types_shared_cpp_sources", - "//base:base", - "//mojo/public/cpp/system", - ] - public_deps = [ - "//base:i18n", - ] -} diff --git a/mojo/common/DEPS b/mojo/common/DEPS deleted file mode 100644 index e8ac428..0000000 --- a/mojo/common/DEPS +++ /dev/null @@ -1,6 +0,0 @@ -include_rules = [ - # common must not depend on embedder. - "-mojo", - "+mojo/common", - "+mojo/public", -] diff --git a/mojo/common/common_custom_types_struct_traits.cc b/mojo/common/common_custom_types_struct_traits.cc deleted file mode 100644 index 6289504..0000000 --- a/mojo/common/common_custom_types_struct_traits.cc +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/common/common_custom_types_struct_traits.h" - -#include "mojo/public/cpp/system/platform_handle.h" - -namespace mojo { - -// static -bool StructTraits::Read( - common::mojom::String16DataView data, - base::string16* out) { - ArrayDataView view; - data.GetDataDataView(&view); - out->assign(reinterpret_cast(view.data()), view.size()); - return true; -} - -// static -const std::vector& -StructTraits::components( - const base::Version& version) { - return version.components(); -} - -// static -bool StructTraits::Read( - common::mojom::VersionDataView data, - base::Version* out) { - std::vector components; - if (!data.ReadComponents(&components)) - return false; - - *out = base::Version(base::Version(std::move(components))); - return out->IsValid(); -} - -// static -bool StructTraits< - common::mojom::UnguessableTokenDataView, - base::UnguessableToken>::Read(common::mojom::UnguessableTokenDataView data, - base::UnguessableToken* out) { - uint64_t high = data.high(); - uint64_t low = data.low(); - - // Receiving a zeroed UnguessableToken is a security issue. - if (high == 0 && low == 0) - return false; - - *out = base::UnguessableToken::Deserialize(high, low); - return true; -} - -mojo::ScopedHandle StructTraits::fd( - base::File& file) { - DCHECK(file.IsValid()); - return mojo::WrapPlatformFile(file.TakePlatformFile()); -} - -bool StructTraits::Read( - common::mojom::FileDataView data, - base::File* file) { - base::PlatformFile platform_handle = base::kInvalidPlatformFile; - if (mojo::UnwrapPlatformFile(data.TakeFd(), &platform_handle) != - MOJO_RESULT_OK) { - return false; - } - *file = base::File(platform_handle); - return true; -} - -// static -common::mojom::TextDirection -EnumTraits::ToMojom( - base::i18n::TextDirection text_direction) { - switch (text_direction) { - case base::i18n::UNKNOWN_DIRECTION: - return common::mojom::TextDirection::UNKNOWN_DIRECTION; - case base::i18n::RIGHT_TO_LEFT: - return common::mojom::TextDirection::RIGHT_TO_LEFT; - case base::i18n::LEFT_TO_RIGHT: - return common::mojom::TextDirection::LEFT_TO_RIGHT; - } - NOTREACHED(); - return common::mojom::TextDirection::UNKNOWN_DIRECTION; -} - -// static -bool EnumTraits:: - FromMojom(common::mojom::TextDirection input, - base::i18n::TextDirection* out) { - switch (input) { - case common::mojom::TextDirection::UNKNOWN_DIRECTION: - *out = base::i18n::UNKNOWN_DIRECTION; - return true; - case common::mojom::TextDirection::RIGHT_TO_LEFT: - *out = base::i18n::RIGHT_TO_LEFT; - return true; - case common::mojom::TextDirection::LEFT_TO_RIGHT: - *out = base::i18n::LEFT_TO_RIGHT; - return true; - } - return false; -} - -} // namespace mojo diff --git a/mojo/common/common_custom_types_struct_traits.h b/mojo/common/common_custom_types_struct_traits.h deleted file mode 100644 index 85815ff..0000000 --- a/mojo/common/common_custom_types_struct_traits.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_ -#define MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_ - -#include "base/files/file.h" -#include "base/i18n/rtl.h" -#include "base/strings/utf_string_conversions.h" -#include "base/unguessable_token.h" -#include "base/version.h" -#include "mojo/common/file.mojom-shared.h" -#include "mojo/common/mojo_common_export.h" -#include "mojo/common/string16.mojom-shared.h" -#include "mojo/common/text_direction.mojom-shared.h" -#include "mojo/common/time.mojom-shared.h" -#include "mojo/common/unguessable_token.mojom-shared.h" -#include "mojo/common/version.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits { - static ConstCArray data(const base::string16& str) { - return ConstCArray(str.size(), - reinterpret_cast(str.data())); - } - - static bool Read(common::mojom::String16DataView data, base::string16* out); -}; - -template <> -struct StructTraits { - static bool IsNull(const base::Version& version) { - return !version.IsValid(); - } - static void SetToNull(base::Version* out) { - *out = base::Version(std::string()); - } - static const std::vector& components(const base::Version& version); - static bool Read(common::mojom::VersionDataView data, base::Version* out); -}; - -// If base::UnguessableToken is no longer 128 bits, the logic below and the -// mojom::UnguessableToken type should be updated. -static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t), - "base::UnguessableToken should be of size 2 * sizeof(uint64_t)."); - -template <> -struct StructTraits { - static uint64_t high(const base::UnguessableToken& token) { - return token.GetHighForSerialization(); - } - - static uint64_t low(const base::UnguessableToken& token) { - return token.GetLowForSerialization(); - } - - static bool Read(common::mojom::UnguessableTokenDataView data, - base::UnguessableToken* out); -}; - -template <> -struct StructTraits { - static bool IsNull(const base::File& file) { return !file.IsValid(); } - - static void SetToNull(base::File* file) { *file = base::File(); } - - static mojo::ScopedHandle fd(base::File& file); - static bool Read(common::mojom::FileDataView data, base::File* file); -}; - -template <> -struct EnumTraits { - static common::mojom::TextDirection ToMojom( - base::i18n::TextDirection text_direction); - static bool FromMojom(common::mojom::TextDirection input, - base::i18n::TextDirection* out); -}; - -} // namespace mojo - -#endif // MOJO_COMMON_COMMON_CUSTOM_TYPES_STRUCT_TRAITS_H_ diff --git a/mojo/common/common_custom_types_unittest.cc b/mojo/common/common_custom_types_unittest.cc deleted file mode 100644 index e3571d9..0000000 --- a/mojo/common/common_custom_types_unittest.cc +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/numerics/safe_math.h" -#include "base/run_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "mojo/common/test_common_custom_types.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace common { -namespace test { -namespace { - -template -struct BounceTestTraits { - static void ExpectEquality(const T& a, const T& b) { - EXPECT_EQ(a, b); - } -}; - -template -struct PassTraits { - using Type = const T&; -}; - -template <> -struct PassTraits { - using Type = base::Time; -}; - -template <> -struct PassTraits { - using Type = base::TimeDelta; -}; - -template <> -struct PassTraits { - using Type = base::TimeTicks; -}; - -template -void DoExpectResponse(T* expected_value, - const base::Closure& closure, - typename PassTraits::Type value) { - BounceTestTraits::ExpectEquality(*expected_value, value); - closure.Run(); -} - -template -base::Callback::Type)> ExpectResponse( - T* expected_value, - const base::Closure& closure) { - return base::Bind(&DoExpectResponse, expected_value, closure); -} - -class TestFilePathImpl : public TestFilePath { - public: - explicit TestFilePathImpl(TestFilePathRequest request) - : binding_(this, std::move(request)) {} - - // TestFilePath implementation: - void BounceFilePath(const base::FilePath& in, - const BounceFilePathCallback& callback) override { - callback.Run(in); - } - - private: - mojo::Binding binding_; -}; - -class TestUnguessableTokenImpl : public TestUnguessableToken { - public: - explicit TestUnguessableTokenImpl(TestUnguessableTokenRequest request) - : binding_(this, std::move(request)) {} - - // TestUnguessableToken implementation: - void BounceNonce(const base::UnguessableToken& in, - const BounceNonceCallback& callback) override { - callback.Run(in); - } - - private: - mojo::Binding binding_; -}; - -class TestTimeImpl : public TestTime { - public: - explicit TestTimeImpl(TestTimeRequest request) - : binding_(this, std::move(request)) {} - - // TestTime implementation: - void BounceTime(base::Time in, const BounceTimeCallback& callback) override { - callback.Run(in); - } - - void BounceTimeDelta(base::TimeDelta in, - const BounceTimeDeltaCallback& callback) override { - callback.Run(in); - } - - void BounceTimeTicks(base::TimeTicks in, - const BounceTimeTicksCallback& callback) override { - callback.Run(in); - } - - private: - mojo::Binding binding_; -}; - -class TestValueImpl : public TestValue { - public: - explicit TestValueImpl(TestValueRequest request) - : binding_(this, std::move(request)) {} - - // TestValue implementation: - void BounceDictionaryValue( - std::unique_ptr in, - const BounceDictionaryValueCallback& callback) override { - callback.Run(std::move(in)); - } - - void BounceListValue(std::unique_ptr in, - const BounceListValueCallback& callback) override { - callback.Run(std::move(in)); - } - - void BounceValue(std::unique_ptr in, - const BounceValueCallback& callback) override { - callback.Run(std::move(in)); - } - - private: - mojo::Binding binding_; -}; - -class TestString16Impl : public TestString16 { - public: - explicit TestString16Impl(TestString16Request request) - : binding_(this, std::move(request)) {} - - // TestString16 implementation: - void BounceString16(const base::string16& in, - const BounceString16Callback& callback) override { - callback.Run(in); - } - - private: - mojo::Binding binding_; -}; - -class TestFileImpl : public TestFile { - public: - explicit TestFileImpl(TestFileRequest request) - : binding_(this, std::move(request)) {} - - // TestFile implementation: - void BounceFile(base::File in, const BounceFileCallback& callback) override { - callback.Run(std::move(in)); - } - - private: - mojo::Binding binding_; -}; - -class TestTextDirectionImpl : public TestTextDirection { - public: - explicit TestTextDirectionImpl(TestTextDirectionRequest request) - : binding_(this, std::move(request)) {} - - // TestTextDirection: - void BounceTextDirection( - base::i18n::TextDirection in, - const BounceTextDirectionCallback& callback) override { - callback.Run(in); - } - - private: - mojo::Binding binding_; -}; - -class CommonCustomTypesTest : public testing::Test { - protected: - CommonCustomTypesTest() {} - ~CommonCustomTypesTest() override {} - - private: - base::MessageLoop message_loop_; - - DISALLOW_COPY_AND_ASSIGN(CommonCustomTypesTest); -}; - -} // namespace - -TEST_F(CommonCustomTypesTest, FilePath) { - base::RunLoop run_loop; - - TestFilePathPtr ptr; - TestFilePathImpl impl(MakeRequest(&ptr)); - - base::FilePath dir(FILE_PATH_LITERAL("hello")); - base::FilePath file = dir.Append(FILE_PATH_LITERAL("world")); - - ptr->BounceFilePath(file, ExpectResponse(&file, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, UnguessableToken) { - base::RunLoop run_loop; - - TestUnguessableTokenPtr ptr; - TestUnguessableTokenImpl impl(MakeRequest(&ptr)); - - base::UnguessableToken token = base::UnguessableToken::Create(); - - ptr->BounceNonce(token, ExpectResponse(&token, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, Time) { - base::RunLoop run_loop; - - TestTimePtr ptr; - TestTimeImpl impl(MakeRequest(&ptr)); - - base::Time t = base::Time::Now(); - - ptr->BounceTime(t, ExpectResponse(&t, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, TimeDelta) { - base::RunLoop run_loop; - - TestTimePtr ptr; - TestTimeImpl impl(MakeRequest(&ptr)); - - base::TimeDelta t = base::TimeDelta::FromDays(123); - - ptr->BounceTimeDelta(t, ExpectResponse(&t, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, TimeTicks) { - base::RunLoop run_loop; - - TestTimePtr ptr; - TestTimeImpl impl(MakeRequest(&ptr)); - - base::TimeTicks t = base::TimeTicks::Now(); - - ptr->BounceTimeTicks(t, ExpectResponse(&t, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, Value) { - TestValuePtr ptr; - TestValueImpl impl(MakeRequest(&ptr)); - - std::unique_ptr output; - - ASSERT_TRUE(ptr->BounceValue(nullptr, &output)); - EXPECT_FALSE(output); - - std::unique_ptr input = base::Value::CreateNullValue(); - ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); - EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); - - input = base::MakeUnique(123); - ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); - EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); - - input = base::MakeUnique(1.23); - ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); - EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); - - input = base::MakeUnique(false); - ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); - EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); - - input = base::MakeUnique("test string"); - ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); - EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); - - input = base::BinaryValue::CreateWithCopiedBuffer("mojo", 4); - ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); - EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); - - auto dict = base::MakeUnique(); - dict->SetBoolean("bool", false); - dict->SetInteger("int", 2); - dict->SetString("string", "some string"); - dict->SetBoolean("nested.bool", true); - dict->SetInteger("nested.int", 9); - dict->Set("some_binary", - base::BinaryValue::CreateWithCopiedBuffer("mojo", 4)); - dict->Set("null_value", base::Value::CreateNullValue()); - dict->SetIntegerWithoutPathExpansion("non_nested.int", 10); - { - std::unique_ptr dict_list(new base::ListValue()); - dict_list->AppendString("string"); - dict_list->AppendBoolean(true); - dict->Set("list", std::move(dict_list)); - } - - std::unique_ptr dict_output; - ASSERT_TRUE(ptr->BounceDictionaryValue(dict->CreateDeepCopy(), &dict_output)); - EXPECT_TRUE(base::Value::Equals(dict.get(), dict_output.get())); - - input = std::move(dict); - ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); - EXPECT_TRUE(base::Value::Equals(input.get(), output.get())); - - auto list = base::MakeUnique(); - list->AppendString("string"); - list->AppendDouble(42.1); - list->AppendBoolean(true); - list->Append(base::BinaryValue::CreateWithCopiedBuffer("mojo", 4)); - list->Append(base::Value::CreateNullValue()); - { - std::unique_ptr list_dict( - new base::DictionaryValue()); - list_dict->SetString("string", "str"); - list->Append(std::move(list_dict)); - } - std::unique_ptr list_output; - ASSERT_TRUE(ptr->BounceListValue(list->CreateDeepCopy(), &list_output)); - EXPECT_TRUE(base::Value::Equals(list.get(), list_output.get())); - - input = std::move(list); - ASSERT_TRUE(ptr->BounceValue(input->CreateDeepCopy(), &output)); - ASSERT_TRUE(base::Value::Equals(input.get(), output.get())); -} - -TEST_F(CommonCustomTypesTest, String16) { - base::RunLoop run_loop; - - TestString16Ptr ptr; - TestString16Impl impl(MakeRequest(&ptr)); - - base::string16 str16 = base::ASCIIToUTF16("hello world"); - - ptr->BounceString16(str16, ExpectResponse(&str16, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, EmptyString16) { - base::RunLoop run_loop; - - TestString16Ptr ptr; - TestString16Impl impl(MakeRequest(&ptr)); - - base::string16 str16; - - ptr->BounceString16(str16, ExpectResponse(&str16, run_loop.QuitClosure())); - - run_loop.Run(); -} - -TEST_F(CommonCustomTypesTest, File) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - TestFilePtr ptr; - TestFileImpl impl(MakeRequest(&ptr)); - - base::File file( - temp_dir.GetPath().AppendASCII("test_file.txt"), - base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ); - const base::StringPiece test_content = - "A test string to be stored in a test file"; - file.WriteAtCurrentPos( - test_content.data(), - base::CheckedNumeric(test_content.size()).ValueOrDie()); - - base::File file_out; - ASSERT_TRUE(ptr->BounceFile(std::move(file), &file_out)); - std::vector content(test_content.size()); - ASSERT_TRUE(file_out.IsValid()); - ASSERT_EQ(static_cast(test_content.size()), - file_out.Read( - 0, content.data(), - base::CheckedNumeric(test_content.size()).ValueOrDie())); - EXPECT_EQ(test_content, - base::StringPiece(content.data(), test_content.size())); -} - -TEST_F(CommonCustomTypesTest, InvalidFile) { - TestFilePtr ptr; - TestFileImpl impl(MakeRequest(&ptr)); - - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - // Test that |file_out| is set to an invalid file. - base::File file_out( - temp_dir.GetPath().AppendASCII("test_file.txt"), - base::File::FLAG_CREATE | base::File::FLAG_WRITE | base::File::FLAG_READ); - - ASSERT_TRUE(ptr->BounceFile(base::File(), &file_out)); - EXPECT_FALSE(file_out.IsValid()); -} - -TEST_F(CommonCustomTypesTest, TextDirection) { - base::i18n::TextDirection kTestDirections[] = {base::i18n::LEFT_TO_RIGHT, - base::i18n::RIGHT_TO_LEFT, - base::i18n::UNKNOWN_DIRECTION}; - - TestTextDirectionPtr ptr; - TestTextDirectionImpl impl(MakeRequest(&ptr)); - - for (size_t i = 0; i < arraysize(kTestDirections); i++) { - base::i18n::TextDirection direction_out; - ASSERT_TRUE(ptr->BounceTextDirection(kTestDirections[i], &direction_out)); - EXPECT_EQ(kTestDirections[i], direction_out); - } -} - -} // namespace test -} // namespace common -} // namespace mojo diff --git a/mojo/common/data_pipe_drainer.cc b/mojo/common/data_pipe_drainer.cc deleted file mode 100644 index e705c8d..0000000 --- a/mojo/common/data_pipe_drainer.cc +++ /dev/null @@ -1,50 +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/common/data_pipe_drainer.h" - -#include - -#include - -#include "base/bind.h" - -namespace mojo { -namespace common { - -DataPipeDrainer::DataPipeDrainer(Client* client, - mojo::ScopedDataPipeConsumerHandle source) - : client_(client), - source_(std::move(source)), - handle_watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC), - weak_factory_(this) { - DCHECK(client_); - handle_watcher_.Watch( - source_.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&DataPipeDrainer::WaitComplete, weak_factory_.GetWeakPtr())); -} - -DataPipeDrainer::~DataPipeDrainer() {} - -void DataPipeDrainer::ReadData() { - const void* buffer = nullptr; - uint32_t num_bytes = 0; - MojoResult rv = BeginReadDataRaw(source_.get(), &buffer, &num_bytes, - MOJO_READ_DATA_FLAG_NONE); - if (rv == MOJO_RESULT_OK) { - client_->OnDataAvailable(buffer, num_bytes); - EndReadDataRaw(source_.get(), num_bytes); - } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) { - client_->OnDataComplete(); - } else if (rv != MOJO_RESULT_SHOULD_WAIT) { - DCHECK(false) << "Unhandled MojoResult: " << rv; - } -} - -void DataPipeDrainer::WaitComplete(MojoResult result) { - ReadData(); -} - -} // namespace common -} // namespace mojo diff --git a/mojo/common/data_pipe_drainer.h b/mojo/common/data_pipe_drainer.h deleted file mode 100644 index 5cff820..0000000 --- a/mojo/common/data_pipe_drainer.h +++ /dev/null @@ -1,49 +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_COMMON_DATA_PIPE_DRAINER_H_ -#define MOJO_COMMON_DATA_PIPE_DRAINER_H_ - -#include - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "mojo/common/mojo_common_export.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/simple_watcher.h" - -namespace mojo { -namespace common { - -class MOJO_COMMON_EXPORT DataPipeDrainer { - public: - class Client { - public: - virtual void OnDataAvailable(const void* data, size_t num_bytes) = 0; - virtual void OnDataComplete() = 0; - - protected: - virtual ~Client() {} - }; - - DataPipeDrainer(Client*, mojo::ScopedDataPipeConsumerHandle source); - ~DataPipeDrainer(); - - private: - void ReadData(); - void WaitComplete(MojoResult result); - - Client* client_; - mojo::ScopedDataPipeConsumerHandle source_; - mojo::SimpleWatcher handle_watcher_; - - base::WeakPtrFactory weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(DataPipeDrainer); -}; - -} // namespace common -} // namespace mojo - -#endif // MOJO_COMMON_DATA_PIPE_DRAINER_H_ diff --git a/mojo/common/data_pipe_utils.cc b/mojo/common/data_pipe_utils.cc deleted file mode 100644 index 9b069b8..0000000 --- a/mojo/common/data_pipe_utils.cc +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/common/data_pipe_utils.h" - -#include - -#include "base/bind.h" -#include "mojo/public/cpp/system/wait.h" - -namespace mojo { -namespace common { -namespace { - -bool BlockingCopyHelper(ScopedDataPipeConsumerHandle source, - const base::Callback& write_bytes) { - for (;;) { - const void* buffer; - uint32_t num_bytes; - MojoResult result = BeginReadDataRaw( - source.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); - if (result == MOJO_RESULT_OK) { - size_t bytes_written = write_bytes.Run(buffer, num_bytes); - result = EndReadDataRaw(source.get(), num_bytes); - if (bytes_written < num_bytes || result != MOJO_RESULT_OK) - return false; - } else if (result == MOJO_RESULT_SHOULD_WAIT) { - result = Wait(source.get(), MOJO_HANDLE_SIGNAL_READABLE); - if (result != MOJO_RESULT_OK) { - // If the producer handle was closed, then treat as EOF. - return result == MOJO_RESULT_FAILED_PRECONDITION; - } - } else if (result == MOJO_RESULT_FAILED_PRECONDITION) { - // If the producer handle was closed, then treat as EOF. - return true; - } else { - // Some other error occurred. - break; - } - } - - return false; -} - -size_t CopyToStringHelper( - std::string* result, const void* buffer, uint32_t num_bytes) { - result->append(static_cast(buffer), num_bytes); - return num_bytes; -} - -} // namespace - -// TODO(hansmuller): Add a max_size parameter. -bool BlockingCopyToString(ScopedDataPipeConsumerHandle source, - std::string* result) { - CHECK(result); - result->clear(); - return BlockingCopyHelper(std::move(source), - base::Bind(&CopyToStringHelper, result)); -} - -bool MOJO_COMMON_EXPORT BlockingCopyFromString( - const std::string& source, - const ScopedDataPipeProducerHandle& destination) { - auto it = source.begin(); - for (;;) { - void* buffer = nullptr; - uint32_t buffer_num_bytes = 0; - MojoResult result = - BeginWriteDataRaw(destination.get(), &buffer, &buffer_num_bytes, - MOJO_WRITE_DATA_FLAG_NONE); - if (result == MOJO_RESULT_OK) { - char* char_buffer = static_cast(buffer); - uint32_t byte_index = 0; - while (it != source.end() && byte_index < buffer_num_bytes) { - char_buffer[byte_index++] = *it++; - } - EndWriteDataRaw(destination.get(), byte_index); - if (it == source.end()) - return true; - } else if (result == MOJO_RESULT_SHOULD_WAIT) { - result = Wait(destination.get(), MOJO_HANDLE_SIGNAL_WRITABLE); - if (result != MOJO_RESULT_OK) { - // If the consumer handle was closed, then treat as EOF. - return result == MOJO_RESULT_FAILED_PRECONDITION; - } - } else { - // If the consumer handle was closed, then treat as EOF. - return result == MOJO_RESULT_FAILED_PRECONDITION; - } - } -} - -} // namespace common -} // namespace mojo diff --git a/mojo/common/data_pipe_utils.h b/mojo/common/data_pipe_utils.h deleted file mode 100644 index a3f7c09..0000000 --- a/mojo/common/data_pipe_utils.h +++ /dev/null @@ -1,32 +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_COMMON_DATA_PIPE_UTILS_H_ -#define MOJO_COMMON_DATA_PIPE_UTILS_H_ - -#include - -#include - -#include "mojo/common/mojo_common_export.h" -#include "mojo/public/cpp/system/data_pipe.h" - -namespace mojo { -namespace common { - -// Copies the data from |source| into |contents| and returns true on success and -// false on error. In case of I/O error, |contents| holds the data that could -// be read from source before the error occurred. -bool MOJO_COMMON_EXPORT BlockingCopyToString( - ScopedDataPipeConsumerHandle source, - std::string* contents); - -bool MOJO_COMMON_EXPORT BlockingCopyFromString( - const std::string& source, - const ScopedDataPipeProducerHandle& destination); - -} // namespace common -} // namespace mojo - -#endif // MOJO_COMMON_DATA_PIPE_UTILS_H_ diff --git a/mojo/common/file.mojom b/mojo/common/file.mojom deleted file mode 100644 index fe22473..0000000 --- a/mojo/common/file.mojom +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -// Corresponds to |base::File| in base/files/file.h -struct File { - handle fd; -}; diff --git a/mojo/common/file.typemap b/mojo/common/file.typemap deleted file mode 100644 index 26d4941..0000000 --- a/mojo/common/file.typemap +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/file.mojom" -public_headers = [ "//base/files/file.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = - [ "mojo.common.mojom.File=base::File[move_only,nullable_is_same_type]" ] diff --git a/mojo/common/file_path.mojom b/mojo/common/file_path.mojom deleted file mode 100644 index 10ebe05..0000000 --- a/mojo/common/file_path.mojom +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -[Native] -struct FilePath; diff --git a/mojo/common/file_path.typemap b/mojo/common/file_path.typemap deleted file mode 100644 index 66d8c54..0000000 --- a/mojo/common/file_path.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/file_path.mojom" -public_headers = [ "//base/files/file_path.h" ] -traits_headers = [ "//ipc/ipc_message_utils.h" ] -public_deps = [ - "//ipc", -] - -type_mappings = [ "mojo.common.mojom.FilePath=base::FilePath" ] diff --git a/mojo/common/mojo_common_export.h b/mojo/common/mojo_common_export.h deleted file mode 100644 index 48d21d0..0000000 --- a/mojo/common/mojo_common_export.h +++ /dev/null @@ -1,32 +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_COMMON_MOJO_COMMON_EXPORT_H_ -#define MOJO_COMMON_MOJO_COMMON_EXPORT_H_ - -#if defined(COMPONENT_BUILD) - -#if defined(WIN32) - -#if defined(MOJO_COMMON_IMPLEMENTATION) -#define MOJO_COMMON_EXPORT __declspec(dllexport) -#else -#define MOJO_COMMON_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(MOJO_COMMON_IMPLEMENTATION) -#define MOJO_COMMON_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_COMMON_EXPORT -#endif - -#endif // defined(WIN32) - -#else // !defined(COMPONENT_BUILD) -#define MOJO_COMMON_EXPORT -#endif - -#endif // MOJO_COMMON_MOJO_COMMON_EXPORT_H_ diff --git a/mojo/common/string16.mojom b/mojo/common/string16.mojom deleted file mode 100644 index 173c867..0000000 --- a/mojo/common/string16.mojom +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -// Corresponds to |base::string16| in base/strings/string16.h -// Corresponds to |WTF::String| in -// third_party/WebKit/Source/wtf/text/WTFString.h. -struct String16 { - array data; -}; diff --git a/mojo/common/string16.typemap b/mojo/common/string16.typemap deleted file mode 100644 index 223de29..0000000 --- a/mojo/common/string16.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/string16.mojom" -public_headers = [ "//base/strings/string16.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = [ "mojo.common.mojom.String16=base::string16" ] diff --git a/mojo/common/struct_traits_unittest.cc b/mojo/common/struct_traits_unittest.cc deleted file mode 100644 index 5ac4bc9..0000000 --- a/mojo/common/struct_traits_unittest.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/message_loop/message_loop.h" -#include "mojo/common/traits_test_service.mojom.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace common { -namespace { - -class StructTraitsTest : public testing::Test, public mojom::TraitsTestService { - public: - StructTraitsTest() {} - - protected: - mojom::TraitsTestServicePtr GetTraitsTestProxy() { - return traits_test_bindings_.CreateInterfacePtrAndBind(this); - } - - private: - // TraitsTestService: - void EchoVersion(const base::Optional& m, - const EchoVersionCallback& callback) override { - callback.Run(m); - } - - base::MessageLoop loop_; - mojo::BindingSet traits_test_bindings_; - - DISALLOW_COPY_AND_ASSIGN(StructTraitsTest); -}; - -TEST_F(StructTraitsTest, Version) { - const std::string& version_str = "1.2.3.4"; - base::Version input(version_str); - mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); - base::Optional output; - proxy->EchoVersion(input, &output); - EXPECT_TRUE(output.has_value()); - EXPECT_EQ(version_str, output->GetString()); -} - -TEST_F(StructTraitsTest, InvalidVersion) { - const std::string invalid_version_str; - base::Version input(invalid_version_str); - mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); - base::Optional output; - proxy->EchoVersion(input, &output); - EXPECT_FALSE(output.has_value()); -} - -} // namespace -} // namespace common -} // namespace mojo diff --git a/mojo/common/test_common_custom_types.mojom b/mojo/common/test_common_custom_types.mojom deleted file mode 100644 index 0f13680..0000000 --- a/mojo/common/test_common_custom_types.mojom +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.test; - -import "mojo/common/file.mojom"; -import "mojo/common/file_path.mojom"; -import "mojo/common/string16.mojom"; -import "mojo/common/text_direction.mojom"; -import "mojo/common/time.mojom"; -import "mojo/common/unguessable_token.mojom"; -import "mojo/common/values.mojom"; - -interface TestFilePath { - BounceFilePath(mojo.common.mojom.FilePath in) - => (mojo.common.mojom.FilePath out); -}; - -interface TestUnguessableToken { - BounceNonce(mojo.common.mojom.UnguessableToken in) - => (mojo.common.mojom.UnguessableToken out); -}; - -interface TestTime { - BounceTime(mojo.common.mojom.Time time) => (mojo.common.mojom.Time time); - BounceTimeDelta(mojo.common.mojom.TimeDelta time_delta) - => (mojo.common.mojom.TimeDelta time_delta); - BounceTimeTicks(mojo.common.mojom.TimeTicks time_ticks) - => (mojo.common.mojom.TimeTicks time_ticks); -}; - -interface TestValue { - [Sync] - BounceDictionaryValue(mojo.common.mojom.DictionaryValue in) - => (mojo.common.mojom.DictionaryValue out); - [Sync] - BounceListValue(mojo.common.mojom.ListValue in) - => (mojo.common.mojom.ListValue out); - [Sync] - BounceValue(mojo.common.mojom.Value? in) - => (mojo.common.mojom.Value? out); -}; - -interface TestString16 { - [Sync] - BounceString16(mojo.common.mojom.String16 in) - => (mojo.common.mojom.String16 out); -}; - -interface TestFile { - [Sync] - BounceFile(mojo.common.mojom.File? in) - => (mojo.common.mojom.File? out); -}; - -interface TestTextDirection { - [Sync] - BounceTextDirection(mojo.common.mojom.TextDirection in) - => (mojo.common.mojom.TextDirection out); -}; diff --git a/mojo/common/text_direction.mojom b/mojo/common/text_direction.mojom deleted file mode 100644 index 7d65124..0000000 --- a/mojo/common/text_direction.mojom +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -// Corresponds to |base::i18n::TextDirection| in base/i18n/rtl.h -enum TextDirection { - UNKNOWN_DIRECTION, - RIGHT_TO_LEFT, - LEFT_TO_RIGHT -}; diff --git a/mojo/common/text_direction.typemap b/mojo/common/text_direction.typemap deleted file mode 100644 index 1f5be8e..0000000 --- a/mojo/common/text_direction.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2017 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/text_direction.mojom" -public_headers = [ "//base/i18n/rtl.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//base:i18n", - "//mojo/common:struct_traits", -] -type_mappings = [ "mojo.common.mojom.TextDirection=base::i18n::TextDirection" ] diff --git a/mojo/common/time.mojom b/mojo/common/time.mojom deleted file mode 100644 index b403bca..0000000 --- a/mojo/common/time.mojom +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -struct Time { - // The internal value is expressed in terms of microseconds since a fixed but - // intentionally unspecified epoch. - int64 internal_value; -}; - -struct TimeDelta { - int64 microseconds; -}; - -struct TimeTicks { - // The internal value is expressed in terms of microseconds since a fixed but - // intentionally unspecified epoch. - int64 internal_value; -}; diff --git a/mojo/common/time.typemap b/mojo/common/time.typemap deleted file mode 100644 index 99e9e3a..0000000 --- a/mojo/common/time.typemap +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/time.mojom" -public_headers = [ "//base/time/time.h" ] -traits_headers = [ - "//ipc/ipc_message_utils.h", - "//mojo/common/common_custom_types_struct_traits.h", -] -public_deps = [ - "//ipc", - "//mojo/common:struct_traits", -] - -type_mappings = [ - "mojo.common.mojom.Time=base::Time[copyable_pass_by_value]", - "mojo.common.mojom.TimeDelta=base::TimeDelta[copyable_pass_by_value]", - "mojo.common.mojom.TimeTicks=base::TimeTicks[copyable_pass_by_value]", -] diff --git a/mojo/common/time_struct_traits.h b/mojo/common/time_struct_traits.h deleted file mode 100644 index b480edb..0000000 --- a/mojo/common/time_struct_traits.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_COMMON_TIME_STRUCT_TRAITS_H_ -#define MOJO_COMMON_TIME_STRUCT_TRAITS_H_ - -#include "base/time/time.h" -#include "mojo/common/time.mojom-shared.h" - -namespace mojo { - -template <> -struct StructTraits { - static int64_t internal_value(const base::Time& time) { - return time.since_origin().InMicroseconds(); - } - - static bool Read(common::mojom::TimeDataView data, base::Time* time) { - *time = - base::Time() + base::TimeDelta::FromMicroseconds(data.internal_value()); - return true; - } -}; - -template <> -struct StructTraits { - static int64_t microseconds(const base::TimeDelta& delta) { - return delta.InMicroseconds(); - } - - static bool Read(common::mojom::TimeDeltaDataView data, - base::TimeDelta* delta) { - *delta = base::TimeDelta::FromMicroseconds(data.microseconds()); - return true; - } -}; - -template <> -struct StructTraits { - static int64_t internal_value(const base::TimeTicks& time) { - return time.since_origin().InMicroseconds(); - } - - static bool Read(common::mojom::TimeTicksDataView data, - base::TimeTicks* time) { - *time = base::TimeTicks() + - base::TimeDelta::FromMicroseconds(data.internal_value()); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_COMMON_TIME_STRUCT_TRAITS_H_ diff --git a/mojo/common/traits_test_service.mojom b/mojo/common/traits_test_service.mojom deleted file mode 100644 index 7659eea..0000000 --- a/mojo/common/traits_test_service.mojom +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -import "mojo/common/version.mojom"; - -// All functions on this interface echo their arguments to test StructTraits -// serialization and deserialization. -interface TraitsTestService { - [Sync] - EchoVersion(Version? v) => (Version? pass); -}; diff --git a/mojo/common/typemaps.gni b/mojo/common/typemaps.gni deleted file mode 100644 index ae36031..0000000 --- a/mojo/common/typemaps.gni +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -typemaps = [ - "//mojo/common/file.typemap", - "//mojo/common/file_path.typemap", - "//mojo/common/string16.typemap", - "//mojo/common/text_direction.typemap", - "//mojo/common/time.typemap", - "//mojo/common/unguessable_token.typemap", - "//mojo/common/values.typemap", - "//mojo/common/version.typemap", -] diff --git a/mojo/common/unguessable_token.mojom b/mojo/common/unguessable_token.mojom deleted file mode 100644 index 3279717..0000000 --- a/mojo/common/unguessable_token.mojom +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -// Corresponds to |base::UnguessableToken| in base/unguessable_token.h -struct UnguessableToken { - uint64 high; - uint64 low; -}; diff --git a/mojo/common/unguessable_token.typemap b/mojo/common/unguessable_token.typemap deleted file mode 100644 index ec7b194..0000000 --- a/mojo/common/unguessable_token.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/unguessable_token.mojom" -public_headers = [ "//base/unguessable_token.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = [ "mojo.common.mojom.UnguessableToken=base::UnguessableToken" ] diff --git a/mojo/common/values.mojom b/mojo/common/values.mojom deleted file mode 100644 index 722198c..0000000 --- a/mojo/common/values.mojom +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -union Value { - NullValue? null_value; - bool bool_value; - int32 int_value; - double double_value; - string string_value; - array binary_value; - DictionaryValue dictionary_value; - ListValue list_value; -}; - -struct ListValue { - array values; -}; - -struct DictionaryValue { - map values; -}; - -// An empty struct representing a null base::Value. -struct NullValue { -}; - -// To avoid versioning problems for arc. TODO(sammc): Remove ASAP. -[Native] -struct LegacyListValue; diff --git a/mojo/common/values.typemap b/mojo/common/values.typemap deleted file mode 100644 index f1f3fc2..0000000 --- a/mojo/common/values.typemap +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/values.mojom" -public_headers = [ "//base/values.h" ] -traits_headers = [ - "//ipc/ipc_message_utils.h", - "//mojo/common/values_struct_traits.h", -] -public_deps = [ - "//base", - "//ipc", -] -sources = [ - "values_struct_traits.cc", - "values_struct_traits.h", -] - -type_mappings = [ - "mojo.common.mojom.DictionaryValue=std::unique_ptr[move_only,nullable_is_same_type]", - "mojo.common.mojom.LegacyListValue=base::ListValue[non_copyable_non_movable]", - "mojo.common.mojom.ListValue=std::unique_ptr[move_only,nullable_is_same_type]", - "mojo.common.mojom.Value=std::unique_ptr[move_only,nullable_is_same_type]", -] diff --git a/mojo/common/values_struct_traits.cc b/mojo/common/values_struct_traits.cc deleted file mode 100644 index 6af7a39..0000000 --- a/mojo/common/values_struct_traits.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/ptr_util.h" -#include "mojo/common/values_struct_traits.h" - -namespace mojo { - -bool StructTraits>:: - Read(common::mojom::ListValueDataView data, - std::unique_ptr* value_out) { - mojo::ArrayDataView view; - data.GetValuesDataView(&view); - - auto list_value = base::MakeUnique(); - for (size_t i = 0; i < view.size(); ++i) { - std::unique_ptr value; - if (!view.Read(i, &value)) - return false; - - list_value->Append(std::move(value)); - } - *value_out = std::move(list_value); - return true; -} - -bool StructTraits>:: - Read(common::mojom::DictionaryValueDataView data, - std::unique_ptr* value_out) { - mojo::MapDataView view; - data.GetValuesDataView(&view); - auto dictionary_value = base::MakeUnique(); - for (size_t i = 0; i < view.size(); ++i) { - base::StringPiece key; - std::unique_ptr value; - if (!view.keys().Read(i, &key) || !view.values().Read(i, &value)) - return false; - - dictionary_value->SetWithoutPathExpansion(key, std::move(value)); - } - *value_out = std::move(dictionary_value); - return true; -} - -std::unique_ptr -CloneTraits, false>::Clone( - const std::unique_ptr& input) { - auto result = base::MakeUnique(); - result->MergeDictionary(input.get()); - return result; -} - -bool UnionTraits>:: - Read(common::mojom::ValueDataView data, - std::unique_ptr* value_out) { - switch (data.tag()) { - case common::mojom::ValueDataView::Tag::NULL_VALUE: { - *value_out = base::Value::CreateNullValue(); - return true; - } - case common::mojom::ValueDataView::Tag::BOOL_VALUE: { - *value_out = base::MakeUnique(data.bool_value()); - return true; - } - case common::mojom::ValueDataView::Tag::INT_VALUE: { - *value_out = base::MakeUnique(data.int_value()); - return true; - } - case common::mojom::ValueDataView::Tag::DOUBLE_VALUE: { - *value_out = base::MakeUnique(data.double_value()); - return true; - } - case common::mojom::ValueDataView::Tag::STRING_VALUE: { - base::StringPiece string_value; - if (!data.ReadStringValue(&string_value)) - return false; - *value_out = base::MakeUnique(string_value); - return true; - } - case common::mojom::ValueDataView::Tag::BINARY_VALUE: { - mojo::ArrayDataView binary_data; - data.GetBinaryValueDataView(&binary_data); - *value_out = base::BinaryValue::CreateWithCopiedBuffer( - reinterpret_cast(binary_data.data()), - binary_data.size()); - return true; - } - case common::mojom::ValueDataView::Tag::DICTIONARY_VALUE: { - std::unique_ptr dictionary_value; - if (!data.ReadDictionaryValue(&dictionary_value)) - return false; - *value_out = std::move(dictionary_value); - return true; - } - case common::mojom::ValueDataView::Tag::LIST_VALUE: { - std::unique_ptr list_value; - if (!data.ReadListValue(&list_value)) - return false; - *value_out = std::move(list_value); - return true; - } - } - return false; -} - -} // namespace mojo diff --git a/mojo/common/values_struct_traits.h b/mojo/common/values_struct_traits.h deleted file mode 100644 index befcf3a..0000000 --- a/mojo/common/values_struct_traits.h +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_COMMON_VALUES_STRUCT_TRAITS_H_ -#define MOJO_COMMON_VALUES_STRUCT_TRAITS_H_ - -#include "base/values.h" -#include "mojo/common/values.mojom.h" -#include "mojo/public/cpp/bindings/array_traits.h" -#include "mojo/public/cpp/bindings/clone_traits.h" -#include "mojo/public/cpp/bindings/map_traits.h" -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "mojo/public/cpp/bindings/union_traits.h" - -namespace mojo { - -template <> -struct ArrayTraits { - using Element = std::unique_ptr; - using ConstIterator = base::ListValue::const_iterator; - - static size_t GetSize(const base::ListValue& input) { - return input.GetSize(); - } - - static ConstIterator GetBegin(const base::ListValue& input) { - return input.begin(); - } - - static void AdvanceIterator(ConstIterator& iterator) { ++iterator; } - - static const Element& GetValue(ConstIterator& iterator) { return *iterator; } -}; - -template <> -struct StructTraits { - static const base::ListValue& values(const base::ListValue& value) { - return value; - } -}; - -template <> -struct StructTraits> { - static bool IsNull(const std::unique_ptr& value) { - return !value; - } - - static void SetToNull(std::unique_ptr* value) { - value->reset(); - } - - static const base::ListValue& values( - const std::unique_ptr& value) { - return *value; - } - - static bool Read(common::mojom::ListValueDataView data, - std::unique_ptr* value); -}; - -template <> -struct MapTraits { - using Key = std::string; - using Value = base::Value; - using Iterator = base::DictionaryValue::Iterator; - - static size_t GetSize(const base::DictionaryValue& input) { - return input.size(); - } - - static Iterator GetBegin(const base::DictionaryValue& input) { - return Iterator(input); - } - - static void AdvanceIterator(Iterator& iterator) { iterator.Advance(); } - - static const Key& GetKey(Iterator& iterator) { return iterator.key(); } - - static const Value& GetValue(Iterator& iterator) { return iterator.value(); } -}; - -template <> -struct StructTraits { - static const base::DictionaryValue& values( - const base::DictionaryValue& value) { - return value; - } -}; - -template <> -struct StructTraits> { - static bool IsNull(const std::unique_ptr& value) { - return !value; - } - - static void SetToNull(std::unique_ptr* value) { - value->reset(); - } - - static const base::DictionaryValue& values( - const std::unique_ptr& value) { - return *value; - } - static bool Read(common::mojom::DictionaryValueDataView data, - std::unique_ptr* value); -}; - -template <> -struct CloneTraits, false> { - static std::unique_ptr Clone( - const std::unique_ptr& input); -}; - -template <> -struct UnionTraits { - static common::mojom::ValueDataView::Tag GetTag(const base::Value& data) { - switch (data.GetType()) { - case base::Value::Type::NONE: - return common::mojom::ValueDataView::Tag::NULL_VALUE; - case base::Value::Type::BOOLEAN: - return common::mojom::ValueDataView::Tag::BOOL_VALUE; - case base::Value::Type::INTEGER: - return common::mojom::ValueDataView::Tag::INT_VALUE; - case base::Value::Type::DOUBLE: - return common::mojom::ValueDataView::Tag::DOUBLE_VALUE; - case base::Value::Type::STRING: - return common::mojom::ValueDataView::Tag::STRING_VALUE; - case base::Value::Type::BINARY: - return common::mojom::ValueDataView::Tag::BINARY_VALUE; - case base::Value::Type::DICTIONARY: - return common::mojom::ValueDataView::Tag::DICTIONARY_VALUE; - case base::Value::Type::LIST: - return common::mojom::ValueDataView::Tag::LIST_VALUE; - } - NOTREACHED(); - return common::mojom::ValueDataView::Tag::NULL_VALUE; - } - - static common::mojom::NullValuePtr null_value(const base::Value& value) { - return common::mojom::NullValuePtr(); - } - - static bool bool_value(const base::Value& value) { - bool bool_value{}; - if (!value.GetAsBoolean(&bool_value)) - NOTREACHED(); - return bool_value; - } - - static int32_t int_value(const base::Value& value) { - int int_value{}; - if (!value.GetAsInteger(&int_value)) - NOTREACHED(); - return int_value; - } - - static double double_value(const base::Value& value) { - double double_value{}; - if (!value.GetAsDouble(&double_value)) - NOTREACHED(); - return double_value; - } - - static base::StringPiece string_value(const base::Value& value) { - base::StringPiece string_piece; - if (!value.GetAsString(&string_piece)) - NOTREACHED(); - return string_piece; - } - - static mojo::ConstCArray binary_value(const base::Value& value) { - const base::BinaryValue* binary_value = nullptr; - if (!value.GetAsBinary(&binary_value)) - NOTREACHED(); - return mojo::ConstCArray( - binary_value->GetSize(), - reinterpret_cast(binary_value->GetBuffer())); - } - - static const base::ListValue& list_value(const base::Value& value) { - const base::ListValue* list_value = nullptr; - if (!value.GetAsList(&list_value)) - NOTREACHED(); - return *list_value; - } - static const base::DictionaryValue& dictionary_value( - const base::Value& value) { - const base::DictionaryValue* dictionary_value = nullptr; - if (!value.GetAsDictionary(&dictionary_value)) - NOTREACHED(); - return *dictionary_value; - } -}; - -template <> -struct UnionTraits> { - static bool IsNull(const std::unique_ptr& value) { - return !value; - } - - static void SetToNull(std::unique_ptr* value) { value->reset(); } - - static common::mojom::ValueDataView::Tag GetTag( - const std::unique_ptr& value) { - return UnionTraits::GetTag( - *value); - } - - static common::mojom::NullValuePtr null_value( - const std::unique_ptr& value) { - return UnionTraits::null_value( - *value); - } - static bool bool_value(const std::unique_ptr& value) { - return UnionTraits::bool_value( - *value); - } - static int32_t int_value(const std::unique_ptr& value) { - return UnionTraits::int_value( - *value); - } - static double double_value(const std::unique_ptr& value) { - return UnionTraits::double_value( - *value); - } - static base::StringPiece string_value( - const std::unique_ptr& value) { - return UnionTraits::string_value( - *value); - } - static mojo::ConstCArray binary_value( - const std::unique_ptr& value) { - return UnionTraits::binary_value( - *value); - } - static const base::ListValue& list_value( - const std::unique_ptr& value) { - return UnionTraits::list_value( - *value); - } - static const base::DictionaryValue& dictionary_value( - const std::unique_ptr& value) { - return UnionTraits::dictionary_value(*value); - } - - static bool Read(common::mojom::ValueDataView data, - std::unique_ptr* value); -}; - -} // namespace mojo - -#endif // MOJO_COMMON_VALUES_STRUCT_TRAITS_H_ diff --git a/mojo/common/version.mojom b/mojo/common/version.mojom deleted file mode 100644 index 6ddf6e6..0000000 --- a/mojo/common/version.mojom +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module mojo.common.mojom; - -// Corresponds to |base::Version| in base/version.h -struct Version { - array components; -}; diff --git a/mojo/common/version.typemap b/mojo/common/version.typemap deleted file mode 100644 index fa7fed9..0000000 --- a/mojo/common/version.typemap +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -mojom = "//mojo/common/version.mojom" -public_headers = [ "//base/version.h" ] -traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ] -public_deps = [ - "//mojo/common:struct_traits", -] - -type_mappings = [ "mojo.common.mojom.Version=base::Version" ] diff --git a/mojo/edk/DEPS b/mojo/edk/DEPS deleted file mode 100644 index 77abb21..0000000 --- a/mojo/edk/DEPS +++ /dev/null @@ -1,14 +0,0 @@ -include_rules = [ - # This code is checked into the chromium repo so it's fine to depend on this. - "+base", - "+crypto", - "+build", - "+gin", - "+native_client/src/public", - "+testing", - "+third_party/ashmem", - "+v8", - - # internal includes. - "+mojo", -] diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn deleted file mode 100644 index 8105bed..0000000 --- a/mojo/edk/embedder/BUILD.gn +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/nacl/config.gni") - -source_set("headers") { - sources = [ - "configuration.h", - "connection_params.h", - "embedder.h", - "embedder_internal.h", - "named_platform_channel_pair.h", - "named_platform_handle.h", - "named_platform_handle_utils.h", - "pending_process_connection.h", - "platform_channel_pair.h", - "platform_handle.h", - "platform_handle_utils.h", - "scoped_platform_handle.h", - ] - - public_deps = [ - "//base", - "//mojo/public/cpp/system", - ] -} - -source_set("embedder") { - # This isn't really a standalone target; it must be linked into the - # mojo_system_impl component. - visibility = [ - "//mojo/edk/system", - "//components/nacl:nacl", - ] - - sources = [ - "configuration.h", - "connection_params.cc", - "connection_params.h", - "embedder.cc", - "embedder.h", - "embedder_internal.h", - "entrypoints.cc", - "entrypoints.h", - "pending_process_connection.cc", - "scoped_ipc_support.cc", - "scoped_ipc_support.h", - - # Test-only code: - # TODO(vtl): It's a little unfortunate that these end up in the same - # component as non-test-only code. In the static build, this code should - # hopefully be dead-stripped. - "test_embedder.cc", - "test_embedder.h", - ] - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - public_deps = [ - ":headers", - ":platform", - "//base", - "//mojo/public/cpp/system", - ] - - if (!is_nacl) { - deps = [ - "//crypto", - ] - } -} - -source_set("platform") { - # This isn't really a standalone target; it must be linked into the - # mojo_system_impl component. - visibility = [ - ":embedder", - "//mojo/edk/system", - ] - - sources = [ - "named_platform_channel_pair.h", - "named_platform_channel_pair_win.cc", - "named_platform_handle.h", - "named_platform_handle_utils.h", - "named_platform_handle_utils_win.cc", - "platform_channel_pair.cc", - "platform_channel_pair.h", - "platform_channel_pair_posix.cc", - "platform_channel_pair_win.cc", - "platform_channel_utils_posix.cc", - "platform_channel_utils_posix.h", - "platform_handle.cc", - "platform_handle.h", - "platform_handle_utils.h", - "platform_handle_utils_posix.cc", - "platform_handle_utils_win.cc", - "platform_handle_vector.h", - "platform_shared_buffer.cc", - "platform_shared_buffer.h", - "scoped_platform_handle.h", - ] - if (!is_nacl) { - sources += [ "named_platform_handle_utils_posix.cc" ] - } - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - public_deps = [ - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - ] - - if (is_android) { - deps += [ "//third_party/ashmem" ] - } - - if (is_nacl && !is_nacl_nonsfi) { - sources -= [ "platform_channel_utils_posix.cc" ] - } -} - -source_set("embedder_unittests") { - testonly = true - - # TODO: Figure out why this visibility check fails on Android. - # visibility = [ "//mojo/edk/system:mojo_system_unittests" ] - - sources = [ - "embedder_unittest.cc", - "platform_channel_pair_posix_unittest.cc", - "platform_shared_buffer_unittest.cc", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//mojo/edk/system", - "//mojo/edk/system:test_utils", - "//mojo/edk/test:test_support", - "//testing/gtest", - ] -} diff --git a/mojo/edk/embedder/README.md b/mojo/edk/embedder/README.md deleted file mode 100644 index fc53bec..0000000 --- a/mojo/edk/embedder/README.md +++ /dev/null @@ -1,346 +0,0 @@ -# ![Mojo Graphic](https://goo.gl/6CdlbH) Mojo Embedder Development Kit (EDK) -This document is a subset of the [Mojo documentation](/mojo). - -[TOC] - -## Overview - -The Mojo EDK is a (binary-unstable) API which enables a process to use Mojo both -internally and for IPC to other Mojo-embedding processes. - -Using any of the API surface in `//mojo/edk/embedder` requires (somewhat -confusingly) a direct dependency on the GN `//mojo/edk/system` target. Despite -this fact, you should never reference any of the headers in `mojo/edk/system` -directly, as everything there is considered to be an internal detail of the EDK. - -**NOTE:** Unless you are introducing a new binary entry point into the system -(*e.g.,* a new executable with a new `main()` definition), you probably don't -need to know anything about the EDK API. Most processes defined in the Chrome -repo today already fully initialize the EDK so that Mojo's other public APIs -"just work" out of the box. - -## Basic Initialization - -In order to use Mojo in a given process, it's necessary to call -`mojo::edk::Init` exactly once: - -``` -#include "mojo/edk/embedder/embedder.h" - -int main(int argc, char** argv) { - mojo::edk::Init(); - - // Now you can create message pipes, write messages, etc - - return 0; -} -``` - -As it happens though, Mojo is less useful without some kind of IPC support as -well, and that's a second initialization step. - -## IPC Initialization - -You also need to provide the system with a background TaskRunner on which it can -watch for inbound I/O from any of the various other processes you will later -connect to it. - -Here we'll just create a new background thread for IPC and let Mojo use that. -Note that in Chromium, we use the existing "IO thread" in the browser process -and content child processes. - -``` -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" - -int main(int argc, char** argv) { - mojo::edk::Init(); - - base::Thread ipc_thread("ipc!"); - ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); - - // As long as this object is alive, all EDK API surface relevant to IPC - // connections is usable and message pipes which span a process boundary will - // continue to function. - mojo::edk::ScopedIPCSupport ipc_support( - ipc_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); - - return 0; -} -``` - -This process is now fully prepared to use Mojo IPC! - -Note that all existing process types in Chromium already perform this setup -very early during startup. - -## Connecting Two Processes - -Now suppose you're running a process which has initialized Mojo IPC, and you -want to launch another process which you know will also initialize Mojo IPC. -You want to be able to connect Mojo interfaces between these two processes. -Rejoice, because this section was written just for you. - -NOTE: For legacy reasons, some API terminology may refer to concepts of "parent" -and "child" as a relationship between processes being connected by Mojo. This -relationship is today completely orthogonal to any notion of process hierarchy -in the OS, and so use of these APIs is not constrained by an adherence to any -such hierarchy. - -Mojo requires you to bring your own OS pipe to the party, and it will do the -rest. It also provides a convenient mechanism for creating such pipes, known as -a `PlatformChannelPair`. - -You provide one end of this pipe to the EDK in the local process via -`PendingProcessConnection` - which can also be used to create cross-process -message pipes (see the next section) - and you're responsible for getting the -other end into the remote process. - -``` -#include "base/process/process_handle.h" -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/pending_process_connection.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" - -// You write this. It launches a new process, passing the pipe handle -// encapsulated by |channel| by any means possible (e.g. on Windows or POSIX -// you may inhert the file descriptor/HANDLE at launch and pass a commandline -// argument to indicate its numeric value). Returns the handle of the new -// process. -base::ProcessHandle LaunchCoolChildProcess( - mojo::edk::ScopedPlatformHandle channel); - -int main(int argc, char** argv) { - mojo::edk::Init(); - - base::Thread ipc_thread("ipc!"); - ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); - - mojo::edk::ScopedIPCSupport ipc_support( - ipc_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); - - // This is essentially always an OS pipe (domain socket pair, Windows named - // pipe, etc.) - mojo::edk::PlatformChannelPair channel; - - // This is a scoper which encapsulates the intent to connect to another - // process. It exists because process connection is inherently asynchronous, - // things may go wrong, and the lifetime of any associated resources is bound - // by the lifetime of this object regardless of success or failure. - mojo::edk::PendingProcessConnection child; - - base::ProcessHandle child_handle = - LaunchCoolChildProcess(channel.PassClientHandle()); - - // At this point it's safe for |child| to go out of scope and nothing will - // break. - child.Connect(child_handle, channel.PassServerHandle()); - - return 0; -} -``` - -The launched process code uses `SetParentPipeHandle` to get connected, and might -look something like: - -``` -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" - -// You write this. It acquires the ScopedPlatformHandle that was passed by -// whomever launched this process (i.e. LaunchCoolChildProcess above). -mojo::edk::ScopedPlatformHandle GetChannelHandle(); - -int main(int argc, char** argv) { - mojo::edk::Init(); - - base::Thread ipc_thread("ipc!"); - ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); - - mojo::edk::ScopedIPCSupport ipc_support( - ipc_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); - - mojo::edk::SetParentPipeHandle(GetChannelHandle()); - - return 0; -} -``` - -Now you have IPC initialized between two processes. For some practical examples -of how this is done, you can dig into the various multiprocess tests in the -`mojo_system_unittests` test suite. - -## Bootstrapping Cross-Process Message Pipes - -Having internal Mojo IPC support initialized is pretty useless if you don't have -any message pipes spanning the process boundary. Fortunately, this is made -trivial by the EDK: `PendingProcessConnection` has a -`CreateMessagePipe` method which synthesizes a new solitary message pipe -endpoint for your immediate use, while also generating a magic token string that -can be exchanged for the other end of the pipe via -`mojo::edk::CreateChildMessagePipe`. - -The token exchange can be done by the same process (which is sometimes useful), -or by the process that is eventually connected via `Connect()` on that -`PendingProcessConnection`. This means that you can effectively pass message -pipes on the commandline by passing a token string. - -We can modify our existing sample code as follows: - -``` -#include "base/command_line.h" -#include "base/process/process_handle.h" -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/pending_process_connection.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "local/foo.mojom.h" // You provide this - -base::ProcessHandle LaunchCoolChildProcess( - const base::CommandLine& command_line, - mojo::edk::ScopedPlatformHandle channel); - -int main(int argc, char** argv) { - mojo::edk::Init(); - - base::Thread ipc_thread("ipc!"); - ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); - - mojo::edk::ScopedIPCSupport ipc_support( - ipc_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); - - mojo::edk::PlatformChannelPair channel; - - mojo::edk::PendingProcessConnection child; - - base::CommandLine command_line; // Assume this is appropriately initialized - - // Create a new message pipe with one end being retrievable in the new - // process. Note that it doesn't matter whether we call CreateMessagePipe() - // before or after Connect(), and we can create as many different pipes as - // we like. - std::string pipe_token; - mojo::ScopedMessagePipeHandle my_pipe = child.CreateMessagePipe(&pipe_token); - command_line.AppendSwitchASCII("primordial-pipe", pipe_token); - - base::ProcessHandle child_handle = - LaunchCoolChildProcess(command_line, channel.PassClientHandle()); - - child.Connect(child_handle, channel.PassServerHandle()); - - // We can start using our end of the pipe immediately. Here we assume the - // other end will eventually be bound to a local::mojom::Foo implementation, - // so we can start making calls on that interface. - // - // Note that this could even be done before the child process is launched and - // it would still work as expected. - local::mojom::FooPtr foo; - foo.Bind(local::mojom::FooPtrInfo(std::move(my_pipe), 0)); - foo->DoSomeStuff(42); - - return 0; -} -``` - -and for the launched process: - - -``` -#include "base/command_line.h" -#include "base/run_loop/run_loop.h" -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "local/foo.mojom.h" // You provide this - -mojo::edk::ScopedPlatformHandle GetChannelHandle(); - -class FooImpl : local::mojom::Foo { - public: - explicit FooImpl(local::mojom::FooRequest request) - : binding_(this, std::move(request)) {} - ~FooImpl() override {} - - void DoSomeStuff(int32_t n) override { - // ... - } - - private: - mojo::Binding binding_; - - DISALLOW_COPY_AND_ASSIGN(FooImpl); -}; - -int main(int argc, char** argv) { - base::CommandLine::Init(argc, argv); - - mojo::edk::Init(); - - base::Thread ipc_thread("ipc!"); - ipc_thread.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO)); - - mojo::edk::ScopedIPCSupport ipc_support( - ipc_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); - - mojo::edk::SetParentPipeHandle(GetChannelHandle()); - - mojo::ScopedMessagePipeHandle my_pipe = mojo::edk::CreateChildMessagePipe( - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - "primordial-pipe")); - - local::mojom::FooRequest foo_request; - foo_request.Bind(std::move(my_pipe)); - FooImpl impl(std::move(foo_request)); - - // Run forever! - base::RunLoop().Run(); - - return 0; -} -``` - -Note that the above samples assume an interface definition in -`//local/test.mojom` which would look something like: - -``` -module local.mojom; - -interface Foo { - DoSomeStuff(int32 n); -}; -``` - -Once you've bootstrapped your process connection with a real mojom interface, -you can avoid any further mucking around with EDK APIs or raw message pipe -handles, as everything beyond this point - including the passing of other -interface pipes - can be handled eloquently using -[public bindings APIs](/mojo#High-Level-Bindings-APIs). - -## Setting System Properties - -The public Mojo C System API exposes a -[**`MojoGetProperty`**](/mojo/public/c/system#MojoGetProperty) function for -querying global, embedder-defined property values. These can be set by calling: - -``` -mojo::edk::SetProperty(MojoPropertyType type, const void* value) -``` - diff --git a/mojo/edk/embedder/configuration.h b/mojo/edk/embedder/configuration.h deleted file mode 100644 index 1990fb1..0000000 --- a/mojo/edk/embedder/configuration.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_CONFIGURATION_H_ -#define MOJO_EDK_EMBEDDER_CONFIGURATION_H_ - -#include -#include - -namespace mojo { -namespace edk { - -// A set of constants that the Mojo system internally uses. These values should -// be consistent across all processes on the same system. -// -// In general, there should be no need to change these values from their -// defaults. However, if you do change them, you must do so before -// initialization. -struct Configuration { - // Maximum number of open (Mojo) handles. The default is 1,000,000. - // - // TODO(vtl): This doesn't count "live" handles, some of which may live in - // messages. - size_t max_handle_table_size; - - // Maximum number of active memory mappings. The default is 1,000,000. - size_t max_mapping_table_sze; - - // Maximum data size of messages sent over message pipes, in bytes. The - // default is 4MB. - size_t max_message_num_bytes; - - // Maximum number of handles that can be attached to messages sent over - // message pipes. The default is 10,000. - size_t max_message_num_handles; - - // Maximum capacity of a data pipe, in bytes. The default is 256MB. This value - // must fit into a |uint32_t|. WARNING: If you bump it closer to 2^32, you - // must audit all the code to check that we don't overflow (2^31 would - // definitely be risky; up to 2^30 is probably okay). - size_t max_data_pipe_capacity_bytes; - - // Default data pipe capacity, if not specified explicitly in the creation - // options. The default is 1MB. - size_t default_data_pipe_capacity_bytes; - - // Alignment for the "start" of the data buffer used by data pipes. (The - // alignment of elements will depend on this and the element size.) The - // default is 16 bytes. - size_t data_pipe_buffer_alignment_bytes; - - // Maximum size of a single shared memory segment, in bytes. The default is - // 1GB. - // - // TODO(vtl): Set this hard limit appropriately (e.g., higher on 64-bit). - // (This will also entail some auditing to make sure I'm not messing up my - // checks anywhere.) - size_t max_shared_memory_num_bytes; -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_CONFIGURATION_H_ diff --git a/mojo/edk/embedder/connection_params.cc b/mojo/edk/embedder/connection_params.cc deleted file mode 100644 index 9b7ec54..0000000 --- a/mojo/edk/embedder/connection_params.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/connection_params.h" - -#include - -namespace mojo { -namespace edk { - -ConnectionParams::ConnectionParams(ScopedPlatformHandle channel) - : channel_(std::move(channel)) {} - -ConnectionParams::ConnectionParams(ConnectionParams&& param) - : channel_(std::move(param.channel_)) {} - -ConnectionParams& ConnectionParams::operator=(ConnectionParams&& param) { - channel_ = std::move(param.channel_); - return *this; -} - -ScopedPlatformHandle ConnectionParams::TakeChannelHandle() { - return std::move(channel_); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/connection_params.h b/mojo/edk/embedder/connection_params.h deleted file mode 100644 index 25ffdde..0000000 --- a/mojo/edk/embedder/connection_params.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_CONNECTION_PARAMS_H_ -#define MOJO_EDK_EMBEDDER_CONNECTION_PARAMS_H_ - -#include "base/macros.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -class MOJO_SYSTEM_IMPL_EXPORT ConnectionParams { - public: - explicit ConnectionParams(ScopedPlatformHandle channel); - - ConnectionParams(ConnectionParams&& param); - ConnectionParams& operator=(ConnectionParams&& param); - - ScopedPlatformHandle TakeChannelHandle(); - - private: - ScopedPlatformHandle channel_; - - DISALLOW_COPY_AND_ASSIGN(ConnectionParams); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_CONNECTION_PARAMS_H_ diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc deleted file mode 100644 index 0fdda5c..0000000 --- a/mojo/edk/embedder/embedder.cc +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/embedder.h" - -#include -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/embedder/entrypoints.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/system/core.h" -#include "mojo/edk/system/node_controller.h" - -#if !defined(OS_NACL) -#include "crypto/random.h" -#endif - -namespace mojo { -namespace edk { - -class Core; -class PlatformSupport; - -namespace internal { - -Core* g_core; - -Core* GetCore() { return g_core; } - -} // namespace internal - -void SetMaxMessageSize(size_t bytes) { -} - -void SetParentPipeHandle(ScopedPlatformHandle pipe) { - CHECK(internal::g_core); - internal::g_core->InitChild(ConnectionParams(std::move(pipe))); -} - -void SetParentPipeHandleFromCommandLine() { - ScopedPlatformHandle platform_channel = - PlatformChannelPair::PassClientHandleFromParentProcess( - *base::CommandLine::ForCurrentProcess()); - CHECK(platform_channel.is_valid()); - SetParentPipeHandle(std::move(platform_channel)); -} - -ScopedMessagePipeHandle ConnectToPeerProcess(ScopedPlatformHandle pipe) { - return ConnectToPeerProcess(std::move(pipe), GenerateRandomToken()); -} - -ScopedMessagePipeHandle ConnectToPeerProcess(ScopedPlatformHandle pipe, - const std::string& peer_token) { - DCHECK(pipe.is_valid()); - DCHECK(!peer_token.empty()); - return internal::g_core->ConnectToPeerProcess(std::move(pipe), peer_token); -} - -void ClosePeerConnection(const std::string& peer_token) { - return internal::g_core->ClosePeerConnection(peer_token); -} - -void Init() { - MojoSystemThunks thunks = MakeSystemThunks(); - size_t expected_size = MojoEmbedderSetSystemThunks(&thunks); - DCHECK_EQ(expected_size, sizeof(thunks)); - - internal::g_core = new Core(); -} - -void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback) { - internal::g_core->SetDefaultProcessErrorCallback(callback); -} - -MojoResult CreatePlatformHandleWrapper( - ScopedPlatformHandle platform_handle, - MojoHandle* platform_handle_wrapper_handle) { - return internal::g_core->CreatePlatformHandleWrapper( - std::move(platform_handle), platform_handle_wrapper_handle); -} - -MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, - ScopedPlatformHandle* platform_handle) { - return internal::g_core->PassWrappedPlatformHandle( - platform_handle_wrapper_handle, platform_handle); -} - -MojoResult CreateSharedBufferWrapper( - base::SharedMemoryHandle shared_memory_handle, - size_t num_bytes, - bool read_only, - MojoHandle* mojo_wrapper_handle) { - return internal::g_core->CreateSharedBufferWrapper( - shared_memory_handle, num_bytes, read_only, mojo_wrapper_handle); -} - -MojoResult PassSharedMemoryHandle( - MojoHandle mojo_handle, - base::SharedMemoryHandle* shared_memory_handle, - size_t* num_bytes, - bool* read_only) { - return internal::g_core->PassSharedMemoryHandle( - mojo_handle, shared_memory_handle, num_bytes, read_only); -} - -void InitIPCSupport(scoped_refptr io_thread_task_runner) { - CHECK(internal::g_core); - internal::g_core->SetIOTaskRunner(io_thread_task_runner); -} - -scoped_refptr GetIOTaskRunner() { - return internal::g_core->GetNodeController()->io_task_runner(); -} - -void ShutdownIPCSupport(const base::Closure& callback) { - CHECK(internal::g_core); - internal::g_core->RequestShutdown(callback); -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -void SetMachPortProvider(base::PortProvider* port_provider) { - DCHECK(port_provider); - internal::g_core->SetMachPortProvider(port_provider); -} -#endif - -ScopedMessagePipeHandle CreateChildMessagePipe(const std::string& token) { - return internal::g_core->CreateChildMessagePipe(token); -} - -std::string GenerateRandomToken() { - char random_bytes[16]; -#if defined(OS_NACL) - // Not secure. For NaCl only! - base::RandBytes(random_bytes, 16); -#else - crypto::RandBytes(random_bytes, 16); -#endif - return base::HexEncode(random_bytes, 16); -} - -MojoResult SetProperty(MojoPropertyType type, const void* value) { - CHECK(internal::g_core); - return internal::g_core->SetProperty(type, value); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h deleted file mode 100644 index 97258e5..0000000 --- a/mojo/edk/embedder/embedder.h +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_EMBEDDER_H_ -#define MOJO_EDK_EMBEDDER_EMBEDDER_H_ - -#include - -#include -#include - -#include "base/callback.h" -#include "base/command_line.h" -#include "base/memory/ref_counted.h" -#include "base/memory/shared_memory_handle.h" -#include "base/process/process_handle.h" -#include "base/task_runner.h" -#include "mojo/edk/embedder/pending_process_connection.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" - -namespace base { -class PortProvider; -} - -namespace mojo { -namespace edk { - -// 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). - -// Allows changing the default max message size. Must be called before Init. -MOJO_SYSTEM_IMPL_EXPORT void SetMaxMessageSize(size_t bytes); - -// Should be called as early as possible in a child process with a handle to the -// other end of a pipe provided in the parent to -// PendingProcessConnection::Connect. -MOJO_SYSTEM_IMPL_EXPORT void SetParentPipeHandle(ScopedPlatformHandle pipe); - -// Same as above but extracts the pipe handle from the command line. See -// PlatformChannelPair for details. -MOJO_SYSTEM_IMPL_EXPORT void SetParentPipeHandleFromCommandLine(); - -// Called to connect to a peer process. This should be called only if there -// is no common ancestor for the processes involved within this mojo system. -// Both processes must call this function, each passing one end of a platform -// channel. This returns one end of a message pipe to each process. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -ConnectToPeerProcess(ScopedPlatformHandle pipe); - -// Called to connect to a peer process. This should be called only if there -// is no common ancestor for the processes involved within this mojo system. -// Both processes must call this function, each passing one end of a platform -// channel. This returns one end of a message pipe to each process. |peer_token| -// may be passed to ClosePeerConnection() to close the connection. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -ConnectToPeerProcess(ScopedPlatformHandle pipe, const std::string& peer_token); - -// Closes a connection to a peer process created by ConnectToPeerProcess() -// where the same |peer_token| was used. -MOJO_SYSTEM_IMPL_EXPORT void ClosePeerConnection(const std::string& peer_token); - -// Must be called first, or just after setting configuration parameters, to -// initialize the (global, singleton) system. -MOJO_SYSTEM_IMPL_EXPORT void Init(); - -// Sets a default callback to invoke when an internal error is reported but -// cannot be associated with a specific child process. -MOJO_SYSTEM_IMPL_EXPORT void SetDefaultProcessErrorCallback( - const ProcessErrorCallback& callback); - -// Basic functions ------------------------------------------------------------- - -// The functions in this section are available once |Init()| has been called. - -// 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| is closed -// on success. -MOJO_SYSTEM_IMPL_EXPORT MojoResult -PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, - ScopedPlatformHandle* platform_handle); - -// Creates a |MojoHandle| that wraps the given |SharedMemoryHandle| (taking -// ownership of it). |num_bytes| is the size of the shared memory object, and -// |read_only| is whether the handle is a read-only handle to shared memory. -// This |MojoHandle| is a Mojo shared buffer and can be manipulated using the -// shared buffer functions and transferred over a message pipe. -MOJO_SYSTEM_IMPL_EXPORT MojoResult -CreateSharedBufferWrapper(base::SharedMemoryHandle shared_memory_handle, - size_t num_bytes, - bool read_only, - MojoHandle* mojo_wrapper_handle); - -// Retrieves the underlying |SharedMemoryHandle| from a shared buffer -// |MojoHandle| and closes the handle. If successful, |num_bytes| will contain -// the size of the shared memory buffer and |read_only| will contain whether the -// buffer handle is read-only. Both |num_bytes| and |read_only| may be null. -// Note: The value of |shared_memory_handle| may be -// base::SharedMemory::NULLHandle(), even if this function returns success. -// Callers should perform appropriate checks. -MOJO_SYSTEM_IMPL_EXPORT MojoResult -PassSharedMemoryHandle(MojoHandle mojo_handle, - base::SharedMemoryHandle* shared_memory_handle, - size_t* num_bytes, - bool* read_only); - -// 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 |ShutdownIPCSupport()|. None of the IPC -// functions may be called after this is called. -// -// |io_thread_task_runner| should live at least until |ShutdownIPCSupport()|'s -// callback has been run. -MOJO_SYSTEM_IMPL_EXPORT void InitIPCSupport( - scoped_refptr io_thread_task_runner); - -// Retrieves the TaskRunner used for IPC I/O, as set by InitIPCSupport. -MOJO_SYSTEM_IMPL_EXPORT scoped_refptr GetIOTaskRunner(); - -// Shuts down the subsystem initialized by |InitIPCSupport()|. It be called from -// any thread and will attempt to complete shutdown on the I/O thread with which -// the system was initialized. Upon completion, |callback| is invoked on an -// arbitrary thread. -MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupport(const base::Closure& callback); - -#if defined(OS_MACOSX) && !defined(OS_IOS) -// Set the |base::PortProvider| for this process. Can be called on any thread, -// but must be set in the root process before any Mach ports can be transferred. -MOJO_SYSTEM_IMPL_EXPORT void SetMachPortProvider( - base::PortProvider* port_provider); -#endif - -// Creates a message pipe from a token in a child process. This token must have -// been acquired by a corresponding call to -// PendingProcessConnection::CreateMessagePipe. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -CreateChildMessagePipe(const std::string& token); - -// Generates a random ASCII token string for use with various APIs that expect -// a globally unique token string. -MOJO_SYSTEM_IMPL_EXPORT std::string GenerateRandomToken(); - -// Sets system properties that can be read by the MojoGetProperty() API. See the -// documentation for MojoPropertyType for supported property types and their -// corresponding value type. -// -// Default property values: -// |MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED| - true -MOJO_SYSTEM_IMPL_EXPORT MojoResult SetProperty(MojoPropertyType type, - const void* value); - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_EMBEDDER_H_ diff --git a/mojo/edk/embedder/embedder_internal.h b/mojo/edk/embedder/embedder_internal.h deleted file mode 100644 index 7deeca1..0000000 --- a/mojo/edk/embedder/embedder_internal.h +++ /dev/null @@ -1,44 +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. - -// This header contains internal details for the *implementation* of the -// embedder API. It should not be included by any public header (nor by users of -// the embedder API). - -#ifndef MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ -#define MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ - -#include - -#include "mojo/edk/system/system_impl_export.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { - -namespace edk { - -class Broker; -class Core; -class ProcessDelegate; - -namespace internal { - -// Instance of |Broker| to use. -extern Broker* g_broker; - -// Instance of |Core| used by the system functions (|Mojo...()|). -extern MOJO_SYSTEM_IMPL_EXPORT Core* g_core; -extern base::TaskRunner* g_delegate_thread_task_runner; -extern ProcessDelegate* g_process_delegate; - -} // namespace internal - -} // namepace edk - -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_ diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc deleted file mode 100644 index 388b45c..0000000 --- a/mojo/edk/embedder/embedder_unittest.cc +++ /dev/null @@ -1,603 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/embedder.h" - -#include -#include -#include - -#include - -#include "base/base_paths.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/shared_memory.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/process/process_handle.h" -#include "base/run_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/test_timeouts.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/named_platform_handle.h" -#include "mojo/edk/embedder/named_platform_handle_utils.h" -#include "mojo/edk/embedder/pending_process_connection.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/test_embedder.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/public/c/system/core.h" -#include "mojo/public/cpp/system/handle.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "mojo/public/cpp/system/wait.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -// The multiprocess tests that use these don't compile on iOS. -#if !defined(OS_IOS) -const char kHelloWorld[] = "hello world"; -const char kByeWorld[] = "bye world"; -#endif - -using EmbedderTest = test::MojoTestBase; - -TEST_F(EmbedderTest, ChannelBasic) { - MojoHandle server_mp, client_mp; - CreateMessagePipe(&server_mp, &client_mp); - - const std::string kHello = "hello"; - - // We can write to a message pipe handle immediately. - WriteMessage(server_mp, kHello); - EXPECT_EQ(kHello, ReadMessage(client_mp)); - - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); -} - -// Verifies that a MP with pending messages to be written can be sent and the -// pending messages aren't dropped. -TEST_F(EmbedderTest, SendMessagePipeWithWriteQueue) { - MojoHandle server_mp, client_mp; - CreateMessagePipe(&server_mp, &client_mp); - - MojoHandle server_mp2, client_mp2; - CreateMessagePipe(&server_mp2, &client_mp2); - - static const size_t kNumMessages = 1001; - for (size_t i = 1; i <= kNumMessages; i++) - WriteMessage(client_mp2, std::string(i, 'A' + (i % 26))); - - // Now send client2. - WriteMessageWithHandles(server_mp, "hey", &client_mp2, 1); - client_mp2 = MOJO_HANDLE_INVALID; - - // Read client2 just so we can close it later. - EXPECT_EQ("hey", ReadMessageWithHandles(client_mp, &client_mp2, 1)); - EXPECT_NE(MOJO_HANDLE_INVALID, client_mp2); - - // Now verify that all the messages that were written were sent correctly. - for (size_t i = 1; i <= kNumMessages; i++) - ASSERT_EQ(std::string(i, 'A' + (i % 26)), ReadMessage(server_mp2)); - - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(server_mp2)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(client_mp2)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); -} - -TEST_F(EmbedderTest, ChannelsHandlePassing) { - MojoHandle server_mp, client_mp; - CreateMessagePipe(&server_mp, &client_mp); - EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); - EXPECT_NE(client_mp, MOJO_HANDLE_INVALID); - - MojoHandle h0, h1; - CreateMessagePipe(&h0, &h1); - - // Write a message to |h0| (attaching nothing). - const std::string kHello = "hello"; - WriteMessage(h0, kHello); - - // Write one message to |server_mp|, attaching |h1|. - const std::string kWorld = "world!!!"; - WriteMessageWithHandles(server_mp, kWorld, &h1, 1); - h1 = MOJO_HANDLE_INVALID; - - // Write another message to |h0|. - const std::string kFoo = "foo"; - WriteMessage(h0, kFoo); - - // Wait for |client_mp| to become readable and read a message from it. - EXPECT_EQ(kWorld, ReadMessageWithHandles(client_mp, &h1, 1)); - EXPECT_NE(h1, MOJO_HANDLE_INVALID); - - // Wait for |h1| to become readable and read a message from it. - EXPECT_EQ(kHello, ReadMessage(h1)); - - // Wait for |h1| to become readable (again) and read its second message. - EXPECT_EQ(kFoo, ReadMessage(h1)); - - // Write a message to |h1|. - const std::string kBarBaz = "barbaz"; - WriteMessage(h1, kBarBaz); - - // Wait for |h0| to become readable and read a message from it. - EXPECT_EQ(kBarBaz, ReadMessage(h0)); - - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(h0)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(h1)); -} - -TEST_F(EmbedderTest, PipeSetup) { - // Ensures that a pending process connection's message pipe can be claimed by - // the host process itself. - PendingProcessConnection process; - std::string pipe_token; - ScopedMessagePipeHandle parent_mp = process.CreateMessagePipe(&pipe_token); - ScopedMessagePipeHandle child_mp = CreateChildMessagePipe(pipe_token); - - const std::string kHello = "hello"; - WriteMessage(parent_mp.get().value(), kHello); - - EXPECT_EQ(kHello, ReadMessage(child_mp.get().value())); -} - -TEST_F(EmbedderTest, PipeSetup_LaunchDeath) { - PlatformChannelPair pair; - - PendingProcessConnection process; - std::string pipe_token; - ScopedMessagePipeHandle parent_mp = process.CreateMessagePipe(&pipe_token); - process.Connect(base::GetCurrentProcessHandle(), - ConnectionParams(pair.PassServerHandle())); - - // Close the remote end, simulating child death before the child connects to - // the reserved port. - ignore_result(pair.PassClientHandle()); - - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(parent_mp.get().value(), - MOJO_HANDLE_SIGNAL_PEER_CLOSED)); -} - -TEST_F(EmbedderTest, PipeSetup_LaunchFailure) { - PlatformChannelPair pair; - - auto process = base::MakeUnique(); - std::string pipe_token; - ScopedMessagePipeHandle parent_mp = process->CreateMessagePipe(&pipe_token); - - // Ensure that if a PendingProcessConnection goes away before Connect() is - // called, any message pipes associated with it detect peer closure. - process.reset(); - - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(parent_mp.get().value(), - MOJO_HANDLE_SIGNAL_PEER_CLOSED)); -} - -// The sequence of messages sent is: -// server_mp client_mp mp0 mp1 mp2 mp3 -// 1. "hello" -// 2. "world!" -// 3. "FOO" -// 4. "Bar"+mp1 -// 5. (close) -// 6. (close) -// 7. "baz" -// 8. (closed) -// 9. "quux"+mp2 -// 10. (close) -// 11. (wait/cl.) -// 12. (wait/cl.) - -#if !defined(OS_IOS) - -TEST_F(EmbedderTest, MultiprocessChannels) { - RUN_CHILD_ON_PIPE(MultiprocessChannelsClient, server_mp) - // 1. Write a message to |server_mp| (attaching nothing). - WriteMessage(server_mp, "hello"); - - // 2. Read a message from |server_mp|. - EXPECT_EQ("world!", ReadMessage(server_mp)); - - // 3. Create a new message pipe (endpoints |mp0| and |mp1|). - MojoHandle mp0, mp1; - CreateMessagePipe(&mp0, &mp1); - - // 4. Write something to |mp0|. - WriteMessage(mp0, "FOO"); - - // 5. Write a message to |server_mp|, attaching |mp1|. - WriteMessageWithHandles(server_mp, "Bar", &mp1, 1); - mp1 = MOJO_HANDLE_INVALID; - - // 6. Read a message from |mp0|, which should have |mp2| attached. - MojoHandle mp2 = MOJO_HANDLE_INVALID; - EXPECT_EQ("quux", ReadMessageWithHandles(mp0, &mp2, 1)); - - // 7. Read a message from |mp2|. - EXPECT_EQ("baz", ReadMessage(mp2)); - - // 8. Close |mp0|. - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp0)); - - // 9. Tell the client to quit. - WriteMessage(server_mp, "quit"); - - // 10. Wait on |mp2| (which should eventually fail) and then close it. - MojoHandleSignalsState state; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(mp2, MOJO_HANDLE_SIGNAL_READABLE, &state)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); - - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp2)); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessChannelsClient, EmbedderTest, - client_mp) { - // 1. Read the first message from |client_mp|. - EXPECT_EQ("hello", ReadMessage(client_mp)); - - // 2. Write a message to |client_mp| (attaching nothing). - WriteMessage(client_mp, "world!"); - - // 4. Read a message from |client_mp|, which should have |mp1| attached. - MojoHandle mp1; - EXPECT_EQ("Bar", ReadMessageWithHandles(client_mp, &mp1, 1)); - - // 5. Create a new message pipe (endpoints |mp2| and |mp3|). - MojoHandle mp2, mp3; - CreateMessagePipe(&mp2, &mp3); - - // 6. Write a message to |mp3|. - WriteMessage(mp3, "baz"); - - // 7. Close |mp3|. - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp3)); - - // 8. Write a message to |mp1|, attaching |mp2|. - WriteMessageWithHandles(mp1, "quux", &mp2, 1); - mp2 = MOJO_HANDLE_INVALID; - - // 9. Read a message from |mp1|. - EXPECT_EQ("FOO", ReadMessage(mp1)); - - EXPECT_EQ("quit", ReadMessage(client_mp)); - - // 10. Wait on |mp1| (which should eventually fail) and then close it. - MojoHandleSignalsState state; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(mp1, MOJO_HANDLE_SIGNAL_READABLE, &state)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); -} - -TEST_F(EmbedderTest, MultiprocessBaseSharedMemory) { - RUN_CHILD_ON_PIPE(MultiprocessSharedMemoryClient, server_mp) - // 1. Create a base::SharedMemory object and create a mojo shared buffer - // from it. - base::SharedMemoryCreateOptions options; - options.size = 123; - base::SharedMemory shared_memory; - ASSERT_TRUE(shared_memory.Create(options)); - base::SharedMemoryHandle shm_handle = base::SharedMemory::DuplicateHandle( - shared_memory.handle()); - MojoHandle sb1; - ASSERT_EQ(MOJO_RESULT_OK, - CreateSharedBufferWrapper(shm_handle, 123, false, &sb1)); - - // 2. Map |sb1| and write something into it. - char* buffer = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, - MojoMapBuffer(sb1, 0, 123, reinterpret_cast(&buffer), 0)); - ASSERT_TRUE(buffer); - memcpy(buffer, kHelloWorld, sizeof(kHelloWorld)); - - // 3. Duplicate |sb1| into |sb2| and pass to |server_mp|. - MojoHandle sb2 = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(sb1, 0, &sb2)); - EXPECT_NE(MOJO_HANDLE_INVALID, sb2); - WriteMessageWithHandles(server_mp, "hello", &sb2, 1); - - // 4. Read a message from |server_mp|. - EXPECT_EQ("bye", ReadMessage(server_mp)); - - // 5. Expect that the contents of the shared buffer have changed. - EXPECT_EQ(kByeWorld, std::string(buffer)); - - // 6. Map the original base::SharedMemory and expect it contains the - // expected value. - ASSERT_TRUE(shared_memory.Map(123)); - EXPECT_EQ(kByeWorld, - std::string(static_cast(shared_memory.memory()))); - - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(sb1)); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessSharedMemoryClient, EmbedderTest, - client_mp) { - // 1. Read the first message from |client_mp|, which should have |sb1| which - // should be a shared buffer handle. - MojoHandle sb1; - EXPECT_EQ("hello", ReadMessageWithHandles(client_mp, &sb1, 1)); - - // 2. Map |sb1|. - char* buffer = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, - MojoMapBuffer(sb1, 0, 123, reinterpret_cast(&buffer), 0)); - ASSERT_TRUE(buffer); - - // 3. Ensure |buffer| contains the values we expect. - EXPECT_EQ(kHelloWorld, std::string(buffer)); - - // 4. Write into |buffer| and send a message back. - memcpy(buffer, kByeWorld, sizeof(kByeWorld)); - WriteMessage(client_mp, "bye"); - - // 5. Extract the shared memory handle and ensure we can map it and read the - // contents. - base::SharedMemoryHandle shm_handle; - ASSERT_EQ(MOJO_RESULT_OK, - PassSharedMemoryHandle(sb1, &shm_handle, nullptr, nullptr)); - base::SharedMemory shared_memory(shm_handle, false); - ASSERT_TRUE(shared_memory.Map(123)); - EXPECT_NE(buffer, shared_memory.memory()); - EXPECT_EQ(kByeWorld, std::string(static_cast(shared_memory.memory()))); - - // 6. Close |sb1|. Should fail because |PassSharedMemoryHandle()| should have - // closed the handle. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(sb1)); -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -TEST_F(EmbedderTest, MultiprocessMachSharedMemory) { - RUN_CHILD_ON_PIPE(MultiprocessSharedMemoryClient, server_mp) - // 1. Create a Mach base::SharedMemory object and create a mojo shared - // buffer from it. - base::SharedMemoryCreateOptions options; - options.size = 123; - base::SharedMemory shared_memory; - ASSERT_TRUE(shared_memory.Create(options)); - base::SharedMemoryHandle shm_handle = base::SharedMemory::DuplicateHandle( - shared_memory.handle()); - MojoHandle sb1; - ASSERT_EQ(MOJO_RESULT_OK, - CreateSharedBufferWrapper(shm_handle, 123, false, &sb1)); - - // 2. Map |sb1| and write something into it. - char* buffer = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, - MojoMapBuffer(sb1, 0, 123, reinterpret_cast(&buffer), 0)); - ASSERT_TRUE(buffer); - memcpy(buffer, kHelloWorld, sizeof(kHelloWorld)); - - // 3. Duplicate |sb1| into |sb2| and pass to |server_mp|. - MojoHandle sb2 = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(sb1, 0, &sb2)); - EXPECT_NE(MOJO_HANDLE_INVALID, sb2); - WriteMessageWithHandles(server_mp, "hello", &sb2, 1); - - // 4. Read a message from |server_mp|. - EXPECT_EQ("bye", ReadMessage(server_mp)); - - // 5. Expect that the contents of the shared buffer have changed. - EXPECT_EQ(kByeWorld, std::string(buffer)); - - // 6. Map the original base::SharedMemory and expect it contains the - // expected value. - ASSERT_TRUE(shared_memory.Map(123)); - EXPECT_EQ(kByeWorld, - std::string(static_cast(shared_memory.memory()))); - - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(sb1)); - END_CHILD() -} - -enum class HandleType { - POSIX, - MACH, - MACH_NULL, -}; - -const HandleType kTestHandleTypes[] = { - HandleType::MACH, - HandleType::MACH_NULL, - HandleType::POSIX, - HandleType::POSIX, - HandleType::MACH, -}; - -// Test that we can mix file descriptors and mach port handles. -TEST_F(EmbedderTest, MultiprocessMixMachAndFds) { - const size_t kShmSize = 1234; - RUN_CHILD_ON_PIPE(MultiprocessMixMachAndFdsClient, server_mp) - // 1. Create fds or Mach objects and mojo handles from them. - MojoHandle platform_handles[arraysize(kTestHandleTypes)]; - for (size_t i = 0; i < arraysize(kTestHandleTypes); i++) { - const auto type = kTestHandleTypes[i]; - ScopedPlatformHandle scoped_handle; - if (type == HandleType::POSIX) { - // The easiest source of fds is opening /dev/null. - base::File file(base::FilePath("/dev/null"), - base::File::FLAG_OPEN | base::File::FLAG_WRITE); - ASSERT_TRUE(file.IsValid()); - scoped_handle.reset(PlatformHandle(file.TakePlatformFile())); - EXPECT_EQ(PlatformHandle::Type::POSIX, scoped_handle.get().type); - } else if (type == HandleType::MACH_NULL) { - scoped_handle.reset(PlatformHandle( - static_cast(MACH_PORT_NULL))); - EXPECT_EQ(PlatformHandle::Type::MACH, scoped_handle.get().type); - } else { - base::SharedMemoryCreateOptions options; - options.size = kShmSize; - base::SharedMemory shared_memory; - ASSERT_TRUE(shared_memory.Create(options)); - base::SharedMemoryHandle shm_handle = - base::SharedMemory::DuplicateHandle(shared_memory.handle()); - scoped_handle.reset(PlatformHandle(shm_handle.GetMemoryObject())); - EXPECT_EQ(PlatformHandle::Type::MACH, scoped_handle.get().type); - } - ASSERT_EQ(MOJO_RESULT_OK, CreatePlatformHandleWrapper( - std::move(scoped_handle), platform_handles + i)); - } - - // 2. Send all the handles to the child. - WriteMessageWithHandles(server_mp, "hello", platform_handles, - arraysize(kTestHandleTypes)); - - // 3. Read a message from |server_mp|. - EXPECT_EQ("bye", ReadMessage(server_mp)); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessMixMachAndFdsClient, EmbedderTest, - client_mp) { - const int kNumHandles = arraysize(kTestHandleTypes); - MojoHandle platform_handles[kNumHandles]; - - // 1. Read from |client_mp|, which should have a message containing - // |kNumHandles| handles. - EXPECT_EQ("hello", - ReadMessageWithHandles(client_mp, platform_handles, kNumHandles)); - - // 2. Extract each handle, and verify the type. - for (int i = 0; i < kNumHandles; i++) { - const auto type = kTestHandleTypes[i]; - ScopedPlatformHandle scoped_handle; - ASSERT_EQ(MOJO_RESULT_OK, - PassWrappedPlatformHandle(platform_handles[i], &scoped_handle)); - if (type == HandleType::POSIX) { - EXPECT_NE(0, scoped_handle.get().handle); - EXPECT_EQ(PlatformHandle::Type::POSIX, scoped_handle.get().type); - } else if (type == HandleType::MACH_NULL) { - EXPECT_EQ(static_cast(MACH_PORT_NULL), - scoped_handle.get().port); - EXPECT_EQ(PlatformHandle::Type::MACH, scoped_handle.get().type); - } else { - EXPECT_NE(static_cast(MACH_PORT_NULL), - scoped_handle.get().port); - EXPECT_EQ(PlatformHandle::Type::MACH, scoped_handle.get().type); - } - } - - // 3. Say bye! - WriteMessage(client_mp, "bye"); -} - -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -// TODO(vtl): Test immediate write & close. -// TODO(vtl): Test broken-connection cases. - -#endif // !defined(OS_IOS) - -NamedPlatformHandle GenerateChannelName() { -#if defined(OS_POSIX) - base::FilePath temp_dir; - CHECK(base::PathService::Get(base::DIR_TEMP, &temp_dir)); - return NamedPlatformHandle( - temp_dir.AppendASCII(GenerateRandomToken()).value()); -#else - return NamedPlatformHandle(GenerateRandomToken()); -#endif -} - -void CreateClientHandleOnIoThread(const NamedPlatformHandle& named_handle, - ScopedPlatformHandle* output) { - *output = CreateClientHandle(named_handle); -} - -TEST_F(EmbedderTest, ClosePendingPeerConnection) { - NamedPlatformHandle named_handle = GenerateChannelName(); - std::string peer_token = GenerateRandomToken(); - ScopedMessagePipeHandle server_pipe = - ConnectToPeerProcess(CreateServerHandle(named_handle), peer_token); - ClosePeerConnection(peer_token); - EXPECT_EQ(MOJO_RESULT_OK, - Wait(server_pipe.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - base::MessageLoop message_loop; - base::RunLoop run_loop; - ScopedPlatformHandle client_handle; - // Closing the channel involves posting a task to the IO thread to do the - // work. By the time the local message pipe has been observerd as closed, - // that task will have been posted. Therefore, a task to create the client - // connection should be handled after the channel is closed. - GetIOTaskRunner()->PostTaskAndReply( - FROM_HERE, - base::Bind(&CreateClientHandleOnIoThread, named_handle, &client_handle), - run_loop.QuitClosure()); - run_loop.Run(); - EXPECT_FALSE(client_handle.is_valid()); -} - -#if !defined(OS_IOS) - -TEST_F(EmbedderTest, ClosePipeToConnectedPeer) { - set_launch_type(LaunchType::PEER); - auto& controller = StartClient("ClosePipeToConnectedPeerClient"); - MojoHandle server_mp = controller.pipe(); - // 1. Write a message to |server_mp| (attaching nothing). - WriteMessage(server_mp, "hello"); - - // 2. Read a message from |server_mp|. - EXPECT_EQ("world!", ReadMessage(server_mp)); - - controller.ClosePeerConnection(); - - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(server_mp, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - - EXPECT_EQ(0, controller.WaitForShutdown()); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ClosePipeToConnectedPeerClient, EmbedderTest, - client_mp) { - // 1. Read the first message from |client_mp|. - EXPECT_EQ("hello", ReadMessage(client_mp)); - - // 2. Write a message to |client_mp| (attaching nothing). - WriteMessage(client_mp, "world!"); - - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(client_mp, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); -} - -TEST_F(EmbedderTest, ClosePipeToConnectingPeer) { - set_launch_type(LaunchType::PEER); - auto& controller = StartClient("ClosePipeToConnectingPeerClient"); - controller.ClosePeerConnection(); - - MojoHandle server_mp = controller.pipe(); - - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(server_mp, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - - EXPECT_EQ(0, controller.WaitForShutdown()); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ClosePipeToConnectingPeerClient, EmbedderTest, - client_mp) { - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(client_mp, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); -} - -#endif // !defined(OS_IOS) - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc deleted file mode 100644 index 9081368..0000000 --- a/mojo/edk/embedder/entrypoints.cc +++ /dev/null @@ -1,283 +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/entrypoints.h" - -#include - -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/core.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/platform_handle.h" - -using mojo::edk::internal::g_core; - -// Definitions of the system functions. -extern "C" { - -MojoTimeTicks MojoGetTimeTicksNowImpl() { - return g_core->GetTimeTicksNow(); -} - -MojoResult MojoCloseImpl(MojoHandle handle) { - return g_core->Close(handle); -} - -MojoResult MojoQueryHandleSignalsStateImpl( - MojoHandle handle, - MojoHandleSignalsState* signals_state) { - return g_core->QueryHandleSignalsState(handle, signals_state); -} - -MojoResult MojoCreateWatcherImpl(MojoWatcherCallback callback, - MojoHandle* watcher_handle) { - return g_core->CreateWatcher(callback, watcher_handle); -} - -MojoResult MojoArmWatcherImpl(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) { - return g_core->ArmWatcher(watcher_handle, num_ready_contexts, ready_contexts, - ready_results, ready_signals_states); -} - -MojoResult MojoWatchImpl(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - uintptr_t context) { - return g_core->Watch(watcher_handle, handle, signals, context); -} - -MojoResult MojoCancelWatchImpl(MojoHandle watcher_handle, uintptr_t context) { - return g_core->CancelWatch(watcher_handle, context); -} - -MojoResult MojoAllocMessageImpl(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message) { - return g_core->AllocMessage(num_bytes, handles, num_handles, flags, message); -} - -MojoResult MojoFreeMessageImpl(MojoMessageHandle message) { - return g_core->FreeMessage(message); -} - -MojoResult MojoGetMessageBufferImpl(MojoMessageHandle message, void** buffer) { - return g_core->GetMessageBuffer(message, buffer); -} - -MojoResult MojoCreateMessagePipeImpl( - const MojoCreateMessagePipeOptions* options, - MojoHandle* message_pipe_handle0, - MojoHandle* message_pipe_handle1) { - return g_core->CreateMessagePipe(options, message_pipe_handle0, - message_pipe_handle1); -} - -MojoResult MojoWriteMessageImpl(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags) { - return g_core->WriteMessage(message_pipe_handle, bytes, num_bytes, handles, - num_handles, flags); -} - -MojoResult MojoWriteMessageNewImpl(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags flags) { - return g_core->WriteMessageNew(message_pipe_handle, message, flags); -} - -MojoResult MojoReadMessageImpl(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - return g_core->ReadMessage( - message_pipe_handle, bytes, num_bytes, handles, num_handles, flags); -} - -MojoResult MojoReadMessageNewImpl(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - return g_core->ReadMessageNew( - message_pipe_handle, message, num_bytes, handles, num_handles, flags); -} - -MojoResult MojoFuseMessagePipesImpl(MojoHandle handle0, MojoHandle handle1) { - return g_core->FuseMessagePipes(handle0, handle1); -} - -MojoResult MojoCreateDataPipeImpl(const MojoCreateDataPipeOptions* options, - MojoHandle* data_pipe_producer_handle, - MojoHandle* data_pipe_consumer_handle) { - return g_core->CreateDataPipe(options, data_pipe_producer_handle, - data_pipe_consumer_handle); -} - -MojoResult MojoWriteDataImpl(MojoHandle data_pipe_producer_handle, - const void* elements, - uint32_t* num_elements, - MojoWriteDataFlags flags) { - return g_core->WriteData(data_pipe_producer_handle, elements, num_elements, - flags); -} - -MojoResult MojoBeginWriteDataImpl(MojoHandle data_pipe_producer_handle, - void** buffer, - uint32_t* buffer_num_elements, - MojoWriteDataFlags flags) { - return g_core->BeginWriteData(data_pipe_producer_handle, buffer, - buffer_num_elements, flags); -} - -MojoResult MojoEndWriteDataImpl(MojoHandle data_pipe_producer_handle, - uint32_t num_elements_written) { - return g_core->EndWriteData(data_pipe_producer_handle, num_elements_written); -} - -MojoResult MojoReadDataImpl(MojoHandle data_pipe_consumer_handle, - void* elements, - uint32_t* num_elements, - MojoReadDataFlags flags) { - return g_core->ReadData(data_pipe_consumer_handle, elements, num_elements, - flags); -} - -MojoResult MojoBeginReadDataImpl(MojoHandle data_pipe_consumer_handle, - const void** buffer, - uint32_t* buffer_num_elements, - MojoReadDataFlags flags) { - return g_core->BeginReadData(data_pipe_consumer_handle, buffer, - buffer_num_elements, flags); -} - -MojoResult MojoEndReadDataImpl(MojoHandle data_pipe_consumer_handle, - uint32_t num_elements_read) { - return g_core->EndReadData(data_pipe_consumer_handle, num_elements_read); -} - -MojoResult MojoCreateSharedBufferImpl( - const struct MojoCreateSharedBufferOptions* options, - uint64_t num_bytes, - MojoHandle* shared_buffer_handle) { - return g_core->CreateSharedBuffer(options, num_bytes, shared_buffer_handle); -} - -MojoResult MojoDuplicateBufferHandleImpl( - MojoHandle buffer_handle, - const struct MojoDuplicateBufferHandleOptions* options, - MojoHandle* new_buffer_handle) { - return g_core->DuplicateBufferHandle(buffer_handle, options, - new_buffer_handle); -} - -MojoResult MojoMapBufferImpl(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - void** buffer, - MojoMapBufferFlags flags) { - return g_core->MapBuffer(buffer_handle, offset, num_bytes, buffer, flags); -} - -MojoResult MojoUnmapBufferImpl(void* buffer) { - return g_core->UnmapBuffer(buffer); -} - -MojoResult MojoWrapPlatformHandleImpl(const MojoPlatformHandle* platform_handle, - MojoHandle* mojo_handle) { - return g_core->WrapPlatformHandle(platform_handle, mojo_handle); -} - -MojoResult MojoUnwrapPlatformHandleImpl(MojoHandle mojo_handle, - MojoPlatformHandle* platform_handle) { - return g_core->UnwrapPlatformHandle(mojo_handle, platform_handle); -} - -MojoResult MojoWrapPlatformSharedBufferHandleImpl( - const MojoPlatformHandle* platform_handle, - size_t num_bytes, - MojoPlatformSharedBufferHandleFlags flags, - MojoHandle* mojo_handle) { - return g_core->WrapPlatformSharedBufferHandle(platform_handle, num_bytes, - flags, mojo_handle); -} - -MojoResult MojoUnwrapPlatformSharedBufferHandleImpl( - MojoHandle mojo_handle, - MojoPlatformHandle* platform_handle, - size_t* num_bytes, - MojoPlatformSharedBufferHandleFlags* flags) { - return g_core->UnwrapPlatformSharedBufferHandle(mojo_handle, platform_handle, - num_bytes, flags); -} - -MojoResult MojoNotifyBadMessageImpl(MojoMessageHandle message, - const char* error, - size_t error_num_bytes) { - return g_core->NotifyBadMessage(message, error, error_num_bytes); -} - -MojoResult MojoGetPropertyImpl(MojoPropertyType type, void* value) { - return g_core->GetProperty(type, value); -} - -} // extern "C" - -namespace mojo { -namespace edk { - -MojoSystemThunks MakeSystemThunks() { - MojoSystemThunks system_thunks = {sizeof(MojoSystemThunks), - MojoGetTimeTicksNowImpl, - MojoCloseImpl, - MojoQueryHandleSignalsStateImpl, - MojoCreateMessagePipeImpl, - MojoWriteMessageImpl, - MojoReadMessageImpl, - MojoCreateDataPipeImpl, - MojoWriteDataImpl, - MojoBeginWriteDataImpl, - MojoEndWriteDataImpl, - MojoReadDataImpl, - MojoBeginReadDataImpl, - MojoEndReadDataImpl, - MojoCreateSharedBufferImpl, - MojoDuplicateBufferHandleImpl, - MojoMapBufferImpl, - MojoUnmapBufferImpl, - MojoCreateWatcherImpl, - MojoWatchImpl, - MojoCancelWatchImpl, - MojoArmWatcherImpl, - MojoFuseMessagePipesImpl, - MojoWriteMessageNewImpl, - MojoReadMessageNewImpl, - MojoAllocMessageImpl, - MojoFreeMessageImpl, - MojoGetMessageBufferImpl, - MojoWrapPlatformHandleImpl, - MojoUnwrapPlatformHandleImpl, - MojoWrapPlatformSharedBufferHandleImpl, - MojoUnwrapPlatformSharedBufferHandleImpl, - MojoNotifyBadMessageImpl, - MojoGetPropertyImpl}; - return system_thunks; -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/entrypoints.h b/mojo/edk/embedder/entrypoints.h deleted file mode 100644 index 8e448c1..0000000 --- a/mojo/edk/embedder/entrypoints.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_ENTRYPOINTS_H_ -#define MOJO_EDK_EMBEDDER_ENTRYPOINTS_H_ - -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/thunks.h" - -namespace mojo { -namespace edk { - -// Creates a MojoSystemThunks struct populated with the EDK's implementation of -// each function. This may be used by embedders to populate thunks for -// application loading. -MOJO_SYSTEM_IMPL_EXPORT MojoSystemThunks MakeSystemThunks(); - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_ENTRYPOINTS_H_ diff --git a/mojo/edk/embedder/named_platform_channel_pair.h b/mojo/edk/embedder/named_platform_channel_pair.h deleted file mode 100644 index 5a83ae3..0000000 --- a/mojo/edk/embedder/named_platform_channel_pair.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_NAMED_PLATFORM_CHANNEL_PAIR_H_ -#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_CHANNEL_PAIR_H_ - -#include - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/named_platform_handle.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace base { -class CommandLine; -} - -namespace mojo { -namespace edk { - -// This is used to create a named bidirectional pipe to connect new child -// processes. The resulting server handle should be passed to the EDK, and the -// child end passed as a pipe name on the command line to the child process. The -// child process can then retrieve the pipe name from the command line and -// resolve it into a client handle. -class MOJO_SYSTEM_IMPL_EXPORT NamedPlatformChannelPair { - public: - struct Options { -#if defined(OS_WIN) - // If non-empty, a security descriptor to use when creating the pipe. If - // empty, a default security descriptor will be used. See - // kDefaultSecurityDescriptor in named_platform_handle_utils_win.cc. - base::string16 security_descriptor; -#endif - }; - - NamedPlatformChannelPair(const Options& options = {}); - ~NamedPlatformChannelPair(); - - // Note: It is NOT acceptable to use this handle as a generic pipe channel. It - // MUST be passed to PendingProcessConnection::Connect() only. - ScopedPlatformHandle PassServerHandle(); - - // To be called in the child process, after the parent process called - // |PrepareToPassClientHandleToChildProcess()| and launched the child (using - // the provided data), to create a client handle connected to the server - // handle (in the parent process). - static ScopedPlatformHandle PassClientHandleFromParentProcess( - const base::CommandLine& command_line); - - // Prepares to pass the client channel to a new child process, to be launched - // using |LaunchProcess()| (from base/launch.h). Modifies |*command_line| and - // |*handle_passing_info| as needed. - // Note: For Windows, this method only works on Vista and later. - void PrepareToPassClientHandleToChildProcess( - base::CommandLine* command_line) const; - - const NamedPlatformHandle& handle() const { return pipe_handle_; } - - private: - NamedPlatformHandle pipe_handle_; - ScopedPlatformHandle server_handle_; - - DISALLOW_COPY_AND_ASSIGN(NamedPlatformChannelPair); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_CHANNEL_PAIR_H_ diff --git a/mojo/edk/embedder/named_platform_channel_pair_win.cc b/mojo/edk/embedder/named_platform_channel_pair_win.cc deleted file mode 100644 index 96589ff..0000000 --- a/mojo/edk/embedder/named_platform_channel_pair_win.cc +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/named_platform_channel_pair.h" - -#include - -#include -#include -#include - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/win/windows_version.h" -#include "mojo/edk/embedder/named_platform_handle_utils.h" -#include "mojo/edk/embedder/platform_handle.h" - -namespace mojo { -namespace edk { - -namespace { - -const char kMojoNamedPlatformChannelPipeSwitch[] = - "mojo-named-platform-channel-pipe"; - -std::wstring GeneratePipeName() { - return base::StringPrintf(L"%u.%u.%I64u", GetCurrentProcessId(), - GetCurrentThreadId(), base::RandUint64()); -} - -} // namespace - -NamedPlatformChannelPair::NamedPlatformChannelPair( - const NamedPlatformChannelPair::Options& options) - : pipe_handle_(GeneratePipeName()) { - CreateServerHandleOptions server_handle_options; - server_handle_options.security_descriptor = options.security_descriptor; - server_handle_options.enforce_uniqueness = true; - server_handle_ = CreateServerHandle(pipe_handle_, server_handle_options); - PCHECK(server_handle_.is_valid()); -} - -NamedPlatformChannelPair::~NamedPlatformChannelPair() {} - -ScopedPlatformHandle NamedPlatformChannelPair::PassServerHandle() { - return std::move(server_handle_); -} - -// static -ScopedPlatformHandle -NamedPlatformChannelPair::PassClientHandleFromParentProcess( - const base::CommandLine& command_line) { - // In order to support passing the pipe name on the command line, the pipe - // handle is lazily created from the pipe name when requested. - NamedPlatformHandle handle( - command_line.GetSwitchValueNative(kMojoNamedPlatformChannelPipeSwitch)); - - if (!handle.is_valid()) - return ScopedPlatformHandle(); - - return CreateClientHandle(handle); -} - -void NamedPlatformChannelPair::PrepareToPassClientHandleToChildProcess( - base::CommandLine* command_line) const { - DCHECK(command_line); - - // Log a warning if the command line already has the switch, but "clobber" it - // anyway, since it's reasonably likely that all the switches were just copied - // from the parent. - LOG_IF(WARNING, - command_line->HasSwitch(kMojoNamedPlatformChannelPipeSwitch)) - << "Child command line already has switch --" - << kMojoNamedPlatformChannelPipeSwitch << "=" - << command_line->GetSwitchValueNative( - kMojoNamedPlatformChannelPipeSwitch); - // (Any existing switch won't actually be removed from the command line, but - // the last one appended takes precedence.) - command_line->AppendSwitchNative(kMojoNamedPlatformChannelPipeSwitch, - pipe_handle_.name); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/named_platform_handle.h b/mojo/edk/embedder/named_platform_handle.h deleted file mode 100644 index 15ca656..0000000 --- a/mojo/edk/embedder/named_platform_handle.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_ -#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_ - -#include - -#include "base/strings/string16.h" -#include "base/strings/string_piece.h" -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -#if defined(OS_POSIX) -struct MOJO_SYSTEM_IMPL_EXPORT NamedPlatformHandle { - NamedPlatformHandle() {} - explicit NamedPlatformHandle(const base::StringPiece& name) - : name(name.as_string()) {} - - bool is_valid() const { return !name.empty(); } - - std::string name; -}; -#elif defined(OS_WIN) -struct MOJO_SYSTEM_IMPL_EXPORT NamedPlatformHandle { - NamedPlatformHandle() {} - explicit NamedPlatformHandle(const base::StringPiece& name) - : name(base::UTF8ToUTF16(name)) {} - - explicit NamedPlatformHandle(const base::StringPiece16& name) - : name(name.as_string()) {} - - bool is_valid() const { return !name.empty(); } - - base::string16 pipe_name() const { return L"\\\\.\\pipe\\mojo." + name; } - - base::string16 name; -}; -#else -#error "Platform not yet supported." -#endif - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_H_ diff --git a/mojo/edk/embedder/named_platform_handle_utils.h b/mojo/edk/embedder/named_platform_handle_utils.h deleted file mode 100644 index b767ea0..0000000 --- a/mojo/edk/embedder/named_platform_handle_utils.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_UTILS_H_ -#define MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_UTILS_H_ - -#include "build/build_config.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" - -#if defined(OS_WIN) -#include "base/strings/string16.h" -#endif - -namespace mojo { -namespace edk { - -struct NamedPlatformHandle; - -#if defined(OS_POSIX) - -// The maximum length of the name of a unix domain socket. The standard size on -// linux is 108, mac is 104. To maintain consistency across platforms we -// standardize on the smaller value. -const size_t kMaxSocketNameLength = 104; - -#endif - -struct CreateServerHandleOptions { -#if defined(OS_WIN) - // If true, creating a server handle will fail if another pipe with the same - // name exists. - bool enforce_uniqueness = true; - - // If non-empty, a security descriptor to use when creating the pipe. If - // empty, a default security descriptor will be used. See - // kDefaultSecurityDescriptor in named_platform_handle_utils_win.cc. - base::string16 security_descriptor; -#endif -}; - -// Creates a client platform handle from |handle|. This may block until |handle| -// is ready to receive connections. -MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle -CreateClientHandle(const NamedPlatformHandle& handle); - -// Creates a server platform handle from |handle|. -MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle -CreateServerHandle(const NamedPlatformHandle& handle, - const CreateServerHandleOptions& options = {}); - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_NAMED_PLATFORM_HANDLE_UTILS_H_ diff --git a/mojo/edk/embedder/named_platform_handle_utils_posix.cc b/mojo/edk/embedder/named_platform_handle_utils_posix.cc deleted file mode 100644 index 056f4d6..0000000 --- a/mojo/edk/embedder/named_platform_handle_utils_posix.cc +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/named_platform_handle_utils.h" - -#include -#include -#include -#include - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "mojo/edk/embedder/named_platform_handle.h" - -namespace mojo { -namespace edk { -namespace { - -// This function fills in |unix_addr| with the appropriate data for the socket, -// and sets |unix_addr_len| to the length of the data therein. -// Returns true on success, or false on failure (typically because |handle.name| -// violated the naming rules). -bool MakeUnixAddr(const NamedPlatformHandle& handle, - struct sockaddr_un* unix_addr, - size_t* unix_addr_len) { - DCHECK(unix_addr); - DCHECK(unix_addr_len); - DCHECK(handle.is_valid()); - - // We reject handle.name.length() == kMaxSocketNameLength to make room for the - // NUL terminator at the end of the string. - if (handle.name.length() >= kMaxSocketNameLength) { - LOG(ERROR) << "Socket name too long: " << handle.name; - return false; - } - - // Create unix_addr structure. - memset(unix_addr, 0, sizeof(struct sockaddr_un)); - unix_addr->sun_family = AF_UNIX; - strncpy(unix_addr->sun_path, handle.name.c_str(), kMaxSocketNameLength); - *unix_addr_len = - offsetof(struct sockaddr_un, sun_path) + handle.name.length(); - return true; -} - -// This function creates a unix domain socket, and set it as non-blocking. -// If successful, this returns a ScopedPlatformHandle containing the socket. -// Otherwise, this returns an invalid ScopedPlatformHandle. -ScopedPlatformHandle CreateUnixDomainSocket(bool needs_connection) { - // Create the unix domain socket. - PlatformHandle socket_handle(socket(AF_UNIX, SOCK_STREAM, 0)); - socket_handle.needs_connection = needs_connection; - ScopedPlatformHandle handle(socket_handle); - if (!handle.is_valid()) { - PLOG(ERROR) << "Failed to create AF_UNIX socket."; - return ScopedPlatformHandle(); - } - - // Now set it as non-blocking. - if (!base::SetNonBlocking(handle.get().handle)) { - PLOG(ERROR) << "base::SetNonBlocking() failed " << handle.get().handle; - return ScopedPlatformHandle(); - } - return handle; -} - -} // namespace - -ScopedPlatformHandle CreateClientHandle( - const NamedPlatformHandle& named_handle) { - if (!named_handle.is_valid()) - return ScopedPlatformHandle(); - - struct sockaddr_un unix_addr; - size_t unix_addr_len; - if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len)) - return ScopedPlatformHandle(); - - ScopedPlatformHandle handle = CreateUnixDomainSocket(false); - if (!handle.is_valid()) - return ScopedPlatformHandle(); - - if (HANDLE_EINTR(connect(handle.get().handle, - reinterpret_cast(&unix_addr), - unix_addr_len)) < 0) { - PLOG(ERROR) << "connect " << named_handle.name; - return ScopedPlatformHandle(); - } - - return handle; -} - -ScopedPlatformHandle CreateServerHandle( - const NamedPlatformHandle& named_handle, - const CreateServerHandleOptions& options) { - if (!named_handle.is_valid()) - return ScopedPlatformHandle(); - - // Make sure the path we need exists. - base::FilePath socket_dir = base::FilePath(named_handle.name).DirName(); - if (!base::CreateDirectory(socket_dir)) { - LOG(ERROR) << "Couldn't create directory: " << socket_dir.value(); - return ScopedPlatformHandle(); - } - - // Delete any old FS instances. - if (unlink(named_handle.name.c_str()) < 0 && errno != ENOENT) { - PLOG(ERROR) << "unlink " << named_handle.name; - return ScopedPlatformHandle(); - } - - struct sockaddr_un unix_addr; - size_t unix_addr_len; - if (!MakeUnixAddr(named_handle, &unix_addr, &unix_addr_len)) - return ScopedPlatformHandle(); - - ScopedPlatformHandle handle = CreateUnixDomainSocket(true); - if (!handle.is_valid()) - return ScopedPlatformHandle(); - - // Bind the socket. - if (bind(handle.get().handle, reinterpret_cast(&unix_addr), - unix_addr_len) < 0) { - PLOG(ERROR) << "bind " << named_handle.name; - return ScopedPlatformHandle(); - } - - // Start listening on the socket. - if (listen(handle.get().handle, SOMAXCONN) < 0) { - PLOG(ERROR) << "listen " << named_handle.name; - unlink(named_handle.name.c_str()); - return ScopedPlatformHandle(); - } - return handle; -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/named_platform_handle_utils_win.cc b/mojo/edk/embedder/named_platform_handle_utils_win.cc deleted file mode 100644 index a145847..0000000 --- a/mojo/edk/embedder/named_platform_handle_utils_win.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/named_platform_handle_utils.h" - -#include -#include - -#include - -#include "base/logging.h" -#include "base/win/windows_version.h" -#include "mojo/edk/embedder/named_platform_handle.h" - -namespace mojo { -namespace edk { -namespace { - -// A DACL to grant: -// GA = Generic All -// access to: -// SY = LOCAL_SYSTEM -// BA = BUILTIN_ADMINISTRATORS -// OW = OWNER_RIGHTS -constexpr base::char16 kDefaultSecurityDescriptor[] = - L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;OW)"; - -} // namespace - -ScopedPlatformHandle CreateClientHandle( - const NamedPlatformHandle& named_handle) { - if (!named_handle.is_valid()) - return ScopedPlatformHandle(); - - base::string16 pipe_name = named_handle.pipe_name(); - - // Note: This may block. - if (!WaitNamedPipeW(pipe_name.c_str(), NMPWAIT_USE_DEFAULT_WAIT)) - return ScopedPlatformHandle(); - - const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE; - // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate - // the client. - const DWORD kFlags = - SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED; - ScopedPlatformHandle handle( - PlatformHandle(CreateFileW(pipe_name.c_str(), kDesiredAccess, - 0, // No sharing. - nullptr, OPEN_EXISTING, kFlags, - nullptr))); // No template file. - // The server may have stopped accepting a connection between the - // WaitNamedPipe() and CreateFile(). If this occurs, an invalid handle is - // returned. - DPLOG_IF(ERROR, !handle.is_valid()) - << "Named pipe " << named_handle.pipe_name() - << " could not be opened after WaitNamedPipe succeeded"; - return handle; -} - -ScopedPlatformHandle CreateServerHandle( - const NamedPlatformHandle& named_handle, - const CreateServerHandleOptions& options) { - if (!named_handle.is_valid()) - return ScopedPlatformHandle(); - - PSECURITY_DESCRIPTOR security_desc = nullptr; - ULONG security_desc_len = 0; - PCHECK(ConvertStringSecurityDescriptorToSecurityDescriptor( - options.security_descriptor.empty() ? kDefaultSecurityDescriptor - : options.security_descriptor.c_str(), - SDDL_REVISION_1, &security_desc, &security_desc_len)); - std::unique_ptr p(security_desc, ::LocalFree); - SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES), - security_desc, FALSE}; - - const DWORD kOpenMode = options.enforce_uniqueness - ? PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | - FILE_FLAG_FIRST_PIPE_INSTANCE - : PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED; - const DWORD kPipeMode = - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS; - PlatformHandle handle( - CreateNamedPipeW(named_handle.pipe_name().c_str(), kOpenMode, kPipeMode, - options.enforce_uniqueness ? 1 : 255, // Max instances. - 4096, // Out buffer size. - 4096, // In buffer size. - 5000, // Timeout in milliseconds. - &security_attributes)); - handle.needs_connection = true; - return ScopedPlatformHandle(handle); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/pending_process_connection.cc b/mojo/edk/embedder/pending_process_connection.cc deleted file mode 100644 index d6be76e..0000000 --- a/mojo/edk/embedder/pending_process_connection.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/pending_process_connection.h" - -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/core.h" - -namespace mojo { -namespace edk { - -PendingProcessConnection::PendingProcessConnection() - : process_token_(GenerateRandomToken()) { - DCHECK(internal::g_core); -} - -PendingProcessConnection::~PendingProcessConnection() { - if (has_message_pipes_ && !connected_) { - DCHECK(internal::g_core); - internal::g_core->ChildLaunchFailed(process_token_); - } -} - -ScopedMessagePipeHandle PendingProcessConnection::CreateMessagePipe( - std::string* token) { - has_message_pipes_ = true; - DCHECK(internal::g_core); - *token = GenerateRandomToken(); - return internal::g_core->CreateParentMessagePipe(*token, process_token_); -} - -void PendingProcessConnection::Connect( - base::ProcessHandle process, - ConnectionParams connection_params, - const ProcessErrorCallback& error_callback) { - // It's now safe to avoid cleanup in the destructor, as the lifetime of any - // associated resources is effectively bound to the |channel| passed to - // AddChild() below. - DCHECK(!connected_); - connected_ = true; - - DCHECK(internal::g_core); - internal::g_core->AddChild(process, std::move(connection_params), - process_token_, error_callback); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/pending_process_connection.h b/mojo/edk/embedder/pending_process_connection.h deleted file mode 100644 index ca18227..0000000 --- a/mojo/edk/embedder/pending_process_connection.h +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_PENDING_PROCESS_CONNECTION_H_ -#define MOJO_EDK_EMBEDDER_PENDING_PROCESS_CONNECTION_H_ - -#include - -#include "base/callback.h" -#include "base/macros.h" -#include "base/process/process_handle.h" -#include "mojo/edk/embedder/connection_params.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" - -namespace mojo { -namespace edk { - -using ProcessErrorCallback = base::Callback; - -// Represents a potential connection to an external process. Use this object -// to make other processes reachable from this one via Mojo IPC. Typical usage -// might look something like: -// -// PendingProcessConnection connection; -// -// std::string pipe_token; -// ScopedMessagePipeHandle pipe = connection.CreateMessagePipe(&pipe_token); -// -// // New pipes to the process are fully functional and can be used right -// // away, even if the process doesn't exist yet. -// GoDoSomethingInteresting(std::move(pipe)); -// -// ScopedPlatformChannelPair channel; -// -// // Give the pipe token to the child process via command-line. -// child_command_line.AppendSwitchASCII("yer-pipe", pipe_token); -// -// // Magic child process launcher which gives one end of the pipe to the -// // new process. -// LaunchProcess(child_command_line, channel.PassClientHandle()); -// -// // Some time later... -// connection.Connect(new_process, channel.PassServerHandle()); -// -// If at any point during the above process, |connection| is destroyed before -// Connect() can be called, |pipe| will imminently behave as if its peer has -// been closed. -// -// Otherwise, if the remote process in this example eventually calls: -// -// mojo::edk::SetParentPipeHandle(std::move(client_channel_handle)); -// -// std::string token = command_line.GetSwitchValueASCII("yer-pipe"); -// ScopedMessagePipeHandle pipe = mojo::edk::CreateChildMessagePipe(token); -// -// it will be connected to this process, and its |pipe| will be connected to -// this process's |pipe|. -// -// If the remote process exits or otherwise closes its client channel handle -// before calling CreateChildMessagePipe for a given message pipe token, -// this process's end of the corresponding message pipe will imminently behave -// as if its peer has been closed. -// -class MOJO_SYSTEM_IMPL_EXPORT PendingProcessConnection { - public: - PendingProcessConnection(); - ~PendingProcessConnection(); - - // Creates a message pipe associated with a new globally unique string value - // which will be placed in |*token|. - // - // The other end of the new pipe is obtainable in the remote process (or in - // this process, to facilitate "single-process mode" in some applications) by - // passing the new |*token| value to mojo::edk::CreateChildMessagePipe. It's - // the caller's responsibility to communicate the value of |*token| to the - // remote process by any means available, e.g. a command-line argument on - // process launch, or some other out-of-band communication channel for an - // existing process. - // - // NOTES: This may be called any number of times to create multiple message - // pipes to the same remote process. This call ALWAYS succeeds, returning - // a valid message pipe handle and populating |*token| with a new unique - // string value. - ScopedMessagePipeHandle CreateMessagePipe(std::string* token); - - // Connects to the process. This must be called at most once, with the process - // handle in |process|. - // - // |connection_param| contains the platform handle of an OS pipe which can be - // used to communicate with the connected process. The other end of that pipe - // must ultimately be passed to mojo::edk::SetParentPipeHandle in the remote - // process, and getting that end of the pipe into the other process is the - // embedder's responsibility. - // - // If this method is not called by the time the PendingProcessConnection is - // destroyed, it's assumed that the process is unavailable (e.g. process - // launch failed or the process has otherwise been terminated early), and - // any associated resources, such as remote endpoints of messages pipes - // created by CreateMessagePipe above) will be cleaned up at that time. - void Connect( - base::ProcessHandle process, - ConnectionParams connection_params, - const ProcessErrorCallback& error_callback = ProcessErrorCallback()); - - private: - // A GUID representing a potential new process to be connected to this one. - const std::string process_token_; - - // Indicates whether this object has been used to create new message pipes. - bool has_message_pipes_ = false; - - // Indicates whether Connect() has been called yet. - bool connected_ = false; - - DISALLOW_COPY_AND_ASSIGN(PendingProcessConnection); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_PENDING_PROCESS_CONNECTION_H_ diff --git a/mojo/edk/embedder/platform_channel_pair.cc b/mojo/edk/embedder/platform_channel_pair.cc deleted file mode 100644 index ee1905a..0000000 --- a/mojo/edk/embedder/platform_channel_pair.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_channel_pair.h" - -#include - -#include "base/logging.h" - -namespace mojo { -namespace edk { - -const char PlatformChannelPair::kMojoPlatformChannelHandleSwitch[] = - "mojo-platform-channel-handle"; - -PlatformChannelPair::~PlatformChannelPair() { -} - -ScopedPlatformHandle PlatformChannelPair::PassServerHandle() { - return std::move(server_handle_); -} - -ScopedPlatformHandle PlatformChannelPair::PassClientHandle() { - return std::move(client_handle_); -} - -void PlatformChannelPair::ChildProcessLaunched() { - DCHECK(client_handle_.is_valid()); - client_handle_.reset(); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_channel_pair.h b/mojo/edk/embedder/platform_channel_pair.h deleted file mode 100644 index 9c93f76..0000000 --- a/mojo/edk/embedder/platform_channel_pair.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ -#define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ - -#include - -#include "base/macros.h" -#include "base/process/launch.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace base { -class CommandLine; -} - -namespace mojo { -namespace edk { - -// It would be nice to refactor base/process/launch.h to have a more platform- -// independent way of representing handles that are passed to child processes. -#if defined(OS_WIN) -using HandlePassingInformation = base::HandlesToInheritVector; -#elif defined(OS_POSIX) -using HandlePassingInformation = base::FileHandleMappingVector; -#else -#error "Unsupported." -#endif - -// This is used to create a pair of |PlatformHandle|s that are connected by a -// suitable (platform-specific) bidirectional "pipe" (e.g., socket on POSIX, -// named pipe on Windows). The resulting handles can then be used in the same -// process (e.g., in tests) or between processes. (The "server" handle is the -// one that will be used in the process that created the pair, whereas the -// "client" handle is the one that will be used in a different process.) -// -// This class provides facilities for passing the client handle to a child -// process. The parent should call |PrepareToPassClientHandlelToChildProcess()| -// to get the data needed to do this, spawn the child using that data, and then -// call |ChildProcessLaunched()|. Note that on Windows this facility (will) only -// work on Vista and later (TODO(vtl)). -// -// Note: |PlatformChannelPair()|, |PassClientHandleFromParentProcess()| and -// |PrepareToPassClientHandleToChildProcess()| have platform-specific -// implementations. -// -// Note: On POSIX platforms, to write to the "pipe", use -// |PlatformChannel{Write,Writev}()| (from platform_channel_utils_posix.h) -// instead of |write()|, |writev()|, etc. Otherwise, you have to worry about -// platform differences in suppressing |SIGPIPE|. -class MOJO_SYSTEM_IMPL_EXPORT PlatformChannelPair { - public: - static const char kMojoPlatformChannelHandleSwitch[]; - - // If |client_is_blocking| is true, then the client handle only supports - // blocking reads and writes. The default is nonblocking. - PlatformChannelPair(bool client_is_blocking = false); - ~PlatformChannelPair(); - - ScopedPlatformHandle PassServerHandle(); - - // For in-process use (e.g., in tests or to pass over another channel). - ScopedPlatformHandle PassClientHandle(); - - // To be called in the child process, after the parent process called - // |PrepareToPassClientHandleToChildProcess()| and launched the child (using - // the provided data), to create a client handle connected to the server - // handle (in the parent process). - // TODO(jcivelli): remove the command_line param. http://crbug.com/670106 - static ScopedPlatformHandle PassClientHandleFromParentProcess( - const base::CommandLine& command_line); - - // Like above, but gets the handle from the passed in string. - static ScopedPlatformHandle PassClientHandleFromParentProcessFromString( - const std::string& value); - - // Prepares to pass the client channel to a new child process, to be launched - // using |LaunchProcess()| (from base/launch.h). Modifies |*command_line| and - // |*handle_passing_info| as needed. - // Note: For Windows, this method only works on Vista and later. - void PrepareToPassClientHandleToChildProcess( - base::CommandLine* command_line, - HandlePassingInformation* handle_passing_info) const; - - // Like above, but returns a string instead of changing the command line. - std::string PrepareToPassClientHandleToChildProcessAsString( - HandlePassingInformation* handle_passing_info) const; - - // To be called once the child process has been successfully launched, to do - // any cleanup necessary. - void ChildProcessLaunched(); - - private: - ScopedPlatformHandle server_handle_; - ScopedPlatformHandle client_handle_; - - DISALLOW_COPY_AND_ASSIGN(PlatformChannelPair); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ diff --git a/mojo/edk/embedder/platform_channel_pair_posix.cc b/mojo/edk/embedder/platform_channel_pair_posix.cc deleted file mode 100644 index fe9f8f5..0000000 --- a/mojo/edk/embedder/platform_channel_pair_posix.cc +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_channel_pair.h" - -#include -#include -#include -#include -#include - -#include - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/posix/global_descriptors.h" -#include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/platform_handle.h" - -#if !defined(OS_NACL_SFI) -#include -#else -#include "native_client/src/public/imc_syscalls.h" -#endif - -#if !defined(SO_PEEK_OFF) -#define SO_PEEK_OFF 42 -#endif - -namespace mojo { -namespace edk { - -namespace { - -#if defined(OS_ANDROID) || defined(__ANDROID__) -enum { - // Leave room for any other descriptors defined in content for example. - // TODO(jcivelli): consider changing base::GlobalDescriptors to generate a - // key when setting the file descriptor (http://crbug.com/676442). - kAndroidClientHandleDescriptor = - base::GlobalDescriptors::kBaseDescriptor + 10000, -}; -#else -bool IsTargetDescriptorUsed( - const base::FileHandleMappingVector& file_handle_mapping, - int target_fd) { - for (size_t i = 0; i < file_handle_mapping.size(); i++) { - if (file_handle_mapping[i].second == target_fd) - return true; - } - return false; -} -#endif - -} // namespace - -PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) { - // Create the Unix domain socket. - int fds[2]; - // TODO(vtl): Maybe fail gracefully if |socketpair()| fails. - -#if defined(OS_NACL_SFI) - PCHECK(imc_socketpair(fds) == 0); -#else - PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0); - - // Set the ends to nonblocking. - PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0); - if (!client_is_blocking) - PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0); - -#if defined(OS_MACOSX) - // This turns off |SIGPIPE| when writing to a closed socket (causing it to - // fail with |EPIPE| instead). On Linux, we have to use |send...()| with - // |MSG_NOSIGNAL| -- which is not supported on Mac -- instead. - int no_sigpipe = 1; - PCHECK(setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, - sizeof(no_sigpipe)) == 0); - PCHECK(setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, - sizeof(no_sigpipe)) == 0); -#endif // defined(OS_MACOSX) -#endif // defined(OS_NACL_SFI) - - server_handle_.reset(PlatformHandle(fds[0])); - DCHECK(server_handle_.is_valid()); - client_handle_.reset(PlatformHandle(fds[1])); - DCHECK(client_handle_.is_valid()); -} - -// static -ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess( - const base::CommandLine& command_line) { - std::string client_fd_string = - command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - return PassClientHandleFromParentProcessFromString(client_fd_string); -} - -ScopedPlatformHandle -PlatformChannelPair::PassClientHandleFromParentProcessFromString( - const std::string& value) { - int client_fd = -1; -#if defined(OS_ANDROID) || defined(__ANDROID__) - base::GlobalDescriptors::Key key = -1; - if (value.empty() || !base::StringToUint(value, &key)) { - LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; - return ScopedPlatformHandle(); - } - client_fd = base::GlobalDescriptors::GetInstance()->Get(key); -#else - if (value.empty() || - !base::StringToInt(value, &client_fd) || - client_fd < base::GlobalDescriptors::kBaseDescriptor) { - LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; - return ScopedPlatformHandle(); - } -#endif - return ScopedPlatformHandle(PlatformHandle(client_fd)); -} - -void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( - base::CommandLine* command_line, - base::FileHandleMappingVector* handle_passing_info) const { - DCHECK(command_line); - - // Log a warning if the command line already has the switch, but "clobber" it - // anyway, since it's reasonably likely that all the switches were just copied - // from the parent. - LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) - << "Child command line already has switch --" - << kMojoPlatformChannelHandleSwitch << "=" - << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - // (Any existing switch won't actually be removed from the command line, but - // the last one appended takes precedence.) - command_line->AppendSwitchASCII( - kMojoPlatformChannelHandleSwitch, - PrepareToPassClientHandleToChildProcessAsString(handle_passing_info)); -} - -std::string -PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString( - HandlePassingInformation* handle_passing_info) const { -#if defined(OS_ANDROID) || defined(__ANDROID__) - int fd = client_handle_.get().handle; - handle_passing_info->push_back( - std::pair(fd, kAndroidClientHandleDescriptor)); - return base::UintToString(kAndroidClientHandleDescriptor); -#else - DCHECK(handle_passing_info); - // This is an arbitrary sanity check. (Note that this guarantees that the loop - // below will terminate sanely.) - CHECK_LT(handle_passing_info->size(), 1000u); - - DCHECK(client_handle_.is_valid()); - - // Find a suitable FD to map our client handle to in the child process. - // This has quadratic time complexity in the size of |*handle_passing_info|, - // but |*handle_passing_info| should be very small (usually/often empty). - int target_fd = base::GlobalDescriptors::kBaseDescriptor; - while (IsTargetDescriptorUsed(*handle_passing_info, target_fd)) - target_fd++; - - handle_passing_info->push_back( - std::pair(client_handle_.get().handle, target_fd)); - return base::IntToString(target_fd); -#endif -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc b/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc deleted file mode 100644 index a3fd275..0000000 --- a/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_channel_pair.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/files/scoped_temp_dir.h" -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/edk/embedder/platform_channel_utils_posix.h" -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/test/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -void WaitReadable(PlatformHandle h) { - struct pollfd pfds = {}; - pfds.fd = h.handle; - pfds.events = POLLIN; - CHECK_EQ(poll(&pfds, 1, -1), 1); -} - -class PlatformChannelPairPosixTest : public testing::Test { - public: - PlatformChannelPairPosixTest() {} - ~PlatformChannelPairPosixTest() override {} - - void SetUp() override { - // Make sure |SIGPIPE| isn't being ignored. - struct sigaction action = {}; - action.sa_handler = SIG_DFL; - ASSERT_EQ(0, sigaction(SIGPIPE, &action, &old_action_)); - } - - void TearDown() override { - // Restore the |SIGPIPE| handler. - ASSERT_EQ(0, sigaction(SIGPIPE, &old_action_, nullptr)); - } - - private: - struct sigaction old_action_; - - DISALLOW_COPY_AND_ASSIGN(PlatformChannelPairPosixTest); -}; - -TEST_F(PlatformChannelPairPosixTest, NoSigPipe) { - PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle(); - ScopedPlatformHandle client_handle = channel_pair.PassClientHandle(); - - // Write to the client. - static const char kHello[] = "hello"; - EXPECT_EQ(static_cast(sizeof(kHello)), - write(client_handle.get().handle, kHello, sizeof(kHello))); - - // Close the client. - client_handle.reset(); - - // Read from the server; this should be okay. - char buffer[100] = {}; - EXPECT_EQ(static_cast(sizeof(kHello)), - read(server_handle.get().handle, buffer, sizeof(buffer))); - EXPECT_STREQ(kHello, buffer); - - // Try reading again. - ssize_t result = read(server_handle.get().handle, buffer, sizeof(buffer)); - // We should probably get zero (for "end of file"), but -1 would also be okay. - EXPECT_TRUE(result == 0 || result == -1); - if (result == -1) - PLOG(WARNING) << "read (expected 0 for EOF)"; - - // Test our replacement for |write()|/|send()|. - result = PlatformChannelWrite(server_handle.get(), kHello, sizeof(kHello)); - EXPECT_EQ(-1, result); - if (errno != EPIPE) - PLOG(WARNING) << "write (expected EPIPE)"; - - // Test our replacement for |writev()|/|sendv()|. - struct iovec iov[2] = {{const_cast(kHello), sizeof(kHello)}, - {const_cast(kHello), sizeof(kHello)}}; - result = PlatformChannelWritev(server_handle.get(), iov, 2); - EXPECT_EQ(-1, result); - if (errno != EPIPE) - PLOG(WARNING) << "write (expected EPIPE)"; -} - -TEST_F(PlatformChannelPairPosixTest, SendReceiveData) { - PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle(); - ScopedPlatformHandle client_handle = channel_pair.PassClientHandle(); - - for (size_t i = 0; i < 10; i++) { - std::string send_string(1 << i, 'A' + i); - - EXPECT_EQ(static_cast(send_string.size()), - PlatformChannelWrite(server_handle.get(), send_string.data(), - send_string.size())); - - WaitReadable(client_handle.get()); - - char buf[10000] = {}; - std::deque received_handles; - ssize_t result = PlatformChannelRecvmsg(client_handle.get(), buf, - sizeof(buf), &received_handles); - EXPECT_EQ(static_cast(send_string.size()), result); - EXPECT_EQ(send_string, std::string(buf, static_cast(result))); - EXPECT_TRUE(received_handles.empty()); - } -} - -TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - static const char kHello[] = "hello"; - - PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle(); - ScopedPlatformHandle client_handle = channel_pair.PassClientHandle(); - -// Reduce the number of FDs opened on OS X to avoid test flake. -#if defined(OS_MACOSX) - const size_t kNumHandlesToSend = kPlatformChannelMaxNumHandles / 2; -#else - const size_t kNumHandlesToSend = kPlatformChannelMaxNumHandles; -#endif - - for (size_t i = 1; i < kNumHandlesToSend; i++) { - // Make |i| files, with the j-th file consisting of j copies of the digit - // |c|. - const char c = '0' + (i % 10); - ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector); - for (size_t j = 1; j <= i; j++) { - base::FilePath unused; - base::ScopedFILE fp( - base::CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused)); - ASSERT_TRUE(fp); - ASSERT_EQ(j, fwrite(std::string(j, c).data(), 1, j, fp.get())); - platform_handles->push_back( - test::PlatformHandleFromFILE(std::move(fp)).release()); - ASSERT_TRUE(platform_handles->back().is_valid()); - } - - // Send the FDs (+ "hello"). - struct iovec iov = {const_cast(kHello), sizeof(kHello)}; - // We assume that the |sendmsg()| actually sends all the data. - EXPECT_EQ(static_cast(sizeof(kHello)), - PlatformChannelSendmsgWithHandles(server_handle.get(), &iov, 1, - &platform_handles->at(0), - platform_handles->size())); - - WaitReadable(client_handle.get()); - - char buf[10000] = {}; - std::deque received_handles; - // We assume that the |recvmsg()| actually reads all the data. - EXPECT_EQ(static_cast(sizeof(kHello)), - PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf), - &received_handles)); - EXPECT_STREQ(kHello, buf); - EXPECT_EQ(i, received_handles.size()); - - for (size_t j = 0; !received_handles.empty(); j++) { - base::ScopedFILE fp(test::FILEFromPlatformHandle( - ScopedPlatformHandle(received_handles.front()), "rb")); - received_handles.pop_front(); - ASSERT_TRUE(fp); - rewind(fp.get()); - char read_buf[kNumHandlesToSend]; - size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get()); - EXPECT_EQ(j + 1, bytes_read); - EXPECT_EQ(std::string(j + 1, c), std::string(read_buf, bytes_read)); - } - } -} - -TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - static const char kHello[] = "hello"; - - PlatformChannelPair channel_pair; - ScopedPlatformHandle server_handle = channel_pair.PassServerHandle(); - ScopedPlatformHandle client_handle = channel_pair.PassClientHandle(); - - const std::string file_contents("hello world"); - - { - base::FilePath unused; - base::ScopedFILE fp( - base::CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused)); - ASSERT_TRUE(fp); - ASSERT_EQ(file_contents.size(), - fwrite(file_contents.data(), 1, file_contents.size(), fp.get())); - ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector); - platform_handles->push_back( - test::PlatformHandleFromFILE(std::move(fp)).release()); - ASSERT_TRUE(platform_handles->back().is_valid()); - - // Send the FD (+ "hello"). - struct iovec iov = {const_cast(kHello), sizeof(kHello)}; - // We assume that the |sendmsg()| actually sends all the data. - EXPECT_EQ(static_cast(sizeof(kHello)), - PlatformChannelSendmsgWithHandles(server_handle.get(), &iov, 1, - &platform_handles->at(0), - platform_handles->size())); - } - - WaitReadable(client_handle.get()); - - // Start with an invalid handle in the deque. - std::deque received_handles; - received_handles.push_back(PlatformHandle()); - - char buf[100] = {}; - // We assume that the |recvmsg()| actually reads all the data. - EXPECT_EQ(static_cast(sizeof(kHello)), - PlatformChannelRecvmsg(client_handle.get(), buf, sizeof(buf), - &received_handles)); - EXPECT_STREQ(kHello, buf); - ASSERT_EQ(2u, received_handles.size()); - EXPECT_FALSE(received_handles[0].is_valid()); - EXPECT_TRUE(received_handles[1].is_valid()); - - { - base::ScopedFILE fp(test::FILEFromPlatformHandle( - ScopedPlatformHandle(received_handles[1]), "rb")); - received_handles[1] = PlatformHandle(); - ASSERT_TRUE(fp); - rewind(fp.get()); - char read_buf[100]; - size_t bytes_read = fread(read_buf, 1, sizeof(read_buf), fp.get()); - EXPECT_EQ(file_contents.size(), bytes_read); - EXPECT_EQ(file_contents, std::string(read_buf, bytes_read)); - } -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_channel_pair_win.cc b/mojo/edk/embedder/platform_channel_pair_win.cc deleted file mode 100644 index f523ade..0000000 --- a/mojo/edk/embedder/platform_channel_pair_win.cc +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_channel_pair.h" - -#include - -#include - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/win/windows_version.h" -#include "mojo/edk/embedder/platform_handle.h" - -namespace mojo { -namespace edk { - -namespace { - -std::wstring GeneratePipeName() { - return base::StringPrintf(L"\\\\.\\pipe\\mojo.%u.%u.%I64u", - GetCurrentProcessId(), GetCurrentThreadId(), - base::RandUint64()); -} - -} // namespace - -PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) { - std::wstring pipe_name = GeneratePipeName(); - - DWORD kOpenMode = - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE; - const DWORD kPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE; - server_handle_.reset(PlatformHandle( - CreateNamedPipeW(pipe_name.c_str(), kOpenMode, kPipeMode, - 1, // Max instances. - 4096, // Out buffer size. - 4096, // In buffer size. - 5000, // Timeout in milliseconds. - nullptr))); // Default security descriptor. - PCHECK(server_handle_.is_valid()); - - const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE; - // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate - // the client. - DWORD kFlags = SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS; - if (!client_is_blocking) - kFlags |= FILE_FLAG_OVERLAPPED; - // Allow the handle to be inherited by child processes. - SECURITY_ATTRIBUTES security_attributes = { - sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; - client_handle_.reset( - PlatformHandle(CreateFileW(pipe_name.c_str(), kDesiredAccess, - 0, // No sharing. - &security_attributes, OPEN_EXISTING, kFlags, - nullptr))); // No template file. - PCHECK(client_handle_.is_valid()); - - // Since a client has connected, ConnectNamedPipe() should return zero and - // GetLastError() should return ERROR_PIPE_CONNECTED. - CHECK(!ConnectNamedPipe(server_handle_.get().handle, nullptr)); - PCHECK(GetLastError() == ERROR_PIPE_CONNECTED); -} - -// static -ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess( - const base::CommandLine& command_line) { - std::string client_handle_string = - command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - return PassClientHandleFromParentProcessFromString(client_handle_string); -} - -ScopedPlatformHandle -PlatformChannelPair::PassClientHandleFromParentProcessFromString( - const std::string& value) { - int client_handle_value = 0; - if (value.empty() || - !base::StringToInt(value, &client_handle_value)) { - LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; - return ScopedPlatformHandle(); - } - - return ScopedPlatformHandle( - PlatformHandle(LongToHandle(client_handle_value))); -} - -void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( - base::CommandLine* command_line, - base::HandlesToInheritVector* handle_passing_info) const { - DCHECK(command_line); - - // Log a warning if the command line already has the switch, but "clobber" it - // anyway, since it's reasonably likely that all the switches were just copied - // from the parent. - LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) - << "Child command line already has switch --" - << kMojoPlatformChannelHandleSwitch << "=" - << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); - // (Any existing switch won't actually be removed from the command line, but - // the last one appended takes precedence.) - command_line->AppendSwitchASCII( - kMojoPlatformChannelHandleSwitch, - PrepareToPassClientHandleToChildProcessAsString(handle_passing_info)); -} - -std::string -PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString( - HandlePassingInformation* handle_passing_info) const { - DCHECK(handle_passing_info); - DCHECK(client_handle_.is_valid()); - - if (base::win::GetVersion() >= base::win::VERSION_VISTA) - handle_passing_info->push_back(client_handle_.get().handle); - - return base::IntToString(HandleToLong(client_handle_.get().handle)); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_channel_utils_posix.cc b/mojo/edk/embedder/platform_channel_utils_posix.cc deleted file mode 100644 index 689b6ee..0000000 --- a/mojo/edk/embedder/platform_channel_utils_posix.cc +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_channel_utils_posix.h" - -#include -#include -#include - -#include - -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" - -#if !defined(OS_NACL) -#include -#endif - -#if !defined(SO_PEEK_OFF) -#define SO_PEEK_OFF 42 -#endif - -namespace mojo { -namespace edk { -namespace { - -#if !defined(OS_NACL) -bool IsRecoverableError() { - return errno == ECONNABORTED || errno == EMFILE || errno == ENFILE || - errno == ENOMEM || errno == ENOBUFS; -} - -bool GetPeerEuid(PlatformHandle handle, uid_t* peer_euid) { - DCHECK(peer_euid); -#if defined(OS_MACOSX) || defined(OS_OPENBSD) || defined(OS_FREEBSD) - uid_t socket_euid; - gid_t socket_gid; - if (getpeereid(handle.handle, &socket_euid, &socket_gid) < 0) { - PLOG(ERROR) << "getpeereid " << handle.handle; - return false; - } - *peer_euid = socket_euid; - return true; -#else - struct ucred cred; - socklen_t cred_len = sizeof(cred); - if (getsockopt(handle.handle, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) < - 0) { - PLOG(ERROR) << "getsockopt " << handle.handle; - return false; - } - if (static_cast(cred_len) < sizeof(cred)) { - NOTREACHED() << "Truncated ucred from SO_PEERCRED?"; - return false; - } - *peer_euid = cred.uid; - return true; -#endif -} - -bool IsPeerAuthorized(PlatformHandle peer_handle) { - uid_t peer_euid; - if (!GetPeerEuid(peer_handle, &peer_euid)) - return false; - if (peer_euid != geteuid()) { - DLOG(ERROR) << "Client euid is not authorised"; - return false; - } - return true; -} -#endif // !defined(OS_NACL) - -} // namespace - -// On Linux, |SIGPIPE| is suppressed by passing |MSG_NOSIGNAL| to -// |send()|/|sendmsg()|. (There is no way of suppressing |SIGPIPE| on -// |write()|/|writev().) On Mac, |SIGPIPE| is suppressed by setting the -// |SO_NOSIGPIPE| option on the socket. -// -// Performance notes: -// - On Linux, we have to use |send()|/|sendmsg()| rather than -// |write()|/|writev()| in order to suppress |SIGPIPE|. This is okay, since -// |send()| is (slightly) faster than |write()| (!), while |sendmsg()| is -// quite comparable to |writev()|. -// - On Mac, we may use |write()|/|writev()|. Here, |write()| is considerably -// faster than |send()|, whereas |sendmsg()| is quite comparable to -// |writev()|. -// - On both platforms, an appropriate |sendmsg()|/|writev()| is considerably -// faster than two |send()|s/|write()|s. -// - Relative numbers (minimum real times from 10 runs) for one |write()| of -// 1032 bytes, one |send()| of 1032 bytes, one |writev()| of 32+1000 bytes, -// one |sendmsg()| of 32+1000 bytes, two |write()|s of 32 and 1000 bytes, two -// |send()|s of 32 and 1000 bytes: -// - Linux: 0.81 s, 0.77 s, 0.87 s, 0.89 s, 1.31 s, 1.22 s -// - Mac: 2.21 s, 2.91 s, 2.98 s, 3.08 s, 3.59 s, 4.74 s - -// Flags to use with calling |send()| or |sendmsg()| (see above). -#if defined(OS_MACOSX) -const int kSendFlags = 0; -#else -const int kSendFlags = MSG_NOSIGNAL; -#endif - -ssize_t PlatformChannelWrite(PlatformHandle h, - const void* bytes, - size_t num_bytes) { - DCHECK(h.is_valid()); - DCHECK(bytes); - DCHECK_GT(num_bytes, 0u); - -#if defined(OS_MACOSX) || defined(OS_NACL_NONSFI) - // send() is not available under NaCl-nonsfi. - return HANDLE_EINTR(write(h.handle, bytes, num_bytes)); -#else - return send(h.handle, bytes, num_bytes, kSendFlags); -#endif -} - -ssize_t PlatformChannelWritev(PlatformHandle h, - struct iovec* iov, - size_t num_iov) { - DCHECK(h.is_valid()); - DCHECK(iov); - DCHECK_GT(num_iov, 0u); - -#if defined(OS_MACOSX) - return HANDLE_EINTR(writev(h.handle, iov, static_cast(num_iov))); -#else - struct msghdr msg = {}; - msg.msg_iov = iov; - msg.msg_iovlen = num_iov; - return HANDLE_EINTR(sendmsg(h.handle, &msg, kSendFlags)); -#endif -} - -ssize_t PlatformChannelSendmsgWithHandles(PlatformHandle h, - struct iovec* iov, - size_t num_iov, - PlatformHandle* platform_handles, - size_t num_platform_handles) { - DCHECK(iov); - DCHECK_GT(num_iov, 0u); - DCHECK(platform_handles); - DCHECK_GT(num_platform_handles, 0u); - DCHECK_LE(num_platform_handles, kPlatformChannelMaxNumHandles); - - char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))]; - struct msghdr msg = {}; - msg.msg_iov = iov; - msg.msg_iovlen = num_iov; - msg.msg_control = cmsg_buf; - msg.msg_controllen = CMSG_LEN(num_platform_handles * sizeof(int)); - struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(num_platform_handles * sizeof(int)); - for (size_t i = 0; i < num_platform_handles; i++) { - DCHECK(platform_handles[i].is_valid()); - reinterpret_cast(CMSG_DATA(cmsg))[i] = platform_handles[i].handle; - } - - return HANDLE_EINTR(sendmsg(h.handle, &msg, kSendFlags)); -} - -bool PlatformChannelSendHandles(PlatformHandle h, - PlatformHandle* handles, - size_t num_handles) { - DCHECK(handles); - DCHECK_GT(num_handles, 0u); - DCHECK_LE(num_handles, kPlatformChannelMaxNumHandles); - - // Note: |sendmsg()| fails on Mac if we don't write at least one character. - struct iovec iov = {const_cast(""), 1}; - char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))]; - struct msghdr msg = {}; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = cmsg_buf; - msg.msg_controllen = CMSG_LEN(num_handles * sizeof(int)); - struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(num_handles * sizeof(int)); - for (size_t i = 0; i < num_handles; i++) { - DCHECK(handles[i].is_valid()); - reinterpret_cast(CMSG_DATA(cmsg))[i] = handles[i].handle; - } - - ssize_t result = HANDLE_EINTR(sendmsg(h.handle, &msg, kSendFlags)); - if (result < 1) { - DCHECK_EQ(result, -1); - return false; - } - - for (size_t i = 0; i < num_handles; i++) - handles[i].CloseIfNecessary(); - return true; -} - -ssize_t PlatformChannelRecvmsg(PlatformHandle h, - void* buf, - size_t num_bytes, - std::deque* platform_handles, - bool block) { - DCHECK(buf); - DCHECK_GT(num_bytes, 0u); - DCHECK(platform_handles); - - struct iovec iov = {buf, num_bytes}; - char cmsg_buf[CMSG_SPACE(kPlatformChannelMaxNumHandles * sizeof(int))]; - struct msghdr msg = {}; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = cmsg_buf; - msg.msg_controllen = sizeof(cmsg_buf); - - ssize_t result = - HANDLE_EINTR(recvmsg(h.handle, &msg, block ? 0 : MSG_DONTWAIT)); - if (result < 0) - return result; - - // Success; no control messages. - if (msg.msg_controllen == 0) - return result; - - DCHECK(!(msg.msg_flags & MSG_CTRUNC)); - - for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - size_t payload_length = cmsg->cmsg_len - CMSG_LEN(0); - DCHECK_EQ(payload_length % sizeof(int), 0u); - size_t num_fds = payload_length / sizeof(int); - const int* fds = reinterpret_cast(CMSG_DATA(cmsg)); - for (size_t i = 0; i < num_fds; i++) { - platform_handles->push_back(PlatformHandle(fds[i])); - DCHECK(platform_handles->back().is_valid()); - } - } - } - - return result; -} - -bool ServerAcceptConnection(PlatformHandle server_handle, - ScopedPlatformHandle* connection_handle, - bool check_peer_user) { - DCHECK(server_handle.is_valid()); - connection_handle->reset(); -#if defined(OS_NACL) - NOTREACHED(); - return false; -#else - ScopedPlatformHandle accept_handle( - PlatformHandle(HANDLE_EINTR(accept(server_handle.handle, NULL, 0)))); - if (!accept_handle.is_valid()) - return IsRecoverableError(); - - // Verify that the IPC channel peer is running as the same user. - if (check_peer_user && !IsPeerAuthorized(accept_handle.get())) { - return true; - } - - if (!base::SetNonBlocking(accept_handle.get().handle)) { - PLOG(ERROR) << "base::SetNonBlocking() failed " - << accept_handle.get().handle; - // It's safe to keep listening on |server_handle| even if the attempt to set - // O_NONBLOCK failed on the client fd. - return true; - } - - *connection_handle = std::move(accept_handle); - return true; -#endif // defined(OS_NACL) -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_channel_utils_posix.h b/mojo/edk/embedder/platform_channel_utils_posix.h deleted file mode 100644 index 23cfa92..0000000 --- a/mojo/edk/embedder/platform_channel_utils_posix.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_ -#define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_ - -#include -#include // For |ssize_t|. - -#include -#include - -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" - -struct iovec; // Declared in . - -namespace mojo { -namespace edk { -class ScopedPlatformHandle; - -// The maximum number of handles that can be sent "at once" using -// |PlatformChannelSendmsgWithHandles()|. This must be less than the Linux -// kernel's SCM_MAX_FD which is 253. -const size_t kPlatformChannelMaxNumHandles = 128; - -// Use these to write to a socket created using |PlatformChannelPair| (or -// equivalent). These are like |write()| and |writev()|, but handle |EINTR| and -// never raise |SIGPIPE|. (Note: On Mac, the suppression of |SIGPIPE| is set up -// by |PlatformChannelPair|.) -MOJO_SYSTEM_IMPL_EXPORT ssize_t -PlatformChannelWrite(PlatformHandle h, const void* bytes, size_t num_bytes); -MOJO_SYSTEM_IMPL_EXPORT ssize_t -PlatformChannelWritev(PlatformHandle h, struct iovec* iov, size_t num_iov); - -// Writes data, and the given set of |PlatformHandle|s (i.e., file descriptors) -// over the Unix domain socket given by |h| (e.g., created using -// |PlatformChannelPair()|). All the handles must be valid, and there must be at -// least one and at most |kPlatformChannelMaxNumHandles| handles. The return -// value is as for |sendmsg()|, namely -1 on failure and otherwise the number of -// bytes of data sent on success (note that this may not be all the data -// specified by |iov|). (The handles are not closed, regardless of success or -// failure.) -MOJO_SYSTEM_IMPL_EXPORT ssize_t -PlatformChannelSendmsgWithHandles(PlatformHandle h, - struct iovec* iov, - size_t num_iov, - PlatformHandle* platform_handles, - size_t num_platform_handles); - -// TODO(vtl): Remove this once I've switched things over to -// |PlatformChannelSendmsgWithHandles()|. -// Sends |PlatformHandle|s (i.e., file descriptors) over the Unix domain socket -// (e.g., created using PlatformChannelPair|). (These will be sent in a single -// message having one null byte of data and one control message header with all -// the file descriptors.) All of the handles must be valid, and there must be at -// most |kPlatformChannelMaxNumHandles| (and at least one handle). Returns true -// on success, in which case it closes all the handles. -MOJO_SYSTEM_IMPL_EXPORT bool PlatformChannelSendHandles(PlatformHandle h, - PlatformHandle* handles, - size_t num_handles); - -// Wrapper around |recvmsg()|, which will extract any attached file descriptors -// (in the control message) to |PlatformHandle|s (and append them to -// |platform_handles|). (This also handles |EINTR|.) -MOJO_SYSTEM_IMPL_EXPORT ssize_t -PlatformChannelRecvmsg(PlatformHandle h, - void* buf, - size_t num_bytes, - std::deque* platform_handles, - bool block = false); - -// Returns false if |server_handle| encounters an unrecoverable error. -// Returns true if it's valid to keep listening on |server_handle|. In this -// case, it's possible that a connection wasn't successfully established; then, -// |connection_handle| will be invalid. If |check_peer_user| is True, the -// connection will be rejected if the peer is running as a different user. -MOJO_SYSTEM_IMPL_EXPORT bool ServerAcceptConnection( - PlatformHandle server_handle, - ScopedPlatformHandle* connection_handle, - bool check_peer_user = true); - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_ diff --git a/mojo/edk/embedder/platform_handle.cc b/mojo/edk/embedder/platform_handle.cc deleted file mode 100644 index b6b2cd2..0000000 --- a/mojo/edk/embedder/platform_handle.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_handle.h" - -#include "build/build_config.h" -#if defined(OS_POSIX) -#include -#elif defined(OS_WIN) -#include -#else -#error "Platform not yet supported." -#endif - -#include "base/logging.h" - -namespace mojo { -namespace edk { - -void PlatformHandle::CloseIfNecessary() { - if (!is_valid()) - return; - -#if defined(OS_POSIX) - if (type == Type::POSIX) { - bool success = (close(handle) == 0); - DPCHECK(success); - handle = -1; - } -#if defined(OS_MACOSX) && !defined(OS_IOS) - else if (type == Type::MACH) { - kern_return_t rv = mach_port_deallocate(mach_task_self(), port); - DPCHECK(rv == KERN_SUCCESS); - port = MACH_PORT_NULL; - } -#endif // defined(OS_MACOSX) && !defined(OS_IOS) -#elif defined(OS_WIN) - if (owning_process != base::GetCurrentProcessHandle()) { - // This handle may have been duplicated to a new target process but not yet - // sent there. In this case CloseHandle should NOT be called. From MSDN - // documentation for DuplicateHandle[1]: - // - // Normally the target process closes a duplicated handle when that - // process is finished using the handle. To close a duplicated handle - // from the source process, call DuplicateHandle with the following - // parameters: - // - // * Set hSourceProcessHandle to the target process from the - // call that created the handle. - // * Set hSourceHandle to the duplicated handle to close. - // * Set lpTargetHandle to NULL. - // * Set dwOptions to DUPLICATE_CLOSE_SOURCE. - // - // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251 - // - // NOTE: It's possible for this operation to fail if the owning process - // was terminated or is in the process of being terminated. Either way, - // there is nothing we can reasonably do about failure, so we ignore it. - DuplicateHandle(owning_process, handle, NULL, &handle, 0, FALSE, - DUPLICATE_CLOSE_SOURCE); - return; - } - - bool success = !!CloseHandle(handle); - DPCHECK(success); - handle = INVALID_HANDLE_VALUE; -#else -#error "Platform not yet supported." -#endif -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_handle.h b/mojo/edk/embedder/platform_handle.h deleted file mode 100644 index 4866e75..0000000 --- a/mojo/edk/embedder/platform_handle.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_ -#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_ - -#include "build/build_config.h" -#include "mojo/edk/system/system_impl_export.h" - -#if defined(OS_WIN) -#include - -#include "base/process/process_handle.h" -#elif defined(OS_MACOSX) && !defined(OS_IOS) -#include -#endif - -namespace mojo { -namespace edk { - -#if defined(OS_POSIX) -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { - PlatformHandle() {} - explicit PlatformHandle(int handle) : handle(handle) {} -#if defined(OS_MACOSX) && !defined(OS_IOS) - explicit PlatformHandle(mach_port_t port) - : type(Type::MACH), port(port) {} -#endif - - void CloseIfNecessary(); - - bool is_valid() const { -#if defined(OS_MACOSX) && !defined(OS_IOS) - if (type == Type::MACH || type == Type::MACH_NAME) - return port != MACH_PORT_NULL; -#endif - return handle != -1; - } - - enum class Type { - POSIX, -#if defined(OS_MACOSX) && !defined(OS_IOS) - MACH, - // MACH_NAME isn't a real Mach port. But rather the "name" of one that can - // be resolved to a real port later. This distinction is needed so that the - // "port" doesn't try to be closed if CloseIfNecessary() is called. Having - // this also allows us to do checks in other places. - MACH_NAME, -#endif - }; - Type type = Type::POSIX; - - int handle = -1; - - // A POSIX handle may be a listen handle that can accept a connection. - bool needs_connection = false; - -#if defined(OS_MACOSX) && !defined(OS_IOS) - mach_port_t port = MACH_PORT_NULL; -#endif -}; -#elif defined(OS_WIN) -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { - PlatformHandle() : PlatformHandle(INVALID_HANDLE_VALUE) {} - explicit PlatformHandle(HANDLE handle) - : handle(handle), owning_process(base::GetCurrentProcessHandle()) {} - - void CloseIfNecessary(); - - bool is_valid() const { return handle != INVALID_HANDLE_VALUE; } - - HANDLE handle; - - // A Windows HANDLE may be duplicated to another process but not yet sent to - // that process. This tracks the handle's owning process. - base::ProcessHandle owning_process; - - // A Windows HANDLE may be an unconnected named pipe. In this case, we need to - // wait for a connection before communicating on the pipe. - bool needs_connection = false; -}; -#else -#error "Platform not yet supported." -#endif - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_H_ diff --git a/mojo/edk/embedder/platform_handle_utils.h b/mojo/edk/embedder/platform_handle_utils.h deleted file mode 100644 index fa683e4..0000000 --- a/mojo/edk/embedder/platform_handle_utils.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_ -#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_ - -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -// Closes all the |PlatformHandle|s in the given container. -template -MOJO_SYSTEM_IMPL_EXPORT inline void CloseAllPlatformHandles( - PlatformHandleContainer* platform_handles) { - for (typename PlatformHandleContainer::iterator it = - platform_handles->begin(); - it != platform_handles->end(); ++it) - it->CloseIfNecessary(); -} - -// Duplicates the given |PlatformHandle| (which must be valid). (Returns an -// invalid |ScopedPlatformHandle| on failure.) -MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle -DuplicatePlatformHandle(PlatformHandle platform_handle); - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_UTILS_H_ diff --git a/mojo/edk/embedder/platform_handle_utils_posix.cc b/mojo/edk/embedder/platform_handle_utils_posix.cc deleted file mode 100644 index 5604f96..0000000 --- a/mojo/edk/embedder/platform_handle_utils_posix.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_handle_utils.h" - -#include - -#include "base/logging.h" - -namespace mojo { -namespace edk { - -ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) { - DCHECK(platform_handle.is_valid()); - // Note that |dup()| returns -1 on error (which is exactly the value we use - // for invalid |PlatformHandle| FDs). - PlatformHandle duped(dup(platform_handle.handle)); - duped.needs_connection = platform_handle.needs_connection; - return ScopedPlatformHandle(duped); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_handle_utils_win.cc b/mojo/edk/embedder/platform_handle_utils_win.cc deleted file mode 100644 index 32ed49a..0000000 --- a/mojo/edk/embedder/platform_handle_utils_win.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_handle_utils.h" - -#include - -#include "base/logging.h" - -namespace mojo { -namespace edk { - -ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) { - DCHECK(platform_handle.is_valid()); - - HANDLE new_handle; - CHECK_NE(platform_handle.handle, INVALID_HANDLE_VALUE); - if (!DuplicateHandle(GetCurrentProcess(), platform_handle.handle, - GetCurrentProcess(), &new_handle, 0, TRUE, - DUPLICATE_SAME_ACCESS)) - return ScopedPlatformHandle(); - DCHECK_NE(new_handle, INVALID_HANDLE_VALUE); - return ScopedPlatformHandle(PlatformHandle(new_handle)); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_handle_vector.h b/mojo/edk/embedder/platform_handle_vector.h deleted file mode 100644 index 9892b23..0000000 --- a/mojo/edk/embedder/platform_handle_vector.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ -#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ - -#include -#include - -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/embedder/platform_handle_utils.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -using PlatformHandleVector = std::vector; - -// A deleter (for use with |scoped_ptr|) which closes all handles and then -// |delete|s the |PlatformHandleVector|. -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandleVectorDeleter { - void operator()(PlatformHandleVector* platform_handles) const { - CloseAllPlatformHandles(platform_handles); - delete platform_handles; - } -}; - -using ScopedPlatformHandleVectorPtr = - std::unique_ptr; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ diff --git a/mojo/edk/embedder/platform_shared_buffer.cc b/mojo/edk/embedder/platform_shared_buffer.cc deleted file mode 100644 index 58af44d..0000000 --- a/mojo/edk/embedder/platform_shared_buffer.cc +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_shared_buffer.h" - -#include - -#include - -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "base/memory/shared_memory.h" -#include "base/process/process_handle.h" -#include "base/sys_info.h" -#include "mojo/edk/embedder/platform_handle_utils.h" - -#if defined(OS_NACL) -// For getpagesize() on NaCl. -#include -#endif - -namespace mojo { -namespace edk { - -namespace { - -// Takes ownership of |memory_handle|. -ScopedPlatformHandle SharedMemoryToPlatformHandle( - base::SharedMemoryHandle memory_handle) { -#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS)) - return ScopedPlatformHandle(PlatformHandle(memory_handle.fd)); -#elif defined(OS_WIN) - return ScopedPlatformHandle(PlatformHandle(memory_handle.GetHandle())); -#else - return ScopedPlatformHandle(PlatformHandle(memory_handle.GetMemoryObject())); -#endif -} - -} // namespace - -// static -PlatformSharedBuffer* PlatformSharedBuffer::Create(size_t num_bytes) { - DCHECK_GT(num_bytes, 0u); - - PlatformSharedBuffer* rv = new PlatformSharedBuffer(num_bytes, false); - if (!rv->Init()) { - // We can't just delete it directly, due to the "in destructor" (debug) - // check. - scoped_refptr deleter(rv); - return nullptr; - } - - return rv; -} - -// static -PlatformSharedBuffer* PlatformSharedBuffer::CreateFromPlatformHandle( - size_t num_bytes, - bool read_only, - ScopedPlatformHandle platform_handle) { - DCHECK_GT(num_bytes, 0u); - - PlatformSharedBuffer* rv = new PlatformSharedBuffer(num_bytes, read_only); - if (!rv->InitFromPlatformHandle(std::move(platform_handle))) { - // We can't just delete it directly, due to the "in destructor" (debug) - // check. - scoped_refptr deleter(rv); - return nullptr; - } - - return rv; -} - -// static -PlatformSharedBuffer* PlatformSharedBuffer::CreateFromPlatformHandlePair( - size_t num_bytes, - ScopedPlatformHandle rw_platform_handle, - ScopedPlatformHandle ro_platform_handle) { - DCHECK_GT(num_bytes, 0u); - DCHECK(rw_platform_handle.is_valid()); - DCHECK(ro_platform_handle.is_valid()); - - PlatformSharedBuffer* rv = new PlatformSharedBuffer(num_bytes, false); - if (!rv->InitFromPlatformHandlePair(std::move(rw_platform_handle), - std::move(ro_platform_handle))) { - // We can't just delete it directly, due to the "in destructor" (debug) - // check. - scoped_refptr deleter(rv); - return nullptr; - } - - return rv; -} - -// static -PlatformSharedBuffer* PlatformSharedBuffer::CreateFromSharedMemoryHandle( - size_t num_bytes, - bool read_only, - base::SharedMemoryHandle handle) { - DCHECK_GT(num_bytes, 0u); - - PlatformSharedBuffer* rv = new PlatformSharedBuffer(num_bytes, read_only); - rv->InitFromSharedMemoryHandle(handle); - - return rv; -} - -size_t PlatformSharedBuffer::GetNumBytes() const { - return num_bytes_; -} - -bool PlatformSharedBuffer::IsReadOnly() const { - return read_only_; -} - -std::unique_ptr PlatformSharedBuffer::Map( - size_t offset, - size_t length) { - if (!IsValidMap(offset, length)) - return nullptr; - - return MapNoCheck(offset, length); -} - -bool PlatformSharedBuffer::IsValidMap(size_t offset, size_t length) { - if (offset > num_bytes_ || length == 0) - return false; - - // Note: This is an overflow-safe check of |offset + length > num_bytes_| - // (that |num_bytes >= offset| is verified above). - if (length > num_bytes_ - offset) - return false; - - return true; -} - -std::unique_ptr PlatformSharedBuffer::MapNoCheck( - size_t offset, - size_t length) { - DCHECK(IsValidMap(offset, length)); - DCHECK(shared_memory_); - base::SharedMemoryHandle handle; - { - base::AutoLock locker(lock_); - handle = base::SharedMemory::DuplicateHandle(shared_memory_->handle()); - } - if (handle == base::SharedMemory::NULLHandle()) - return nullptr; - - std::unique_ptr mapping( - new PlatformSharedBufferMapping(handle, read_only_, offset, length)); - if (mapping->Map()) - return base::WrapUnique(mapping.release()); - - return nullptr; -} - -ScopedPlatformHandle PlatformSharedBuffer::DuplicatePlatformHandle() { - DCHECK(shared_memory_); - base::SharedMemoryHandle handle; - { - base::AutoLock locker(lock_); - handle = base::SharedMemory::DuplicateHandle(shared_memory_->handle()); - } - if (handle == base::SharedMemory::NULLHandle()) - return ScopedPlatformHandle(); - - return SharedMemoryToPlatformHandle(handle); -} - -ScopedPlatformHandle PlatformSharedBuffer::PassPlatformHandle() { - DCHECK(HasOneRef()); - - // The only way to pass a handle from base::SharedMemory is to duplicate it - // and close the original. - ScopedPlatformHandle handle = DuplicatePlatformHandle(); - - base::AutoLock locker(lock_); - shared_memory_->Close(); - return handle; -} - -base::SharedMemoryHandle PlatformSharedBuffer::DuplicateSharedMemoryHandle() { - DCHECK(shared_memory_); - - base::AutoLock locker(lock_); - return base::SharedMemory::DuplicateHandle(shared_memory_->handle()); -} - -PlatformSharedBuffer* PlatformSharedBuffer::CreateReadOnlyDuplicate() { - DCHECK(shared_memory_); - - if (ro_shared_memory_) { - base::AutoLock locker(lock_); - base::SharedMemoryHandle handle; - handle = base::SharedMemory::DuplicateHandle(ro_shared_memory_->handle()); - if (handle == base::SharedMemory::NULLHandle()) - return nullptr; - return CreateFromSharedMemoryHandle(num_bytes_, true, handle); - } - - base::SharedMemoryHandle handle; - bool success; - { - base::AutoLock locker(lock_); - success = shared_memory_->ShareReadOnlyToProcess( - base::GetCurrentProcessHandle(), &handle); - } - if (!success || handle == base::SharedMemory::NULLHandle()) - return nullptr; - - return CreateFromSharedMemoryHandle(num_bytes_, true, handle); -} - -PlatformSharedBuffer::PlatformSharedBuffer(size_t num_bytes, bool read_only) - : num_bytes_(num_bytes), read_only_(read_only) {} - -PlatformSharedBuffer::~PlatformSharedBuffer() {} - -bool PlatformSharedBuffer::Init() { - DCHECK(!shared_memory_); - DCHECK(!read_only_); - - base::SharedMemoryCreateOptions options; - options.size = num_bytes_; - // By default, we can share as read-only. - options.share_read_only = true; - - shared_memory_.reset(new base::SharedMemory); - return shared_memory_->Create(options); -} - -bool PlatformSharedBuffer::InitFromPlatformHandle( - ScopedPlatformHandle platform_handle) { - DCHECK(!shared_memory_); - -#if defined(OS_WIN) - base::SharedMemoryHandle handle(platform_handle.release().handle, - base::GetCurrentProcId()); -#elif defined(OS_MACOSX) && !defined(OS_IOS) - base::SharedMemoryHandle handle; - handle = base::SharedMemoryHandle(platform_handle.release().port, num_bytes_, - base::GetCurrentProcId()); -#else - base::SharedMemoryHandle handle(platform_handle.release().handle, false); -#endif - - shared_memory_.reset(new base::SharedMemory(handle, read_only_)); - return true; -} - -bool PlatformSharedBuffer::InitFromPlatformHandlePair( - ScopedPlatformHandle rw_platform_handle, - ScopedPlatformHandle ro_platform_handle) { -#if defined(OS_MACOSX) - NOTREACHED(); - return false; -#else // defined(OS_MACOSX) - -#if defined(OS_WIN) - base::SharedMemoryHandle handle(rw_platform_handle.release().handle, - base::GetCurrentProcId()); - base::SharedMemoryHandle ro_handle(ro_platform_handle.release().handle, - base::GetCurrentProcId()); -#else // defined(OS_WIN) - base::SharedMemoryHandle handle(rw_platform_handle.release().handle, false); - base::SharedMemoryHandle ro_handle(ro_platform_handle.release().handle, - false); -#endif // defined(OS_WIN) - - DCHECK(!shared_memory_); - shared_memory_.reset(new base::SharedMemory(handle, false)); - ro_shared_memory_.reset(new base::SharedMemory(ro_handle, true)); - return true; - -#endif // defined(OS_MACOSX) -} - -void PlatformSharedBuffer::InitFromSharedMemoryHandle( - base::SharedMemoryHandle handle) { - DCHECK(!shared_memory_); - - shared_memory_.reset(new base::SharedMemory(handle, read_only_)); -} - -PlatformSharedBufferMapping::~PlatformSharedBufferMapping() { - Unmap(); -} - -void* PlatformSharedBufferMapping::GetBase() const { - return base_; -} - -size_t PlatformSharedBufferMapping::GetLength() const { - return length_; -} - -bool PlatformSharedBufferMapping::Map() { - // Mojo shared buffers can be mapped at any offset. However, - // base::SharedMemory must be mapped at a page boundary. So calculate what the - // nearest whole page offset is, and build a mapping that's offset from that. -#if defined(OS_NACL) - // base::SysInfo isn't available under NaCl. - size_t page_size = getpagesize(); -#else - size_t page_size = base::SysInfo::VMAllocationGranularity(); -#endif - size_t offset_rounding = offset_ % page_size; - size_t real_offset = offset_ - offset_rounding; - size_t real_length = length_ + offset_rounding; - - if (!shared_memory_.MapAt(static_cast(real_offset), real_length)) - return false; - - base_ = static_cast(shared_memory_.memory()) + offset_rounding; - return true; -} - -void PlatformSharedBufferMapping::Unmap() { - shared_memory_.Unmap(); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/platform_shared_buffer.h b/mojo/edk/embedder/platform_shared_buffer.h deleted file mode 100644 index 45be723..0000000 --- a/mojo/edk/embedder/platform_shared_buffer.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_ -#define MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_ - -#include - -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/shared_memory.h" -#include "base/memory/shared_memory_handle.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -class PlatformSharedBufferMapping; - -// |PlatformSharedBuffer| is a thread-safe, ref-counted wrapper around -// OS-specific shared memory. It has the following features: -// - A |PlatformSharedBuffer| simply represents a piece of shared memory that -// *may* be mapped and *may* be shared to another process. -// - A single |PlatformSharedBuffer| may be mapped multiple times. The -// lifetime of the mapping (owned by |PlatformSharedBufferMapping|) is -// separate from the lifetime of the |PlatformSharedBuffer|. -// - Sizes/offsets (of the shared memory and mappings) are arbitrary, and not -// restricted by page size. However, more memory may actually be mapped than -// requested. -class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer - : public base::RefCountedThreadSafe { - public: - // Creates a shared buffer of size |num_bytes| bytes (initially zero-filled). - // |num_bytes| must be nonzero. Returns null on failure. - static PlatformSharedBuffer* Create(size_t num_bytes); - - // Creates a shared buffer of size |num_bytes| from the existing platform - // handle |platform_handle|. Returns null on failure. - static PlatformSharedBuffer* CreateFromPlatformHandle( - size_t num_bytes, - bool read_only, - ScopedPlatformHandle platform_handle); - - // Creates a shared buffer of size |num_bytes| from the existing pair of - // read/write and read-only handles |rw_platform_handle| and - // |ro_platform_handle|. Returns null on failure. - static PlatformSharedBuffer* CreateFromPlatformHandlePair( - size_t num_bytes, - ScopedPlatformHandle rw_platform_handle, - ScopedPlatformHandle ro_platform_handle); - - // Creates a shared buffer of size |num_bytes| from the existing shared memory - // handle |handle|. - static PlatformSharedBuffer* CreateFromSharedMemoryHandle( - size_t num_bytes, - bool read_only, - base::SharedMemoryHandle handle); - - // Gets the size of shared buffer (in number of bytes). - size_t GetNumBytes() const; - - // Returns whether this shared buffer is read-only. - bool IsReadOnly() const; - - // Maps (some) of the shared buffer into memory; [|offset|, |offset + length|] - // must be contained in [0, |num_bytes|], and |length| must be at least 1. - // Returns null on failure. - std::unique_ptr Map(size_t offset, - size_t length); - - // Checks if |offset| and |length| are valid arguments. - bool IsValidMap(size_t offset, size_t length); - - // Like |Map()|, but doesn't check its arguments (which should have been - // preflighted using |IsValidMap()|). - std::unique_ptr MapNoCheck(size_t offset, - size_t length); - - // Duplicates the underlying platform handle and passes it to the caller. - ScopedPlatformHandle DuplicatePlatformHandle(); - - // Duplicates the underlying shared memory handle and passes it to the caller. - base::SharedMemoryHandle DuplicateSharedMemoryHandle(); - - // Passes the underlying platform handle to the caller. This should only be - // called if there's a unique reference to this object (owned by the caller). - // After calling this, this object should no longer be used, but should only - // be disposed of. - ScopedPlatformHandle PassPlatformHandle(); - - // Create and return a read-only duplicate of this shared buffer. If this - // shared buffer isn't capable of returning a read-only duplicate, then - // nullptr will be returned. - PlatformSharedBuffer* CreateReadOnlyDuplicate(); - - private: - friend class base::RefCountedThreadSafe; - - PlatformSharedBuffer(size_t num_bytes, bool read_only); - ~PlatformSharedBuffer(); - - // This is called by |Create()| before this object is given to anyone. - bool Init(); - - // This is like |Init()|, but for |CreateFromPlatformHandle()|. (Note: It - // should verify that |platform_handle| is an appropriate handle for the - // claimed |num_bytes_|.) - bool InitFromPlatformHandle(ScopedPlatformHandle platform_handle); - - bool InitFromPlatformHandlePair(ScopedPlatformHandle rw_platform_handle, - ScopedPlatformHandle ro_platform_handle); - - void InitFromSharedMemoryHandle(base::SharedMemoryHandle handle); - - const size_t num_bytes_; - const bool read_only_; - - base::Lock lock_; - std::unique_ptr shared_memory_; - - // A separate read-only shared memory for platforms that need it (i.e. Linux - // with sync broker). - std::unique_ptr ro_shared_memory_; - - DISALLOW_COPY_AND_ASSIGN(PlatformSharedBuffer); -}; - -// A mapping of a |PlatformSharedBuffer| (compararable to a "file view" in -// Windows); see above. Created by |PlatformSharedBuffer::Map()|. Automatically -// unmaps memory on destruction. -// -// Mappings are NOT thread-safe. -// -// Note: This is an entirely separate class (instead of -// |PlatformSharedBuffer::Mapping|) so that it can be forward-declared. -class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBufferMapping { - public: - ~PlatformSharedBufferMapping(); - - void* GetBase() const; - size_t GetLength() const; - - private: - friend class PlatformSharedBuffer; - - PlatformSharedBufferMapping(base::SharedMemoryHandle handle, - bool read_only, - size_t offset, - size_t length) - : offset_(offset), - length_(length), - base_(nullptr), - shared_memory_(handle, read_only) {} - - bool Map(); - void Unmap(); - - const size_t offset_; - const size_t length_; - void* base_; - - // Since mapping life cycles are separate from PlatformSharedBuffer and a - // buffer can be mapped multiple times, we have our own SharedMemory object - // created from a duplicate handle. - base::SharedMemory shared_memory_; - - DISALLOW_COPY_AND_ASSIGN(PlatformSharedBufferMapping); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_ diff --git a/mojo/edk/embedder/platform_shared_buffer_unittest.cc b/mojo/edk/embedder/platform_shared_buffer_unittest.cc deleted file mode 100644 index f1593f0..0000000 --- a/mojo/edk/embedder/platform_shared_buffer_unittest.cc +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_shared_buffer.h" - -#include - -#include -#include - -#include "base/memory/ref_counted.h" -#include "base/memory/shared_memory.h" -#include "base/sys_info.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -namespace mojo { -namespace edk { -namespace { - -TEST(PlatformSharedBufferTest, Basic) { - const size_t kNumInts = 100; - const size_t kNumBytes = kNumInts * sizeof(int); - // A fudge so that we're not just writing zero bytes 75% of the time. - const int kFudge = 1234567890; - - // Make some memory. - scoped_refptr buffer( - PlatformSharedBuffer::Create(kNumBytes)); - ASSERT_TRUE(buffer); - - // Map it all, scribble some stuff, and then unmap it. - { - EXPECT_TRUE(buffer->IsValidMap(0, kNumBytes)); - std::unique_ptr mapping( - buffer->Map(0, kNumBytes)); - ASSERT_TRUE(mapping); - ASSERT_TRUE(mapping->GetBase()); - int* stuff = static_cast(mapping->GetBase()); - for (size_t i = 0; i < kNumInts; i++) - stuff[i] = static_cast(i) + kFudge; - } - - // Map it all again, check that our scribbling is still there, then do a - // partial mapping and scribble on that, check that everything is coherent, - // unmap the first mapping, scribble on some of the second mapping, and then - // unmap it. - { - ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes)); - // Use |MapNoCheck()| this time. - std::unique_ptr mapping1( - buffer->MapNoCheck(0, kNumBytes)); - ASSERT_TRUE(mapping1); - ASSERT_TRUE(mapping1->GetBase()); - int* stuff1 = static_cast(mapping1->GetBase()); - for (size_t i = 0; i < kNumInts; i++) - EXPECT_EQ(static_cast(i) + kFudge, stuff1[i]) << i; - - std::unique_ptr mapping2( - buffer->Map((kNumInts / 2) * sizeof(int), 2 * sizeof(int))); - ASSERT_TRUE(mapping2); - ASSERT_TRUE(mapping2->GetBase()); - int* stuff2 = static_cast(mapping2->GetBase()); - EXPECT_EQ(static_cast(kNumInts / 2) + kFudge, stuff2[0]); - EXPECT_EQ(static_cast(kNumInts / 2) + 1 + kFudge, stuff2[1]); - - stuff2[0] = 123; - stuff2[1] = 456; - EXPECT_EQ(123, stuff1[kNumInts / 2]); - EXPECT_EQ(456, stuff1[kNumInts / 2 + 1]); - - mapping1.reset(); - - EXPECT_EQ(123, stuff2[0]); - EXPECT_EQ(456, stuff2[1]); - stuff2[1] = 789; - } - - // Do another partial mapping and check that everything is the way we expect - // it to be. - { - EXPECT_TRUE(buffer->IsValidMap(sizeof(int), kNumBytes - sizeof(int))); - std::unique_ptr mapping( - buffer->Map(sizeof(int), kNumBytes - sizeof(int))); - ASSERT_TRUE(mapping); - ASSERT_TRUE(mapping->GetBase()); - int* stuff = static_cast(mapping->GetBase()); - - for (size_t j = 0; j < kNumInts - 1; j++) { - int i = static_cast(j) + 1; - if (i == kNumInts / 2) { - EXPECT_EQ(123, stuff[j]); - } else if (i == kNumInts / 2 + 1) { - EXPECT_EQ(789, stuff[j]); - } else { - EXPECT_EQ(i + kFudge, stuff[j]) << i; - } - } - } -} - -// TODO(vtl): Bigger buffers. - -TEST(PlatformSharedBufferTest, InvalidMappings) { - scoped_refptr buffer(PlatformSharedBuffer::Create(100)); - ASSERT_TRUE(buffer); - - // Zero length not allowed. - EXPECT_FALSE(buffer->Map(0, 0)); - EXPECT_FALSE(buffer->IsValidMap(0, 0)); - - // Okay: - EXPECT_TRUE(buffer->Map(0, 100)); - EXPECT_TRUE(buffer->IsValidMap(0, 100)); - // Offset + length too big. - EXPECT_FALSE(buffer->Map(0, 101)); - EXPECT_FALSE(buffer->IsValidMap(0, 101)); - EXPECT_FALSE(buffer->Map(1, 100)); - EXPECT_FALSE(buffer->IsValidMap(1, 100)); - - // Okay: - EXPECT_TRUE(buffer->Map(50, 50)); - EXPECT_TRUE(buffer->IsValidMap(50, 50)); - // Offset + length too big. - EXPECT_FALSE(buffer->Map(50, 51)); - EXPECT_FALSE(buffer->IsValidMap(50, 51)); - EXPECT_FALSE(buffer->Map(51, 50)); - EXPECT_FALSE(buffer->IsValidMap(51, 50)); -} - -TEST(PlatformSharedBufferTest, TooBig) { - // If |size_t| is 32-bit, it's quite possible/likely that |Create()| succeeds - // (since it only involves creating a 4 GB file). - size_t max_size = std::numeric_limits::max(); - if (base::SysInfo::AmountOfVirtualMemory() && - max_size > static_cast(base::SysInfo::AmountOfVirtualMemory())) - max_size = static_cast(base::SysInfo::AmountOfVirtualMemory()); - scoped_refptr buffer( - PlatformSharedBuffer::Create(max_size)); - // But, assuming |sizeof(size_t) == sizeof(void*)|, mapping all of it should - // always fail. - if (buffer) - EXPECT_FALSE(buffer->Map(0, max_size)); -} - -// Tests that separate mappings get distinct addresses. -// Note: It's not inconceivable that the OS could ref-count identical mappings -// and reuse the same address, in which case we'd have to be more careful about -// using the address as the key for unmapping. -TEST(PlatformSharedBufferTest, MappingsDistinct) { - scoped_refptr buffer(PlatformSharedBuffer::Create(100)); - std::unique_ptr mapping1(buffer->Map(0, 100)); - std::unique_ptr mapping2(buffer->Map(0, 100)); - EXPECT_NE(mapping1->GetBase(), mapping2->GetBase()); -} - -TEST(PlatformSharedBufferTest, BufferZeroInitialized) { - static const size_t kSizes[] = {10, 100, 1000, 10000, 100000}; - for (size_t i = 0; i < arraysize(kSizes); i++) { - scoped_refptr buffer( - PlatformSharedBuffer::Create(kSizes[i])); - std::unique_ptr mapping( - buffer->Map(0, kSizes[i])); - for (size_t j = 0; j < kSizes[i]; j++) { - // "Assert" instead of "expect" so we don't spam the output with thousands - // of failures if we fail. - ASSERT_EQ('\0', static_cast(mapping->GetBase())[j]) - << "size " << kSizes[i] << ", offset " << j; - } - } -} - -TEST(PlatformSharedBufferTest, MappingsOutliveBuffer) { - std::unique_ptr mapping1; - std::unique_ptr mapping2; - - { - scoped_refptr buffer( - PlatformSharedBuffer::Create(100)); - mapping1 = buffer->Map(0, 100); - mapping2 = buffer->Map(50, 50); - static_cast(mapping1->GetBase())[50] = 'x'; - } - - EXPECT_EQ('x', static_cast(mapping2->GetBase())[0]); - - static_cast(mapping2->GetBase())[1] = 'y'; - EXPECT_EQ('y', static_cast(mapping1->GetBase())[51]); -} - -TEST(PlatformSharedBufferTest, FromSharedMemoryHandle) { - const size_t kBufferSize = 1234; - base::SharedMemoryCreateOptions options; - options.size = kBufferSize; - base::SharedMemory shared_memory; - ASSERT_TRUE(shared_memory.Create(options)); - ASSERT_TRUE(shared_memory.Map(kBufferSize)); - - base::SharedMemoryHandle shm_handle = - base::SharedMemory::DuplicateHandle(shared_memory.handle()); - scoped_refptr simple_buffer( - PlatformSharedBuffer::CreateFromSharedMemoryHandle( - kBufferSize, false /* read_only */, shm_handle)); - ASSERT_TRUE(simple_buffer); - - std::unique_ptr mapping = - simple_buffer->Map(0, kBufferSize); - ASSERT_TRUE(mapping); - - const int kOffset = 123; - char* base_memory = static_cast(shared_memory.memory()); - char* mojo_memory = static_cast(mapping->GetBase()); - base_memory[kOffset] = 0; - EXPECT_EQ(0, mojo_memory[kOffset]); - base_memory[kOffset] = 'a'; - EXPECT_EQ('a', mojo_memory[kOffset]); - mojo_memory[kOffset] = 'z'; - EXPECT_EQ('z', base_memory[kOffset]); -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/scoped_ipc_support.cc b/mojo/edk/embedder/scoped_ipc_support.cc deleted file mode 100644 index f67210a..0000000 --- a/mojo/edk/embedder/scoped_ipc_support.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/scoped_ipc_support.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread_restrictions.h" -#include "mojo/edk/embedder/embedder.h" - -namespace mojo { -namespace edk { - -ScopedIPCSupport::ScopedIPCSupport( - scoped_refptr io_thread_task_runner, - ShutdownPolicy shutdown_policy) : shutdown_policy_(shutdown_policy) { - InitIPCSupport(io_thread_task_runner); -} - -ScopedIPCSupport::~ScopedIPCSupport() { - if (shutdown_policy_ == ShutdownPolicy::FAST) { - ShutdownIPCSupport(base::Bind(&base::DoNothing)); - return; - } - - base::WaitableEvent shutdown_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - ShutdownIPCSupport(base::Bind(&base::WaitableEvent::Signal, - base::Unretained(&shutdown_event))); - - base::ThreadRestrictions::ScopedAllowWait allow_io; - shutdown_event.Wait(); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/embedder/scoped_ipc_support.h b/mojo/edk/embedder/scoped_ipc_support.h deleted file mode 100644 index 22d8e50..0000000 --- a/mojo/edk/embedder/scoped_ipc_support.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ -#define MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ - -#include "base/memory/ref_counted.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace base { -class TaskRunner; -} - -namespace mojo { -namespace edk { - -// A simple class that calls |InitIPCSupport()| on construction and -// |ShutdownIPCSupport()| on destruction, blocking the destructor on clean IPC -// shutdown completion. -class MOJO_SYSTEM_IMPL_EXPORT ScopedIPCSupport { - public: - // ShutdownPolicy is a type for specifying the desired Mojo IPC support - // shutdown behavior used during ScopedIPCSupport destruction. - // - // What follows is a quick overview of why shutdown behavior is interesting - // and how you might decide which behavior is right for your use case. - // - // BACKGROUND - // ========== - // - // In order to facilitate efficient and reliable transfer of Mojo message pipe - // endpoints across process boundaries, the underlying model for a message - // pipe is actually a self-collapsing cycle of "ports." See - // //mojo/edk/system/ports for gritty implementation details. - // - // Ports are essentially globally unique identifiers used for system-wide - // message routing. Every message pipe consists of at least two such ports: - // the pipe's two concrete endpoints. - // - // When a message pipe endpoint is transferred over another message pipe, that - // endpoint's port (which subsequently exists only internally with no - // publicly-reachable handle) enters a transient proxying state for the - // remainder of its lifetime. Once sufficient information has been - // proagated throughout the system and this proxying port can be safely - // bypassed, it is garbage-collected. - // - // If a process is terminated while hosting any active proxy ports, this - // will necessarily break the message pipe(s) to which those ports belong. - // - // WHEN TO USE CLEAN SHUTDOWN - // ========================== - // - // Consider three processes, A, B, and C. Suppose A creates a message pipe, - // sending one end to B and the other to C. For some brief period of time, - // messages sent by B or C over this pipe may be proxied through A. - // - // If A is suddenly terminated, there may be no way for B's messages to reach - // C (and vice versa), since the message pipe state may not have been fully - // propagated to all concerned processes in the system. As such, both B and C - // may have no choice but to signal peer closure on their respective ends of - // the pipe, and thus the pipe may be broken despite a lack of intent by - // either B or C. - // - // This can also happen if A creates a pipe and passes one end to B, who then - // passes it along to C. B may temporarily proxy messages for this pipe - // between A and C, and B's sudden demise will in turn beget the pipe's - // own sudden demise. - // - // In situations where these sort of arrangements may occur, potentially - // proxying processes must ensure they are shut down cleanly in order to avoid - // flaky system behavior. - // - // WHEN TO USE FAST SHUTDOWN - // ========================= - // - // As a general rule of thumb, if your process never creates a message pipe - // where both ends are passed to other processes, or never forwards a pipe - // endpoint from one process to another, fast shutdown is safe. Satisfaction - // of these constraints can be difficult to prove though, so clean shutdown is - // a safe default choice. - // - // Content renderer processes are a good example of a case where fast shutdown - // is safe, because as a matter of security and stability, a renderer cannot - // be trusted to do any proxying on behalf of two other processes anyway. - // - // There are other practical scenarios where fast shutdown is safe even if - // the process may have live proxies. For example, content's browser process - // is treated as a sort of master process in the system, in the sense that if - // the browser is terminated, no other part of the system is expected to - // continue normal operation anyway. In this case the side-effects of fast - // shutdown are irrelevant, so fast shutdown is preferred. - enum class ShutdownPolicy { - // Clean shutdown. This causes the ScopedIPCSupport destructor to *block* - // the calling thread until clean shutdown is complete. See explanation - // above for details. - CLEAN, - - // Fast shutdown. In this case a cheap best-effort attempt is made to - // shut down the IPC system, but no effort is made to wait for its - // completion. See explanation above for details. - FAST, - }; - - ScopedIPCSupport(scoped_refptr io_thread_task_runner, - ShutdownPolicy shutdown_policy); - ~ScopedIPCSupport(); - - private: - const ShutdownPolicy shutdown_policy_; - - DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ diff --git a/mojo/edk/embedder/scoped_platform_handle.h b/mojo/edk/embedder/scoped_platform_handle.h deleted file mode 100644 index 15b80ea..0000000 --- a/mojo/edk/embedder/scoped_platform_handle.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_ -#define MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_ - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/macros.h" - -namespace mojo { -namespace edk { - -class MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle { - public: - ScopedPlatformHandle() {} - explicit ScopedPlatformHandle(PlatformHandle handle) : handle_(handle) {} - ~ScopedPlatformHandle() { handle_.CloseIfNecessary(); } - - // Move-only constructor and operator=. - ScopedPlatformHandle(ScopedPlatformHandle&& other) - : handle_(other.release()) {} - - ScopedPlatformHandle& operator=(ScopedPlatformHandle&& other) { - if (this != &other) - handle_ = other.release(); - return *this; - } - - const PlatformHandle& get() const { return handle_; } - - void swap(ScopedPlatformHandle& other) { - PlatformHandle temp = handle_; - handle_ = other.handle_; - other.handle_ = temp; - } - - PlatformHandle release() WARN_UNUSED_RESULT { - PlatformHandle rv = handle_; - handle_ = PlatformHandle(); - return rv; - } - - void reset(PlatformHandle handle = PlatformHandle()) { - handle_.CloseIfNecessary(); - handle_ = handle; - } - - bool is_valid() const { return handle_.is_valid(); } - - private: - PlatformHandle handle_; - - DISALLOW_COPY_AND_ASSIGN(ScopedPlatformHandle); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_ diff --git a/mojo/edk/embedder/test_embedder.cc b/mojo/edk/embedder/test_embedder.cc deleted file mode 100644 index 9658010..0000000 --- a/mojo/edk/embedder/test_embedder.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/test_embedder.h" - -#include - -#include "base/logging.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/core.h" -#include "mojo/edk/system/handle_table.h" - -namespace mojo { - -namespace edk { -namespace internal { - -bool ShutdownCheckNoLeaks(Core* core) { - std::vector leaked_handles; - core->GetActiveHandlesForTest(&leaked_handles); - if (leaked_handles.empty()) - return true; - for (auto handle : leaked_handles) - LOG(ERROR) << "Mojo embedder shutdown: Leaking handle " << handle; - return false; -} - -} // namespace internal - -namespace test { - -bool Shutdown() { - CHECK(internal::g_core); - bool rv = internal::ShutdownCheckNoLeaks(internal::g_core); - delete internal::g_core; - internal::g_core = nullptr; - - return rv; -} - -} // namespace test -} // namespace edk - -} // namespace mojo diff --git a/mojo/edk/embedder/test_embedder.h b/mojo/edk/embedder/test_embedder.h deleted file mode 100644 index c64ba17..0000000 --- a/mojo/edk/embedder/test_embedder.h +++ /dev/null @@ -1,28 +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_TEST_EMBEDDER_H_ -#define MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_ - -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { -namespace test { - -// This shuts down the global, singleton instance. (Note: "Real" embedders are -// not expected to ever shut down this instance. This |Shutdown()| function will -// do more work to ensure that tests don't leak, etc.) Returns true if there -// were no problems, false if there were leaks -- i.e., handles still open -- or -// any other problems. -// -// Note: It is up to the caller to ensure that there are not outstanding -// callbacks from |CreateChannel()| before calling this. -MOJO_SYSTEM_IMPL_EXPORT bool Shutdown(); - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_ diff --git a/mojo/edk/js/BUILD.gn b/mojo/edk/js/BUILD.gn deleted file mode 100644 index fc1e03c..0000000 --- a/mojo/edk/js/BUILD.gn +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -component("js") { - sources = [ - "core.cc", - "core.h", - "drain_data.cc", - "drain_data.h", - "handle.cc", - "handle.h", - "handle_close_observer.h", - "js_export.h", - "mojo_runner_delegate.cc", - "mojo_runner_delegate.h", - "support.cc", - "support.h", - "threading.cc", - "threading.h", - "waiting_callback.cc", - "waiting_callback.h", - ] - - public_deps = [ - "//base", - "//gin", - "//v8", - ] - - deps = [ - "//mojo/public/cpp/system", - ] - defines = [ "MOJO_JS_IMPLEMENTATION" ] -} diff --git a/mojo/edk/js/core.cc b/mojo/edk/js/core.cc deleted file mode 100644 index baccc4c..0000000 --- a/mojo/edk/js/core.cc +++ /dev/null @@ -1,454 +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/js/core.h" - -#include -#include - -#include "base/bind.h" -#include "base/logging.h" -#include "gin/arguments.h" -#include "gin/array_buffer.h" -#include "gin/converter.h" -#include "gin/dictionary.h" -#include "gin/function_template.h" -#include "gin/handle.h" -#include "gin/object_template_builder.h" -#include "gin/per_isolate_data.h" -#include "gin/public/wrapper_info.h" -#include "gin/wrappable.h" -#include "mojo/edk/js/drain_data.h" -#include "mojo/edk/js/handle.h" -#include "mojo/public/cpp/system/wait.h" - -namespace mojo { -namespace edk { -namespace js { - -namespace { - -MojoResult CloseHandle(gin::Handle handle) { - if (!handle->get().is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - handle->Close(); - return MOJO_RESULT_OK; -} - -gin::Dictionary QueryHandleSignalsState(const gin::Arguments& args, - mojo::Handle handle) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - if (!handle.is_valid()) { - dictionary.Set("result", MOJO_RESULT_INVALID_ARGUMENT); - } else { - HandleSignalsState state = handle.QuerySignalsState(); - dictionary.Set("result", MOJO_RESULT_OK); - dictionary.Set("satisfiedSignals", state.satisfied_signals); - dictionary.Set("satisfiableSignals", state.satisfiable_signals); - } - return dictionary; -} - -gin::Dictionary WaitHandle(const gin::Arguments& args, - mojo::Handle handle, - MojoHandleSignals signals) { - v8::Isolate* isolate = args.isolate(); - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate); - - MojoHandleSignalsState signals_state; - MojoResult result = Wait(handle, signals, &signals_state); - dictionary.Set("result", result); - - if (result != MOJO_RESULT_OK && result != MOJO_RESULT_FAILED_PRECONDITION) { - dictionary.Set("signalsState", v8::Null(isolate).As()); - } else { - gin::Dictionary signalsStateDict = gin::Dictionary::CreateEmpty(isolate); - signalsStateDict.Set("satisfiedSignals", signals_state.satisfied_signals); - signalsStateDict.Set("satisfiableSignals", - signals_state.satisfiable_signals); - dictionary.Set("signalsState", signalsStateDict); - } - - return dictionary; -} - -gin::Dictionary CreateMessagePipe(const gin::Arguments& args) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", MOJO_RESULT_INVALID_ARGUMENT); - - MojoHandle handle0 = MOJO_HANDLE_INVALID; - MojoHandle handle1 = MOJO_HANDLE_INVALID; - MojoResult result = MOJO_RESULT_OK; - - v8::Handle options_value = args.PeekNext(); - if (options_value.IsEmpty() || options_value->IsNull() || - options_value->IsUndefined()) { - result = MojoCreateMessagePipe(NULL, &handle0, &handle1); - } else if (options_value->IsObject()) { - gin::Dictionary options_dict(args.isolate(), options_value->ToObject()); - MojoCreateMessagePipeOptions options; - // For future struct_size, we can probably infer that from the presence of - // properties in options_dict. For now, it's always 8. - options.struct_size = 8; - // Ideally these would be optional. But the interface makes it hard to - // typecheck them then. - if (!options_dict.Get("flags", &options.flags)) { - return dictionary; - } - - result = MojoCreateMessagePipe(&options, &handle0, &handle1); - } else { - return dictionary; - } - - CHECK_EQ(MOJO_RESULT_OK, result); - - dictionary.Set("result", result); - dictionary.Set("handle0", mojo::Handle(handle0)); - dictionary.Set("handle1", mojo::Handle(handle1)); - return dictionary; -} - -MojoResult WriteMessage( - mojo::Handle handle, - const gin::ArrayBufferView& buffer, - const std::vector >& handles, - MojoWriteMessageFlags flags) { - std::vector raw_handles(handles.size()); - for (size_t i = 0; i < handles.size(); ++i) - raw_handles[i] = handles[i]->get().value(); - MojoResult rv = MojoWriteMessage(handle.value(), - buffer.bytes(), - static_cast(buffer.num_bytes()), - raw_handles.empty() ? NULL : &raw_handles[0], - static_cast(raw_handles.size()), - flags); - // MojoWriteMessage takes ownership of the handles, so release them here. - for (size_t i = 0; i < handles.size(); ++i) - ignore_result(handles[i]->release()); - - return rv; -} - -gin::Dictionary ReadMessage(const gin::Arguments& args, - mojo::Handle handle, - MojoReadMessageFlags flags) { - uint32_t num_bytes = 0; - uint32_t num_handles = 0; - MojoResult result = MojoReadMessage( - handle.value(), NULL, &num_bytes, NULL, &num_handles, flags); - if (result != MOJO_RESULT_RESOURCE_EXHAUSTED) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - return dictionary; - } - - v8::Handle array_buffer = - v8::ArrayBuffer::New(args.isolate(), num_bytes); - std::vector handles(num_handles); - - gin::ArrayBuffer buffer; - ConvertFromV8(args.isolate(), array_buffer, &buffer); - CHECK(buffer.num_bytes() == num_bytes); - - result = MojoReadMessage(handle.value(), - buffer.bytes(), - &num_bytes, - handles.empty() ? NULL : - reinterpret_cast(&handles[0]), - &num_handles, - flags); - - CHECK(buffer.num_bytes() == num_bytes); - CHECK(handles.size() == num_handles); - - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - dictionary.Set("buffer", array_buffer); - dictionary.Set("handles", handles); - return dictionary; -} - -gin::Dictionary CreateDataPipe(const gin::Arguments& args) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", MOJO_RESULT_INVALID_ARGUMENT); - - MojoHandle producer_handle = MOJO_HANDLE_INVALID; - MojoHandle consumer_handle = MOJO_HANDLE_INVALID; - MojoResult result = MOJO_RESULT_OK; - - v8::Handle options_value = args.PeekNext(); - if (options_value.IsEmpty() || options_value->IsNull() || - options_value->IsUndefined()) { - result = MojoCreateDataPipe(NULL, &producer_handle, &consumer_handle); - } else if (options_value->IsObject()) { - gin::Dictionary options_dict(args.isolate(), options_value->ToObject()); - MojoCreateDataPipeOptions options; - // For future struct_size, we can probably infer that from the presence of - // properties in options_dict. For now, it's always 16. - options.struct_size = 16; - // Ideally these would be optional. But the interface makes it hard to - // typecheck them then. - if (!options_dict.Get("flags", &options.flags) || - !options_dict.Get("elementNumBytes", &options.element_num_bytes) || - !options_dict.Get("capacityNumBytes", &options.capacity_num_bytes)) { - return dictionary; - } - - result = MojoCreateDataPipe(&options, &producer_handle, &consumer_handle); - } else { - return dictionary; - } - - CHECK_EQ(MOJO_RESULT_OK, result); - - dictionary.Set("result", result); - dictionary.Set("producerHandle", mojo::Handle(producer_handle)); - dictionary.Set("consumerHandle", mojo::Handle(consumer_handle)); - return dictionary; -} - -gin::Dictionary WriteData(const gin::Arguments& args, - mojo::Handle handle, - const gin::ArrayBufferView& buffer, - MojoWriteDataFlags flags) { - uint32_t num_bytes = static_cast(buffer.num_bytes()); - MojoResult result = - MojoWriteData(handle.value(), buffer.bytes(), &num_bytes, flags); - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - dictionary.Set("numBytes", num_bytes); - return dictionary; -} - -gin::Dictionary ReadData(const gin::Arguments& args, - mojo::Handle handle, - MojoReadDataFlags flags) { - uint32_t num_bytes = 0; - MojoResult result = MojoReadData( - handle.value(), NULL, &num_bytes, MOJO_READ_DATA_FLAG_QUERY); - if (result != MOJO_RESULT_OK) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - return dictionary; - } - - v8::Handle array_buffer = - v8::ArrayBuffer::New(args.isolate(), num_bytes); - gin::ArrayBuffer buffer; - ConvertFromV8(args.isolate(), array_buffer, &buffer); - CHECK_EQ(num_bytes, buffer.num_bytes()); - - result = MojoReadData(handle.value(), buffer.bytes(), &num_bytes, flags); - CHECK_EQ(num_bytes, buffer.num_bytes()); - - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - dictionary.Set("result", result); - dictionary.Set("buffer", array_buffer); - return dictionary; -} - -// Asynchronously read all of the data available for the specified data pipe -// consumer handle until the remote handle is closed or an error occurs. A -// Promise is returned whose settled value is an object like this: -// {result: core.RESULT_OK, buffer: dataArrayBuffer}. If the read failed, -// then the Promise is rejected, the result will be the actual error code, -// and the buffer will contain whatever was read before the error occurred. -// The drainData data pipe handle argument is closed automatically. - -v8::Handle DoDrainData(gin::Arguments* args, - gin::Handle handle) { - return (new DrainData(args->isolate(), handle->release()))->GetPromise(); -} - -bool IsHandle(gin::Arguments* args, v8::Handle val) { - gin::Handle ignore_handle; - return gin::Converter>::FromV8( - args->isolate(), val, &ignore_handle); -} - -gin::Dictionary CreateSharedBuffer(const gin::Arguments& args, - uint64_t num_bytes, - MojoCreateSharedBufferOptionsFlags flags) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - MojoHandle handle = MOJO_HANDLE_INVALID; - MojoCreateSharedBufferOptions options; - // The |flags| is mandatory parameter for CreateSharedBuffer, and it will - // be always initialized in MojoCreateSharedBufferOptions struct. For - // forward compatibility, set struct_size to be 8 bytes (struct_size + flags), - // so that validator will only check the field that is set. - options.struct_size = 8; - options.flags = flags; - MojoResult result = MojoCreateSharedBuffer(&options, num_bytes, &handle); - if (result != MOJO_RESULT_OK) { - dictionary.Set("result", result); - return dictionary; - } - - dictionary.Set("result", result); - dictionary.Set("handle", mojo::Handle(handle)); - - return dictionary; -} - -gin::Dictionary DuplicateBufferHandle( - const gin::Arguments& args, - mojo::Handle handle, - MojoDuplicateBufferHandleOptionsFlags flags) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - MojoHandle duped = MOJO_HANDLE_INVALID; - MojoDuplicateBufferHandleOptions options; - // The |flags| is mandatory parameter for DuplicateBufferHandle, and it will - // be always initialized in MojoDuplicateBufferHandleOptions struct. For - // forward compatibility, set struct_size to be 8 bytes (struct_size + flags), - // so that validator will only check the field that is set. - options.struct_size = 8; - options.flags = flags; - MojoResult result = - MojoDuplicateBufferHandle(handle.value(), &options, &duped); - if (result != MOJO_RESULT_OK) { - dictionary.Set("result", result); - return dictionary; - } - - dictionary.Set("result", result); - dictionary.Set("handle", mojo::Handle(duped)); - - return dictionary; -} - -gin::Dictionary MapBuffer(const gin::Arguments& args, - mojo::Handle handle, - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags) { - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(args.isolate()); - void* data = nullptr; - MojoResult result = - MojoMapBuffer(handle.value(), offset, num_bytes, &data, flags); - if (result != MOJO_RESULT_OK) { - dictionary.Set("result", result); - return dictionary; - } - - v8::Handle array_buffer = - v8::ArrayBuffer::New(args.isolate(), data, num_bytes); - - dictionary.Set("result", result); - dictionary.Set("buffer", array_buffer); - - return dictionary; -} - -MojoResult UnmapBuffer(const gin::Arguments& args, - const v8::Handle& buffer) { - // Buffer must be external, created by MapBuffer - if (!buffer->IsExternal()) - return MOJO_RESULT_INVALID_ARGUMENT; - - return MojoUnmapBuffer(buffer->GetContents().Data()); -} - -gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; - -} // namespace - -const char Core::kModuleName[] = "mojo/public/js/core"; - -v8::Local Core::GetModule(v8::Isolate* isolate) { - gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); - v8::Local templ = data->GetObjectTemplate( - &g_wrapper_info); - - if (templ.IsEmpty()) { - templ = - gin::ObjectTemplateBuilder(isolate) - // TODO(mpcomplete): Should these just be methods on the JS Handle - // object? - .SetMethod("close", CloseHandle) - .SetMethod("queryHandleSignalsState", QueryHandleSignalsState) - .SetMethod("wait", WaitHandle) - .SetMethod("createMessagePipe", CreateMessagePipe) - .SetMethod("writeMessage", WriteMessage) - .SetMethod("readMessage", ReadMessage) - .SetMethod("createDataPipe", CreateDataPipe) - .SetMethod("writeData", WriteData) - .SetMethod("readData", ReadData) - .SetMethod("drainData", DoDrainData) - .SetMethod("isHandle", IsHandle) - .SetMethod("createSharedBuffer", CreateSharedBuffer) - .SetMethod("duplicateBufferHandle", DuplicateBufferHandle) - .SetMethod("mapBuffer", MapBuffer) - .SetMethod("unmapBuffer", UnmapBuffer) - - .SetValue("RESULT_OK", MOJO_RESULT_OK) - .SetValue("RESULT_CANCELLED", MOJO_RESULT_CANCELLED) - .SetValue("RESULT_UNKNOWN", MOJO_RESULT_UNKNOWN) - .SetValue("RESULT_INVALID_ARGUMENT", MOJO_RESULT_INVALID_ARGUMENT) - .SetValue("RESULT_DEADLINE_EXCEEDED", MOJO_RESULT_DEADLINE_EXCEEDED) - .SetValue("RESULT_NOT_FOUND", MOJO_RESULT_NOT_FOUND) - .SetValue("RESULT_ALREADY_EXISTS", MOJO_RESULT_ALREADY_EXISTS) - .SetValue("RESULT_PERMISSION_DENIED", MOJO_RESULT_PERMISSION_DENIED) - .SetValue("RESULT_RESOURCE_EXHAUSTED", - MOJO_RESULT_RESOURCE_EXHAUSTED) - .SetValue("RESULT_FAILED_PRECONDITION", - MOJO_RESULT_FAILED_PRECONDITION) - .SetValue("RESULT_ABORTED", MOJO_RESULT_ABORTED) - .SetValue("RESULT_OUT_OF_RANGE", MOJO_RESULT_OUT_OF_RANGE) - .SetValue("RESULT_UNIMPLEMENTED", MOJO_RESULT_UNIMPLEMENTED) - .SetValue("RESULT_INTERNAL", MOJO_RESULT_INTERNAL) - .SetValue("RESULT_UNAVAILABLE", MOJO_RESULT_UNAVAILABLE) - .SetValue("RESULT_DATA_LOSS", MOJO_RESULT_DATA_LOSS) - .SetValue("RESULT_BUSY", MOJO_RESULT_BUSY) - .SetValue("RESULT_SHOULD_WAIT", MOJO_RESULT_SHOULD_WAIT) - - .SetValue("HANDLE_SIGNAL_NONE", MOJO_HANDLE_SIGNAL_NONE) - .SetValue("HANDLE_SIGNAL_READABLE", MOJO_HANDLE_SIGNAL_READABLE) - .SetValue("HANDLE_SIGNAL_WRITABLE", MOJO_HANDLE_SIGNAL_WRITABLE) - .SetValue("HANDLE_SIGNAL_PEER_CLOSED", - MOJO_HANDLE_SIGNAL_PEER_CLOSED) - - .SetValue("CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE", - MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE) - - .SetValue("WRITE_MESSAGE_FLAG_NONE", MOJO_WRITE_MESSAGE_FLAG_NONE) - - .SetValue("READ_MESSAGE_FLAG_NONE", MOJO_READ_MESSAGE_FLAG_NONE) - .SetValue("READ_MESSAGE_FLAG_MAY_DISCARD", - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD) - - .SetValue("CREATE_DATA_PIPE_OPTIONS_FLAG_NONE", - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE) - - .SetValue("WRITE_DATA_FLAG_NONE", MOJO_WRITE_DATA_FLAG_NONE) - .SetValue("WRITE_DATA_FLAG_ALL_OR_NONE", - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) - - .SetValue("READ_DATA_FLAG_NONE", MOJO_READ_DATA_FLAG_NONE) - .SetValue("READ_DATA_FLAG_ALL_OR_NONE", - MOJO_READ_DATA_FLAG_ALL_OR_NONE) - .SetValue("READ_DATA_FLAG_DISCARD", MOJO_READ_DATA_FLAG_DISCARD) - .SetValue("READ_DATA_FLAG_QUERY", MOJO_READ_DATA_FLAG_QUERY) - .SetValue("READ_DATA_FLAG_PEEK", MOJO_READ_DATA_FLAG_PEEK) - .SetValue("CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE", - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE) - - .SetValue("DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE", - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE) - - .SetValue("DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY", - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY) - - .SetValue("MAP_BUFFER_FLAG_NONE", MOJO_MAP_BUFFER_FLAG_NONE) - .Build(); - - data->SetObjectTemplate(&g_wrapper_info, templ); - } - - return templ->NewInstance(); -} - -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/core.h b/mojo/edk/js/core.h deleted file mode 100644 index 97ef5df..0000000 --- a/mojo/edk/js/core.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_JS_CORE_H_ -#define MOJO_EDK_JS_CORE_H_ - -#include "mojo/edk/js/js_export.h" -#include "v8/include/v8.h" - -namespace mojo { -namespace edk { -namespace js { - -class MOJO_JS_EXPORT Core { - public: - static const char kModuleName[]; - static v8::Local GetModule(v8::Isolate* isolate); -}; - -} // namespace js -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_JS_CORE_H_ diff --git a/mojo/edk/js/drain_data.cc b/mojo/edk/js/drain_data.cc deleted file mode 100644 index 334ced3..0000000 --- a/mojo/edk/js/drain_data.cc +++ /dev/null @@ -1,129 +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/js/drain_data.h" - -#include -#include - -#include "base/bind.h" -#include "base/memory/ptr_util.h" -#include "gin/array_buffer.h" -#include "gin/converter.h" -#include "gin/dictionary.h" -#include "gin/per_context_data.h" -#include "gin/per_isolate_data.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace edk { -namespace js { - -DrainData::DrainData(v8::Isolate* isolate, mojo::Handle handle) - : isolate_(isolate), - handle_(DataPipeConsumerHandle(handle.value())), - handle_watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC) { - v8::Handle context(isolate_->GetCurrentContext()); - runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); - - WaitForData(); -} - -v8::Handle DrainData::GetPromise() { - CHECK(resolver_.IsEmpty()); - v8::Handle resolver( - v8::Promise::Resolver::New(isolate_)); - resolver_.Reset(isolate_, resolver); - return resolver->GetPromise(); -} - -DrainData::~DrainData() { - resolver_.Reset(); -} - -void DrainData::WaitForData() { - handle_watcher_.Watch( - handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&DrainData::DataReady, base::Unretained(this))); -} - -void DrainData::DataReady(MojoResult result) { - if (result != MOJO_RESULT_OK) { - DeliverData(result); - return; - } - while (result == MOJO_RESULT_OK) { - result = ReadData(); - if (result == MOJO_RESULT_SHOULD_WAIT) - WaitForData(); - else if (result != MOJO_RESULT_OK) - DeliverData(result); - } -} - -MojoResult DrainData::ReadData() { - const void* buffer; - uint32_t num_bytes = 0; - MojoResult result = BeginReadDataRaw( - handle_.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); - if (result != MOJO_RESULT_OK) - return result; - const char* p = static_cast(buffer); - data_buffers_.push_back(base::MakeUnique(p, p + num_bytes)); - return EndReadDataRaw(handle_.get(), num_bytes); -} - -void DrainData::DeliverData(MojoResult result) { - if (!runner_) { - delete this; - return; - } - - size_t total_bytes = 0; - for (unsigned i = 0; i < data_buffers_.size(); i++) - total_bytes += data_buffers_[i]->size(); - - // Create a total_bytes length ArrayBuffer return value. - gin::Runner::Scope scope(runner_.get()); - v8::Handle array_buffer = - v8::ArrayBuffer::New(isolate_, total_bytes); - gin::ArrayBuffer buffer; - ConvertFromV8(isolate_, array_buffer, &buffer); - CHECK_EQ(total_bytes, buffer.num_bytes()); - - // Copy the data_buffers into the ArrayBuffer. - char* array_buffer_ptr = static_cast(buffer.bytes()); - size_t offset = 0; - for (size_t i = 0; i < data_buffers_.size(); i++) { - size_t num_bytes = data_buffers_[i]->size(); - if (num_bytes == 0) - continue; - const char* data_buffer_ptr = &((*data_buffers_[i])[0]); - memcpy(array_buffer_ptr + offset, data_buffer_ptr, num_bytes); - offset += num_bytes; - } - - // The "settled" value of the promise always includes all of the data - // that was read before either an error occurred or the remote pipe handle - // was closed. The latter is indicated by MOJO_RESULT_FAILED_PRECONDITION. - - v8::Handle resolver( - v8::Local::New(isolate_, resolver_)); - - gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate_); - dictionary.Set("result", result); - dictionary.Set("buffer", array_buffer); - v8::Handle settled_value(ConvertToV8(isolate_, dictionary)); - - if (result == MOJO_RESULT_FAILED_PRECONDITION) - resolver->Resolve(settled_value); - else - resolver->Reject(settled_value); - - delete this; -} - -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/drain_data.h b/mojo/edk/js/drain_data.h deleted file mode 100644 index 42da90f..0000000 --- a/mojo/edk/js/drain_data.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_JS_DRAIN_DATA_H_ -#define MOJO_EDK_JS_DRAIN_DATA_H_ - -#include -#include - -#include "gin/runner.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/simple_watcher.h" -#include "v8/include/v8.h" - -namespace mojo { -namespace edk { -namespace js { - -// This class is the implementation of the Mojo JavaScript core module's -// drainData() method. It is not intended to be used directly. The caller -// allocates a DrainData on the heap and returns GetPromise() to JS. The -// implementation deletes itself after reading as much data as possible -// and rejecting or resolving the Promise. - -class DrainData { - public: - // Starts waiting for data on the specified data pipe consumer handle. - // See WaitForData(). The constructor does not block. - DrainData(v8::Isolate* isolate, mojo::Handle handle); - - // Returns a Promise that will be settled when no more data can be read. - // Should be called just once on a newly allocated DrainData object. - v8::Handle GetPromise(); - - private: - ~DrainData(); - - // Waits for data to be available. DataReady() will be notified. - void WaitForData(); - - // Use ReadData() to read whatever is availble now on handle_ and save - // it in data_buffers_. - void DataReady(MojoResult result); - MojoResult ReadData(); - - // When the remote data pipe handle is closed, or an error occurs, deliver - // all of the buffered data to the JS Promise and then delete this. - void DeliverData(MojoResult result); - - using DataBuffer = std::vector; - - v8::Isolate* isolate_; - ScopedDataPipeConsumerHandle handle_; - SimpleWatcher handle_watcher_; - base::WeakPtr runner_; - v8::UniquePersistent resolver_; - std::vector> data_buffers_; -}; - -} // namespace js -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_JS_DRAIN_DATA_H_ diff --git a/mojo/edk/js/handle.cc b/mojo/edk/js/handle.cc deleted file mode 100644 index 7da8e9f..0000000 --- a/mojo/edk/js/handle.cc +++ /dev/null @@ -1,85 +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/js/handle.h" - -#include "mojo/edk/js/handle_close_observer.h" - -namespace mojo { -namespace edk { -namespace js { - -gin::WrapperInfo HandleWrapper::kWrapperInfo = { gin::kEmbedderNativeGin }; - -HandleWrapper::HandleWrapper(MojoHandle handle) - : handle_(mojo::Handle(handle)) { -} - -HandleWrapper::~HandleWrapper() { - NotifyCloseObservers(); -} - -void HandleWrapper::Close() { - NotifyCloseObservers(); - handle_.reset(); -} - -void HandleWrapper::AddCloseObserver(HandleCloseObserver* observer) { - close_observers_.AddObserver(observer); -} - -void HandleWrapper::RemoveCloseObserver(HandleCloseObserver* observer) { - close_observers_.RemoveObserver(observer); -} - -void HandleWrapper::NotifyCloseObservers() { - if (!handle_.is_valid()) - return; - - for (auto& observer : close_observers_) - observer.OnWillCloseHandle(); -} - -} // namespace js -} // namespace edk -} // namespace mojo - -namespace gin { - -v8::Handle Converter::ToV8(v8::Isolate* isolate, - const mojo::Handle& val) { - if (!val.is_valid()) - return v8::Null(isolate); - return mojo::edk::js::HandleWrapper::Create(isolate, val.value()).ToV8(); -} - -bool Converter::FromV8(v8::Isolate* isolate, - v8::Handle val, - mojo::Handle* out) { - if (val->IsNull()) { - *out = mojo::Handle(); - return true; - } - - gin::Handle handle; - if (!Converter>::FromV8( - isolate, val, &handle)) - return false; - - *out = handle->get(); - return true; -} - -v8::Handle Converter::ToV8( - v8::Isolate* isolate, mojo::MessagePipeHandle val) { - return Converter::ToV8(isolate, val); -} - -bool Converter::FromV8(v8::Isolate* isolate, - v8::Handle val, - mojo::MessagePipeHandle* out) { - return Converter::FromV8(isolate, val, out); -} - -} // namespace gin diff --git a/mojo/edk/js/handle.h b/mojo/edk/js/handle.h deleted file mode 100644 index 60652ed..0000000 --- a/mojo/edk/js/handle.h +++ /dev/null @@ -1,107 +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_JS_HANDLE_H_ -#define MOJO_EDK_JS_HANDLE_H_ - -#include - -#include "base/observer_list.h" -#include "gin/converter.h" -#include "gin/handle.h" -#include "gin/wrappable.h" -#include "mojo/edk/js/js_export.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace edk { -namespace js { - -class HandleCloseObserver; - -// Wrapper for mojo Handles exposed to JavaScript. This ensures the Handle -// is Closed when its JS object is garbage collected. -class MOJO_JS_EXPORT HandleWrapper : public gin::Wrappable { - public: - static gin::WrapperInfo kWrapperInfo; - - static gin::Handle Create(v8::Isolate* isolate, - MojoHandle handle) { - return gin::CreateHandle(isolate, new HandleWrapper(handle)); - } - - mojo::Handle get() const { return handle_.get(); } - mojo::Handle release() { return handle_.release(); } - void Close(); - - void AddCloseObserver(HandleCloseObserver* observer); - void RemoveCloseObserver(HandleCloseObserver* observer); - - protected: - HandleWrapper(MojoHandle handle); - ~HandleWrapper() override; - void NotifyCloseObservers(); - - mojo::ScopedHandle handle_; - base::ObserverList close_observers_; -}; - -} // namespace js -} // namespace edk -} // namespace mojo - -namespace gin { - -// Note: It's important to use this converter rather than the one for -// MojoHandle, since that will do a simple int32_t conversion. It's unfortunate -// there's no way to prevent against accidental use. -// TODO(mpcomplete): define converters for all Handle subtypes. -template <> -struct MOJO_JS_EXPORT Converter { - static v8::Handle ToV8(v8::Isolate* isolate, - const mojo::Handle& val); - static bool FromV8(v8::Isolate* isolate, v8::Handle val, - mojo::Handle* out); -}; - -template <> -struct MOJO_JS_EXPORT Converter { - static v8::Handle ToV8(v8::Isolate* isolate, - mojo::MessagePipeHandle val); - static bool FromV8(v8::Isolate* isolate, - v8::Handle val, - mojo::MessagePipeHandle* out); -}; - -// We need to specialize the normal gin::Handle converter in order to handle -// converting |null| to a wrapper for an empty mojo::Handle. -template <> -struct MOJO_JS_EXPORT Converter> { - static v8::Handle ToV8( - v8::Isolate* isolate, - const gin::Handle& val) { - return val.ToV8(); - } - - static bool FromV8(v8::Isolate* isolate, - v8::Handle val, - gin::Handle* out) { - if (val->IsNull()) { - *out = mojo::edk::js::HandleWrapper::Create(isolate, MOJO_HANDLE_INVALID); - return true; - } - - mojo::edk::js::HandleWrapper* object = NULL; - if (!Converter::FromV8(isolate, val, - &object)) { - return false; - } - *out = gin::Handle(val, object); - return true; - } -}; - -} // namespace gin - -#endif // MOJO_EDK_JS_HANDLE_H_ diff --git a/mojo/edk/js/handle_close_observer.h b/mojo/edk/js/handle_close_observer.h deleted file mode 100644 index c7b935e..0000000 --- a/mojo/edk/js/handle_close_observer.h +++ /dev/null @@ -1,24 +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_JS_HANDLE_CLOSE_OBSERVER_H_ -#define MOJO_EDK_JS_HANDLE_CLOSE_OBSERVER_H_ - -namespace mojo { -namespace edk { -namespace js { - -class HandleCloseObserver { - public: - virtual void OnWillCloseHandle() = 0; - - protected: - virtual ~HandleCloseObserver() {} -}; - -} // namespace js -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_JS_HANDLE_CLOSE_OBSERVER_H_ diff --git a/mojo/edk/js/handle_unittest.cc b/mojo/edk/js/handle_unittest.cc deleted file mode 100644 index dd2562f..0000000 --- a/mojo/edk/js/handle_unittest.cc +++ /dev/null @@ -1,92 +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 "base/macros.h" -#include "mojo/edk/js/handle.h" -#include "mojo/edk/js/handle_close_observer.h" -#include "mojo/public/cpp/system/core.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace js { - -class HandleWrapperTest : public testing::Test, - public HandleCloseObserver { - public: - HandleWrapperTest() : closes_observed_(0) {} - - void OnWillCloseHandle() override { closes_observed_++; } - - protected: - int closes_observed_; - - private: - DISALLOW_COPY_AND_ASSIGN(HandleWrapperTest); -}; - -class TestHandleWrapper : public HandleWrapper { - public: - explicit TestHandleWrapper(MojoHandle handle) : HandleWrapper(handle) {} - - private: - DISALLOW_COPY_AND_ASSIGN(TestHandleWrapper); -}; - -// Test that calling Close() on a HandleWrapper for an invalid handle does not -// notify observers. -TEST_F(HandleWrapperTest, CloseWithInvalidHandle) { - { - TestHandleWrapper wrapper(MOJO_HANDLE_INVALID); - wrapper.AddCloseObserver(this); - ASSERT_EQ(0, closes_observed_); - wrapper.Close(); - EXPECT_EQ(0, closes_observed_); - } - EXPECT_EQ(0, closes_observed_); -} - -// Test that destroying a HandleWrapper for an invalid handle does not notify -// observers. -TEST_F(HandleWrapperTest, DestroyWithInvalidHandle) { - { - TestHandleWrapper wrapper(MOJO_HANDLE_INVALID); - wrapper.AddCloseObserver(this); - ASSERT_EQ(0, closes_observed_); - } - EXPECT_EQ(0, closes_observed_); -} - -// Test that calling Close on a HandleWrapper for a valid handle notifies -// observers once. -TEST_F(HandleWrapperTest, CloseWithValidHandle) { - { - mojo::MessagePipe pipe; - TestHandleWrapper wrapper(pipe.handle0.release().value()); - wrapper.AddCloseObserver(this); - ASSERT_EQ(0, closes_observed_); - wrapper.Close(); - EXPECT_EQ(1, closes_observed_); - // Check that calling close again doesn't notify observers. - wrapper.Close(); - EXPECT_EQ(1, closes_observed_); - } - // Check that destroying a closed HandleWrapper doesn't notify observers. - EXPECT_EQ(1, closes_observed_); -} - -// Test that destroying a HandleWrapper for a valid handle notifies observers. -TEST_F(HandleWrapperTest, DestroyWithValidHandle) { - { - mojo::MessagePipe pipe; - TestHandleWrapper wrapper(pipe.handle0.release().value()); - wrapper.AddCloseObserver(this); - ASSERT_EQ(0, closes_observed_); - } - EXPECT_EQ(1, closes_observed_); -} - -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/js_export.h b/mojo/edk/js/js_export.h deleted file mode 100644 index 179113c..0000000 --- a/mojo/edk/js/js_export.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_JS_JS_EXPORT_H_ -#define MOJO_EDK_JS_JS_EXPORT_H_ - -// Defines MOJO_JS_EXPORT so that functionality implemented by //mojo/edk/js can -// be exported to consumers. - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(MOJO_JS_IMPLEMENTATION) -#define MOJO_JS_EXPORT __declspec(dllexport) -#else -#define MOJO_JS_EXPORT __declspec(dllimport) -#endif // defined(MOJO_JS_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(MOJO_JS_IMPLEMENTATION) -#define MOJO_JS_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_JS_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define MOJO_JS_EXPORT -#endif - -#endif // MOJO_EDK_JS_JS_EXPORT_H_ diff --git a/mojo/edk/js/mojo_runner_delegate.cc b/mojo/edk/js/mojo_runner_delegate.cc deleted file mode 100644 index dda0b2c..0000000 --- a/mojo/edk/js/mojo_runner_delegate.cc +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/js/mojo_runner_delegate.h" - -#include "base/bind.h" -#include "base/path_service.h" -#include "gin/converter.h" -#include "gin/modules/console.h" -#include "gin/modules/module_registry.h" -#include "gin/modules/timer.h" -#include "gin/try_catch.h" -#include "mojo/edk/js/core.h" -#include "mojo/edk/js/handle.h" -#include "mojo/edk/js/support.h" -#include "mojo/edk/js/threading.h" - -namespace mojo { -namespace edk { -namespace js { - -namespace { - -// TODO(abarth): Rather than loading these modules from the file system, we -// should load them from the network via Mojo IPC. -std::vector GetModuleSearchPaths() { - std::vector search_paths(2); - PathService::Get(base::DIR_SOURCE_ROOT, &search_paths[0]); - PathService::Get(base::DIR_EXE, &search_paths[1]); - search_paths[1] = search_paths[1].AppendASCII("gen"); - return search_paths; -} - -void StartCallback(base::WeakPtr runner, - MojoHandle pipe, - v8::Handle module) { - v8::Isolate* isolate = runner->GetContextHolder()->isolate(); - v8::Handle start; - CHECK(gin::ConvertFromV8(isolate, module, &start)); - - v8::Handle args[] = { - gin::ConvertToV8(isolate, Handle(pipe)) }; - runner->Call(start, runner->global(), 1, args); -} - -} // namespace - -MojoRunnerDelegate::MojoRunnerDelegate() - : ModuleRunnerDelegate(GetModuleSearchPaths()) { - AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule); - AddBuiltinModule(gin::TimerModule::kName, gin::TimerModule::GetModule); - AddBuiltinModule(Core::kModuleName, Core::GetModule); - AddBuiltinModule(Support::kModuleName, Support::GetModule); - AddBuiltinModule(Threading::kModuleName, Threading::GetModule); -} - -MojoRunnerDelegate::~MojoRunnerDelegate() { -} - -void MojoRunnerDelegate::Start(gin::Runner* runner, - MojoHandle pipe, - const std::string& module) { - gin::Runner::Scope scope(runner); - gin::ModuleRegistry* registry = - gin::ModuleRegistry::From(runner->GetContextHolder()->context()); - registry->LoadModule(runner->GetContextHolder()->isolate(), module, - base::Bind(StartCallback, runner->GetWeakPtr(), pipe)); - AttemptToLoadMoreModules(runner); -} - -void MojoRunnerDelegate::UnhandledException(gin::ShellRunner* runner, - gin::TryCatch& try_catch) { - gin::ModuleRunnerDelegate::UnhandledException(runner, try_catch); - LOG(ERROR) << try_catch.GetStackTrace(); -} - -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/mojo_runner_delegate.h b/mojo/edk/js/mojo_runner_delegate.h deleted file mode 100644 index 9ab325c..0000000 --- a/mojo/edk/js/mojo_runner_delegate.h +++ /dev/null @@ -1,36 +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_JS_MOJO_RUNNER_DELEGATE_H_ -#define MOJO_EDK_JS_MOJO_RUNNER_DELEGATE_H_ - -#include "base/macros.h" -#include "gin/modules/module_runner_delegate.h" -#include "mojo/edk/js/js_export.h" -#include "mojo/public/c/system/core.h" - -namespace mojo { -namespace edk { -namespace js { - -class MOJO_JS_EXPORT MojoRunnerDelegate : public gin::ModuleRunnerDelegate { - public: - MojoRunnerDelegate(); - ~MojoRunnerDelegate() override; - - void Start(gin::Runner* runner, MojoHandle pipe, const std::string& module); - - private: - // From ModuleRunnerDelegate: - void UnhandledException(gin::ShellRunner* runner, - gin::TryCatch& try_catch) override; - - DISALLOW_COPY_AND_ASSIGN(MojoRunnerDelegate); -}; - -} // namespace js -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_JS_MOJO_RUNNER_DELEGATE_H_ diff --git a/mojo/edk/js/support.cc b/mojo/edk/js/support.cc deleted file mode 100644 index 404cb9b..0000000 --- a/mojo/edk/js/support.cc +++ /dev/null @@ -1,77 +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/js/support.h" - -#include "base/bind.h" -#include "gin/arguments.h" -#include "gin/converter.h" -#include "gin/function_template.h" -#include "gin/object_template_builder.h" -#include "gin/per_isolate_data.h" -#include "gin/public/wrapper_info.h" -#include "gin/wrappable.h" -#include "mojo/edk/js/handle.h" -#include "mojo/edk/js/waiting_callback.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace edk { -namespace js { - -namespace { - -WaitingCallback* AsyncWait(const gin::Arguments& args, - gin::Handle handle, - MojoHandleSignals signals, - v8::Handle callback) { - return WaitingCallback::Create( - args.isolate(), callback, handle, signals, true /* one_shot */).get(); -} - -void CancelWait(WaitingCallback* waiting_callback) { - waiting_callback->Cancel(); -} - -WaitingCallback* Watch(const gin::Arguments& args, - gin::Handle handle, - MojoHandleSignals signals, - v8::Handle callback) { - return WaitingCallback::Create( - args.isolate(), callback, handle, signals, false /* one_shot */).get(); -} - -void CancelWatch(WaitingCallback* waiting_callback) { - waiting_callback->Cancel(); -} - -gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; - -} // namespace - -const char Support::kModuleName[] = "mojo/public/js/support"; - -v8::Local Support::GetModule(v8::Isolate* isolate) { - gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); - v8::Local templ = data->GetObjectTemplate( - &g_wrapper_info); - - if (templ.IsEmpty()) { - templ = gin::ObjectTemplateBuilder(isolate) - // TODO(rockot): Remove asyncWait and cancelWait. - .SetMethod("asyncWait", AsyncWait) - .SetMethod("cancelWait", CancelWait) - .SetMethod("watch", Watch) - .SetMethod("cancelWatch", CancelWatch) - .Build(); - - data->SetObjectTemplate(&g_wrapper_info, templ); - } - - return templ->NewInstance(); -} - -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/support.h b/mojo/edk/js/support.h deleted file mode 100644 index 551f5ac..0000000 --- a/mojo/edk/js/support.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_JS_SUPPORT_H_ -#define MOJO_EDK_JS_SUPPORT_H_ - -#include "mojo/edk/js/js_export.h" -#include "v8/include/v8.h" - -namespace mojo { -namespace edk { -namespace js { - -class MOJO_JS_EXPORT Support { - public: - static const char kModuleName[]; - static v8::Local GetModule(v8::Isolate* isolate); -}; - -} // namespace js -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_JS_SUPPORT_H_ diff --git a/mojo/edk/js/tests/BUILD.gn b/mojo/edk/js/tests/BUILD.gn deleted file mode 100644 index f56c4b9..0000000 --- a/mojo/edk/js/tests/BUILD.gn +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/tools/bindings/mojom.gni") -import("//testing/test.gni") - -# TODO(hansmuller): The organization of tests in this directory is weird: -# * Really, js_unittests tests public stuff, so that should live in public -# and be reworked as some sort of apptest. -# * Both js_unittests and js_integration_tests should auto-generate their -# tests somehow. The .cc files are just test runner stubs, including -# explicit lists of .js files. - -group("tests") { - testonly = true - deps = [ - ":mojo_js_integration_tests", - ":mojo_js_unittests", - ] -} - -test("mojo_js_integration_tests") { - deps = [ - ":js_to_cpp_bindings", - "//gin:gin_test", - "//mojo/common", - "//mojo/edk/js", - "//mojo/edk/test:run_all_unittests", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/public/js:bindings", - ] - - sources = [ - "js_to_cpp_tests.cc", - ] - - data = [ - "js_to_cpp_tests.js", - ] - - configs += [ "//v8:external_startup_data" ] -} - -mojom("js_to_cpp_bindings") { - sources = [ - "js_to_cpp.mojom", - ] -} - -test("mojo_js_unittests") { - deps = [ - "//base", - "//gin:gin_test", - "//mojo/edk/js", - "//mojo/edk/test:run_all_unittests", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/system", - "//mojo/public/interfaces/bindings/tests:test_interfaces", - "//mojo/public/js:tests", - ] - - sources = [ - "//mojo/edk/js/handle_unittest.cc", - "run_js_unittests.cc", - ] -} diff --git a/mojo/edk/js/tests/js_to_cpp.mojom b/mojo/edk/js/tests/js_to_cpp.mojom deleted file mode 100644 index 688b22b..0000000 --- a/mojo/edk/js/tests/js_to_cpp.mojom +++ /dev/null @@ -1,54 +0,0 @@ -module js_to_cpp; - -// This struct encompasses all of the basic types, so that they -// may be sent from C++ to JS and back for validation. -struct EchoArgs { - int64 si64; - int32 si32; - int16 si16; - int8 si8; - uint64 ui64; - uint32 ui32; - uint16 ui16; - uint8 ui8; - float float_val; - float float_inf; - float float_nan; - double double_val; - double double_inf; - double double_nan; - string? name; - array? string_array; - handle? message_handle; - handle? data_handle; -}; - -struct EchoArgsList { - EchoArgsList? next; - EchoArgs? item; -}; - -// Note: For messages which control test flow, pick numbers that are unlikely -// to be hit as a result of our deliberate corruption of response messages. -interface CppSide { - // Sent for all tests to notify that the JS side is now ready. - StartTest@88888888(); - - // Indicates end for echo, bit-flip, and back-pointer tests. - TestFinished@99999999(); - - // Responses from specific tests. - PingResponse(); - EchoResponse(EchoArgsList list); - BitFlipResponse(EchoArgsList arg); - BackPointerResponse(EchoArgsList arg); -}; - -interface JsSide { - SetCppSide(CppSide cpp); - - Ping(); - Echo(int32 numIterations, EchoArgs arg); - BitFlip(EchoArgs arg); - BackPointer(EchoArgs arg); -}; diff --git a/mojo/edk/js/tests/js_to_cpp_tests.cc b/mojo/edk/js/tests/js_to_cpp_tests.cc deleted file mode 100644 index b6b74e3..0000000 --- a/mojo/edk/js/tests/js_to_cpp_tests.cc +++ /dev/null @@ -1,455 +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 -#include - -#include -#include - -#include "base/at_exit.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "gin/array_buffer.h" -#include "gin/public/isolate_holder.h" -#include "gin/v8_initializer.h" -#include "mojo/common/data_pipe_utils.h" -#include "mojo/edk/js/mojo_runner_delegate.h" -#include "mojo/edk/js/tests/js_to_cpp.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/wait.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace js { - -// Global value updated by some checks to prevent compilers from optimizing -// reads out of existence. -uint32_t g_waste_accumulator = 0; - -namespace { - -// Negative numbers with different values in each byte, the last of -// which can survive promotion to double and back. -const int8_t kExpectedInt8Value = -65; -const int16_t kExpectedInt16Value = -16961; -const int32_t kExpectedInt32Value = -1145258561; -const int64_t kExpectedInt64Value = -77263311946305LL; - -// Positive numbers with different values in each byte, the last of -// which can survive promotion to double and back. -const uint8_t kExpectedUInt8Value = 65; -const uint16_t kExpectedUInt16Value = 16961; -const uint32_t kExpectedUInt32Value = 1145258561; -const uint64_t kExpectedUInt64Value = 77263311946305LL; - -// Double/float values, including special case constants. -const double kExpectedDoubleVal = 3.14159265358979323846; -const double kExpectedDoubleInf = std::numeric_limits::infinity(); -const double kExpectedDoubleNan = std::numeric_limits::quiet_NaN(); -const float kExpectedFloatVal = static_cast(kExpectedDoubleVal); -const float kExpectedFloatInf = std::numeric_limits::infinity(); -const float kExpectedFloatNan = std::numeric_limits::quiet_NaN(); - -// NaN has the property that it is not equal to itself. -#define EXPECT_NAN(x) EXPECT_NE(x, x) - -void CheckDataPipe(ScopedDataPipeConsumerHandle data_pipe_handle) { - std::string buffer; - bool result = common::BlockingCopyToString(std::move(data_pipe_handle), - &buffer); - EXPECT_TRUE(result); - EXPECT_EQ(64u, buffer.size()); - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(i, buffer[i]); - } -} - -void CheckMessagePipe(MessagePipeHandle message_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast(sizeof(buffer)); - MojoResult result = Wait(message_pipe_handle, MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_RESULT_OK, result); - result = ReadMessageRaw( - message_pipe_handle, buffer, &buffer_size, 0, 0, 0); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(64u, buffer_size); - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(255 - i, buffer[i]); - } -} - -js_to_cpp::EchoArgsPtr BuildSampleEchoArgs() { - js_to_cpp::EchoArgsPtr args(js_to_cpp::EchoArgs::New()); - args->si64 = kExpectedInt64Value; - args->si32 = kExpectedInt32Value; - args->si16 = kExpectedInt16Value; - args->si8 = kExpectedInt8Value; - args->ui64 = kExpectedUInt64Value; - args->ui32 = kExpectedUInt32Value; - args->ui16 = kExpectedUInt16Value; - args->ui8 = kExpectedUInt8Value; - args->float_val = kExpectedFloatVal; - args->float_inf = kExpectedFloatInf; - args->float_nan = kExpectedFloatNan; - args->double_val = kExpectedDoubleVal; - args->double_inf = kExpectedDoubleInf; - args->double_nan = kExpectedDoubleNan; - args->name.emplace("coming"); - args->string_array.emplace(3); - (*args->string_array)[0] = "one"; - (*args->string_array)[1] = "two"; - (*args->string_array)[2] = "three"; - return args; -} - -void CheckSampleEchoArgs(js_to_cpp::EchoArgsPtr arg) { - EXPECT_EQ(kExpectedInt64Value, arg->si64); - EXPECT_EQ(kExpectedInt32Value, arg->si32); - EXPECT_EQ(kExpectedInt16Value, arg->si16); - EXPECT_EQ(kExpectedInt8Value, arg->si8); - EXPECT_EQ(kExpectedUInt64Value, arg->ui64); - EXPECT_EQ(kExpectedUInt32Value, arg->ui32); - EXPECT_EQ(kExpectedUInt16Value, arg->ui16); - EXPECT_EQ(kExpectedUInt8Value, arg->ui8); - EXPECT_EQ(kExpectedFloatVal, arg->float_val); - EXPECT_EQ(kExpectedFloatInf, arg->float_inf); - EXPECT_NAN(arg->float_nan); - EXPECT_EQ(kExpectedDoubleVal, arg->double_val); - EXPECT_EQ(kExpectedDoubleInf, arg->double_inf); - EXPECT_NAN(arg->double_nan); - EXPECT_EQ(std::string("coming"), *arg->name); - EXPECT_EQ(std::string("one"), (*arg->string_array)[0]); - EXPECT_EQ(std::string("two"), (*arg->string_array)[1]); - EXPECT_EQ(std::string("three"), (*arg->string_array)[2]); - CheckDataPipe(std::move(arg->data_handle)); - CheckMessagePipe(arg->message_handle.get()); -} - -void CheckSampleEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) { - if (list.is_null()) - return; - CheckSampleEchoArgs(std::move(list->item)); - CheckSampleEchoArgsList(list->next); -} - -// More forgiving checks are needed in the face of potentially corrupt -// messages. The values don't matter so long as all accesses are within -// bounds. -void CheckCorruptedString(const std::string& arg) { - for (size_t i = 0; i < arg.size(); ++i) - g_waste_accumulator += arg[i]; -} - -void CheckCorruptedString(const base::Optional& arg) { - if (!arg) - return; - CheckCorruptedString(*arg); -} - -void CheckCorruptedStringArray( - const base::Optional>& string_array) { - if (!string_array) - return; - for (size_t i = 0; i < string_array->size(); ++i) - CheckCorruptedString((*string_array)[i]); -} - -void CheckCorruptedDataPipe(MojoHandle data_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast(sizeof(buffer)); - MojoResult result = MojoReadData( - data_pipe_handle, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE); - if (result != MOJO_RESULT_OK) - return; - for (uint32_t i = 0; i < buffer_size; ++i) - g_waste_accumulator += buffer[i]; -} - -void CheckCorruptedMessagePipe(MojoHandle message_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast(sizeof(buffer)); - MojoResult result = MojoReadMessage( - message_pipe_handle, buffer, &buffer_size, 0, 0, 0); - if (result != MOJO_RESULT_OK) - return; - for (uint32_t i = 0; i < buffer_size; ++i) - g_waste_accumulator += buffer[i]; -} - -void CheckCorruptedEchoArgs(const js_to_cpp::EchoArgsPtr& arg) { - if (arg.is_null()) - return; - CheckCorruptedString(arg->name); - CheckCorruptedStringArray(arg->string_array); - if (arg->data_handle.is_valid()) - CheckCorruptedDataPipe(arg->data_handle.get().value()); - if (arg->message_handle.is_valid()) - CheckCorruptedMessagePipe(arg->message_handle.get().value()); -} - -void CheckCorruptedEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) { - if (list.is_null()) - return; - CheckCorruptedEchoArgs(list->item); - CheckCorruptedEchoArgsList(list->next); -} - -// Base Provider implementation class. It's expected that tests subclass and -// override the appropriate Provider functions. When test is done quit the -// run_loop(). -class CppSideConnection : public js_to_cpp::CppSide { - public: - CppSideConnection() - : run_loop_(nullptr), - js_side_(nullptr), - mishandled_messages_(0), - binding_(this) {} - ~CppSideConnection() override {} - - void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; } - base::RunLoop* run_loop() { return run_loop_; } - - void set_js_side(js_to_cpp::JsSide* js_side) { js_side_ = js_side; } - js_to_cpp::JsSide* js_side() { return js_side_; } - - void Bind(InterfaceRequest request) { - binding_.Bind(std::move(request)); - // Keep the pipe open even after validation errors. - binding_.EnableTestingMode(); - } - - // js_to_cpp::CppSide: - void StartTest() override { NOTREACHED(); } - - void TestFinished() override { NOTREACHED(); } - - void PingResponse() override { mishandled_messages_ += 1; } - - void EchoResponse(js_to_cpp::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - void BitFlipResponse(js_to_cpp::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - protected: - base::RunLoop* run_loop_; - js_to_cpp::JsSide* js_side_; - int mishandled_messages_; - mojo::Binding binding_; - - private: - DISALLOW_COPY_AND_ASSIGN(CppSideConnection); -}; - -// Trivial test to verify a message sent from JS is received. -class PingCppSideConnection : public CppSideConnection { - public: - PingCppSideConnection() : got_message_(false) {} - ~PingCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->Ping(); } - - void PingResponse() override { - got_message_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return got_message_ && !mishandled_messages_; - } - - private: - bool got_message_; - DISALLOW_COPY_AND_ASSIGN(PingCppSideConnection); -}; - -// Test that parameters are passed with correct values. -class EchoCppSideConnection : public CppSideConnection { - public: - EchoCppSideConnection() : - message_count_(0), - termination_seen_(false) { - } - ~EchoCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { - js_side_->Echo(kExpectedMessageCount, BuildSampleEchoArgs()); - } - - void EchoResponse(js_to_cpp::EchoArgsListPtr list) override { - const js_to_cpp::EchoArgsPtr& special_arg = list->item; - message_count_ += 1; - EXPECT_EQ(-1, special_arg->si64); - EXPECT_EQ(-1, special_arg->si32); - EXPECT_EQ(-1, special_arg->si16); - EXPECT_EQ(-1, special_arg->si8); - EXPECT_EQ(std::string("going"), *special_arg->name); - CheckSampleEchoArgsList(list->next); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_ && - !mishandled_messages_ && - message_count_ == kExpectedMessageCount; - } - - private: - static const int kExpectedMessageCount = 10; - int message_count_; - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(EchoCppSideConnection); -}; - -// Test that corrupted messages don't wreak havoc. -class BitFlipCppSideConnection : public CppSideConnection { - public: - BitFlipCppSideConnection() : termination_seen_(false) {} - ~BitFlipCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->BitFlip(BuildSampleEchoArgs()); } - - void BitFlipResponse(js_to_cpp::EchoArgsListPtr list) override { - CheckCorruptedEchoArgsList(list); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_; - } - - private: - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(BitFlipCppSideConnection); -}; - -// Test that severely random messages don't wreak havoc. -class BackPointerCppSideConnection : public CppSideConnection { - public: - BackPointerCppSideConnection() : termination_seen_(false) {} - ~BackPointerCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->BackPointer(BuildSampleEchoArgs()); } - - void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override { - CheckCorruptedEchoArgsList(list); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_; - } - - private: - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(BackPointerCppSideConnection); -}; - -} // namespace - -class JsToCppTest : public testing::Test { - public: - JsToCppTest() {} - - void RunTest(const std::string& test, CppSideConnection* cpp_side) { - cpp_side->set_run_loop(&run_loop_); - - js_to_cpp::JsSidePtr js_side; - auto js_side_proxy = MakeRequest(&js_side); - - cpp_side->set_js_side(js_side.get()); - js_to_cpp::CppSidePtr cpp_side_ptr; - cpp_side->Bind(MakeRequest(&cpp_side_ptr)); - - js_side->SetCppSide(std::move(cpp_side_ptr)); - -#ifdef V8_USE_EXTERNAL_STARTUP_DATA - gin::V8Initializer::LoadV8Snapshot(); - gin::V8Initializer::LoadV8Natives(); -#endif - - gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode, - gin::IsolateHolder::kStableV8Extras, - gin::ArrayBufferAllocator::SharedInstance()); - gin::IsolateHolder instance(base::ThreadTaskRunnerHandle::Get()); - MojoRunnerDelegate delegate; - gin::ShellRunner runner(&delegate, instance.isolate()); - delegate.Start(&runner, js_side_proxy.PassMessagePipe().release().value(), - test); - - run_loop_.Run(); - } - - private: - base::ShadowingAtExitManager at_exit_; - base::MessageLoop loop; - base::RunLoop run_loop_; - - DISALLOW_COPY_AND_ASSIGN(JsToCppTest); -}; - -TEST_F(JsToCppTest, Ping) { - PingCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, Echo) { - EchoCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, BitFlip) { - // These tests generate a lot of expected validation errors. Suppress logging. - mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; - - BitFlipCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, BackPointer) { - // These tests generate a lot of expected validation errors. Suppress logging. - mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; - - BackPointerCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/tests/js_to_cpp_tests.js b/mojo/edk/js/tests/js_to_cpp_tests.js deleted file mode 100644 index 6b69fca..0000000 --- a/mojo/edk/js/tests/js_to_cpp_tests.js +++ /dev/null @@ -1,223 +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. - -define('mojo/edk/js/tests/js_to_cpp_tests', [ - 'console', - 'mojo/edk/js/tests/js_to_cpp.mojom', - 'mojo/public/js/bindings', - 'mojo/public/js/connector', - 'mojo/public/js/core', -], function (console, jsToCpp, bindings, connector, core) { - var retainedJsSide; - var retainedJsSideStub; - var sampleData; - var sampleMessage; - var BAD_VALUE = 13; - var DATA_PIPE_PARAMS = { - flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, - elementNumBytes: 1, - capacityNumBytes: 64 - }; - - function JsSideConnection() { - this.binding = new bindings.Binding(jsToCpp.JsSide, this); - } - - JsSideConnection.prototype.setCppSide = function(cppSide) { - this.cppSide_ = cppSide; - this.cppSide_.startTest(); - }; - - JsSideConnection.prototype.ping = function (arg) { - this.cppSide_.pingResponse(); - }; - - JsSideConnection.prototype.echo = function (numIterations, arg) { - var dataPipe1; - var dataPipe2; - var i; - var messagePipe1; - var messagePipe2; - var specialArg; - - // Ensure expected negative values are negative. - if (arg.si64 > 0) - arg.si64 = BAD_VALUE; - - if (arg.si32 > 0) - arg.si32 = BAD_VALUE; - - if (arg.si16 > 0) - arg.si16 = BAD_VALUE; - - if (arg.si8 > 0) - arg.si8 = BAD_VALUE; - - for (i = 0; i < numIterations; ++i) { - dataPipe1 = core.createDataPipe(DATA_PIPE_PARAMS); - dataPipe2 = core.createDataPipe(DATA_PIPE_PARAMS); - messagePipe1 = core.createMessagePipe(); - messagePipe2 = core.createMessagePipe(); - - arg.data_handle = dataPipe1.consumerHandle; - arg.message_handle = messagePipe1.handle1; - - specialArg = new jsToCpp.EchoArgs(); - specialArg.si64 = -1; - specialArg.si32 = -1; - specialArg.si16 = -1; - specialArg.si8 = -1; - specialArg.name = 'going'; - specialArg.data_handle = dataPipe2.consumerHandle; - specialArg.message_handle = messagePipe2.handle1; - - writeDataPipe(dataPipe1, sampleData); - writeDataPipe(dataPipe2, sampleData); - writeMessagePipe(messagePipe1, sampleMessage); - writeMessagePipe(messagePipe2, sampleMessage); - - this.cppSide_.echoResponse(createEchoArgsList(specialArg, arg)); - - core.close(dataPipe1.producerHandle); - core.close(dataPipe2.producerHandle); - core.close(messagePipe1.handle0); - core.close(messagePipe2.handle0); - } - this.cppSide_.testFinished(); - }; - - JsSideConnection.prototype.bitFlip = function (arg) { - var iteration = 0; - var dataPipe; - var messagePipe; - var proto = connector.Connector.prototype; - var stopSignalled = false; - - proto.realAccept = proto.accept; - proto.accept = function (message) { - var offset = iteration / 8; - var mask; - var value; - if (offset < message.buffer.arrayBuffer.byteLength) { - mask = 1 << (iteration % 8); - value = message.buffer.getUint8(offset) ^ mask; - message.buffer.setUint8(offset, value); - return this.realAccept(message); - } - stopSignalled = true; - return false; - }; - - while (!stopSignalled) { - dataPipe = core.createDataPipe(DATA_PIPE_PARAMS); - messagePipe = core.createMessagePipe(); - writeDataPipe(dataPipe, sampleData); - writeMessagePipe(messagePipe, sampleMessage); - arg.data_handle = dataPipe.consumerHandle; - arg.message_handle = messagePipe.handle1; - - this.cppSide_.bitFlipResponse(createEchoArgsList(arg)); - - core.close(dataPipe.producerHandle); - core.close(messagePipe.handle0); - iteration += 1; - } - - proto.accept = proto.realAccept; - proto.realAccept = null; - this.cppSide_.testFinished(); - }; - - JsSideConnection.prototype.backPointer = function (arg) { - var iteration = 0; - var dataPipe; - var messagePipe; - var proto = connector.Connector.prototype; - var stopSignalled = false; - - proto.realAccept = proto.accept; - proto.accept = function (message) { - var delta = 8 * (1 + iteration % 32); - var offset = 8 * ((iteration / 32) | 0); - if (offset < message.buffer.arrayBuffer.byteLength - 4) { - message.buffer.dataView.setUint32(offset, 0x100000000 - delta, true); - message.buffer.dataView.setUint32(offset + 4, 0xffffffff, true); - return this.realAccept(message); - } - stopSignalled = true; - return false; - }; - - while (!stopSignalled) { - dataPipe = core.createDataPipe(DATA_PIPE_PARAMS); - messagePipe = core.createMessagePipe(); - writeDataPipe(dataPipe, sampleData); - writeMessagePipe(messagePipe, sampleMessage); - arg.data_handle = dataPipe.consumerHandle; - arg.message_handle = messagePipe.handle1; - - this.cppSide_.backPointerResponse(createEchoArgsList(arg)); - - core.close(dataPipe.producerHandle); - core.close(messagePipe.handle0); - iteration += 1; - } - - proto.accept = proto.realAccept; - proto.realAccept = null; - this.cppSide_.testFinished(); - }; - - function writeDataPipe(pipe, data) { - var writeResult = core.writeData( - pipe.producerHandle, data, core.WRITE_DATA_FLAG_ALL_OR_NONE); - - if (writeResult.result != core.RESULT_OK) { - console.log('ERROR: Data pipe write result was ' + writeResult.result); - return false; - } - if (writeResult.numBytes != data.length) { - console.log('ERROR: Data pipe write length was ' + writeResult.numBytes); - return false; - } - return true; - } - - function writeMessagePipe(pipe, arrayBuffer) { - var result = core.writeMessage(pipe.handle0, arrayBuffer, [], 0); - if (result != core.RESULT_OK) { - console.log('ERROR: Message pipe write result was ' + result); - return false; - } - return true; - } - - function createEchoArgsListElement(item, next) { - var list = new jsToCpp.EchoArgsList(); - list.item = item; - list.next = next; - return list; - } - - function createEchoArgsList() { - var genuineArray = Array.prototype.slice.call(arguments); - return genuineArray.reduceRight(function (previous, current) { - return createEchoArgsListElement(current, previous); - }, null); - } - - return function(jsSideRequestHandle) { - var i; - sampleData = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes); - for (i = 0; i < sampleData.length; ++i) { - sampleData[i] = i; - } - sampleMessage = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes); - for (i = 0; i < sampleMessage.length; ++i) { - sampleMessage[i] = 255 - i; - } - retainedJsSide = new JsSideConnection; - retainedJsSide.binding.bind(jsSideRequestHandle); - }; -}); diff --git a/mojo/edk/js/tests/run_js_unittests.cc b/mojo/edk/js/tests/run_js_unittests.cc deleted file mode 100644 index 13e796b..0000000 --- a/mojo/edk/js/tests/run_js_unittests.cc +++ /dev/null @@ -1,61 +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 "base/files/file_path.h" -#include "base/macros.h" -#include "base/path_service.h" -#include "gin/modules/console.h" -#include "gin/modules/module_registry.h" -#include "gin/modules/timer.h" -#include "gin/test/file_runner.h" -#include "gin/test/gtest.h" -#include "mojo/edk/js/core.h" -#include "mojo/edk/js/support.h" -#include "mojo/edk/js/threading.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace js { -namespace { - -class TestRunnerDelegate : public gin::FileRunnerDelegate { - public: - TestRunnerDelegate() { - AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule); - AddBuiltinModule(gin::TimerModule::kName, gin::TimerModule::GetModule); - AddBuiltinModule(Core::kModuleName, Core::GetModule); - AddBuiltinModule(Threading::kModuleName, Threading::GetModule); - AddBuiltinModule(Support::kModuleName, Support::GetModule); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TestRunnerDelegate); -}; - -void RunTest(std::string test, bool run_until_idle) { - base::FilePath path; - PathService::Get(base::DIR_SOURCE_ROOT, &path); - path = path.AppendASCII("mojo") - .AppendASCII("public") - .AppendASCII("js") - .AppendASCII("tests") - .AppendASCII(test); - TestRunnerDelegate delegate; - gin::RunTestFromFile(path, &delegate, run_until_idle); -} - -// TODO(abarth): Should we autogenerate these stubs from GYP? -TEST(JSTest, Core) { - RunTest("core_unittest.js", true); -} - -TEST(JSTest, Validation) { - RunTest("validation_unittest.js", true); -} - -} // namespace -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/threading.cc b/mojo/edk/js/threading.cc deleted file mode 100644 index db9f12d..0000000 --- a/mojo/edk/js/threading.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/js/threading.h" - -#include "base/message_loop/message_loop.h" -#include "gin/object_template_builder.h" -#include "gin/per_isolate_data.h" -#include "mojo/edk/js/handle.h" - -namespace mojo { -namespace edk { -namespace js { - -namespace { - -void Quit() { - base::MessageLoop::current()->QuitNow(); -} - -gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin }; - -} // namespace - -const char Threading::kModuleName[] = "mojo/public/js/threading"; - -v8::Local Threading::GetModule(v8::Isolate* isolate) { - gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); - v8::Local templ = data->GetObjectTemplate( - &g_wrapper_info); - - if (templ.IsEmpty()) { - templ = gin::ObjectTemplateBuilder(isolate) - .SetMethod("quit", Quit) - .Build(); - - data->SetObjectTemplate(&g_wrapper_info, templ); - } - - return templ->NewInstance(); -} - -Threading::Threading() { -} - -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/threading.h b/mojo/edk/js/threading.h deleted file mode 100644 index 653d076..0000000 --- a/mojo/edk/js/threading.h +++ /dev/null @@ -1,28 +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_JS_THREADING_H_ -#define MOJO_EDK_JS_THREADING_H_ - -#include "gin/public/wrapper_info.h" -#include "mojo/edk/js/js_export.h" -#include "v8/include/v8.h" - -namespace mojo { -namespace edk { -namespace js { - -class MOJO_JS_EXPORT Threading { - public: - static const char kModuleName[]; - static v8::Local GetModule(v8::Isolate* isolate); - private: - Threading(); -}; - -} // namespace js -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_JS_THREADING_H_ diff --git a/mojo/edk/js/waiting_callback.cc b/mojo/edk/js/waiting_callback.cc deleted file mode 100644 index 6ad4bd0..0000000 --- a/mojo/edk/js/waiting_callback.cc +++ /dev/null @@ -1,95 +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/js/waiting_callback.h" - -#include "base/bind.h" -#include "base/message_loop/message_loop.h" -#include "gin/per_context_data.h" - -namespace mojo { -namespace edk { -namespace js { - -namespace { - -v8::Handle GetHiddenPropertyName(v8::Isolate* isolate) { - return v8::Private::ForApi( - isolate, gin::StringToV8(isolate, "::mojo::js::WaitingCallback")); -} - -} // namespace - -gin::WrapperInfo WaitingCallback::kWrapperInfo = { gin::kEmbedderNativeGin }; - -// static -gin::Handle WaitingCallback::Create( - v8::Isolate* isolate, - v8::Handle callback, - gin::Handle handle_wrapper, - MojoHandleSignals signals, - bool one_shot) { - gin::Handle waiting_callback = gin::CreateHandle( - isolate, new WaitingCallback(isolate, callback, one_shot)); - MojoResult result = waiting_callback->watcher_.Watch( - handle_wrapper->get(), signals, - base::Bind(&WaitingCallback::OnHandleReady, - base::Unretained(waiting_callback.get()))); - - // The signals may already be unsatisfiable. - if (result == MOJO_RESULT_FAILED_PRECONDITION) - waiting_callback->OnHandleReady(MOJO_RESULT_FAILED_PRECONDITION); - - return waiting_callback; -} - -void WaitingCallback::Cancel() { - if (watcher_.IsWatching()) - watcher_.Cancel(); -} - -WaitingCallback::WaitingCallback(v8::Isolate* isolate, - v8::Handle callback, - bool one_shot) - : one_shot_(one_shot), - watcher_(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC), - weak_factory_(this) { - v8::Handle context = isolate->GetCurrentContext(); - runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); - GetWrapper(isolate) - ->SetPrivate(context, GetHiddenPropertyName(isolate), callback) - .FromJust(); -} - -WaitingCallback::~WaitingCallback() { - Cancel(); -} - -void WaitingCallback::OnHandleReady(MojoResult result) { - if (!runner_) - return; - - gin::Runner::Scope scope(runner_.get()); - v8::Isolate* isolate = runner_->GetContextHolder()->isolate(); - - v8::Handle hidden_value = - GetWrapper(isolate) - ->GetPrivate(runner_->GetContextHolder()->context(), - GetHiddenPropertyName(isolate)) - .ToLocalChecked(); - v8::Handle callback; - CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback)); - - v8::Handle args[] = { gin::ConvertToV8(isolate, result) }; - runner_->Call(callback, runner_->global(), 1, args); - - if (one_shot_ || result == MOJO_RESULT_CANCELLED) { - runner_.reset(); - Cancel(); - } -} - -} // namespace js -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/js/waiting_callback.h b/mojo/edk/js/waiting_callback.h deleted file mode 100644 index f97b389..0000000 --- a/mojo/edk/js/waiting_callback.h +++ /dev/null @@ -1,67 +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_JS_WAITING_CALLBACK_H_ -#define MOJO_EDK_JS_WAITING_CALLBACK_H_ - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "gin/handle.h" -#include "gin/runner.h" -#include "gin/wrappable.h" -#include "mojo/edk/js/handle.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/simple_watcher.h" - -namespace mojo { -namespace edk { -namespace js { - -class WaitingCallback : public gin::Wrappable { - public: - static gin::WrapperInfo kWrapperInfo; - - // Creates a new WaitingCallback. - // - // If |one_shot| is true, the callback will only ever be called at most once. - // If false, the callback may be called any number of times until the - // WaitingCallback is explicitly cancelled. - static gin::Handle Create( - v8::Isolate* isolate, - v8::Handle callback, - gin::Handle handle_wrapper, - MojoHandleSignals signals, - bool one_shot); - - // Cancels the callback. Does nothing if a callback is not pending. This is - // implicitly invoked from the destructor but can be explicitly invoked as - // necessary. - void Cancel(); - - private: - WaitingCallback(v8::Isolate* isolate, - v8::Handle callback, - bool one_shot); - ~WaitingCallback() override; - - // Callback from the Watcher. - void OnHandleReady(MojoResult result); - - // Indicates whether this is a one-shot callback or not. If so, it uses the - // deprecated HandleWatcher to wait for signals; otherwise it uses the new - // system Watcher API. - const bool one_shot_; - - base::WeakPtr runner_; - SimpleWatcher watcher_; - base::WeakPtrFactory weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(WaitingCallback); -}; - -} // namespace js -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_JS_WAITING_CALLBACK_H_ diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn deleted file mode 100644 index a68cd44..0000000 --- a/mojo/edk/system/BUILD.gn +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/nacl/config.gni") -import("//testing/test.gni") -import("../../../mojo/public/tools/bindings/mojom.gni") - -if (is_android) { - import("//build/config/android/config.gni") - import("//build/config/android/rules.gni") -} - -component("system") { - output_name = "mojo_system_impl" - - sources = [ - "atomic_flag.h", - "broker.h", - "broker_host.cc", - "broker_host.h", - "broker_posix.cc", - "broker_win.cc", - "channel.cc", - "channel.h", - "channel_posix.cc", - "channel_win.cc", - "configuration.cc", - "configuration.h", - "core.cc", - "core.h", - "data_pipe_consumer_dispatcher.cc", - "data_pipe_consumer_dispatcher.h", - "data_pipe_control_message.cc", - "data_pipe_control_message.h", - "data_pipe_producer_dispatcher.cc", - "data_pipe_producer_dispatcher.h", - "dispatcher.cc", - "dispatcher.h", - "handle_signals_state.h", - "handle_table.cc", - "handle_table.h", - "mapping_table.cc", - "mapping_table.h", - "message_for_transit.cc", - "message_for_transit.h", - "message_pipe_dispatcher.cc", - "message_pipe_dispatcher.h", - "node_channel.cc", - "node_channel.h", - "node_controller.cc", - "node_controller.h", - "options_validation.h", - "platform_handle_dispatcher.cc", - "platform_handle_dispatcher.h", - "ports_message.cc", - "ports_message.h", - "request_context.cc", - "request_context.h", - "shared_buffer_dispatcher.cc", - "shared_buffer_dispatcher.h", - "watch.cc", - "watch.h", - "watcher_dispatcher.cc", - "watcher_dispatcher.h", - "watcher_set.cc", - "watcher_set.h", - ] - - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - - public_deps = [ - "//mojo/edk/embedder", - "//mojo/edk/embedder:platform", - "//mojo/edk/system/ports", - "//mojo/public/c/system", - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - ] - - if (!is_nacl) { - deps += [ "//crypto" ] - } - - if (is_win) { - cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()), - # which is uninteresting. - } - - if (is_mac && !is_ios) { - sources += [ - "mach_port_relay.cc", - "mach_port_relay.h", - ] - } - - if (is_nacl && !is_nacl_nonsfi) { - sources -= [ - "broker_host.cc", - "broker_posix.cc", - "channel_posix.cc", - ] - } - - # Use target_os == "chromeos" instead of is_chromeos because we need to - # build NaCl targets (i.e. IRT) for ChromeOS the same as the rest of ChromeOS. - if (is_android || target_os == "chromeos") { - defines += [ "MOJO_EDK_LEGACY_PROTOCOL" ] - } - - allow_circular_includes_from = [ "//mojo/edk/embedder" ] -} - -group("tests") { - testonly = true - deps = [ - ":mojo_system_unittests", - ] - - if (!is_ios) { - deps += [ ":mojo_message_pipe_perftests" ] - } -} - -source_set("test_utils") { - testonly = true - - sources = [ - "test_utils.cc", - "test_utils.h", - ] - - public_deps = [ - "//mojo/public/c/system", - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//mojo/edk/test:test_support", - "//testing/gtest:gtest", - ] -} - -test("mojo_system_unittests") { - sources = [ - "channel_unittest.cc", - "core_test_base.cc", - "core_test_base.h", - "core_unittest.cc", - "message_pipe_unittest.cc", - "options_validation_unittest.cc", - "platform_handle_dispatcher_unittest.cc", - "shared_buffer_dispatcher_unittest.cc", - "shared_buffer_unittest.cc", - "signals_unittest.cc", - "watcher_unittest.cc", - ] - - if (!is_ios) { - sources += [ - "data_pipe_unittest.cc", - "multiprocess_message_pipe_unittest.cc", - "platform_wrapper_unittest.cc", - ] - } - - deps = [ - ":test_utils", - "//base", - "//base/test:test_support", - "//mojo/edk/embedder:embedder_unittests", - "//mojo/edk/system", - "//mojo/edk/system/ports:tests", - "//mojo/edk/test:run_all_unittests", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/system", - "//testing/gmock", - "//testing/gtest", - ] - - allow_circular_includes_from = [ "//mojo/edk/embedder:embedder_unittests" ] -} - -if (!is_ios) { - test("mojo_message_pipe_perftests") { - sources = [ - "message_pipe_perftest.cc", - ] - - deps = [ - ":test_utils", - "//base", - "//base/test:test_support", - "//mojo/edk/system", - "//mojo/edk/test:run_all_perftests", - "//mojo/edk/test:test_support", - "//testing/gtest", - ] - } -} diff --git a/mojo/edk/system/atomic_flag.h b/mojo/edk/system/atomic_flag.h deleted file mode 100644 index 6bdcfaa..0000000 --- a/mojo/edk/system/atomic_flag.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_ -#define MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_ - -#include "base/atomicops.h" -#include "base/macros.h" - -namespace mojo { -namespace edk { - -// AtomicFlag is a boolean flag that can be set and tested atomically. It is -// intended to be used to fast-path checks where the common case would normally -// release the governing mutex immediately after checking. -// -// Example usage: -// void DoFoo(Bar* bar) { -// AutoLock l(lock_); -// queue_.push_back(bar); -// flag_.Set(true); -// } -// -// void Baz() { -// if (!flag_) // Assume this is the common case. -// return; -// -// AutoLock l(lock_); -// ... drain queue_ ... -// flag_.Set(false); -// } -class AtomicFlag { - public: - AtomicFlag() : flag_(0) {} - ~AtomicFlag() {} - - void Set(bool value) { - base::subtle::Release_Store(&flag_, value ? 1 : 0); - } - - bool Get() const { - return base::subtle::Acquire_Load(&flag_) ? true : false; - } - - operator const bool() const { return Get(); } - - private: - base::subtle::Atomic32 flag_; - - DISALLOW_COPY_AND_ASSIGN(AtomicFlag); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_ATOMIC_FLAG_H_ diff --git a/mojo/edk/system/broker.h b/mojo/edk/system/broker.h deleted file mode 100644 index 1577972..0000000 --- a/mojo/edk/system/broker.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_BROKER_H_ -#define MOJO_EDK_SYSTEM_BROKER_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" - -namespace mojo { -namespace edk { - -class PlatformSharedBuffer; - -// The Broker is a channel to the parent process, which allows synchronous IPCs. -class Broker { - public: - // Note: This is blocking, and will wait for the first message over - // |platform_handle|. - explicit Broker(ScopedPlatformHandle platform_handle); - ~Broker(); - - // Returns the platform handle that should be used to establish a NodeChannel - // to the parent process. - ScopedPlatformHandle GetParentPlatformHandle(); - - // Request a shared buffer from the parent process. Blocks the current thread. - scoped_refptr GetSharedBuffer(size_t num_bytes); - - private: - // Handle to the parent process, used for synchronous IPCs. - ScopedPlatformHandle sync_channel_; - - // Handle to the parent process which is recieved in the first first message - // over |sync_channel_|. - ScopedPlatformHandle parent_channel_; - - // Lock to only allow one sync message at a time. This avoids having to deal - // with message ordering since we can only have one request at a time - // in-flight. - base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(Broker); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_BROKER_H_ diff --git a/mojo/edk/system/broker_host.cc b/mojo/edk/system/broker_host.cc deleted file mode 100644 index 6096034..0000000 --- a/mojo/edk/system/broker_host.cc +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/broker_host.h" - -#include - -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/edk/embedder/named_platform_channel_pair.h" -#include "mojo/edk/embedder/named_platform_handle.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/broker_messages.h" - -namespace mojo { -namespace edk { - -BrokerHost::BrokerHost(base::ProcessHandle client_process, - ScopedPlatformHandle platform_handle) -#if defined(OS_WIN) - : client_process_(client_process) -#endif -{ - CHECK(platform_handle.is_valid()); - - base::MessageLoop::current()->AddDestructionObserver(this); - - channel_ = Channel::Create(this, ConnectionParams(std::move(platform_handle)), - base::ThreadTaskRunnerHandle::Get()); - channel_->Start(); -} - -BrokerHost::~BrokerHost() { - // We're always destroyed on the creation thread, which is the IO thread. - base::MessageLoop::current()->RemoveDestructionObserver(this); - - if (channel_) - channel_->ShutDown(); -} - -bool BrokerHost::PrepareHandlesForClient(PlatformHandleVector* handles) { -#if defined(OS_WIN) - if (!Channel::Message::RewriteHandles( - base::GetCurrentProcessHandle(), client_process_, handles)) { - // NOTE: We only log an error here. We do not signal a logical error or - // prevent any message from being sent. The client should handle unexpected - // invalid handles appropriately. - DLOG(ERROR) << "Failed to rewrite one or more handles to broker client."; - return false; - } -#endif - return true; -} - -bool BrokerHost::SendChannel(ScopedPlatformHandle handle) { - CHECK(handle.is_valid()); - CHECK(channel_); - -#if defined(OS_WIN) - InitData* data; - Channel::MessagePtr message = - CreateBrokerMessage(BrokerMessageType::INIT, 1, 0, &data); - data->pipe_name_length = 0; -#else - Channel::MessagePtr message = - CreateBrokerMessage(BrokerMessageType::INIT, 1, nullptr); -#endif - ScopedPlatformHandleVectorPtr handles; - handles.reset(new PlatformHandleVector(1)); - handles->at(0) = handle.release(); - - // This may legitimately fail on Windows if the client process is in another - // session, e.g., is an elevated process. - if (!PrepareHandlesForClient(handles.get())) - return false; - - message->SetHandles(std::move(handles)); - channel_->Write(std::move(message)); - return true; -} - -#if defined(OS_WIN) - -void BrokerHost::SendNamedChannel(const base::StringPiece16& pipe_name) { - InitData* data; - base::char16* name_data; - Channel::MessagePtr message = CreateBrokerMessage( - BrokerMessageType::INIT, 0, sizeof(*name_data) * pipe_name.length(), - &data, reinterpret_cast(&name_data)); - data->pipe_name_length = static_cast(pipe_name.length()); - std::copy(pipe_name.begin(), pipe_name.end(), name_data); - channel_->Write(std::move(message)); -} - -#endif // defined(OS_WIN) - -void BrokerHost::OnBufferRequest(uint32_t num_bytes) { - scoped_refptr read_only_buffer; - scoped_refptr buffer = - PlatformSharedBuffer::Create(num_bytes); - if (buffer) - read_only_buffer = buffer->CreateReadOnlyDuplicate(); - if (!read_only_buffer) - buffer = nullptr; - - Channel::MessagePtr message = CreateBrokerMessage( - BrokerMessageType::BUFFER_RESPONSE, buffer ? 2 : 0, nullptr); - if (buffer) { - ScopedPlatformHandleVectorPtr handles; - handles.reset(new PlatformHandleVector(2)); - handles->at(0) = buffer->PassPlatformHandle().release(); - handles->at(1) = read_only_buffer->PassPlatformHandle().release(); - PrepareHandlesForClient(handles.get()); - message->SetHandles(std::move(handles)); - } - - channel_->Write(std::move(message)); -} - -void BrokerHost::OnChannelMessage(const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) { - if (payload_size < sizeof(BrokerMessageHeader)) - return; - - const BrokerMessageHeader* header = - static_cast(payload); - switch (header->type) { - case BrokerMessageType::BUFFER_REQUEST: - if (payload_size == - sizeof(BrokerMessageHeader) + sizeof(BufferRequestData)) { - const BufferRequestData* request = - reinterpret_cast(header + 1); - OnBufferRequest(request->size); - } - break; - - default: - LOG(ERROR) << "Unexpected broker message type: " << header->type; - break; - } -} - -void BrokerHost::OnChannelError() { delete this; } - -void BrokerHost::WillDestroyCurrentMessageLoop() { delete this; } - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/broker_host.h b/mojo/edk/system/broker_host.h deleted file mode 100644 index a7995d2..0000000 --- a/mojo/edk/system/broker_host.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_BROKER_HOST_H_ -#define MOJO_EDK_SYSTEM_BROKER_HOST_H_ - -#include - -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/process/process_handle.h" -#include "base/strings/string_piece.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/channel.h" - -namespace mojo { -namespace edk { - -// The BrokerHost is a channel to the child process, which services synchronous -// IPCs. -class BrokerHost : public Channel::Delegate, - public base::MessageLoop::DestructionObserver { - public: - BrokerHost(base::ProcessHandle client_process, ScopedPlatformHandle handle); - - // Send |handle| to the child, to be used to establish a NodeChannel to us. - bool SendChannel(ScopedPlatformHandle handle); - -#if defined(OS_WIN) - // Sends a named channel to the child. Like above, but for named pipes. - void SendNamedChannel(const base::StringPiece16& pipe_name); -#endif - - private: - ~BrokerHost() override; - - bool PrepareHandlesForClient(PlatformHandleVector* handles); - - // Channel::Delegate: - void OnChannelMessage(const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) override; - void OnChannelError() override; - - // base::MessageLoop::DestructionObserver: - void WillDestroyCurrentMessageLoop() override; - - void OnBufferRequest(uint32_t num_bytes); - -#if defined(OS_WIN) - base::ProcessHandle client_process_; -#endif - - scoped_refptr channel_; - - DISALLOW_COPY_AND_ASSIGN(BrokerHost); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_BROKER_HOST_H_ diff --git a/mojo/edk/system/broker_messages.h b/mojo/edk/system/broker_messages.h deleted file mode 100644 index 0f0dd9d..0000000 --- a/mojo/edk/system/broker_messages.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_BROKER_MESSAGES_H_ -#define MOJO_EDK_SYSTEM_BROKER_MESSAGES_H_ - -#include "mojo/edk/system/channel.h" - -namespace mojo { -namespace edk { - -#pragma pack(push, 1) - -enum BrokerMessageType : uint32_t { - INIT, - BUFFER_REQUEST, - BUFFER_RESPONSE, -}; - -struct BrokerMessageHeader { - BrokerMessageType type; - uint32_t padding; -}; - -static_assert(IsAlignedForChannelMessage(sizeof(BrokerMessageHeader)), - "Invalid header size."); - -struct BufferRequestData { - uint32_t size; -}; - -#if defined(OS_WIN) -struct InitData { - // NOTE: InitData in the payload is followed by string16 data with exactly - // |pipe_name_length| wide characters (i.e., |pipe_name_length|*2 bytes.) - // This applies to Windows only. - uint32_t pipe_name_length; -}; -#endif - -#pragma pack(pop) - -template -inline Channel::MessagePtr CreateBrokerMessage( - BrokerMessageType type, - size_t num_handles, - size_t extra_data_size, - T** out_message_data, - void** out_extra_data = nullptr) { - const size_t message_size = sizeof(BrokerMessageHeader) + - sizeof(**out_message_data) + extra_data_size; - Channel::MessagePtr message(new Channel::Message(message_size, num_handles)); - BrokerMessageHeader* header = - reinterpret_cast(message->mutable_payload()); - header->type = type; - header->padding = 0; - *out_message_data = reinterpret_cast(header + 1); - if (out_extra_data) - *out_extra_data = *out_message_data + 1; - return message; -} - -inline Channel::MessagePtr CreateBrokerMessage( - BrokerMessageType type, - size_t num_handles, - std::nullptr_t** dummy_out_data) { - Channel::MessagePtr message( - new Channel::Message(sizeof(BrokerMessageHeader), num_handles)); - BrokerMessageHeader* header = - reinterpret_cast(message->mutable_payload()); - header->type = type; - header->padding = 0; - return message; -} - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_BROKER_MESSAGES_H_ diff --git a/mojo/edk/system/broker_posix.cc b/mojo/edk/system/broker_posix.cc deleted file mode 100644 index 8742f70..0000000 --- a/mojo/edk/system/broker_posix.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/broker.h" - -#include -#include - -#include - -#include "base/logging.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/embedder/platform_channel_utils_posix.h" -#include "mojo/edk/embedder/platform_handle_utils.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/broker_messages.h" -#include "mojo/edk/system/channel.h" - -namespace mojo { -namespace edk { - -namespace { - -bool WaitForBrokerMessage(PlatformHandle platform_handle, - BrokerMessageType expected_type, - size_t expected_num_handles, - std::deque* incoming_handles) { - Channel::MessagePtr message( - new Channel::Message(sizeof(BrokerMessageHeader), expected_num_handles)); - std::deque incoming_platform_handles; - ssize_t read_result = PlatformChannelRecvmsg( - platform_handle, const_cast(message->data()), - message->data_num_bytes(), &incoming_platform_handles, true /* block */); - bool error = false; - if (read_result < 0) { - PLOG(ERROR) << "Recvmsg error"; - error = true; - } else if (static_cast(read_result) != message->data_num_bytes()) { - LOG(ERROR) << "Invalid node channel message"; - error = true; - } else if (incoming_platform_handles.size() != expected_num_handles) { - LOG(ERROR) << "Received unexpected number of handles"; - error = true; - } - - if (!error) { - const BrokerMessageHeader* header = - reinterpret_cast(message->payload()); - if (header->type != expected_type) { - LOG(ERROR) << "Unexpected message"; - error = true; - } - } - - if (error) { - CloseAllPlatformHandles(&incoming_platform_handles); - } else { - if (incoming_handles) - incoming_handles->swap(incoming_platform_handles); - } - return !error; -} - -} // namespace - -Broker::Broker(ScopedPlatformHandle platform_handle) - : sync_channel_(std::move(platform_handle)) { - CHECK(sync_channel_.is_valid()); - - // Mark the channel as blocking. - int flags = fcntl(sync_channel_.get().handle, F_GETFL); - PCHECK(flags != -1); - flags = fcntl(sync_channel_.get().handle, F_SETFL, flags & ~O_NONBLOCK); - PCHECK(flags != -1); - - // Wait for the first message, which should contain a handle. - std::deque incoming_platform_handles; - if (WaitForBrokerMessage(sync_channel_.get(), BrokerMessageType::INIT, 1, - &incoming_platform_handles)) { - parent_channel_ = ScopedPlatformHandle(incoming_platform_handles.front()); - } -} - -Broker::~Broker() = default; - -ScopedPlatformHandle Broker::GetParentPlatformHandle() { - return std::move(parent_channel_); -} - -scoped_refptr Broker::GetSharedBuffer(size_t num_bytes) { - base::AutoLock lock(lock_); - - BufferRequestData* buffer_request; - Channel::MessagePtr out_message = CreateBrokerMessage( - BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request); - buffer_request->size = num_bytes; - ssize_t write_result = PlatformChannelWrite( - sync_channel_.get(), out_message->data(), out_message->data_num_bytes()); - if (write_result < 0) { - PLOG(ERROR) << "Error sending sync broker message"; - return nullptr; - } else if (static_cast(write_result) != - out_message->data_num_bytes()) { - LOG(ERROR) << "Error sending complete broker message"; - return nullptr; - } - - std::deque incoming_platform_handles; - if (WaitForBrokerMessage(sync_channel_.get(), - BrokerMessageType::BUFFER_RESPONSE, 2, - &incoming_platform_handles)) { - ScopedPlatformHandle rw_handle(incoming_platform_handles.front()); - incoming_platform_handles.pop_front(); - ScopedPlatformHandle ro_handle(incoming_platform_handles.front()); - return PlatformSharedBuffer::CreateFromPlatformHandlePair( - num_bytes, std::move(rw_handle), std::move(ro_handle)); - } - - return nullptr; -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/broker_win.cc b/mojo/edk/system/broker_win.cc deleted file mode 100644 index 063282c..0000000 --- a/mojo/edk/system/broker_win.cc +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include -#include - -#include "base/debug/alias.h" -#include "base/numerics/safe_conversions.h" -#include "base/strings/string_piece.h" -#include "mojo/edk/embedder/named_platform_handle.h" -#include "mojo/edk/embedder/named_platform_handle_utils.h" -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/broker.h" -#include "mojo/edk/system/broker_messages.h" -#include "mojo/edk/system/channel.h" - -namespace mojo { -namespace edk { - -namespace { - -// 256 bytes should be enough for anyone! -const size_t kMaxBrokerMessageSize = 256; - -bool TakeHandlesFromBrokerMessage(Channel::Message* message, - size_t num_handles, - ScopedPlatformHandle* out_handles) { - if (message->num_handles() != num_handles) { - DLOG(ERROR) << "Received unexpected number of handles in broker message"; - return false; - } - - ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); - DCHECK(handles); - DCHECK_EQ(handles->size(), num_handles); - DCHECK(out_handles); - - for (size_t i = 0; i < num_handles; ++i) - out_handles[i] = ScopedPlatformHandle((*handles)[i]); - handles->clear(); - return true; -} - -Channel::MessagePtr WaitForBrokerMessage(PlatformHandle platform_handle, - BrokerMessageType expected_type) { - char buffer[kMaxBrokerMessageSize]; - DWORD bytes_read = 0; - BOOL result = ::ReadFile(platform_handle.handle, buffer, - kMaxBrokerMessageSize, &bytes_read, nullptr); - if (!result) { - // The pipe may be broken if the browser side has been closed, e.g. during - // browser shutdown. In that case the ReadFile call will fail and we - // shouldn't continue waiting. - PLOG(ERROR) << "Error reading broker pipe"; - return nullptr; - } - - Channel::MessagePtr message = - Channel::Message::Deserialize(buffer, static_cast(bytes_read)); - if (!message || message->payload_size() < sizeof(BrokerMessageHeader)) { - LOG(ERROR) << "Invalid broker message"; - - base::debug::Alias(&buffer[0]); - base::debug::Alias(&bytes_read); - base::debug::Alias(message.get()); - CHECK(false); - return nullptr; - } - - const BrokerMessageHeader* header = - reinterpret_cast(message->payload()); - if (header->type != expected_type) { - LOG(ERROR) << "Unexpected broker message type"; - - base::debug::Alias(&buffer[0]); - base::debug::Alias(&bytes_read); - base::debug::Alias(message.get()); - CHECK(false); - return nullptr; - } - - return message; -} - -} // namespace - -Broker::Broker(ScopedPlatformHandle handle) : sync_channel_(std::move(handle)) { - CHECK(sync_channel_.is_valid()); - Channel::MessagePtr message = - WaitForBrokerMessage(sync_channel_.get(), BrokerMessageType::INIT); - - // If we fail to read a message (broken pipe), just return early. The parent - // handle will be null and callers must handle this gracefully. - if (!message) - return; - - if (!TakeHandlesFromBrokerMessage(message.get(), 1, &parent_channel_)) { - // If the message has no handles, we expect it to carry pipe name instead. - const BrokerMessageHeader* header = - static_cast(message->payload()); - CHECK_GE(message->payload_size(), - sizeof(BrokerMessageHeader) + sizeof(InitData)); - const InitData* data = reinterpret_cast(header + 1); - CHECK_EQ(message->payload_size(), - sizeof(BrokerMessageHeader) + sizeof(InitData) + - data->pipe_name_length * sizeof(base::char16)); - const base::char16* name_data = - reinterpret_cast(data + 1); - CHECK(data->pipe_name_length); - parent_channel_ = CreateClientHandle(NamedPlatformHandle( - base::StringPiece16(name_data, data->pipe_name_length))); - } -} - -Broker::~Broker() {} - -ScopedPlatformHandle Broker::GetParentPlatformHandle() { - return std::move(parent_channel_); -} - -scoped_refptr Broker::GetSharedBuffer(size_t num_bytes) { - base::AutoLock lock(lock_); - BufferRequestData* buffer_request; - Channel::MessagePtr out_message = CreateBrokerMessage( - BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request); - buffer_request->size = base::checked_cast(num_bytes); - DWORD bytes_written = 0; - BOOL result = ::WriteFile(sync_channel_.get().handle, out_message->data(), - static_cast(out_message->data_num_bytes()), - &bytes_written, nullptr); - if (!result || - static_cast(bytes_written) != out_message->data_num_bytes()) { - LOG(ERROR) << "Error sending sync broker message"; - return nullptr; - } - - ScopedPlatformHandle handles[2]; - Channel::MessagePtr response = WaitForBrokerMessage( - sync_channel_.get(), BrokerMessageType::BUFFER_RESPONSE); - if (response && - TakeHandlesFromBrokerMessage(response.get(), 2, &handles[0])) { - return PlatformSharedBuffer::CreateFromPlatformHandlePair( - num_bytes, std::move(handles[0]), std::move(handles[1])); - } - - return nullptr; -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc deleted file mode 100644 index 8a44d36..0000000 --- a/mojo/edk/system/channel.cc +++ /dev/null @@ -1,683 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/channel.h" - -#include -#include - -#include -#include -#include - -#include "base/macros.h" -#include "base/memory/aligned_memory.h" -#include "base/process/process_handle.h" -#include "mojo/edk/embedder/platform_handle.h" - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include "base/mac/mach_logging.h" -#elif defined(OS_WIN) -#include "base/win/win_util.h" -#endif - -namespace mojo { -namespace edk { - -namespace { - -static_assert( - IsAlignedForChannelMessage(sizeof(Channel::Message::LegacyHeader)), - "Invalid LegacyHeader size."); - -static_assert(IsAlignedForChannelMessage(sizeof(Channel::Message::Header)), - "Invalid Header size."); - -static_assert(sizeof(Channel::Message::LegacyHeader) == 8, - "LegacyHeader must be 8 bytes on ChromeOS and Android"); - -static_assert(offsetof(Channel::Message::LegacyHeader, num_bytes) == - offsetof(Channel::Message::Header, num_bytes), - "num_bytes should be at the same offset in both Header structs."); -static_assert(offsetof(Channel::Message::LegacyHeader, message_type) == - offsetof(Channel::Message::Header, message_type), - "message_type should be at the same offset in both Header " - "structs."); - -} // namespace - -const size_t kReadBufferSize = 4096; -const size_t kMaxUnusedReadBufferCapacity = 4096; -const size_t kMaxChannelMessageSize = 256 * 1024 * 1024; -const size_t kMaxAttachedHandles = 128; - -Channel::Message::Message(size_t payload_size, size_t max_handles) -#if defined(MOJO_EDK_LEGACY_PROTOCOL) - : Message(payload_size, max_handles, MessageType::NORMAL_LEGACY) { -} -#else - : Message(payload_size, max_handles, MessageType::NORMAL) { -} -#endif - -Channel::Message::Message(size_t payload_size, - size_t max_handles, - MessageType message_type) - : max_handles_(max_handles) { - DCHECK_LE(max_handles_, kMaxAttachedHandles); - - const bool is_legacy_message = (message_type == MessageType::NORMAL_LEGACY); - size_t extra_header_size = 0; -#if defined(OS_WIN) - // On Windows we serialize HANDLEs into the extra header space. - extra_header_size = max_handles_ * sizeof(HandleEntry); -#elif defined(OS_MACOSX) && !defined(OS_IOS) - // On OSX, some of the platform handles may be mach ports, which are - // serialised into the message buffer. Since there could be a mix of fds and - // mach ports, we store the mach ports as an pair (of uint32_t), - // so that the original ordering of handles can be re-created. - if (max_handles) { - extra_header_size = - sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry)); - } -#endif - // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. - if (!IsAlignedForChannelMessage(extra_header_size)) { - extra_header_size += kChannelMessageAlignment - - (extra_header_size % kChannelMessageAlignment); - } - DCHECK(IsAlignedForChannelMessage(extra_header_size)); - const size_t header_size = - is_legacy_message ? sizeof(LegacyHeader) : sizeof(Header); - DCHECK(extra_header_size == 0 || !is_legacy_message); - - size_ = header_size + extra_header_size + payload_size; - data_ = static_cast(base::AlignedAlloc(size_, - kChannelMessageAlignment)); - // Only zero out the header and not the payload. Since the payload is going to - // be memcpy'd, zeroing the payload is unnecessary work and a significant - // performance issue when dealing with large messages. Any sanitizer errors - // complaining about an uninitialized read in the payload area should be - // treated as an error and fixed. - memset(data_, 0, header_size + extra_header_size); - - DCHECK_LE(size_, std::numeric_limits::max()); - legacy_header()->num_bytes = static_cast(size_); - - DCHECK_LE(header_size + extra_header_size, - std::numeric_limits::max()); - legacy_header()->message_type = message_type; - - if (is_legacy_message) { - legacy_header()->num_handles = static_cast(max_handles); - } else { - header()->num_header_bytes = - static_cast(header_size + extra_header_size); - } - - if (max_handles_ > 0) { -#if defined(OS_WIN) - handles_ = reinterpret_cast(mutable_extra_header()); - // Initialize all handles to invalid values. - for (size_t i = 0; i < max_handles_; ++i) - handles_[i].handle = base::win::HandleToUint32(INVALID_HANDLE_VALUE); -#elif defined(OS_MACOSX) && !defined(OS_IOS) - mach_ports_header_ = - reinterpret_cast(mutable_extra_header()); - mach_ports_header_->num_ports = 0; - // Initialize all handles to invalid values. - for (size_t i = 0; i < max_handles_; ++i) { - mach_ports_header_->entries[i] = - {0, static_cast(MACH_PORT_NULL)}; - } -#endif - } -} - -Channel::Message::~Message() { - base::AlignedFree(data_); -} - -// static -Channel::MessagePtr Channel::Message::Deserialize(const void* data, - size_t data_num_bytes) { - if (data_num_bytes < sizeof(LegacyHeader)) - return nullptr; - - const LegacyHeader* legacy_header = - reinterpret_cast(data); - if (legacy_header->num_bytes != data_num_bytes) { - DLOG(ERROR) << "Decoding invalid message: " << legacy_header->num_bytes - << " != " << data_num_bytes; - return nullptr; - } - - const Header* header = nullptr; - if (legacy_header->message_type == MessageType::NORMAL) - header = reinterpret_cast(data); - - uint32_t extra_header_size = 0; - size_t payload_size = 0; - const char* payload = nullptr; - if (!header) { - payload_size = data_num_bytes - sizeof(LegacyHeader); - payload = static_cast(data) + sizeof(LegacyHeader); - } else { - if (header->num_bytes < header->num_header_bytes || - header->num_header_bytes < sizeof(Header)) { - DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " - << header->num_header_bytes; - return nullptr; - } - extra_header_size = header->num_header_bytes - sizeof(Header); - payload_size = data_num_bytes - header->num_header_bytes; - payload = static_cast(data) + header->num_header_bytes; - } - -#if defined(OS_WIN) - uint32_t max_handles = extra_header_size / sizeof(HandleEntry); -#elif defined(OS_MACOSX) && !defined(OS_IOS) - if (extra_header_size > 0 && - extra_header_size < sizeof(MachPortsExtraHeader)) { - DLOG(ERROR) << "Decoding invalid message: " << extra_header_size << " < " - << sizeof(MachPortsExtraHeader); - return nullptr; - } - uint32_t max_handles = - extra_header_size == 0 - ? 0 - : (extra_header_size - sizeof(MachPortsExtraHeader)) / - sizeof(MachPortsEntry); -#else - const uint32_t max_handles = 0; -#endif // defined(OS_WIN) - - const uint16_t num_handles = - header ? header->num_handles : legacy_header->num_handles; - if (num_handles > max_handles || max_handles > kMaxAttachedHandles) { - DLOG(ERROR) << "Decoding invalid message: " << num_handles << " > " - << max_handles; - return nullptr; - } - - MessagePtr message( - new Message(payload_size, max_handles, legacy_header->message_type)); - DCHECK_EQ(message->data_num_bytes(), data_num_bytes); - - // Copy all payload bytes. - if (payload_size) - memcpy(message->mutable_payload(), payload, payload_size); - - if (header) { - DCHECK_EQ(message->extra_header_size(), extra_header_size); - DCHECK_EQ(message->header()->num_header_bytes, header->num_header_bytes); - - if (message->extra_header_size()) { - // Copy extra header bytes. - memcpy(message->mutable_extra_header(), - static_cast(data) + sizeof(Header), - message->extra_header_size()); - } - message->header()->num_handles = header->num_handles; - } else { - message->legacy_header()->num_handles = legacy_header->num_handles; - } - -#if defined(OS_WIN) - ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector(num_handles)); - for (size_t i = 0; i < num_handles; i++) { - (*handles)[i].handle = - base::win::Uint32ToHandle(message->handles_[i].handle); - } - message->SetHandles(std::move(handles)); -#endif - - return message; -} - -const void* Channel::Message::extra_header() const { - DCHECK(!is_legacy_message()); - return data_ + sizeof(Header); -} - -void* Channel::Message::mutable_extra_header() { - DCHECK(!is_legacy_message()); - return data_ + sizeof(Header); -} - -size_t Channel::Message::extra_header_size() const { - return header()->num_header_bytes - sizeof(Header); -} - -void* Channel::Message::mutable_payload() { - if (is_legacy_message()) - return static_cast(legacy_header() + 1); - return data_ + header()->num_header_bytes; -} - -const void* Channel::Message::payload() const { - if (is_legacy_message()) - return static_cast(legacy_header() + 1); - return data_ + header()->num_header_bytes; -} - -size_t Channel::Message::payload_size() const { - if (is_legacy_message()) - return legacy_header()->num_bytes - sizeof(LegacyHeader); - return size_ - header()->num_header_bytes; -} - -size_t Channel::Message::num_handles() const { - return is_legacy_message() ? legacy_header()->num_handles - : header()->num_handles; -} - -bool Channel::Message::has_handles() const { - return (is_legacy_message() ? legacy_header()->num_handles - : header()->num_handles) > 0; -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -bool Channel::Message::has_mach_ports() const { - if (!has_handles()) - return false; - - for (const auto& handle : (*handle_vector_)) { - if (handle.type == PlatformHandle::Type::MACH || - handle.type == PlatformHandle::Type::MACH_NAME) { - return true; - } - } - return false; -} -#endif - -bool Channel::Message::is_legacy_message() const { - return legacy_header()->message_type == MessageType::NORMAL_LEGACY; -} - -Channel::Message::LegacyHeader* Channel::Message::legacy_header() const { - return reinterpret_cast(data_); -} - -Channel::Message::Header* Channel::Message::header() const { - DCHECK(!is_legacy_message()); - return reinterpret_cast(data_); -} - -void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { - if (is_legacy_message()) { - // Old semantics for ChromeOS and Android - if (legacy_header()->num_handles == 0) { - CHECK(!new_handles || new_handles->size() == 0); - return; - } - CHECK(new_handles && new_handles->size() == legacy_header()->num_handles); - std::swap(handle_vector_, new_handles); - return; - } - - if (max_handles_ == 0) { - CHECK(!new_handles || new_handles->size() == 0); - return; - } - - CHECK(new_handles && new_handles->size() <= max_handles_); - header()->num_handles = static_cast(new_handles->size()); - std::swap(handle_vector_, new_handles); -#if defined(OS_WIN) - memset(handles_, 0, extra_header_size()); - for (size_t i = 0; i < handle_vector_->size(); i++) - handles_[i].handle = base::win::HandleToUint32((*handle_vector_)[i].handle); -#endif // defined(OS_WIN) - -#if defined(OS_MACOSX) && !defined(OS_IOS) - size_t mach_port_index = 0; - if (mach_ports_header_) { - for (size_t i = 0; i < max_handles_; ++i) { - mach_ports_header_->entries[i] = - {0, static_cast(MACH_PORT_NULL)}; - } - for (size_t i = 0; i < handle_vector_->size(); i++) { - if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || - (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) { - mach_port_t port = (*handle_vector_)[i].port; - mach_ports_header_->entries[mach_port_index].index = i; - mach_ports_header_->entries[mach_port_index].mach_port = port; - mach_port_index++; - } - } - mach_ports_header_->num_ports = static_cast(mach_port_index); - } -#endif -} - -ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { -#if defined(OS_MACOSX) && !defined(OS_IOS) - if (mach_ports_header_) { - for (size_t i = 0; i < max_handles_; ++i) { - mach_ports_header_->entries[i] = - {0, static_cast(MACH_PORT_NULL)}; - } - mach_ports_header_->num_ports = 0; - } -#endif - if (is_legacy_message()) - legacy_header()->num_handles = 0; - else - header()->num_handles = 0; - return std::move(handle_vector_); -} - -ScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() { -#if defined(OS_WIN) - // Not necessary on Windows. - NOTREACHED(); - return nullptr; -#elif defined(OS_MACOSX) && !defined(OS_IOS) - if (handle_vector_) { - for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) { - if (it->type == PlatformHandle::Type::MACH || - it->type == PlatformHandle::Type::MACH_NAME) { - // For Mach port names, we can can just leak them. They're not real - // ports anyways. For real ports, they're leaked because this is a child - // process and the remote process will take ownership. - it = handle_vector_->erase(it); - } else { - ++it; - } - } - } - return std::move(handle_vector_); -#else - return std::move(handle_vector_); -#endif -} - -#if defined(OS_WIN) -// static -bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, - base::ProcessHandle to_process, - PlatformHandleVector* handles) { - bool success = true; - for (size_t i = 0; i < handles->size(); ++i) { - if (!(*handles)[i].is_valid()) { - DLOG(ERROR) << "Refusing to duplicate invalid handle."; - continue; - } - DCHECK_EQ((*handles)[i].owning_process, from_process); - BOOL result = DuplicateHandle( - from_process, (*handles)[i].handle, to_process, - &(*handles)[i].handle, 0, FALSE, - DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); - if (result) { - (*handles)[i].owning_process = to_process; - } else { - success = false; - - // If handle duplication fails, the source handle will already be closed - // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with - // an invalid handle. - (*handles)[i].handle = INVALID_HANDLE_VALUE; - (*handles)[i].owning_process = base::GetCurrentProcessHandle(); - } - } - return success; -} -#endif - -// Helper class for managing a Channel's read buffer allocations. This maintains -// a single contiguous buffer with the layout: -// -// [discarded bytes][occupied bytes][unoccupied bytes] -// -// The Reserve() method ensures that a certain capacity of unoccupied bytes are -// available. It does not claim that capacity and only allocates new capacity -// when strictly necessary. -// -// Claim() marks unoccupied bytes as occupied. -// -// Discard() marks occupied bytes as discarded, signifying that their contents -// can be forgotten or overwritten. -// -// Realign() moves occupied bytes to the front of the buffer so that those -// occupied bytes are properly aligned. -// -// The most common Channel behavior in practice should result in very few -// allocations and copies, as memory is claimed and discarded shortly after -// being reserved, and future reservations will immediately reuse discarded -// memory. -class Channel::ReadBuffer { - public: - ReadBuffer() { - size_ = kReadBufferSize; - data_ = static_cast(base::AlignedAlloc(size_, - kChannelMessageAlignment)); - } - - ~ReadBuffer() { - DCHECK(data_); - base::AlignedFree(data_); - } - - const char* occupied_bytes() const { return data_ + num_discarded_bytes_; } - - size_t num_occupied_bytes() const { - return num_occupied_bytes_ - num_discarded_bytes_; - } - - // Ensures the ReadBuffer has enough contiguous space allocated to hold - // |num_bytes| more bytes; returns the address of the first available byte. - char* Reserve(size_t num_bytes) { - if (num_occupied_bytes_ + num_bytes > size_) { - size_ = std::max(size_ * 2, num_occupied_bytes_ + num_bytes); - void* new_data = base::AlignedAlloc(size_, kChannelMessageAlignment); - memcpy(new_data, data_, num_occupied_bytes_); - base::AlignedFree(data_); - data_ = static_cast(new_data); - } - - return data_ + num_occupied_bytes_; - } - - // Marks the first |num_bytes| unoccupied bytes as occupied. - void Claim(size_t num_bytes) { - DCHECK_LE(num_occupied_bytes_ + num_bytes, size_); - num_occupied_bytes_ += num_bytes; - } - - // Marks the first |num_bytes| occupied bytes as discarded. This may result in - // shrinkage of the internal buffer, and it is not safe to assume the result - // of a previous Reserve() call is still valid after this. - void Discard(size_t num_bytes) { - DCHECK_LE(num_discarded_bytes_ + num_bytes, num_occupied_bytes_); - num_discarded_bytes_ += num_bytes; - - if (num_discarded_bytes_ == num_occupied_bytes_) { - // We can just reuse the buffer from the beginning in this common case. - num_discarded_bytes_ = 0; - num_occupied_bytes_ = 0; - } - - if (num_discarded_bytes_ > kMaxUnusedReadBufferCapacity) { - // In the uncommon case that we have a lot of discarded data at the - // front of the buffer, simply move remaining data to a smaller buffer. - size_t num_preserved_bytes = num_occupied_bytes_ - num_discarded_bytes_; - size_ = std::max(num_preserved_bytes, kReadBufferSize); - char* new_data = static_cast( - base::AlignedAlloc(size_, kChannelMessageAlignment)); - memcpy(new_data, data_ + num_discarded_bytes_, num_preserved_bytes); - base::AlignedFree(data_); - data_ = new_data; - num_discarded_bytes_ = 0; - num_occupied_bytes_ = num_preserved_bytes; - } - - if (num_occupied_bytes_ == 0 && size_ > kMaxUnusedReadBufferCapacity) { - // Opportunistically shrink the read buffer back down to a small size if - // it's grown very large. We only do this if there are no remaining - // unconsumed bytes in the buffer to avoid copies in most the common - // cases. - size_ = kMaxUnusedReadBufferCapacity; - base::AlignedFree(data_); - data_ = static_cast( - base::AlignedAlloc(size_, kChannelMessageAlignment)); - } - } - - void Realign() { - size_t num_bytes = num_occupied_bytes(); - memmove(data_, occupied_bytes(), num_bytes); - num_discarded_bytes_ = 0; - num_occupied_bytes_ = num_bytes; - } - - private: - char* data_ = nullptr; - - // The total size of the allocated buffer. - size_t size_ = 0; - - // The number of discarded bytes at the beginning of the allocated buffer. - size_t num_discarded_bytes_ = 0; - - // The total number of occupied bytes, including discarded bytes. - size_t num_occupied_bytes_ = 0; - - DISALLOW_COPY_AND_ASSIGN(ReadBuffer); -}; - -Channel::Channel(Delegate* delegate) - : delegate_(delegate), read_buffer_(new ReadBuffer) { -} - -Channel::~Channel() { -} - -void Channel::ShutDown() { - delegate_ = nullptr; - ShutDownImpl(); -} - -char* Channel::GetReadBuffer(size_t *buffer_capacity) { - DCHECK(read_buffer_); - size_t required_capacity = *buffer_capacity; - if (!required_capacity) - required_capacity = kReadBufferSize; - - *buffer_capacity = required_capacity; - return read_buffer_->Reserve(required_capacity); -} - -bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) { - bool did_dispatch_message = false; - read_buffer_->Claim(bytes_read); - while (read_buffer_->num_occupied_bytes() >= sizeof(Message::LegacyHeader)) { - // Ensure the occupied data is properly aligned. If it isn't, a SIGBUS could - // happen on architectures that don't allow misaligned words access (i.e. - // anything other than x86). Only re-align when necessary to avoid copies. - if (!IsAlignedForChannelMessage( - reinterpret_cast(read_buffer_->occupied_bytes()))) { - read_buffer_->Realign(); - } - - // We have at least enough data available for a LegacyHeader. - const Message::LegacyHeader* legacy_header = - reinterpret_cast( - read_buffer_->occupied_bytes()); - - if (legacy_header->num_bytes < sizeof(Message::LegacyHeader) || - legacy_header->num_bytes > kMaxChannelMessageSize) { - LOG(ERROR) << "Invalid message size: " << legacy_header->num_bytes; - return false; - } - - if (read_buffer_->num_occupied_bytes() < legacy_header->num_bytes) { - // Not enough data available to read the full message. Hint to the - // implementation that it should try reading the full size of the message. - *next_read_size_hint = - legacy_header->num_bytes - read_buffer_->num_occupied_bytes(); - return true; - } - - const Message::Header* header = nullptr; - if (legacy_header->message_type != Message::MessageType::NORMAL_LEGACY) { - header = reinterpret_cast(legacy_header); - } - - size_t extra_header_size = 0; - const void* extra_header = nullptr; - size_t payload_size = 0; - void* payload = nullptr; - if (header) { - if (header->num_header_bytes < sizeof(Message::Header) || - header->num_header_bytes > header->num_bytes) { - LOG(ERROR) << "Invalid message header size: " - << header->num_header_bytes; - return false; - } - extra_header_size = header->num_header_bytes - sizeof(Message::Header); - extra_header = extra_header_size ? header + 1 : nullptr; - payload_size = header->num_bytes - header->num_header_bytes; - payload = payload_size - ? reinterpret_cast( - const_cast(read_buffer_->occupied_bytes()) + - header->num_header_bytes) - : nullptr; - } else { - payload_size = legacy_header->num_bytes - sizeof(Message::LegacyHeader); - payload = payload_size - ? const_cast(&legacy_header[1]) - : nullptr; - } - - const uint16_t num_handles = - header ? header->num_handles : legacy_header->num_handles; - ScopedPlatformHandleVectorPtr handles; - if (num_handles > 0) { - if (!GetReadPlatformHandles(num_handles, extra_header, extra_header_size, - &handles)) { - return false; - } - - if (!handles) { - // Not enough handles available for this message. - break; - } - } - - // We've got a complete message! Dispatch it and try another. - if (legacy_header->message_type != Message::MessageType::NORMAL_LEGACY && - legacy_header->message_type != Message::MessageType::NORMAL) { - if (!OnControlMessage(legacy_header->message_type, payload, payload_size, - std::move(handles))) { - return false; - } - did_dispatch_message = true; - } else if (delegate_) { - delegate_->OnChannelMessage(payload, payload_size, std::move(handles)); - did_dispatch_message = true; - } - - read_buffer_->Discard(legacy_header->num_bytes); - } - - *next_read_size_hint = did_dispatch_message ? 0 : kReadBufferSize; - return true; -} - -void Channel::OnError() { - if (delegate_) - delegate_->OnChannelError(); -} - -bool Channel::OnControlMessage(Message::MessageType message_type, - const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) { - return false; -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/channel.h b/mojo/edk/system/channel.h deleted file mode 100644 index 33a510c..0000000 --- a/mojo/edk/system/channel.h +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_CHANNEL_H_ -#define MOJO_EDK_SYSTEM_CHANNEL_H_ - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/process/process_handle.h" -#include "base/task_runner.h" -#include "mojo/edk/embedder/connection_params.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" - -namespace mojo { -namespace edk { - -const size_t kChannelMessageAlignment = 8; - -constexpr bool IsAlignedForChannelMessage(size_t n) { - return n % kChannelMessageAlignment == 0; -} - -// Channel provides a thread-safe interface to read and write arbitrary -// delimited messages over an underlying I/O channel, optionally transferring -// one or more platform handles in the process. -class MOJO_SYSTEM_IMPL_EXPORT Channel - : public base::RefCountedThreadSafe { - public: - struct Message; - - using MessagePtr = std::unique_ptr; - - // A message to be written to a channel. - struct MOJO_SYSTEM_IMPL_EXPORT Message { - enum class MessageType : uint16_t { - // An old format normal message, that uses the LegacyHeader. - // Only used on Android and ChromeOS. - // TODO(jcivelli): remove legacy support when Arc++ has updated to Mojo - // with normal versioned messages. crbug.com/695645 - NORMAL_LEGACY = 0, -#if defined(OS_MACOSX) - // A control message containing handles to echo back. - HANDLES_SENT, - // A control message containing handles that can now be closed. - HANDLES_SENT_ACK, -#endif - // A normal message that uses Header and can contain extra header values. - NORMAL, - }; - -#pragma pack(push, 1) - // Old message wire format for ChromeOS and Android, used by NORMAL_LEGACY - // messages. - struct LegacyHeader { - // Message size in bytes, including the header. - uint32_t num_bytes; - - // Number of attached handles. - uint16_t num_handles; - - MessageType message_type; - }; - - // Header used by NORMAL messages. - // To preserve backward compatibility with LegacyHeader, the num_bytes and - // message_type field must be at the same offset as in LegacyHeader. - struct Header { - // Message size in bytes, including the header. - uint32_t num_bytes; - - // Total size of header, including extra header data (i.e. HANDLEs on - // windows). - uint16_t num_header_bytes; - - MessageType message_type; - - // Number of attached handles. May be less than the reserved handle - // storage size in this message on platforms that serialise handles as - // data (i.e. HANDLEs on Windows, Mach ports on OSX). - uint16_t num_handles; - - char padding[6]; - }; - -#if defined(OS_MACOSX) && !defined(OS_IOS) - struct MachPortsEntry { - // Index of Mach port in the original vector of PlatformHandles. - uint16_t index; - - // Mach port name. - uint32_t mach_port; - static_assert(sizeof(mach_port_t) <= sizeof(uint32_t), - "mach_port_t must be no larger than uint32_t"); - }; - static_assert(sizeof(MachPortsEntry) == 6, - "sizeof(MachPortsEntry) must be 6 bytes"); - - // Structure of the extra header field when present on OSX. - struct MachPortsExtraHeader { - // Actual number of Mach ports encoded in the extra header. - uint16_t num_ports; - - // Array of encoded Mach ports. If |num_ports| > 0, |entries[0]| through - // to |entries[num_ports-1]| inclusive are valid. - MachPortsEntry entries[0]; - }; - static_assert(sizeof(MachPortsExtraHeader) == 2, - "sizeof(MachPortsExtraHeader) must be 2 bytes"); -#elif defined(OS_WIN) - struct HandleEntry { - // The windows HANDLE. HANDLEs are guaranteed to fit inside 32-bits. - // See: https://msdn.microsoft.com/en-us/library/aa384203(VS.85).aspx - uint32_t handle; - }; - static_assert(sizeof(HandleEntry) == 4, - "sizeof(HandleEntry) must be 4 bytes"); -#endif -#pragma pack(pop) - - // Allocates and owns a buffer for message data with enough capacity for - // |payload_size| bytes plus a header, plus |max_handles| platform handles. - Message(size_t payload_size, size_t max_handles); - Message(size_t payload_size, size_t max_handles, MessageType message_type); - ~Message(); - - // Constructs a Message from serialized message data. - static MessagePtr Deserialize(const void* data, size_t data_num_bytes); - - const void* data() const { return data_; } - size_t data_num_bytes() const { return size_; } - - const void* extra_header() const; - void* mutable_extra_header(); - size_t extra_header_size() const; - - void* mutable_payload(); - const void* payload() const; - size_t payload_size() const; - - size_t num_handles() const; - bool has_handles() const; -#if defined(OS_MACOSX) && !defined(OS_IOS) - bool has_mach_ports() const; -#endif - - bool is_legacy_message() const; - LegacyHeader* legacy_header() const; - Header* header() const; - - // Note: SetHandles() and TakeHandles() invalidate any previous value of - // handles(). - void SetHandles(ScopedPlatformHandleVectorPtr new_handles); - ScopedPlatformHandleVectorPtr TakeHandles(); - // Version of TakeHandles that returns a vector of platform handles suitable - // for transfer over an underlying OS mechanism. i.e. file descriptors over - // a unix domain socket. Any handle that cannot be transferred this way, - // such as Mach ports, will be removed. - ScopedPlatformHandleVectorPtr TakeHandlesForTransport(); - -#if defined(OS_WIN) - // Prepares the handles in this message for use in a different process. - // Upon calling this the handles should belong to |from_process|; after the - // call they'll belong to |to_process|. The source handles are always - // closed by this call. Returns false iff one or more handles failed - // duplication. - static bool RewriteHandles(base::ProcessHandle from_process, - base::ProcessHandle to_process, - PlatformHandleVector* handles); -#endif - - void SetVersionForTest(uint16_t version_number); - - private: - size_t size_ = 0; - size_t max_handles_ = 0; - char* data_ = nullptr; - - ScopedPlatformHandleVectorPtr handle_vector_; - -#if defined(OS_WIN) - // On Windows, handles are serialised into the extra header section. - HandleEntry* handles_ = nullptr; -#elif defined(OS_MACOSX) && !defined(OS_IOS) - // On OSX, handles are serialised into the extra header section. - MachPortsExtraHeader* mach_ports_header_ = nullptr; -#endif - - DISALLOW_COPY_AND_ASSIGN(Message); - }; - - // Delegate methods are called from the I/O task runner with which the Channel - // was created (see Channel::Create). - class Delegate { - public: - virtual ~Delegate() {} - - // Notify of a received message. |payload| is not owned and must not be - // retained; it will be null if |payload_size| is 0. |handles| are - // transferred to the callee. - virtual void OnChannelMessage(const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) = 0; - - // Notify that an error has occured and the Channel will cease operation. - virtual void OnChannelError() = 0; - }; - - // Creates a new Channel around a |platform_handle|, taking ownership of the - // handle. All I/O on the handle will be performed on |io_task_runner|. - // Note that ShutDown() MUST be called on the Channel some time before - // |delegate| is destroyed. - static scoped_refptr Create( - Delegate* delegate, - ConnectionParams connection_params, - scoped_refptr io_task_runner); - - // Request that the channel be shut down. This should always be called before - // releasing the last reference to a Channel to ensure that it's cleaned up - // on its I/O task runner's thread. - // - // Delegate methods will no longer be invoked after this call. - void ShutDown(); - - // Begin processing I/O events. Delegate methods must only be invoked after - // this call. - virtual void Start() = 0; - - // Stop processing I/O events. - virtual void ShutDownImpl() = 0; - - // Queues an outgoing message on the Channel. This message will either - // eventually be written or will fail to write and trigger - // Delegate::OnChannelError. - virtual void Write(MessagePtr message) = 0; - - // Causes the platform handle to leak when this channel is shut down instead - // of closing it. - virtual void LeakHandle() = 0; - - protected: - explicit Channel(Delegate* delegate); - virtual ~Channel(); - - // Called by the implementation when it wants somewhere to stick data. - // |*buffer_capacity| may be set by the caller to indicate the desired buffer - // size. If 0, a sane default size will be used instead. - // - // Returns the address of a buffer which can be written to, and indicates its - // actual capacity in |*buffer_capacity|. - char* GetReadBuffer(size_t* buffer_capacity); - - // Called by the implementation when new data is available in the read - // buffer. Returns false to indicate an error. Upon success, - // |*next_read_size_hint| will be set to a recommended size for the next - // read done by the implementation. - bool OnReadComplete(size_t bytes_read, size_t* next_read_size_hint); - - // Called by the implementation when something goes horribly wrong. It is NOT - // OK to call this synchronously from any public interface methods. - void OnError(); - - // Retrieves the set of platform handles read for a given message. - // |extra_header| and |extra_header_size| correspond to the extra header data. - // Depending on the Channel implementation, this body may encode platform - // handles, or handles may be stored and managed elsewhere by the - // implementation. - // - // Returns |false| on unrecoverable error (i.e. the Channel should be closed). - // Returns |true| otherwise. Note that it is possible on some platforms for an - // insufficient number of handles to be available when this call is made, but - // this is not necessarily an error condition. In such cases this returns - // |true| but |*handles| will also be reset to null. - virtual bool GetReadPlatformHandles( - size_t num_handles, - const void* extra_header, - size_t extra_header_size, - ScopedPlatformHandleVectorPtr* handles) = 0; - - // Handles a received control message. Returns |true| if the message is - // accepted, or |false| otherwise. - virtual bool OnControlMessage(Message::MessageType message_type, - const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles); - - private: - friend class base::RefCountedThreadSafe; - - class ReadBuffer; - - Delegate* delegate_; - const std::unique_ptr read_buffer_; - - DISALLOW_COPY_AND_ASSIGN(Channel); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_CHANNEL_H_ diff --git a/mojo/edk/system/channel_posix.cc b/mojo/edk/system/channel_posix.cc deleted file mode 100644 index 8b4ca7f..0000000 --- a/mojo/edk/system/channel_posix.cc +++ /dev/null @@ -1,572 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/channel.h" - -#include -#include - -#include -#include -#include -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/lock.h" -#include "base/task_runner.h" -#include "mojo/edk/embedder/platform_channel_utils_posix.h" -#include "mojo/edk/embedder/platform_handle_vector.h" - -#if !defined(OS_NACL) -#include -#endif - -namespace mojo { -namespace edk { - -namespace { - -const size_t kMaxBatchReadCapacity = 256 * 1024; - -// A view over a Channel::Message object. The write queue uses these since -// large messages may need to be sent in chunks. -class MessageView { - public: - // Owns |message|. |offset| indexes the first unsent byte in the message. - MessageView(Channel::MessagePtr message, size_t offset) - : message_(std::move(message)), - offset_(offset), - handles_(message_->TakeHandlesForTransport()) { - DCHECK_GT(message_->data_num_bytes(), offset_); - } - - MessageView(MessageView&& other) { *this = std::move(other); } - - MessageView& operator=(MessageView&& other) { - message_ = std::move(other.message_); - offset_ = other.offset_; - handles_ = std::move(other.handles_); - return *this; - } - - ~MessageView() {} - - const void* data() const { - return static_cast(message_->data()) + offset_; - } - - size_t data_num_bytes() const { return message_->data_num_bytes() - offset_; } - - size_t data_offset() const { return offset_; } - void advance_data_offset(size_t num_bytes) { - DCHECK_GT(message_->data_num_bytes(), offset_ + num_bytes); - offset_ += num_bytes; - } - - ScopedPlatformHandleVectorPtr TakeHandles() { return std::move(handles_); } - Channel::MessagePtr TakeMessage() { return std::move(message_); } - - void SetHandles(ScopedPlatformHandleVectorPtr handles) { - handles_ = std::move(handles); - } - - private: - Channel::MessagePtr message_; - size_t offset_; - ScopedPlatformHandleVectorPtr handles_; - - DISALLOW_COPY_AND_ASSIGN(MessageView); -}; - -class ChannelPosix : public Channel, - public base::MessageLoop::DestructionObserver, - public base::MessageLoopForIO::Watcher { - public: - ChannelPosix(Delegate* delegate, - ConnectionParams connection_params, - scoped_refptr io_task_runner) - : Channel(delegate), - self_(this), - handle_(connection_params.TakeChannelHandle()), - io_task_runner_(io_task_runner) -#if defined(OS_MACOSX) - , - handles_to_close_(new PlatformHandleVector) -#endif - { - CHECK(handle_.is_valid()); - } - - void Start() override { - if (io_task_runner_->RunsTasksOnCurrentThread()) { - StartOnIOThread(); - } else { - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelPosix::StartOnIOThread, this)); - } - } - - void ShutDownImpl() override { - // Always shut down asynchronously when called through the public interface. - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelPosix::ShutDownOnIOThread, this)); - } - - void Write(MessagePtr message) override { - bool write_error = false; - { - base::AutoLock lock(write_lock_); - if (reject_writes_) - return; - if (outgoing_messages_.empty()) { - if (!WriteNoLock(MessageView(std::move(message), 0))) - reject_writes_ = write_error = true; - } else { - outgoing_messages_.emplace_back(std::move(message), 0); - } - } - if (write_error) { - // Do not synchronously invoke OnError(). Write() may have been called by - // the delegate and we don't want to re-enter it. - io_task_runner_->PostTask(FROM_HERE, - base::Bind(&ChannelPosix::OnError, this)); - } - } - - void LeakHandle() override { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - leak_handle_ = true; - } - - bool GetReadPlatformHandles( - size_t num_handles, - const void* extra_header, - size_t extra_header_size, - ScopedPlatformHandleVectorPtr* handles) override { - if (num_handles > std::numeric_limits::max()) - return false; -#if defined(OS_MACOSX) && !defined(OS_IOS) - // On OSX, we can have mach ports which are located in the extra header - // section. - using MachPortsEntry = Channel::Message::MachPortsEntry; - using MachPortsExtraHeader = Channel::Message::MachPortsExtraHeader; - CHECK(extra_header_size >= - sizeof(MachPortsExtraHeader) + num_handles * sizeof(MachPortsEntry)); - const MachPortsExtraHeader* mach_ports_header = - reinterpret_cast(extra_header); - size_t num_mach_ports = mach_ports_header->num_ports; - CHECK(num_mach_ports <= num_handles); - if (incoming_platform_handles_.size() + num_mach_ports < num_handles) { - handles->reset(); - return true; - } - - handles->reset(new PlatformHandleVector(num_handles)); - const MachPortsEntry* mach_ports = mach_ports_header->entries; - for (size_t i = 0, mach_port_index = 0; i < num_handles; ++i) { - if (mach_port_index < num_mach_ports && - mach_ports[mach_port_index].index == i) { - (*handles)->at(i) = PlatformHandle( - static_cast(mach_ports[mach_port_index].mach_port)); - CHECK((*handles)->at(i).type == PlatformHandle::Type::MACH); - // These are actually just Mach port names until they're resolved from - // the remote process. - (*handles)->at(i).type = PlatformHandle::Type::MACH_NAME; - mach_port_index++; - } else { - CHECK(!incoming_platform_handles_.empty()); - (*handles)->at(i) = incoming_platform_handles_.front(); - incoming_platform_handles_.pop_front(); - } - } -#else - if (incoming_platform_handles_.size() < num_handles) { - handles->reset(); - return true; - } - - handles->reset(new PlatformHandleVector(num_handles)); - for (size_t i = 0; i < num_handles; ++i) { - (*handles)->at(i) = incoming_platform_handles_.front(); - incoming_platform_handles_.pop_front(); - } -#endif - - return true; - } - - private: - ~ChannelPosix() override { - DCHECK(!read_watcher_); - DCHECK(!write_watcher_); - for (auto handle : incoming_platform_handles_) - handle.CloseIfNecessary(); - } - - void StartOnIOThread() { - DCHECK(!read_watcher_); - DCHECK(!write_watcher_); - read_watcher_.reset( - new base::MessageLoopForIO::FileDescriptorWatcher(FROM_HERE)); - base::MessageLoop::current()->AddDestructionObserver(this); - if (handle_.get().needs_connection) { - base::MessageLoopForIO::current()->WatchFileDescriptor( - handle_.get().handle, false /* persistent */, - base::MessageLoopForIO::WATCH_READ, read_watcher_.get(), this); - } else { - write_watcher_.reset( - new base::MessageLoopForIO::FileDescriptorWatcher(FROM_HERE)); - base::MessageLoopForIO::current()->WatchFileDescriptor( - handle_.get().handle, true /* persistent */, - base::MessageLoopForIO::WATCH_READ, read_watcher_.get(), this); - base::AutoLock lock(write_lock_); - FlushOutgoingMessagesNoLock(); - } - } - - void WaitForWriteOnIOThread() { - base::AutoLock lock(write_lock_); - WaitForWriteOnIOThreadNoLock(); - } - - void WaitForWriteOnIOThreadNoLock() { - if (pending_write_) - return; - if (!write_watcher_) - return; - if (io_task_runner_->RunsTasksOnCurrentThread()) { - pending_write_ = true; - base::MessageLoopForIO::current()->WatchFileDescriptor( - handle_.get().handle, false /* persistent */, - base::MessageLoopForIO::WATCH_WRITE, write_watcher_.get(), this); - } else { - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelPosix::WaitForWriteOnIOThread, this)); - } - } - - void ShutDownOnIOThread() { - base::MessageLoop::current()->RemoveDestructionObserver(this); - - read_watcher_.reset(); - write_watcher_.reset(); - if (leak_handle_) - ignore_result(handle_.release()); - handle_.reset(); -#if defined(OS_MACOSX) - handles_to_close_.reset(); -#endif - - // May destroy the |this| if it was the last reference. - self_ = nullptr; - } - - // base::MessageLoop::DestructionObserver: - void WillDestroyCurrentMessageLoop() override { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - if (self_) - ShutDownOnIOThread(); - } - - // base::MessageLoopForIO::Watcher: - void OnFileCanReadWithoutBlocking(int fd) override { - CHECK_EQ(fd, handle_.get().handle); - if (handle_.get().needs_connection) { -#if !defined(OS_NACL) - read_watcher_.reset(); - base::MessageLoop::current()->RemoveDestructionObserver(this); - - ScopedPlatformHandle accept_fd; - ServerAcceptConnection(handle_.get(), &accept_fd); - if (!accept_fd.is_valid()) { - OnError(); - return; - } - handle_ = std::move(accept_fd); - StartOnIOThread(); -#else - NOTREACHED(); -#endif - return; - } - - bool read_error = false; - size_t next_read_size = 0; - size_t buffer_capacity = 0; - size_t total_bytes_read = 0; - size_t bytes_read = 0; - do { - buffer_capacity = next_read_size; - char* buffer = GetReadBuffer(&buffer_capacity); - DCHECK_GT(buffer_capacity, 0u); - - ssize_t read_result = PlatformChannelRecvmsg( - handle_.get(), - buffer, - buffer_capacity, - &incoming_platform_handles_); - - if (read_result > 0) { - bytes_read = static_cast(read_result); - total_bytes_read += bytes_read; - if (!OnReadComplete(bytes_read, &next_read_size)) { - read_error = true; - break; - } - } else if (read_result == 0 || - (errno != EAGAIN && errno != EWOULDBLOCK)) { - read_error = true; - break; - } - } while (bytes_read == buffer_capacity && - total_bytes_read < kMaxBatchReadCapacity && - next_read_size > 0); - if (read_error) { - // Stop receiving read notifications. - read_watcher_.reset(); - - OnError(); - } - } - - void OnFileCanWriteWithoutBlocking(int fd) override { - bool write_error = false; - { - base::AutoLock lock(write_lock_); - pending_write_ = false; - if (!FlushOutgoingMessagesNoLock()) - reject_writes_ = write_error = true; - } - if (write_error) - OnError(); - } - - // Attempts to write a message directly to the channel. If the full message - // cannot be written, it's queued and a wait is initiated to write the message - // ASAP on the I/O thread. - bool WriteNoLock(MessageView message_view) { - if (handle_.get().needs_connection) { - outgoing_messages_.emplace_front(std::move(message_view)); - return true; - } - size_t bytes_written = 0; - do { - message_view.advance_data_offset(bytes_written); - - ssize_t result; - ScopedPlatformHandleVectorPtr handles = message_view.TakeHandles(); - if (handles && handles->size()) { - iovec iov = { - const_cast(message_view.data()), - message_view.data_num_bytes() - }; - // TODO: Handle lots of handles. - result = PlatformChannelSendmsgWithHandles( - handle_.get(), &iov, 1, handles->data(), handles->size()); - if (result >= 0) { -#if defined(OS_MACOSX) - // There is a bug on OSX which makes it dangerous to close - // a file descriptor while it is in transit. So instead we - // store the file descriptor in a set and send a message to - // the recipient, which is queued AFTER the message that - // sent the FD. The recipient will reply to the message, - // letting us know that it is now safe to close the file - // descriptor. For more information, see: - // http://crbug.com/298276 - std::vector fds; - for (auto& handle : *handles) - fds.push_back(handle.handle); - { - base::AutoLock l(handles_to_close_lock_); - for (auto& handle : *handles) - handles_to_close_->push_back(handle); - } - MessagePtr fds_message( - new Channel::Message(sizeof(fds[0]) * fds.size(), 0, - Message::MessageType::HANDLES_SENT)); - memcpy(fds_message->mutable_payload(), fds.data(), - sizeof(fds[0]) * fds.size()); - outgoing_messages_.emplace_back(std::move(fds_message), 0); - handles->clear(); -#else - handles.reset(); -#endif // defined(OS_MACOSX) - } - } else { - result = PlatformChannelWrite(handle_.get(), message_view.data(), - message_view.data_num_bytes()); - } - - if (result < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK -#if defined(OS_MACOSX) - // On OS X if sendmsg() is trying to send fds between processes and - // there isn't enough room in the output buffer to send the fd - // structure over atomically then EMSGSIZE is returned. - // - // EMSGSIZE presents a problem since the system APIs can only call - // us when there's room in the socket buffer and not when there is - // "enough" room. - // - // The current behavior is to return to the event loop when EMSGSIZE - // is received and hopefull service another FD. This is however - // still technically a busy wait since the event loop will call us - // right back until the receiver has read enough data to allow - // passing the FD over atomically. - && errno != EMSGSIZE -#endif - ) { - return false; - } - message_view.SetHandles(std::move(handles)); - outgoing_messages_.emplace_front(std::move(message_view)); - WaitForWriteOnIOThreadNoLock(); - return true; - } - - bytes_written = static_cast(result); - } while (bytes_written < message_view.data_num_bytes()); - - return FlushOutgoingMessagesNoLock(); - } - - bool FlushOutgoingMessagesNoLock() { - std::deque messages; - std::swap(outgoing_messages_, messages); - - while (!messages.empty()) { - if (!WriteNoLock(std::move(messages.front()))) - return false; - - messages.pop_front(); - if (!outgoing_messages_.empty()) { - // The message was requeued by WriteNoLock(), so we have to wait for - // pipe to become writable again. Repopulate the message queue and exit. - // If sending the message triggered any control messages, they may be - // in |outgoing_messages_| in addition to or instead of the message - // being sent. - std::swap(messages, outgoing_messages_); - while (!messages.empty()) { - outgoing_messages_.push_front(std::move(messages.back())); - messages.pop_back(); - } - return true; - } - } - - return true; - } - -#if defined(OS_MACOSX) - bool OnControlMessage(Message::MessageType message_type, - const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) override { - switch (message_type) { - case Message::MessageType::HANDLES_SENT: { - if (payload_size == 0) - break; - MessagePtr message(new Channel::Message( - payload_size, 0, Message::MessageType::HANDLES_SENT_ACK)); - memcpy(message->mutable_payload(), payload, payload_size); - Write(std::move(message)); - return true; - } - - case Message::MessageType::HANDLES_SENT_ACK: { - size_t num_fds = payload_size / sizeof(int); - if (num_fds == 0 || payload_size % sizeof(int) != 0) - break; - - const int* fds = reinterpret_cast(payload); - if (!CloseHandles(fds, num_fds)) - break; - return true; - } - - default: - break; - } - - return false; - } - - // Closes handles referenced by |fds|. Returns false if |num_fds| is 0, or if - // |fds| does not match a sequence of handles in |handles_to_close_|. - bool CloseHandles(const int* fds, size_t num_fds) { - base::AutoLock l(handles_to_close_lock_); - if (!num_fds) - return false; - - auto start = - std::find_if(handles_to_close_->begin(), handles_to_close_->end(), - [&fds](const PlatformHandle& handle) { - return handle.handle == fds[0]; - }); - if (start == handles_to_close_->end()) - return false; - - auto it = start; - size_t i = 0; - // The FDs in the message should match a sequence of handles in - // |handles_to_close_|. - for (; i < num_fds && it != handles_to_close_->end(); i++, ++it) { - if (it->handle != fds[i]) - return false; - - it->CloseIfNecessary(); - } - if (i != num_fds) - return false; - - handles_to_close_->erase(start, it); - return true; - } -#endif // defined(OS_MACOSX) - - // Keeps the Channel alive at least until explicit shutdown on the IO thread. - scoped_refptr self_; - - ScopedPlatformHandle handle_; - scoped_refptr io_task_runner_; - - // These watchers must only be accessed on the IO thread. - std::unique_ptr read_watcher_; - std::unique_ptr write_watcher_; - - std::deque incoming_platform_handles_; - - // Protects |pending_write_| and |outgoing_messages_|. - base::Lock write_lock_; - bool pending_write_ = false; - bool reject_writes_ = false; - std::deque outgoing_messages_; - - bool leak_handle_ = false; - -#if defined(OS_MACOSX) - base::Lock handles_to_close_lock_; - ScopedPlatformHandleVectorPtr handles_to_close_; -#endif - - DISALLOW_COPY_AND_ASSIGN(ChannelPosix); -}; - -} // namespace - -// static -scoped_refptr Channel::Create( - Delegate* delegate, - ConnectionParams connection_params, - scoped_refptr io_task_runner) { - return new ChannelPosix(delegate, std::move(connection_params), - io_task_runner); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/channel_unittest.cc b/mojo/edk/system/channel_unittest.cc deleted file mode 100644 index ce2c804..0000000 --- a/mojo/edk/system/channel_unittest.cc +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/channel.h" -#include "base/memory/ptr_util.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -class TestChannel : public Channel { - public: - TestChannel(Channel::Delegate* delegate) : Channel(delegate) {} - - char* GetReadBufferTest(size_t* buffer_capacity) { - return GetReadBuffer(buffer_capacity); - } - - bool OnReadCompleteTest(size_t bytes_read, size_t* next_read_size_hint) { - return OnReadComplete(bytes_read, next_read_size_hint); - } - - MOCK_METHOD4(GetReadPlatformHandles, - bool(size_t num_handles, - const void* extra_header, - size_t extra_header_size, - ScopedPlatformHandleVectorPtr* handles)); - MOCK_METHOD0(Start, void()); - MOCK_METHOD0(ShutDownImpl, void()); - MOCK_METHOD0(LeakHandle, void()); - - void Write(MessagePtr message) {} - - protected: - ~TestChannel() override {} -}; - -// Not using GMock as I don't think it supports movable types. -class MockChannelDelegate : public Channel::Delegate { - public: - MockChannelDelegate() {} - - size_t GetReceivedPayloadSize() const { return payload_size_; } - - const void* GetReceivedPayload() const { return payload_.get(); } - - protected: - void OnChannelMessage(const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) override { - payload_.reset(new char[payload_size]); - memcpy(payload_.get(), payload, payload_size); - payload_size_ = payload_size; - } - - // Notify that an error has occured and the Channel will cease operation. - void OnChannelError() override {} - - private: - size_t payload_size_ = 0; - std::unique_ptr payload_; -}; - -Channel::MessagePtr CreateDefaultMessage(bool legacy_message) { - const size_t payload_size = 100; - Channel::MessagePtr message = base::MakeUnique( - payload_size, 0, - legacy_message ? Channel::Message::MessageType::NORMAL_LEGACY - : Channel::Message::MessageType::NORMAL); - char* payload = static_cast(message->mutable_payload()); - for (size_t i = 0; i < payload_size; i++) { - payload[i] = static_cast(i); - } - return message; -} - -void TestMemoryEqual(const void* data1, - size_t data1_size, - const void* data2, - size_t data2_size) { - ASSERT_EQ(data1_size, data2_size); - const unsigned char* data1_char = static_cast(data1); - const unsigned char* data2_char = static_cast(data2); - for (size_t i = 0; i < data1_size; i++) { - // ASSERT so we don't log tons of errors if the data is different. - ASSERT_EQ(data1_char[i], data2_char[i]); - } -} - -void TestMessagesAreEqual(Channel::Message* message1, - Channel::Message* message2, - bool legacy_messages) { - // If any of the message is null, this is probably not what you wanted to - // test. - ASSERT_NE(nullptr, message1); - ASSERT_NE(nullptr, message2); - - ASSERT_EQ(message1->payload_size(), message2->payload_size()); - EXPECT_EQ(message1->has_handles(), message2->has_handles()); - - TestMemoryEqual(message1->payload(), message1->payload_size(), - message2->payload(), message2->payload_size()); - - if (legacy_messages) - return; - - ASSERT_EQ(message1->extra_header_size(), message2->extra_header_size()); - TestMemoryEqual(message1->extra_header(), message1->extra_header_size(), - message2->extra_header(), message2->extra_header_size()); -} - -TEST(ChannelTest, LegacyMessageDeserialization) { - Channel::MessagePtr message = CreateDefaultMessage(true /* legacy_message */); - Channel::MessagePtr deserialized_message = - Channel::Message::Deserialize(message->data(), message->data_num_bytes()); - TestMessagesAreEqual(message.get(), deserialized_message.get(), - true /* legacy_message */); -} - -TEST(ChannelTest, NonLegacyMessageDeserialization) { - Channel::MessagePtr message = - CreateDefaultMessage(false /* legacy_message */); - Channel::MessagePtr deserialized_message = - Channel::Message::Deserialize(message->data(), message->data_num_bytes()); - TestMessagesAreEqual(message.get(), deserialized_message.get(), - false /* legacy_message */); -} - -TEST(ChannelTest, OnReadLegacyMessage) { - size_t buffer_size = 100 * 1024; - Channel::MessagePtr message = CreateDefaultMessage(true /* legacy_message */); - - MockChannelDelegate channel_delegate; - scoped_refptr channel = new TestChannel(&channel_delegate); - char* read_buffer = channel->GetReadBufferTest(&buffer_size); - ASSERT_LT(message->data_num_bytes(), - buffer_size); // Bad test. Increase buffer - // size. - memcpy(read_buffer, message->data(), message->data_num_bytes()); - - size_t next_read_size_hint = 0; - EXPECT_TRUE(channel->OnReadCompleteTest(message->data_num_bytes(), - &next_read_size_hint)); - - TestMemoryEqual(message->payload(), message->payload_size(), - channel_delegate.GetReceivedPayload(), - channel_delegate.GetReceivedPayloadSize()); -} - -TEST(ChannelTest, OnReadNonLegacyMessage) { - size_t buffer_size = 100 * 1024; - Channel::MessagePtr message = - CreateDefaultMessage(false /* legacy_message */); - - MockChannelDelegate channel_delegate; - scoped_refptr channel = new TestChannel(&channel_delegate); - char* read_buffer = channel->GetReadBufferTest(&buffer_size); - ASSERT_LT(message->data_num_bytes(), - buffer_size); // Bad test. Increase buffer - // size. - memcpy(read_buffer, message->data(), message->data_num_bytes()); - - size_t next_read_size_hint = 0; - EXPECT_TRUE(channel->OnReadCompleteTest(message->data_num_bytes(), - &next_read_size_hint)); - - TestMemoryEqual(message->payload(), message->payload_size(), - channel_delegate.GetReceivedPayload(), - channel_delegate.GetReceivedPayloadSize()); -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/channel_win.cc b/mojo/edk/system/channel_win.cc deleted file mode 100644 index c15df16..0000000 --- a/mojo/edk/system/channel_win.cc +++ /dev/null @@ -1,360 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/channel.h" - -#include -#include - -#include -#include -#include -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/lock.h" -#include "base/task_runner.h" -#include "base/win/win_util.h" -#include "mojo/edk/embedder/platform_handle_vector.h" - -namespace mojo { -namespace edk { - -namespace { - -// A view over a Channel::Message object. The write queue uses these since -// large messages may need to be sent in chunks. -class MessageView { - public: - // Owns |message|. |offset| indexes the first unsent byte in the message. - MessageView(Channel::MessagePtr message, size_t offset) - : message_(std::move(message)), - offset_(offset) { - DCHECK_GT(message_->data_num_bytes(), offset_); - } - - MessageView(MessageView&& other) { *this = std::move(other); } - - MessageView& operator=(MessageView&& other) { - message_ = std::move(other.message_); - offset_ = other.offset_; - return *this; - } - - ~MessageView() {} - - const void* data() const { - return static_cast(message_->data()) + offset_; - } - - size_t data_num_bytes() const { return message_->data_num_bytes() - offset_; } - - size_t data_offset() const { return offset_; } - void advance_data_offset(size_t num_bytes) { - DCHECK_GE(message_->data_num_bytes(), offset_ + num_bytes); - offset_ += num_bytes; - } - - Channel::MessagePtr TakeChannelMessage() { return std::move(message_); } - - private: - Channel::MessagePtr message_; - size_t offset_; - - DISALLOW_COPY_AND_ASSIGN(MessageView); -}; - -class ChannelWin : public Channel, - public base::MessageLoop::DestructionObserver, - public base::MessageLoopForIO::IOHandler { - public: - ChannelWin(Delegate* delegate, - ScopedPlatformHandle handle, - scoped_refptr io_task_runner) - : Channel(delegate), - self_(this), - handle_(std::move(handle)), - io_task_runner_(io_task_runner) { - CHECK(handle_.is_valid()); - - wait_for_connect_ = handle_.get().needs_connection; - } - - void Start() override { - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelWin::StartOnIOThread, this)); - } - - void ShutDownImpl() override { - // Always shut down asynchronously when called through the public interface. - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&ChannelWin::ShutDownOnIOThread, this)); - } - - void Write(MessagePtr message) override { - bool write_error = false; - { - base::AutoLock lock(write_lock_); - if (reject_writes_) - return; - - bool write_now = !delay_writes_ && outgoing_messages_.empty(); - outgoing_messages_.emplace_back(std::move(message), 0); - - if (write_now && !WriteNoLock(outgoing_messages_.front())) - reject_writes_ = write_error = true; - } - if (write_error) { - // Do not synchronously invoke OnError(). Write() may have been called by - // the delegate and we don't want to re-enter it. - io_task_runner_->PostTask(FROM_HERE, - base::Bind(&ChannelWin::OnError, this)); - } - } - - void LeakHandle() override { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - leak_handle_ = true; - } - - bool GetReadPlatformHandles( - size_t num_handles, - const void* extra_header, - size_t extra_header_size, - ScopedPlatformHandleVectorPtr* handles) override { - if (num_handles > std::numeric_limits::max()) - return false; - using HandleEntry = Channel::Message::HandleEntry; - size_t handles_size = sizeof(HandleEntry) * num_handles; - if (handles_size > extra_header_size) - return false; - DCHECK(extra_header); - handles->reset(new PlatformHandleVector(num_handles)); - const HandleEntry* extra_header_handles = - reinterpret_cast(extra_header); - for (size_t i = 0; i < num_handles; i++) { - (*handles)->at(i).handle = - base::win::Uint32ToHandle(extra_header_handles[i].handle); - } - return true; - } - - private: - // May run on any thread. - ~ChannelWin() override {} - - void StartOnIOThread() { - base::MessageLoop::current()->AddDestructionObserver(this); - base::MessageLoopForIO::current()->RegisterIOHandler( - handle_.get().handle, this); - - if (wait_for_connect_) { - BOOL ok = ConnectNamedPipe(handle_.get().handle, - &connect_context_.overlapped); - if (ok) { - PLOG(ERROR) << "Unexpected success while waiting for pipe connection"; - OnError(); - return; - } - - const DWORD err = GetLastError(); - switch (err) { - case ERROR_PIPE_CONNECTED: - wait_for_connect_ = false; - break; - case ERROR_IO_PENDING: - AddRef(); - return; - case ERROR_NO_DATA: - OnError(); - return; - } - } - - // Now that we have registered our IOHandler, we can start writing. - { - base::AutoLock lock(write_lock_); - if (delay_writes_) { - delay_writes_ = false; - WriteNextNoLock(); - } - } - - // Keep this alive in case we synchronously run shutdown. - scoped_refptr keep_alive(this); - ReadMore(0); - } - - void ShutDownOnIOThread() { - base::MessageLoop::current()->RemoveDestructionObserver(this); - - // BUG(crbug.com/583525): This function is expected to be called once, and - // |handle_| should be valid at this point. - CHECK(handle_.is_valid()); - CancelIo(handle_.get().handle); - if (leak_handle_) - ignore_result(handle_.release()); - handle_.reset(); - - // May destroy the |this| if it was the last reference. - self_ = nullptr; - } - - // base::MessageLoop::DestructionObserver: - void WillDestroyCurrentMessageLoop() override { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - if (self_) - ShutDownOnIOThread(); - } - - // base::MessageLoop::IOHandler: - void OnIOCompleted(base::MessageLoopForIO::IOContext* context, - DWORD bytes_transfered, - DWORD error) override { - if (error != ERROR_SUCCESS) { - OnError(); - } else if (context == &connect_context_) { - DCHECK(wait_for_connect_); - wait_for_connect_ = false; - ReadMore(0); - - base::AutoLock lock(write_lock_); - if (delay_writes_) { - delay_writes_ = false; - WriteNextNoLock(); - } - } else if (context == &read_context_) { - OnReadDone(static_cast(bytes_transfered)); - } else { - CHECK(context == &write_context_); - OnWriteDone(static_cast(bytes_transfered)); - } - Release(); // Balancing reference taken after ReadFile / WriteFile. - } - - void OnReadDone(size_t bytes_read) { - if (bytes_read > 0) { - size_t next_read_size = 0; - if (OnReadComplete(bytes_read, &next_read_size)) { - ReadMore(next_read_size); - } else { - OnError(); - } - } else if (bytes_read == 0) { - OnError(); - } - } - - void OnWriteDone(size_t bytes_written) { - if (bytes_written == 0) - return; - - bool write_error = false; - { - base::AutoLock lock(write_lock_); - - DCHECK(!outgoing_messages_.empty()); - - MessageView& message_view = outgoing_messages_.front(); - message_view.advance_data_offset(bytes_written); - if (message_view.data_num_bytes() == 0) { - Channel::MessagePtr message = message_view.TakeChannelMessage(); - outgoing_messages_.pop_front(); - - // Clear any handles so they don't get closed on destruction. - ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); - if (handles) - handles->clear(); - } - - if (!WriteNextNoLock()) - reject_writes_ = write_error = true; - } - if (write_error) - OnError(); - } - - void ReadMore(size_t next_read_size_hint) { - size_t buffer_capacity = next_read_size_hint; - char* buffer = GetReadBuffer(&buffer_capacity); - DCHECK_GT(buffer_capacity, 0u); - - BOOL ok = ReadFile(handle_.get().handle, - buffer, - static_cast(buffer_capacity), - NULL, - &read_context_.overlapped); - - if (ok || GetLastError() == ERROR_IO_PENDING) { - AddRef(); // Will be balanced in OnIOCompleted - } else { - OnError(); - } - } - - // Attempts to write a message directly to the channel. If the full message - // cannot be written, it's queued and a wait is initiated to write the message - // ASAP on the I/O thread. - bool WriteNoLock(const MessageView& message_view) { - BOOL ok = WriteFile(handle_.get().handle, - message_view.data(), - static_cast(message_view.data_num_bytes()), - NULL, - &write_context_.overlapped); - - if (ok || GetLastError() == ERROR_IO_PENDING) { - AddRef(); // Will be balanced in OnIOCompleted. - return true; - } - return false; - } - - bool WriteNextNoLock() { - if (outgoing_messages_.empty()) - return true; - return WriteNoLock(outgoing_messages_.front()); - } - - // Keeps the Channel alive at least until explicit shutdown on the IO thread. - scoped_refptr self_; - - ScopedPlatformHandle handle_; - scoped_refptr io_task_runner_; - - base::MessageLoopForIO::IOContext connect_context_; - base::MessageLoopForIO::IOContext read_context_; - base::MessageLoopForIO::IOContext write_context_; - - // Protects |reject_writes_| and |outgoing_messages_|. - base::Lock write_lock_; - - bool delay_writes_ = true; - - bool reject_writes_ = false; - std::deque outgoing_messages_; - - bool wait_for_connect_; - - bool leak_handle_ = false; - - DISALLOW_COPY_AND_ASSIGN(ChannelWin); -}; - -} // namespace - -// static -scoped_refptr Channel::Create( - Delegate* delegate, - ConnectionParams connection_params, - scoped_refptr io_task_runner) { - return new ChannelWin(delegate, connection_params.TakeChannelHandle(), - io_task_runner); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/configuration.cc b/mojo/edk/system/configuration.cc deleted file mode 100644 index f5eb2b8..0000000 --- a/mojo/edk/system/configuration.cc +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/configuration.h" - -namespace mojo { -namespace edk { -namespace internal { - -// These default values should be synced with the documentation in -// mojo/edk/embedder/configuration.h. -Configuration g_configuration = { - 1000000, // max_handle_table_size - 1000000, // max_mapping_table_sze - 4 * 1024 * 1024, // max_message_num_bytes - 10000, // max_message_num_handles - 256 * 1024 * 1024, // max_data_pipe_capacity_bytes - 1024 * 1024, // default_data_pipe_capacity_bytes - 16, // data_pipe_buffer_alignment_bytes - 1024 * 1024 * 1024}; // max_shared_memory_num_bytes - -} // namespace internal -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/configuration.h b/mojo/edk/system/configuration.h deleted file mode 100644 index 038835f..0000000 --- a/mojo/edk/system/configuration.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_CONFIGURATION_H_ -#define MOJO_EDK_SYSTEM_CONFIGURATION_H_ - -#include "mojo/edk/embedder/configuration.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -namespace internal { -MOJO_SYSTEM_IMPL_EXPORT extern Configuration g_configuration; -} // namespace internal - -MOJO_SYSTEM_IMPL_EXPORT inline const Configuration& GetConfiguration() { - return internal::g_configuration; -} - -MOJO_SYSTEM_IMPL_EXPORT inline Configuration* GetMutableConfiguration() { - return &internal::g_configuration; -} - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_CONFIGURATION_H_ diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc deleted file mode 100644 index 360e8c3..0000000 --- a/mojo/edk/system/core.cc +++ /dev/null @@ -1,1019 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/core.h" - -#include - -#include - -#include "base/bind.h" -#include "base/containers/stack_container.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/rand_util.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/channel.h" -#include "mojo/edk/system/configuration.h" -#include "mojo/edk/system/data_pipe_consumer_dispatcher.h" -#include "mojo/edk/system/data_pipe_producer_dispatcher.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/message_for_transit.h" -#include "mojo/edk/system/message_pipe_dispatcher.h" -#include "mojo/edk/system/platform_handle_dispatcher.h" -#include "mojo/edk/system/ports/name.h" -#include "mojo/edk/system/ports/node.h" -#include "mojo/edk/system/request_context.h" -#include "mojo/edk/system/shared_buffer_dispatcher.h" -#include "mojo/edk/system/watcher_dispatcher.h" - -namespace mojo { -namespace edk { - -namespace { - -// This is an unnecessarily large limit that is relatively easy to enforce. -const uint32_t kMaxHandlesPerMessage = 1024 * 1024; - -// TODO(rockot): Maybe we could negotiate a debugging pipe ID for cross-process -// pipes too; for now we just use a constant. This only affects bootstrap pipes. -const uint64_t kUnknownPipeIdForDebug = 0x7f7f7f7f7f7f7f7fUL; - -MojoResult MojoPlatformHandleToScopedPlatformHandle( - const MojoPlatformHandle* platform_handle, - ScopedPlatformHandle* out_handle) { - if (platform_handle->struct_size != sizeof(MojoPlatformHandle)) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (platform_handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) { - out_handle->reset(); - return MOJO_RESULT_OK; - } - - PlatformHandle handle; - switch (platform_handle->type) { -#if defined(OS_POSIX) - case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR: - handle.handle = static_cast(platform_handle->value); - break; -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) - case MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT: - handle.type = PlatformHandle::Type::MACH; - handle.port = static_cast(platform_handle->value); - break; -#endif - -#if defined(OS_WIN) - case MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE: - handle.handle = reinterpret_cast(platform_handle->value); - break; -#endif - - default: - return MOJO_RESULT_INVALID_ARGUMENT; - } - - out_handle->reset(handle); - return MOJO_RESULT_OK; -} - -MojoResult ScopedPlatformHandleToMojoPlatformHandle( - ScopedPlatformHandle handle, - MojoPlatformHandle* platform_handle) { - if (platform_handle->struct_size != sizeof(MojoPlatformHandle)) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!handle.is_valid()) { - platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID; - return MOJO_RESULT_OK; - } - -#if defined(OS_POSIX) - switch (handle.get().type) { - case PlatformHandle::Type::POSIX: - platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; - platform_handle->value = static_cast(handle.release().handle); - break; - -#if defined(OS_MACOSX) && !defined(OS_IOS) - case PlatformHandle::Type::MACH: - platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT; - platform_handle->value = static_cast(handle.release().port); - break; -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - - default: - return MOJO_RESULT_INVALID_ARGUMENT; - } -#elif defined(OS_WIN) - platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; - platform_handle->value = reinterpret_cast(handle.release().handle); -#endif // defined(OS_WIN) - - return MOJO_RESULT_OK; -} - -} // namespace - -Core::Core() {} - -Core::~Core() { - if (node_controller_ && node_controller_->io_task_runner()) { - // If this races with IO thread shutdown the callback will be dropped and - // the NodeController will be shutdown on this thread anyway, which is also - // just fine. - scoped_refptr io_task_runner = - node_controller_->io_task_runner(); - io_task_runner->PostTask(FROM_HERE, - base::Bind(&Core::PassNodeControllerToIOThread, - base::Passed(&node_controller_))); - } -} - -void Core::SetIOTaskRunner(scoped_refptr io_task_runner) { - GetNodeController()->SetIOTaskRunner(io_task_runner); -} - -NodeController* Core::GetNodeController() { - base::AutoLock lock(node_controller_lock_); - if (!node_controller_) - node_controller_.reset(new NodeController(this)); - return node_controller_.get(); -} - -scoped_refptr Core::GetDispatcher(MojoHandle handle) { - base::AutoLock lock(handles_lock_); - return handles_.GetDispatcher(handle); -} - -void Core::SetDefaultProcessErrorCallback( - const ProcessErrorCallback& callback) { - default_process_error_callback_ = callback; -} - -void Core::AddChild(base::ProcessHandle process_handle, - ConnectionParams connection_params, - const std::string& child_token, - const ProcessErrorCallback& process_error_callback) { - GetNodeController()->ConnectToChild(process_handle, - std::move(connection_params), child_token, - process_error_callback); -} - -void Core::ChildLaunchFailed(const std::string& child_token) { - RequestContext request_context; - GetNodeController()->CloseChildPorts(child_token); -} - -ScopedMessagePipeHandle Core::ConnectToPeerProcess( - ScopedPlatformHandle pipe_handle, - const std::string& peer_token) { - RequestContext request_context; - ports::PortRef port0, port1; - GetNodeController()->node()->CreatePortPair(&port0, &port1); - MojoHandle handle = AddDispatcher(new MessagePipeDispatcher( - GetNodeController(), port0, kUnknownPipeIdForDebug, 0)); - ConnectionParams connection_params(std::move(pipe_handle)); - GetNodeController()->ConnectToPeer(std::move(connection_params), port1, - peer_token); - return ScopedMessagePipeHandle(MessagePipeHandle(handle)); -} - -void Core::ClosePeerConnection(const std::string& peer_token) { - GetNodeController()->ClosePeerConnection(peer_token); -} - -void Core::InitChild(ConnectionParams connection_params) { - GetNodeController()->ConnectToParent(std::move(connection_params)); -} - -void Core::SetMachPortProvider(base::PortProvider* port_provider) { -#if defined(OS_MACOSX) && !defined(OS_IOS) - GetNodeController()->CreateMachPortRelay(port_provider); -#endif -} - -MojoHandle Core::AddDispatcher(scoped_refptr dispatcher) { - base::AutoLock lock(handles_lock_); - return handles_.AddDispatcher(dispatcher); -} - -bool Core::AddDispatchersFromTransit( - const std::vector& dispatchers, - MojoHandle* handles) { - bool failed = false; - { - base::AutoLock lock(handles_lock_); - if (!handles_.AddDispatchersFromTransit(dispatchers, handles)) - failed = true; - } - if (failed) { - for (auto d : dispatchers) - d.dispatcher->Close(); - return false; - } - return true; -} - -MojoResult Core::CreatePlatformHandleWrapper( - ScopedPlatformHandle platform_handle, - MojoHandle* wrapper_handle) { - MojoHandle h = AddDispatcher( - PlatformHandleDispatcher::Create(std::move(platform_handle))); - if (h == MOJO_HANDLE_INVALID) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - *wrapper_handle = h; - return MOJO_RESULT_OK; -} - -MojoResult Core::PassWrappedPlatformHandle( - MojoHandle wrapper_handle, - ScopedPlatformHandle* platform_handle) { - base::AutoLock lock(handles_lock_); - scoped_refptr d; - MojoResult result = handles_.GetAndRemoveDispatcher(wrapper_handle, &d); - if (result != MOJO_RESULT_OK) - return result; - if (d->GetType() == Dispatcher::Type::PLATFORM_HANDLE) { - PlatformHandleDispatcher* phd = - static_cast(d.get()); - *platform_handle = phd->PassPlatformHandle(); - } else { - result = MOJO_RESULT_INVALID_ARGUMENT; - } - d->Close(); - return result; -} - -MojoResult Core::CreateSharedBufferWrapper( - base::SharedMemoryHandle shared_memory_handle, - size_t num_bytes, - bool read_only, - MojoHandle* mojo_wrapper_handle) { - DCHECK(num_bytes); - scoped_refptr platform_buffer = - PlatformSharedBuffer::CreateFromSharedMemoryHandle(num_bytes, read_only, - shared_memory_handle); - if (!platform_buffer) - return MOJO_RESULT_UNKNOWN; - - scoped_refptr dispatcher; - MojoResult result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer( - platform_buffer, &dispatcher); - if (result != MOJO_RESULT_OK) - return result; - MojoHandle h = AddDispatcher(dispatcher); - if (h == MOJO_HANDLE_INVALID) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - *mojo_wrapper_handle = h; - return MOJO_RESULT_OK; -} - -MojoResult Core::PassSharedMemoryHandle( - MojoHandle mojo_handle, - base::SharedMemoryHandle* shared_memory_handle, - size_t* num_bytes, - bool* read_only) { - if (!shared_memory_handle) - return MOJO_RESULT_INVALID_ARGUMENT; - - scoped_refptr dispatcher; - MojoResult result = MOJO_RESULT_OK; - { - base::AutoLock lock(handles_lock_); - // Get the dispatcher and check it before removing it from the handle table - // to ensure that the dispatcher is of the correct type. This ensures we - // don't close and remove the wrong type of dispatcher. - dispatcher = handles_.GetDispatcher(mojo_handle); - if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) - return MOJO_RESULT_INVALID_ARGUMENT; - - result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher); - if (result != MOJO_RESULT_OK) - return result; - } - - SharedBufferDispatcher* shm_dispatcher = - static_cast(dispatcher.get()); - scoped_refptr platform_shared_buffer = - shm_dispatcher->PassPlatformSharedBuffer(); - - if (!platform_shared_buffer) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (num_bytes) - *num_bytes = platform_shared_buffer->GetNumBytes(); - if (read_only) - *read_only = platform_shared_buffer->IsReadOnly(); - *shared_memory_handle = platform_shared_buffer->DuplicateSharedMemoryHandle(); - - shm_dispatcher->Close(); - return result; -} - -void Core::RequestShutdown(const base::Closure& callback) { - GetNodeController()->RequestShutdown(callback); -} - -ScopedMessagePipeHandle Core::CreateParentMessagePipe( - const std::string& token, const std::string& child_token) { - RequestContext request_context; - ports::PortRef port0, port1; - GetNodeController()->node()->CreatePortPair(&port0, &port1); - MojoHandle handle = AddDispatcher( - new MessagePipeDispatcher(GetNodeController(), port0, - kUnknownPipeIdForDebug, 0)); - GetNodeController()->ReservePort(token, port1, child_token); - return ScopedMessagePipeHandle(MessagePipeHandle(handle)); -} - -ScopedMessagePipeHandle Core::CreateChildMessagePipe(const std::string& token) { - RequestContext request_context; - ports::PortRef port0, port1; - GetNodeController()->node()->CreatePortPair(&port0, &port1); - MojoHandle handle = AddDispatcher( - new MessagePipeDispatcher(GetNodeController(), port0, - kUnknownPipeIdForDebug, 1)); - GetNodeController()->MergePortIntoParent(token, port1); - return ScopedMessagePipeHandle(MessagePipeHandle(handle)); -} - -MojoResult Core::SetProperty(MojoPropertyType type, const void* value) { - base::AutoLock locker(property_lock_); - switch (type) { - case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED: - property_sync_call_allowed_ = *static_cast(value); - return MOJO_RESULT_OK; - default: - return MOJO_RESULT_INVALID_ARGUMENT; - } -} - -MojoTimeTicks Core::GetTimeTicksNow() { - return base::TimeTicks::Now().ToInternalValue(); -} - -MojoResult Core::Close(MojoHandle handle) { - RequestContext request_context; - scoped_refptr dispatcher; - { - base::AutoLock lock(handles_lock_); - MojoResult rv = handles_.GetAndRemoveDispatcher(handle, &dispatcher); - if (rv != MOJO_RESULT_OK) - return rv; - } - dispatcher->Close(); - return MOJO_RESULT_OK; -} - -MojoResult Core::QueryHandleSignalsState( - MojoHandle handle, - MojoHandleSignalsState* signals_state) { - RequestContext request_context; - scoped_refptr dispatcher = GetDispatcher(handle); - if (!dispatcher || !signals_state) - return MOJO_RESULT_INVALID_ARGUMENT; - *signals_state = dispatcher->GetHandleSignalsState(); - return MOJO_RESULT_OK; -} - -MojoResult Core::CreateWatcher(MojoWatcherCallback callback, - MojoHandle* watcher_handle) { - RequestContext request_context; - if (!watcher_handle) - return MOJO_RESULT_INVALID_ARGUMENT; - *watcher_handle = AddDispatcher(new WatcherDispatcher(callback)); - if (*watcher_handle == MOJO_HANDLE_INVALID) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - return MOJO_RESULT_OK; -} - -MojoResult Core::Watch(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - uintptr_t context) { - RequestContext request_context; - scoped_refptr watcher = GetDispatcher(watcher_handle); - if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER) - return MOJO_RESULT_INVALID_ARGUMENT; - scoped_refptr dispatcher = GetDispatcher(handle); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - return watcher->WatchDispatcher(dispatcher, signals, context); -} - -MojoResult Core::CancelWatch(MojoHandle watcher_handle, uintptr_t context) { - RequestContext request_context; - scoped_refptr watcher = GetDispatcher(watcher_handle); - if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER) - return MOJO_RESULT_INVALID_ARGUMENT; - return watcher->CancelWatch(context); -} - -MojoResult Core::ArmWatcher(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) { - RequestContext request_context; - scoped_refptr watcher = GetDispatcher(watcher_handle); - if (!watcher || watcher->GetType() != Dispatcher::Type::WATCHER) - return MOJO_RESULT_INVALID_ARGUMENT; - return watcher->Arm(num_ready_contexts, ready_contexts, ready_results, - ready_signals_states); -} - -MojoResult Core::AllocMessage(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message) { - if (!message) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (num_handles == 0) { // Fast path: no handles. - std::unique_ptr msg; - MojoResult rv = MessageForTransit::Create(&msg, num_bytes, nullptr, 0); - if (rv != MOJO_RESULT_OK) - return rv; - - *message = reinterpret_cast(msg.release()); - return MOJO_RESULT_OK; - } - - if (!handles) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (num_handles > kMaxHandlesPerMessage) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - std::vector dispatchers; - { - base::AutoLock lock(handles_lock_); - MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers); - if (rv != MOJO_RESULT_OK) { - handles_.CancelTransit(dispatchers); - return rv; - } - } - DCHECK_EQ(num_handles, dispatchers.size()); - - std::unique_ptr msg; - MojoResult rv = MessageForTransit::Create( - &msg, num_bytes, dispatchers.data(), num_handles); - - { - base::AutoLock lock(handles_lock_); - if (rv == MOJO_RESULT_OK) { - handles_.CompleteTransitAndClose(dispatchers); - *message = reinterpret_cast(msg.release()); - } else { - handles_.CancelTransit(dispatchers); - } - } - - return rv; -} - -MojoResult Core::FreeMessage(MojoMessageHandle message) { - if (!message) - return MOJO_RESULT_INVALID_ARGUMENT; - - delete reinterpret_cast(message); - - return MOJO_RESULT_OK; -} - -MojoResult Core::GetMessageBuffer(MojoMessageHandle message, void** buffer) { - if (!message) - return MOJO_RESULT_INVALID_ARGUMENT; - - *buffer = reinterpret_cast(message)->mutable_bytes(); - - return MOJO_RESULT_OK; -} - -MojoResult Core::GetProperty(MojoPropertyType type, void* value) { - base::AutoLock locker(property_lock_); - switch (type) { - case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED: - *static_cast(value) = property_sync_call_allowed_; - return MOJO_RESULT_OK; - default: - return MOJO_RESULT_INVALID_ARGUMENT; - } -} - -MojoResult Core::CreateMessagePipe( - const MojoCreateMessagePipeOptions* options, - MojoHandle* message_pipe_handle0, - MojoHandle* message_pipe_handle1) { - RequestContext request_context; - ports::PortRef port0, port1; - GetNodeController()->node()->CreatePortPair(&port0, &port1); - - CHECK(message_pipe_handle0); - CHECK(message_pipe_handle1); - - uint64_t pipe_id = base::RandUint64(); - - *message_pipe_handle0 = AddDispatcher( - new MessagePipeDispatcher(GetNodeController(), port0, pipe_id, 0)); - if (*message_pipe_handle0 == MOJO_HANDLE_INVALID) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - *message_pipe_handle1 = AddDispatcher( - new MessagePipeDispatcher(GetNodeController(), port1, pipe_id, 1)); - if (*message_pipe_handle1 == MOJO_HANDLE_INVALID) { - scoped_refptr unused; - unused->Close(); - - base::AutoLock lock(handles_lock_); - handles_.GetAndRemoveDispatcher(*message_pipe_handle0, &unused); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - return MOJO_RESULT_OK; -} - -MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags) { - if (num_bytes && !bytes) - return MOJO_RESULT_INVALID_ARGUMENT; - - MojoMessageHandle message; - MojoResult rv = AllocMessage(num_bytes, handles, num_handles, - MOJO_ALLOC_MESSAGE_FLAG_NONE, &message); - if (rv != MOJO_RESULT_OK) - return rv; - - if (num_bytes) { - void* buffer = nullptr; - rv = GetMessageBuffer(message, &buffer); - DCHECK_EQ(rv, MOJO_RESULT_OK); - memcpy(buffer, bytes, num_bytes); - } - - return WriteMessageNew(message_pipe_handle, message, flags); -} - -MojoResult Core::WriteMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags flags) { - RequestContext request_context; - std::unique_ptr message_for_transit( - reinterpret_cast(message)); - auto dispatcher = GetDispatcher(message_pipe_handle); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->WriteMessage(std::move(message_for_transit), flags); -} - -MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - CHECK((!num_handles || !*num_handles || handles) && - (!num_bytes || !*num_bytes || bytes)); - RequestContext request_context; - auto dispatcher = GetDispatcher(message_pipe_handle); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - std::unique_ptr message; - MojoResult rv = - dispatcher->ReadMessage(&message, num_bytes, handles, num_handles, flags, - false /* ignore_num_bytes */); - if (rv != MOJO_RESULT_OK) - return rv; - - if (message && message->num_bytes()) - memcpy(bytes, message->bytes(), message->num_bytes()); - - return MOJO_RESULT_OK; -} - -MojoResult Core::ReadMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - CHECK(message); - CHECK(!num_handles || !*num_handles || handles); - RequestContext request_context; - auto dispatcher = GetDispatcher(message_pipe_handle); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - std::unique_ptr msg; - MojoResult rv = - dispatcher->ReadMessage(&msg, num_bytes, handles, num_handles, flags, - true /* ignore_num_bytes */); - if (rv != MOJO_RESULT_OK) - return rv; - *message = reinterpret_cast(msg.release()); - return MOJO_RESULT_OK; -} - -MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { - RequestContext request_context; - scoped_refptr dispatcher0; - scoped_refptr dispatcher1; - - bool valid_handles = true; - { - base::AutoLock lock(handles_lock_); - MojoResult result0 = handles_.GetAndRemoveDispatcher(handle0, &dispatcher0); - MojoResult result1 = handles_.GetAndRemoveDispatcher(handle1, &dispatcher1); - if (result0 != MOJO_RESULT_OK || result1 != MOJO_RESULT_OK || - dispatcher0->GetType() != Dispatcher::Type::MESSAGE_PIPE || - dispatcher1->GetType() != Dispatcher::Type::MESSAGE_PIPE) - valid_handles = false; - } - - if (!valid_handles) { - if (dispatcher0) - dispatcher0->Close(); - if (dispatcher1) - dispatcher1->Close(); - return MOJO_RESULT_INVALID_ARGUMENT; - } - - MessagePipeDispatcher* mpd0 = - static_cast(dispatcher0.get()); - MessagePipeDispatcher* mpd1 = - static_cast(dispatcher1.get()); - - if (!mpd0->Fuse(mpd1)) - return MOJO_RESULT_FAILED_PRECONDITION; - - return MOJO_RESULT_OK; -} - -MojoResult Core::NotifyBadMessage(MojoMessageHandle message, - const char* error, - size_t error_num_bytes) { - if (!message) - return MOJO_RESULT_INVALID_ARGUMENT; - - const PortsMessage& ports_message = - reinterpret_cast(message)->ports_message(); - if (ports_message.source_node() == ports::kInvalidNodeName) { - DVLOG(1) << "Received invalid message from unknown node."; - if (!default_process_error_callback_.is_null()) - default_process_error_callback_.Run(std::string(error, error_num_bytes)); - return MOJO_RESULT_OK; - } - - GetNodeController()->NotifyBadMessageFrom( - ports_message.source_node(), std::string(error, error_num_bytes)); - return MOJO_RESULT_OK; -} - -MojoResult Core::CreateDataPipe( - const MojoCreateDataPipeOptions* options, - MojoHandle* data_pipe_producer_handle, - MojoHandle* data_pipe_consumer_handle) { - RequestContext request_context; - if (options && options->struct_size != sizeof(MojoCreateDataPipeOptions)) - return MOJO_RESULT_INVALID_ARGUMENT; - - MojoCreateDataPipeOptions create_options; - create_options.struct_size = sizeof(MojoCreateDataPipeOptions); - create_options.flags = options ? options->flags : 0; - create_options.element_num_bytes = options ? options->element_num_bytes : 1; - // TODO(rockot): Use Configuration to get default data pipe capacity. - create_options.capacity_num_bytes = - options && options->capacity_num_bytes ? options->capacity_num_bytes - : 64 * 1024; - - // TODO(rockot): Broker through the parent when necessary. - scoped_refptr ring_buffer = - GetNodeController()->CreateSharedBuffer( - create_options.capacity_num_bytes); - if (!ring_buffer) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - ports::PortRef port0, port1; - GetNodeController()->node()->CreatePortPair(&port0, &port1); - - CHECK(data_pipe_producer_handle); - CHECK(data_pipe_consumer_handle); - - uint64_t pipe_id = base::RandUint64(); - - scoped_refptr producer = new DataPipeProducerDispatcher( - GetNodeController(), port0, ring_buffer, create_options, - true /* initialized */, pipe_id); - scoped_refptr consumer = new DataPipeConsumerDispatcher( - GetNodeController(), port1, ring_buffer, create_options, - true /* initialized */, pipe_id); - - *data_pipe_producer_handle = AddDispatcher(producer); - *data_pipe_consumer_handle = AddDispatcher(consumer); - if (*data_pipe_producer_handle == MOJO_HANDLE_INVALID || - *data_pipe_consumer_handle == MOJO_HANDLE_INVALID) { - if (*data_pipe_producer_handle != MOJO_HANDLE_INVALID) { - scoped_refptr unused; - base::AutoLock lock(handles_lock_); - handles_.GetAndRemoveDispatcher(*data_pipe_producer_handle, &unused); - } - producer->Close(); - consumer->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - return MOJO_RESULT_OK; -} - -MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, - const void* elements, - uint32_t* num_bytes, - MojoWriteDataFlags flags) { - RequestContext request_context; - scoped_refptr dispatcher( - GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->WriteData(elements, num_bytes, flags); -} - -MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, - void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags) { - RequestContext request_context; - scoped_refptr dispatcher( - GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags); -} - -MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, - uint32_t num_bytes_written) { - RequestContext request_context; - scoped_refptr dispatcher( - GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->EndWriteData(num_bytes_written); -} - -MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, - void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) { - RequestContext request_context; - scoped_refptr dispatcher( - GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->ReadData(elements, num_bytes, flags); -} - -MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, - const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags) { - RequestContext request_context; - scoped_refptr dispatcher( - GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags); -} - -MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, - uint32_t num_bytes_read) { - RequestContext request_context; - scoped_refptr dispatcher( - GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - return dispatcher->EndReadData(num_bytes_read); -} - -MojoResult Core::CreateSharedBuffer( - const MojoCreateSharedBufferOptions* options, - uint64_t num_bytes, - MojoHandle* shared_buffer_handle) { - RequestContext request_context; - MojoCreateSharedBufferOptions validated_options = {}; - MojoResult result = SharedBufferDispatcher::ValidateCreateOptions( - options, &validated_options); - if (result != MOJO_RESULT_OK) - return result; - - scoped_refptr dispatcher; - result = SharedBufferDispatcher::Create( - validated_options, GetNodeController(), num_bytes, &dispatcher); - if (result != MOJO_RESULT_OK) { - DCHECK(!dispatcher); - return result; - } - - *shared_buffer_handle = AddDispatcher(dispatcher); - if (*shared_buffer_handle == MOJO_HANDLE_INVALID) { - LOG(ERROR) << "Handle table full"; - dispatcher->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - return MOJO_RESULT_OK; -} - -MojoResult Core::DuplicateBufferHandle( - MojoHandle buffer_handle, - const MojoDuplicateBufferHandleOptions* options, - MojoHandle* new_buffer_handle) { - RequestContext request_context; - scoped_refptr dispatcher(GetDispatcher(buffer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - // Don't verify |options| here; that's the dispatcher's job. - scoped_refptr new_dispatcher; - MojoResult result = - dispatcher->DuplicateBufferHandle(options, &new_dispatcher); - if (result != MOJO_RESULT_OK) - return result; - - *new_buffer_handle = AddDispatcher(new_dispatcher); - if (*new_buffer_handle == MOJO_HANDLE_INVALID) { - LOG(ERROR) << "Handle table full"; - dispatcher->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - return MOJO_RESULT_OK; -} - -MojoResult Core::MapBuffer(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - void** buffer, - MojoMapBufferFlags flags) { - RequestContext request_context; - scoped_refptr dispatcher(GetDispatcher(buffer_handle)); - if (!dispatcher) - return MOJO_RESULT_INVALID_ARGUMENT; - - std::unique_ptr mapping; - MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); - if (result != MOJO_RESULT_OK) - return result; - - DCHECK(mapping); - void* address = mapping->GetBase(); - { - base::AutoLock locker(mapping_table_lock_); - result = mapping_table_.AddMapping(std::move(mapping)); - } - if (result != MOJO_RESULT_OK) - return result; - - *buffer = address; - return MOJO_RESULT_OK; -} - -MojoResult Core::UnmapBuffer(void* buffer) { - RequestContext request_context; - base::AutoLock lock(mapping_table_lock_); - return mapping_table_.RemoveMapping(buffer); -} - -MojoResult Core::WrapPlatformHandle(const MojoPlatformHandle* platform_handle, - MojoHandle* mojo_handle) { - ScopedPlatformHandle handle; - MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle, - &handle); - if (result != MOJO_RESULT_OK) - return result; - - return CreatePlatformHandleWrapper(std::move(handle), mojo_handle); -} - -MojoResult Core::UnwrapPlatformHandle(MojoHandle mojo_handle, - MojoPlatformHandle* platform_handle) { - ScopedPlatformHandle handle; - MojoResult result = PassWrappedPlatformHandle(mojo_handle, &handle); - if (result != MOJO_RESULT_OK) - return result; - - return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle), - platform_handle); -} - -MojoResult Core::WrapPlatformSharedBufferHandle( - const MojoPlatformHandle* platform_handle, - size_t size, - MojoPlatformSharedBufferHandleFlags flags, - MojoHandle* mojo_handle) { - DCHECK(size); - ScopedPlatformHandle handle; - MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle, - &handle); - if (result != MOJO_RESULT_OK) - return result; - - bool read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY; - scoped_refptr platform_buffer = - PlatformSharedBuffer::CreateFromPlatformHandle(size, read_only, - std::move(handle)); - if (!platform_buffer) - return MOJO_RESULT_UNKNOWN; - - scoped_refptr dispatcher; - result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer( - platform_buffer, &dispatcher); - if (result != MOJO_RESULT_OK) - return result; - - MojoHandle h = AddDispatcher(dispatcher); - if (h == MOJO_HANDLE_INVALID) { - dispatcher->Close(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - *mojo_handle = h; - return MOJO_RESULT_OK; -} - -MojoResult Core::UnwrapPlatformSharedBufferHandle( - MojoHandle mojo_handle, - MojoPlatformHandle* platform_handle, - size_t* size, - MojoPlatformSharedBufferHandleFlags* flags) { - scoped_refptr dispatcher; - MojoResult result = MOJO_RESULT_OK; - { - base::AutoLock lock(handles_lock_); - result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher); - if (result != MOJO_RESULT_OK) - return result; - } - - if (dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) { - dispatcher->Close(); - return MOJO_RESULT_INVALID_ARGUMENT; - } - - SharedBufferDispatcher* shm_dispatcher = - static_cast(dispatcher.get()); - scoped_refptr platform_shared_buffer = - shm_dispatcher->PassPlatformSharedBuffer(); - CHECK(platform_shared_buffer); - - CHECK(size); - *size = platform_shared_buffer->GetNumBytes(); - - CHECK(flags); - *flags = MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE; - if (platform_shared_buffer->IsReadOnly()) - *flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY; - - ScopedPlatformHandle handle = platform_shared_buffer->PassPlatformHandle(); - return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle), - platform_handle); -} - -void Core::GetActiveHandlesForTest(std::vector* handles) { - base::AutoLock lock(handles_lock_); - handles_.GetActiveHandlesForTest(handles); -} - -// static -void Core::PassNodeControllerToIOThread( - std::unique_ptr node_controller) { - // It's OK to leak this reference. At this point we know the IO loop is still - // running, and we know the NodeController will observe its eventual - // destruction. This tells the NodeController to delete itself when that - // happens. - node_controller.release()->DestroyOnIOThreadShutdown(); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h deleted file mode 100644 index 1f6d865..0000000 --- a/mojo/edk/system/core.h +++ /dev/null @@ -1,297 +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_CORE_H_ -#define MOJO_EDK_SYSTEM_CORE_H_ - -#include -#include -#include - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/shared_memory_handle.h" -#include "base/synchronization/lock.h" -#include "base/task_runner.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/handle_table.h" -#include "mojo/edk/system/mapping_table.h" -#include "mojo/edk/system/node_controller.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/platform_handle.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/c/system/watcher.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace base { -class PortProvider; -} - -namespace mojo { -namespace edk { - -// |Core| is an object that implements the Mojo system calls. All public methods -// are thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT Core { - public: - Core(); - virtual ~Core(); - - // Called exactly once, shortly after construction, and before any other - // methods are called on this object. - void SetIOTaskRunner(scoped_refptr io_task_runner); - - // Retrieves the NodeController for the current process. - NodeController* GetNodeController(); - - scoped_refptr GetDispatcher(MojoHandle handle); - - void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback); - - // Called in the parent process any time a new child is launched. - void AddChild(base::ProcessHandle process_handle, - ConnectionParams connection_params, - const std::string& child_token, - const ProcessErrorCallback& process_error_callback); - - // Called in the parent process when a child process fails to launch. - void ChildLaunchFailed(const std::string& child_token); - - // Called to connect to a peer process. This should be called only if there - // is no common ancestor for the processes involved within this mojo system. - // Both processes must call this function, each passing one end of a platform - // channel. This returns one end of a message pipe to each process. - ScopedMessagePipeHandle ConnectToPeerProcess(ScopedPlatformHandle pipe_handle, - const std::string& peer_token); - void ClosePeerConnection(const std::string& peer_token); - - // Called in a child process exactly once during early initialization. - void InitChild(ConnectionParams connection_params); - - // Creates a message pipe endpoint associated with |token|, which a child - // holding the token can later locate and connect to. - ScopedMessagePipeHandle CreateParentMessagePipe( - const std::string& token, const std::string& child_token); - - // Creates a message pipe endpoint and connects it to a pipe the parent has - // associated with |token|. - ScopedMessagePipeHandle CreateChildMessagePipe(const std::string& token); - - // Sets the mach port provider for this process. - void SetMachPortProvider(base::PortProvider* port_provider); - - MojoHandle AddDispatcher(scoped_refptr dispatcher); - - // Adds new dispatchers for non-message-pipe handles received in a message. - // |dispatchers| and |handles| should be the same size. - bool AddDispatchersFromTransit( - const std::vector& dispatchers, - MojoHandle* handles); - - // See "mojo/edk/embedder/embedder.h" for more information on these functions. - MojoResult CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle, - MojoHandle* wrapper_handle); - - MojoResult PassWrappedPlatformHandle(MojoHandle wrapper_handle, - ScopedPlatformHandle* platform_handle); - - MojoResult CreateSharedBufferWrapper( - base::SharedMemoryHandle shared_memory_handle, - size_t num_bytes, - bool read_only, - MojoHandle* mojo_wrapper_handle); - - MojoResult PassSharedMemoryHandle( - MojoHandle mojo_handle, - base::SharedMemoryHandle* shared_memory_handle, - size_t* num_bytes, - bool* read_only); - - // Requests that the EDK tear itself down. |callback| will be called once - // the shutdown process is complete. Note that |callback| is always called - // asynchronously on the calling thread if said thread is running a message - // loop, and the calling thread must continue running a MessageLoop at least - // until the callback is called. If there is no running loop, the |callback| - // may be called from any thread. Beware! - void RequestShutdown(const base::Closure& callback); - - MojoResult SetProperty(MojoPropertyType type, const void* value); - - // --------------------------------------------------------------------------- - - // The following methods are essentially implementations of the Mojo Core - // functions of the Mojo API, with the C interface translated to C++ by - // "mojo/edk/embedder/entrypoints.cc". The best way to understand the contract - // of these methods is to look at the header files defining the corresponding - // API functions, referenced below. - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/functions.h": - MojoTimeTicks GetTimeTicksNow(); - MojoResult Close(MojoHandle handle); - MojoResult QueryHandleSignalsState(MojoHandle handle, - MojoHandleSignalsState* signals_state); - MojoResult CreateWatcher(MojoWatcherCallback callback, - MojoHandle* watcher_handle); - MojoResult Watch(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - uintptr_t context); - MojoResult CancelWatch(MojoHandle watcher_handle, uintptr_t context); - MojoResult ArmWatcher(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states); - MojoResult AllocMessage(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message); - MojoResult FreeMessage(MojoMessageHandle message); - MojoResult GetMessageBuffer(MojoMessageHandle message, void** buffer); - MojoResult GetProperty(MojoPropertyType type, void* value); - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/message_pipe.h": - MojoResult CreateMessagePipe( - const MojoCreateMessagePipeOptions* options, - MojoHandle* message_pipe_handle0, - MojoHandle* message_pipe_handle1); - MojoResult WriteMessage(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags); - MojoResult WriteMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags flags); - MojoResult ReadMessage(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags); - MojoResult ReadMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags); - MojoResult FuseMessagePipes(MojoHandle handle0, MojoHandle handle1); - MojoResult NotifyBadMessage(MojoMessageHandle message, - const char* error, - size_t error_num_bytes); - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/data_pipe.h": - MojoResult CreateDataPipe( - const MojoCreateDataPipeOptions* options, - MojoHandle* data_pipe_producer_handle, - MojoHandle* data_pipe_consumer_handle); - MojoResult WriteData(MojoHandle data_pipe_producer_handle, - const void* elements, - uint32_t* num_bytes, - MojoWriteDataFlags flags); - MojoResult BeginWriteData(MojoHandle data_pipe_producer_handle, - void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags); - MojoResult EndWriteData(MojoHandle data_pipe_producer_handle, - uint32_t num_bytes_written); - MojoResult ReadData(MojoHandle data_pipe_consumer_handle, - void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags); - MojoResult BeginReadData(MojoHandle data_pipe_consumer_handle, - const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags); - MojoResult EndReadData(MojoHandle data_pipe_consumer_handle, - uint32_t num_bytes_read); - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/buffer.h": - MojoResult CreateSharedBuffer( - const MojoCreateSharedBufferOptions* options, - uint64_t num_bytes, - MojoHandle* shared_buffer_handle); - MojoResult DuplicateBufferHandle( - MojoHandle buffer_handle, - const MojoDuplicateBufferHandleOptions* options, - MojoHandle* new_buffer_handle); - MojoResult MapBuffer(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - void** buffer, - MojoMapBufferFlags flags); - MojoResult UnmapBuffer(void* buffer); - - // These methods correspond to the API functions defined in - // "mojo/public/c/system/platform_handle.h". - MojoResult WrapPlatformHandle(const MojoPlatformHandle* platform_handle, - MojoHandle* mojo_handle); - MojoResult UnwrapPlatformHandle(MojoHandle mojo_handle, - MojoPlatformHandle* platform_handle); - MojoResult WrapPlatformSharedBufferHandle( - const MojoPlatformHandle* platform_handle, - size_t size, - MojoPlatformSharedBufferHandleFlags flags, - MojoHandle* mojo_handle); - MojoResult UnwrapPlatformSharedBufferHandle( - MojoHandle mojo_handle, - MojoPlatformHandle* platform_handle, - size_t* size, - MojoPlatformSharedBufferHandleFlags* flags); - - void GetActiveHandlesForTest(std::vector* handles); - - private: - // Used to pass ownership of our NodeController over to the IO thread in the - // event that we're torn down before said thread. - static void PassNodeControllerToIOThread( - std::unique_ptr node_controller); - - // Guards node_controller_. - // - // TODO(rockot): Consider removing this. It's only needed because we - // initialize node_controller_ lazily and that may happen on any thread. - // Otherwise it's effectively const and shouldn't need to be guarded. - // - // We can get rid of lazy initialization if we defer Mojo initialization far - // enough that zygotes don't do it. The zygote can't create a NodeController. - base::Lock node_controller_lock_; - - // This is lazily initialized on first access. Always use GetNodeController() - // to access it. - std::unique_ptr node_controller_; - - // The default callback to invoke, if any, when a process error is reported - // but cannot be associated with a specific process. - ProcessErrorCallback default_process_error_callback_; - - base::Lock handles_lock_; - HandleTable handles_; - - base::Lock mapping_table_lock_; // Protects |mapping_table_|. - MappingTable mapping_table_; - - base::Lock property_lock_; - // Properties that can be read using the MojoGetProperty() API. - bool property_sync_call_allowed_ = true; - - DISALLOW_COPY_AND_ASSIGN(Core); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_CORE_H_ diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc deleted file mode 100644 index 7751612..0000000 --- a/mojo/edk/system/core_test_base.cc +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/core_test_base.h" - -#include -#include - -#include - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/configuration.h" -#include "mojo/edk/system/core.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/message_for_transit.h" - -namespace mojo { -namespace edk { -namespace test { - -namespace { - -// MockDispatcher -------------------------------------------------------------- - -class MockDispatcher : public Dispatcher { - public: - static scoped_refptr Create( - CoreTestBase::MockHandleInfo* info) { - return make_scoped_refptr(new MockDispatcher(info)); - } - - // Dispatcher: - Type GetType() const override { return Type::UNKNOWN; } - - MojoResult Close() override { - info_->IncrementCloseCallCount(); - return MOJO_RESULT_OK; - } - - MojoResult WriteMessage( - std::unique_ptr message, - MojoWriteMessageFlags /*flags*/) override { - info_->IncrementWriteMessageCallCount(); - - if (message->num_bytes() > GetConfiguration().max_message_num_bytes) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - if (message->num_handles()) - return MOJO_RESULT_UNIMPLEMENTED; - - return MOJO_RESULT_OK; - } - - MojoResult ReadMessage(std::unique_ptr* message, - uint32_t* num_bytes, - MojoHandle* handle, - uint32_t* num_handles, - MojoReadMessageFlags /*flags*/, - bool ignore_num_bytes) override { - info_->IncrementReadMessageCallCount(); - - if (num_handles) - *num_handles = 1; - - return MOJO_RESULT_OK; - } - - MojoResult WriteData(const void* elements, - uint32_t* num_bytes, - MojoWriteDataFlags flags) override { - info_->IncrementWriteDataCallCount(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult BeginWriteData(void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags) override { - info_->IncrementBeginWriteDataCallCount(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult EndWriteData(uint32_t num_bytes_written) override { - info_->IncrementEndWriteDataCallCount(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult ReadData(void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) override { - info_->IncrementReadDataCallCount(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult BeginReadData(const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags) override { - info_->IncrementBeginReadDataCallCount(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - MojoResult EndReadData(uint32_t num_bytes_read) override { - info_->IncrementEndReadDataCallCount(); - return MOJO_RESULT_UNIMPLEMENTED; - } - - private: - explicit MockDispatcher(CoreTestBase::MockHandleInfo* info) : info_(info) { - CHECK(info_); - info_->IncrementCtorCallCount(); - } - - ~MockDispatcher() override { info_->IncrementDtorCallCount(); } - - CoreTestBase::MockHandleInfo* const info_; - - DISALLOW_COPY_AND_ASSIGN(MockDispatcher); -}; - -} // namespace - -// CoreTestBase ---------------------------------------------------------------- - -CoreTestBase::CoreTestBase() { -} - -CoreTestBase::~CoreTestBase() { -} - -MojoHandle CoreTestBase::CreateMockHandle(CoreTestBase::MockHandleInfo* info) { - scoped_refptr dispatcher = MockDispatcher::Create(info); - return core()->AddDispatcher(dispatcher); -} - -Core* CoreTestBase::core() { - return mojo::edk::internal::g_core; -} - -// CoreTestBase_MockHandleInfo ------------------------------------------------- - -CoreTestBase_MockHandleInfo::CoreTestBase_MockHandleInfo() - : ctor_call_count_(0), - dtor_call_count_(0), - close_call_count_(0), - write_message_call_count_(0), - read_message_call_count_(0), - write_data_call_count_(0), - begin_write_data_call_count_(0), - end_write_data_call_count_(0), - read_data_call_count_(0), - begin_read_data_call_count_(0), - end_read_data_call_count_(0) {} - -CoreTestBase_MockHandleInfo::~CoreTestBase_MockHandleInfo() { -} - -unsigned CoreTestBase_MockHandleInfo::GetCtorCallCount() const { - base::AutoLock locker(lock_); - return ctor_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetDtorCallCount() const { - base::AutoLock locker(lock_); - return dtor_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetCloseCallCount() const { - base::AutoLock locker(lock_); - return close_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetWriteMessageCallCount() const { - base::AutoLock locker(lock_); - return write_message_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetReadMessageCallCount() const { - base::AutoLock locker(lock_); - return read_message_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetWriteDataCallCount() const { - base::AutoLock locker(lock_); - return write_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetBeginWriteDataCallCount() const { - base::AutoLock locker(lock_); - return begin_write_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetEndWriteDataCallCount() const { - base::AutoLock locker(lock_); - return end_write_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetReadDataCallCount() const { - base::AutoLock locker(lock_); - return read_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetBeginReadDataCallCount() const { - base::AutoLock locker(lock_); - return begin_read_data_call_count_; -} - -unsigned CoreTestBase_MockHandleInfo::GetEndReadDataCallCount() const { - base::AutoLock locker(lock_); - return end_read_data_call_count_; -} - -void CoreTestBase_MockHandleInfo::IncrementCtorCallCount() { - base::AutoLock locker(lock_); - ctor_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementDtorCallCount() { - base::AutoLock locker(lock_); - dtor_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementCloseCallCount() { - base::AutoLock locker(lock_); - close_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementWriteMessageCallCount() { - base::AutoLock locker(lock_); - write_message_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementReadMessageCallCount() { - base::AutoLock locker(lock_); - read_message_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementWriteDataCallCount() { - base::AutoLock locker(lock_); - write_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementBeginWriteDataCallCount() { - base::AutoLock locker(lock_); - begin_write_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementEndWriteDataCallCount() { - base::AutoLock locker(lock_); - end_write_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementReadDataCallCount() { - base::AutoLock locker(lock_); - read_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementBeginReadDataCallCount() { - base::AutoLock locker(lock_); - begin_read_data_call_count_++; -} - -void CoreTestBase_MockHandleInfo::IncrementEndReadDataCallCount() { - base::AutoLock locker(lock_); - end_read_data_call_count_++; -} - -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/core_test_base.h b/mojo/edk/system/core_test_base.h deleted file mode 100644 index 3d156e3..0000000 --- a/mojo/edk/system/core_test_base.h +++ /dev/null @@ -1,94 +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_CORE_TEST_BASE_H_ -#define MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_ - -#include - -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/public/c/system/types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { - -class Core; - -namespace test { - -class CoreTestBase_MockHandleInfo; - -class CoreTestBase : public testing::Test { - public: - using MockHandleInfo = CoreTestBase_MockHandleInfo; - - CoreTestBase(); - ~CoreTestBase() override; - - protected: - // |info| must remain alive until the returned handle is closed. - MojoHandle CreateMockHandle(MockHandleInfo* info); - - Core* core(); - - private: - DISALLOW_COPY_AND_ASSIGN(CoreTestBase); -}; - -class CoreTestBase_MockHandleInfo { - public: - CoreTestBase_MockHandleInfo(); - ~CoreTestBase_MockHandleInfo(); - - unsigned GetCtorCallCount() const; - unsigned GetDtorCallCount() const; - unsigned GetCloseCallCount() const; - unsigned GetWriteMessageCallCount() const; - unsigned GetReadMessageCallCount() const; - unsigned GetWriteDataCallCount() const; - unsigned GetBeginWriteDataCallCount() const; - unsigned GetEndWriteDataCallCount() const; - unsigned GetReadDataCallCount() const; - unsigned GetBeginReadDataCallCount() const; - unsigned GetEndReadDataCallCount() const; - - // For use by |MockDispatcher|: - void IncrementCtorCallCount(); - void IncrementDtorCallCount(); - void IncrementCloseCallCount(); - void IncrementWriteMessageCallCount(); - void IncrementReadMessageCallCount(); - void IncrementWriteDataCallCount(); - void IncrementBeginWriteDataCallCount(); - void IncrementEndWriteDataCallCount(); - void IncrementReadDataCallCount(); - void IncrementBeginReadDataCallCount(); - void IncrementEndReadDataCallCount(); - - private: - mutable base::Lock lock_; // Protects the following members. - unsigned ctor_call_count_; - unsigned dtor_call_count_; - unsigned close_call_count_; - unsigned write_message_call_count_; - unsigned read_message_call_count_; - unsigned write_data_call_count_; - unsigned begin_write_data_call_count_; - unsigned end_write_data_call_count_; - unsigned read_data_call_count_; - unsigned begin_read_data_call_count_; - unsigned end_read_data_call_count_; - - DISALLOW_COPY_AND_ASSIGN(CoreTestBase_MockHandleInfo); -}; - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_ diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc deleted file mode 100644 index 0d60b48..0000000 --- a/mojo/edk/system/core_unittest.cc +++ /dev/null @@ -1,971 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/core.h" - -#include - -#include - -#include "base/bind.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/core_test_base.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/public/cpp/system/wait.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -namespace mojo { -namespace edk { -namespace { - -const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u}; -const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u}; -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -using CoreTest = test::CoreTestBase; - -TEST_F(CoreTest, GetTimeTicksNow) { - const MojoTimeTicks start = core()->GetTimeTicksNow(); - ASSERT_NE(static_cast(0), start) - << "GetTimeTicksNow should return nonzero value"; - test::Sleep(test::DeadlineFromMilliseconds(15)); - const MojoTimeTicks finish = core()->GetTimeTicksNow(); - // Allow for some fuzz in sleep. - ASSERT_GE((finish - start), static_cast(8000)) - << "Sleeping should result in increasing time ticks"; -} - -TEST_F(CoreTest, Basic) { - MockHandleInfo info; - - ASSERT_EQ(0u, info.GetCtorCallCount()); - MojoHandle h = CreateMockHandle(&info); - ASSERT_EQ(1u, info.GetCtorCallCount()); - ASSERT_NE(h, MOJO_HANDLE_INVALID); - - ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h, nullptr, 0, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, info.GetWriteMessageCallCount()); - - ASSERT_EQ(0u, info.GetReadMessageCallCount()); - uint32_t num_bytes = 0; - ASSERT_EQ( - MOJO_RESULT_OK, - core()->ReadMessage(h, nullptr, &num_bytes, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, info.GetReadMessageCallCount()); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage(h, nullptr, nullptr, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(2u, info.GetReadMessageCallCount()); - - ASSERT_EQ(0u, info.GetWriteDataCallCount()); - ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->WriteData(h, nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE)); - ASSERT_EQ(1u, info.GetWriteDataCallCount()); - - ASSERT_EQ(0u, info.GetBeginWriteDataCallCount()); - ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->BeginWriteData(h, nullptr, nullptr, - MOJO_WRITE_DATA_FLAG_NONE)); - ASSERT_EQ(1u, info.GetBeginWriteDataCallCount()); - - ASSERT_EQ(0u, info.GetEndWriteDataCallCount()); - ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndWriteData(h, 0)); - ASSERT_EQ(1u, info.GetEndWriteDataCallCount()); - - ASSERT_EQ(0u, info.GetReadDataCallCount()); - ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->ReadData(h, nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE)); - ASSERT_EQ(1u, info.GetReadDataCallCount()); - - ASSERT_EQ(0u, info.GetBeginReadDataCallCount()); - ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, - core()->BeginReadData(h, nullptr, nullptr, - MOJO_READ_DATA_FLAG_NONE)); - ASSERT_EQ(1u, info.GetBeginReadDataCallCount()); - - ASSERT_EQ(0u, info.GetEndReadDataCallCount()); - ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0)); - ASSERT_EQ(1u, info.GetEndReadDataCallCount()); - - ASSERT_EQ(0u, info.GetDtorCallCount()); - ASSERT_EQ(0u, info.GetCloseCallCount()); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h)); - ASSERT_EQ(1u, info.GetCloseCallCount()); - ASSERT_EQ(1u, info.GetDtorCallCount()); -} - -TEST_F(CoreTest, InvalidArguments) { - // |Close()|: - { - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(MOJO_HANDLE_INVALID)); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(10)); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(1000000000)); - - // Test a double-close. - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h)); - ASSERT_EQ(1u, info.GetCloseCallCount()); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h)); - ASSERT_EQ(1u, info.GetCloseCallCount()); - } - - // |CreateMessagePipe()|: Nothing to check (apart from things that cause - // death). - - // |WriteMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(MOJO_HANDLE_INVALID, nullptr, 0, - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID}; - - // Huge handle count (implausibly big on some systems -- more than can be - // stored in a 32-bit address space). - // Note: This may return either |MOJO_RESULT_INVALID_ARGUMENT| or - // |MOJO_RESULT_RESOURCE_EXHAUSTED|, depending on whether it's plausible or - // not. - ASSERT_NE( - MOJO_RESULT_OK, - core()->WriteMessage(h, nullptr, 0, handles, - std::numeric_limits::max(), - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - - // Null |bytes| with non-zero message size. - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, nullptr, 1, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - - // Null |handles| with non-zero handle count. - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, nullptr, 0, nullptr, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - - // Huge handle count (plausibly big). - ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->WriteMessage( - h, nullptr, 0, handles, - std::numeric_limits::max() / sizeof(handles[0]), - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - - // Invalid handle in |handles|. - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, nullptr, 0, handles, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - - // Two invalid handles in |handles|. - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, nullptr, 0, handles, 2, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - - // Can't send a handle over itself. Note that this will also cause |h| to be - // closed. - handles[0] = h; - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, nullptr, 0, handles, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(0u, info.GetWriteMessageCallCount()); - - h = CreateMockHandle(&info); - - MockHandleInfo info2; - - // This is "okay", but |MockDispatcher| doesn't implement it. - handles[0] = CreateMockHandle(&info2); - ASSERT_EQ( - MOJO_RESULT_UNIMPLEMENTED, - core()->WriteMessage(h, nullptr, 0, handles, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, info.GetWriteMessageCallCount()); - - // One of the |handles| is still invalid. - handles[0] = CreateMockHandle(&info2); - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, nullptr, 0, handles, 2, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, info.GetWriteMessageCallCount()); - - // One of the |handles| is the same as |h|. Both handles are closed. - handles[0] = CreateMockHandle(&info2); - handles[1] = h; - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h, nullptr, 0, handles, 2, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, info.GetWriteMessageCallCount()); - - h = CreateMockHandle(&info); - - // Can't send a handle twice in the same message. - handles[0] = CreateMockHandle(&info2); - handles[1] = handles[0]; - ASSERT_EQ( - MOJO_RESULT_BUSY, - core()->WriteMessage(h, nullptr, 0, handles, 2, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, info.GetWriteMessageCallCount()); - - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } - - // |ReadMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadMessage(MOJO_HANDLE_INVALID, nullptr, nullptr, nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); - - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - // Okay. - uint32_t handle_count = 0; - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h, nullptr, nullptr, nullptr, &handle_count, - MOJO_READ_MESSAGE_FLAG_NONE)); - // Checked by |Core|, shouldn't go through to the dispatcher. - ASSERT_EQ(1u, info.GetReadMessageCallCount()); - - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } -} - -// These test invalid arguments that should cause death if we're being paranoid -// about checking arguments (which we would want to do if, e.g., we were in a -// true "kernel" situation, but we might not want to do otherwise for -// performance reasons). Probably blatant errors like passing in null pointers -// (for required pointer arguments) will still cause death, but perhaps not -// predictably. -TEST_F(CoreTest, InvalidArgumentsDeath) { -#if defined(OFFICIAL_BUILD) - const char kMemoryCheckFailedRegex[] = ""; -#else - const char kMemoryCheckFailedRegex[] = "Check failed"; -#endif - - // |CreateMessagePipe()|: - { - MojoHandle h; - ASSERT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(nullptr, nullptr, nullptr), - kMemoryCheckFailedRegex); - ASSERT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(nullptr, &h, nullptr), - kMemoryCheckFailedRegex); - ASSERT_DEATH_IF_SUPPORTED( - core()->CreateMessagePipe(nullptr, nullptr, &h), - kMemoryCheckFailedRegex); - } - - // |ReadMessage()|: - // Only check arguments checked by |Core|, namely |handle|, |handles|, and - // |num_handles|. - { - MockHandleInfo info; - MojoHandle h = CreateMockHandle(&info); - - uint32_t handle_count = 1; - ASSERT_DEATH_IF_SUPPORTED( - core()->ReadMessage(h, nullptr, nullptr, nullptr, &handle_count, - MOJO_READ_MESSAGE_FLAG_NONE), - kMemoryCheckFailedRegex); - - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h)); - } -} - -TEST_F(CoreTest, MessagePipe) { - MojoHandle h[2]; - MojoHandleSignalsState hss[2]; - - ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessagePipe(nullptr, &h[0], &h[1])); - // Should get two distinct, valid handles. - ASSERT_NE(h[0], MOJO_HANDLE_INVALID); - ASSERT_NE(h[1], MOJO_HANDLE_INVALID); - ASSERT_NE(h[0], h[1]); - - // Neither should be readable. - hss[0] = kEmptyMojoHandleSignalsState; - hss[1] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[0], &hss[0])); - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[1], &hss[1])); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - ASSERT_EQ(kAllSignals, hss[0].satisfiable_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals); - ASSERT_EQ(kAllSignals, hss[1].satisfiable_signals); - - // Try to read anyway. - char buffer[1] = {'a'}; - uint32_t buffer_size = 1; - ASSERT_EQ( - MOJO_RESULT_SHOULD_WAIT, - core()->ReadMessage(h[0], buffer, &buffer_size, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - // Check that it left its inputs alone. - ASSERT_EQ('a', buffer[0]); - ASSERT_EQ(1u, buffer_size); - - // Write to |h[1]|. - buffer[0] = 'b'; - ASSERT_EQ( - MOJO_RESULT_OK, - core()->WriteMessage(h[1], buffer, 1, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for |h[0]| to become readable. - EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h[0]), - MOJO_HANDLE_SIGNAL_READABLE, &hss[0])); - - // Read from |h[0]|. - // First, get only the size. - buffer_size = 0; - ASSERT_EQ( - MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->ReadMessage(h[0], nullptr, &buffer_size, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, buffer_size); - // Then actually read it. - buffer[0] = 'c'; - buffer_size = 1; - ASSERT_EQ( - MOJO_RESULT_OK, - core()->ReadMessage(h[0], buffer, &buffer_size, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ('b', buffer[0]); - ASSERT_EQ(1u, buffer_size); - - // |h[0]| should no longer be readable. - hss[0] = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[0], &hss[0])); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals); - ASSERT_EQ(kAllSignals, hss[0].satisfiable_signals); - - // Write to |h[0]|. - buffer[0] = 'd'; - ASSERT_EQ( - MOJO_RESULT_OK, - core()->WriteMessage(h[0], buffer, 1, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Close |h[0]|. - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h[0])); - - // Wait for |h[1]| to learn about the other end's closure. - EXPECT_EQ( - MOJO_RESULT_OK, - mojo::Wait(mojo::Handle(h[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss[1])); - - // Check that |h[1]| is no longer writable (and will never be). - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[1].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[1].satisfiable_signals); - - // Check that |h[1]| is still readable (for the moment). - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[1].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss[1].satisfiable_signals); - - // Discard a message from |h[1]|. - ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - core()->ReadMessage(h[1], nullptr, nullptr, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); - - // |h[1]| is no longer readable (and will never be). - hss[1] = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(h[1], &hss[1])); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[1].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[1].satisfiable_signals); - - // Try writing to |h[1]|. - buffer[0] = 'e'; - ASSERT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - core()->WriteMessage(h[1], buffer, 1, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h[1])); -} - -// Tests passing a message pipe handle. -TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast(sizeof(kHello)); - const char kWorld[] = "world!!!"; - const uint32_t kWorldSize = static_cast(sizeof(kWorld)); - char buffer[100]; - const uint32_t kBufferSize = static_cast(sizeof(buffer)); - uint32_t num_bytes; - MojoHandle handles[10]; - uint32_t num_handles; - MojoHandleSignalsState hss; - MojoHandle h_received; - - MojoHandle h_passing[2]; - ASSERT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(nullptr, &h_passing[0], &h_passing[1])); - - // Make sure that |h_passing[]| work properly. - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], kHello, kHelloSize, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kHelloSize, num_bytes); - ASSERT_STREQ(kHello, buffer); - ASSERT_EQ(0u, num_handles); - - // Make sure that you can't pass either of the message pipe's handles over - // itself. - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h_passing[0], kHello, kHelloSize, - &h_passing[0], 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(nullptr, &h_passing[0], &h_passing[1])); - - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->WriteMessage(h_passing[0], kHello, kHelloSize, - &h_passing[1], 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(nullptr, &h_passing[0], &h_passing[1])); - - MojoHandle h_passed[2]; - ASSERT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(nullptr, &h_passed[0], &h_passed[1])); - - // Make sure that |h_passed[]| work properly. - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passed[0], kHello, kHelloSize, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - ASSERT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passed[1]), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passed[1], buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kHelloSize, num_bytes); - ASSERT_STREQ(kHello, buffer); - ASSERT_EQ(0u, num_handles); - - // Send |h_passed[1]| from |h_passing[0]| to |h_passing[1]|. - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], kWorld, kWorldSize, - &h_passed[1], 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - ASSERT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kWorldSize, num_bytes); - ASSERT_STREQ(kWorld, buffer); - ASSERT_EQ(1u, num_handles); - h_received = handles[0]; - ASSERT_NE(h_received, MOJO_HANDLE_INVALID); - ASSERT_NE(h_received, h_passing[0]); - ASSERT_NE(h_received, h_passing[1]); - ASSERT_NE(h_received, h_passed[0]); - - // Note: We rely on the Mojo system not re-using handle values very often. - ASSERT_NE(h_received, h_passed[1]); - - // |h_passed[1]| should no longer be valid; check that trying to close it - // fails. See above note. - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h_passed[1])); - - // Write to |h_passed[0]|. Should receive on |h_received|. - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passed[0], kHello, kHelloSize, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - ASSERT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_received), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_received, buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kHelloSize, num_bytes); - ASSERT_STREQ(kHello, buffer); - ASSERT_EQ(0u, num_handles); - - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0])); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1])); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h_passed[0])); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h_received)); -} - -TEST_F(CoreTest, DataPipe) { - MojoHandle ph, ch; // p is for producer and c is for consumer. - MojoHandleSignalsState hss; - - ASSERT_EQ(MOJO_RESULT_OK, - core()->CreateDataPipe(nullptr, &ph, &ch)); - // Should get two distinct, valid handles. - ASSERT_NE(ph, MOJO_HANDLE_INVALID); - ASSERT_NE(ch, MOJO_HANDLE_INVALID); - ASSERT_NE(ph, ch); - - // Producer should be never-readable, but already writable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ph, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Consumer should be never-writable, and not yet readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ch, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Write. - signed char elements[2] = {'A', 'B'}; - uint32_t num_bytes = 2u; - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph, elements, &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE)); - ASSERT_EQ(2u, num_bytes); - - // Wait for the data to arrive to the consumer. - EXPECT_EQ(MOJO_RESULT_OK, - mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_READABLE, &hss)); - - // Consumer should now be readable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ch, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Peek one character. - elements[0] = -1; - elements[1] = -1; - num_bytes = 1u; - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadData( - ch, elements, &num_bytes, - MOJO_READ_DATA_FLAG_NONE | MOJO_READ_DATA_FLAG_PEEK)); - ASSERT_EQ('A', elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Read one character. - elements[0] = -1; - elements[1] = -1; - num_bytes = 1u; - ASSERT_EQ(MOJO_RESULT_OK, core()->ReadData(ch, elements, &num_bytes, - MOJO_READ_DATA_FLAG_NONE)); - ASSERT_EQ('A', elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Two-phase write. - void* write_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginWriteData(ph, &write_ptr, &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE)); - // We count on the default options providing a decent buffer size. - ASSERT_GE(num_bytes, 3u); - - // Trying to do a normal write during a two-phase write should fail. - elements[0] = 'X'; - num_bytes = 1u; - ASSERT_EQ(MOJO_RESULT_BUSY, - core()->WriteData(ph, elements, &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE)); - - // Actually write the data, and complete it now. - static_cast(write_ptr)[0] = 'C'; - static_cast(write_ptr)[1] = 'D'; - static_cast(write_ptr)[2] = 'E'; - ASSERT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 3u)); - - // Wait for the data to arrive to the consumer. - ASSERT_EQ(MOJO_RESULT_OK, - mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_READABLE, &hss)); - - // Query how much data we have. - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch, nullptr, &num_bytes, - MOJO_READ_DATA_FLAG_QUERY)); - ASSERT_GE(num_bytes, 1u); - - // Try to query with peek. Should fail. - num_bytes = 0; - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadData(ch, nullptr, &num_bytes, - MOJO_READ_DATA_FLAG_QUERY | MOJO_READ_DATA_FLAG_PEEK)); - ASSERT_EQ(0u, num_bytes); - - // Try to discard ten characters, in all-or-none mode. Should fail. - num_bytes = 10; - ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, - core()->ReadData( - ch, nullptr, &num_bytes, - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // Try to discard two characters, in peek mode. Should fail. - num_bytes = 2; - ASSERT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - core()->ReadData(ch, nullptr, &num_bytes, - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_PEEK)); - - // Discard a character. - num_bytes = 1; - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadData( - ch, nullptr, &num_bytes, - MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // Ensure the 3 bytes were read. - ASSERT_EQ(MOJO_RESULT_OK, - mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_READABLE, &hss)); - - // Try a two-phase read of the remaining three bytes with peek. Should fail. - const void* read_ptr = nullptr; - num_bytes = 3; - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - core()->BeginReadData(ch, &read_ptr, &num_bytes, - MOJO_READ_DATA_FLAG_PEEK)); - - // Read the remaining two characters, in two-phase mode (all-or-none). - num_bytes = 3; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginReadData(ch, &read_ptr, &num_bytes, - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - // Note: Count on still being able to do the contiguous read here. - ASSERT_EQ(3u, num_bytes); - - // Discarding right now should fail. - num_bytes = 1; - ASSERT_EQ(MOJO_RESULT_BUSY, - core()->ReadData(ch, nullptr, &num_bytes, - MOJO_READ_DATA_FLAG_DISCARD)); - - // Actually check our data and end the two-phase read. - ASSERT_EQ('C', static_cast(read_ptr)[0]); - ASSERT_EQ('D', static_cast(read_ptr)[1]); - ASSERT_EQ('E', static_cast(read_ptr)[2]); - ASSERT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 3u)); - - // Consumer should now be no longer readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ch, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // TODO(vtl): More. - - // Close the producer. - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(ph)); - - // Wait for this to get to the consumer. - EXPECT_EQ(MOJO_RESULT_OK, - mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - - // The consumer should now be never-readable. - hss = kFullMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, core()->QueryHandleSignalsState(ch, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(ch)); -} - -// Tests passing data pipe producer and consumer handles. -TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { - const char kHello[] = "hello"; - const uint32_t kHelloSize = static_cast(sizeof(kHello)); - const char kWorld[] = "world!!!"; - const uint32_t kWorldSize = static_cast(sizeof(kWorld)); - char buffer[100]; - const uint32_t kBufferSize = static_cast(sizeof(buffer)); - uint32_t num_bytes; - MojoHandle handles[10]; - uint32_t num_handles; - MojoHandleSignalsState hss; - - MojoHandle h_passing[2]; - ASSERT_EQ(MOJO_RESULT_OK, - core()->CreateMessagePipe(nullptr, &h_passing[0], &h_passing[1])); - - MojoHandle ph, ch; - ASSERT_EQ(MOJO_RESULT_OK, - core()->CreateDataPipe(nullptr, &ph, &ch)); - - // Send |ch| from |h_passing[0]| to |h_passing[1]|. - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], kHello, kHelloSize, &ch, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - ASSERT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kHelloSize, num_bytes); - ASSERT_STREQ(kHello, buffer); - ASSERT_EQ(1u, num_handles); - MojoHandle ch_received = handles[0]; - ASSERT_NE(ch_received, MOJO_HANDLE_INVALID); - ASSERT_NE(ch_received, h_passing[0]); - ASSERT_NE(ch_received, h_passing[1]); - ASSERT_NE(ch_received, ph); - - // Note: We rely on the Mojo system not re-using handle values very often. - ASSERT_NE(ch_received, ch); - - // |ch| should no longer be valid; check that trying to close it fails. See - // above note. - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ch)); - - // Write to |ph|. Should receive on |ch_received|. - num_bytes = kWorldSize; - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph, kWorld, &num_bytes, - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(ch_received), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - num_bytes = kBufferSize; - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch_received, buffer, &num_bytes, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kWorldSize, num_bytes); - ASSERT_STREQ(kWorld, buffer); - - // Now pass |ph| in the same direction. - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], kWorld, kWorldSize, &ph, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - hss = kEmptyMojoHandleSignalsState; - ASSERT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kWorldSize, num_bytes); - ASSERT_STREQ(kWorld, buffer); - ASSERT_EQ(1u, num_handles); - MojoHandle ph_received = handles[0]; - ASSERT_NE(ph_received, MOJO_HANDLE_INVALID); - ASSERT_NE(ph_received, h_passing[0]); - ASSERT_NE(ph_received, h_passing[1]); - ASSERT_NE(ph_received, ch_received); - - // Again, rely on the Mojo system not re-using handle values very often. - ASSERT_NE(ph_received, ph); - - // |ph| should no longer be valid; check that trying to close it fails. See - // above note. - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ph)); - - // Write to |ph_received|. Should receive on |ch_received|. - num_bytes = kHelloSize; - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteData(ph_received, kHello, &num_bytes, - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(ch_received), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - num_bytes = kBufferSize; - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadData(ch_received, buffer, &num_bytes, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kHelloSize, num_bytes); - ASSERT_STREQ(kHello, buffer); - - ph = ph_received; - ph_received = MOJO_HANDLE_INVALID; - ch = ch_received; - ch_received = MOJO_HANDLE_INVALID; - - // Make sure that |ph| can't be sent if it's in a two-phase write. - void* write_ptr = nullptr; - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginWriteData(ph, &write_ptr, &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE)); - ASSERT_GE(num_bytes, 1u); - ASSERT_EQ(MOJO_RESULT_BUSY, - core()->WriteMessage(h_passing[0], kHello, kHelloSize, &ph, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // But |ch| can, even if |ph| is in a two-phase write. - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], kHello, kHelloSize, &ch, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ch = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]), - MOJO_HANDLE_SIGNAL_READABLE)); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kHelloSize, num_bytes); - ASSERT_STREQ(kHello, buffer); - ASSERT_EQ(1u, num_handles); - ch = handles[0]; - ASSERT_NE(ch, MOJO_HANDLE_INVALID); - - // Complete the two-phase write. - static_cast(write_ptr)[0] = 'x'; - ASSERT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 1)); - - // Wait for |ch| to be readable. - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, - mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Make sure that |ch| can't be sent if it's in a two-phase read. - const void* read_ptr = nullptr; - num_bytes = 1; - ASSERT_EQ(MOJO_RESULT_OK, - core()->BeginReadData(ch, &read_ptr, &num_bytes, - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - ASSERT_EQ(MOJO_RESULT_BUSY, - core()->WriteMessage(h_passing[0], kHello, kHelloSize, &ch, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // But |ph| can, even if |ch| is in a two-phase read. - ASSERT_EQ(MOJO_RESULT_OK, - core()->WriteMessage(h_passing[0], kWorld, kWorldSize, &ph, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ph = MOJO_HANDLE_INVALID; - hss = kEmptyMojoHandleSignalsState; - EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]), - MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - num_bytes = kBufferSize; - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - core()->ReadMessage( - h_passing[1], buffer, &num_bytes, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(kWorldSize, num_bytes); - ASSERT_STREQ(kWorld, buffer); - ASSERT_EQ(1u, num_handles); - ph = handles[0]; - ASSERT_NE(ph, MOJO_HANDLE_INVALID); - - // Complete the two-phase read. - ASSERT_EQ('x', static_cast(read_ptr)[0]); - ASSERT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 1)); - - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[0])); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h_passing[1])); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(ph)); - ASSERT_EQ(MOJO_RESULT_OK, core()->Close(ch)); -} - -struct TestAsyncWaiter { - TestAsyncWaiter() : result(MOJO_RESULT_UNKNOWN) {} - - void Awake(MojoResult r) { result = r; } - - MojoResult result; -}; - -// TODO(vtl): Test |DuplicateBufferHandle()| and |MapBuffer()|. - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/mojo/edk/system/data_pipe_consumer_dispatcher.cc deleted file mode 100644 index f338732..0000000 --- a/mojo/edk/system/data_pipe_consumer_dispatcher.cc +++ /dev/null @@ -1,562 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/data_pipe_consumer_dispatcher.h" - -#include -#include - -#include -#include -#include - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/core.h" -#include "mojo/edk/system/data_pipe_control_message.h" -#include "mojo/edk/system/node_controller.h" -#include "mojo/edk/system/ports_message.h" -#include "mojo/edk/system/request_context.h" -#include "mojo/public/c/system/data_pipe.h" - -namespace mojo { -namespace edk { - -namespace { - -const uint8_t kFlagPeerClosed = 0x01; - -#pragma pack(push, 1) - -struct SerializedState { - MojoCreateDataPipeOptions options; - uint64_t pipe_id; - uint32_t read_offset; - uint32_t bytes_available; - uint8_t flags; - char padding[7]; -}; - -static_assert(sizeof(SerializedState) % 8 == 0, - "Invalid SerializedState size."); - -#pragma pack(pop) - -} // namespace - -// A PortObserver which forwards to a DataPipeConsumerDispatcher. This owns a -// reference to the dispatcher to ensure it lives as long as the observed port. -class DataPipeConsumerDispatcher::PortObserverThunk - : public NodeController::PortObserver { - public: - explicit PortObserverThunk( - scoped_refptr dispatcher) - : dispatcher_(dispatcher) {} - - private: - ~PortObserverThunk() override {} - - // NodeController::PortObserver: - void OnPortStatusChanged() override { dispatcher_->OnPortStatusChanged(); } - - scoped_refptr dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(PortObserverThunk); -}; - -DataPipeConsumerDispatcher::DataPipeConsumerDispatcher( - NodeController* node_controller, - const ports::PortRef& control_port, - scoped_refptr shared_ring_buffer, - const MojoCreateDataPipeOptions& options, - bool initialized, - uint64_t pipe_id) - : options_(options), - node_controller_(node_controller), - control_port_(control_port), - pipe_id_(pipe_id), - watchers_(this), - shared_ring_buffer_(shared_ring_buffer) { - if (initialized) { - base::AutoLock lock(lock_); - InitializeNoLock(); - } -} - -Dispatcher::Type DataPipeConsumerDispatcher::GetType() const { - return Type::DATA_PIPE_CONSUMER; -} - -MojoResult DataPipeConsumerDispatcher::Close() { - base::AutoLock lock(lock_); - DVLOG(1) << "Closing data pipe consumer " << pipe_id_; - return CloseNoLock(); -} - -MojoResult DataPipeConsumerDispatcher::ReadData(void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) { - base::AutoLock lock(lock_); - - if (!shared_ring_buffer_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (in_two_phase_read_) - return MOJO_RESULT_BUSY; - - const bool had_new_data = new_data_available_; - new_data_available_ = false; - - if ((flags & MOJO_READ_DATA_FLAG_QUERY)) { - if ((flags & MOJO_READ_DATA_FLAG_PEEK) || - (flags & MOJO_READ_DATA_FLAG_DISCARD)) - return MOJO_RESULT_INVALID_ARGUMENT; - DCHECK(!(flags & MOJO_READ_DATA_FLAG_DISCARD)); // Handled above. - DVLOG_IF(2, elements) - << "Query mode: ignoring non-null |elements|"; - *num_bytes = static_cast(bytes_available_); - - if (had_new_data) - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - return MOJO_RESULT_OK; - } - - bool discard = false; - if ((flags & MOJO_READ_DATA_FLAG_DISCARD)) { - // These flags are mutally exclusive. - if (flags & MOJO_READ_DATA_FLAG_PEEK) - return MOJO_RESULT_INVALID_ARGUMENT; - DVLOG_IF(2, elements) - << "Discard mode: ignoring non-null |elements|"; - discard = true; - } - - uint32_t max_num_bytes_to_read = *num_bytes; - if (max_num_bytes_to_read % options_.element_num_bytes != 0) - return MOJO_RESULT_INVALID_ARGUMENT; - - bool all_or_none = flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE; - uint32_t min_num_bytes_to_read = - all_or_none ? max_num_bytes_to_read : 0; - - if (min_num_bytes_to_read > bytes_available_) { - if (had_new_data) - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - return peer_closed_ ? MOJO_RESULT_FAILED_PRECONDITION - : MOJO_RESULT_OUT_OF_RANGE; - } - - uint32_t bytes_to_read = std::min(max_num_bytes_to_read, bytes_available_); - if (bytes_to_read == 0) { - if (had_new_data) - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - return peer_closed_ ? MOJO_RESULT_FAILED_PRECONDITION - : MOJO_RESULT_SHOULD_WAIT; - } - - if (!discard) { - uint8_t* data = static_cast(ring_buffer_mapping_->GetBase()); - CHECK(data); - - uint8_t* destination = static_cast(elements); - CHECK(destination); - - DCHECK_LE(read_offset_, options_.capacity_num_bytes); - uint32_t tail_bytes_to_copy = - std::min(options_.capacity_num_bytes - read_offset_, bytes_to_read); - uint32_t head_bytes_to_copy = bytes_to_read - tail_bytes_to_copy; - if (tail_bytes_to_copy > 0) - memcpy(destination, data + read_offset_, tail_bytes_to_copy); - if (head_bytes_to_copy > 0) - memcpy(destination + tail_bytes_to_copy, data, head_bytes_to_copy); - } - *num_bytes = bytes_to_read; - - bool peek = !!(flags & MOJO_READ_DATA_FLAG_PEEK); - if (discard || !peek) { - read_offset_ = (read_offset_ + bytes_to_read) % options_.capacity_num_bytes; - bytes_available_ -= bytes_to_read; - - base::AutoUnlock unlock(lock_); - NotifyRead(bytes_to_read); - } - - // We may have just read the last available data and thus changed the signals - // state. - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - - return MOJO_RESULT_OK; -} - -MojoResult DataPipeConsumerDispatcher::BeginReadData(const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags) { - base::AutoLock lock(lock_); - if (!shared_ring_buffer_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (in_two_phase_read_) - return MOJO_RESULT_BUSY; - - // These flags may not be used in two-phase mode. - if ((flags & MOJO_READ_DATA_FLAG_DISCARD) || - (flags & MOJO_READ_DATA_FLAG_QUERY) || - (flags & MOJO_READ_DATA_FLAG_PEEK)) - return MOJO_RESULT_INVALID_ARGUMENT; - - const bool had_new_data = new_data_available_; - new_data_available_ = false; - - if (bytes_available_ == 0) { - if (had_new_data) - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - return peer_closed_ ? MOJO_RESULT_FAILED_PRECONDITION - : MOJO_RESULT_SHOULD_WAIT; - } - - DCHECK_LT(read_offset_, options_.capacity_num_bytes); - uint32_t bytes_to_read = std::min(bytes_available_, - options_.capacity_num_bytes - read_offset_); - - CHECK(ring_buffer_mapping_); - uint8_t* data = static_cast(ring_buffer_mapping_->GetBase()); - CHECK(data); - - in_two_phase_read_ = true; - *buffer = data + read_offset_; - *buffer_num_bytes = bytes_to_read; - two_phase_max_bytes_read_ = bytes_to_read; - - if (had_new_data) - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - - return MOJO_RESULT_OK; -} - -MojoResult DataPipeConsumerDispatcher::EndReadData(uint32_t num_bytes_read) { - base::AutoLock lock(lock_); - if (!in_two_phase_read_) - return MOJO_RESULT_FAILED_PRECONDITION; - - if (in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - CHECK(shared_ring_buffer_); - - MojoResult rv; - if (num_bytes_read > two_phase_max_bytes_read_ || - num_bytes_read % options_.element_num_bytes != 0) { - rv = MOJO_RESULT_INVALID_ARGUMENT; - } else { - rv = MOJO_RESULT_OK; - read_offset_ = - (read_offset_ + num_bytes_read) % options_.capacity_num_bytes; - - DCHECK_GE(bytes_available_, num_bytes_read); - bytes_available_ -= num_bytes_read; - - base::AutoUnlock unlock(lock_); - NotifyRead(num_bytes_read); - } - - in_two_phase_read_ = false; - two_phase_max_bytes_read_ = 0; - - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - - return rv; -} - -HandleSignalsState DataPipeConsumerDispatcher::GetHandleSignalsState() const { - base::AutoLock lock(lock_); - return GetHandleSignalsStateNoLock(); -} - -MojoResult DataPipeConsumerDispatcher::AddWatcherRef( - const scoped_refptr& watcher, - uintptr_t context) { - base::AutoLock lock(lock_); - if (is_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - return watchers_.Add(watcher, context, GetHandleSignalsStateNoLock()); -} - -MojoResult DataPipeConsumerDispatcher::RemoveWatcherRef( - WatcherDispatcher* watcher, - uintptr_t context) { - base::AutoLock lock(lock_); - if (is_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - return watchers_.Remove(watcher, context); -} - -void DataPipeConsumerDispatcher::StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_handles) { - base::AutoLock lock(lock_); - DCHECK(in_transit_); - *num_bytes = static_cast(sizeof(SerializedState)); - *num_ports = 1; - *num_handles = 1; -} - -bool DataPipeConsumerDispatcher::EndSerialize( - void* destination, - ports::PortName* ports, - PlatformHandle* platform_handles) { - SerializedState* state = static_cast(destination); - memcpy(&state->options, &options_, sizeof(MojoCreateDataPipeOptions)); - memset(state->padding, 0, sizeof(state->padding)); - - base::AutoLock lock(lock_); - DCHECK(in_transit_); - state->pipe_id = pipe_id_; - state->read_offset = read_offset_; - state->bytes_available = bytes_available_; - state->flags = peer_closed_ ? kFlagPeerClosed : 0; - - ports[0] = control_port_.name(); - - buffer_handle_for_transit_ = shared_ring_buffer_->DuplicatePlatformHandle(); - platform_handles[0] = buffer_handle_for_transit_.get(); - - return true; -} - -bool DataPipeConsumerDispatcher::BeginTransit() { - base::AutoLock lock(lock_); - if (in_transit_) - return false; - in_transit_ = !in_two_phase_read_; - return in_transit_; -} - -void DataPipeConsumerDispatcher::CompleteTransitAndClose() { - node_controller_->SetPortObserver(control_port_, nullptr); - - base::AutoLock lock(lock_); - DCHECK(in_transit_); - in_transit_ = false; - transferred_ = true; - ignore_result(buffer_handle_for_transit_.release()); - CloseNoLock(); -} - -void DataPipeConsumerDispatcher::CancelTransit() { - base::AutoLock lock(lock_); - DCHECK(in_transit_); - in_transit_ = false; - buffer_handle_for_transit_.reset(); - UpdateSignalsStateNoLock(); -} - -// static -scoped_refptr -DataPipeConsumerDispatcher::Deserialize(const void* data, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* handles, - size_t num_handles) { - if (num_ports != 1 || num_handles != 1 || - num_bytes != sizeof(SerializedState)) { - return nullptr; - } - - const SerializedState* state = static_cast(data); - - NodeController* node_controller = internal::g_core->GetNodeController(); - ports::PortRef port; - if (node_controller->node()->GetPort(ports[0], &port) != ports::OK) - return nullptr; - - PlatformHandle buffer_handle; - std::swap(buffer_handle, handles[0]); - scoped_refptr ring_buffer = - PlatformSharedBuffer::CreateFromPlatformHandle( - state->options.capacity_num_bytes, - false /* read_only */, - ScopedPlatformHandle(buffer_handle)); - if (!ring_buffer) { - DLOG(ERROR) << "Failed to deserialize shared buffer handle."; - return nullptr; - } - - scoped_refptr dispatcher = - new DataPipeConsumerDispatcher(node_controller, port, ring_buffer, - state->options, false /* initialized */, - state->pipe_id); - - { - base::AutoLock lock(dispatcher->lock_); - dispatcher->read_offset_ = state->read_offset; - dispatcher->bytes_available_ = state->bytes_available; - dispatcher->new_data_available_ = state->bytes_available > 0; - dispatcher->peer_closed_ = state->flags & kFlagPeerClosed; - dispatcher->InitializeNoLock(); - dispatcher->UpdateSignalsStateNoLock(); - } - - return dispatcher; -} - -DataPipeConsumerDispatcher::~DataPipeConsumerDispatcher() { - DCHECK(is_closed_ && !shared_ring_buffer_ && !ring_buffer_mapping_ && - !in_transit_); -} - -void DataPipeConsumerDispatcher::InitializeNoLock() { - lock_.AssertAcquired(); - - if (shared_ring_buffer_) { - DCHECK(!ring_buffer_mapping_); - ring_buffer_mapping_ = - shared_ring_buffer_->Map(0, options_.capacity_num_bytes); - if (!ring_buffer_mapping_) { - DLOG(ERROR) << "Failed to map shared buffer."; - shared_ring_buffer_ = nullptr; - } - } - - base::AutoUnlock unlock(lock_); - node_controller_->SetPortObserver( - control_port_, - make_scoped_refptr(new PortObserverThunk(this))); -} - -MojoResult DataPipeConsumerDispatcher::CloseNoLock() { - lock_.AssertAcquired(); - if (is_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - is_closed_ = true; - ring_buffer_mapping_.reset(); - shared_ring_buffer_ = nullptr; - - watchers_.NotifyClosed(); - if (!transferred_) { - base::AutoUnlock unlock(lock_); - node_controller_->ClosePort(control_port_); - } - - return MOJO_RESULT_OK; -} - -HandleSignalsState -DataPipeConsumerDispatcher::GetHandleSignalsStateNoLock() const { - lock_.AssertAcquired(); - - HandleSignalsState rv; - if (shared_ring_buffer_ && bytes_available_) { - if (!in_two_phase_read_) { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE; - if (new_data_available_) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE; - } - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } else if (!peer_closed_ && shared_ring_buffer_) { - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } - - if (shared_ring_buffer_) { - if (new_data_available_ || !peer_closed_) - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE; - } - - if (peer_closed_) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - - return rv; -} - -void DataPipeConsumerDispatcher::NotifyRead(uint32_t num_bytes) { - DVLOG(1) << "Data pipe consumer " << pipe_id_ << " notifying peer: " - << num_bytes << " bytes read. [control_port=" - << control_port_.name() << "]"; - - SendDataPipeControlMessage(node_controller_, control_port_, - DataPipeCommand::DATA_WAS_READ, num_bytes); -} - -void DataPipeConsumerDispatcher::OnPortStatusChanged() { - DCHECK(RequestContext::current()); - - base::AutoLock lock(lock_); - - // We stop observing the control port as soon it's transferred, but this can - // race with events which are raised right before that happens. This is fine - // to ignore. - if (transferred_) - return; - - DVLOG(1) << "Control port status changed for data pipe producer " << pipe_id_; - - UpdateSignalsStateNoLock(); -} - -void DataPipeConsumerDispatcher::UpdateSignalsStateNoLock() { - lock_.AssertAcquired(); - - bool was_peer_closed = peer_closed_; - size_t previous_bytes_available = bytes_available_; - - ports::PortStatus port_status; - int rv = node_controller_->node()->GetStatus(control_port_, &port_status); - if (rv != ports::OK || !port_status.receiving_messages) { - DVLOG(1) << "Data pipe consumer " << pipe_id_ << " is aware of peer closure" - << " [control_port=" << control_port_.name() << "]"; - peer_closed_ = true; - } else if (rv == ports::OK && port_status.has_messages && !in_transit_) { - ports::ScopedMessage message; - do { - int rv = node_controller_->node()->GetMessage( - control_port_, &message, nullptr); - if (rv != ports::OK) - peer_closed_ = true; - if (message) { - if (message->num_payload_bytes() < sizeof(DataPipeControlMessage)) { - peer_closed_ = true; - break; - } - - const DataPipeControlMessage* m = - static_cast( - message->payload_bytes()); - - if (m->command != DataPipeCommand::DATA_WAS_WRITTEN) { - DLOG(ERROR) << "Unexpected control message from producer."; - peer_closed_ = true; - break; - } - - if (static_cast(bytes_available_) + m->num_bytes > - options_.capacity_num_bytes) { - DLOG(ERROR) << "Producer claims to have written too many bytes."; - peer_closed_ = true; - break; - } - - DVLOG(1) << "Data pipe consumer " << pipe_id_ << " is aware that " - << m->num_bytes << " bytes were written. [control_port=" - << control_port_.name() << "]"; - - bytes_available_ += m->num_bytes; - } - } while (message); - } - - bool has_new_data = bytes_available_ != previous_bytes_available; - if (has_new_data) - new_data_available_ = true; - - if (peer_closed_ != was_peer_closed || has_new_data) - watchers_.NotifyState(GetHandleSignalsStateNoLock()); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.h b/mojo/edk/system/data_pipe_consumer_dispatcher.h deleted file mode 100644 index 120c7a3..0000000 --- a/mojo/edk/system/data_pipe_consumer_dispatcher.h +++ /dev/null @@ -1,123 +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_DATA_PIPE_CONSUMER_DISPATCHER_H_ -#define MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_ - -#include -#include - -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/ports/port_ref.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/edk/system/watcher_set.h" - -namespace mojo { -namespace edk { - -class NodeController; - -// This is the Dispatcher implementation for the consumer handle for data -// pipes created by the Mojo primitive MojoCreateDataPipe(). This class is -// thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final - : public Dispatcher { - public: - DataPipeConsumerDispatcher( - NodeController* node_controller, - const ports::PortRef& control_port, - scoped_refptr shared_ring_buffer, - const MojoCreateDataPipeOptions& options, - bool initialized, - uint64_t pipe_id); - - // Dispatcher: - Type GetType() const override; - MojoResult Close() override; - MojoResult ReadData(void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) override; - MojoResult BeginReadData(const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags) override; - MojoResult EndReadData(uint32_t num_bytes_read) override; - HandleSignalsState GetHandleSignalsState() const override; - MojoResult AddWatcherRef(const scoped_refptr& watcher, - uintptr_t context) override; - MojoResult RemoveWatcherRef(WatcherDispatcher* watcher, - uintptr_t context) override; - void StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_handles) override; - bool EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) override; - bool BeginTransit() override; - void CompleteTransitAndClose() override; - void CancelTransit() override; - - static scoped_refptr - Deserialize(const void* data, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* handles, - size_t num_handles); - - private: - class PortObserverThunk; - friend class PortObserverThunk; - - ~DataPipeConsumerDispatcher() override; - - void InitializeNoLock(); - MojoResult CloseNoLock(); - HandleSignalsState GetHandleSignalsStateNoLock() const; - void NotifyRead(uint32_t num_bytes); - void OnPortStatusChanged(); - void UpdateSignalsStateNoLock(); - - const MojoCreateDataPipeOptions options_; - NodeController* const node_controller_; - const ports::PortRef control_port_; - const uint64_t pipe_id_; - - // Guards access to the fields below. - mutable base::Lock lock_; - - WatcherSet watchers_; - - scoped_refptr shared_ring_buffer_; - std::unique_ptr ring_buffer_mapping_; - ScopedPlatformHandle buffer_handle_for_transit_; - - bool in_two_phase_read_ = false; - uint32_t two_phase_max_bytes_read_ = 0; - - bool in_transit_ = false; - bool is_closed_ = false; - bool peer_closed_ = false; - bool transferred_ = false; - - uint32_t read_offset_ = 0; - uint32_t bytes_available_ = 0; - - // Indicates whether any new data is available since the last read attempt. - bool new_data_available_ = false; - - DISALLOW_COPY_AND_ASSIGN(DataPipeConsumerDispatcher); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_ diff --git a/mojo/edk/system/data_pipe_control_message.cc b/mojo/edk/system/data_pipe_control_message.cc deleted file mode 100644 index 23873b8..0000000 --- a/mojo/edk/system/data_pipe_control_message.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/data_pipe_control_message.h" - -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/system/node_controller.h" -#include "mojo/edk/system/ports_message.h" - -namespace mojo { -namespace edk { - -void SendDataPipeControlMessage(NodeController* node_controller, - const ports::PortRef& port, - DataPipeCommand command, - uint32_t num_bytes) { - std::unique_ptr message = - PortsMessage::NewUserMessage(sizeof(DataPipeControlMessage), 0, 0); - CHECK(message); - - DataPipeControlMessage* data = - static_cast(message->mutable_payload_bytes()); - data->command = command; - data->num_bytes = num_bytes; - - int rv = node_controller->SendMessage(port, std::move(message)); - if (rv != ports::OK && rv != ports::ERROR_PORT_PEER_CLOSED) { - DLOG(ERROR) << "Unexpected failure sending data pipe control message: " - << rv; - } -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/data_pipe_control_message.h b/mojo/edk/system/data_pipe_control_message.h deleted file mode 100644 index ec84ea3..0000000 --- a/mojo/edk/system/data_pipe_control_message.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_DATA_PIPE_CONTROL_MESSAGE_H_ -#define MOJO_EDK_SYSTEM_DATA_PIPE_CONTROL_MESSAGE_H_ - -#include - -#include - -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/ports/port_ref.h" -#include "mojo/public/c/system/macros.h" - -namespace mojo { -namespace edk { - -class NodeController; - -enum DataPipeCommand : uint32_t { - // Signal to the consumer that new data is available. - DATA_WAS_WRITTEN, - - // Signal to the producer that data has been consumed. - DATA_WAS_READ, -}; - -// Message header for messages sent over a data pipe control port. -struct MOJO_ALIGNAS(8) DataPipeControlMessage { - DataPipeCommand command; - uint32_t num_bytes; -}; - -void SendDataPipeControlMessage(NodeController* node_controller, - const ports::PortRef& port, - DataPipeCommand command, - uint32_t num_bytes); - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_DATA_PIPE_CONTROL_MESSAGE_H_ diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.cc b/mojo/edk/system/data_pipe_producer_dispatcher.cc deleted file mode 100644 index b0102a6..0000000 --- a/mojo/edk/system/data_pipe_producer_dispatcher.cc +++ /dev/null @@ -1,507 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/data_pipe_producer_dispatcher.h" - -#include -#include - -#include - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/configuration.h" -#include "mojo/edk/system/core.h" -#include "mojo/edk/system/data_pipe_control_message.h" -#include "mojo/edk/system/node_controller.h" -#include "mojo/edk/system/ports_message.h" -#include "mojo/edk/system/request_context.h" -#include "mojo/public/c/system/data_pipe.h" - -namespace mojo { -namespace edk { - -namespace { - -const uint8_t kFlagPeerClosed = 0x01; - -#pragma pack(push, 1) - -struct SerializedState { - MojoCreateDataPipeOptions options; - uint64_t pipe_id; - uint32_t write_offset; - uint32_t available_capacity; - uint8_t flags; - char padding[7]; -}; - -static_assert(sizeof(SerializedState) % 8 == 0, - "Invalid SerializedState size."); - -#pragma pack(pop) - -} // namespace - -// A PortObserver which forwards to a DataPipeProducerDispatcher. This owns a -// reference to the dispatcher to ensure it lives as long as the observed port. -class DataPipeProducerDispatcher::PortObserverThunk - : public NodeController::PortObserver { - public: - explicit PortObserverThunk( - scoped_refptr dispatcher) - : dispatcher_(dispatcher) {} - - private: - ~PortObserverThunk() override {} - - // NodeController::PortObserver: - void OnPortStatusChanged() override { dispatcher_->OnPortStatusChanged(); } - - scoped_refptr dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(PortObserverThunk); -}; - -DataPipeProducerDispatcher::DataPipeProducerDispatcher( - NodeController* node_controller, - const ports::PortRef& control_port, - scoped_refptr shared_ring_buffer, - const MojoCreateDataPipeOptions& options, - bool initialized, - uint64_t pipe_id) - : options_(options), - node_controller_(node_controller), - control_port_(control_port), - pipe_id_(pipe_id), - watchers_(this), - shared_ring_buffer_(shared_ring_buffer), - available_capacity_(options_.capacity_num_bytes) { - if (initialized) { - base::AutoLock lock(lock_); - InitializeNoLock(); - } -} - -Dispatcher::Type DataPipeProducerDispatcher::GetType() const { - return Type::DATA_PIPE_PRODUCER; -} - -MojoResult DataPipeProducerDispatcher::Close() { - base::AutoLock lock(lock_); - DVLOG(1) << "Closing data pipe producer " << pipe_id_; - return CloseNoLock(); -} - -MojoResult DataPipeProducerDispatcher::WriteData(const void* elements, - uint32_t* num_bytes, - MojoWriteDataFlags flags) { - base::AutoLock lock(lock_); - if (!shared_ring_buffer_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (in_two_phase_write_) - return MOJO_RESULT_BUSY; - - if (peer_closed_) - return MOJO_RESULT_FAILED_PRECONDITION; - - if (*num_bytes % options_.element_num_bytes != 0) - return MOJO_RESULT_INVALID_ARGUMENT; - if (*num_bytes == 0) - return MOJO_RESULT_OK; // Nothing to do. - - if ((flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) && - (*num_bytes > available_capacity_)) { - // Don't return "should wait" since you can't wait for a specified amount of - // data. - return MOJO_RESULT_OUT_OF_RANGE; - } - - DCHECK_LE(available_capacity_, options_.capacity_num_bytes); - uint32_t num_bytes_to_write = std::min(*num_bytes, available_capacity_); - if (num_bytes_to_write == 0) - return MOJO_RESULT_SHOULD_WAIT; - - *num_bytes = num_bytes_to_write; - - CHECK(ring_buffer_mapping_); - uint8_t* data = static_cast(ring_buffer_mapping_->GetBase()); - CHECK(data); - - const uint8_t* source = static_cast(elements); - CHECK(source); - - DCHECK_LE(write_offset_, options_.capacity_num_bytes); - uint32_t tail_bytes_to_write = - std::min(options_.capacity_num_bytes - write_offset_, - num_bytes_to_write); - uint32_t head_bytes_to_write = num_bytes_to_write - tail_bytes_to_write; - - DCHECK_GT(tail_bytes_to_write, 0u); - memcpy(data + write_offset_, source, tail_bytes_to_write); - if (head_bytes_to_write > 0) - memcpy(data, source + tail_bytes_to_write, head_bytes_to_write); - - DCHECK_LE(num_bytes_to_write, available_capacity_); - available_capacity_ -= num_bytes_to_write; - write_offset_ = (write_offset_ + num_bytes_to_write) % - options_.capacity_num_bytes; - - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - - base::AutoUnlock unlock(lock_); - NotifyWrite(num_bytes_to_write); - - return MOJO_RESULT_OK; -} - -MojoResult DataPipeProducerDispatcher::BeginWriteData( - void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags) { - base::AutoLock lock(lock_); - if (!shared_ring_buffer_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - // These flags may not be used in two-phase mode. - if (flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (in_two_phase_write_) - return MOJO_RESULT_BUSY; - if (peer_closed_) - return MOJO_RESULT_FAILED_PRECONDITION; - - if (available_capacity_ == 0) { - return peer_closed_ ? MOJO_RESULT_FAILED_PRECONDITION - : MOJO_RESULT_SHOULD_WAIT; - } - - in_two_phase_write_ = true; - *buffer_num_bytes = std::min(options_.capacity_num_bytes - write_offset_, - available_capacity_); - DCHECK_GT(*buffer_num_bytes, 0u); - - CHECK(ring_buffer_mapping_); - uint8_t* data = static_cast(ring_buffer_mapping_->GetBase()); - *buffer = data + write_offset_; - - return MOJO_RESULT_OK; -} - -MojoResult DataPipeProducerDispatcher::EndWriteData( - uint32_t num_bytes_written) { - base::AutoLock lock(lock_); - if (is_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!in_two_phase_write_) - return MOJO_RESULT_FAILED_PRECONDITION; - - DCHECK(shared_ring_buffer_); - DCHECK(ring_buffer_mapping_); - - // Note: Allow successful completion of the two-phase write even if the other - // side has been closed. - MojoResult rv = MOJO_RESULT_OK; - if (num_bytes_written > available_capacity_ || - num_bytes_written % options_.element_num_bytes != 0 || - write_offset_ + num_bytes_written > options_.capacity_num_bytes) { - rv = MOJO_RESULT_INVALID_ARGUMENT; - } else { - DCHECK_LE(num_bytes_written + write_offset_, options_.capacity_num_bytes); - available_capacity_ -= num_bytes_written; - write_offset_ = (write_offset_ + num_bytes_written) % - options_.capacity_num_bytes; - - base::AutoUnlock unlock(lock_); - NotifyWrite(num_bytes_written); - } - - in_two_phase_write_ = false; - - // If we're now writable, we *became* writable (since we weren't writable - // during the two-phase write), so notify watchers. - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - - return rv; -} - -HandleSignalsState DataPipeProducerDispatcher::GetHandleSignalsState() const { - base::AutoLock lock(lock_); - return GetHandleSignalsStateNoLock(); -} - -MojoResult DataPipeProducerDispatcher::AddWatcherRef( - const scoped_refptr& watcher, - uintptr_t context) { - base::AutoLock lock(lock_); - if (is_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - return watchers_.Add(watcher, context, GetHandleSignalsStateNoLock()); -} - -MojoResult DataPipeProducerDispatcher::RemoveWatcherRef( - WatcherDispatcher* watcher, - uintptr_t context) { - base::AutoLock lock(lock_); - if (is_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - return watchers_.Remove(watcher, context); -} - -void DataPipeProducerDispatcher::StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_handles) { - base::AutoLock lock(lock_); - DCHECK(in_transit_); - *num_bytes = sizeof(SerializedState); - *num_ports = 1; - *num_handles = 1; -} - -bool DataPipeProducerDispatcher::EndSerialize( - void* destination, - ports::PortName* ports, - PlatformHandle* platform_handles) { - SerializedState* state = static_cast(destination); - memcpy(&state->options, &options_, sizeof(MojoCreateDataPipeOptions)); - memset(state->padding, 0, sizeof(state->padding)); - - base::AutoLock lock(lock_); - DCHECK(in_transit_); - state->pipe_id = pipe_id_; - state->write_offset = write_offset_; - state->available_capacity = available_capacity_; - state->flags = peer_closed_ ? kFlagPeerClosed : 0; - - ports[0] = control_port_.name(); - - buffer_handle_for_transit_ = shared_ring_buffer_->DuplicatePlatformHandle(); - platform_handles[0] = buffer_handle_for_transit_.get(); - - return true; -} - -bool DataPipeProducerDispatcher::BeginTransit() { - base::AutoLock lock(lock_); - if (in_transit_) - return false; - in_transit_ = !in_two_phase_write_; - return in_transit_; -} - -void DataPipeProducerDispatcher::CompleteTransitAndClose() { - node_controller_->SetPortObserver(control_port_, nullptr); - - base::AutoLock lock(lock_); - DCHECK(in_transit_); - transferred_ = true; - in_transit_ = false; - ignore_result(buffer_handle_for_transit_.release()); - CloseNoLock(); -} - -void DataPipeProducerDispatcher::CancelTransit() { - base::AutoLock lock(lock_); - DCHECK(in_transit_); - in_transit_ = false; - buffer_handle_for_transit_.reset(); - - HandleSignalsState state = GetHandleSignalsStateNoLock(); - watchers_.NotifyState(state); -} - -// static -scoped_refptr -DataPipeProducerDispatcher::Deserialize(const void* data, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* handles, - size_t num_handles) { - if (num_ports != 1 || num_handles != 1 || - num_bytes != sizeof(SerializedState)) { - return nullptr; - } - - const SerializedState* state = static_cast(data); - - NodeController* node_controller = internal::g_core->GetNodeController(); - ports::PortRef port; - if (node_controller->node()->GetPort(ports[0], &port) != ports::OK) - return nullptr; - - PlatformHandle buffer_handle; - std::swap(buffer_handle, handles[0]); - scoped_refptr ring_buffer = - PlatformSharedBuffer::CreateFromPlatformHandle( - state->options.capacity_num_bytes, - false /* read_only */, - ScopedPlatformHandle(buffer_handle)); - if (!ring_buffer) { - DLOG(ERROR) << "Failed to deserialize shared buffer handle."; - return nullptr; - } - - scoped_refptr dispatcher = - new DataPipeProducerDispatcher(node_controller, port, ring_buffer, - state->options, false /* initialized */, - state->pipe_id); - - { - base::AutoLock lock(dispatcher->lock_); - dispatcher->write_offset_ = state->write_offset; - dispatcher->available_capacity_ = state->available_capacity; - dispatcher->peer_closed_ = state->flags & kFlagPeerClosed; - dispatcher->InitializeNoLock(); - dispatcher->UpdateSignalsStateNoLock(); - } - - return dispatcher; -} - -DataPipeProducerDispatcher::~DataPipeProducerDispatcher() { - DCHECK(is_closed_ && !in_transit_ && !shared_ring_buffer_ && - !ring_buffer_mapping_); -} - -void DataPipeProducerDispatcher::InitializeNoLock() { - lock_.AssertAcquired(); - - if (shared_ring_buffer_) { - ring_buffer_mapping_ = - shared_ring_buffer_->Map(0, options_.capacity_num_bytes); - if (!ring_buffer_mapping_) { - DLOG(ERROR) << "Failed to map shared buffer."; - shared_ring_buffer_ = nullptr; - } - } - - base::AutoUnlock unlock(lock_); - node_controller_->SetPortObserver( - control_port_, - make_scoped_refptr(new PortObserverThunk(this))); -} - -MojoResult DataPipeProducerDispatcher::CloseNoLock() { - lock_.AssertAcquired(); - if (is_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - is_closed_ = true; - ring_buffer_mapping_.reset(); - shared_ring_buffer_ = nullptr; - - watchers_.NotifyClosed(); - if (!transferred_) { - base::AutoUnlock unlock(lock_); - node_controller_->ClosePort(control_port_); - } - - return MOJO_RESULT_OK; -} - -HandleSignalsState DataPipeProducerDispatcher::GetHandleSignalsStateNoLock() - const { - lock_.AssertAcquired(); - HandleSignalsState rv; - if (!peer_closed_) { - if (!in_two_phase_write_ && shared_ring_buffer_ && available_capacity_ > 0) - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - } else { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - } - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - return rv; -} - -void DataPipeProducerDispatcher::NotifyWrite(uint32_t num_bytes) { - DVLOG(1) << "Data pipe producer " << pipe_id_ << " notifying peer: " - << num_bytes << " bytes written. [control_port=" - << control_port_.name() << "]"; - - SendDataPipeControlMessage(node_controller_, control_port_, - DataPipeCommand::DATA_WAS_WRITTEN, num_bytes); -} - -void DataPipeProducerDispatcher::OnPortStatusChanged() { - DCHECK(RequestContext::current()); - - base::AutoLock lock(lock_); - - // We stop observing the control port as soon it's transferred, but this can - // race with events which are raised right before that happens. This is fine - // to ignore. - if (transferred_) - return; - - DVLOG(1) << "Control port status changed for data pipe producer " << pipe_id_; - - UpdateSignalsStateNoLock(); -} - -void DataPipeProducerDispatcher::UpdateSignalsStateNoLock() { - lock_.AssertAcquired(); - - bool was_peer_closed = peer_closed_; - size_t previous_capacity = available_capacity_; - - ports::PortStatus port_status; - int rv = node_controller_->node()->GetStatus(control_port_, &port_status); - if (rv != ports::OK || !port_status.receiving_messages) { - DVLOG(1) << "Data pipe producer " << pipe_id_ << " is aware of peer closure" - << " [control_port=" << control_port_.name() << "]"; - peer_closed_ = true; - } else if (rv == ports::OK && port_status.has_messages && !in_transit_) { - ports::ScopedMessage message; - do { - int rv = node_controller_->node()->GetMessage( - control_port_, &message, nullptr); - if (rv != ports::OK) - peer_closed_ = true; - if (message) { - if (message->num_payload_bytes() < sizeof(DataPipeControlMessage)) { - peer_closed_ = true; - break; - } - - const DataPipeControlMessage* m = - static_cast( - message->payload_bytes()); - - if (m->command != DataPipeCommand::DATA_WAS_READ) { - DLOG(ERROR) << "Unexpected message from consumer."; - peer_closed_ = true; - break; - } - - if (static_cast(available_capacity_) + m->num_bytes > - options_.capacity_num_bytes) { - DLOG(ERROR) << "Consumer claims to have read too many bytes."; - break; - } - - DVLOG(1) << "Data pipe producer " << pipe_id_ << " is aware that " - << m->num_bytes << " bytes were read. [control_port=" - << control_port_.name() << "]"; - - available_capacity_ += m->num_bytes; - } - } while (message); - } - - if (peer_closed_ != was_peer_closed || - available_capacity_ != previous_capacity) { - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - } -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.h b/mojo/edk/system/data_pipe_producer_dispatcher.h deleted file mode 100644 index 1eddd5d..0000000 --- a/mojo/edk/system/data_pipe_producer_dispatcher.h +++ /dev/null @@ -1,123 +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_DATA_PIPE_PRODUCER_DISPATCHER_H_ -#define MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_ - -#include -#include - -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/ports/port_ref.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/edk/system/watcher_set.h" - -namespace mojo { -namespace edk { - -struct DataPipeControlMessage; -class NodeController; - -// This is the Dispatcher implementation for the producer handle for data -// pipes created by the Mojo primitive MojoCreateDataPipe(). This class is -// thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final - : public Dispatcher { - public: - DataPipeProducerDispatcher( - NodeController* node_controller, - const ports::PortRef& port, - scoped_refptr shared_ring_buffer, - const MojoCreateDataPipeOptions& options, - bool initialized, - uint64_t pipe_id); - - // Dispatcher: - Type GetType() const override; - MojoResult Close() override; - MojoResult WriteData(const void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) override; - MojoResult BeginWriteData(void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags) override; - MojoResult EndWriteData(uint32_t num_bytes_written) override; - HandleSignalsState GetHandleSignalsState() const override; - MojoResult AddWatcherRef(const scoped_refptr& watcher, - uintptr_t context) override; - MojoResult RemoveWatcherRef(WatcherDispatcher* watcher, - uintptr_t context) override; - void StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_handles) override; - bool EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) override; - bool BeginTransit() override; - void CompleteTransitAndClose() override; - void CancelTransit() override; - - static scoped_refptr - Deserialize(const void* data, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* handles, - size_t num_handles); - - private: - class PortObserverThunk; - friend class PortObserverThunk; - - ~DataPipeProducerDispatcher() override; - - void OnSharedBufferCreated(const scoped_refptr& buffer); - void InitializeNoLock(); - MojoResult CloseNoLock(); - HandleSignalsState GetHandleSignalsStateNoLock() const; - void NotifyWrite(uint32_t num_bytes); - void OnPortStatusChanged(); - void UpdateSignalsStateNoLock(); - bool ProcessMessageNoLock(const DataPipeControlMessage& message, - ScopedPlatformHandleVectorPtr handles); - - const MojoCreateDataPipeOptions options_; - NodeController* const node_controller_; - const ports::PortRef control_port_; - const uint64_t pipe_id_; - - // Guards access to the fields below. - mutable base::Lock lock_; - - WatcherSet watchers_; - - bool buffer_requested_ = false; - - scoped_refptr shared_ring_buffer_; - std::unique_ptr ring_buffer_mapping_; - ScopedPlatformHandle buffer_handle_for_transit_; - - bool in_transit_ = false; - bool is_closed_ = false; - bool peer_closed_ = false; - bool transferred_ = false; - bool in_two_phase_write_ = false; - - uint32_t write_offset_ = 0; - uint32_t available_capacity_; - - DISALLOW_COPY_AND_ASSIGN(DataPipeProducerDispatcher); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_ diff --git a/mojo/edk/system/data_pipe_unittest.cc b/mojo/edk/system/data_pipe_unittest.cc deleted file mode 100644 index 79c1f75..0000000 --- a/mojo/edk/system/data_pipe_unittest.cc +++ /dev/null @@ -1,2034 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include - -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/cpp/system/simple_watcher.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -const uint32_t kSizeOfOptions = - static_cast(sizeof(MojoCreateDataPipeOptions)); - -// In various places, we have to poll (since, e.g., we can't yet wait for a -// certain amount of data to be available). This is the maximum number of -// iterations (separated by a short sleep). -// TODO(vtl): Get rid of this. -const size_t kMaxPoll = 100; - -// Used in Multiprocess test. -const size_t kMultiprocessCapacity = 37; -const char kMultiprocessTestData[] = "hello i'm a string that is 36 bytes"; -const int kMultiprocessMaxIter = 5; - -// TODO(rockot): There are many uses of ASSERT where EXPECT would be more -// appropriate. Fix this. - -class DataPipeTest : public test::MojoTestBase { - public: - DataPipeTest() : producer_(MOJO_HANDLE_INVALID), - consumer_(MOJO_HANDLE_INVALID) {} - - ~DataPipeTest() override { - if (producer_ != MOJO_HANDLE_INVALID) - CHECK_EQ(MOJO_RESULT_OK, MojoClose(producer_)); - if (consumer_ != MOJO_HANDLE_INVALID) - CHECK_EQ(MOJO_RESULT_OK, MojoClose(consumer_)); - } - - MojoResult Create(const MojoCreateDataPipeOptions* options) { - return MojoCreateDataPipe(options, &producer_, &consumer_); - } - - MojoResult WriteData(const void* elements, - uint32_t* num_bytes, - bool all_or_none = false) { - return MojoWriteData(producer_, elements, num_bytes, - all_or_none ? MOJO_WRITE_DATA_FLAG_ALL_OR_NONE - : MOJO_WRITE_DATA_FLAG_NONE); - } - - MojoResult ReadData(void* elements, - uint32_t* num_bytes, - bool all_or_none = false, - bool peek = false) { - MojoReadDataFlags flags = MOJO_READ_DATA_FLAG_NONE; - if (all_or_none) - flags |= MOJO_READ_DATA_FLAG_ALL_OR_NONE; - if (peek) - flags |= MOJO_READ_DATA_FLAG_PEEK; - return MojoReadData(consumer_, elements, num_bytes, flags); - } - - MojoResult QueryData(uint32_t* num_bytes) { - return MojoReadData(consumer_, nullptr, num_bytes, - MOJO_READ_DATA_FLAG_QUERY); - } - - MojoResult DiscardData(uint32_t* num_bytes, bool all_or_none = false) { - MojoReadDataFlags flags = MOJO_READ_DATA_FLAG_DISCARD; - if (all_or_none) - flags |= MOJO_READ_DATA_FLAG_ALL_OR_NONE; - return MojoReadData(consumer_, nullptr, num_bytes, flags); - } - - MojoResult BeginReadData(const void** elements, - uint32_t* num_bytes, - bool all_or_none = false) { - MojoReadDataFlags flags = MOJO_READ_DATA_FLAG_NONE; - if (all_or_none) - flags |= MOJO_READ_DATA_FLAG_ALL_OR_NONE; - return MojoBeginReadData(consumer_, elements, num_bytes, flags); - } - - MojoResult EndReadData(uint32_t num_bytes_read) { - return MojoEndReadData(consumer_, num_bytes_read); - } - - MojoResult BeginWriteData(void** elements, - uint32_t* num_bytes, - bool all_or_none = false) { - MojoReadDataFlags flags = MOJO_WRITE_DATA_FLAG_NONE; - if (all_or_none) - flags |= MOJO_WRITE_DATA_FLAG_ALL_OR_NONE; - return MojoBeginWriteData(producer_, elements, num_bytes, flags); - } - - MojoResult EndWriteData(uint32_t num_bytes_written) { - return MojoEndWriteData(producer_, num_bytes_written); - } - - MojoResult CloseProducer() { - MojoResult rv = MojoClose(producer_); - producer_ = MOJO_HANDLE_INVALID; - return rv; - } - - MojoResult CloseConsumer() { - MojoResult rv = MojoClose(consumer_); - consumer_ = MOJO_HANDLE_INVALID; - return rv; - } - - MojoHandle producer_, consumer_; - - private: - DISALLOW_COPY_AND_ASSIGN(DataPipeTest); -}; - -TEST_F(DataPipeTest, Basic) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - - // We can write to a data pipe handle immediately. - int32_t elements[10] = {}; - uint32_t num_bytes = 0; - - num_bytes = - static_cast(arraysize(elements) * sizeof(elements[0])); - - elements[0] = 123; - elements[1] = 456; - num_bytes = static_cast(2u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(&elements[0], &num_bytes)); - - // Now wait for the other side to become readable. - MojoHandleSignalsState state; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - state.satisfied_signals); - - elements[0] = -1; - elements[1] = -1; - ASSERT_EQ(MOJO_RESULT_OK, ReadData(&elements[0], &num_bytes)); - ASSERT_EQ(static_cast(2u * sizeof(elements[0])), num_bytes); - ASSERT_EQ(elements[0], 123); - ASSERT_EQ(elements[1], 456); -} - -// Tests creation of data pipes with various (valid) options. -TEST_F(DataPipeTest, CreateAndMaybeTransfer) { - MojoCreateDataPipeOptions test_options[] = { - // Default options. - {}, - // Trivial element size, non-default capacity. - {kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1, // |element_num_bytes|. - 1000}, // |capacity_num_bytes|. - // Nontrivial element size, non-default capacity. - {kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 4, // |element_num_bytes|. - 4000}, // |capacity_num_bytes|. - // Nontrivial element size, default capacity. - {kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 100, // |element_num_bytes|. - 0} // |capacity_num_bytes|. - }; - for (size_t i = 0; i < arraysize(test_options); i++) { - MojoHandle producer_handle, consumer_handle; - MojoCreateDataPipeOptions* options = - i ? &test_options[i] : nullptr; - ASSERT_EQ(MOJO_RESULT_OK, - MojoCreateDataPipe(options, &producer_handle, &consumer_handle)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(producer_handle)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(consumer_handle)); - } -} - -TEST_F(DataPipeTest, SimpleReadWrite) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - int32_t elements[10] = {}; - uint32_t num_bytes = 0; - - // Try reading; nothing there yet. - num_bytes = - static_cast(arraysize(elements) * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadData(elements, &num_bytes)); - - // Query; nothing there yet. - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(0u, num_bytes); - - // Discard; nothing there yet. - num_bytes = static_cast(5u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, DiscardData(&num_bytes)); - - // Read with invalid |num_bytes|. - num_bytes = sizeof(elements[0]) + 1; - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, ReadData(elements, &num_bytes)); - - // Write two elements. - elements[0] = 123; - elements[1] = 456; - num_bytes = static_cast(2u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(elements, &num_bytes)); - // It should have written everything (even without "all or none"). - ASSERT_EQ(2u * sizeof(elements[0]), num_bytes); - - // Wait. - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Query. - // TODO(vtl): It's theoretically possible (though not with the current - // implementation/configured limits) that not all the data has arrived yet. - // (The theoretically-correct assertion here is that |num_bytes| is |1 * ...| - // or |2 * ...|.) - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(2 * sizeof(elements[0]), num_bytes); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(elements, &num_bytes)); - ASSERT_EQ(1u * sizeof(elements[0]), num_bytes); - ASSERT_EQ(123, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Query. - // TODO(vtl): See previous TODO. (If we got 2 elements there, however, we - // should get 1 here.) - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(1 * sizeof(elements[0]), num_bytes); - - // Peek one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(elements, &num_bytes, false, true)); - ASSERT_EQ(1u * sizeof(elements[0]), num_bytes); - ASSERT_EQ(456, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Query. Still has 1 element remaining. - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(1 * sizeof(elements[0]), num_bytes); - - // Try to read two elements, with "all or none". - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(2u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, - ReadData(elements, &num_bytes, true, false)); - ASSERT_EQ(-1, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Try to read two elements, without "all or none". - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(2u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(elements, &num_bytes, false, false)); - ASSERT_EQ(1u * sizeof(elements[0]), num_bytes); - ASSERT_EQ(456, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Query. - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(0u, num_bytes); -} - -// 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_F(DataPipeTest, BasicProducerWaiting) { - // Note: We take advantage of the fact that current for current - // implementations capacities are strict maximums. This is not guaranteed by - // the API. - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 2 * sizeof(int32_t) // |capacity_num_bytes|. - }; - Create(&options); - MojoHandleSignalsState hss; - - // Never readable. Already writable. - hss = GetSignalsState(producer_); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Write two elements. - int32_t elements[2] = {123, 456}; - uint32_t num_bytes = static_cast(2u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(elements, &num_bytes, true)); - ASSERT_EQ(static_cast(2u * sizeof(elements[0])), num_bytes); - - // Wait for data to become available to the consumer. - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Peek one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(elements, &num_bytes, true, true)); - ASSERT_EQ(static_cast(1u * sizeof(elements[0])), num_bytes); - ASSERT_EQ(123, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(elements, &num_bytes, true, false)); - ASSERT_EQ(static_cast(1u * sizeof(elements[0])), num_bytes); - ASSERT_EQ(123, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Try writing, using a two-phase write. - void* buffer = nullptr; - num_bytes = static_cast(3u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&buffer, &num_bytes)); - EXPECT_TRUE(buffer); - ASSERT_GE(num_bytes, static_cast(1u * sizeof(elements[0]))); - - static_cast(buffer)[0] = 789; - ASSERT_EQ(MOJO_RESULT_OK, EndWriteData(static_cast( - 1u * sizeof(elements[0])))); - - // Read one element, using a two-phase read. - const void* read_buffer = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - BeginReadData(&read_buffer, &num_bytes, false)); - EXPECT_TRUE(read_buffer); - // The two-phase read should be able to read at least one element. - ASSERT_GE(num_bytes, static_cast(1u * sizeof(elements[0]))); - ASSERT_EQ(456, static_cast(read_buffer)[0]); - ASSERT_EQ(MOJO_RESULT_OK, EndReadData(static_cast( - 1u * sizeof(elements[0])))); - - // Write one element. - elements[0] = 123; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(elements, &num_bytes)); - ASSERT_EQ(static_cast(1u * sizeof(elements[0])), num_bytes); - - // Close the consumer. - CloseConsumer(); - - // It should now be never-writable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(producer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); -} - -TEST_F(DataPipeTest, PeerClosedProducerWaiting) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 2 * sizeof(int32_t) // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Close the consumer. - CloseConsumer(); - - // It should be signaled. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(producer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); -} - -TEST_F(DataPipeTest, PeerClosedConsumerWaiting) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 2 * sizeof(int32_t) // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Close the producer. - CloseProducer(); - - // It should be signaled. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); -} - -TEST_F(DataPipeTest, BasicConsumerWaiting) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Never writable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_WRITABLE, &hss)); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Write two elements. - int32_t elements[2] = {123, 456}; - uint32_t num_bytes = static_cast(2u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(elements, &num_bytes, true)); - - // Wait for readability. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Discard one element. - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, DiscardData(&num_bytes, true)); - ASSERT_EQ(static_cast(1u * sizeof(elements[0])), num_bytes); - - // Should still be readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Peek one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(elements, &num_bytes, true, true)); - ASSERT_EQ(456, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Should still be readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(elements, &num_bytes, true)); - ASSERT_EQ(static_cast(1u * sizeof(elements[0])), num_bytes); - ASSERT_EQ(456, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Write one element. - elements[0] = 789; - elements[1] = -1; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(elements, &num_bytes, true)); - - // Waiting should now succeed. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Close the producer. - CloseProducer(); - - // Should still be readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE(hss.satisfied_signals & (MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Wait for the peer closed signal. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Read one element. - elements[0] = -1; - elements[1] = -1; - num_bytes = static_cast(1u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(elements, &num_bytes, true)); - ASSERT_EQ(static_cast(1u * sizeof(elements[0])), num_bytes); - ASSERT_EQ(789, elements[0]); - ASSERT_EQ(-1, elements[1]); - - // Should be never-readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); -} - -TEST_F(DataPipeTest, ConsumerNewDataReadable) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - EXPECT_EQ(MOJO_RESULT_OK, Create(&options)); - - int32_t elements[2] = {123, 456}; - uint32_t num_bytes = static_cast(2u * sizeof(elements[0])); - EXPECT_EQ(MOJO_RESULT_OK, WriteData(elements, &num_bytes, true)); - - // The consumer handle should appear to be readable and have new data. - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE(GetSignalsState(consumer_).satisfied_signals & - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE); - - // Now try to read a minimum of 6 elements. - int32_t read_elements[6]; - uint32_t num_read_bytes = sizeof(read_elements); - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - MojoReadData(consumer_, read_elements, &num_read_bytes, - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // The consumer should still appear to be readable but not with new data. - EXPECT_TRUE(GetSignalsState(consumer_).satisfied_signals & - MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_FALSE(GetSignalsState(consumer_).satisfied_signals & - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE); - - // Write four more elements. - EXPECT_EQ(MOJO_RESULT_OK, WriteData(elements, &num_bytes, true)); - EXPECT_EQ(MOJO_RESULT_OK, WriteData(elements, &num_bytes, true)); - - // The consumer handle should once again appear to be readable. - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE)); - - // Try again to read a minimum of 6 elements. Should succeed this time. - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadData(consumer_, read_elements, &num_read_bytes, - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // And now the consumer is unreadable. - EXPECT_FALSE(GetSignalsState(consumer_).satisfied_signals & - MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_FALSE(GetSignalsState(consumer_).satisfied_signals & - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE); -} - -// Test with two-phase APIs and also closing the producer with an active -// consumer waiter. -TEST_F(DataPipeTest, ConsumerWaitingTwoPhase) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Write two elements. - int32_t* elements = nullptr; - void* buffer = nullptr; - // Request room for three (but we'll only write two). - uint32_t num_bytes = static_cast(3u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&buffer, &num_bytes, false)); - EXPECT_TRUE(buffer); - EXPECT_GE(num_bytes, static_cast(3u * sizeof(elements[0]))); - elements = static_cast(buffer); - elements[0] = 123; - elements[1] = 456; - ASSERT_EQ(MOJO_RESULT_OK, EndWriteData(2u * sizeof(elements[0]))); - - // Wait for readability. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Read one element. - // Request two in all-or-none mode, but only read one. - const void* read_buffer = nullptr; - num_bytes = static_cast(2u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_buffer, &num_bytes, true)); - EXPECT_TRUE(read_buffer); - ASSERT_EQ(static_cast(2u * sizeof(elements[0])), num_bytes); - const int32_t* read_elements = static_cast(read_buffer); - ASSERT_EQ(123, read_elements[0]); - ASSERT_EQ(MOJO_RESULT_OK, EndReadData(1u * sizeof(elements[0]))); - - // Should still be readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Read one element. - // Request three, but not in all-or-none mode. - read_buffer = nullptr; - num_bytes = static_cast(3u * sizeof(elements[0])); - ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_buffer, &num_bytes)); - EXPECT_TRUE(read_buffer); - ASSERT_EQ(static_cast(1u * sizeof(elements[0])), num_bytes); - read_elements = static_cast(read_buffer); - ASSERT_EQ(456, read_elements[0]); - ASSERT_EQ(MOJO_RESULT_OK, EndReadData(1u * sizeof(elements[0]))); - - // Close the producer. - CloseProducer(); - - // Should be never-readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); -} - -// Tests that data pipes aren't writable/readable during two-phase writes/reads. -TEST_F(DataPipeTest, BasicTwoPhaseWaiting) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // It should be writable. - hss = GetSignalsState(producer_); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - uint32_t num_bytes = static_cast(1u * sizeof(int32_t)); - void* write_ptr = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&write_ptr, &num_bytes)); - EXPECT_TRUE(write_ptr); - EXPECT_GE(num_bytes, static_cast(1u * sizeof(int32_t))); - - // At this point, it shouldn't be writable. - hss = GetSignalsState(producer_); - ASSERT_EQ(0u, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // It shouldn't be readable yet either (we'll wait later). - hss = GetSignalsState(consumer_); - ASSERT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - static_cast(write_ptr)[0] = 123; - ASSERT_EQ(MOJO_RESULT_OK, EndWriteData(1u * sizeof(int32_t))); - - // It should immediately be writable again. - hss = GetSignalsState(producer_); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // It should become readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Start another two-phase write and check that it's readable even in the - // middle of it. - num_bytes = static_cast(1u * sizeof(int32_t)); - write_ptr = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&write_ptr, &num_bytes)); - EXPECT_TRUE(write_ptr); - EXPECT_GE(num_bytes, static_cast(1u * sizeof(int32_t))); - - // It should be readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // End the two-phase write without writing anything. - ASSERT_EQ(MOJO_RESULT_OK, EndWriteData(0u)); - - // Start a two-phase read. - num_bytes = static_cast(1u * sizeof(int32_t)); - const void* read_ptr = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_ptr, &num_bytes)); - EXPECT_TRUE(read_ptr); - ASSERT_EQ(static_cast(1u * sizeof(int32_t)), num_bytes); - - // At this point, it should still be writable. - hss = GetSignalsState(producer_); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // But not readable. - hss = GetSignalsState(consumer_); - ASSERT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // End the two-phase read without reading anything. - ASSERT_EQ(MOJO_RESULT_OK, EndReadData(0u)); - - // It should be readable again. - hss = GetSignalsState(consumer_); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); -} - -void Seq(int32_t start, size_t count, int32_t* out) { - for (size_t i = 0; i < count; i++) - out[i] = start + static_cast(i); -} - -TEST_F(DataPipeTest, AllOrNone) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 10 * sizeof(int32_t) // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Try writing more than the total capacity of the pipe. - uint32_t num_bytes = 20u * sizeof(int32_t); - int32_t buffer[100]; - Seq(0, arraysize(buffer), buffer); - ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, WriteData(buffer, &num_bytes, true)); - - // Should still be empty. - num_bytes = ~0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(0u, num_bytes); - - // Write some data. - num_bytes = 5u * sizeof(int32_t); - Seq(100, arraysize(buffer), buffer); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(buffer, &num_bytes, true)); - ASSERT_EQ(5u * sizeof(int32_t), num_bytes); - - // Wait for data. - // TODO(vtl): There's no real guarantee that all the data will become - // available at once (except that in current implementations, with reasonable - // limits, it will). Eventually, we'll be able to wait for a specified amount - // of data to become available. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Half full. - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(5u * sizeof(int32_t), num_bytes); - - // Try writing more than the available capacity of the pipe, but less than the - // total capacity. - num_bytes = 6u * sizeof(int32_t); - Seq(200, arraysize(buffer), buffer); - ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, WriteData(buffer, &num_bytes, true)); - - // Try reading too much. - num_bytes = 11u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, ReadData(buffer, &num_bytes, true)); - int32_t expected_buffer[100]; - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - ASSERT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Try discarding too much. - num_bytes = 11u * sizeof(int32_t); - ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, DiscardData(&num_bytes, true)); - - // Just a little. - num_bytes = 2u * sizeof(int32_t); - Seq(300, arraysize(buffer), buffer); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(buffer, &num_bytes, true)); - ASSERT_EQ(2u * sizeof(int32_t), num_bytes); - - // Just right. - num_bytes = 3u * sizeof(int32_t); - Seq(400, arraysize(buffer), buffer); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(buffer, &num_bytes, true)); - ASSERT_EQ(3u * sizeof(int32_t), num_bytes); - - // TODO(vtl): Hack (see also the TODO above): We can't currently wait for a - // specified amount of data to be available, so poll. - for (size_t i = 0; i < kMaxPoll; i++) { - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - if (num_bytes >= 10u * sizeof(int32_t)) - break; - - test::Sleep(test::EpsilonDeadline()); - } - ASSERT_EQ(10u * sizeof(int32_t), num_bytes); - - // Read half. - num_bytes = 5u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(buffer, &num_bytes, true)); - ASSERT_EQ(5u * sizeof(int32_t), num_bytes); - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - Seq(100, 5, expected_buffer); - ASSERT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Try reading too much again. - num_bytes = 6u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, ReadData(buffer, &num_bytes, true)); - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - ASSERT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Try discarding too much again. - num_bytes = 6u * sizeof(int32_t); - ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, DiscardData(&num_bytes, true)); - - // Discard a little. - num_bytes = 2u * sizeof(int32_t); - ASSERT_EQ(MOJO_RESULT_OK, DiscardData(&num_bytes, true)); - ASSERT_EQ(2u * sizeof(int32_t), num_bytes); - - // Three left. - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(3u * sizeof(int32_t), num_bytes); - - // Close the producer, then test producer-closed cases. - CloseProducer(); - - // Wait. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Try reading too much; "failed precondition" since the producer is closed. - num_bytes = 4u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - ReadData(buffer, &num_bytes, true)); - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - ASSERT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Try discarding too much; "failed precondition" again. - num_bytes = 4u * sizeof(int32_t); - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, DiscardData(&num_bytes, true)); - - // Read a little. - num_bytes = 2u * sizeof(int32_t); - memset(buffer, 0xab, sizeof(buffer)); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(buffer, &num_bytes, true)); - ASSERT_EQ(2u * sizeof(int32_t), num_bytes); - memset(expected_buffer, 0xab, sizeof(expected_buffer)); - Seq(400, 2, expected_buffer); - ASSERT_EQ(0, memcmp(buffer, expected_buffer, sizeof(buffer))); - - // Discard the remaining element. - num_bytes = 1u * sizeof(int32_t); - ASSERT_EQ(MOJO_RESULT_OK, DiscardData(&num_bytes, true)); - ASSERT_EQ(1u * sizeof(int32_t), num_bytes); - - // Empty again. - num_bytes = ~0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(0u, num_bytes); -} - -// Tests that |ProducerWriteData()| and |ConsumerReadData()| writes and reads, -// respectively, as much as possible, even if it may have to "wrap around" the -// internal circular buffer. (Note that the two-phase write and read need not do -// this.) -TEST_F(DataPipeTest, WrapAround) { - unsigned char test_data[1000]; - for (size_t i = 0; i < arraysize(test_data); i++) - test_data[i] = static_cast(i); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 100u // |capacity_num_bytes|. - }; - - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Write 20 bytes. - uint32_t num_bytes = 20u; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(&test_data[0], &num_bytes, true)); - ASSERT_EQ(20u, num_bytes); - - // Wait for data. - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Read 10 bytes. - unsigned char read_buffer[1000] = {0}; - num_bytes = 10u; - ASSERT_EQ(MOJO_RESULT_OK, ReadData(read_buffer, &num_bytes, true)); - ASSERT_EQ(10u, num_bytes); - ASSERT_EQ(0, memcmp(read_buffer, &test_data[0], 10u)); - - // Check that a two-phase write can now only write (at most) 80 bytes. (This - // checks an implementation detail; this behavior is not guaranteed.) - void* write_buffer_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - BeginWriteData(&write_buffer_ptr, &num_bytes, false)); - EXPECT_TRUE(write_buffer_ptr); - ASSERT_EQ(80u, num_bytes); - ASSERT_EQ(MOJO_RESULT_OK, EndWriteData(0)); - - size_t total_num_bytes = 0; - while (total_num_bytes < 90) { - // Wait to write. - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(producer_, MOJO_HANDLE_SIGNAL_WRITABLE, &hss)); - ASSERT_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_WRITABLE); - ASSERT_EQ(hss.satisfiable_signals, - MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - // Write as much as we can. - num_bytes = 100; - ASSERT_EQ(MOJO_RESULT_OK, - WriteData(&test_data[20 + total_num_bytes], &num_bytes, false)); - total_num_bytes += num_bytes; - } - - ASSERT_EQ(90u, total_num_bytes); - - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(100u, num_bytes); - - // Check that a two-phase read can now only read (at most) 90 bytes. (This - // checks an implementation detail; this behavior is not guaranteed.) - const void* read_buffer_ptr = nullptr; - num_bytes = 0; - ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_buffer_ptr, &num_bytes, false)); - EXPECT_TRUE(read_buffer_ptr); - ASSERT_EQ(90u, num_bytes); - ASSERT_EQ(MOJO_RESULT_OK, EndReadData(0)); - - // Read as much as possible. We should read 100 bytes. - num_bytes = static_cast(arraysize(read_buffer) * - sizeof(read_buffer[0])); - memset(read_buffer, 0, num_bytes); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(read_buffer, &num_bytes)); - ASSERT_EQ(100u, num_bytes); - ASSERT_EQ(0, memcmp(read_buffer, &test_data[10], 100u)); -} - -// Tests the behavior of writing (simple and two-phase), closing the producer, -// then reading (simple and two-phase). -TEST_F(DataPipeTest, WriteCloseProducerRead) { - const char kTestData[] = "hello world"; - const uint32_t kTestDataSize = static_cast(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - - // Write some data, so we'll have something to read. - uint32_t num_bytes = kTestDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kTestData, &num_bytes, false)); - ASSERT_EQ(kTestDataSize, num_bytes); - - // Write it again, so we'll have something left over. - num_bytes = kTestDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kTestData, &num_bytes, false)); - ASSERT_EQ(kTestDataSize, num_bytes); - - // Start two-phase write. - void* write_buffer_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - BeginWriteData(&write_buffer_ptr, &num_bytes, false)); - EXPECT_TRUE(write_buffer_ptr); - EXPECT_GT(num_bytes, 0u); - - // TODO(vtl): (See corresponding TODO in TwoPhaseAllOrNone.) - for (size_t i = 0; i < kMaxPoll; i++) { - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - if (num_bytes >= 2u * kTestDataSize) - break; - - test::Sleep(test::EpsilonDeadline()); - } - ASSERT_EQ(2u * kTestDataSize, num_bytes); - - // Start two-phase read. - const void* read_buffer_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - BeginReadData(&read_buffer_ptr, &num_bytes)); - EXPECT_TRUE(read_buffer_ptr); - ASSERT_EQ(2u * kTestDataSize, num_bytes); - - // Close the producer. - CloseProducer(); - - // The consumer can finish its two-phase read. - ASSERT_EQ(0, memcmp(read_buffer_ptr, kTestData, kTestDataSize)); - ASSERT_EQ(MOJO_RESULT_OK, EndReadData(kTestDataSize)); - - // And start another. - read_buffer_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - BeginReadData(&read_buffer_ptr, &num_bytes)); - EXPECT_TRUE(read_buffer_ptr); - ASSERT_EQ(kTestDataSize, num_bytes); -} - - -// Tests the behavior of interrupting a two-phase read and write by closing the -// consumer. -TEST_F(DataPipeTest, TwoPhaseWriteReadCloseConsumer) { - const char kTestData[] = "hello world"; - const uint32_t kTestDataSize = static_cast(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Write some data, so we'll have something to read. - uint32_t num_bytes = kTestDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kTestData, &num_bytes)); - ASSERT_EQ(kTestDataSize, num_bytes); - - // Start two-phase write. - void* write_buffer_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&write_buffer_ptr, &num_bytes)); - EXPECT_TRUE(write_buffer_ptr); - ASSERT_GT(num_bytes, kTestDataSize); - - // Wait for data. - // TODO(vtl): (See corresponding TODO in AllOrNone.) - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Start two-phase read. - const void* read_buffer_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_buffer_ptr, &num_bytes)); - EXPECT_TRUE(read_buffer_ptr); - ASSERT_EQ(kTestDataSize, num_bytes); - - // Close the consumer. - CloseConsumer(); - - // Wait for producer to know that the consumer is closed. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(producer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - - // Actually write some data. (Note: Premature freeing of the buffer would - // probably only be detected under ASAN or similar.) - memcpy(write_buffer_ptr, kTestData, kTestDataSize); - // Note: Even though the consumer has been closed, ending the two-phase - // write will report success. - ASSERT_EQ(MOJO_RESULT_OK, EndWriteData(kTestDataSize)); - - // But trying to write should result in failure. - num_bytes = kTestDataSize; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, WriteData(kTestData, &num_bytes)); - - // As will trying to start another two-phase write. - write_buffer_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - BeginWriteData(&write_buffer_ptr, &num_bytes)); -} - -// Tests the behavior of "interrupting" a two-phase write by closing both the -// producer and the consumer. -TEST_F(DataPipeTest, TwoPhaseWriteCloseBoth) { - const uint32_t kTestDataSize = 15u; - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - - // Start two-phase write. - void* write_buffer_ptr = nullptr; - uint32_t num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&write_buffer_ptr, &num_bytes)); - EXPECT_TRUE(write_buffer_ptr); - ASSERT_GT(num_bytes, kTestDataSize); -} - -// Tests the behavior of writing, closing the producer, and then reading (with -// and without data remaining). -TEST_F(DataPipeTest, WriteCloseProducerReadNoData) { - const char kTestData[] = "hello world"; - const uint32_t kTestDataSize = static_cast(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Write some data, so we'll have something to read. - uint32_t num_bytes = kTestDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kTestData, &num_bytes)); - ASSERT_EQ(kTestDataSize, num_bytes); - - // Close the producer. - CloseProducer(); - - // Wait. (Note that once the consumer knows that the producer is closed, it - // must also know about all the data that was sent.) - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Peek that data. - char buffer[1000]; - num_bytes = static_cast(sizeof(buffer)); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(buffer, &num_bytes, false, true)); - ASSERT_EQ(kTestDataSize, num_bytes); - ASSERT_EQ(0, memcmp(buffer, kTestData, kTestDataSize)); - - // Read that data. - memset(buffer, 0, 1000); - num_bytes = static_cast(sizeof(buffer)); - ASSERT_EQ(MOJO_RESULT_OK, ReadData(buffer, &num_bytes)); - ASSERT_EQ(kTestDataSize, num_bytes); - ASSERT_EQ(0, memcmp(buffer, kTestData, kTestDataSize)); - - // A second read should fail. - num_bytes = static_cast(sizeof(buffer)); - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ReadData(buffer, &num_bytes)); - - // A two-phase read should also fail. - const void* read_buffer_ptr = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - BeginReadData(&read_buffer_ptr, &num_bytes)); - - // Ditto for discard. - num_bytes = 10u; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, DiscardData(&num_bytes)); -} - -// Test that during a two phase read the memory stays valid even if more data -// comes in. -TEST_F(DataPipeTest, TwoPhaseReadMemoryStable) { - const char kTestData[] = "hello world"; - const uint32_t kTestDataSize = static_cast(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Write some data. - uint32_t num_bytes = kTestDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kTestData, &num_bytes)); - ASSERT_EQ(kTestDataSize, num_bytes); - - // Wait for the data. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Begin a two-phase read. - const void* read_buffer_ptr = nullptr; - uint32_t read_buffer_size = 0u; - ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_buffer_ptr, &read_buffer_size)); - - // Write more data. - const char kExtraData[] = "bye world"; - const uint32_t kExtraDataSize = static_cast(sizeof(kExtraData)); - num_bytes = kExtraDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kExtraData, &num_bytes)); - ASSERT_EQ(kExtraDataSize, num_bytes); - - // Close the producer. - CloseProducer(); - - // Wait. (Note that once the consumer knows that the producer is closed, it - // must also have received the extra data). - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Read the two phase memory to check it's still valid. - ASSERT_EQ(0, memcmp(read_buffer_ptr, kTestData, kTestDataSize)); - EndReadData(read_buffer_size); -} - -// Test that two-phase reads/writes behave correctly when given invalid -// arguments. -TEST_F(DataPipeTest, TwoPhaseMoreInvalidArguments) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 10 * sizeof(int32_t) // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // No data. - uint32_t num_bytes = 1000u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(0u, num_bytes); - - // Try "ending" a two-phase write when one isn't active. - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - EndWriteData(1u * sizeof(int32_t))); - - // Wait a bit, to make sure that if a signal were (incorrectly) sent, it'd - // have time to propagate. - test::Sleep(test::EpsilonDeadline()); - - // Still no data. - num_bytes = 1000u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(0u, num_bytes); - - // Try ending a two-phase write with an invalid amount (too much). - num_bytes = 0u; - void* write_ptr = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&write_ptr, &num_bytes)); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - EndWriteData(num_bytes + static_cast(sizeof(int32_t)))); - - // But the two-phase write still ended. - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EndWriteData(0u)); - - // Wait a bit (as above). - test::Sleep(test::EpsilonDeadline()); - - // Still no data. - num_bytes = 1000u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(0u, num_bytes); - - // Try ending a two-phase write with an invalid amount (not a multiple of the - // element size). - num_bytes = 0u; - write_ptr = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&write_ptr, &num_bytes)); - EXPECT_GE(num_bytes, 1u); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EndWriteData(1u)); - - // But the two-phase write still ended. - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EndWriteData(0u)); - - // Wait a bit (as above). - test::Sleep(test::EpsilonDeadline()); - - // Still no data. - num_bytes = 1000u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(0u, num_bytes); - - // Now write some data, so we'll be able to try reading. - int32_t element = 123; - num_bytes = 1u * sizeof(int32_t); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(&element, &num_bytes)); - - // Wait for data. - // TODO(vtl): (See corresponding TODO in AllOrNone.) - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // One element available. - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(1u * sizeof(int32_t), num_bytes); - - // Try "ending" a two-phase read when one isn't active. - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, EndReadData(1u * sizeof(int32_t))); - - // Still one element available. - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(1u * sizeof(int32_t), num_bytes); - - // Try ending a two-phase read with an invalid amount (too much). - num_bytes = 0u; - const void* read_ptr = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_ptr, &num_bytes)); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - EndReadData(num_bytes + static_cast(sizeof(int32_t)))); - - // Still one element available. - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(1u * sizeof(int32_t), num_bytes); - - // Try ending a two-phase read with an invalid amount (not a multiple of the - // element size). - num_bytes = 0u; - read_ptr = nullptr; - ASSERT_EQ(MOJO_RESULT_OK, BeginReadData(&read_ptr, &num_bytes)); - ASSERT_EQ(1u * sizeof(int32_t), num_bytes); - ASSERT_EQ(123, static_cast(read_ptr)[0]); - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EndReadData(1u)); - - // Still one element available. - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, QueryData(&num_bytes)); - ASSERT_EQ(1u * sizeof(int32_t), num_bytes); -} - -// Test that a producer can be sent over a MP. -TEST_F(DataPipeTest, SendProducer) { - const char kTestData[] = "hello world"; - const uint32_t kTestDataSize = static_cast(sizeof(kTestData)); - - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1u, // |element_num_bytes|. - 1000u // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - MojoHandleSignalsState hss; - - // Write some data. - uint32_t num_bytes = kTestDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kTestData, &num_bytes)); - ASSERT_EQ(kTestDataSize, num_bytes); - - // Wait for the data. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Check the data. - const void* read_buffer = nullptr; - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - BeginReadData(&read_buffer, &num_bytes, false)); - ASSERT_EQ(0, memcmp(read_buffer, kTestData, kTestDataSize)); - EndReadData(num_bytes); - - // Now send the producer over a MP so that it's serialized. - MojoHandle pipe0, pipe1; - ASSERT_EQ(MOJO_RESULT_OK, - MojoCreateMessagePipe(nullptr, &pipe0, &pipe1)); - - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(pipe0, nullptr, 0, &producer_, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - producer_ = MOJO_HANDLE_INVALID; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - uint32_t num_handles = 1; - ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessage(pipe1, nullptr, 0, &producer_, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(num_handles, 1u); - - // Write more data. - const char kExtraData[] = "bye world"; - const uint32_t kExtraDataSize = static_cast(sizeof(kExtraData)); - num_bytes = kExtraDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kExtraData, &num_bytes)); - ASSERT_EQ(kExtraDataSize, num_bytes); - - // Wait for it. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - hss.satisfiable_signals); - - // Check the second write. - num_bytes = 0u; - ASSERT_EQ(MOJO_RESULT_OK, - BeginReadData(&read_buffer, &num_bytes, false)); - ASSERT_EQ(0, memcmp(read_buffer, kExtraData, kExtraDataSize)); - EndReadData(num_bytes); - - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(pipe0)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(pipe1)); -} - -// Ensures that if a data pipe consumer whose producer has closed is passed over -// a message pipe, the deserialized dispatcher is also marked as having a closed -// peer. -TEST_F(DataPipeTest, ConsumerWithClosedProducerSent) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - static_cast(sizeof(int32_t)), // |element_num_bytes|. - 1000 * sizeof(int32_t) // |capacity_num_bytes|. - }; - - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - - // We can write to a data pipe handle immediately. - int32_t data = 123; - uint32_t num_bytes = sizeof(data); - ASSERT_EQ(MOJO_RESULT_OK, WriteData(&data, &num_bytes)); - ASSERT_EQ(MOJO_RESULT_OK, CloseProducer()); - - // Now wait for the other side to become readable and to see the peer closed. - MojoHandleSignalsState state; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - state.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - state.satisfiable_signals); - - // Now send the consumer over a MP so that it's serialized. - MojoHandle pipe0, pipe1; - ASSERT_EQ(MOJO_RESULT_OK, - MojoCreateMessagePipe(nullptr, &pipe0, &pipe1)); - - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(pipe0, nullptr, 0, &consumer_, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - consumer_ = MOJO_HANDLE_INVALID; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1, MOJO_HANDLE_SIGNAL_READABLE, &state)); - uint32_t num_handles = 1; - ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessage(pipe1, nullptr, 0, &consumer_, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(num_handles, 1u); - - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - state.satisfiable_signals); - - int32_t read_data; - ASSERT_EQ(MOJO_RESULT_OK, ReadData(&read_data, &num_bytes)); - ASSERT_EQ(sizeof(read_data), num_bytes); - ASSERT_EQ(data, read_data); - - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(pipe0)); - ASSERT_EQ(MOJO_RESULT_OK, MojoClose(pipe1)); -} - -bool WriteAllData(MojoHandle producer, - const void* elements, - uint32_t num_bytes) { - for (size_t i = 0; i < kMaxPoll; i++) { - // Write as much data as we can. - uint32_t write_bytes = num_bytes; - MojoResult result = MojoWriteData(producer, elements, &write_bytes, - MOJO_WRITE_DATA_FLAG_NONE); - if (result == MOJO_RESULT_OK) { - num_bytes -= write_bytes; - elements = static_cast(elements) + write_bytes; - if (num_bytes == 0) - return true; - } else { - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, result); - } - - MojoHandleSignalsState hss = MojoHandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_OK, test::MojoTestBase::WaitForSignals( - producer, MOJO_HANDLE_SIGNAL_WRITABLE, &hss)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - } - - return false; -} - -// If |expect_empty| is true, expect |consumer| to be empty after reading. -bool ReadAllData(MojoHandle consumer, - void* elements, - uint32_t num_bytes, - bool expect_empty) { - for (size_t i = 0; i < kMaxPoll; i++) { - // Read as much data as we can. - uint32_t read_bytes = num_bytes; - MojoResult result = - MojoReadData(consumer, elements, &read_bytes, MOJO_READ_DATA_FLAG_NONE); - if (result == MOJO_RESULT_OK) { - num_bytes -= read_bytes; - elements = static_cast(elements) + read_bytes; - if (num_bytes == 0) { - if (expect_empty) { - // Expect no more data. - test::Sleep(test::TinyDeadline()); - MojoReadData(consumer, nullptr, &num_bytes, - MOJO_READ_DATA_FLAG_QUERY); - EXPECT_EQ(0u, num_bytes); - } - return true; - } - } else { - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, result); - } - - MojoHandleSignalsState hss = MojoHandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_OK, test::MojoTestBase::WaitForSignals( - consumer, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - // Peer could have become closed while we're still waiting for data. - EXPECT_TRUE(MOJO_HANDLE_SIGNAL_READABLE & hss.satisfied_signals); - EXPECT_TRUE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_TRUE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_CLOSED); - } - - return num_bytes == 0; -} - -#if !defined(OS_IOS) - -TEST_F(DataPipeTest, Multiprocess) { - const uint32_t kTestDataSize = - static_cast(sizeof(kMultiprocessTestData)); - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1, // |element_num_bytes|. - kMultiprocessCapacity // |capacity_num_bytes|. - }; - ASSERT_EQ(MOJO_RESULT_OK, Create(&options)); - - RUN_CHILD_ON_PIPE(MultiprocessClient, server_mp) - // Send some data before serialising and sending the data pipe over. - // This is the first write so we don't need to use WriteAllData. - uint32_t num_bytes = kTestDataSize; - ASSERT_EQ(MOJO_RESULT_OK, WriteData(kMultiprocessTestData, &num_bytes, - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); - ASSERT_EQ(kTestDataSize, num_bytes); - - // Send child process the data pipe. - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(server_mp, nullptr, 0, &consumer_, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Send a bunch of data of varying sizes. - uint8_t buffer[100]; - int seq = 0; - for (int i = 0; i < kMultiprocessMaxIter; ++i) { - for (uint32_t size = 1; size <= kMultiprocessCapacity; size++) { - for (unsigned int j = 0; j < size; ++j) - buffer[j] = seq + j; - EXPECT_TRUE(WriteAllData(producer_, buffer, size)); - seq += size; - } - } - - // Write the test string in again. - ASSERT_TRUE(WriteAllData(producer_, kMultiprocessTestData, kTestDataSize)); - - // Swap ends. - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(server_mp, nullptr, 0, &producer_, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Receive the consumer from the other side. - producer_ = MOJO_HANDLE_INVALID; - MojoHandleSignalsState hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(server_mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - MojoHandle handles[2]; - uint32_t num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessage(server_mp, nullptr, 0, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, num_handles); - consumer_ = handles[0]; - - // Read the test string twice. Once for when we sent it, and once for the - // other end sending it. - for (int i = 0; i < 2; ++i) { - EXPECT_TRUE(ReadAllData(consumer_, buffer, kTestDataSize, i == 1)); - EXPECT_EQ(0, memcmp(buffer, kMultiprocessTestData, kTestDataSize)); - } - - WriteMessage(server_mp, "quit"); - - // Don't have to close the consumer here because it will be done for us. - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessClient, DataPipeTest, client_mp) { - const uint32_t kTestDataSize = - static_cast(sizeof(kMultiprocessTestData)); - - // Receive the data pipe from the other side. - MojoHandle consumer = MOJO_HANDLE_INVALID; - MojoHandleSignalsState hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(client_mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - MojoHandle handles[2]; - uint32_t num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessage(client_mp, nullptr, 0, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, num_handles); - consumer = handles[0]; - - // Read the initial string that was sent. - int32_t buffer[100]; - EXPECT_TRUE(ReadAllData(consumer, buffer, kTestDataSize, false)); - EXPECT_EQ(0, memcmp(buffer, kMultiprocessTestData, kTestDataSize)); - - // Receive the main data and check it is correct. - int seq = 0; - uint8_t expected_buffer[100]; - for (int i = 0; i < kMultiprocessMaxIter; ++i) { - for (uint32_t size = 1; size <= kMultiprocessCapacity; ++size) { - for (unsigned int j = 0; j < size; ++j) - expected_buffer[j] = seq + j; - EXPECT_TRUE(ReadAllData(consumer, buffer, size, false)); - EXPECT_EQ(0, memcmp(buffer, expected_buffer, size)); - - seq += size; - } - } - - // Swap ends. - ASSERT_EQ(MOJO_RESULT_OK, MojoWriteMessage(client_mp, nullptr, 0, &consumer, - 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Receive the producer from the other side. - MojoHandle producer = MOJO_HANDLE_INVALID; - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(client_mp, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - num_handles = arraysize(handles); - ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessage(client_mp, nullptr, 0, handles, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_EQ(1u, num_handles); - producer = handles[0]; - - // Write the test string one more time. - EXPECT_TRUE(WriteAllData(producer, kMultiprocessTestData, kTestDataSize)); - - // We swapped ends, so close the producer. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); - - // Wait to receive a "quit" message before exiting. - EXPECT_EQ("quit", ReadMessage(client_mp)); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteAndCloseProducer, DataPipeTest, h) { - MojoHandle p; - std::string message = ReadMessageWithHandles(h, &p, 1); - - // Write some data to the producer and close it. - uint32_t num_bytes = static_cast(message.size()); - EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(p, message.data(), &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(num_bytes, static_cast(message.size())); - - // Close the producer before quitting. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(p)); - - // Wait for a quit message. - EXPECT_EQ("quit", ReadMessage(h)); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndCloseConsumer, DataPipeTest, h) { - MojoHandle c; - std::string expected_message = ReadMessageWithHandles(h, &c, 1); - - // Wait for the consumer to become readable. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(c, MOJO_HANDLE_SIGNAL_READABLE)); - - // Drain the consumer and expect to find the given message. - uint32_t num_bytes = static_cast(expected_message.size()); - std::vector bytes(expected_message.size()); - EXPECT_EQ(MOJO_RESULT_OK, MojoReadData(c, bytes.data(), &num_bytes, - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(num_bytes, static_cast(bytes.size())); - - std::string message(bytes.data(), bytes.size()); - EXPECT_EQ(expected_message, message); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); - - // Wait for a quit message. - EXPECT_EQ("quit", ReadMessage(h)); -} - -TEST_F(DataPipeTest, SendConsumerAndCloseProducer) { - // Create a new data pipe. - MojoHandle p, c; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p ,&c)); - - RUN_CHILD_ON_PIPE(WriteAndCloseProducer, producer_client) - RUN_CHILD_ON_PIPE(ReadAndCloseConsumer, consumer_client) - const std::string kMessage = "Hello, world!"; - WriteMessageWithHandles(producer_client, kMessage, &p, 1); - WriteMessageWithHandles(consumer_client, kMessage, &c, 1); - - WriteMessage(consumer_client, "quit"); - END_CHILD() - - WriteMessage(producer_client, "quit"); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndWrite, DataPipeTest, h) { - const MojoCreateDataPipeOptions options = { - kSizeOfOptions, // |struct_size|. - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. - 1, // |element_num_bytes|. - kMultiprocessCapacity // |capacity_num_bytes|. - }; - - MojoHandle p, c; - ASSERT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(&options, &p, &c)); - - const std::string kMessage = "Hello, world!"; - WriteMessageWithHandles(h, kMessage, &c, 1); - - // Write some data to the producer and close it. - uint32_t num_bytes = static_cast(kMessage.size()); - EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(p, kMessage.data(), &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(num_bytes, static_cast(kMessage.size())); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(p)); - - // Wait for a quit message. - EXPECT_EQ("quit", ReadMessage(h)); -} - -TEST_F(DataPipeTest, CreateInChild) { - RUN_CHILD_ON_PIPE(CreateAndWrite, child) - MojoHandle c; - std::string expected_message = ReadMessageWithHandles(child, &c, 1); - - // Wait for the consumer to become readable. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(c, MOJO_HANDLE_SIGNAL_READABLE)); - - // Drain the consumer and expect to find the given message. - uint32_t num_bytes = static_cast(expected_message.size()); - std::vector bytes(expected_message.size()); - EXPECT_EQ(MOJO_RESULT_OK, MojoReadData(c, bytes.data(), &num_bytes, - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(num_bytes, static_cast(bytes.size())); - - std::string message(bytes.data(), bytes.size()); - EXPECT_EQ(expected_message, message); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); - WriteMessage(child, "quit"); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(DataPipeStatusChangeInTransitClient, - DataPipeTest, parent) { - // This test verifies that peer closure is detectable through various - // mechanisms when it races with handle transfer. - - MojoHandle handles[6]; - EXPECT_EQ("o_O", ReadMessageWithHandles(parent, handles, 6)); - MojoHandle* producers = &handles[0]; - MojoHandle* consumers = &handles[3]; - - // Wait on producer 0 - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(producers[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - - // Wait on consumer 0 - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(consumers[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - - base::MessageLoop message_loop; - - // Wait on producer 1 and consumer 1 using SimpleWatchers. - { - base::RunLoop run_loop; - int count = 0; - auto callback = base::Bind( - [] (base::RunLoop* loop, int* count, MojoResult result) { - EXPECT_EQ(MOJO_RESULT_OK, result); - if (++*count == 2) - loop->Quit(); - }, - &run_loop, &count); - SimpleWatcher producer_watcher(FROM_HERE, - SimpleWatcher::ArmingPolicy::AUTOMATIC); - SimpleWatcher consumer_watcher(FROM_HERE, - SimpleWatcher::ArmingPolicy::AUTOMATIC); - producer_watcher.Watch(Handle(producers[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, - callback); - consumer_watcher.Watch(Handle(consumers[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, - callback); - run_loop.Run(); - EXPECT_EQ(2, count); - } - - // Wait on producer 2 by polling with MojoWriteData. - MojoResult result; - do { - uint32_t num_bytes = 0; - result = MojoWriteData( - producers[2], nullptr, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE); - } while (result == MOJO_RESULT_OK); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - - // Wait on consumer 2 by polling with MojoReadData. - do { - char byte; - uint32_t num_bytes = 1; - result = MojoReadData( - consumers[2], &byte, &num_bytes, MOJO_READ_DATA_FLAG_NONE); - } while (result == MOJO_RESULT_SHOULD_WAIT); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - - for (size_t i = 0; i < 6; ++i) - CloseHandle(handles[i]); -} - -TEST_F(DataPipeTest, StatusChangeInTransit) { - MojoHandle producers[6]; - MojoHandle consumers[6]; - for (size_t i = 0; i < 6; ++i) - CreateDataPipe(&producers[i], &consumers[i], 1); - - RUN_CHILD_ON_PIPE(DataPipeStatusChangeInTransitClient, child) - MojoHandle handles[] = { producers[0], producers[1], producers[2], - consumers[3], consumers[4], consumers[5] }; - - // Send 3 producers and 3 consumers, and let their transfer race with their - // peers' closure. - WriteMessageWithHandles(child, "o_O", handles, 6); - - for (size_t i = 0; i < 3; ++i) - CloseHandle(consumers[i]); - for (size_t i = 3; i < 6; ++i) - CloseHandle(producers[i]); - END_CHILD() -} - -#endif // !defined(OS_IOS) - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc deleted file mode 100644 index 7cdbe91..0000000 --- a/mojo/edk/system/dispatcher.cc +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/dispatcher.h" - -#include "base/logging.h" -#include "mojo/edk/system/configuration.h" -#include "mojo/edk/system/data_pipe_consumer_dispatcher.h" -#include "mojo/edk/system/data_pipe_producer_dispatcher.h" -#include "mojo/edk/system/message_pipe_dispatcher.h" -#include "mojo/edk/system/platform_handle_dispatcher.h" -#include "mojo/edk/system/shared_buffer_dispatcher.h" - -namespace mojo { -namespace edk { - -Dispatcher::DispatcherInTransit::DispatcherInTransit() {} - -Dispatcher::DispatcherInTransit::DispatcherInTransit( - const DispatcherInTransit& other) = default; - -Dispatcher::DispatcherInTransit::~DispatcherInTransit() {} - -MojoResult Dispatcher::WatchDispatcher(scoped_refptr dispatcher, - MojoHandleSignals signals, - uintptr_t context) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::CancelWatch(uintptr_t context) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::Arm(uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::WriteMessage(std::unique_ptr message, - MojoWriteMessageFlags flags) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::ReadMessage(std::unique_ptr* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags, - bool read_any_size) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::DuplicateBufferHandle( - const MojoDuplicateBufferHandleOptions* options, - scoped_refptr* new_dispatcher) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::MapBuffer( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - std::unique_ptr* mapping) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::ReadData(void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::BeginReadData(const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::WriteData(const void* elements, - uint32_t* num_bytes, - MojoWriteDataFlags flags) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::BeginWriteData(void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::AddWaitingDispatcher( - const scoped_refptr& dispatcher, - MojoHandleSignals signals, - uintptr_t context) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::RemoveWaitingDispatcher( - const scoped_refptr& dispatcher) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::GetReadyDispatchers(uint32_t* count, - DispatcherVector* dispatchers, - MojoResult* results, - uintptr_t* contexts) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -HandleSignalsState Dispatcher::GetHandleSignalsState() const { - return HandleSignalsState(); -} - -MojoResult Dispatcher::AddWatcherRef( - const scoped_refptr& watcher, - uintptr_t context) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -MojoResult Dispatcher::RemoveWatcherRef(WatcherDispatcher* watcher, - uintptr_t context) { - return MOJO_RESULT_INVALID_ARGUMENT; -} - -void Dispatcher::StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_platform_handles) { - *num_bytes = 0; - *num_ports = 0; - *num_platform_handles = 0; -} - -bool Dispatcher::EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) { - LOG(ERROR) << "Attempting to serialize a non-transferrable dispatcher."; - return true; -} - -bool Dispatcher::BeginTransit() { return true; } - -void Dispatcher::CompleteTransitAndClose() {} - -void Dispatcher::CancelTransit() {} - -// static -scoped_refptr Dispatcher::Deserialize( - Type type, - const void* bytes, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* platform_handles, - size_t num_platform_handles) { - switch (type) { - case Type::MESSAGE_PIPE: - return MessagePipeDispatcher::Deserialize( - bytes, num_bytes, ports, num_ports, platform_handles, - num_platform_handles); - case Type::SHARED_BUFFER: - return SharedBufferDispatcher::Deserialize( - bytes, num_bytes, ports, num_ports, platform_handles, - num_platform_handles); - case Type::DATA_PIPE_CONSUMER: - return DataPipeConsumerDispatcher::Deserialize( - bytes, num_bytes, ports, num_ports, platform_handles, - num_platform_handles); - case Type::DATA_PIPE_PRODUCER: - return DataPipeProducerDispatcher::Deserialize( - bytes, num_bytes, ports, num_ports, platform_handles, - num_platform_handles); - case Type::PLATFORM_HANDLE: - return PlatformHandleDispatcher::Deserialize( - bytes, num_bytes, ports, num_ports, platform_handles, - num_platform_handles); - default: - LOG(ERROR) << "Deserializing invalid dispatcher type."; - return nullptr; - } -} - -Dispatcher::Dispatcher() {} - -Dispatcher::~Dispatcher() {} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h deleted file mode 100644 index db1f1f1..0000000 --- a/mojo/edk/system/dispatcher.h +++ /dev/null @@ -1,245 +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_DISPATCHER_H_ -#define MOJO_EDK_SYSTEM_DISPATCHER_H_ - -#include -#include - -#include -#include -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/ports/name.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/edk/system/watch.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/types.h" - -namespace mojo { -namespace edk { - -class Dispatcher; -class MessageForTransit; - -using DispatcherVector = std::vector>; - -// A |Dispatcher| implements Mojo EDK calls that are associated with a -// particular MojoHandle. -class MOJO_SYSTEM_IMPL_EXPORT Dispatcher - : public base::RefCountedThreadSafe { - public: - struct DispatcherInTransit { - DispatcherInTransit(); - DispatcherInTransit(const DispatcherInTransit& other); - ~DispatcherInTransit(); - - scoped_refptr dispatcher; - MojoHandle local_handle; - }; - - enum class Type { - UNKNOWN = 0, - MESSAGE_PIPE, - DATA_PIPE_PRODUCER, - DATA_PIPE_CONSUMER, - SHARED_BUFFER, - WATCHER, - - // "Private" types (not exposed via the public interface): - PLATFORM_HANDLE = -1, - }; - - // All Dispatchers must minimally implement these methods. - - virtual Type GetType() const = 0; - virtual MojoResult Close() = 0; - - ///////////// Watcher API //////////////////// - - virtual MojoResult WatchDispatcher(scoped_refptr dispatcher, - MojoHandleSignals signals, - uintptr_t context); - virtual MojoResult CancelWatch(uintptr_t context); - virtual MojoResult Arm(uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states); - - ///////////// Message pipe API ///////////// - - virtual MojoResult WriteMessage(std::unique_ptr message, - MojoWriteMessageFlags flags); - - virtual MojoResult ReadMessage(std::unique_ptr* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags, - bool read_any_size); - - ///////////// Shared buffer API ///////////// - - // |options| may be null. |new_dispatcher| must not be null, but - // |*new_dispatcher| should be null (and will contain the dispatcher for the - // new handle on success). - virtual MojoResult DuplicateBufferHandle( - const MojoDuplicateBufferHandleOptions* options, - scoped_refptr* new_dispatcher); - - virtual MojoResult MapBuffer( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - std::unique_ptr* mapping); - - ///////////// Data pipe consumer API ///////////// - - virtual MojoResult ReadData(void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags); - - virtual MojoResult BeginReadData(const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags); - - virtual MojoResult EndReadData(uint32_t num_bytes_read); - - ///////////// Data pipe producer API ///////////// - - virtual MojoResult WriteData(const void* elements, - uint32_t* num_bytes, - MojoWriteDataFlags flags); - - virtual MojoResult BeginWriteData(void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags); - - virtual MojoResult EndWriteData(uint32_t num_bytes_written); - - ///////////// Wait set API ///////////// - - // Adds a dispatcher to wait on. When the dispatcher satisfies |signals|, it - // will be returned in the next call to |GetReadyDispatchers()|. If - // |dispatcher| has been added, it must be removed before adding again, - // otherwise |MOJO_RESULT_ALREADY_EXISTS| will be returned. - virtual MojoResult AddWaitingDispatcher( - const scoped_refptr& dispatcher, - MojoHandleSignals signals, - uintptr_t context); - - // Removes a dispatcher to wait on. If |dispatcher| has not been added, - // |MOJO_RESULT_NOT_FOUND| will be returned. - virtual MojoResult RemoveWaitingDispatcher( - const scoped_refptr& dispatcher); - - // Returns a set of ready dispatchers. |*count| is the maximum number of - // dispatchers to return, and will contain the number of dispatchers returned - // in |dispatchers| on completion. - virtual MojoResult GetReadyDispatchers(uint32_t* count, - DispatcherVector* dispatchers, - MojoResult* results, - uintptr_t* contexts); - - ///////////// General-purpose API for all handle types ///////// - - // Gets the current handle signals state. (The default implementation simply - // returns a default-constructed |HandleSignalsState|, i.e., no signals - // satisfied or satisfiable.) Note: The state is subject to change from other - // threads. - virtual HandleSignalsState GetHandleSignalsState() const; - - // Adds a WatcherDispatcher reference to this dispatcher, to be notified of - // all subsequent changes to handle state including signal changes or closure. - // The reference is associated with a |context| for disambiguation of - // removals. - virtual MojoResult AddWatcherRef( - const scoped_refptr& watcher, - uintptr_t context); - - // Removes a WatcherDispatcher reference from this dispatcher. - virtual MojoResult RemoveWatcherRef(WatcherDispatcher* watcher, - uintptr_t context); - - // Informs the caller of the total serialized size (in bytes) and the total - // number of platform handles and ports needed to transfer this dispatcher - // across a message pipe. - // - // Must eventually be followed by a call to EndSerializeAndClose(). Note that - // StartSerialize() and EndSerialize() are always called in sequence, and - // only between calls to BeginTransit() and either (but not both) - // CompleteTransitAndClose() or CancelTransit(). - // - // For this reason it is IMPERATIVE that the implementation ensure a - // consistent serializable state between BeginTransit() and - // CompleteTransitAndClose()/CancelTransit(). - virtual void StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_platform_handles); - - // Serializes this dispatcher into |destination|, |ports|, and |handles|. - // Returns true iff successful, false otherwise. In either case the dispatcher - // will close. - // - // NOTE: Transit MAY still fail after this call returns. Implementations - // should not assume PlatformHandle ownership has transferred until - // CompleteTransitAndClose() is called. In other words, if CancelTransit() is - // called, the implementation should retain its PlatformHandles in working - // condition. - virtual bool EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles); - - // Does whatever is necessary to begin transit of the dispatcher. This - // should return |true| if transit is OK, or false if the underlying resource - // is deemed busy by the implementation. - virtual bool BeginTransit(); - - // Does whatever is necessary to complete transit of the dispatcher, including - // closure. This is only called upon successfully transmitting an outgoing - // message containing this serialized dispatcher. - virtual void CompleteTransitAndClose(); - - // Does whatever is necessary to cancel transit of the dispatcher. The - // dispatcher should remain in a working state and resume normal operation. - virtual void CancelTransit(); - - // Deserializes a specific dispatcher type from an incoming message. - static scoped_refptr Deserialize( - Type type, - const void* bytes, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* platform_handles, - size_t num_platform_handles); - - protected: - friend class base::RefCountedThreadSafe; - - Dispatcher(); - virtual ~Dispatcher(); - - DISALLOW_COPY_AND_ASSIGN(Dispatcher); -}; - -// So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out, - Dispatcher::Type type) { - return out << static_cast(type); -} - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_DISPATCHER_H_ diff --git a/mojo/edk/system/handle_signals_state.h b/mojo/edk/system/handle_signals_state.h deleted file mode 100644 index f241278..0000000 --- a/mojo/edk/system/handle_signals_state.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ -#define MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ - -#include "mojo/public/cpp/system/handle_signals_state.h" - -// TODO(rockot): Remove this header and use the C++ system library type -// directly inside the EDK. - -#endif // MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ diff --git a/mojo/edk/system/handle_table.cc b/mojo/edk/system/handle_table.cc deleted file mode 100644 index b570793..0000000 --- a/mojo/edk/system/handle_table.cc +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/handle_table.h" - -#include - -#include - -namespace mojo { -namespace edk { - -HandleTable::HandleTable() {} - -HandleTable::~HandleTable() {} - -MojoHandle HandleTable::AddDispatcher(scoped_refptr dispatcher) { - // Oops, we're out of handles. - if (next_available_handle_ == MOJO_HANDLE_INVALID) - return MOJO_HANDLE_INVALID; - - MojoHandle handle = next_available_handle_++; - auto result = - handles_.insert(std::make_pair(handle, Entry(std::move(dispatcher)))); - DCHECK(result.second); - - return handle; -} - -bool HandleTable::AddDispatchersFromTransit( - const std::vector& dispatchers, - MojoHandle* handles) { - // Oops, we're out of handles. - if (next_available_handle_ == MOJO_HANDLE_INVALID) - return false; - - DCHECK_LE(dispatchers.size(), std::numeric_limits::max()); - // If this insertion would cause handle overflow, we're out of handles. - if (next_available_handle_ + dispatchers.size() < next_available_handle_) - return false; - - for (size_t i = 0; i < dispatchers.size(); ++i) { - MojoHandle handle = next_available_handle_++; - auto result = handles_.insert( - std::make_pair(handle, Entry(dispatchers[i].dispatcher))); - DCHECK(result.second); - handles[i] = handle; - } - - return true; -} - -scoped_refptr HandleTable::GetDispatcher(MojoHandle handle) const { - auto it = handles_.find(handle); - if (it == handles_.end()) - return nullptr; - return it->second.dispatcher; -} - -MojoResult HandleTable::GetAndRemoveDispatcher( - MojoHandle handle, - scoped_refptr* dispatcher) { - auto it = handles_.find(handle); - if (it == handles_.end()) - return MOJO_RESULT_INVALID_ARGUMENT; - if (it->second.busy) - return MOJO_RESULT_BUSY; - - *dispatcher = std::move(it->second.dispatcher); - handles_.erase(it); - return MOJO_RESULT_OK; -} - -MojoResult HandleTable::BeginTransit( - const MojoHandle* handles, - uint32_t num_handles, - std::vector* dispatchers) { - dispatchers->clear(); - dispatchers->reserve(num_handles); - for (size_t i = 0; i < num_handles; ++i) { - auto it = handles_.find(handles[i]); - if (it == handles_.end()) - return MOJO_RESULT_INVALID_ARGUMENT; - if (it->second.busy) - return MOJO_RESULT_BUSY; - - Dispatcher::DispatcherInTransit d; - d.local_handle = handles[i]; - d.dispatcher = it->second.dispatcher; - if (!d.dispatcher->BeginTransit()) - return MOJO_RESULT_BUSY; - it->second.busy = true; - dispatchers->push_back(d); - } - return MOJO_RESULT_OK; -} - -void HandleTable::CompleteTransitAndClose( - const std::vector& dispatchers) { - for (const auto& dispatcher : dispatchers) { - auto it = handles_.find(dispatcher.local_handle); - DCHECK(it != handles_.end() && it->second.busy); - handles_.erase(it); - dispatcher.dispatcher->CompleteTransitAndClose(); - } -} - -void HandleTable::CancelTransit( - const std::vector& dispatchers) { - for (const auto& dispatcher : dispatchers) { - auto it = handles_.find(dispatcher.local_handle); - DCHECK(it != handles_.end() && it->second.busy); - it->second.busy = false; - dispatcher.dispatcher->CancelTransit(); - } -} - -void HandleTable::GetActiveHandlesForTest(std::vector* handles) { - handles->clear(); - for (const auto& entry : handles_) - handles->push_back(entry.first); -} - -HandleTable::Entry::Entry() {} - -HandleTable::Entry::Entry(scoped_refptr dispatcher) - : dispatcher(std::move(dispatcher)) {} - -HandleTable::Entry::Entry(const Entry& other) = default; - -HandleTable::Entry::~Entry() {} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/handle_table.h b/mojo/edk/system/handle_table.h deleted file mode 100644 index 882d540..0000000 --- a/mojo/edk/system/handle_table.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_HANDLE_TABLE_H_ -#define MOJO_EDK_SYSTEM_HANDLE_TABLE_H_ - -#include - -#include - -#include "base/containers/hash_tables.h" -#include "base/macros.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/public/c/system/types.h" - -namespace mojo { -namespace edk { - -class HandleTable { - public: - HandleTable(); - ~HandleTable(); - - MojoHandle AddDispatcher(scoped_refptr dispatcher); - - // Inserts multiple dispatchers received from message transit, populating - // |handles| with their newly allocated handles. Returns |true| on success. - bool AddDispatchersFromTransit( - const std::vector& dispatchers, - MojoHandle* handles); - - scoped_refptr GetDispatcher(MojoHandle handle) const; - MojoResult GetAndRemoveDispatcher(MojoHandle, - scoped_refptr* dispatcher); - - // Marks handles as busy and populates |dispatchers|. Returns MOJO_RESULT_BUSY - // if any of the handles are already in transit; MOJO_RESULT_INVALID_ARGUMENT - // if any of the handles are invalid; or MOJO_RESULT_OK if successful. - MojoResult BeginTransit( - const MojoHandle* handles, - uint32_t num_handles, - std::vector* dispatchers); - - void CompleteTransitAndClose( - const std::vector& dispatchers); - void CancelTransit( - const std::vector& dispatchers); - - void GetActiveHandlesForTest(std::vector *handles); - - private: - struct Entry { - Entry(); - explicit Entry(scoped_refptr dispatcher); - Entry(const Entry& other); - ~Entry(); - - scoped_refptr dispatcher; - bool busy = false; - }; - - using HandleMap = base::hash_map; - - HandleMap handles_; - - uint32_t next_available_handle_ = 1; - - DISALLOW_COPY_AND_ASSIGN(HandleTable); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_HANDLE_TABLE_H_ diff --git a/mojo/edk/system/mach_port_relay.cc b/mojo/edk/system/mach_port_relay.cc deleted file mode 100644 index f05cf22..0000000 --- a/mojo/edk/system/mach_port_relay.cc +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/mach_port_relay.h" - -#include - -#include - -#include "base/logging.h" -#include "base/mac/mach_port_util.h" -#include "base/mac/scoped_mach_port.h" -#include "base/metrics/histogram_macros.h" -#include "base/process/process.h" -#include "mojo/edk/embedder/platform_handle_vector.h" - -namespace mojo { -namespace edk { - -namespace { - -// Errors that can occur in the broker (privileged parent) process. -// These match tools/metrics/histograms.xml. -// This enum is append-only. -enum class BrokerUMAError : int { - SUCCESS = 0, - // Couldn't get a task port for the process with a given pid. - ERROR_TASK_FOR_PID = 1, - // Couldn't make a port with receive rights in the destination process. - ERROR_MAKE_RECEIVE_PORT = 2, - // Couldn't change the attributes of a Mach port. - ERROR_SET_ATTRIBUTES = 3, - // Couldn't extract a right from the destination. - ERROR_EXTRACT_DEST_RIGHT = 4, - // Couldn't send a Mach port in a call to mach_msg(). - ERROR_SEND_MACH_PORT = 5, - // Couldn't extract a right from the source. - ERROR_EXTRACT_SOURCE_RIGHT = 6, - ERROR_MAX -}; - -// Errors that can occur in a child process. -// These match tools/metrics/histograms.xml. -// This enum is append-only. -enum class ChildUMAError : int { - SUCCESS = 0, - // An error occurred while trying to receive a Mach port with mach_msg(). - ERROR_RECEIVE_MACH_MESSAGE = 1, - ERROR_MAX -}; - -void ReportBrokerError(BrokerUMAError error) { - UMA_HISTOGRAM_ENUMERATION("Mojo.MachPortRelay.BrokerError", - static_cast(error), - static_cast(BrokerUMAError::ERROR_MAX)); -} - -void ReportChildError(ChildUMAError error) { - UMA_HISTOGRAM_ENUMERATION("Mojo.MachPortRelay.ChildError", - static_cast(error), - static_cast(ChildUMAError::ERROR_MAX)); -} - -} // namespace - -// static -bool MachPortRelay::ReceivePorts(PlatformHandleVector* handles) { - DCHECK(handles); - - for (size_t i = 0; i < handles->size(); i++) { - PlatformHandle* handle = handles->data() + i; - DCHECK(handle->type != PlatformHandle::Type::MACH); - if (handle->type != PlatformHandle::Type::MACH_NAME) - continue; - - if (handle->port == MACH_PORT_NULL) { - handle->type = PlatformHandle::Type::MACH; - continue; - } - - base::mac::ScopedMachReceiveRight message_port(handle->port); - base::mac::ScopedMachSendRight received_port( - base::ReceiveMachPort(message_port.get())); - if (received_port.get() == MACH_PORT_NULL) { - ReportChildError(ChildUMAError::ERROR_RECEIVE_MACH_MESSAGE); - handle->port = MACH_PORT_NULL; - LOG(ERROR) << "Error receiving mach port"; - return false; - } - - ReportChildError(ChildUMAError::SUCCESS); - handle->port = received_port.release(); - handle->type = PlatformHandle::Type::MACH; - } - - return true; -} - -MachPortRelay::MachPortRelay(base::PortProvider* port_provider) - : port_provider_(port_provider) { - DCHECK(port_provider); - port_provider_->AddObserver(this); -} - -MachPortRelay::~MachPortRelay() { - port_provider_->RemoveObserver(this); -} - -bool MachPortRelay::SendPortsToProcess(Channel::Message* message, - base::ProcessHandle process) { - DCHECK(message); - mach_port_t task_port = port_provider_->TaskForPid(process); - if (task_port == MACH_PORT_NULL) { - // Callers check the port provider for the task port before calling this - // function, in order to queue pending messages. Therefore, if this fails, - // it should be considered a genuine, bona fide, electrified, six-car error. - ReportBrokerError(BrokerUMAError::ERROR_TASK_FOR_PID); - return false; - } - - size_t num_sent = 0; - bool error = false; - ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); - // Message should have handles, otherwise there's no point in calling this - // function. - DCHECK(handles); - for (size_t i = 0; i < handles->size(); i++) { - PlatformHandle* handle = &(*handles)[i]; - DCHECK(handle->type != PlatformHandle::Type::MACH_NAME); - if (handle->type != PlatformHandle::Type::MACH) - continue; - - if (handle->port == MACH_PORT_NULL) { - handle->type = PlatformHandle::Type::MACH_NAME; - num_sent++; - continue; - } - - mach_port_name_t intermediate_port; - base::MachCreateError error_code; - intermediate_port = base::CreateIntermediateMachPort( - task_port, base::mac::ScopedMachSendRight(handle->port), &error_code); - if (intermediate_port == MACH_PORT_NULL) { - BrokerUMAError uma_error; - switch (error_code) { - case base::MachCreateError::ERROR_MAKE_RECEIVE_PORT: - uma_error = BrokerUMAError::ERROR_MAKE_RECEIVE_PORT; - break; - case base::MachCreateError::ERROR_SET_ATTRIBUTES: - uma_error = BrokerUMAError::ERROR_SET_ATTRIBUTES; - break; - case base::MachCreateError::ERROR_EXTRACT_DEST_RIGHT: - uma_error = BrokerUMAError::ERROR_EXTRACT_DEST_RIGHT; - break; - case base::MachCreateError::ERROR_SEND_MACH_PORT: - uma_error = BrokerUMAError::ERROR_SEND_MACH_PORT; - break; - } - ReportBrokerError(uma_error); - handle->port = MACH_PORT_NULL; - error = true; - break; - } - - ReportBrokerError(BrokerUMAError::SUCCESS); - handle->port = intermediate_port; - handle->type = PlatformHandle::Type::MACH_NAME; - num_sent++; - } - DCHECK(error || num_sent); - message->SetHandles(std::move(handles)); - - return !error; -} - -bool MachPortRelay::ExtractPortRights(Channel::Message* message, - base::ProcessHandle process) { - DCHECK(message); - - mach_port_t task_port = port_provider_->TaskForPid(process); - if (task_port == MACH_PORT_NULL) { - ReportBrokerError(BrokerUMAError::ERROR_TASK_FOR_PID); - return false; - } - - size_t num_received = 0; - bool error = false; - ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); - // Message should have handles, otherwise there's no point in calling this - // function. - DCHECK(handles); - for (size_t i = 0; i < handles->size(); i++) { - PlatformHandle* handle = handles->data() + i; - DCHECK(handle->type != PlatformHandle::Type::MACH); - if (handle->type != PlatformHandle::Type::MACH_NAME) - continue; - - if (handle->port == MACH_PORT_NULL) { - handle->type = PlatformHandle::Type::MACH; - num_received++; - continue; - } - - mach_port_t extracted_right = MACH_PORT_NULL; - mach_msg_type_name_t extracted_right_type; - kern_return_t kr = - mach_port_extract_right(task_port, handle->port, - MACH_MSG_TYPE_MOVE_SEND, - &extracted_right, &extracted_right_type); - if (kr != KERN_SUCCESS) { - ReportBrokerError(BrokerUMAError::ERROR_EXTRACT_SOURCE_RIGHT); - error = true; - break; - } - - ReportBrokerError(BrokerUMAError::SUCCESS); - DCHECK_EQ(static_cast(MACH_MSG_TYPE_PORT_SEND), - extracted_right_type); - handle->port = extracted_right; - handle->type = PlatformHandle::Type::MACH; - num_received++; - } - DCHECK(error || num_received); - message->SetHandles(std::move(handles)); - - return !error; -} - -void MachPortRelay::AddObserver(Observer* observer) { - base::AutoLock locker(observers_lock_); - bool inserted = observers_.insert(observer).second; - DCHECK(inserted); -} - -void MachPortRelay::RemoveObserver(Observer* observer) { - base::AutoLock locker(observers_lock_); - observers_.erase(observer); -} - -void MachPortRelay::OnReceivedTaskPort(base::ProcessHandle process) { - base::AutoLock locker(observers_lock_); - for (auto* observer : observers_) - observer->OnProcessReady(process); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/mach_port_relay.h b/mojo/edk/system/mach_port_relay.h deleted file mode 100644 index 87bc56c..0000000 --- a/mojo/edk/system/mach_port_relay.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_MACH_PORT_RELAY_H_ -#define MOJO_EDK_SYSTEM_MACH_PORT_RELAY_H_ - -#include - -#include "base/macros.h" -#include "base/process/port_provider_mac.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/channel.h" - -namespace mojo { -namespace edk { - -// The MachPortRelay is used by a privileged process, usually the root process, -// to manipulate Mach ports in a child process. Ports can be added to and -// extracted from a child process that has registered itself with the -// |base::PortProvider| used by this class. -class MachPortRelay : public base::PortProvider::Observer { - public: - class Observer { - public: - // Called by the MachPortRelay to notify observers that a new process is - // ready for Mach ports to be sent/received. There are no guarantees about - // the thread this is called on, including the presence of a MessageLoop. - // Implementations must not call AddObserver() or RemoveObserver() during - // this function, as doing so will deadlock. - virtual void OnProcessReady(base::ProcessHandle process) = 0; - }; - - // Used by a child process to receive Mach ports from a sender (privileged) - // process. Each Mach port in |handles| is interpreted as an intermediate Mach - // port. It replaces each Mach port with the final Mach port received from the - // intermediate port. This method takes ownership of the intermediate Mach - // port and gives ownership of the final Mach port to the caller. Any handles - // that are not Mach ports will remain unchanged, and the number and ordering - // of handles is preserved. - // Returns |false| on failure and there is no guarantee about whether a Mach - // port is intermediate or final. - // - // See SendPortsToProcess() for the definition of intermediate and final Mach - // ports. - static bool ReceivePorts(PlatformHandleVector* handles); - - explicit MachPortRelay(base::PortProvider* port_provider); - ~MachPortRelay() override; - - // Sends the Mach ports attached to |message| to |process|. - // For each Mach port attached to |message|, a new Mach port, the intermediate - // port, is created in |process|. The message's Mach port is then sent over - // this intermediate port and the message is modified to refer to the name of - // the intermediate port. The Mach port received over the intermediate port in - // the child is referred to as the final Mach port. - // Returns |false| on failure and |message| may contain a mix of actual Mach - // ports and names. - bool SendPortsToProcess(Channel::Message* message, - base::ProcessHandle process); - - // Extracts the Mach ports attached to |message| from |process|. - // Any Mach ports attached to |message| are names and not actual Mach ports - // that are valid in this process. For each of those Mach port names, a send - // right is extracted from |process| and the port name is replaced with the - // send right. - // Returns |false| on failure and |message| may contain a mix of actual Mach - // ports and names. - bool ExtractPortRights(Channel::Message* message, - base::ProcessHandle process); - - // Observer interface. - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - base::PortProvider* port_provider() const { return port_provider_; } - - private: - // base::PortProvider::Observer implementation. - void OnReceivedTaskPort(base::ProcessHandle process) override; - - base::PortProvider* const port_provider_; - - base::Lock observers_lock_; - std::set observers_; - - DISALLOW_COPY_AND_ASSIGN(MachPortRelay); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_MACH_PORT_RELAY_H_ diff --git a/mojo/edk/system/mapping_table.cc b/mojo/edk/system/mapping_table.cc deleted file mode 100644 index 8509443..0000000 --- a/mojo/edk/system/mapping_table.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/mapping_table.h" - -#include "base/logging.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/configuration.h" - -namespace mojo { -namespace edk { - -MappingTable::MappingTable() { -} - -MappingTable::~MappingTable() { - // This should usually not be reached (the only instance should be owned by - // the singleton |Core|, which lives forever), except in tests. -} - -MojoResult MappingTable::AddMapping( - std::unique_ptr mapping) { - DCHECK(mapping); - - if (address_to_mapping_map_.size() >= - GetConfiguration().max_mapping_table_sze) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - void* address = mapping->GetBase(); - DCHECK(address_to_mapping_map_.find(address) == - address_to_mapping_map_.end()); - address_to_mapping_map_[address] = mapping.release(); - return MOJO_RESULT_OK; -} - -MojoResult MappingTable::RemoveMapping(void* address) { - AddressToMappingMap::iterator it = address_to_mapping_map_.find(address); - if (it == address_to_mapping_map_.end()) - return MOJO_RESULT_INVALID_ARGUMENT; - PlatformSharedBufferMapping* mapping_to_delete = it->second; - address_to_mapping_map_.erase(it); - delete mapping_to_delete; - return MOJO_RESULT_OK; -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/mapping_table.h b/mojo/edk/system/mapping_table.h deleted file mode 100644 index 00167e3..0000000 --- a/mojo/edk/system/mapping_table.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_SYSTEM_MAPPING_TABLE_H_ -#define MOJO_EDK_SYSTEM_MAPPING_TABLE_H_ - -#include - -#include -#include - -#include "base/containers/hash_tables.h" -#include "base/macros.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/types.h" - -namespace mojo { - -namespace edk { -class Core; -class PlatformSharedBufferMapping; - -// Test-only function (defined/used in embedder/test_embedder.cc). Declared here -// so it can be friended. -namespace internal { -bool ShutdownCheckNoLeaks(Core*); -} - -// This class provides the (global) table of memory mappings (owned by |Core|), -// which maps mapping base addresses to |PlatformSharedBufferMapping|s. -// -// This class is NOT thread-safe; locking is left to |Core|. -class MOJO_SYSTEM_IMPL_EXPORT MappingTable { - public: - MappingTable(); - ~MappingTable(); - - // Tries to add a mapping. (Takes ownership of the mapping in all cases; on - // failure, it will be destroyed.) - MojoResult AddMapping(std::unique_ptr mapping); - MojoResult RemoveMapping(void* address); - - private: - friend bool internal::ShutdownCheckNoLeaks(Core*); - - using AddressToMappingMap = - base::hash_map; - AddressToMappingMap address_to_mapping_map_; - - DISALLOW_COPY_AND_ASSIGN(MappingTable); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_MAPPING_TABLE_H_ diff --git a/mojo/edk/system/message_for_transit.cc b/mojo/edk/system/message_for_transit.cc deleted file mode 100644 index 26658e1..0000000 --- a/mojo/edk/system/message_for_transit.cc +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/message_for_transit.h" - -#include - -#include "mojo/edk/embedder/platform_handle_vector.h" - -namespace mojo { -namespace edk { - -namespace { - -static_assert(sizeof(MessageForTransit::MessageHeader) % 8 == 0, - "Invalid MessageHeader size."); -static_assert(sizeof(MessageForTransit::DispatcherHeader) % 8 == 0, - "Invalid DispatcherHeader size."); - -} // namespace - -MessageForTransit::~MessageForTransit() {} - -// static -MojoResult MessageForTransit::Create( - std::unique_ptr* message, - uint32_t num_bytes, - const Dispatcher::DispatcherInTransit* dispatchers, - uint32_t num_dispatchers) { - // A structure for retaining information about every Dispatcher that will be - // sent with this message. - struct DispatcherInfo { - uint32_t num_bytes; - uint32_t num_ports; - uint32_t num_handles; - }; - - // This is only the base header size. It will grow as we accumulate the - // size of serialized state for each dispatcher. - size_t header_size = sizeof(MessageHeader) + - num_dispatchers * sizeof(DispatcherHeader); - size_t num_ports = 0; - size_t num_handles = 0; - - std::vector dispatcher_info(num_dispatchers); - for (size_t i = 0; i < num_dispatchers; ++i) { - Dispatcher* d = dispatchers[i].dispatcher.get(); - d->StartSerialize(&dispatcher_info[i].num_bytes, - &dispatcher_info[i].num_ports, - &dispatcher_info[i].num_handles); - header_size += dispatcher_info[i].num_bytes; - num_ports += dispatcher_info[i].num_ports; - num_handles += dispatcher_info[i].num_handles; - } - - // We now have enough information to fully allocate the message storage. - std::unique_ptr msg = PortsMessage::NewUserMessage( - header_size + num_bytes, num_ports, num_handles); - if (!msg) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - // Populate the message header with information about serialized dispatchers. - // - // The front of the message is always a MessageHeader followed by a - // DispatcherHeader for each dispatcher to be sent. - MessageHeader* header = - static_cast(msg->mutable_payload_bytes()); - DispatcherHeader* dispatcher_headers = - reinterpret_cast(header + 1); - - // Serialized dispatcher state immediately follows the series of - // DispatcherHeaders. - char* dispatcher_data = - reinterpret_cast(dispatcher_headers + num_dispatchers); - - header->num_dispatchers = num_dispatchers; - - // |header_size| is the total number of bytes preceding the message payload, - // including all dispatcher headers and serialized dispatcher state. - DCHECK_LE(header_size, std::numeric_limits::max()); - header->header_size = static_cast(header_size); - - if (num_dispatchers > 0) { - ScopedPlatformHandleVectorPtr handles( - new PlatformHandleVector(num_handles)); - size_t port_index = 0; - size_t handle_index = 0; - bool fail = false; - for (size_t i = 0; i < num_dispatchers; ++i) { - Dispatcher* d = dispatchers[i].dispatcher.get(); - DispatcherHeader* dh = &dispatcher_headers[i]; - const DispatcherInfo& info = dispatcher_info[i]; - - // Fill in the header for this dispatcher. - dh->type = static_cast(d->GetType()); - dh->num_bytes = info.num_bytes; - dh->num_ports = info.num_ports; - dh->num_platform_handles = info.num_handles; - - // Fill in serialized state, ports, and platform handles. We'll cancel - // the send if the dispatcher implementation rejects for some reason. - if (!d->EndSerialize(static_cast(dispatcher_data), - msg->mutable_ports() + port_index, - handles->data() + handle_index)) { - fail = true; - break; - } - - dispatcher_data += info.num_bytes; - port_index += info.num_ports; - handle_index += info.num_handles; - } - - if (fail) { - // Release any platform handles we've accumulated. Their dispatchers - // retain ownership when message creation fails, so these are not actually - // leaking. - handles->clear(); - return MOJO_RESULT_INVALID_ARGUMENT; - } - - // Take ownership of all the handles and move them into message storage. - msg->SetHandles(std::move(handles)); - } - - message->reset(new MessageForTransit(std::move(msg))); - return MOJO_RESULT_OK; -} - -MessageForTransit::MessageForTransit(std::unique_ptr message) - : message_(std::move(message)) { -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/message_for_transit.h b/mojo/edk/system/message_for_transit.h deleted file mode 100644 index 6103a77..0000000 --- a/mojo/edk/system/message_for_transit.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_MESSAGE_FOR_TRANSIT_H_ -#define MOJO_EDK_SYSTEM_MESSAGE_FOR_TRANSIT_H_ - -#include - -#include - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/ports_message.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -// MessageForTransit holds onto a PortsMessage which may be sent via -// |MojoWriteMessage()| or which may have been received on a pipe endpoint. -// Instances of this class are exposed to Mojo system API consumers via the -// opaque pointers used with |MojoCreateMessage()|, |MojoDestroyMessage()|, -// |MojoWriteMessageNew()|, and |MojoReadMessageNew()|. -class MOJO_SYSTEM_IMPL_EXPORT MessageForTransit { - public: -#pragma pack(push, 1) - // Header attached to every message. - struct MessageHeader { - // The number of serialized dispatchers included in this header. - uint32_t num_dispatchers; - - // Total size of the header, including serialized dispatcher data. - uint32_t header_size; - }; - - // Header for each dispatcher in a message, immediately following the message - // header. - struct DispatcherHeader { - // The type of the dispatcher, correpsonding to the Dispatcher::Type enum. - int32_t type; - - // The size of the serialized dispatcher, not including this header. - uint32_t num_bytes; - - // The number of ports needed to deserialize this dispatcher. - uint32_t num_ports; - - // The number of platform handles needed to deserialize this dispatcher. - uint32_t num_platform_handles; - }; -#pragma pack(pop) - - ~MessageForTransit(); - - // A static constructor for building outbound messages. - static MojoResult Create( - std::unique_ptr* message, - uint32_t num_bytes, - const Dispatcher::DispatcherInTransit* dispatchers, - uint32_t num_dispatchers); - - // A static constructor for wrapping inbound messages. - static std::unique_ptr WrapPortsMessage( - std::unique_ptr message) { - return base::WrapUnique(new MessageForTransit(std::move(message))); - } - - const void* bytes() const { - DCHECK(message_); - return static_cast( - static_cast(message_->payload_bytes()) + - header()->header_size); - } - - void* mutable_bytes() { - DCHECK(message_); - return static_cast( - static_cast(message_->mutable_payload_bytes()) + - header()->header_size); - } - - size_t num_bytes() const { - size_t header_size = header()->header_size; - DCHECK_GE(message_->num_payload_bytes(), header_size); - return message_->num_payload_bytes() - header_size; - } - - size_t num_handles() const { return header()->num_dispatchers; } - - const PortsMessage& ports_message() const { return *message_; } - - std::unique_ptr TakePortsMessage() { - return std::move(message_); - } - - private: - explicit MessageForTransit(std::unique_ptr message); - - const MessageForTransit::MessageHeader* header() const { - DCHECK(message_); - return static_cast( - message_->payload_bytes()); - } - - std::unique_ptr message_; - - DISALLOW_COPY_AND_ASSIGN(MessageForTransit); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_MESSAGE_FOR_TRANSIT_H_ diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc deleted file mode 100644 index 1db56c0..0000000 --- a/mojo/edk/system/message_pipe_dispatcher.cc +++ /dev/null @@ -1,554 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/message_pipe_dispatcher.h" - -#include -#include - -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/core.h" -#include "mojo/edk/system/message_for_transit.h" -#include "mojo/edk/system/node_controller.h" -#include "mojo/edk/system/ports/message_filter.h" -#include "mojo/edk/system/ports_message.h" -#include "mojo/edk/system/request_context.h" - -namespace mojo { -namespace edk { - -namespace { - -using DispatcherHeader = MessageForTransit::DispatcherHeader; -using MessageHeader = MessageForTransit::MessageHeader; - -#pragma pack(push, 1) - -struct SerializedState { - uint64_t pipe_id; - int8_t endpoint; - char padding[7]; -}; - -static_assert(sizeof(SerializedState) % 8 == 0, - "Invalid SerializedState size."); - -#pragma pack(pop) - -} // namespace - -// A PortObserver which forwards to a MessagePipeDispatcher. This owns a -// reference to the MPD to ensure it lives as long as the observed port. -class MessagePipeDispatcher::PortObserverThunk - : public NodeController::PortObserver { - public: - explicit PortObserverThunk(scoped_refptr dispatcher) - : dispatcher_(dispatcher) {} - - private: - ~PortObserverThunk() override {} - - // NodeController::PortObserver: - void OnPortStatusChanged() override { dispatcher_->OnPortStatusChanged(); } - - scoped_refptr dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(PortObserverThunk); -}; - -// A MessageFilter used by ReadMessage to determine whether a message should -// actually be consumed yet. -class ReadMessageFilter : public ports::MessageFilter { - public: - // Creates a new ReadMessageFilter which captures and potentially modifies - // various (unowned) local state within MessagePipeDispatcher::ReadMessage. - ReadMessageFilter(bool read_any_size, - bool may_discard, - uint32_t* num_bytes, - uint32_t* num_handles, - bool* no_space, - bool* invalid_message) - : read_any_size_(read_any_size), - may_discard_(may_discard), - num_bytes_(num_bytes), - num_handles_(num_handles), - no_space_(no_space), - invalid_message_(invalid_message) {} - - ~ReadMessageFilter() override {} - - // ports::MessageFilter: - bool Match(const ports::Message& m) override { - const PortsMessage& message = static_cast(m); - if (message.num_payload_bytes() < sizeof(MessageHeader)) { - *invalid_message_ = true; - return true; - } - - const MessageHeader* header = - static_cast(message.payload_bytes()); - if (header->header_size > message.num_payload_bytes()) { - *invalid_message_ = true; - return true; - } - - uint32_t bytes_to_read = 0; - uint32_t bytes_available = - static_cast(message.num_payload_bytes()) - - header->header_size; - if (num_bytes_) { - bytes_to_read = std::min(*num_bytes_, bytes_available); - *num_bytes_ = bytes_available; - } - - uint32_t handles_to_read = 0; - uint32_t handles_available = header->num_dispatchers; - if (num_handles_) { - handles_to_read = std::min(*num_handles_, handles_available); - *num_handles_ = handles_available; - } - - if (handles_to_read < handles_available || - (!read_any_size_ && bytes_to_read < bytes_available)) { - *no_space_ = true; - return may_discard_; - } - - return true; - } - - private: - const bool read_any_size_; - const bool may_discard_; - uint32_t* const num_bytes_; - uint32_t* const num_handles_; - bool* const no_space_; - bool* const invalid_message_; - - DISALLOW_COPY_AND_ASSIGN(ReadMessageFilter); -}; - -#if DCHECK_IS_ON() - -// A MessageFilter which never matches a message. Used to peek at the size of -// the next available message on a port, for debug logging only. -class PeekSizeMessageFilter : public ports::MessageFilter { - public: - PeekSizeMessageFilter() {} - ~PeekSizeMessageFilter() override {} - - // ports::MessageFilter: - bool Match(const ports::Message& message) override { - message_size_ = message.num_payload_bytes(); - return false; - } - - size_t message_size() const { return message_size_; } - - private: - size_t message_size_ = 0; - - DISALLOW_COPY_AND_ASSIGN(PeekSizeMessageFilter); -}; - -#endif // DCHECK_IS_ON() - -MessagePipeDispatcher::MessagePipeDispatcher(NodeController* node_controller, - const ports::PortRef& port, - uint64_t pipe_id, - int endpoint) - : node_controller_(node_controller), - port_(port), - pipe_id_(pipe_id), - endpoint_(endpoint), - watchers_(this) { - DVLOG(2) << "Creating new MessagePipeDispatcher for port " << port.name() - << " [pipe_id=" << pipe_id << "; endpoint=" << endpoint << "]"; - - node_controller_->SetPortObserver( - port_, - make_scoped_refptr(new PortObserverThunk(this))); -} - -bool MessagePipeDispatcher::Fuse(MessagePipeDispatcher* other) { - node_controller_->SetPortObserver(port_, nullptr); - node_controller_->SetPortObserver(other->port_, nullptr); - - ports::PortRef port0; - { - base::AutoLock lock(signal_lock_); - port0 = port_; - port_closed_.Set(true); - watchers_.NotifyClosed(); - } - - ports::PortRef port1; - { - base::AutoLock lock(other->signal_lock_); - port1 = other->port_; - other->port_closed_.Set(true); - other->watchers_.NotifyClosed(); - } - - // Both ports are always closed by this call. - int rv = node_controller_->MergeLocalPorts(port0, port1); - return rv == ports::OK; -} - -Dispatcher::Type MessagePipeDispatcher::GetType() const { - return Type::MESSAGE_PIPE; -} - -MojoResult MessagePipeDispatcher::Close() { - base::AutoLock lock(signal_lock_); - DVLOG(2) << "Closing message pipe " << pipe_id_ << " endpoint " << endpoint_ - << " [port=" << port_.name() << "]"; - return CloseNoLock(); -} - -MojoResult MessagePipeDispatcher::WriteMessage( - std::unique_ptr message, - MojoWriteMessageFlags flags) { - if (port_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - size_t num_bytes = message->num_bytes(); - int rv = node_controller_->SendMessage(port_, message->TakePortsMessage()); - - DVLOG(4) << "Sent message on pipe " << pipe_id_ << " endpoint " << endpoint_ - << " [port=" << port_.name() << "; rv=" << rv - << "; num_bytes=" << num_bytes << "]"; - - if (rv != ports::OK) { - if (rv == ports::ERROR_PORT_UNKNOWN || - rv == ports::ERROR_PORT_STATE_UNEXPECTED || - rv == ports::ERROR_PORT_CANNOT_SEND_PEER) { - return MOJO_RESULT_INVALID_ARGUMENT; - } else if (rv == ports::ERROR_PORT_PEER_CLOSED) { - return MOJO_RESULT_FAILED_PRECONDITION; - } - - NOTREACHED(); - return MOJO_RESULT_UNKNOWN; - } - - return MOJO_RESULT_OK; -} - -MojoResult MessagePipeDispatcher::ReadMessage( - std::unique_ptr* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags, - bool read_any_size) { - // We can't read from a port that's closed or in transit! - if (port_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - bool no_space = false; - bool may_discard = flags & MOJO_READ_MESSAGE_FLAG_MAY_DISCARD; - bool invalid_message = false; - - // Grab a message if the provided handles buffer is large enough. If the input - // |num_bytes| is provided and |read_any_size| is false, we also ensure - // that it specifies a size at least as large as the next available payload. - // - // If |read_any_size| is true, the input value of |*num_bytes| is ignored. - // This flag exists to support both new and old API behavior. - - ports::ScopedMessage ports_message; - ReadMessageFilter filter(read_any_size, may_discard, num_bytes, num_handles, - &no_space, &invalid_message); - int rv = node_controller_->node()->GetMessage(port_, &ports_message, &filter); - - if (invalid_message) - return MOJO_RESULT_UNKNOWN; - - if (rv != ports::OK && rv != ports::ERROR_PORT_PEER_CLOSED) { - if (rv == ports::ERROR_PORT_UNKNOWN || - rv == ports::ERROR_PORT_STATE_UNEXPECTED) - return MOJO_RESULT_INVALID_ARGUMENT; - - NOTREACHED(); - return MOJO_RESULT_UNKNOWN; // TODO: Add a better error code here? - } - - if (no_space) { - if (may_discard) { - // May have been the last message on the pipe. Need to update signals just - // in case. - base::AutoLock lock(signal_lock_); - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - } - // |*num_handles| (and/or |*num_bytes| if |read_any_size| is false) wasn't - // sufficient to hold this message's data. The message will still be in - // queue unless MOJO_READ_MESSAGE_FLAG_MAY_DISCARD was set. - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - if (!ports_message) { - // No message was available in queue. - - if (rv == ports::OK) - return MOJO_RESULT_SHOULD_WAIT; - - // Peer is closed and there are no more messages to read. - DCHECK_EQ(rv, ports::ERROR_PORT_PEER_CLOSED); - return MOJO_RESULT_FAILED_PRECONDITION; - } - - // Alright! We have a message and the caller has provided sufficient storage - // in which to receive it. - - { - // We need to update anyone watching our signals in case that was the last - // available message. - base::AutoLock lock(signal_lock_); - watchers_.NotifyState(GetHandleSignalsStateNoLock()); - } - - std::unique_ptr msg( - static_cast(ports_message.release())); - - const MessageHeader* header = - static_cast(msg->payload_bytes()); - const DispatcherHeader* dispatcher_headers = - reinterpret_cast(header + 1); - - if (header->num_dispatchers > std::numeric_limits::max()) - return MOJO_RESULT_UNKNOWN; - - // Deserialize dispatchers. - if (header->num_dispatchers > 0) { - CHECK(handles); - std::vector dispatchers(header->num_dispatchers); - size_t data_payload_index = sizeof(MessageHeader) + - header->num_dispatchers * sizeof(DispatcherHeader); - if (data_payload_index > header->header_size) - return MOJO_RESULT_UNKNOWN; - const char* dispatcher_data = reinterpret_cast( - dispatcher_headers + header->num_dispatchers); - size_t port_index = 0; - size_t platform_handle_index = 0; - ScopedPlatformHandleVectorPtr msg_handles = msg->TakeHandles(); - const size_t num_msg_handles = msg_handles ? msg_handles->size() : 0; - for (size_t i = 0; i < header->num_dispatchers; ++i) { - const DispatcherHeader& dh = dispatcher_headers[i]; - Type type = static_cast(dh.type); - - size_t next_payload_index = data_payload_index + dh.num_bytes; - if (msg->num_payload_bytes() < next_payload_index || - next_payload_index < data_payload_index) { - return MOJO_RESULT_UNKNOWN; - } - - size_t next_port_index = port_index + dh.num_ports; - if (msg->num_ports() < next_port_index || next_port_index < port_index) - return MOJO_RESULT_UNKNOWN; - - size_t next_platform_handle_index = - platform_handle_index + dh.num_platform_handles; - if (num_msg_handles < next_platform_handle_index || - next_platform_handle_index < platform_handle_index) { - return MOJO_RESULT_UNKNOWN; - } - - PlatformHandle* out_handles = - num_msg_handles ? msg_handles->data() + platform_handle_index - : nullptr; - dispatchers[i].dispatcher = Dispatcher::Deserialize( - type, dispatcher_data, dh.num_bytes, msg->ports() + port_index, - dh.num_ports, out_handles, dh.num_platform_handles); - if (!dispatchers[i].dispatcher) - return MOJO_RESULT_UNKNOWN; - - dispatcher_data += dh.num_bytes; - data_payload_index = next_payload_index; - port_index = next_port_index; - platform_handle_index = next_platform_handle_index; - } - - if (!node_controller_->core()->AddDispatchersFromTransit(dispatchers, - handles)) - return MOJO_RESULT_UNKNOWN; - } - - CHECK(msg); - *message = MessageForTransit::WrapPortsMessage(std::move(msg)); - return MOJO_RESULT_OK; -} - -HandleSignalsState -MessagePipeDispatcher::GetHandleSignalsState() const { - base::AutoLock lock(signal_lock_); - return GetHandleSignalsStateNoLock(); -} - -MojoResult MessagePipeDispatcher::AddWatcherRef( - const scoped_refptr& watcher, - uintptr_t context) { - base::AutoLock lock(signal_lock_); - if (port_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - return watchers_.Add(watcher, context, GetHandleSignalsStateNoLock()); -} - -MojoResult MessagePipeDispatcher::RemoveWatcherRef(WatcherDispatcher* watcher, - uintptr_t context) { - base::AutoLock lock(signal_lock_); - if (port_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - return watchers_.Remove(watcher, context); -} - -void MessagePipeDispatcher::StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_handles) { - *num_bytes = static_cast(sizeof(SerializedState)); - *num_ports = 1; - *num_handles = 0; -} - -bool MessagePipeDispatcher::EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) { - SerializedState* state = static_cast(destination); - state->pipe_id = pipe_id_; - state->endpoint = static_cast(endpoint_); - memset(state->padding, 0, sizeof(state->padding)); - ports[0] = port_.name(); - return true; -} - -bool MessagePipeDispatcher::BeginTransit() { - base::AutoLock lock(signal_lock_); - if (in_transit_ || port_closed_) - return false; - in_transit_.Set(true); - return in_transit_; -} - -void MessagePipeDispatcher::CompleteTransitAndClose() { - node_controller_->SetPortObserver(port_, nullptr); - - base::AutoLock lock(signal_lock_); - port_transferred_ = true; - in_transit_.Set(false); - CloseNoLock(); -} - -void MessagePipeDispatcher::CancelTransit() { - base::AutoLock lock(signal_lock_); - in_transit_.Set(false); - - // Something may have happened while we were waiting for potential transit. - watchers_.NotifyState(GetHandleSignalsStateNoLock()); -} - -// static -scoped_refptr MessagePipeDispatcher::Deserialize( - const void* data, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* handles, - size_t num_handles) { - if (num_ports != 1 || num_handles || num_bytes != sizeof(SerializedState)) - return nullptr; - - const SerializedState* state = static_cast(data); - - ports::PortRef port; - CHECK_EQ( - ports::OK, - internal::g_core->GetNodeController()->node()->GetPort(ports[0], &port)); - - return new MessagePipeDispatcher(internal::g_core->GetNodeController(), port, - state->pipe_id, state->endpoint); -} - -MessagePipeDispatcher::~MessagePipeDispatcher() { - DCHECK(port_closed_ && !in_transit_); -} - -MojoResult MessagePipeDispatcher::CloseNoLock() { - signal_lock_.AssertAcquired(); - if (port_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - port_closed_.Set(true); - watchers_.NotifyClosed(); - - if (!port_transferred_) { - base::AutoUnlock unlock(signal_lock_); - node_controller_->ClosePort(port_); - } - - return MOJO_RESULT_OK; -} - -HandleSignalsState MessagePipeDispatcher::GetHandleSignalsStateNoLock() const { - HandleSignalsState rv; - - ports::PortStatus port_status; - if (node_controller_->node()->GetStatus(port_, &port_status) != ports::OK) { - CHECK(in_transit_ || port_transferred_ || port_closed_); - return HandleSignalsState(); - } - - if (port_status.has_messages) { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } - if (port_status.receiving_messages) - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - if (!port_status.peer_closed) { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_WRITABLE; - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE; - } else { - rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - } - rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; - return rv; -} - -void MessagePipeDispatcher::OnPortStatusChanged() { - DCHECK(RequestContext::current()); - - base::AutoLock lock(signal_lock_); - - // We stop observing our port as soon as it's transferred, but this can race - // with events which are raised right before that happens. This is fine to - // ignore. - if (port_transferred_) - return; - -#if DCHECK_IS_ON() - ports::PortStatus port_status; - if (node_controller_->node()->GetStatus(port_, &port_status) == ports::OK) { - if (port_status.has_messages) { - ports::ScopedMessage unused; - PeekSizeMessageFilter filter; - node_controller_->node()->GetMessage(port_, &unused, &filter); - DVLOG(4) << "New message detected on message pipe " << pipe_id_ - << " endpoint " << endpoint_ << " [port=" << port_.name() - << "; size=" << filter.message_size() << "]"; - } - if (port_status.peer_closed) { - DVLOG(2) << "Peer closure detected on message pipe " << pipe_id_ - << " endpoint " << endpoint_ << " [port=" << port_.name() << "]"; - } - } -#endif - - watchers_.NotifyState(GetHandleSignalsStateNoLock()); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/message_pipe_dispatcher.h b/mojo/edk/system/message_pipe_dispatcher.h deleted file mode 100644 index 574ad66..0000000 --- a/mojo/edk/system/message_pipe_dispatcher.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_ -#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_ - -#include - -#include -#include - -#include "base/macros.h" -#include "mojo/edk/system/atomic_flag.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/message_for_transit.h" -#include "mojo/edk/system/ports/port_ref.h" -#include "mojo/edk/system/watcher_set.h" - -namespace mojo { -namespace edk { - -class NodeController; - -class MessagePipeDispatcher : public Dispatcher { - public: - // Constructs a MessagePipeDispatcher permanently tied to a specific port. - // |connected| must indicate the state of the port at construction time; if - // the port is initialized with a peer, |connected| must be true. Otherwise it - // must be false. - // - // A MessagePipeDispatcher may not be transferred while in a disconnected - // state, and one can never return to a disconnected once connected. - // - // |pipe_id| is a unique identifier which can be used to track pipe endpoints - // as they're passed around. |endpoint| is either 0 or 1 and again is only - // used for tracking pipes (one side is always 0, the other is always 1.) - MessagePipeDispatcher(NodeController* node_controller, - const ports::PortRef& port, - uint64_t pipe_id, - int endpoint); - - // Fuses this pipe with |other|. Returns |true| on success or |false| on - // failure. Regardless of the return value, both dispatchers are closed by - // this call. - bool Fuse(MessagePipeDispatcher* other); - - // Dispatcher: - Type GetType() const override; - MojoResult Close() override; - MojoResult WriteMessage(std::unique_ptr message, - MojoWriteMessageFlags flags) override; - MojoResult ReadMessage(std::unique_ptr* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags, - bool read_any_size) override; - HandleSignalsState GetHandleSignalsState() const override; - MojoResult AddWatcherRef(const scoped_refptr& watcher, - uintptr_t context) override; - MojoResult RemoveWatcherRef(WatcherDispatcher* watcher, - uintptr_t context) override; - void StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_handles) override; - bool EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) override; - bool BeginTransit() override; - void CompleteTransitAndClose() override; - void CancelTransit() override; - - static scoped_refptr Deserialize( - const void* data, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* handles, - size_t num_handles); - - private: - class PortObserverThunk; - friend class PortObserverThunk; - - ~MessagePipeDispatcher() override; - - MojoResult CloseNoLock(); - HandleSignalsState GetHandleSignalsStateNoLock() const; - void OnPortStatusChanged(); - - // These are safe to access from any thread without locking. - NodeController* const node_controller_; - const ports::PortRef port_; - const uint64_t pipe_id_; - const int endpoint_; - - // Guards access to all the fields below. - mutable base::Lock signal_lock_; - - // This is not the same is |port_transferred_|. It's only held true between - // BeginTransit() and Complete/CancelTransit(). - AtomicFlag in_transit_; - - bool port_transferred_ = false; - AtomicFlag port_closed_; - WatcherSet watchers_; - - DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_ diff --git a/mojo/edk/system/message_pipe_perftest.cc b/mojo/edk/system/message_pipe_perftest.cc deleted file mode 100644 index 9866c47..0000000 --- a/mojo/edk/system/message_pipe_perftest.cc +++ /dev/null @@ -1,167 +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 -#include - -#include -#include - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/strings/stringprintf.h" -#include "base/test/perf_time_logger.h" -#include "base/threading/thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/edk/test/test_utils.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -class MessagePipePerfTest : public test::MojoTestBase { - public: - MessagePipePerfTest() : message_count_(0), message_size_(0) {} - - void SetUpMeasurement(int message_count, size_t message_size) { - message_count_ = message_count; - message_size_ = message_size; - payload_ = std::string(message_size, '*'); - read_buffer_.resize(message_size * 2); - } - - protected: - void WriteWaitThenRead(MojoHandle mp) { - CHECK_EQ(MojoWriteMessage(mp, payload_.data(), - static_cast(payload_.size()), nullptr, - 0, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - HandleSignalsState hss; - CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - uint32_t read_buffer_size = static_cast(read_buffer_.size()); - CHECK_EQ(MojoReadMessage(mp, &read_buffer_[0], &read_buffer_size, nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - CHECK_EQ(read_buffer_size, static_cast(payload_.size())); - } - - void SendQuitMessage(MojoHandle mp) { - CHECK_EQ(MojoWriteMessage(mp, "", 0, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - } - - void Measure(MojoHandle mp) { - // Have one ping-pong to ensure channel being established. - WriteWaitThenRead(mp); - - std::string test_name = - base::StringPrintf("IPC_Perf_%dx_%u", message_count_, - static_cast(message_size_)); - base::PerfTimeLogger logger(test_name.c_str()); - - for (int i = 0; i < message_count_; ++i) - WriteWaitThenRead(mp); - - logger.Done(); - } - - protected: - void RunPingPongServer(MojoHandle mp) { - // This values are set to align with one at ipc_pertests.cc for comparison. - const size_t kMsgSize[5] = {12, 144, 1728, 20736, 248832}; - const int kMessageCount[5] = {50000, 50000, 50000, 12000, 1000}; - - for (size_t i = 0; i < 5; i++) { - SetUpMeasurement(kMessageCount[i], kMsgSize[i]); - Measure(mp); - } - - SendQuitMessage(mp); - } - - static int RunPingPongClient(MojoHandle mp) { - std::string buffer(1000000, '\0'); - int rv = 0; - while (true) { - // Wait for our end of the message pipe to be readable. - HandleSignalsState hss; - MojoResult result = WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss); - if (result != MOJO_RESULT_OK) { - rv = result; - break; - } - - uint32_t read_size = static_cast(buffer.size()); - CHECK_EQ(MojoReadMessage(mp, &buffer[0], - &read_size, nullptr, - 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - - // Empty message indicates quit. - if (read_size == 0) - break; - - CHECK_EQ(MojoWriteMessage(mp, &buffer[0], - read_size, - nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - } - - return rv; - } - - private: - int message_count_; - size_t message_size_; - std::string payload_; - std::string read_buffer_; - std::unique_ptr perf_logger_; - - DISALLOW_COPY_AND_ASSIGN(MessagePipePerfTest); -}; - -TEST_F(MessagePipePerfTest, PingPong) { - MojoHandle server_handle, client_handle; - CreateMessagePipe(&server_handle, &client_handle); - - base::Thread client_thread("PingPongClient"); - client_thread.Start(); - client_thread.task_runner()->PostTask( - FROM_HERE, - base::Bind(base::IgnoreResult(&RunPingPongClient), client_handle)); - - RunPingPongServer(server_handle); -} - -// For each message received, sends a reply message with the same contents -// repeated twice, until the other end is closed or it receives "quitquitquit" -// (which it doesn't reply to). It'll return the number of messages received, -// not including any "quitquitquit" message, modulo 100. -DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient, MessagePipePerfTest, h) { - return RunPingPongClient(h); -} - -// Repeatedly sends messages as previous one got replied by the child. -// Waits for the child to close its end before quitting once specified -// number of messages has been sent. -TEST_F(MessagePipePerfTest, MultiprocessPingPong) { - RUN_CHILD_ON_PIPE(PingPongClient, h) - RunPingPongServer(h); - END_CHILD() -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/message_pipe_unittest.cc b/mojo/edk/system/message_pipe_unittest.cc deleted file mode 100644 index e6f1ff6..0000000 --- a/mojo/edk/system/message_pipe_unittest.cc +++ /dev/null @@ -1,699 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include - -#include "base/memory/ref_counted.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/public/c/system/core.h" -#include "mojo/public/c/system/types.h" - -namespace mojo { -namespace edk { -namespace { - -const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; -static const char kHelloWorld[] = "hello world"; - -class MessagePipeTest : public test::MojoTestBase { - public: - MessagePipeTest() { - CHECK_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &pipe0_, &pipe1_)); - } - - ~MessagePipeTest() override { - if (pipe0_ != MOJO_HANDLE_INVALID) - CHECK_EQ(MOJO_RESULT_OK, MojoClose(pipe0_)); - if (pipe1_ != MOJO_HANDLE_INVALID) - CHECK_EQ(MOJO_RESULT_OK, MojoClose(pipe1_)); - } - - MojoResult WriteMessage(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes) { - return MojoWriteMessage(message_pipe_handle, bytes, num_bytes, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE); - } - - MojoResult ReadMessage(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - bool may_discard = false) { - return MojoReadMessage(message_pipe_handle, bytes, num_bytes, nullptr, 0, - may_discard ? MOJO_READ_MESSAGE_FLAG_MAY_DISCARD : - MOJO_READ_MESSAGE_FLAG_NONE); - } - - MojoHandle pipe0_, pipe1_; - - private: - DISALLOW_COPY_AND_ASSIGN(MessagePipeTest); -}; - -using FuseMessagePipeTest = test::MojoTestBase; - -TEST_F(MessagePipeTest, WriteData) { - ASSERT_EQ(MOJO_RESULT_OK, - WriteMessage(pipe0_, kHelloWorld, sizeof(kHelloWorld))); -} - -// Tests: -// - only default flags -// - reading messages from a port -// - when there are no/one/two messages available for that port -// - with buffer size 0 (and null buffer) -- should get size -// - with too-small buffer -- should get size -// - also verify that buffers aren't modified when/where they shouldn't be -// - writing messages to a port -// - in the obvious scenarios (as above) -// - to a port that's been closed -// - writing a message to a port, closing the other (would be the source) port, -// and reading it -TEST_F(MessagePipeTest, Basic) { - int32_t buffer[2]; - const uint32_t kBufferSize = static_cast(sizeof(buffer)); - uint32_t buffer_size; - - // Nothing to read yet on port 0. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe0_, buffer, &buffer_size)); - ASSERT_EQ(kBufferSize, buffer_size); - ASSERT_EQ(123, buffer[0]); - ASSERT_EQ(456, buffer[1]); - - // Ditto for port 1. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe1_, buffer, &buffer_size)); - - // Write from port 1 (to port 0). - buffer[0] = 789012345; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0]))); - - MojoHandleSignalsState state; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - - // Read from port 0. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe0_, buffer, &buffer_size)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - ASSERT_EQ(789012345, buffer[0]); - ASSERT_EQ(456, buffer[1]); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe0_, buffer, &buffer_size)); - - // Write two messages from port 0 (to port 1). - buffer[0] = 123456789; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0]))); - buffer[0] = 234567890; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0]))); - - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - - // Read from port 1 with buffer size 0 (should get the size of next message). - // Also test that giving a null buffer is okay when the buffer size is 0. - buffer_size = 0; - ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - ReadMessage(pipe1_, nullptr, &buffer_size)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - - // Read from port 1 with buffer size 1 (too small; should get the size of next - // message). - buffer[0] = 123; - buffer[1] = 456; - buffer_size = 1; - ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - ReadMessage(pipe1_, buffer, &buffer_size)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - ASSERT_EQ(123, buffer[0]); - ASSERT_EQ(456, buffer[1]); - - // Read from port 1. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - ASSERT_EQ(123456789, buffer[0]); - ASSERT_EQ(456, buffer[1]); - - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - - // Read again from port 1. - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - ASSERT_EQ(234567890, buffer[0]); - ASSERT_EQ(456, buffer[1]); - - // Read again from port 1 -- it should be empty. - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe1_, buffer, &buffer_size)); - - // Write from port 0 (to port 1). - buffer[0] = 345678901; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0]))); - - // Close port 0. - MojoClose(pipe0_); - pipe0_ = MOJO_HANDLE_INVALID; - - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &state)); - - // Try to write from port 1 (to port 0). - buffer[0] = 456789012; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WriteMessage(pipe1_, buffer, sizeof(buffer[0]))); - - // Read from port 1; should still get message (even though port 0 was closed). - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - ASSERT_EQ(345678901, buffer[0]); - ASSERT_EQ(456, buffer[1]); - - // Read again from port 1 -- it should be empty (and port 0 is closed). - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - ReadMessage(pipe1_, buffer, &buffer_size)); -} - -TEST_F(MessagePipeTest, CloseWithQueuedIncomingMessages) { - int32_t buffer[1]; - const uint32_t kBufferSize = static_cast(sizeof(buffer)); - uint32_t buffer_size; - - // Write some messages from port 1 (to port 0). - for (int32_t i = 0; i < 5; i++) { - buffer[0] = i; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, kBufferSize)); - } - - MojoHandleSignalsState state; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - - // Port 0 shouldn't be empty. - buffer_size = 0; - ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - ReadMessage(pipe0_, nullptr, &buffer_size)); - ASSERT_EQ(kBufferSize, buffer_size); - - // Close port 0 first, which should have outstanding (incoming) messages. - MojoClose(pipe0_); - MojoClose(pipe1_); - pipe0_ = pipe1_ = MOJO_HANDLE_INVALID; -} - -TEST_F(MessagePipeTest, DiscardMode) { - int32_t buffer[2]; - const uint32_t kBufferSize = static_cast(sizeof(buffer)); - uint32_t buffer_size; - - // Write from port 1 (to port 0). - buffer[0] = 789012345; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0]))); - - MojoHandleSignalsState state; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - - // Read/discard from port 0 (no buffer); get size. - buffer_size = 0; - ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - ReadMessage(pipe0_, nullptr, &buffer_size, true)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, - ReadMessage(pipe0_, buffer, &buffer_size, true)); - - // Write from port 1 (to port 0). - buffer[0] = 890123456; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_OK, - WriteMessage(pipe1_, buffer, sizeof(buffer[0]))); - - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - - // Read from port 0 (buffer big enough). - buffer[0] = 123; - buffer[1] = 456; - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe0_, buffer, &buffer_size, true)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - ASSERT_EQ(890123456, buffer[0]); - ASSERT_EQ(456, buffer[1]); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, - ReadMessage(pipe0_, buffer, &buffer_size, true)); - - // Write from port 1 (to port 0). - buffer[0] = 901234567; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0]))); - - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - - // Read/discard from port 0 (buffer too small); get size. - buffer_size = 1; - ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - ReadMessage(pipe0_, buffer, &buffer_size, true)); - ASSERT_EQ(static_cast(sizeof(buffer[0])), buffer_size); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, - ReadMessage(pipe0_, buffer, &buffer_size, true)); - - // Write from port 1 (to port 0). - buffer[0] = 123456789; - buffer[1] = 0; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0]))); - - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, &state)); - - // Discard from port 0. - buffer_size = 1; - ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - ReadMessage(pipe0_, nullptr, 0, true)); - - // Read again from port 0 -- it should be empty. - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, - ReadMessage(pipe0_, buffer, &buffer_size, true)); -} - -TEST_F(MessagePipeTest, BasicWaiting) { - MojoHandleSignalsState hss; - - int32_t buffer[1]; - const uint32_t kBufferSize = static_cast(sizeof(buffer)); - uint32_t buffer_size; - - // Always writable (until the other port is closed). Not yet readable. Peer - // not closed. - hss = GetSignalsState(pipe0_); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - hss = MojoHandleSignalsState(); - - // Write from port 0 (to port 1), to make port 1 readable. - buffer[0] = 123456789; - ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, kBufferSize)); - - // Port 1 should already be readable now. - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - // ... and still writable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_WRITABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - hss.satisfied_signals); - ASSERT_EQ(kAllSignals, hss.satisfiable_signals); - - // Close port 0. - MojoClose(pipe0_); - pipe0_ = MOJO_HANDLE_INVALID; - - // Port 1 should be signaled with peer closed. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Port 1 should not be writable. - hss = MojoHandleSignalsState(); - - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_WRITABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // But it should still be readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - hss.satisfiable_signals); - - // Read from port 1. - buffer[0] = 0; - buffer_size = kBufferSize; - ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size)); - ASSERT_EQ(123456789, buffer[0]); - - // Now port 1 should no longer be readable. - hss = MojoHandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); -} - -TEST_F(MessagePipeTest, InvalidMessageObjects) { - // null message - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoFreeMessage(MOJO_MESSAGE_HANDLE_INVALID)); - - // null message - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoGetMessageBuffer(MOJO_MESSAGE_HANDLE_INVALID, nullptr)); - - // Non-zero num_handles with null handles array. - ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoAllocMessage(0, nullptr, 1, MOJO_ALLOC_MESSAGE_FLAG_NONE, - nullptr)); -} - -TEST_F(MessagePipeTest, AllocAndFreeMessage) { - const std::string kMessage = "Hello, world."; - MojoMessageHandle message = MOJO_MESSAGE_HANDLE_INVALID; - ASSERT_EQ(MOJO_RESULT_OK, - MojoAllocMessage(static_cast(kMessage.size()), nullptr, 0, - MOJO_ALLOC_MESSAGE_FLAG_NONE, &message)); - ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message); - ASSERT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message)); -} - -TEST_F(MessagePipeTest, WriteAndReadMessageObject) { - const std::string kMessage = "Hello, world."; - MojoMessageHandle message = MOJO_MESSAGE_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, - MojoAllocMessage(static_cast(kMessage.size()), nullptr, 0, - MOJO_ALLOC_MESSAGE_FLAG_NONE, &message)); - ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message); - - void* buffer = nullptr; - EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageBuffer(message, &buffer)); - ASSERT_TRUE(buffer); - memcpy(buffer, kMessage.data(), kMessage.size()); - - MojoHandle a, b; - CreateMessagePipe(&a, &b); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessageNew(a, message, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE)); - uint32_t num_bytes = 0; - uint32_t num_handles = 0; - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessageNew(b, &message, &num_bytes, nullptr, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE)); - ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message); - EXPECT_EQ(static_cast(kMessage.size()), num_bytes); - EXPECT_EQ(0u, num_handles); - - EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageBuffer(message, &buffer)); - ASSERT_TRUE(buffer); - - EXPECT_EQ(0, strncmp(static_cast(buffer), kMessage.data(), - num_bytes)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); -} - -#if !defined(OS_IOS) - -const size_t kPingPongHandlesPerIteration = 50; -const size_t kPingPongIterations = 500; - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(HandlePingPong, MessagePipeTest, h) { - // Waits for a handle to become readable and writes it back to the sender. - for (size_t i = 0; i < kPingPongIterations; i++) { - MojoHandle handles[kPingPongHandlesPerIteration]; - ReadMessageWithHandles(h, handles, kPingPongHandlesPerIteration); - WriteMessageWithHandles(h, "", handles, kPingPongHandlesPerIteration); - } - - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE)); - char msg[4]; - uint32_t num_bytes = 4; - EXPECT_EQ(MOJO_RESULT_OK, ReadMessage(h, msg, &num_bytes)); -} - -// This test is flaky: http://crbug.com/585784 -TEST_F(MessagePipeTest, DISABLED_DataPipeConsumerHandlePingPong) { - MojoHandle p, c[kPingPongHandlesPerIteration]; - for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i) { - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p, &c[i])); - MojoClose(p); - } - - RUN_CHILD_ON_PIPE(HandlePingPong, h) - for (size_t i = 0; i < kPingPongIterations; i++) { - WriteMessageWithHandles(h, "", c, kPingPongHandlesPerIteration); - ReadMessageWithHandles(h, c, kPingPongHandlesPerIteration); - } - WriteMessage(h, "quit", 4); - END_CHILD() - for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i) - MojoClose(c[i]); -} - -// This test is flaky: http://crbug.com/585784 -TEST_F(MessagePipeTest, DISABLED_DataPipeProducerHandlePingPong) { - MojoHandle p[kPingPongHandlesPerIteration], c; - for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i) { - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p[i], &c)); - MojoClose(c); - } - - RUN_CHILD_ON_PIPE(HandlePingPong, h) - for (size_t i = 0; i < kPingPongIterations; i++) { - WriteMessageWithHandles(h, "", p, kPingPongHandlesPerIteration); - ReadMessageWithHandles(h, p, kPingPongHandlesPerIteration); - } - WriteMessage(h, "quit", 4); - END_CHILD() - for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i) - MojoClose(p[i]); -} - -TEST_F(MessagePipeTest, SharedBufferHandlePingPong) { - MojoHandle buffers[kPingPongHandlesPerIteration]; - for (size_t i = 0; i -#include -#include -#include - -#include -#include -#include - -#include "base/bind.h" -#include "base/containers/hash_tables.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/files/scoped_temp_dir.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/strings/string_split.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/edk/test/test_utils.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/simple_watcher.h" -#include "mojo/public/cpp/system/wait.h" -#include "testing/gtest/include/gtest/gtest.h" - - -namespace mojo { -namespace edk { -namespace { - -class MultiprocessMessagePipeTest : public test::MojoTestBase { - protected: - // Convenience class for tests which will control command-driven children. - // See the CommandDrivenClient definition below. - class CommandDrivenClientController { - public: - explicit CommandDrivenClientController(MojoHandle h) : h_(h) {} - - void Send(const std::string& command) { - WriteMessage(h_, command); - EXPECT_EQ("ok", ReadMessage(h_)); - } - - void SendHandle(const std::string& name, MojoHandle p) { - WriteMessageWithHandles(h_, "take:" + name, &p, 1); - EXPECT_EQ("ok", ReadMessage(h_)); - } - - MojoHandle RetrieveHandle(const std::string& name) { - WriteMessage(h_, "return:" + name); - MojoHandle p; - EXPECT_EQ("ok", ReadMessageWithHandles(h_, &p, 1)); - return p; - } - - void Exit() { WriteMessage(h_, "exit"); } - - private: - MojoHandle h_; - }; -}; - -class MultiprocessMessagePipeTestWithPeerSupport - : public MultiprocessMessagePipeTest, - public testing::WithParamInterface { - protected: - void SetUp() override { - test::MojoTestBase::SetUp(); - set_launch_type(GetParam()); - } -}; - -// For each message received, sends a reply message with the same contents -// repeated twice, until the other end is closed or it receives "quitquitquit" -// (which it doesn't reply to). It'll return the number of messages received, -// not including any "quitquitquit" message, modulo 100. -DEFINE_TEST_CLIENT_WITH_PIPE(EchoEcho, MultiprocessMessagePipeTest, h) { - const std::string quitquitquit("quitquitquit"); - int rv = 0; - for (;; rv = (rv + 1) % 100) { - // Wait for our end of the message pipe to be readable. - HandleSignalsState hss; - MojoResult result = WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss); - if (result != MOJO_RESULT_OK) { - // It was closed, probably. - CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION); - CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); - break; - } else { - CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - } - - std::string read_buffer(1000, '\0'); - uint32_t read_buffer_size = static_cast(read_buffer.size()); - CHECK_EQ(MojoReadMessage(h, &read_buffer[0], - &read_buffer_size, nullptr, - 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - VLOG(2) << "Child got: " << read_buffer; - - if (read_buffer == quitquitquit) { - VLOG(2) << "Child quitting."; - break; - } - - std::string write_buffer = read_buffer + read_buffer; - CHECK_EQ(MojoWriteMessage(h, write_buffer.data(), - static_cast(write_buffer.size()), - nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - } - - return rv; -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, Basic) { - RUN_CHILD_ON_PIPE(EchoEcho, h) - std::string hello("hello"); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, hello.data(), - static_cast(hello.size()), nullptr, 0u, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - HandleSignalsState hss; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - // The child may or may not have closed its end of the message pipe and died - // (and we may or may not know it yet), so our end may or may not appear as - // writable. - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(1000, '\0'); - uint32_t read_buffer_size = static_cast(read_buffer.size()); - CHECK_EQ(MojoReadMessage(h, &read_buffer[0], - &read_buffer_size, nullptr, 0, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - VLOG(2) << "Parent got: " << read_buffer; - ASSERT_EQ(hello + hello, read_buffer); - - std::string quitquitquit("quitquitquit"); - CHECK_EQ(MojoWriteMessage(h, quitquitquit.data(), - static_cast(quitquitquit.size()), - nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - END_CHILD_AND_EXPECT_EXIT_CODE(1 % 100); -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, QueueMessages) { - static const size_t kNumMessages = 1001; - RUN_CHILD_ON_PIPE(EchoEcho, h) - for (size_t i = 0; i < kNumMessages; i++) { - std::string write_buffer(i, 'A' + (i % 26)); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, write_buffer.data(), - static_cast(write_buffer.size()), - nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); - } - - for (size_t i = 0; i < kNumMessages; i++) { - HandleSignalsState hss; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - // The child may or may not have closed its end of the message pipe and - // died (and we may or may not know it yet), so our end may or may not - // appear as writable. - ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - ASSERT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(kNumMessages * 2, '\0'); - uint32_t read_buffer_size = static_cast(read_buffer.size()); - ASSERT_EQ(MojoReadMessage(h, &read_buffer[0], - &read_buffer_size, nullptr, 0, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - - ASSERT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); - } - - const std::string quitquitquit("quitquitquit"); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, quitquitquit.data(), - static_cast(quitquitquit.size()), - nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for it to become readable, which should fail (since we sent - // "quitquitquit"). - HandleSignalsState hss; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - END_CHILD_AND_EXPECT_EXIT_CODE(static_cast(kNumMessages % 100)); -} - -DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer, MultiprocessMessagePipeTest, - h) { - // Wait for the first message from our parent. - HandleSignalsState hss; - CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - // In this test, the parent definitely doesn't close its end of the message - // pipe before we do. - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - // It should have a shared buffer. - std::string read_buffer(100, '\0'); - uint32_t num_bytes = static_cast(read_buffer.size()); - MojoHandle handles[10]; - uint32_t num_handlers = arraysize(handles); // Maximum number to receive - CHECK_EQ(MojoReadMessage(h, &read_buffer[0], - &num_bytes, &handles[0], - &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(num_bytes); - CHECK_EQ(read_buffer, std::string("go 1")); - CHECK_EQ(num_handlers, 1u); - - // Make a mapping. - void* buffer; - CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, &buffer, - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), - MOJO_RESULT_OK); - - // Write some stuff to the shared buffer. - static const char kHello[] = "hello"; - memcpy(buffer, kHello, sizeof(kHello)); - - // We should be able to close the dispatcher now. - MojoClose(handles[0]); - - // And send a message to signal that we've written stuff. - const std::string go2("go 2"); - CHECK_EQ(MojoWriteMessage(h, go2.data(), - static_cast(go2.size()), nullptr, 0u, - MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - - // Now wait for our parent to send us a message. - hss = HandleSignalsState(); - CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - read_buffer = std::string(100, '\0'); - num_bytes = static_cast(read_buffer.size()); - CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &num_bytes, - nullptr, 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(num_bytes); - CHECK_EQ(read_buffer, std::string("go 3")); - - // It should have written something to the shared buffer. - static const char kWorld[] = "world!!!"; - CHECK_EQ(memcmp(buffer, kWorld, sizeof(kWorld)), 0); - - // And we're done. - - return 0; -} - -TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) { - RUN_CHILD_ON_PIPE(CheckSharedBuffer, h) - // Make a shared buffer. - MojoCreateSharedBufferOptions options; - options.struct_size = sizeof(options); - options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; - - MojoHandle shared_buffer; - ASSERT_EQ(MOJO_RESULT_OK, - MojoCreateSharedBuffer(&options, 100, &shared_buffer)); - - // Send the shared buffer. - const std::string go1("go 1"); - - MojoHandle duplicated_shared_buffer; - ASSERT_EQ(MOJO_RESULT_OK, - MojoDuplicateBufferHandle( - shared_buffer, - nullptr, - &duplicated_shared_buffer)); - MojoHandle handles[1]; - handles[0] = duplicated_shared_buffer; - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, &go1[0], - static_cast(go1.size()), &handles[0], - arraysize(handles), - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for a message from the child. - HandleSignalsState hss; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(100, '\0'); - uint32_t num_bytes = static_cast(read_buffer.size()); - ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessage(h, &read_buffer[0], - &num_bytes, nullptr, 0, - MOJO_READ_MESSAGE_FLAG_NONE)); - read_buffer.resize(num_bytes); - ASSERT_EQ(std::string("go 2"), read_buffer); - - // After we get it, the child should have written something to the shared - // buffer. - static const char kHello[] = "hello"; - void* buffer; - CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, &buffer, - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), - MOJO_RESULT_OK); - ASSERT_EQ(0, memcmp(buffer, kHello, sizeof(kHello))); - - // Now we'll write some stuff to the shared buffer. - static const char kWorld[] = "world!!!"; - memcpy(buffer, kWorld, sizeof(kWorld)); - - // And send a message to signal that we've written stuff. - const std::string go3("go 3"); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, &go3[0], - static_cast(go3.size()), nullptr, 0u, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for |h| to become readable, which should fail. - hss = HandleSignalsState(); - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - END_CHILD() -} - -DEFINE_TEST_CLIENT_WITH_PIPE(CheckPlatformHandleFile, - MultiprocessMessagePipeTest, h) { - HandleSignalsState hss; - CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - std::string read_buffer(100, '\0'); - uint32_t num_bytes = static_cast(read_buffer.size()); - MojoHandle handles[255]; // Maximum number to receive. - uint32_t num_handlers = arraysize(handles); - - CHECK_EQ(MojoReadMessage(h, &read_buffer[0], - &num_bytes, &handles[0], - &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - - read_buffer.resize(num_bytes); - char hello[32]; - int num_handles = 0; - sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles); - CHECK_EQ(std::string("hello"), std::string(hello)); - CHECK_GT(num_handles, 0); - - for (int i = 0; i < num_handles; ++i) { - ScopedPlatformHandle h; - CHECK_EQ(PassWrappedPlatformHandle(handles[i], &h), MOJO_RESULT_OK); - CHECK(h.is_valid()); - MojoClose(handles[i]); - - base::ScopedFILE fp(test::FILEFromPlatformHandle(std::move(h), "r")); - CHECK(fp); - std::string fread_buffer(100, '\0'); - size_t bytes_read = - fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get()); - fread_buffer.resize(bytes_read); - CHECK_EQ(fread_buffer, "world"); - } - - return 0; -} - -class MultiprocessMessagePipeTestWithPipeCount - : public MultiprocessMessagePipeTest, - public testing::WithParamInterface {}; - -TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - RUN_CHILD_ON_PIPE(CheckPlatformHandleFile, h) - std::vector handles; - - size_t pipe_count = GetParam(); - for (size_t i = 0; i < pipe_count; ++i) { - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused)); - const std::string world("world"); - CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size()); - fflush(fp.get()); - rewind(fp.get()); - MojoHandle handle; - ASSERT_EQ( - CreatePlatformHandleWrapper( - ScopedPlatformHandle(test::PlatformHandleFromFILE(std::move(fp))), - &handle), - MOJO_RESULT_OK); - handles.push_back(handle); - } - - char message[128]; - snprintf(message, sizeof(message), "hello %d", - static_cast(pipe_count)); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, message, - static_cast(strlen(message)), - &handles[0], - static_cast(handles.size()), - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for it to become readable, which should fail. - HandleSignalsState hss; - ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); - ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - END_CHILD() -} - -// Android multi-process tests are not executing the new process. This is flaky. -#if !defined(OS_ANDROID) -INSTANTIATE_TEST_CASE_P(PipeCount, - MultiprocessMessagePipeTestWithPipeCount, - // TODO(rockot): Re-enable the 140-pipe case when - // ChannelPosix has support for sending lots of handles. - testing::Values(1u, 128u /*, 140u*/)); -#endif - -DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe, MultiprocessMessagePipeTest, h) { - // Wait for the first message from our parent. - HandleSignalsState hss; - CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - // In this test, the parent definitely doesn't close its end of the message - // pipe before we do. - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - // It should have a message pipe. - MojoHandle handles[10]; - uint32_t num_handlers = arraysize(handles); - CHECK_EQ(MojoReadMessage(h, nullptr, - nullptr, &handles[0], - &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - CHECK_EQ(num_handlers, 1u); - - // Read data from the received message pipe. - CHECK_EQ(WaitForSignals(handles[0], MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - std::string read_buffer(100, '\0'); - uint32_t read_buffer_size = static_cast(read_buffer.size()); - CHECK_EQ(MojoReadMessage(handles[0], &read_buffer[0], - &read_buffer_size, nullptr, - 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - CHECK_EQ(read_buffer, std::string("hello")); - - // Now write some data into the message pipe. - std::string write_buffer = "world"; - CHECK_EQ(MojoWriteMessage(handles[0], write_buffer.data(), - static_cast(write_buffer.size()), nullptr, - 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - MojoClose(handles[0]); - return 0; -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MessagePipePassing) { - RUN_CHILD_ON_PIPE(CheckMessagePipe, h) - MojoCreateSharedBufferOptions options; - options.struct_size = sizeof(options); - options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; - - MojoHandle mp1, mp2; - ASSERT_EQ(MOJO_RESULT_OK, - MojoCreateMessagePipe(nullptr, &mp1, &mp2)); - - // Write a string into one end of the new message pipe and send the other - // end. - const std::string hello("hello"); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(mp1, &hello[0], - static_cast(hello.size()), nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, nullptr, 0, &mp2, 1, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for a message from the child. - HandleSignalsState hss; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(mp1, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(100, '\0'); - uint32_t read_buffer_size = static_cast(read_buffer.size()); - CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], - &read_buffer_size, nullptr, - 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - CHECK_EQ(read_buffer, std::string("world")); - - MojoClose(mp1); - END_CHILD() -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MessagePipeTwoPassing) { - RUN_CHILD_ON_PIPE(CheckMessagePipe, h) - MojoHandle mp1, mp2; - ASSERT_EQ(MOJO_RESULT_OK, - MojoCreateMessagePipe(nullptr, &mp2, &mp1)); - - // Write a string into one end of the new message pipe and send the other - // end. - const std::string hello("hello"); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(mp1, &hello[0], - static_cast(hello.size()), nullptr, 0u, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, nullptr, 0u, &mp2, 1u, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for a message from the child. - HandleSignalsState hss; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(mp1, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(100, '\0'); - uint32_t read_buffer_size = static_cast(read_buffer.size()); - CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], - &read_buffer_size, nullptr, - 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - CHECK_EQ(read_buffer, std::string("world")); - END_CHILD(); -} - -DEFINE_TEST_CLIENT_WITH_PIPE(DataPipeConsumer, MultiprocessMessagePipeTest, h) { - // Wait for the first message from our parent. - HandleSignalsState hss; - CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - // In this test, the parent definitely doesn't close its end of the message - // pipe before we do. - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - // It should have a message pipe. - MojoHandle handles[10]; - uint32_t num_handlers = arraysize(handles); - CHECK_EQ(MojoReadMessage(h, nullptr, - nullptr, &handles[0], - &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - CHECK_EQ(num_handlers, 1u); - - // Read data from the received message pipe. - CHECK_EQ(WaitForSignals(handles[0], MOJO_HANDLE_SIGNAL_READABLE, &hss), - MOJO_RESULT_OK); - CHECK_EQ(hss.satisfied_signals, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); - CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - - std::string read_buffer(100, '\0'); - uint32_t read_buffer_size = static_cast(read_buffer.size()); - CHECK_EQ(MojoReadMessage(handles[0], &read_buffer[0], - &read_buffer_size, nullptr, - 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - CHECK_EQ(read_buffer, std::string("hello")); - - // Now write some data into the message pipe. - std::string write_buffer = "world"; - CHECK_EQ(MojoWriteMessage(handles[0], write_buffer.data(), - static_cast(write_buffer.size()), - nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - MojoClose(handles[0]); - return 0; -} - -TEST_F(MultiprocessMessagePipeTest, DataPipeConsumer) { - RUN_CHILD_ON_PIPE(DataPipeConsumer, h) - MojoCreateSharedBufferOptions options; - options.struct_size = sizeof(options); - options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; - - MojoHandle mp1, mp2; - ASSERT_EQ(MOJO_RESULT_OK, - MojoCreateMessagePipe(nullptr, &mp2, &mp1)); - - // Write a string into one end of the new message pipe and send the other - // end. - const std::string hello("hello"); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(mp1, &hello[0], - static_cast(hello.size()), nullptr, 0u, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - ASSERT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(h, nullptr, 0, &mp2, 1u, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // Wait for a message from the child. - HandleSignalsState hss; - ASSERT_EQ(MOJO_RESULT_OK, - WaitForSignals(mp1, MOJO_HANDLE_SIGNAL_READABLE, &hss)); - EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); - EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); - - std::string read_buffer(100, '\0'); - uint32_t read_buffer_size = static_cast(read_buffer.size()); - CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], - &read_buffer_size, nullptr, - 0, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - read_buffer.resize(read_buffer_size); - CHECK_EQ(read_buffer, std::string("world")); - - MojoClose(mp1); - END_CHILD(); -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, CreateMessagePipe) { - MojoHandle p0, p1; - CreateMessagePipe(&p0, &p1); - VerifyTransmission(p0, p1, std::string(10 * 1024 * 1024, 'a')); - VerifyTransmission(p1, p0, std::string(10 * 1024 * 1024, 'e')); - - CloseHandle(p0); - CloseHandle(p1); -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, PassMessagePipeLocal) { - MojoHandle p0, p1; - CreateMessagePipe(&p0, &p1); - VerifyTransmission(p0, p1, "testing testing"); - VerifyTransmission(p1, p0, "one two three"); - - MojoHandle p2, p3; - - CreateMessagePipe(&p2, &p3); - VerifyTransmission(p2, p3, "testing testing"); - VerifyTransmission(p3, p2, "one two three"); - - // Pass p2 over p0 to p1. - const std::string message = "ceci n'est pas une pipe"; - WriteMessageWithHandles(p0, message, &p2, 1); - EXPECT_EQ(message, ReadMessageWithHandles(p1, &p2, 1)); - - CloseHandle(p0); - CloseHandle(p1); - - // Verify that the received handle (now in p2) still works. - VerifyTransmission(p2, p3, "Easy come, easy go; will you let me go?"); - VerifyTransmission(p3, p2, "Bismillah! NO! We will not let you go!"); - - CloseHandle(p2); - CloseHandle(p3); -} - -// Echos the primordial channel until "exit". -DEFINE_TEST_CLIENT_WITH_PIPE(ChannelEchoClient, MultiprocessMessagePipeTest, - h) { - for (;;) { - std::string message = ReadMessage(h); - if (message == "exit") - break; - WriteMessage(h, message); - } - return 0; -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MultiprocessChannelPipe) { - RUN_CHILD_ON_PIPE(ChannelEchoClient, h) - VerifyEcho(h, "in an interstellar burst"); - VerifyEcho(h, "i am back to save the universe"); - VerifyEcho(h, std::string(10 * 1024 * 1024, 'o')); - - WriteMessage(h, "exit"); - END_CHILD() -} - -// Receives a pipe handle from the primordial channel and echos on it until -// "exit". Used to test simple pipe transfer across processes via channels. -DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceClient, MultiprocessMessagePipeTest, - h) { - MojoHandle p; - ReadMessageWithHandles(h, &p, 1); - for (;;) { - std::string message = ReadMessage(p); - if (message == "exit") - break; - WriteMessage(p, message); - } - return 0; -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, - PassMessagePipeCrossProcess) { - MojoHandle p0, p1; - CreateMessagePipe(&p0, &p1); - RUN_CHILD_ON_PIPE(EchoServiceClient, h) - - // Pass one end of the pipe to the other process. - WriteMessageWithHandles(h, "here take this", &p1, 1); - - VerifyEcho(p0, "and you may ask yourself"); - VerifyEcho(p0, "where does that highway go?"); - VerifyEcho(p0, std::string(20 * 1024 * 1024, 'i')); - - WriteMessage(p0, "exit"); - END_CHILD() - CloseHandle(p0); -} - -// Receives a pipe handle from the primordial channel and reads new handles -// from it. Each read handle establishes a new echo channel. -DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceFactoryClient, - MultiprocessMessagePipeTest, h) { - MojoHandle p; - ReadMessageWithHandles(h, &p, 1); - - std::vector handles(2); - handles[0] = Handle(h); - handles[1] = Handle(p); - std::vector signals(2, MOJO_HANDLE_SIGNAL_READABLE); - for (;;) { - size_t index; - CHECK_EQ( - mojo::WaitMany(handles.data(), signals.data(), handles.size(), &index), - MOJO_RESULT_OK); - DCHECK_LE(index, handles.size()); - if (index == 0) { - // If data is available on the first pipe, it should be an exit command. - EXPECT_EQ(std::string("exit"), ReadMessage(h)); - break; - } else if (index == 1) { - // If the second pipe, it should be a new handle requesting echo service. - MojoHandle echo_request; - ReadMessageWithHandles(p, &echo_request, 1); - handles.push_back(Handle(echo_request)); - signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); - } else { - // Otherwise it was one of our established echo pipes. Echo! - WriteMessage(handles[index].value(), ReadMessage(handles[index].value())); - } - } - - for (size_t i = 1; i < handles.size(); ++i) - CloseHandle(handles[i].value()); - - return 0; -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, - PassMoarMessagePipesCrossProcess) { - MojoHandle echo_factory_proxy, echo_factory_request; - CreateMessagePipe(&echo_factory_proxy, &echo_factory_request); - - MojoHandle echo_proxy_a, echo_request_a; - CreateMessagePipe(&echo_proxy_a, &echo_request_a); - - MojoHandle echo_proxy_b, echo_request_b; - CreateMessagePipe(&echo_proxy_b, &echo_request_b); - - MojoHandle echo_proxy_c, echo_request_c; - CreateMessagePipe(&echo_proxy_c, &echo_request_c); - - RUN_CHILD_ON_PIPE(EchoServiceFactoryClient, h) - WriteMessageWithHandles( - h, "gief factory naow plz", &echo_factory_request, 1); - - WriteMessageWithHandles(echo_factory_proxy, "give me an echo service plz!", - &echo_request_a, 1); - WriteMessageWithHandles(echo_factory_proxy, "give me one too!", - &echo_request_b, 1); - - VerifyEcho(echo_proxy_a, "i came here for an argument"); - VerifyEcho(echo_proxy_a, "shut your festering gob"); - VerifyEcho(echo_proxy_a, "mumble mumble mumble"); - - VerifyEcho(echo_proxy_b, "wubalubadubdub"); - VerifyEcho(echo_proxy_b, "wubalubadubdub"); - - WriteMessageWithHandles(echo_factory_proxy, "hook me up also thanks", - &echo_request_c, 1); - - VerifyEcho(echo_proxy_a, "the frobinators taste like frobinators"); - VerifyEcho(echo_proxy_b, "beep bop boop"); - VerifyEcho(echo_proxy_c, "zzzzzzzzzzzzzzzzzzzzzzzzzz"); - - WriteMessage(h, "exit"); - END_CHILD() - - CloseHandle(echo_factory_proxy); - CloseHandle(echo_proxy_a); - CloseHandle(echo_proxy_b); - CloseHandle(echo_proxy_c); -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, - ChannelPipesWithMultipleChildren) { - RUN_CHILD_ON_PIPE(ChannelEchoClient, a) - RUN_CHILD_ON_PIPE(ChannelEchoClient, b) - VerifyEcho(a, "hello child 0"); - VerifyEcho(b, "hello child 1"); - - WriteMessage(a, "exit"); - WriteMessage(b, "exit"); - END_CHILD() - END_CHILD() -} - -// Reads and turns a pipe handle some number of times to create lots of -// transient proxies. -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingPongPipeClient, - MultiprocessMessagePipeTest, h) { - const size_t kNumBounces = 50; - MojoHandle p0, p1; - ReadMessageWithHandles(h, &p0, 1); - ReadMessageWithHandles(h, &p1, 1); - for (size_t i = 0; i < kNumBounces; ++i) { - WriteMessageWithHandles(h, "", &p1, 1); - ReadMessageWithHandles(h, &p1, 1); - } - WriteMessageWithHandles(h, "", &p0, 1); - WriteMessage(p1, "bye"); - MojoClose(p1); - EXPECT_EQ("quit", ReadMessage(h)); -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, PingPongPipe) { - MojoHandle p0, p1; - CreateMessagePipe(&p0, &p1); - - RUN_CHILD_ON_PIPE(PingPongPipeClient, h) - const size_t kNumBounces = 50; - WriteMessageWithHandles(h, "", &p0, 1); - WriteMessageWithHandles(h, "", &p1, 1); - for (size_t i = 0; i < kNumBounces; ++i) { - ReadMessageWithHandles(h, &p1, 1); - WriteMessageWithHandles(h, "", &p1, 1); - } - ReadMessageWithHandles(h, &p0, 1); - WriteMessage(h, "quit"); - END_CHILD() - - EXPECT_EQ("bye", ReadMessage(p0)); - - // We should still be able to observe peer closure from the other end. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(p0, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); -} - -// Parses commands from the parent pipe and does whatever it's asked to do. -DEFINE_TEST_CLIENT_WITH_PIPE(CommandDrivenClient, MultiprocessMessagePipeTest, - h) { - base::hash_map named_pipes; - for (;;) { - MojoHandle p; - auto parts = base::SplitString(ReadMessageWithOptionalHandle(h, &p), ":", - base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); - CHECK(!parts.empty()); - std::string command = parts[0]; - if (command == "take") { - // Take a pipe. - CHECK_EQ(parts.size(), 2u); - CHECK_NE(p, MOJO_HANDLE_INVALID); - named_pipes[parts[1]] = p; - WriteMessage(h, "ok"); - } else if (command == "return") { - // Return a pipe. - CHECK_EQ(parts.size(), 2u); - CHECK_EQ(p, MOJO_HANDLE_INVALID); - p = named_pipes[parts[1]]; - CHECK_NE(p, MOJO_HANDLE_INVALID); - named_pipes.erase(parts[1]); - WriteMessageWithHandles(h, "ok", &p, 1); - } else if (command == "say") { - // Say something to a named pipe. - CHECK_EQ(parts.size(), 3u); - CHECK_EQ(p, MOJO_HANDLE_INVALID); - p = named_pipes[parts[1]]; - CHECK_NE(p, MOJO_HANDLE_INVALID); - CHECK(!parts[2].empty()); - WriteMessage(p, parts[2]); - WriteMessage(h, "ok"); - } else if (command == "hear") { - // Expect to read something from a named pipe. - CHECK_EQ(parts.size(), 3u); - CHECK_EQ(p, MOJO_HANDLE_INVALID); - p = named_pipes[parts[1]]; - CHECK_NE(p, MOJO_HANDLE_INVALID); - CHECK(!parts[2].empty()); - CHECK_EQ(parts[2], ReadMessage(p)); - WriteMessage(h, "ok"); - } else if (command == "pass") { - // Pass one named pipe over another named pipe. - CHECK_EQ(parts.size(), 3u); - CHECK_EQ(p, MOJO_HANDLE_INVALID); - p = named_pipes[parts[1]]; - MojoHandle carrier = named_pipes[parts[2]]; - CHECK_NE(p, MOJO_HANDLE_INVALID); - CHECK_NE(carrier, MOJO_HANDLE_INVALID); - named_pipes.erase(parts[1]); - WriteMessageWithHandles(carrier, "got a pipe for ya", &p, 1); - WriteMessage(h, "ok"); - } else if (command == "catch") { - // Expect to receive one named pipe from another named pipe. - CHECK_EQ(parts.size(), 3u); - CHECK_EQ(p, MOJO_HANDLE_INVALID); - MojoHandle carrier = named_pipes[parts[2]]; - CHECK_NE(carrier, MOJO_HANDLE_INVALID); - ReadMessageWithHandles(carrier, &p, 1); - CHECK_NE(p, MOJO_HANDLE_INVALID); - named_pipes[parts[1]] = p; - WriteMessage(h, "ok"); - } else if (command == "exit") { - CHECK_EQ(parts.size(), 1u); - break; - } - } - - for (auto& pipe : named_pipes) - CloseHandle(pipe.second); - - return 0; -} - -TEST_F(MultiprocessMessagePipeTest, ChildToChildPipes) { - RUN_CHILD_ON_PIPE(CommandDrivenClient, h0) - RUN_CHILD_ON_PIPE(CommandDrivenClient, h1) - CommandDrivenClientController a(h0); - CommandDrivenClientController b(h1); - - // Create a pipe and pass each end to a different client. - MojoHandle p0, p1; - CreateMessagePipe(&p0, &p1); - a.SendHandle("x", p0); - b.SendHandle("y", p1); - - // Make sure they can talk. - a.Send("say:x:hello"); - b.Send("hear:y:hello"); - - b.Send("say:y:i love multiprocess pipes!"); - a.Send("hear:x:i love multiprocess pipes!"); - - a.Exit(); - b.Exit(); - END_CHILD() - END_CHILD() -} - -TEST_F(MultiprocessMessagePipeTest, MoreChildToChildPipes) { - RUN_CHILD_ON_PIPE(CommandDrivenClient, h0) - RUN_CHILD_ON_PIPE(CommandDrivenClient, h1) - RUN_CHILD_ON_PIPE(CommandDrivenClient, h2) - RUN_CHILD_ON_PIPE(CommandDrivenClient, h3) - CommandDrivenClientController a(h0), b(h1), c(h2), d(h3); - - // Connect a to b and c to d - - MojoHandle p0, p1; - - CreateMessagePipe(&p0, &p1); - a.SendHandle("b_pipe", p0); - b.SendHandle("a_pipe", p1); - - MojoHandle p2, p3; - - CreateMessagePipe(&p2, &p3); - c.SendHandle("d_pipe", p2); - d.SendHandle("c_pipe", p3); - - // Connect b to c via a and d - MojoHandle p4, p5; - CreateMessagePipe(&p4, &p5); - a.SendHandle("d_pipe", p4); - d.SendHandle("a_pipe", p5); - - // Have |a| pass its new |d|-pipe to |b|. It will eventually connect - // to |c|. - a.Send("pass:d_pipe:b_pipe"); - b.Send("catch:c_pipe:a_pipe"); - - // Have |d| pass its new |a|-pipe to |c|. It will now be connected to - // |b|. - d.Send("pass:a_pipe:c_pipe"); - c.Send("catch:b_pipe:d_pipe"); - - // Make sure b and c and talk. - b.Send("say:c_pipe:it's a beautiful day"); - c.Send("hear:b_pipe:it's a beautiful day"); - - // Create x and y and have b and c exchange them. - MojoHandle x, y; - CreateMessagePipe(&x, &y); - b.SendHandle("x", x); - c.SendHandle("y", y); - b.Send("pass:x:c_pipe"); - c.Send("pass:y:b_pipe"); - b.Send("catch:y:c_pipe"); - c.Send("catch:x:b_pipe"); - - // Make sure the pipe still works in both directions. - b.Send("say:y:hello"); - c.Send("hear:x:hello"); - c.Send("say:x:goodbye"); - b.Send("hear:y:goodbye"); - - // Take both pipes back. - y = c.RetrieveHandle("x"); - x = b.RetrieveHandle("y"); - - VerifyTransmission(x, y, "still works"); - VerifyTransmission(y, x, "in both directions"); - - CloseHandle(x); - CloseHandle(y); - - a.Exit(); - b.Exit(); - c.Exit(); - d.Exit(); - END_CHILD() - END_CHILD() - END_CHILD() - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeer, - MultiprocessMessagePipeTest, h) { - MojoHandle p; - EXPECT_EQ("foo", ReadMessageWithHandles(h, &p, 1)); - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, SendPipeThenClosePeer) { - RUN_CHILD_ON_PIPE(ReceivePipeWithClosedPeer, h) - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - // Send |a| and immediately close |b|. The child should observe closure. - WriteMessageWithHandles(h, "foo", &a, 1); - MojoClose(b); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(SendOtherChildPipeWithClosedPeer, - MultiprocessMessagePipeTest, h) { - // Create a new pipe and send one end to the parent, who will connect it to - // a client running ReceivePipeWithClosedPeerFromOtherChild. - MojoHandle application_proxy, application_request; - CreateMessagePipe(&application_proxy, &application_request); - WriteMessageWithHandles(h, "c2a plz", &application_request, 1); - - // Create another pipe and send one end to the remote "application". - MojoHandle service_proxy, service_request; - CreateMessagePipe(&service_proxy, &service_request); - WriteMessageWithHandles(application_proxy, "c2s lol", &service_request, 1); - - // Immediately close the service proxy. The "application" should detect this. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(service_proxy)); - - // Wait for quit. - EXPECT_EQ("quit", ReadMessage(h)); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeerFromOtherChild, - MultiprocessMessagePipeTest, h) { - // Receive a pipe from the parent. This is akin to an "application request". - MojoHandle application_client; - EXPECT_EQ("c2a", ReadMessageWithHandles(h, &application_client, 1)); - - // Receive a pipe from the "application" "client". - MojoHandle service_client; - EXPECT_EQ("c2s lol", - ReadMessageWithHandles(application_client, &service_client, 1)); - - // Wait for the service client to signal closure. - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(service_client, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(service_client)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(application_client)); -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_SendPipeWithClosedPeerBetweenChildren \ - DISABLED_SendPipeWithClosedPeerBetweenChildren -#else -#define MAYBE_SendPipeWithClosedPeerBetweenChildren \ - SendPipeWithClosedPeerBetweenChildren -#endif -TEST_F(MultiprocessMessagePipeTest, - MAYBE_SendPipeWithClosedPeerBetweenChildren) { - RUN_CHILD_ON_PIPE(SendOtherChildPipeWithClosedPeer, kid_a) - RUN_CHILD_ON_PIPE(ReceivePipeWithClosedPeerFromOtherChild, kid_b) - // Receive an "application request" from the first child and forward it - // to the second child. - MojoHandle application_request; - EXPECT_EQ("c2a plz", - ReadMessageWithHandles(kid_a, &application_request, 1)); - - WriteMessageWithHandles(kid_b, "c2a", &application_request, 1); - END_CHILD() - - WriteMessage(kid_a, "quit"); - END_CHILD() -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, SendClosePeerSend) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - MojoHandle c, d; - CreateMessagePipe(&c, &d); - - // Send |a| over |c|, immediately close |b|, then send |a| back over |d|. - WriteMessageWithHandles(c, "foo", &a, 1); - EXPECT_EQ("foo", ReadMessageWithHandles(d, &a, 1)); - WriteMessageWithHandles(d, "bar", &a, 1); - EXPECT_EQ("bar", ReadMessageWithHandles(c, &a, 1)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - - // We should be able to detect peer closure on |a|. - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteCloseSendPeerClient, - MultiprocessMessagePipeTest, h) { - MojoHandle pipe[2]; - EXPECT_EQ("foo", ReadMessageWithHandles(h, pipe, 2)); - - // Write some messages to the first endpoint and then close it. - WriteMessage(pipe[0], "baz"); - WriteMessage(pipe[0], "qux"); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe[0])); - - MojoHandle c, d; - CreateMessagePipe(&c, &d); - - // Pass the orphaned endpoint over another pipe before passing it back to - // the parent, just for some extra proxying goodness. - WriteMessageWithHandles(c, "foo", &pipe[1], 1); - EXPECT_EQ("foo", ReadMessageWithHandles(d, &pipe[1], 1)); - - // And finally pass it back to the parent. - WriteMessageWithHandles(h, "bar", &pipe[1], 1); - - EXPECT_EQ("quit", ReadMessage(h)); -} - -TEST_P(MultiprocessMessagePipeTestWithPeerSupport, WriteCloseSendPeer) { - MojoHandle pipe[2]; - CreateMessagePipe(&pipe[0], &pipe[1]); - - RUN_CHILD_ON_PIPE(WriteCloseSendPeerClient, h) - // Pass the pipe to the child. - WriteMessageWithHandles(h, "foo", pipe, 2); - - // Read back an endpoint which should have messages on it. - MojoHandle p; - EXPECT_EQ("bar", ReadMessageWithHandles(h, &p, 1)); - - EXPECT_EQ("baz", ReadMessage(p)); - EXPECT_EQ("qux", ReadMessage(p)); - - // Expect to have peer closure signaled. - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - - WriteMessage(h, "quit"); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MessagePipeStatusChangeInTransitClient, - MultiprocessMessagePipeTest, parent) { - // This test verifies that peer closure is detectable through various - // mechanisms when it races with handle transfer. - MojoHandle handles[4]; - EXPECT_EQ("o_O", ReadMessageWithHandles(parent, handles, 4)); - - EXPECT_EQ(MOJO_RESULT_OK, - WaitForSignals(handles[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - - base::MessageLoop message_loop; - - // Wait on handle 1 using a SimpleWatcher. - { - base::RunLoop run_loop; - SimpleWatcher watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC); - watcher.Watch(Handle(handles[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, - base::Bind( - [](base::RunLoop* loop, MojoResult result) { - EXPECT_EQ(MOJO_RESULT_OK, result); - loop->Quit(); - }, - &run_loop)); - run_loop.Run(); - } - - // Wait on handle 2 by polling with MojoReadMessage. - MojoResult result; - do { - result = MojoReadMessage(handles[2], nullptr, nullptr, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE); - } while (result == MOJO_RESULT_SHOULD_WAIT); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - - // Wait on handle 3 by polling with MojoWriteMessage. - do { - result = MojoWriteMessage(handles[3], nullptr, 0, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE); - } while (result == MOJO_RESULT_OK); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - - for (size_t i = 0; i < 4; ++i) - CloseHandle(handles[i]); -} - -TEST_F(MultiprocessMessagePipeTest, MessagePipeStatusChangeInTransit) { - MojoHandle local_handles[4]; - MojoHandle sent_handles[4]; - for (size_t i = 0; i < 4; ++i) - CreateMessagePipe(&local_handles[i], &sent_handles[i]); - - RUN_CHILD_ON_PIPE(MessagePipeStatusChangeInTransitClient, child) - // Send 4 handles and let their transfer race with their peers' closure. - WriteMessageWithHandles(child, "o_O", sent_handles, 4); - for (size_t i = 0; i < 4; ++i) - CloseHandle(local_handles[i]); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(BadMessageClient, MultiprocessMessagePipeTest, - parent) { - MojoHandle pipe; - EXPECT_EQ("hi", ReadMessageWithHandles(parent, &pipe, 1)); - WriteMessage(pipe, "derp"); - EXPECT_EQ("bye", ReadMessage(parent)); -} - -void OnProcessError(std::string* out_error, const std::string& error) { - *out_error = error; -} - -TEST_F(MultiprocessMessagePipeTest, NotifyBadMessage) { - const std::string kFirstErrorMessage = "everything is terrible!"; - const std::string kSecondErrorMessage = "not the bits you're looking for"; - - std::string first_process_error; - std::string second_process_error; - - set_process_error_callback(base::Bind(&OnProcessError, &first_process_error)); - RUN_CHILD_ON_PIPE(BadMessageClient, child1) - set_process_error_callback(base::Bind(&OnProcessError, - &second_process_error)); - RUN_CHILD_ON_PIPE(BadMessageClient, child2) - MojoHandle a, b, c, d; - CreateMessagePipe(&a, &b); - CreateMessagePipe(&c, &d); - WriteMessageWithHandles(child1, "hi", &b, 1); - WriteMessageWithHandles(child2, "hi", &d, 1); - - // Read a message from the pipe we sent to child1 and flag it as bad. - ASSERT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_READABLE)); - uint32_t num_bytes = 0; - MojoMessageHandle message; - ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessageNew(a, &message, &num_bytes, nullptr, 0, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoNotifyBadMessage(message, kFirstErrorMessage.data(), - kFirstErrorMessage.size())); - EXPECT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message)); - - // Read a message from the pipe we sent to child2 and flag it as bad. - ASSERT_EQ(MOJO_RESULT_OK, WaitForSignals(c, MOJO_HANDLE_SIGNAL_READABLE)); - ASSERT_EQ(MOJO_RESULT_OK, - MojoReadMessageNew(c, &message, &num_bytes, nullptr, 0, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoNotifyBadMessage(message, kSecondErrorMessage.data(), - kSecondErrorMessage.size())); - EXPECT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message)); - - WriteMessage(child2, "bye"); - END_CHILD(); - - WriteMessage(child1, "bye"); - END_CHILD() - - // The error messages should match the processes which triggered them. - EXPECT_NE(std::string::npos, first_process_error.find(kFirstErrorMessage)); - EXPECT_NE(std::string::npos, second_process_error.find(kSecondErrorMessage)); -} -INSTANTIATE_TEST_CASE_P( - , - MultiprocessMessagePipeTestWithPeerSupport, - testing::Values(test::MojoTestBase::LaunchType::CHILD, - test::MojoTestBase::LaunchType::PEER, - test::MojoTestBase::LaunchType::NAMED_CHILD, - test::MojoTestBase::LaunchType::NAMED_PEER)); -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/node_channel.cc b/mojo/edk/system/node_channel.cc deleted file mode 100644 index b0f770d..0000000 --- a/mojo/edk/system/node_channel.cc +++ /dev/null @@ -1,905 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/node_channel.h" - -#include -#include -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "mojo/edk/system/channel.h" -#include "mojo/edk/system/request_context.h" - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include "mojo/edk/system/mach_port_relay.h" -#endif - -namespace mojo { -namespace edk { - -namespace { - -template -T Align(T t) { - const auto k = kChannelMessageAlignment; - return t + (k - (t % k)) % k; -} - -// NOTE: Please ONLY append messages to the end of this enum. -enum class MessageType : uint32_t { - ACCEPT_CHILD, - ACCEPT_PARENT, - ADD_BROKER_CLIENT, - BROKER_CLIENT_ADDED, - ACCEPT_BROKER_CLIENT, - PORTS_MESSAGE, - REQUEST_PORT_MERGE, - REQUEST_INTRODUCTION, - INTRODUCE, -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - RELAY_PORTS_MESSAGE, -#endif - BROADCAST, -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - PORTS_MESSAGE_FROM_RELAY, -#endif - ACCEPT_PEER, -}; - -struct Header { - MessageType type; - uint32_t padding; -}; - -static_assert(IsAlignedForChannelMessage(sizeof(Header)), - "Invalid header size."); - -struct AcceptChildData { - ports::NodeName parent_name; - ports::NodeName token; -}; - -struct AcceptParentData { - ports::NodeName token; - ports::NodeName child_name; -}; - -struct AcceptPeerData { - ports::NodeName token; - ports::NodeName peer_name; - ports::PortName port_name; -}; - -// This message may include a process handle on plaforms that require it. -struct AddBrokerClientData { - ports::NodeName client_name; -#if !defined(OS_WIN) - uint32_t process_handle; - uint32_t padding; -#endif -}; - -#if !defined(OS_WIN) -static_assert(sizeof(base::ProcessHandle) == sizeof(uint32_t), - "Unexpected pid size"); -static_assert(sizeof(AddBrokerClientData) % kChannelMessageAlignment == 0, - "Invalid AddBrokerClientData size."); -#endif - -// This data is followed by a platform channel handle to the broker. -struct BrokerClientAddedData { - ports::NodeName client_name; -}; - -// This data may be followed by a platform channel handle to the broker. If not, -// then the parent is the broker and its channel should be used as such. -struct AcceptBrokerClientData { - ports::NodeName broker_name; -}; - -// This is followed by arbitrary payload data which is interpreted as a token -// string for port location. -struct RequestPortMergeData { - ports::PortName connector_port_name; -}; - -// Used for both REQUEST_INTRODUCTION and INTRODUCE. -// -// For INTRODUCE the message also includes a valid platform handle for a channel -// the receiver may use to communicate with the named node directly, or an -// invalid platform handle if the node is unknown to the sender or otherwise -// cannot be introduced. -struct IntroductionData { - ports::NodeName name; -}; - -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) -// This struct is followed by the full payload of a message to be relayed. -struct RelayPortsMessageData { - ports::NodeName destination; -}; - -// This struct is followed by the full payload of a relayed message. -struct PortsMessageFromRelayData { - ports::NodeName source; -}; -#endif - -template -Channel::MessagePtr CreateMessage(MessageType type, - size_t payload_size, - size_t num_handles, - DataType** out_data) { - Channel::MessagePtr message( - new Channel::Message(sizeof(Header) + payload_size, num_handles)); - Header* header = reinterpret_cast(message->mutable_payload()); - header->type = type; - header->padding = 0; - *out_data = reinterpret_cast(&header[1]); - return message; -} - -template -bool GetMessagePayload(const void* bytes, - size_t num_bytes, - DataType** out_data) { - static_assert(sizeof(DataType) > 0, "DataType must have non-zero size."); - if (num_bytes < sizeof(Header) + sizeof(DataType)) - return false; - *out_data = reinterpret_cast( - static_cast(bytes) + sizeof(Header)); - return true; -} - -} // namespace - -// static -scoped_refptr NodeChannel::Create( - Delegate* delegate, - ConnectionParams connection_params, - scoped_refptr io_task_runner, - const ProcessErrorCallback& process_error_callback) { -#if defined(OS_NACL_SFI) - LOG(FATAL) << "Multi-process not yet supported on NaCl-SFI"; - return nullptr; -#else - return new NodeChannel(delegate, std::move(connection_params), io_task_runner, - process_error_callback); -#endif -} - -// static -Channel::MessagePtr NodeChannel::CreatePortsMessage(size_t payload_size, - void** payload, - size_t num_handles) { - return CreateMessage(MessageType::PORTS_MESSAGE, payload_size, num_handles, - payload); -} - -// static -void NodeChannel::GetPortsMessageData(Channel::Message* message, - void** data, - size_t* num_data_bytes) { - *data = reinterpret_cast(message->mutable_payload()) + 1; - *num_data_bytes = message->payload_size() - sizeof(Header); -} - -void NodeChannel::Start() { -#if defined(OS_MACOSX) && !defined(OS_IOS) - MachPortRelay* relay = delegate_->GetMachPortRelay(); - if (relay) - relay->AddObserver(this); -#endif - - base::AutoLock lock(channel_lock_); - // ShutDown() may have already been called, in which case |channel_| is null. - if (channel_) - channel_->Start(); -} - -void NodeChannel::ShutDown() { -#if defined(OS_MACOSX) && !defined(OS_IOS) - MachPortRelay* relay = delegate_->GetMachPortRelay(); - if (relay) - relay->RemoveObserver(this); -#endif - - base::AutoLock lock(channel_lock_); - if (channel_) { - channel_->ShutDown(); - channel_ = nullptr; - } -} - -void NodeChannel::LeakHandleOnShutdown() { - base::AutoLock lock(channel_lock_); - if (channel_) { - channel_->LeakHandle(); - } -} - -void NodeChannel::NotifyBadMessage(const std::string& error) { - if (!process_error_callback_.is_null()) - process_error_callback_.Run("Received bad user message: " + error); -} - -void NodeChannel::SetRemoteProcessHandle(base::ProcessHandle process_handle) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - base::AutoLock lock(remote_process_handle_lock_); - DCHECK_EQ(base::kNullProcessHandle, remote_process_handle_); - CHECK_NE(remote_process_handle_, base::GetCurrentProcessHandle()); - remote_process_handle_ = process_handle; -#if defined(OS_WIN) - DCHECK(!scoped_remote_process_handle_.is_valid()); - scoped_remote_process_handle_.reset(PlatformHandle(process_handle)); -#endif -} - -bool NodeChannel::HasRemoteProcessHandle() { - base::AutoLock lock(remote_process_handle_lock_); - return remote_process_handle_ != base::kNullProcessHandle; -} - -base::ProcessHandle NodeChannel::CopyRemoteProcessHandle() { - base::AutoLock lock(remote_process_handle_lock_); -#if defined(OS_WIN) - if (remote_process_handle_ != base::kNullProcessHandle) { - // Privileged nodes use this to pass their childrens' process handles to the - // broker on launch. - HANDLE handle = remote_process_handle_; - BOOL result = DuplicateHandle( - base::GetCurrentProcessHandle(), remote_process_handle_, - base::GetCurrentProcessHandle(), &handle, 0, FALSE, - DUPLICATE_SAME_ACCESS); - DPCHECK(result); - return handle; - } - return base::kNullProcessHandle; -#else - return remote_process_handle_; -#endif -} - -void NodeChannel::SetRemoteNodeName(const ports::NodeName& name) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - remote_node_name_ = name; -} - -void NodeChannel::AcceptChild(const ports::NodeName& parent_name, - const ports::NodeName& token) { - AcceptChildData* data; - Channel::MessagePtr message = CreateMessage( - MessageType::ACCEPT_CHILD, sizeof(AcceptChildData), 0, &data); - data->parent_name = parent_name; - data->token = token; - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::AcceptParent(const ports::NodeName& token, - const ports::NodeName& child_name) { - AcceptParentData* data; - Channel::MessagePtr message = CreateMessage( - MessageType::ACCEPT_PARENT, sizeof(AcceptParentData), 0, &data); - data->token = token; - data->child_name = child_name; - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::AcceptPeer(const ports::NodeName& sender_name, - const ports::NodeName& token, - const ports::PortName& port_name) { - AcceptPeerData* data; - Channel::MessagePtr message = - CreateMessage(MessageType::ACCEPT_PEER, sizeof(AcceptPeerData), 0, &data); - data->token = token; - data->peer_name = sender_name; - data->port_name = port_name; - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::AddBrokerClient(const ports::NodeName& client_name, - base::ProcessHandle process_handle) { - AddBrokerClientData* data; - ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector()); -#if defined(OS_WIN) - handles->push_back(PlatformHandle(process_handle)); -#endif - Channel::MessagePtr message = CreateMessage( - MessageType::ADD_BROKER_CLIENT, sizeof(AddBrokerClientData), - handles->size(), &data); - message->SetHandles(std::move(handles)); - data->client_name = client_name; -#if !defined(OS_WIN) - data->process_handle = process_handle; - data->padding = 0; -#endif - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::BrokerClientAdded(const ports::NodeName& client_name, - ScopedPlatformHandle broker_channel) { - BrokerClientAddedData* data; - ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector()); - if (broker_channel.is_valid()) - handles->push_back(broker_channel.release()); - Channel::MessagePtr message = CreateMessage( - MessageType::BROKER_CLIENT_ADDED, sizeof(BrokerClientAddedData), - handles->size(), &data); - message->SetHandles(std::move(handles)); - data->client_name = client_name; - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::AcceptBrokerClient(const ports::NodeName& broker_name, - ScopedPlatformHandle broker_channel) { - AcceptBrokerClientData* data; - ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector()); - if (broker_channel.is_valid()) - handles->push_back(broker_channel.release()); - Channel::MessagePtr message = CreateMessage( - MessageType::ACCEPT_BROKER_CLIENT, sizeof(AcceptBrokerClientData), - handles->size(), &data); - message->SetHandles(std::move(handles)); - data->broker_name = broker_name; - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::PortsMessage(Channel::MessagePtr message) { - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::RequestPortMerge(const ports::PortName& connector_port_name, - const std::string& token) { - RequestPortMergeData* data; - Channel::MessagePtr message = CreateMessage( - MessageType::REQUEST_PORT_MERGE, - sizeof(RequestPortMergeData) + token.size(), 0, &data); - data->connector_port_name = connector_port_name; - memcpy(data + 1, token.data(), token.size()); - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::RequestIntroduction(const ports::NodeName& name) { - IntroductionData* data; - Channel::MessagePtr message = CreateMessage( - MessageType::REQUEST_INTRODUCTION, sizeof(IntroductionData), 0, &data); - data->name = name; - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::Introduce(const ports::NodeName& name, - ScopedPlatformHandle channel_handle) { - IntroductionData* data; - ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector()); - if (channel_handle.is_valid()) - handles->push_back(channel_handle.release()); - Channel::MessagePtr message = CreateMessage( - MessageType::INTRODUCE, sizeof(IntroductionData), handles->size(), &data); - message->SetHandles(std::move(handles)); - data->name = name; - WriteChannelMessage(std::move(message)); -} - -void NodeChannel::Broadcast(Channel::MessagePtr message) { - DCHECK(!message->has_handles()); - void* data; - Channel::MessagePtr broadcast_message = CreateMessage( - MessageType::BROADCAST, message->data_num_bytes(), 0, &data); - memcpy(data, message->data(), message->data_num_bytes()); - WriteChannelMessage(std::move(broadcast_message)); -} - -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) -void NodeChannel::RelayPortsMessage(const ports::NodeName& destination, - Channel::MessagePtr message) { -#if defined(OS_WIN) - DCHECK(message->has_handles()); - - // Note that this is only used on Windows, and on Windows all platform - // handles are included in the message data. We blindly copy all the data - // here and the relay node (the parent) will duplicate handles as needed. - size_t num_bytes = sizeof(RelayPortsMessageData) + message->data_num_bytes(); - RelayPortsMessageData* data; - Channel::MessagePtr relay_message = CreateMessage( - MessageType::RELAY_PORTS_MESSAGE, num_bytes, 0, &data); - data->destination = destination; - memcpy(data + 1, message->data(), message->data_num_bytes()); - - // When the handles are duplicated in the parent, the source handles will - // be closed. If the parent never receives this message then these handles - // will leak, but that means something else has probably broken and the - // sending process won't likely be around much longer. - ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); - handles->clear(); - -#else - DCHECK(message->has_mach_ports()); - - // On OSX, the handles are extracted from the relayed message and attached to - // the wrapper. The broker then takes the handles attached to the wrapper and - // moves them back to the relayed message. This is necessary because the - // message may contain fds which need to be attached to the outer message so - // that they can be transferred to the broker. - ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); - size_t num_bytes = sizeof(RelayPortsMessageData) + message->data_num_bytes(); - RelayPortsMessageData* data; - Channel::MessagePtr relay_message = CreateMessage( - MessageType::RELAY_PORTS_MESSAGE, num_bytes, handles->size(), &data); - data->destination = destination; - memcpy(data + 1, message->data(), message->data_num_bytes()); - relay_message->SetHandles(std::move(handles)); -#endif // defined(OS_WIN) - - WriteChannelMessage(std::move(relay_message)); -} - -void NodeChannel::PortsMessageFromRelay(const ports::NodeName& source, - Channel::MessagePtr message) { - size_t num_bytes = sizeof(PortsMessageFromRelayData) + - message->payload_size(); - PortsMessageFromRelayData* data; - Channel::MessagePtr relayed_message = CreateMessage( - MessageType::PORTS_MESSAGE_FROM_RELAY, num_bytes, message->num_handles(), - &data); - data->source = source; - if (message->payload_size()) - memcpy(data + 1, message->payload(), message->payload_size()); - relayed_message->SetHandles(message->TakeHandles()); - WriteChannelMessage(std::move(relayed_message)); -} -#endif // defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - -NodeChannel::NodeChannel(Delegate* delegate, - ConnectionParams connection_params, - scoped_refptr io_task_runner, - const ProcessErrorCallback& process_error_callback) - : delegate_(delegate), - io_task_runner_(io_task_runner), - process_error_callback_(process_error_callback) -#if !defined(OS_NACL_SFI) - , - channel_( - Channel::Create(this, std::move(connection_params), io_task_runner_)) -#endif -{ -} - -NodeChannel::~NodeChannel() { - ShutDown(); -} - -void NodeChannel::OnChannelMessage(const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - RequestContext request_context(RequestContext::Source::SYSTEM); - - // Ensure this NodeChannel stays alive through the extent of this method. The - // delegate may have the only other reference to this object and it may choose - // to drop it here in response to, e.g., a malformed message. - scoped_refptr keepalive = this; - -#if defined(OS_WIN) - // If we receive handles from a known process, rewrite them to our own - // process. This can occur when a privileged node receives handles directly - // from a privileged descendant. - { - base::AutoLock lock(remote_process_handle_lock_); - if (handles && remote_process_handle_ != base::kNullProcessHandle) { - // Note that we explicitly mark the handles as being owned by the sending - // process before rewriting them, in order to accommodate RewriteHandles' - // internal sanity checks. - for (auto& handle : *handles) - handle.owning_process = remote_process_handle_; - if (!Channel::Message::RewriteHandles(remote_process_handle_, - base::GetCurrentProcessHandle(), - handles.get())) { - DLOG(ERROR) << "Received one or more invalid handles."; - } - } else if (handles) { - // Handles received by an unknown process must already be owned by us. - for (auto& handle : *handles) - handle.owning_process = base::GetCurrentProcessHandle(); - } - } -#elif defined(OS_MACOSX) && !defined(OS_IOS) - // If we're not the root, receive any mach ports from the message. If we're - // the root, the only message containing mach ports should be a - // RELAY_PORTS_MESSAGE. - { - MachPortRelay* relay = delegate_->GetMachPortRelay(); - if (handles && !relay) { - if (!MachPortRelay::ReceivePorts(handles.get())) { - LOG(ERROR) << "Error receiving mach ports."; - } - } - } -#endif // defined(OS_WIN) - - - if (payload_size <= sizeof(Header)) { - delegate_->OnChannelError(remote_node_name_, this); - return; - } - - const Header* header = static_cast(payload); - switch (header->type) { - case MessageType::ACCEPT_CHILD: { - const AcceptChildData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - delegate_->OnAcceptChild(remote_node_name_, data->parent_name, - data->token); - return; - } - break; - } - - case MessageType::ACCEPT_PARENT: { - const AcceptParentData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - delegate_->OnAcceptParent(remote_node_name_, data->token, - data->child_name); - return; - } - break; - } - - case MessageType::ADD_BROKER_CLIENT: { - const AddBrokerClientData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - ScopedPlatformHandle process_handle; -#if defined(OS_WIN) - if (!handles || handles->size() != 1) { - DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; - break; - } - process_handle = ScopedPlatformHandle(handles->at(0)); - handles->clear(); - delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, - process_handle.release().handle); -#else - if (handles && handles->size() != 0) { - DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; - break; - } - delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, - data->process_handle); -#endif - return; - } - break; - } - - case MessageType::BROKER_CLIENT_ADDED: { - const BrokerClientAddedData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - ScopedPlatformHandle broker_channel; - if (!handles || handles->size() != 1) { - DLOG(ERROR) << "Dropping invalid BrokerClientAdded message."; - break; - } - broker_channel = ScopedPlatformHandle(handles->at(0)); - handles->clear(); - delegate_->OnBrokerClientAdded(remote_node_name_, data->client_name, - std::move(broker_channel)); - return; - } - break; - } - - case MessageType::ACCEPT_BROKER_CLIENT: { - const AcceptBrokerClientData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - ScopedPlatformHandle broker_channel; - if (handles && handles->size() > 1) { - DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message."; - break; - } - if (handles && handles->size() == 1) { - broker_channel = ScopedPlatformHandle(handles->at(0)); - handles->clear(); - } - delegate_->OnAcceptBrokerClient(remote_node_name_, data->broker_name, - std::move(broker_channel)); - return; - } - break; - } - - case MessageType::PORTS_MESSAGE: { - size_t num_handles = handles ? handles->size() : 0; - Channel::MessagePtr message( - new Channel::Message(payload_size, num_handles)); - message->SetHandles(std::move(handles)); - memcpy(message->mutable_payload(), payload, payload_size); - delegate_->OnPortsMessage(remote_node_name_, std::move(message)); - return; - } - - case MessageType::REQUEST_PORT_MERGE: { - const RequestPortMergeData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - // Don't accept an empty token. - size_t token_size = payload_size - sizeof(*data) - sizeof(Header); - if (token_size == 0) - break; - std::string token(reinterpret_cast(data + 1), token_size); - delegate_->OnRequestPortMerge(remote_node_name_, - data->connector_port_name, token); - return; - } - break; - } - - case MessageType::REQUEST_INTRODUCTION: { - const IntroductionData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - delegate_->OnRequestIntroduction(remote_node_name_, data->name); - return; - } - break; - } - - case MessageType::INTRODUCE: { - const IntroductionData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - if (handles && handles->size() > 1) { - DLOG(ERROR) << "Dropping invalid introduction message."; - break; - } - ScopedPlatformHandle channel_handle; - if (handles && handles->size() == 1) { - channel_handle = ScopedPlatformHandle(handles->at(0)); - handles->clear(); - } - delegate_->OnIntroduce(remote_node_name_, data->name, - std::move(channel_handle)); - return; - } - break; - } - -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - case MessageType::RELAY_PORTS_MESSAGE: { - base::ProcessHandle from_process; - { - base::AutoLock lock(remote_process_handle_lock_); - from_process = remote_process_handle_; - } - const RelayPortsMessageData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - // Don't try to relay an empty message. - if (payload_size <= sizeof(Header) + sizeof(RelayPortsMessageData)) - break; - - const void* message_start = data + 1; - Channel::MessagePtr message = Channel::Message::Deserialize( - message_start, payload_size - sizeof(Header) - sizeof(*data)); - if (!message) { - DLOG(ERROR) << "Dropping invalid relay message."; - break; - } - #if defined(OS_MACOSX) && !defined(OS_IOS) - message->SetHandles(std::move(handles)); - MachPortRelay* relay = delegate_->GetMachPortRelay(); - if (!relay) { - LOG(ERROR) << "Receiving mach ports without a port relay from " - << remote_node_name_ << ". Dropping message."; - break; - } - { - base::AutoLock lock(pending_mach_messages_lock_); - if (relay->port_provider()->TaskForPid(from_process) == - MACH_PORT_NULL) { - pending_relay_messages_.push( - std::make_pair(data->destination, std::move(message))); - break; - } - } - #endif - delegate_->OnRelayPortsMessage(remote_node_name_, from_process, - data->destination, std::move(message)); - return; - } - break; - } -#endif - - case MessageType::BROADCAST: { - if (payload_size <= sizeof(Header)) - break; - const void* data = static_cast( - reinterpret_cast(payload) + 1); - Channel::MessagePtr message = - Channel::Message::Deserialize(data, payload_size - sizeof(Header)); - if (!message || message->has_handles()) { - DLOG(ERROR) << "Dropping invalid broadcast message."; - break; - } - delegate_->OnBroadcast(remote_node_name_, std::move(message)); - return; - } - -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - case MessageType::PORTS_MESSAGE_FROM_RELAY: - const PortsMessageFromRelayData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - size_t num_bytes = payload_size - sizeof(*data); - if (num_bytes < sizeof(Header)) - break; - num_bytes -= sizeof(Header); - - size_t num_handles = handles ? handles->size() : 0; - Channel::MessagePtr message( - new Channel::Message(num_bytes, num_handles)); - message->SetHandles(std::move(handles)); - if (num_bytes) - memcpy(message->mutable_payload(), data + 1, num_bytes); - delegate_->OnPortsMessageFromRelay( - remote_node_name_, data->source, std::move(message)); - return; - } - break; - -#endif // defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - - case MessageType::ACCEPT_PEER: { - const AcceptPeerData* data; - if (GetMessagePayload(payload, payload_size, &data)) { - delegate_->OnAcceptPeer(remote_node_name_, data->token, data->peer_name, - data->port_name); - return; - } - break; - } - - default: - break; - } - - DLOG(ERROR) << "Received invalid message. Closing channel."; - delegate_->OnChannelError(remote_node_name_, this); -} - -void NodeChannel::OnChannelError() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - RequestContext request_context(RequestContext::Source::SYSTEM); - - ShutDown(); - // |OnChannelError()| may cause |this| to be destroyed, but still need access - // to the name name after that destruction. So may a copy of - // |remote_node_name_| so it can be used if |this| becomes destroyed. - ports::NodeName node_name = remote_node_name_; - delegate_->OnChannelError(node_name, this); -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -void NodeChannel::OnProcessReady(base::ProcessHandle process) { - io_task_runner_->PostTask(FROM_HERE, base::Bind( - &NodeChannel::ProcessPendingMessagesWithMachPorts, this)); -} - -void NodeChannel::ProcessPendingMessagesWithMachPorts() { - MachPortRelay* relay = delegate_->GetMachPortRelay(); - DCHECK(relay); - - base::ProcessHandle remote_process_handle; - { - base::AutoLock lock(remote_process_handle_lock_); - remote_process_handle = remote_process_handle_; - } - PendingMessageQueue pending_writes; - PendingRelayMessageQueue pending_relays; - { - base::AutoLock lock(pending_mach_messages_lock_); - pending_writes.swap(pending_write_messages_); - pending_relays.swap(pending_relay_messages_); - } - - while (!pending_writes.empty()) { - Channel::MessagePtr message = std::move(pending_writes.front()); - pending_writes.pop(); - if (!relay->SendPortsToProcess(message.get(), remote_process_handle)) { - LOG(ERROR) << "Error on sending mach ports. Remote process is likely " - << "gone. Dropping message."; - return; - } - - base::AutoLock lock(channel_lock_); - if (!channel_) { - DLOG(ERROR) << "Dropping message on closed channel."; - break; - } else { - channel_->Write(std::move(message)); - } - } - - // Ensure this NodeChannel stays alive while flushing relay messages. - scoped_refptr keepalive = this; - - while (!pending_relays.empty()) { - ports::NodeName destination = pending_relays.front().first; - Channel::MessagePtr message = std::move(pending_relays.front().second); - pending_relays.pop(); - delegate_->OnRelayPortsMessage(remote_node_name_, remote_process_handle, - destination, std::move(message)); - } -} -#endif - -void NodeChannel::WriteChannelMessage(Channel::MessagePtr message) { -#if defined(OS_WIN) - // Map handles to the destination process. Note: only messages from a - // privileged node should contain handles on Windows. If an unprivileged - // node needs to send handles, it should do so via RelayPortsMessage which - // stashes the handles in the message in such a way that they go undetected - // here (they'll be unpacked and duplicated by a privileged parent.) - - if (message->has_handles()) { - base::ProcessHandle remote_process_handle; - { - base::AutoLock lock(remote_process_handle_lock_); - remote_process_handle = remote_process_handle_; - } - - // Rewrite outgoing handles if we have a handle to the destination process. - if (remote_process_handle != base::kNullProcessHandle) { - ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); - if (!Channel::Message::RewriteHandles(base::GetCurrentProcessHandle(), - remote_process_handle, - handles.get())) { - DLOG(ERROR) << "Failed to duplicate one or more outgoing handles."; - } - message->SetHandles(std::move(handles)); - } - } -#elif defined(OS_MACOSX) && !defined(OS_IOS) - // On OSX, we need to transfer mach ports to the destination process before - // transferring the message itself. - if (message->has_mach_ports()) { - MachPortRelay* relay = delegate_->GetMachPortRelay(); - if (relay) { - base::ProcessHandle remote_process_handle; - { - base::AutoLock lock(remote_process_handle_lock_); - // Expect that the receiving node is a child. - DCHECK(remote_process_handle_ != base::kNullProcessHandle); - remote_process_handle = remote_process_handle_; - } - { - base::AutoLock lock(pending_mach_messages_lock_); - if (relay->port_provider()->TaskForPid(remote_process_handle) == - MACH_PORT_NULL) { - // It is also possible for TaskForPid() to return MACH_PORT_NULL when - // the process has started, then died. In that case, the queued - // message will never be processed. But that's fine since we're about - // to die anyway. - pending_write_messages_.push(std::move(message)); - return; - } - } - - if (!relay->SendPortsToProcess(message.get(), remote_process_handle)) { - LOG(ERROR) << "Error on sending mach ports. Remote process is likely " - << "gone. Dropping message."; - return; - } - } - } -#endif - - base::AutoLock lock(channel_lock_); - if (!channel_) - DLOG(ERROR) << "Dropping message on closed channel."; - else - channel_->Write(std::move(message)); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/node_channel.h b/mojo/edk/system/node_channel.h deleted file mode 100644 index 95dc341..0000000 --- a/mojo/edk/system/node_channel.h +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_NODE_CHANNEL_H_ -#define MOJO_EDK_SYSTEM_NODE_CHANNEL_H_ - -#include -#include -#include - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/process/process_handle.h" -#include "base/synchronization/lock.h" -#include "base/task_runner.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/connection_params.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/channel.h" -#include "mojo/edk/system/ports/name.h" - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include "mojo/edk/system/mach_port_relay.h" -#endif - -namespace mojo { -namespace edk { - -// Wraps a Channel to send and receive Node control messages. -class NodeChannel : public base::RefCountedThreadSafe, - public Channel::Delegate -#if defined(OS_MACOSX) && !defined(OS_IOS) - , public MachPortRelay::Observer -#endif - { - public: - class Delegate { - public: - virtual ~Delegate() {} - virtual void OnAcceptChild(const ports::NodeName& from_node, - const ports::NodeName& parent_name, - const ports::NodeName& token) = 0; - virtual void OnAcceptParent(const ports::NodeName& from_node, - const ports::NodeName& token, - const ports::NodeName& child_name) = 0; - virtual void OnAddBrokerClient(const ports::NodeName& from_node, - const ports::NodeName& client_name, - base::ProcessHandle process_handle) = 0; - virtual void OnBrokerClientAdded(const ports::NodeName& from_node, - const ports::NodeName& client_name, - ScopedPlatformHandle broker_channel) = 0; - virtual void OnAcceptBrokerClient(const ports::NodeName& from_node, - const ports::NodeName& broker_name, - ScopedPlatformHandle broker_channel) = 0; - virtual void OnPortsMessage(const ports::NodeName& from_node, - Channel::MessagePtr message) = 0; - virtual void OnRequestPortMerge(const ports::NodeName& from_node, - const ports::PortName& connector_port_name, - const std::string& token) = 0; - virtual void OnRequestIntroduction(const ports::NodeName& from_node, - const ports::NodeName& name) = 0; - virtual void OnIntroduce(const ports::NodeName& from_node, - const ports::NodeName& name, - ScopedPlatformHandle channel_handle) = 0; - virtual void OnBroadcast(const ports::NodeName& from_node, - Channel::MessagePtr message) = 0; -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - virtual void OnRelayPortsMessage(const ports::NodeName& from_node, - base::ProcessHandle from_process, - const ports::NodeName& destination, - Channel::MessagePtr message) = 0; - virtual void OnPortsMessageFromRelay(const ports::NodeName& from_node, - const ports::NodeName& source_node, - Channel::MessagePtr message) = 0; -#endif - virtual void OnAcceptPeer(const ports::NodeName& from_node, - const ports::NodeName& token, - const ports::NodeName& peer_name, - const ports::PortName& port_name) = 0; - virtual void OnChannelError(const ports::NodeName& node, - NodeChannel* channel) = 0; - -#if defined(OS_MACOSX) && !defined(OS_IOS) - virtual MachPortRelay* GetMachPortRelay() = 0; -#endif - }; - - static scoped_refptr Create( - Delegate* delegate, - ConnectionParams connection_params, - scoped_refptr io_task_runner, - const ProcessErrorCallback& process_error_callback); - - static Channel::MessagePtr CreatePortsMessage(size_t payload_size, - void** payload, - size_t num_handles); - - static void GetPortsMessageData(Channel::Message* message, void** data, - size_t* num_data_bytes); - - // Start receiving messages. - void Start(); - - // Permanently stop the channel from sending or receiving messages. - void ShutDown(); - - // Leaks the pipe handle instead of closing it on shutdown. - void LeakHandleOnShutdown(); - - // Invokes the bad message callback for this channel, if any. - void NotifyBadMessage(const std::string& error); - - // Note: On Windows, we take ownership of the remote process handle. - void SetRemoteProcessHandle(base::ProcessHandle process_handle); - bool HasRemoteProcessHandle(); - // Note: The returned |ProcessHandle| is owned by the caller and should be - // freed if necessary. - base::ProcessHandle CopyRemoteProcessHandle(); - - // Used for context in Delegate calls (via |from_node| arguments.) - void SetRemoteNodeName(const ports::NodeName& name); - - void AcceptChild(const ports::NodeName& parent_name, - const ports::NodeName& token); - void AcceptParent(const ports::NodeName& token, - const ports::NodeName& child_name); - void AcceptPeer(const ports::NodeName& sender_name, - const ports::NodeName& token, - const ports::PortName& port_name); - void AddBrokerClient(const ports::NodeName& client_name, - base::ProcessHandle process_handle); - void BrokerClientAdded(const ports::NodeName& client_name, - ScopedPlatformHandle broker_channel); - void AcceptBrokerClient(const ports::NodeName& broker_name, - ScopedPlatformHandle broker_channel); - void PortsMessage(Channel::MessagePtr message); - void RequestPortMerge(const ports::PortName& connector_port_name, - const std::string& token); - void RequestIntroduction(const ports::NodeName& name); - void Introduce(const ports::NodeName& name, - ScopedPlatformHandle channel_handle); - void Broadcast(Channel::MessagePtr message); - -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - // Relay the message to the specified node via this channel. This is used to - // pass windows handles between two processes that do not have permission to - // duplicate handles into the other's address space. The relay process is - // assumed to have that permission. - void RelayPortsMessage(const ports::NodeName& destination, - Channel::MessagePtr message); - - // Sends a message to its destination from a relay. This is interpreted by the - // receiver similarly to PortsMessage, but the original source node is - // provided as additional message metadata from the (trusted) relay node. - void PortsMessageFromRelay(const ports::NodeName& source, - Channel::MessagePtr message); -#endif - - private: - friend class base::RefCountedThreadSafe; - - using PendingMessageQueue = std::queue; - using PendingRelayMessageQueue = - std::queue>; - - NodeChannel(Delegate* delegate, - ConnectionParams connection_params, - scoped_refptr io_task_runner, - const ProcessErrorCallback& process_error_callback); - ~NodeChannel() override; - - // Channel::Delegate: - void OnChannelMessage(const void* payload, - size_t payload_size, - ScopedPlatformHandleVectorPtr handles) override; - void OnChannelError() override; - -#if defined(OS_MACOSX) && !defined(OS_IOS) - // MachPortRelay::Observer: - void OnProcessReady(base::ProcessHandle process) override; - - void ProcessPendingMessagesWithMachPorts(); -#endif - - void WriteChannelMessage(Channel::MessagePtr message); - - Delegate* const delegate_; - const scoped_refptr io_task_runner_; - const ProcessErrorCallback process_error_callback_; - - base::Lock channel_lock_; - scoped_refptr channel_; - - // Must only be accessed from |io_task_runner_|'s thread. - ports::NodeName remote_node_name_; - - base::Lock remote_process_handle_lock_; - base::ProcessHandle remote_process_handle_ = base::kNullProcessHandle; -#if defined(OS_WIN) - ScopedPlatformHandle scoped_remote_process_handle_; -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) - base::Lock pending_mach_messages_lock_; - PendingMessageQueue pending_write_messages_; - PendingRelayMessageQueue pending_relay_messages_; -#endif - - DISALLOW_COPY_AND_ASSIGN(NodeChannel); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_NODE_CHANNEL_H_ diff --git a/mojo/edk/system/node_controller.cc b/mojo/edk/system/node_controller.cc deleted file mode 100644 index 73b16b1..0000000 --- a/mojo/edk/system/node_controller.cc +++ /dev/null @@ -1,1470 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/node_controller.h" - -#include -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/metrics/histogram_macros.h" -#include "base/process/process_handle.h" -#include "base/rand_util.h" -#include "base/time/time.h" -#include "base/timer/elapsed_timer.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/embedder/named_platform_channel_pair.h" -#include "mojo/edk/embedder/named_platform_handle.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/system/broker.h" -#include "mojo/edk/system/broker_host.h" -#include "mojo/edk/system/core.h" -#include "mojo/edk/system/ports_message.h" -#include "mojo/edk/system/request_context.h" - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include "mojo/edk/system/mach_port_relay.h" -#endif - -#if !defined(OS_NACL) -#include "crypto/random.h" -#endif - -namespace mojo { -namespace edk { - -namespace { - -#if defined(OS_NACL) -template -void GenerateRandomName(T* out) { base::RandBytes(out, sizeof(T)); } -#else -template -void GenerateRandomName(T* out) { crypto::RandBytes(out, sizeof(T)); } -#endif - -ports::NodeName GetRandomNodeName() { - ports::NodeName name; - GenerateRandomName(&name); - return name; -} - -void RecordPeerCount(size_t count) { - DCHECK_LE(count, static_cast(std::numeric_limits::max())); - - // 8k is the maximum number of file descriptors allowed in Chrome. - UMA_HISTOGRAM_CUSTOM_COUNTS("Mojo.System.Node.ConnectedPeers", - static_cast(count), - 1 /* min */, - 8000 /* max */, - 50 /* bucket count */); -} - -void RecordPendingChildCount(size_t count) { - DCHECK_LE(count, static_cast(std::numeric_limits::max())); - - // 8k is the maximum number of file descriptors allowed in Chrome. - UMA_HISTOGRAM_CUSTOM_COUNTS("Mojo.System.Node.PendingChildren", - static_cast(count), - 1 /* min */, - 8000 /* max */, - 50 /* bucket count */); -} - -bool ParsePortsMessage(Channel::Message* message, - void** data, - size_t* num_data_bytes, - size_t* num_header_bytes, - size_t* num_payload_bytes, - size_t* num_ports_bytes) { - DCHECK(data && num_data_bytes && num_header_bytes && num_payload_bytes && - num_ports_bytes); - - NodeChannel::GetPortsMessageData(message, data, num_data_bytes); - if (!*num_data_bytes) - return false; - - if (!ports::Message::Parse(*data, *num_data_bytes, num_header_bytes, - num_payload_bytes, num_ports_bytes)) { - return false; - } - - return true; -} - -// Used by NodeController to watch for shutdown. Since no IO can happen once -// the IO thread is killed, the NodeController can cleanly drop all its peers -// at that time. -class ThreadDestructionObserver : - public base::MessageLoop::DestructionObserver { - public: - static void Create(scoped_refptr task_runner, - const base::Closure& callback) { - if (task_runner->RunsTasksOnCurrentThread()) { - // Owns itself. - new ThreadDestructionObserver(callback); - } else { - task_runner->PostTask(FROM_HERE, - base::Bind(&Create, task_runner, callback)); - } - } - - private: - explicit ThreadDestructionObserver(const base::Closure& callback) - : callback_(callback) { - base::MessageLoop::current()->AddDestructionObserver(this); - } - - ~ThreadDestructionObserver() override { - base::MessageLoop::current()->RemoveDestructionObserver(this); - } - - // base::MessageLoop::DestructionObserver: - void WillDestroyCurrentMessageLoop() override { - callback_.Run(); - delete this; - } - - const base::Closure callback_; - - DISALLOW_COPY_AND_ASSIGN(ThreadDestructionObserver); -}; - -} // namespace - -NodeController::~NodeController() {} - -NodeController::NodeController(Core* core) - : core_(core), - name_(GetRandomNodeName()), - node_(new ports::Node(name_, this)) { - DVLOG(1) << "Initializing node " << name_; -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -void NodeController::CreateMachPortRelay( - base::PortProvider* port_provider) { - base::AutoLock lock(mach_port_relay_lock_); - DCHECK(!mach_port_relay_); - mach_port_relay_.reset(new MachPortRelay(port_provider)); -} -#endif - -void NodeController::SetIOTaskRunner( - scoped_refptr task_runner) { - io_task_runner_ = task_runner; - ThreadDestructionObserver::Create( - io_task_runner_, - base::Bind(&NodeController::DropAllPeers, base::Unretained(this))); -} - -void NodeController::ConnectToChild( - base::ProcessHandle process_handle, - ConnectionParams connection_params, - const std::string& child_token, - const ProcessErrorCallback& process_error_callback) { - // Generate the temporary remote node name here so that it can be associated - // with the embedder's child_token. If an error occurs in the child process - // after it is launched, but before any reserved ports are connected, this can - // be used to clean up any dangling ports. - ports::NodeName node_name; - GenerateRandomName(&node_name); - - { - base::AutoLock lock(reserved_ports_lock_); - bool inserted = pending_child_tokens_.insert( - std::make_pair(node_name, child_token)).second; - DCHECK(inserted); - } - -#if defined(OS_WIN) - // On Windows, we need to duplicate the process handle because we have no - // control over its lifetime and it may become invalid by the time the posted - // task runs. - HANDLE dup_handle = INVALID_HANDLE_VALUE; - BOOL ok = ::DuplicateHandle( - base::GetCurrentProcessHandle(), process_handle, - base::GetCurrentProcessHandle(), &dup_handle, - 0, FALSE, DUPLICATE_SAME_ACCESS); - DPCHECK(ok); - process_handle = dup_handle; -#endif - - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&NodeController::ConnectToChildOnIOThread, - base::Unretained(this), process_handle, - base::Passed(&connection_params), node_name, - process_error_callback)); -} - -void NodeController::CloseChildPorts(const std::string& child_token) { - std::vector ports_to_close; - { - std::vector port_tokens; - base::AutoLock lock(reserved_ports_lock_); - for (const auto& port : reserved_ports_) { - if (port.second.child_token == child_token) { - DVLOG(1) << "Closing reserved port " << port.second.port.name(); - ports_to_close.push_back(port.second.port); - port_tokens.push_back(port.first); - } - } - - for (const auto& token : port_tokens) - reserved_ports_.erase(token); - } - - for (const auto& port : ports_to_close) - node_->ClosePort(port); - - // Ensure local port closure messages are processed. - AcceptIncomingMessages(); -} - -void NodeController::ClosePeerConnection(const std::string& peer_token) { - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&NodeController::ClosePeerConnectionOnIOThread, - base::Unretained(this), peer_token)); -} - -void NodeController::ConnectToParent(ConnectionParams connection_params) { -#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI) - // Use the bootstrap channel for the broker and receive the node's channel - // synchronously as the first message from the broker. - base::ElapsedTimer timer; - broker_.reset(new Broker(connection_params.TakeChannelHandle())); - ScopedPlatformHandle platform_handle = broker_->GetParentPlatformHandle(); - UMA_HISTOGRAM_TIMES("Mojo.System.GetParentPlatformHandleSyncTime", - timer.Elapsed()); - - if (!platform_handle.is_valid()) { - // Most likely the browser side of the channel has already been closed and - // the broker was unable to negotiate a NodeChannel pipe. In this case we - // can cancel parent connection. - DVLOG(1) << "Cannot connect to invalid parent channel."; - CancelPendingPortMerges(); - return; - } - connection_params = ConnectionParams(std::move(platform_handle)); -#endif - - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&NodeController::ConnectToParentOnIOThread, - base::Unretained(this), base::Passed(&connection_params))); -} - -void NodeController::ConnectToPeer(ConnectionParams connection_params, - const ports::PortRef& port, - const std::string& peer_token) { - ports::NodeName node_name; - GenerateRandomName(&node_name); - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&NodeController::ConnectToPeerOnIOThread, - base::Unretained(this), base::Passed(&connection_params), - node_name, port, peer_token)); -} - -void NodeController::SetPortObserver(const ports::PortRef& port, - scoped_refptr observer) { - node_->SetUserData(port, std::move(observer)); -} - -void NodeController::ClosePort(const ports::PortRef& port) { - SetPortObserver(port, nullptr); - int rv = node_->ClosePort(port); - DCHECK_EQ(rv, ports::OK) << " Failed to close port: " << port.name(); - - AcceptIncomingMessages(); -} - -int NodeController::SendMessage(const ports::PortRef& port, - std::unique_ptr message) { - ports::ScopedMessage ports_message(message.release()); - int rv = node_->SendMessage(port, std::move(ports_message)); - - AcceptIncomingMessages(); - return rv; -} - -void NodeController::ReservePort(const std::string& token, - const ports::PortRef& port, - const std::string& child_token) { - DVLOG(2) << "Reserving port " << port.name() << "@" << name_ << " for token " - << token; - - base::AutoLock lock(reserved_ports_lock_); - auto result = reserved_ports_.insert( - std::make_pair(token, ReservedPort{port, child_token})); - DCHECK(result.second); -} - -void NodeController::MergePortIntoParent(const std::string& token, - const ports::PortRef& port) { - bool was_merged = false; - { - // This request may be coming from within the process that reserved the - // "parent" side (e.g. for Chrome single-process mode), so if this token is - // reserved locally, merge locally instead. - base::AutoLock lock(reserved_ports_lock_); - auto it = reserved_ports_.find(token); - if (it != reserved_ports_.end()) { - node_->MergePorts(port, name_, it->second.port.name()); - reserved_ports_.erase(it); - was_merged = true; - } - } - if (was_merged) { - AcceptIncomingMessages(); - return; - } - - scoped_refptr parent; - bool reject_merge = false; - { - // Hold |pending_port_merges_lock_| while getting |parent|. Otherwise, - // there is a race where the parent can be set, and |pending_port_merges_| - // be processed between retrieving |parent| and adding the merge to - // |pending_port_merges_|. - base::AutoLock lock(pending_port_merges_lock_); - parent = GetParentChannel(); - if (reject_pending_merges_) { - reject_merge = true; - } else if (!parent) { - pending_port_merges_.push_back(std::make_pair(token, port)); - return; - } - } - if (reject_merge) { - node_->ClosePort(port); - DVLOG(2) << "Rejecting port merge for token " << token - << " due to closed parent channel."; - AcceptIncomingMessages(); - return; - } - - parent->RequestPortMerge(port.name(), token); -} - -int NodeController::MergeLocalPorts(const ports::PortRef& port0, - const ports::PortRef& port1) { - int rv = node_->MergeLocalPorts(port0, port1); - AcceptIncomingMessages(); - return rv; -} - -scoped_refptr NodeController::CreateSharedBuffer( - size_t num_bytes) { -#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI) - // Shared buffer creation failure is fatal, so always use the broker when we - // have one. This does mean that a non-root process that has children will use - // the broker for shared buffer creation even though that process is - // privileged. - if (broker_) { - return broker_->GetSharedBuffer(num_bytes); - } -#endif - return PlatformSharedBuffer::Create(num_bytes); -} - -void NodeController::RequestShutdown(const base::Closure& callback) { - { - base::AutoLock lock(shutdown_lock_); - shutdown_callback_ = callback; - shutdown_callback_flag_.Set(true); - } - - AttemptShutdownIfRequested(); -} - -void NodeController::NotifyBadMessageFrom(const ports::NodeName& source_node, - const std::string& error) { - scoped_refptr peer = GetPeerChannel(source_node); - if (peer) - peer->NotifyBadMessage(error); -} - -void NodeController::ConnectToChildOnIOThread( - base::ProcessHandle process_handle, - ConnectionParams connection_params, - ports::NodeName token, - const ProcessErrorCallback& process_error_callback) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - -#if !defined(OS_MACOSX) && !defined(OS_NACL) - PlatformChannelPair node_channel; - ScopedPlatformHandle server_handle = node_channel.PassServerHandle(); - // BrokerHost owns itself. - BrokerHost* broker_host = - new BrokerHost(process_handle, connection_params.TakeChannelHandle()); - bool channel_ok = broker_host->SendChannel(node_channel.PassClientHandle()); - -#if defined(OS_WIN) - if (!channel_ok) { - // On Windows the above operation may fail if the channel is crossing a - // session boundary. In that case we fall back to a named pipe. - NamedPlatformChannelPair named_channel; - server_handle = named_channel.PassServerHandle(); - broker_host->SendNamedChannel(named_channel.handle().name); - } -#else - CHECK(channel_ok); -#endif // defined(OS_WIN) - - scoped_refptr channel = - NodeChannel::Create(this, ConnectionParams(std::move(server_handle)), - io_task_runner_, process_error_callback); - -#else // !defined(OS_MACOSX) && !defined(OS_NACL) - scoped_refptr channel = - NodeChannel::Create(this, std::move(connection_params), io_task_runner_, - process_error_callback); -#endif // !defined(OS_MACOSX) && !defined(OS_NACL) - - // We set up the child channel with a temporary name so it can be identified - // as a pending child if it writes any messages to the channel. We may start - // receiving messages from it (though we shouldn't) as soon as Start() is - // called below. - - pending_children_.insert(std::make_pair(token, channel)); - RecordPendingChildCount(pending_children_.size()); - - channel->SetRemoteNodeName(token); - channel->SetRemoteProcessHandle(process_handle); - channel->Start(); - - channel->AcceptChild(name_, token); -} - -void NodeController::ConnectToParentOnIOThread( - ConnectionParams connection_params) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - { - base::AutoLock lock(parent_lock_); - DCHECK(parent_name_ == ports::kInvalidNodeName); - - // At this point we don't know the parent's name, so we can't yet insert it - // into our |peers_| map. That will happen as soon as we receive an - // AcceptChild message from them. - bootstrap_parent_channel_ = - NodeChannel::Create(this, std::move(connection_params), io_task_runner_, - ProcessErrorCallback()); - // Prevent the parent pipe handle from being closed on shutdown. Pipe - // closure is used by the parent to detect the child process has exited. - // Relying on message pipes to be closed is not enough because the parent - // may see the message pipe closure before the child is dead, causing the - // child process to be unexpectedly SIGKILL'd. - bootstrap_parent_channel_->LeakHandleOnShutdown(); - } - bootstrap_parent_channel_->Start(); -} - -void NodeController::ConnectToPeerOnIOThread(ConnectionParams connection_params, - ports::NodeName token, - ports::PortRef port, - const std::string& peer_token) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - scoped_refptr channel = NodeChannel::Create( - this, std::move(connection_params), io_task_runner_, {}); - peer_connections_.insert( - {token, PeerConnection{channel, port, peer_token}}); - peers_by_token_.insert({peer_token, token}); - - channel->SetRemoteNodeName(token); - channel->Start(); - - channel->AcceptPeer(name_, token, port.name()); -} - -void NodeController::ClosePeerConnectionOnIOThread( - const std::string& peer_token) { - RequestContext request_context(RequestContext::Source::SYSTEM); - auto peer = peers_by_token_.find(peer_token); - // The connection may already be closed. - if (peer == peers_by_token_.end()) - return; - - // |peer| may be removed so make a copy of |name|. - ports::NodeName name = peer->second; - DropPeer(name, nullptr); -} - -scoped_refptr NodeController::GetPeerChannel( - const ports::NodeName& name) { - base::AutoLock lock(peers_lock_); - auto it = peers_.find(name); - if (it == peers_.end()) - return nullptr; - return it->second; -} - -scoped_refptr NodeController::GetParentChannel() { - ports::NodeName parent_name; - { - base::AutoLock lock(parent_lock_); - parent_name = parent_name_; - } - return GetPeerChannel(parent_name); -} - -scoped_refptr NodeController::GetBrokerChannel() { - ports::NodeName broker_name; - { - base::AutoLock lock(broker_lock_); - broker_name = broker_name_; - } - return GetPeerChannel(broker_name); -} - -void NodeController::AddPeer(const ports::NodeName& name, - scoped_refptr channel, - bool start_channel) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - DCHECK(name != ports::kInvalidNodeName); - DCHECK(channel); - - channel->SetRemoteNodeName(name); - - OutgoingMessageQueue pending_messages; - { - base::AutoLock lock(peers_lock_); - if (peers_.find(name) != peers_.end()) { - // This can happen normally if two nodes race to be introduced to each - // other. The losing pipe will be silently closed and introduction should - // not be affected. - DVLOG(1) << "Ignoring duplicate peer name " << name; - return; - } - - auto result = peers_.insert(std::make_pair(name, channel)); - DCHECK(result.second); - - DVLOG(2) << "Accepting new peer " << name << " on node " << name_; - - RecordPeerCount(peers_.size()); - - auto it = pending_peer_messages_.find(name); - if (it != pending_peer_messages_.end()) { - std::swap(pending_messages, it->second); - pending_peer_messages_.erase(it); - } - } - - if (start_channel) - channel->Start(); - - // Flush any queued message we need to deliver to this node. - while (!pending_messages.empty()) { - channel->PortsMessage(std::move(pending_messages.front())); - pending_messages.pop(); - } -} - -void NodeController::DropPeer(const ports::NodeName& name, - NodeChannel* channel) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - { - base::AutoLock lock(peers_lock_); - auto it = peers_.find(name); - - if (it != peers_.end()) { - ports::NodeName peer = it->first; - peers_.erase(it); - DVLOG(1) << "Dropped peer " << peer; - } - - pending_peer_messages_.erase(name); - pending_children_.erase(name); - - RecordPeerCount(peers_.size()); - RecordPendingChildCount(pending_children_.size()); - } - - std::vector ports_to_close; - { - // Clean up any reserved ports. - base::AutoLock lock(reserved_ports_lock_); - auto it = pending_child_tokens_.find(name); - if (it != pending_child_tokens_.end()) { - const std::string& child_token = it->second; - - std::vector port_tokens; - for (const auto& port : reserved_ports_) { - if (port.second.child_token == child_token) { - DVLOG(1) << "Closing reserved port: " << port.second.port.name(); - ports_to_close.push_back(port.second.port); - port_tokens.push_back(port.first); - } - } - - // We have to erase reserved ports in a two-step manner because the usual - // manner of using the returned iterator from map::erase isn't technically - // valid in C++11 (although it is in C++14). - for (const auto& token : port_tokens) - reserved_ports_.erase(token); - - pending_child_tokens_.erase(it); - } - } - - bool is_parent; - { - base::AutoLock lock(parent_lock_); - is_parent = (name == parent_name_ || channel == bootstrap_parent_channel_); - } - - // If the error comes from the parent channel, we also need to cancel any - // port merge requests, so that errors can be propagated to the message - // pipes. - if (is_parent) - CancelPendingPortMerges(); - - auto peer = peer_connections_.find(name); - if (peer != peer_connections_.end()) { - peers_by_token_.erase(peer->second.peer_token); - ports_to_close.push_back(peer->second.local_port); - peer_connections_.erase(peer); - } - - for (const auto& port : ports_to_close) - node_->ClosePort(port); - - node_->LostConnectionToNode(name); - - AcceptIncomingMessages(); -} - -void NodeController::SendPeerMessage(const ports::NodeName& name, - ports::ScopedMessage message) { - Channel::MessagePtr channel_message = - static_cast(message.get())->TakeChannelMessage(); - - scoped_refptr peer = GetPeerChannel(name); -#if defined(OS_WIN) - if (channel_message->has_handles()) { - // If we're sending a message with handles we aren't the destination - // node's parent or broker (i.e. we don't know its process handle), ask - // the broker to relay for us. - scoped_refptr broker = GetBrokerChannel(); - if (!peer || !peer->HasRemoteProcessHandle()) { - if (broker) { - broker->RelayPortsMessage(name, std::move(channel_message)); - } else { - base::AutoLock lock(broker_lock_); - pending_relay_messages_[name].emplace(std::move(channel_message)); - } - return; - } - } -#elif defined(OS_MACOSX) && !defined(OS_IOS) - if (channel_message->has_mach_ports()) { - // Messages containing Mach ports are always routed through the broker, even - // if the broker process is the intended recipient. - bool use_broker = false; - { - base::AutoLock lock(parent_lock_); - use_broker = (bootstrap_parent_channel_ || - parent_name_ != ports::kInvalidNodeName); - } - if (use_broker) { - scoped_refptr broker = GetBrokerChannel(); - if (broker) { - broker->RelayPortsMessage(name, std::move(channel_message)); - } else { - base::AutoLock lock(broker_lock_); - pending_relay_messages_[name].emplace(std::move(channel_message)); - } - return; - } - } -#endif // defined(OS_WIN) - - if (peer) { - peer->PortsMessage(std::move(channel_message)); - return; - } - - // If we don't know who the peer is and we are the broker, we can only assume - // the peer is invalid, i.e., it's either a junk name or has already been - // disconnected. - scoped_refptr broker = GetBrokerChannel(); - if (!broker) { - DVLOG(1) << "Dropping message for unknown peer: " << name; - return; - } - - // If we aren't the broker, assume we just need to be introduced and queue - // until that can be either confirmed or denied by the broker. - bool needs_introduction = false; - { - base::AutoLock lock(peers_lock_); - auto& queue = pending_peer_messages_[name]; - needs_introduction = queue.empty(); - queue.emplace(std::move(channel_message)); - } - if (needs_introduction) - broker->RequestIntroduction(name); -} - -void NodeController::AcceptIncomingMessages() { - // This is an impactically large value which should never be reached in - // practice. See the CHECK below for usage. - constexpr size_t kMaxAcceptedMessages = 1000000; - - size_t num_messages_accepted = 0; - while (incoming_messages_flag_) { - // TODO: We may need to be more careful to avoid starving the rest of the - // thread here. Revisit this if it turns out to be a problem. One - // alternative would be to schedule a task to continue pumping messages - // after flushing once. - - messages_lock_.Acquire(); - if (incoming_messages_.empty()) { - messages_lock_.Release(); - break; - } - - // libstdc++'s deque creates an internal buffer on construction, even when - // the size is 0. So avoid creating it until it is necessary. - std::queue messages; - std::swap(messages, incoming_messages_); - incoming_messages_flag_.Set(false); - messages_lock_.Release(); - - num_messages_accepted += messages.size(); - while (!messages.empty()) { - node_->AcceptMessage(std::move(messages.front())); - messages.pop(); - } - - // This is effectively a safeguard against potential bugs which might lead - // to runaway message cycles. If any such cycles arise, we'll start seeing - // crash reports from this location. - CHECK_LE(num_messages_accepted, kMaxAcceptedMessages); - } - - if (num_messages_accepted >= 4) { - // Note: We avoid logging this histogram for the vast majority of cases. - // See https://crbug.com/685763 for more context. - UMA_HISTOGRAM_CUSTOM_COUNTS("Mojo.System.MessagesAcceptedPerEvent", - static_cast(num_messages_accepted), - 1 /* min */, - 500 /* max */, - 50 /* bucket count */); - } - - AttemptShutdownIfRequested(); -} - -void NodeController::ProcessIncomingMessages() { - RequestContext request_context(RequestContext::Source::SYSTEM); - - { - base::AutoLock lock(messages_lock_); - // Allow a new incoming messages processing task to be posted. This can't be - // done after AcceptIncomingMessages() otherwise a message might be missed. - // Doing it here may result in at most two tasks existing at the same time; - // this running one, and one pending in the task runner. - incoming_messages_task_posted_ = false; - } - - AcceptIncomingMessages(); -} - -void NodeController::DropAllPeers() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - std::vector> all_peers; - { - base::AutoLock lock(parent_lock_); - if (bootstrap_parent_channel_) { - // |bootstrap_parent_channel_| isn't null'd here becuase we rely on its - // existence to determine whether or not this is the root node. Once - // bootstrap_parent_channel_->ShutDown() has been called, - // |bootstrap_parent_channel_| is essentially a dead object and it doesn't - // matter if it's deleted now or when |this| is deleted. - // Note: |bootstrap_parent_channel_| is only modified on the IO thread. - all_peers.push_back(bootstrap_parent_channel_); - } - } - - { - base::AutoLock lock(peers_lock_); - for (const auto& peer : peers_) - all_peers.push_back(peer.second); - for (const auto& peer : pending_children_) - all_peers.push_back(peer.second); - peers_.clear(); - pending_children_.clear(); - pending_peer_messages_.clear(); - peer_connections_.clear(); - } - - for (const auto& peer : all_peers) - peer->ShutDown(); - - if (destroy_on_io_thread_shutdown_) - delete this; -} - -void NodeController::GenerateRandomPortName(ports::PortName* port_name) { - GenerateRandomName(port_name); -} - -void NodeController::AllocMessage(size_t num_header_bytes, - ports::ScopedMessage* message) { - message->reset(new PortsMessage(num_header_bytes, 0, 0, nullptr)); -} - -void NodeController::ForwardMessage(const ports::NodeName& node, - ports::ScopedMessage message) { - DCHECK(message); - bool schedule_pump_task = false; - if (node == name_) { - // NOTE: We need to avoid re-entering the Node instance within - // ForwardMessage. Because ForwardMessage is only ever called - // (synchronously) in response to Node's ClosePort, SendMessage, or - // AcceptMessage, we flush the queue after calling any of those methods. - base::AutoLock lock(messages_lock_); - // |io_task_runner_| may be null in tests or processes that don't require - // multi-process Mojo. - schedule_pump_task = incoming_messages_.empty() && io_task_runner_ && - !incoming_messages_task_posted_; - incoming_messages_task_posted_ |= schedule_pump_task; - incoming_messages_.emplace(std::move(message)); - incoming_messages_flag_.Set(true); - } else { - SendPeerMessage(node, std::move(message)); - } - - if (schedule_pump_task) { - // Normally, the queue is processed after the action that added the local - // message is done (i.e. SendMessage, ClosePort, etc). However, it's also - // possible for a local message to be added as a result of a remote message, - // and OnChannelMessage() doesn't process this queue (although - // OnPortsMessage() does). There may also be other code paths, now or added - // in the future, which cause local messages to be added but don't process - // this message queue. - // - // Instead of adding a call to AcceptIncomingMessages() on every possible - // code path, post a task to the IO thread to process the queue. If the - // current call stack processes the queue, this may end up doing nothing. - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&NodeController::ProcessIncomingMessages, - base::Unretained(this))); - } -} - -void NodeController::BroadcastMessage(ports::ScopedMessage message) { - CHECK_EQ(message->num_ports(), 0u); - Channel::MessagePtr channel_message = - static_cast(message.get())->TakeChannelMessage(); - CHECK(!channel_message->has_handles()); - - scoped_refptr broker = GetBrokerChannel(); - if (broker) - broker->Broadcast(std::move(channel_message)); - else - OnBroadcast(name_, std::move(channel_message)); -} - -void NodeController::PortStatusChanged(const ports::PortRef& port) { - scoped_refptr user_data; - node_->GetUserData(port, &user_data); - - PortObserver* observer = static_cast(user_data.get()); - if (observer) { - observer->OnPortStatusChanged(); - } else { - DVLOG(2) << "Ignoring status change for " << port.name() << " because it " - << "doesn't have an observer."; - } -} - -void NodeController::OnAcceptChild(const ports::NodeName& from_node, - const ports::NodeName& parent_name, - const ports::NodeName& token) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - scoped_refptr parent; - { - base::AutoLock lock(parent_lock_); - if (bootstrap_parent_channel_ && parent_name_ == ports::kInvalidNodeName) { - parent_name_ = parent_name; - parent = bootstrap_parent_channel_; - } - } - - if (!parent) { - DLOG(ERROR) << "Unexpected AcceptChild message from " << from_node; - DropPeer(from_node, nullptr); - return; - } - - parent->SetRemoteNodeName(parent_name); - parent->AcceptParent(token, name_); - - // NOTE: The child does not actually add its parent as a peer until - // receiving an AcceptBrokerClient message from the broker. The parent - // will request that said message be sent upon receiving AcceptParent. - - DVLOG(1) << "Child " << name_ << " accepting parent " << parent_name; -} - -void NodeController::OnAcceptParent(const ports::NodeName& from_node, - const ports::NodeName& token, - const ports::NodeName& child_name) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - auto it = pending_children_.find(from_node); - if (it == pending_children_.end() || token != from_node) { - DLOG(ERROR) << "Received unexpected AcceptParent message from " - << from_node; - DropPeer(from_node, nullptr); - return; - } - - { - base::AutoLock lock(reserved_ports_lock_); - auto it = pending_child_tokens_.find(from_node); - if (it != pending_child_tokens_.end()) { - std::string token = std::move(it->second); - pending_child_tokens_.erase(it); - pending_child_tokens_[child_name] = std::move(token); - } - } - - scoped_refptr channel = it->second; - pending_children_.erase(it); - - DCHECK(channel); - - DVLOG(1) << "Parent " << name_ << " accepted child " << child_name; - - AddPeer(child_name, channel, false /* start_channel */); - - // TODO(rockot/amistry): We could simplify child initialization if we could - // synchronously get a new async broker channel from the broker. For now we do - // it asynchronously since it's only used to facilitate handle passing, not - // handle creation. - scoped_refptr broker = GetBrokerChannel(); - if (broker) { - // Inform the broker of this new child. - broker->AddBrokerClient(child_name, channel->CopyRemoteProcessHandle()); - } else { - // If we have no broker, either we need to wait for one, or we *are* the - // broker. - scoped_refptr parent = GetParentChannel(); - if (!parent) { - base::AutoLock lock(parent_lock_); - parent = bootstrap_parent_channel_; - } - - if (!parent) { - // Yes, we're the broker. We can initialize the child directly. - channel->AcceptBrokerClient(name_, ScopedPlatformHandle()); - } else { - // We aren't the broker, so wait for a broker connection. - base::AutoLock lock(broker_lock_); - pending_broker_clients_.push(child_name); - } - } -} - -void NodeController::OnAddBrokerClient(const ports::NodeName& from_node, - const ports::NodeName& client_name, - base::ProcessHandle process_handle) { -#if defined(OS_WIN) - // Scoped handle to avoid leaks on error. - ScopedPlatformHandle scoped_process_handle = - ScopedPlatformHandle(PlatformHandle(process_handle)); -#endif - scoped_refptr sender = GetPeerChannel(from_node); - if (!sender) { - DLOG(ERROR) << "Ignoring AddBrokerClient from unknown sender."; - return; - } - - if (GetPeerChannel(client_name)) { - DLOG(ERROR) << "Ignoring AddBrokerClient for known client."; - DropPeer(from_node, nullptr); - return; - } - - PlatformChannelPair broker_channel; - ConnectionParams connection_params(broker_channel.PassServerHandle()); - scoped_refptr client = - NodeChannel::Create(this, std::move(connection_params), io_task_runner_, - ProcessErrorCallback()); - -#if defined(OS_WIN) - // The broker must have a working handle to the client process in order to - // properly copy other handles to and from the client. - if (!scoped_process_handle.is_valid()) { - DLOG(ERROR) << "Broker rejecting client with invalid process handle."; - return; - } - client->SetRemoteProcessHandle(scoped_process_handle.release().handle); -#else - client->SetRemoteProcessHandle(process_handle); -#endif - - AddPeer(client_name, client, true /* start_channel */); - - DVLOG(1) << "Broker " << name_ << " accepting client " << client_name - << " from peer " << from_node; - - sender->BrokerClientAdded(client_name, broker_channel.PassClientHandle()); -} - -void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node, - const ports::NodeName& client_name, - ScopedPlatformHandle broker_channel) { - scoped_refptr client = GetPeerChannel(client_name); - if (!client) { - DLOG(ERROR) << "BrokerClientAdded for unknown child " << client_name; - return; - } - - // This should have come from our own broker. - if (GetBrokerChannel() != GetPeerChannel(from_node)) { - DLOG(ERROR) << "BrokerClientAdded from non-broker node " << from_node; - return; - } - - DVLOG(1) << "Child " << client_name << " accepted by broker " << from_node; - - client->AcceptBrokerClient(from_node, std::move(broker_channel)); -} - -void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node, - const ports::NodeName& broker_name, - ScopedPlatformHandle broker_channel) { - // This node should already have a parent in bootstrap mode. - ports::NodeName parent_name; - scoped_refptr parent; - { - base::AutoLock lock(parent_lock_); - parent_name = parent_name_; - parent = bootstrap_parent_channel_; - bootstrap_parent_channel_ = nullptr; - } - DCHECK(parent_name == from_node); - DCHECK(parent); - - std::queue pending_broker_clients; - std::unordered_map - pending_relay_messages; - { - base::AutoLock lock(broker_lock_); - broker_name_ = broker_name; - std::swap(pending_broker_clients, pending_broker_clients_); - std::swap(pending_relay_messages, pending_relay_messages_); - } - DCHECK(broker_name != ports::kInvalidNodeName); - - // It's now possible to add both the broker and the parent as peers. - // Note that the broker and parent may be the same node. - scoped_refptr broker; - if (broker_name == parent_name) { - DCHECK(!broker_channel.is_valid()); - broker = parent; - } else { - DCHECK(broker_channel.is_valid()); - broker = - NodeChannel::Create(this, ConnectionParams(std::move(broker_channel)), - io_task_runner_, ProcessErrorCallback()); - AddPeer(broker_name, broker, true /* start_channel */); - } - - AddPeer(parent_name, parent, false /* start_channel */); - - { - // Complete any port merge requests we have waiting for the parent. - base::AutoLock lock(pending_port_merges_lock_); - for (const auto& request : pending_port_merges_) - parent->RequestPortMerge(request.second.name(), request.first); - pending_port_merges_.clear(); - } - - // Feed the broker any pending children of our own. - while (!pending_broker_clients.empty()) { - const ports::NodeName& child_name = pending_broker_clients.front(); - auto it = pending_children_.find(child_name); - DCHECK(it != pending_children_.end()); - broker->AddBrokerClient(child_name, it->second->CopyRemoteProcessHandle()); - pending_broker_clients.pop(); - } - -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - // Have the broker relay any messages we have waiting. - for (auto& entry : pending_relay_messages) { - const ports::NodeName& destination = entry.first; - auto& message_queue = entry.second; - while (!message_queue.empty()) { - broker->RelayPortsMessage(destination, std::move(message_queue.front())); - message_queue.pop(); - } - } -#endif - - DVLOG(1) << "Child " << name_ << " accepted by broker " << broker_name; -} - -void NodeController::OnPortsMessage(const ports::NodeName& from_node, - Channel::MessagePtr channel_message) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - void* data; - size_t num_data_bytes, num_header_bytes, num_payload_bytes, num_ports_bytes; - if (!ParsePortsMessage(channel_message.get(), &data, &num_data_bytes, - &num_header_bytes, &num_payload_bytes, - &num_ports_bytes)) { - DropPeer(from_node, nullptr); - return; - } - - CHECK(channel_message); - std::unique_ptr ports_message( - new PortsMessage(num_header_bytes, - num_payload_bytes, - num_ports_bytes, - std::move(channel_message))); - ports_message->set_source_node(from_node); - node_->AcceptMessage(ports::ScopedMessage(ports_message.release())); - AcceptIncomingMessages(); -} - -void NodeController::OnRequestPortMerge( - const ports::NodeName& from_node, - const ports::PortName& connector_port_name, - const std::string& token) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - DVLOG(2) << "Node " << name_ << " received RequestPortMerge for token " - << token << " and port " << connector_port_name << "@" << from_node; - - ports::PortRef local_port; - { - base::AutoLock lock(reserved_ports_lock_); - auto it = reserved_ports_.find(token); - if (it == reserved_ports_.end()) { - DVLOG(1) << "Ignoring request to connect to port for unknown token " - << token; - return; - } - local_port = it->second.port; - reserved_ports_.erase(it); - } - - int rv = node_->MergePorts(local_port, from_node, connector_port_name); - if (rv != ports::OK) - DLOG(ERROR) << "MergePorts failed: " << rv; - - AcceptIncomingMessages(); -} - -void NodeController::OnRequestIntroduction(const ports::NodeName& from_node, - const ports::NodeName& name) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - scoped_refptr requestor = GetPeerChannel(from_node); - if (from_node == name || name == ports::kInvalidNodeName || !requestor) { - DLOG(ERROR) << "Rejecting invalid OnRequestIntroduction message from " - << from_node; - DropPeer(from_node, nullptr); - return; - } - - scoped_refptr new_friend = GetPeerChannel(name); - if (!new_friend) { - // We don't know who they're talking about! - requestor->Introduce(name, ScopedPlatformHandle()); - } else { - PlatformChannelPair new_channel; - requestor->Introduce(name, new_channel.PassServerHandle()); - new_friend->Introduce(from_node, new_channel.PassClientHandle()); - } -} - -void NodeController::OnIntroduce(const ports::NodeName& from_node, - const ports::NodeName& name, - ScopedPlatformHandle channel_handle) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - if (!channel_handle.is_valid()) { - node_->LostConnectionToNode(name); - - DVLOG(1) << "Could not be introduced to peer " << name; - base::AutoLock lock(peers_lock_); - pending_peer_messages_.erase(name); - return; - } - - scoped_refptr channel = - NodeChannel::Create(this, ConnectionParams(std::move(channel_handle)), - io_task_runner_, ProcessErrorCallback()); - - DVLOG(1) << "Adding new peer " << name << " via parent introduction."; - AddPeer(name, channel, true /* start_channel */); -} - -void NodeController::OnBroadcast(const ports::NodeName& from_node, - Channel::MessagePtr message) { - DCHECK(!message->has_handles()); - - void* data; - size_t num_data_bytes, num_header_bytes, num_payload_bytes, num_ports_bytes; - if (!ParsePortsMessage(message.get(), &data, &num_data_bytes, - &num_header_bytes, &num_payload_bytes, - &num_ports_bytes)) { - DropPeer(from_node, nullptr); - return; - } - - // Broadcast messages must not contain ports. - if (num_ports_bytes > 0) { - DropPeer(from_node, nullptr); - return; - } - - base::AutoLock lock(peers_lock_); - for (auto& iter : peers_) { - // Copy and send the message to each known peer. - Channel::MessagePtr peer_message( - new Channel::Message(message->payload_size(), 0)); - memcpy(peer_message->mutable_payload(), message->payload(), - message->payload_size()); - iter.second->PortsMessage(std::move(peer_message)); - } -} - -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) -void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, - base::ProcessHandle from_process, - const ports::NodeName& destination, - Channel::MessagePtr message) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - if (GetBrokerChannel()) { - // Only the broker should be asked to relay a message. - LOG(ERROR) << "Non-broker refusing to relay message."; - DropPeer(from_node, nullptr); - return; - } - - // The parent should always know which process this came from. - DCHECK(from_process != base::kNullProcessHandle); - -#if defined(OS_WIN) - // Rewrite the handles to this (the parent) process. If the message is - // destined for another child process, the handles will be rewritten to that - // process before going out (see NodeChannel::WriteChannelMessage). - // - // TODO: We could avoid double-duplication. - // - // Note that we explicitly mark the handles as being owned by the sending - // process before rewriting them, in order to accommodate RewriteHandles' - // internal sanity checks. - ScopedPlatformHandleVectorPtr handles = message->TakeHandles(); - for (size_t i = 0; i < handles->size(); ++i) - (*handles)[i].owning_process = from_process; - if (!Channel::Message::RewriteHandles(from_process, - base::GetCurrentProcessHandle(), - handles.get())) { - DLOG(ERROR) << "Failed to relay one or more handles."; - } - message->SetHandles(std::move(handles)); -#else - MachPortRelay* relay = GetMachPortRelay(); - if (!relay) { - LOG(ERROR) << "Receiving Mach ports without a port relay from " - << from_node << ". Dropping message."; - return; - } - if (!relay->ExtractPortRights(message.get(), from_process)) { - // NodeChannel should ensure that MachPortRelay is ready for the remote - // process. At this point, if the port extraction failed, either something - // went wrong in the mach stuff, or the remote process died. - LOG(ERROR) << "Error on receiving Mach ports " << from_node - << ". Dropping message."; - return; - } -#endif // defined(OS_WIN) - - if (destination == name_) { - // Great, we can deliver this message locally. - OnPortsMessage(from_node, std::move(message)); - return; - } - - scoped_refptr peer = GetPeerChannel(destination); - if (peer) - peer->PortsMessageFromRelay(from_node, std::move(message)); - else - DLOG(ERROR) << "Dropping relay message for unknown node " << destination; -} - -void NodeController::OnPortsMessageFromRelay(const ports::NodeName& from_node, - const ports::NodeName& source_node, - Channel::MessagePtr message) { - if (GetPeerChannel(from_node) != GetBrokerChannel()) { - LOG(ERROR) << "Refusing relayed message from non-broker node."; - DropPeer(from_node, nullptr); - return; - } - - OnPortsMessage(source_node, std::move(message)); -} -#endif - -void NodeController::OnAcceptPeer(const ports::NodeName& from_node, - const ports::NodeName& token, - const ports::NodeName& peer_name, - const ports::PortName& port_name) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - auto it = peer_connections_.find(from_node); - if (it == peer_connections_.end()) { - DLOG(ERROR) << "Received unexpected AcceptPeer message from " << from_node; - DropPeer(from_node, nullptr); - return; - } - - scoped_refptr channel = std::move(it->second.channel); - ports::PortRef local_port = it->second.local_port; - std::string peer_token = std::move(it->second.peer_token); - peer_connections_.erase(it); - DCHECK(channel); - - // If the peer connection is a self connection (which is used in tests), - // drop the channel to it and skip straight to merging the ports. - if (name_ == peer_name) { - peers_by_token_.erase(peer_token); - } else { - peers_by_token_[peer_token] = peer_name; - peer_connections_.insert( - {peer_name, PeerConnection{nullptr, local_port, peer_token}}); - DVLOG(1) << "Node " << name_ << " accepted peer " << peer_name; - - AddPeer(peer_name, channel, false /* start_channel */); - } - - // We need to choose one side to initiate the port merge. It doesn't matter - // who does it as long as they don't both try. Simple solution: pick the one - // with the "smaller" port name. - if (local_port.name() < port_name) { - node()->MergePorts(local_port, peer_name, port_name); - } -} - -void NodeController::OnChannelError(const ports::NodeName& from_node, - NodeChannel* channel) { - if (io_task_runner_->RunsTasksOnCurrentThread()) { - DropPeer(from_node, channel); - // DropPeer may have caused local port closures, so be sure to process any - // pending local messages. - AcceptIncomingMessages(); - } else { - io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&NodeController::OnChannelError, base::Unretained(this), - from_node, channel)); - } -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -MachPortRelay* NodeController::GetMachPortRelay() { - { - base::AutoLock lock(parent_lock_); - // Return null if we're not the root. - if (bootstrap_parent_channel_ || parent_name_ != ports::kInvalidNodeName) - return nullptr; - } - - base::AutoLock lock(mach_port_relay_lock_); - return mach_port_relay_.get(); -} -#endif - -void NodeController::CancelPendingPortMerges() { - std::vector ports_to_close; - - { - base::AutoLock lock(pending_port_merges_lock_); - reject_pending_merges_ = true; - for (const auto& port : pending_port_merges_) - ports_to_close.push_back(port.second); - pending_port_merges_.clear(); - } - - for (const auto& port : ports_to_close) - node_->ClosePort(port); -} - -void NodeController::DestroyOnIOThreadShutdown() { - destroy_on_io_thread_shutdown_ = true; -} - -void NodeController::AttemptShutdownIfRequested() { - if (!shutdown_callback_flag_) - return; - - base::Closure callback; - { - base::AutoLock lock(shutdown_lock_); - if (shutdown_callback_.is_null()) - return; - if (!node_->CanShutdownCleanly( - ports::Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)) { - DVLOG(2) << "Unable to cleanly shut down node " << name_; - return; - } - - callback = shutdown_callback_; - shutdown_callback_.Reset(); - shutdown_callback_flag_.Set(false); - } - - DCHECK(!callback.is_null()); - - callback.Run(); -} - -NodeController::PeerConnection::PeerConnection() = default; - -NodeController::PeerConnection::PeerConnection( - const PeerConnection& other) = default; - -NodeController::PeerConnection::PeerConnection( - PeerConnection&& other) = default; - -NodeController::PeerConnection::PeerConnection( - scoped_refptr channel, - const ports::PortRef& local_port, - const std::string& peer_token) - : channel(std::move(channel)), - local_port(local_port), - peer_token(peer_token) {} - -NodeController::PeerConnection::~PeerConnection() = default; - -NodeController::PeerConnection& NodeController::PeerConnection:: -operator=(const PeerConnection& other) = default; - -NodeController::PeerConnection& NodeController::PeerConnection:: -operator=(PeerConnection&& other) = default; - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/node_controller.h b/mojo/edk/system/node_controller.h deleted file mode 100644 index 46a2d61..0000000 --- a/mojo/edk/system/node_controller.h +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_NODE_CONTROLLER_H_ -#define MOJO_EDK_SYSTEM_NODE_CONTROLLER_H_ - -#include -#include -#include -#include -#include -#include - -#include "base/callback.h" -#include "base/containers/hash_tables.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/task_runner.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/atomic_flag.h" -#include "mojo/edk/system/node_channel.h" -#include "mojo/edk/system/ports/name.h" -#include "mojo/edk/system/ports/node.h" -#include "mojo/edk/system/ports/node_delegate.h" - -namespace base { -class PortProvider; -} - -namespace mojo { -namespace edk { - -class Broker; -class Core; -class MachPortRelay; -class PortsMessage; - -// The owner of ports::Node which facilitates core EDK implementation. All -// public interface methods are safe to call from any thread. -class NodeController : public ports::NodeDelegate, - public NodeChannel::Delegate { - public: - class PortObserver : public ports::UserData { - public: - virtual void OnPortStatusChanged() = 0; - - protected: - ~PortObserver() override {} - }; - - // |core| owns and out-lives us. - explicit NodeController(Core* core); - ~NodeController() override; - - const ports::NodeName& name() const { return name_; } - Core* core() const { return core_; } - ports::Node* node() const { return node_.get(); } - scoped_refptr io_task_runner() const { - return io_task_runner_; - } - -#if defined(OS_MACOSX) && !defined(OS_IOS) - // Create the relay used to transfer mach ports between processes. - void CreateMachPortRelay(base::PortProvider* port_provider); -#endif - - // Called exactly once, shortly after construction, and before any other - // methods are called on this object. - void SetIOTaskRunner(scoped_refptr io_task_runner); - - // Connects this node to a child node. This node will initiate a handshake. - void ConnectToChild(base::ProcessHandle process_handle, - ConnectionParams connection_params, - const std::string& child_token, - const ProcessErrorCallback& process_error_callback); - - // Closes all reserved ports which associated with the child process - // |child_token|. - void CloseChildPorts(const std::string& child_token); - - // Close a connection to a peer associated with |peer_token|. - void ClosePeerConnection(const std::string& peer_token); - - // Connects this node to a parent node. The parent node will initiate a - // handshake. - void ConnectToParent(ConnectionParams connection_params); - - // Connects this node to a peer node. On success, |port| will be merged with - // the corresponding port in the peer node. - void ConnectToPeer(ConnectionParams connection_params, - const ports::PortRef& port, - const std::string& peer_token); - - // Sets a port's observer. If |observer| is null the port's current observer - // is removed. - void SetPortObserver(const ports::PortRef& port, - scoped_refptr observer); - - // Closes a port. Use this in lieu of calling Node::ClosePort() directly, as - // it ensures the port's observer has also been removed. - void ClosePort(const ports::PortRef& port); - - // Sends a message on a port to its peer. - int SendMessage(const ports::PortRef& port_ref, - std::unique_ptr message); - - // Reserves a local port |port| associated with |token|. A peer holding a copy - // of |token| can merge one of its own ports into this one. - void ReservePort(const std::string& token, const ports::PortRef& port, - const std::string& child_token); - - // Merges a local port |port| into a port reserved by |token| in the parent. - void MergePortIntoParent(const std::string& token, - const ports::PortRef& port); - - // Merges two local ports together. - int MergeLocalPorts(const ports::PortRef& port0, const ports::PortRef& port1); - - // Creates a new shared buffer for use in the current process. - scoped_refptr CreateSharedBuffer(size_t num_bytes); - - // Request that the Node be shut down cleanly. This may take an arbitrarily - // long time to complete, at which point |callback| will be called. - // - // Note that while it is safe to continue using the NodeController's public - // interface after requesting shutdown, you do so at your own risk and there - // is NO guarantee that new messages will be sent or ports will complete - // transfer. - void RequestShutdown(const base::Closure& callback); - - // Notifies the NodeController that we received a bad message from the given - // node. - void NotifyBadMessageFrom(const ports::NodeName& source_node, - const std::string& error); - - private: - friend Core; - - using NodeMap = std::unordered_map>; - using OutgoingMessageQueue = std::queue; - - struct ReservedPort { - ports::PortRef port; - const std::string child_token; - }; - - struct PeerConnection { - PeerConnection(); - PeerConnection(const PeerConnection& other); - PeerConnection(PeerConnection&& other); - PeerConnection(scoped_refptr channel, - const ports::PortRef& local_port, - const std::string& peer_token); - ~PeerConnection(); - - PeerConnection& operator=(const PeerConnection& other); - PeerConnection& operator=(PeerConnection&& other); - - - scoped_refptr channel; - ports::PortRef local_port; - std::string peer_token; - }; - - void ConnectToChildOnIOThread( - base::ProcessHandle process_handle, - ConnectionParams connection_params, - ports::NodeName token, - const ProcessErrorCallback& process_error_callback); - void ConnectToParentOnIOThread(ConnectionParams connection_params); - - void ConnectToPeerOnIOThread(ConnectionParams connection_params, - ports::NodeName token, - ports::PortRef port, - const std::string& peer_token); - void ClosePeerConnectionOnIOThread(const std::string& node_name); - - scoped_refptr GetPeerChannel(const ports::NodeName& name); - scoped_refptr GetParentChannel(); - scoped_refptr GetBrokerChannel(); - - void AddPeer(const ports::NodeName& name, - scoped_refptr channel, - bool start_channel); - void DropPeer(const ports::NodeName& name, NodeChannel* channel); - void SendPeerMessage(const ports::NodeName& name, - ports::ScopedMessage message); - void AcceptIncomingMessages(); - void ProcessIncomingMessages(); - void DropAllPeers(); - - // ports::NodeDelegate: - void GenerateRandomPortName(ports::PortName* port_name) override; - void AllocMessage(size_t num_header_bytes, - ports::ScopedMessage* message) override; - void ForwardMessage(const ports::NodeName& node, - ports::ScopedMessage message) override; - void BroadcastMessage(ports::ScopedMessage message) override; - void PortStatusChanged(const ports::PortRef& port) override; - - // NodeChannel::Delegate: - void OnAcceptChild(const ports::NodeName& from_node, - const ports::NodeName& parent_name, - const ports::NodeName& token) override; - void OnAcceptParent(const ports::NodeName& from_node, - const ports::NodeName& token, - const ports::NodeName& child_name) override; - void OnAddBrokerClient(const ports::NodeName& from_node, - const ports::NodeName& client_name, - base::ProcessHandle process_handle) override; - void OnBrokerClientAdded(const ports::NodeName& from_node, - const ports::NodeName& client_name, - ScopedPlatformHandle broker_channel) override; - void OnAcceptBrokerClient(const ports::NodeName& from_node, - const ports::NodeName& broker_name, - ScopedPlatformHandle broker_channel) override; - void OnPortsMessage(const ports::NodeName& from_node, - Channel::MessagePtr message) override; - void OnRequestPortMerge(const ports::NodeName& from_node, - const ports::PortName& connector_port_name, - const std::string& token) override; - void OnRequestIntroduction(const ports::NodeName& from_node, - const ports::NodeName& name) override; - void OnIntroduce(const ports::NodeName& from_node, - const ports::NodeName& name, - ScopedPlatformHandle channel_handle) override; - void OnBroadcast(const ports::NodeName& from_node, - Channel::MessagePtr message) override; -#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) - void OnRelayPortsMessage(const ports::NodeName& from_node, - base::ProcessHandle from_process, - const ports::NodeName& destination, - Channel::MessagePtr message) override; - void OnPortsMessageFromRelay(const ports::NodeName& from_node, - const ports::NodeName& source_node, - Channel::MessagePtr message) override; -#endif - void OnAcceptPeer(const ports::NodeName& from_node, - const ports::NodeName& token, - const ports::NodeName& peer_name, - const ports::PortName& port_name) override; - void OnChannelError(const ports::NodeName& from_node, - NodeChannel* channel) override; -#if defined(OS_MACOSX) && !defined(OS_IOS) - MachPortRelay* GetMachPortRelay() override; -#endif - - // Cancels all pending port merges. These are merges which are supposed to - // be requested from the parent ASAP, and they may be cancelled if the - // connection to the parent is broken or never established. - void CancelPendingPortMerges(); - - // Marks this NodeController for destruction when the IO thread shuts down. - // This is used in case Core is torn down before the IO thread. Must only be - // called on the IO thread. - void DestroyOnIOThreadShutdown(); - - // If there is a registered shutdown callback (meaning shutdown has been - // requested, this checks the Node's status to see if clean shutdown is - // possible. If so, shutdown is performed and the shutdown callback is run. - void AttemptShutdownIfRequested(); - - // These are safe to access from any thread as long as the Node is alive. - Core* const core_; - const ports::NodeName name_; - const std::unique_ptr node_; - scoped_refptr io_task_runner_; - - // Guards |peers_| and |pending_peer_messages_|. - base::Lock peers_lock_; - - // Channels to known peers, including parent and children, if any. - NodeMap peers_; - - // Outgoing message queues for peers we've heard of but can't yet talk to. - std::unordered_map - pending_peer_messages_; - - // Guards |reserved_ports_| and |pending_child_tokens_|. - base::Lock reserved_ports_lock_; - - // Ports reserved by token. Key is the port token. - base::hash_map reserved_ports_; - // TODO(amistry): This _really_ needs to be a bimap. Unfortunately, we don't - // have one yet :( - std::unordered_map pending_child_tokens_; - - // Guards |pending_port_merges_| and |reject_pending_merges_|. - base::Lock pending_port_merges_lock_; - - // A set of port merge requests awaiting parent connection. - std::vector> pending_port_merges_; - - // Indicates that new merge requests should be rejected because the parent has - // disconnected. - bool reject_pending_merges_ = false; - - // Guards |parent_name_| and |bootstrap_parent_channel_|. - base::Lock parent_lock_; - - // The name of our parent node, if any. - ports::NodeName parent_name_; - - // A temporary reference to the parent channel before we know their name. - scoped_refptr bootstrap_parent_channel_; - - // Guards |broker_name_|, |pending_broker_clients_|, and - // |pending_relay_messages_|. - base::Lock broker_lock_; - - // The name of our broker node, if any. - ports::NodeName broker_name_; - - // A queue of pending child names waiting to be connected to a broker. - std::queue pending_broker_clients_; - - // Messages waiting to be relayed by the broker once it's known. - std::unordered_map - pending_relay_messages_; - - // Guards |incoming_messages_| and |incoming_messages_task_posted_|. - base::Lock messages_lock_; - std::queue incoming_messages_; - // Ensures that there is only one incoming messages task posted to the IO - // thread. - bool incoming_messages_task_posted_ = false; - // Flag to fast-path checking |incoming_messages_|. - AtomicFlag incoming_messages_flag_; - - // Guards |shutdown_callback_|. - base::Lock shutdown_lock_; - - // Set by RequestShutdown(). If this is non-null, the controller will - // begin polling the Node to see if clean shutdown is possible any time the - // Node's state is modified by the controller. - base::Closure shutdown_callback_; - // Flag to fast-path checking |shutdown_callback_|. - AtomicFlag shutdown_callback_flag_; - - // All other fields below must only be accessed on the I/O thread, i.e., the - // thread on which core_->io_task_runner() runs tasks. - - // Channels to children during handshake. - NodeMap pending_children_; - - using PeerNodeMap = - std::unordered_map; - PeerNodeMap peer_connections_; - - // Maps from peer token to node name, pending or not. - std::unordered_map peers_by_token_; - - // Indicates whether this object should delete itself on IO thread shutdown. - // Must only be accessed from the IO thread. - bool destroy_on_io_thread_shutdown_ = false; - -#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI) - // Broker for sync shared buffer creation in children. - std::unique_ptr broker_; -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) - base::Lock mach_port_relay_lock_; - // Relay for transferring mach ports to/from children. - std::unique_ptr mach_port_relay_; -#endif - - DISALLOW_COPY_AND_ASSIGN(NodeController); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_NODE_CONTROLLER_H_ diff --git a/mojo/edk/system/options_validation.h b/mojo/edk/system/options_validation.h deleted file mode 100644 index e1b337d..0000000 --- a/mojo/edk/system/options_validation.h +++ /dev/null @@ -1,97 +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. - -// Functions to help with verifying various |Mojo...Options| structs from the -// (public, C) API. These are "extensible" structs, which all have |struct_size| -// as their first member. All fields (other than |struct_size|) are optional, -// but any |flags| specified must be known to the system (otherwise, an error of -// |MOJO_RESULT_UNIMPLEMENTED| should be returned). - -#ifndef MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_ -#define MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_ - -#include -#include - -#include - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/types.h" - -namespace mojo { -namespace edk { - -template -class UserOptionsReader { - public: - // Constructor from a |const* Options| (which it checks -- this constructor - // has side effects!). - // Note: We initialize |options_reader_| without checking, since we do a check - // in |GetSizeForReader()|. - explicit UserOptionsReader(const Options* options) { - CHECK(options && IsAligned(options)); - options_ = GetSizeForReader(options) == 0 ? nullptr : options; - static_assert(offsetof(Options, struct_size) == 0, - "struct_size not first member of Options"); - // TODO(vtl): Enable when MSVC supports this (C++11 extended sizeof): - // static_assert(sizeof(Options::struct_size) == sizeof(uint32_t), - // "Options::struct_size not a uint32_t"); - // (Or maybe assert that its type is uint32_t?) - } - - bool is_valid() const { return !!options_; } - - const Options& options() const { - DCHECK(is_valid()); - return *options_; - } - - // Checks that the given (variable-size) |options| passed to the constructor - // (plausibly) has a member at the given offset with the given size. You - // probably want to use |OPTIONS_STRUCT_HAS_MEMBER()| instead. - bool HasMember(size_t offset, size_t size) const { - DCHECK(is_valid()); - // We assume that |offset| and |size| are reasonable, since they should come - // from |offsetof(Options, some_member)| and |sizeof(Options::some_member)|, - // respectively. - return options().struct_size >= offset + size; - } - - private: - static inline size_t GetSizeForReader(const Options* options) { - uint32_t struct_size = *reinterpret_cast(options); - if (struct_size < sizeof(uint32_t)) - return 0; - - return std::min(static_cast(struct_size), sizeof(Options)); - } - - template - static bool IsAligned(const void* pointer) { - return reinterpret_cast(pointer) % alignment == 0; - } - - const Options* options_; - - DISALLOW_COPY_AND_ASSIGN(UserOptionsReader); -}; - -// Macro to invoke |UserOptionsReader::HasMember()| parametrized by -// member name instead of offset and size. -// -// (We can't just give |HasMember()| a member pointer template argument instead, -// since there's no good/strictly-correct way to get an offset from that.) -// -// TODO(vtl): With C++11, use |sizeof(Options::member)| instead of (the -// contortion below). We might also be able to pull out the type |Options| from -// |reader| (using |decltype|) instead of requiring a parameter. -#define OPTIONS_STRUCT_HAS_MEMBER(Options, member, reader) \ - reader.HasMember(offsetof(Options, member), sizeof(reader.options().member)) - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_OPTIONS_VALIDATION_H_ diff --git a/mojo/edk/system/options_validation_unittest.cc b/mojo/edk/system/options_validation_unittest.cc deleted file mode 100644 index a01a92c..0000000 --- a/mojo/edk/system/options_validation_unittest.cc +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/options_validation.h" - -#include -#include - -#include "mojo/public/c/system/macros.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -// Declare a test options struct just as we do in actual public headers. - -using TestOptionsFlags = uint32_t; - -static_assert(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment"); -struct MOJO_ALIGNAS(8) TestOptions { - uint32_t struct_size; - TestOptionsFlags flags; - uint32_t member1; - uint32_t member2; -}; -static_assert(sizeof(TestOptions) == 16, "TestOptions has wrong size"); - -const uint32_t kSizeOfTestOptions = static_cast(sizeof(TestOptions)); - -TEST(OptionsValidationTest, Valid) { - { - const TestOptions kOptions = {kSizeOfTestOptions}; - UserOptionsReader reader(&kOptions); - EXPECT_TRUE(reader.is_valid()); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } - { - const TestOptions kOptions = {static_cast( - offsetof(TestOptions, struct_size) + sizeof(uint32_t))}; - UserOptionsReader reader(&kOptions); - EXPECT_TRUE(reader.is_valid()); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } - - { - const TestOptions kOptions = { - static_cast(offsetof(TestOptions, flags) + sizeof(uint32_t))}; - UserOptionsReader reader(&kOptions); - EXPECT_TRUE(reader.is_valid()); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } - { - MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {}; - TestOptions* options = reinterpret_cast(buf); - options->struct_size = kSizeOfTestOptions + 1; - UserOptionsReader reader(options); - EXPECT_TRUE(reader.is_valid()); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } - { - MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {}; - TestOptions* options = reinterpret_cast(buf); - options->struct_size = kSizeOfTestOptions + 4; - UserOptionsReader reader(options); - EXPECT_TRUE(reader.is_valid()); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); - EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); - } -} - -TEST(OptionsValidationTest, Invalid) { - // Size too small: - for (size_t i = 0; i < sizeof(uint32_t); i++) { - TestOptions options = {static_cast(i)}; - UserOptionsReader reader(&options); - EXPECT_FALSE(reader.is_valid()) << i; - } -} - -// These test invalid arguments that should cause death if we're being paranoid -// about checking arguments (which we would want to do if, e.g., we were in a -// true "kernel" situation, but we might not want to do otherwise for -// performance reasons). Probably blatant errors like passing in null pointers -// (for required pointer arguments) will still cause death, but perhaps not -// predictably. -TEST(OptionsValidationTest, InvalidDeath) { -#if defined(OFFICIAL_BUILD) - const char kMemoryCheckFailedRegex[] = ""; -#else - const char kMemoryCheckFailedRegex[] = "Check failed"; -#endif - - // Null: - EXPECT_DEATH_IF_SUPPORTED( - { UserOptionsReader reader((nullptr)); }, - kMemoryCheckFailedRegex); - - // Unaligned: - EXPECT_DEATH_IF_SUPPORTED( - { - UserOptionsReader reader( - reinterpret_cast(1)); - }, - kMemoryCheckFailedRegex); - // Note: The current implementation checks the size only after checking the - // alignment versus that required for the |uint32_t| size, so it won't die in - // the expected way if you pass, e.g., 4. So we have to manufacture a valid - // pointer at an offset of alignment 4. - EXPECT_DEATH_IF_SUPPORTED( - { - uint32_t buffer[100] = {}; - TestOptions* options = (reinterpret_cast(buffer) % 8 == 0) - ? reinterpret_cast(&buffer[1]) - : reinterpret_cast(&buffer[0]); - options->struct_size = static_cast(sizeof(TestOptions)); - UserOptionsReader reader(options); - }, - kMemoryCheckFailedRegex); -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/platform_handle_dispatcher.cc b/mojo/edk/system/platform_handle_dispatcher.cc deleted file mode 100644 index 3e708c2..0000000 --- a/mojo/edk/system/platform_handle_dispatcher.cc +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/platform_handle_dispatcher.h" - -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/platform_handle_vector.h" - -namespace mojo { -namespace edk { - -// static -scoped_refptr PlatformHandleDispatcher::Create( - ScopedPlatformHandle platform_handle) { - return new PlatformHandleDispatcher(std::move(platform_handle)); -} - -ScopedPlatformHandle PlatformHandleDispatcher::PassPlatformHandle() { - return std::move(platform_handle_); -} - -Dispatcher::Type PlatformHandleDispatcher::GetType() const { - return Type::PLATFORM_HANDLE; -} - -MojoResult PlatformHandleDispatcher::Close() { - base::AutoLock lock(lock_); - if (is_closed_ || in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - is_closed_ = true; - platform_handle_.reset(); - return MOJO_RESULT_OK; -} - -void PlatformHandleDispatcher::StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_handles) { - *num_bytes = 0; - *num_ports = 0; - *num_handles = 1; -} - -bool PlatformHandleDispatcher::EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) { - base::AutoLock lock(lock_); - if (is_closed_) - return false; - handles[0] = platform_handle_.get(); - return true; -} - -bool PlatformHandleDispatcher::BeginTransit() { - base::AutoLock lock(lock_); - if (in_transit_) - return false; - in_transit_ = !is_closed_; - return in_transit_; -} - -void PlatformHandleDispatcher::CompleteTransitAndClose() { - base::AutoLock lock(lock_); - - in_transit_ = false; - is_closed_ = true; - - // The system has taken ownership of our handle. - ignore_result(platform_handle_.release()); -} - -void PlatformHandleDispatcher::CancelTransit() { - base::AutoLock lock(lock_); - in_transit_ = false; -} - -// static -scoped_refptr PlatformHandleDispatcher::Deserialize( - const void* bytes, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* handles, - size_t num_handles) { - if (num_bytes || num_ports || num_handles != 1) - return nullptr; - - PlatformHandle handle; - std::swap(handle, handles[0]); - - return PlatformHandleDispatcher::Create(ScopedPlatformHandle(handle)); -} - -PlatformHandleDispatcher::PlatformHandleDispatcher( - ScopedPlatformHandle platform_handle) - : platform_handle_(std::move(platform_handle)) {} - -PlatformHandleDispatcher::~PlatformHandleDispatcher() { - DCHECK(is_closed_ && !in_transit_); - DCHECK(!platform_handle_.is_valid()); -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/platform_handle_dispatcher.h b/mojo/edk/system/platform_handle_dispatcher.h deleted file mode 100644 index a36c7a0..0000000 --- a/mojo/edk/system/platform_handle_dispatcher.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_ -#define MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { -namespace edk { - -class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher { - public: - static scoped_refptr Create( - ScopedPlatformHandle platform_handle); - - ScopedPlatformHandle PassPlatformHandle(); - - // Dispatcher: - Type GetType() const override; - MojoResult Close() override; - void StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_handles) override; - bool EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) override; - bool BeginTransit() override; - void CompleteTransitAndClose() override; - void CancelTransit() override; - - static scoped_refptr Deserialize( - const void* bytes, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* handles, - size_t num_handles); - - private: - PlatformHandleDispatcher(ScopedPlatformHandle platform_handle); - ~PlatformHandleDispatcher() override; - - base::Lock lock_; - bool in_transit_ = false; - bool is_closed_ = false; - ScopedPlatformHandle platform_handle_; - - DISALLOW_COPY_AND_ASSIGN(PlatformHandleDispatcher); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_ diff --git a/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/mojo/edk/system/platform_handle_dispatcher_unittest.cc deleted file mode 100644 index 7a94262..0000000 --- a/mojo/edk/system/platform_handle_dispatcher_unittest.cc +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/platform_handle_dispatcher.h" - -#include -#include - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/ref_counted.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/test/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -TEST(PlatformHandleDispatcherTest, Basic) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - static const char kHelloWorld[] = "hello world"; - - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused)); - ASSERT_TRUE(fp); - EXPECT_EQ(sizeof(kHelloWorld), - fwrite(kHelloWorld, 1, sizeof(kHelloWorld), fp.get())); - - ScopedPlatformHandle h(test::PlatformHandleFromFILE(std::move(fp))); - EXPECT_FALSE(fp); - ASSERT_TRUE(h.is_valid()); - - scoped_refptr dispatcher = - PlatformHandleDispatcher::Create(std::move(h)); - EXPECT_FALSE(h.is_valid()); - EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, dispatcher->GetType()); - - h = dispatcher->PassPlatformHandle(); - EXPECT_TRUE(h.is_valid()); - - fp = test::FILEFromPlatformHandle(std::move(h), "rb"); - EXPECT_FALSE(h.is_valid()); - EXPECT_TRUE(fp); - - rewind(fp.get()); - char read_buffer[1000] = {}; - EXPECT_EQ(sizeof(kHelloWorld), - fread(read_buffer, 1, sizeof(read_buffer), fp.get())); - EXPECT_STREQ(kHelloWorld, read_buffer); - - // Try getting the handle again. (It should fail cleanly.) - h = dispatcher->PassPlatformHandle(); - EXPECT_FALSE(h.is_valid()); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); -} - -TEST(PlatformHandleDispatcherTest, Serialization) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - - static const char kFooBar[] = "foo bar"; - - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused)); - EXPECT_EQ(sizeof(kFooBar), fwrite(kFooBar, 1, sizeof(kFooBar), fp.get())); - - scoped_refptr dispatcher = - PlatformHandleDispatcher::Create( - test::PlatformHandleFromFILE(std::move(fp))); - - uint32_t num_bytes = 0; - uint32_t num_ports = 0; - uint32_t num_handles = 0; - EXPECT_TRUE(dispatcher->BeginTransit()); - dispatcher->StartSerialize(&num_bytes, &num_ports, &num_handles); - - EXPECT_EQ(0u, num_bytes); - EXPECT_EQ(0u, num_ports); - EXPECT_EQ(1u, num_handles); - - ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector(1)); - EXPECT_TRUE(dispatcher->EndSerialize(nullptr, nullptr, handles->data())); - dispatcher->CompleteTransitAndClose(); - - EXPECT_TRUE(handles->at(0).is_valid()); - - ScopedPlatformHandle handle = dispatcher->PassPlatformHandle(); - EXPECT_FALSE(handle.is_valid()); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher->Close()); - - dispatcher = static_cast( - Dispatcher::Deserialize(Dispatcher::Type::PLATFORM_HANDLE, nullptr, - num_bytes, nullptr, num_ports, handles->data(), - 1).get()); - - EXPECT_FALSE(handles->at(0).is_valid()); - EXPECT_TRUE(dispatcher->GetType() == Dispatcher::Type::PLATFORM_HANDLE); - - fp = test::FILEFromPlatformHandle(dispatcher->PassPlatformHandle(), "rb"); - EXPECT_TRUE(fp); - - rewind(fp.get()); - char read_buffer[1000] = {}; - EXPECT_EQ(sizeof(kFooBar), - fread(read_buffer, 1, sizeof(read_buffer), fp.get())); - EXPECT_STREQ(kFooBar, read_buffer); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/platform_wrapper_unittest.cc b/mojo/edk/system/platform_wrapper_unittest.cc deleted file mode 100644 index f29d62b..0000000 --- a/mojo/edk/system/platform_wrapper_unittest.cc +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include - -#include -#include -#include - -#include "base/files/file.h" -#include "base/files/file_util.h" -#include "base/memory/shared_memory.h" -#include "base/process/process_handle.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/public/c/system/platform_handle.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#include -#endif - -#if defined(OS_POSIX) -#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR -#elif defined(OS_WIN) -#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT -#else -#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE SIMPLE_PLATFORM_HANDLE_TYPE -#endif - -uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) { -#if defined(OS_WIN) - return reinterpret_cast(file); -#else - return static_cast(file); -#endif -} - -base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) { -#if defined(OS_WIN) - return reinterpret_cast(value); -#else - return static_cast(value); -#endif -} - -namespace mojo { -namespace edk { -namespace { - -using PlatformWrapperTest = test::MojoTestBase; - -TEST_F(PlatformWrapperTest, WrapPlatformHandle) { - // Create a temporary file and write a message to it. - base::FilePath temp_file_path; - ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path)); - const std::string kMessage = "Hello, world!"; - EXPECT_EQ(base::WriteFile(temp_file_path, kMessage.data(), - static_cast(kMessage.size())), - static_cast(kMessage.size())); - - RUN_CHILD_ON_PIPE(ReadPlatformFile, h) - // Open the temporary file for reading, wrap its handle, and send it to - // the child along with the expected message to be read. - base::File file(temp_file_path, - base::File::FLAG_OPEN | base::File::FLAG_READ); - EXPECT_TRUE(file.IsValid()); - - MojoHandle wrapped_handle; - MojoPlatformHandle os_file; - os_file.struct_size = sizeof(MojoPlatformHandle); - os_file.type = SIMPLE_PLATFORM_HANDLE_TYPE; - os_file.value = - PlatformHandleValueFromPlatformFile(file.TakePlatformFile()); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWrapPlatformHandle(&os_file, &wrapped_handle)); - - WriteMessageWithHandles(h, kMessage, &wrapped_handle, 1); - END_CHILD() - - base::DeleteFile(temp_file_path, false); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadPlatformFile, PlatformWrapperTest, h) { - // Read a message and a wrapped file handle; unwrap the handle. - MojoHandle wrapped_handle; - std::string message = ReadMessageWithHandles(h, &wrapped_handle, 1); - - MojoPlatformHandle platform_handle; - platform_handle.struct_size = sizeof(MojoPlatformHandle); - ASSERT_EQ(MOJO_RESULT_OK, - MojoUnwrapPlatformHandle(wrapped_handle, &platform_handle)); - EXPECT_EQ(SIMPLE_PLATFORM_HANDLE_TYPE, platform_handle.type); - base::File file(PlatformFileFromPlatformHandleValue(platform_handle.value)); - - // Expect to read the same message from the file. - std::vector data(message.size()); - EXPECT_EQ(file.ReadAtCurrentPos(data.data(), static_cast(data.size())), - static_cast(data.size())); - EXPECT_TRUE(std::equal(message.begin(), message.end(), data.begin())); -} - -TEST_F(PlatformWrapperTest, WrapPlatformSharedBufferHandle) { - // Allocate a new platform shared buffer and write a message into it. - const std::string kMessage = "Hello, world!"; - base::SharedMemory buffer; - buffer.CreateAndMapAnonymous(kMessage.size()); - CHECK(buffer.memory()); - memcpy(buffer.memory(), kMessage.data(), kMessage.size()); - - RUN_CHILD_ON_PIPE(ReadPlatformSharedBuffer, h) - // Wrap the shared memory handle and send it to the child along with the - // expected message. - base::SharedMemoryHandle memory_handle = - base::SharedMemory::DuplicateHandle(buffer.handle()); - MojoPlatformHandle os_buffer; - os_buffer.struct_size = sizeof(MojoPlatformHandle); - os_buffer.type = SHARED_BUFFER_PLATFORM_HANDLE_TYPE; -#if defined(OS_MACOSX) && !defined(OS_IOS) - os_buffer.value = static_cast(memory_handle.GetMemoryObject()); -#elif defined(OS_POSIX) - os_buffer.value = static_cast(memory_handle.fd); -#elif defined(OS_WIN) - os_buffer.value = reinterpret_cast(memory_handle.GetHandle()); -#endif - - MojoHandle wrapped_handle; - ASSERT_EQ(MOJO_RESULT_OK, - MojoWrapPlatformSharedBufferHandle( - &os_buffer, kMessage.size(), - MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE, - &wrapped_handle)); - WriteMessageWithHandles(h, kMessage, &wrapped_handle, 1); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadPlatformSharedBuffer, PlatformWrapperTest, - h) { - // Read a message and a wrapped shared buffer handle. - MojoHandle wrapped_handle; - std::string message = ReadMessageWithHandles(h, &wrapped_handle, 1); - - // Check the message in the buffer - ExpectBufferContents(wrapped_handle, 0, message); - - // Now unwrap the buffer and verify that the base::SharedMemoryHandle also - // works as expected. - MojoPlatformHandle os_buffer; - os_buffer.struct_size = sizeof(MojoPlatformHandle); - size_t size; - MojoPlatformSharedBufferHandleFlags flags; - ASSERT_EQ(MOJO_RESULT_OK, - MojoUnwrapPlatformSharedBufferHandle(wrapped_handle, &os_buffer, - &size, &flags)); - bool read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE; - EXPECT_FALSE(read_only); - -#if defined(OS_MACOSX) && !defined(OS_IOS) - ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT, os_buffer.type); - base::SharedMemoryHandle memory_handle( - static_cast(os_buffer.value), size, - base::GetCurrentProcId()); -#elif defined(OS_POSIX) - ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR, os_buffer.type); - base::SharedMemoryHandle memory_handle(static_cast(os_buffer.value), - false); -#elif defined(OS_WIN) - ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE, os_buffer.type); - base::SharedMemoryHandle memory_handle( - reinterpret_cast(os_buffer.value), base::GetCurrentProcId()); -#endif - - base::SharedMemory memory(memory_handle, read_only); - memory.Map(message.size()); - ASSERT_TRUE(memory.memory()); - - EXPECT_TRUE(std::equal(message.begin(), message.end(), - static_cast(memory.memory()))); -} - -TEST_F(PlatformWrapperTest, InvalidHandle) { - // Wrap an invalid platform handle and expect to unwrap the same. - - MojoHandle wrapped_handle; - MojoPlatformHandle invalid_handle; - invalid_handle.struct_size = sizeof(MojoPlatformHandle); - invalid_handle.type = MOJO_PLATFORM_HANDLE_TYPE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, - MojoWrapPlatformHandle(&invalid_handle, &wrapped_handle)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoUnwrapPlatformHandle(wrapped_handle, &invalid_handle)); - EXPECT_EQ(MOJO_PLATFORM_HANDLE_TYPE_INVALID, invalid_handle.type); -} - -TEST_F(PlatformWrapperTest, InvalidArgument) { - // Try to wrap an invalid MojoPlatformHandle struct and expect an error. - MojoHandle wrapped_handle; - MojoPlatformHandle platform_handle; - platform_handle.struct_size = 0; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWrapPlatformHandle(&platform_handle, &wrapped_handle)); -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/BUILD.gn b/mojo/edk/system/ports/BUILD.gn deleted file mode 100644 index 5c82761..0000000 --- a/mojo/edk/system/ports/BUILD.gn +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//testing/test.gni") - -source_set("ports") { - sources = [ - "event.cc", - "event.h", - "message.cc", - "message.h", - "message_filter.h", - "message_queue.cc", - "message_queue.h", - "name.cc", - "name.h", - "node.cc", - "node.h", - "node_delegate.h", - "port.cc", - "port.h", - "port_ref.cc", - "port_ref.h", - "user_data.h", - ] - - public_deps = [ - "//base", - ] -} - -source_set("tests") { - testonly = true - - sources = [ - "ports_unittest.cc", - ] - - deps = [ - ":ports", - "//base", - "//base/test:test_support", - "//testing/gtest", - ] -} diff --git a/mojo/edk/system/ports/event.cc b/mojo/edk/system/ports/event.cc deleted file mode 100644 index 2e22086..0000000 --- a/mojo/edk/system/ports/event.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/ports/event.h" - -#include - -namespace mojo { -namespace edk { -namespace ports { - -namespace { - -const size_t kPortsMessageAlignment = 8; - -static_assert(sizeof(PortDescriptor) % kPortsMessageAlignment == 0, - "Invalid PortDescriptor size."); - -static_assert(sizeof(EventHeader) % kPortsMessageAlignment == 0, - "Invalid EventHeader size."); - -static_assert(sizeof(UserEventData) % kPortsMessageAlignment == 0, - "Invalid UserEventData size."); - -static_assert(sizeof(ObserveProxyEventData) % kPortsMessageAlignment == 0, - "Invalid ObserveProxyEventData size."); - -static_assert(sizeof(ObserveProxyAckEventData) % kPortsMessageAlignment == 0, - "Invalid ObserveProxyAckEventData size."); - -static_assert(sizeof(ObserveClosureEventData) % kPortsMessageAlignment == 0, - "Invalid ObserveClosureEventData size."); - -static_assert(sizeof(MergePortEventData) % kPortsMessageAlignment == 0, - "Invalid MergePortEventData size."); - -} // namespace - -PortDescriptor::PortDescriptor() { - memset(padding, 0, sizeof(padding)); -} - -} // namespace ports -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/event.h b/mojo/edk/system/ports/event.h deleted file mode 100644 index a66dfc1..0000000 --- a/mojo/edk/system/ports/event.h +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_EVENT_H_ -#define MOJO_EDK_SYSTEM_PORTS_EVENT_H_ - -#include - -#include "mojo/edk/system/ports/message.h" -#include "mojo/edk/system/ports/name.h" - -namespace mojo { -namespace edk { -namespace ports { - -#pragma pack(push, 1) - -// TODO: Add static assertions of alignment. - -struct PortDescriptor { - PortDescriptor(); - - NodeName peer_node_name; - PortName peer_port_name; - NodeName referring_node_name; - PortName referring_port_name; - uint64_t next_sequence_num_to_send; - uint64_t next_sequence_num_to_receive; - uint64_t last_sequence_num_to_receive; - bool peer_closed; - char padding[7]; -}; - -enum struct EventType : uint32_t { - kUser, - kPortAccepted, - kObserveProxy, - kObserveProxyAck, - kObserveClosure, - kMergePort, -}; - -struct EventHeader { - EventType type; - uint32_t padding; - PortName port_name; -}; - -struct UserEventData { - uint64_t sequence_num; - uint32_t num_ports; - uint32_t padding; -}; - -struct ObserveProxyEventData { - NodeName proxy_node_name; - PortName proxy_port_name; - NodeName proxy_to_node_name; - PortName proxy_to_port_name; -}; - -struct ObserveProxyAckEventData { - uint64_t last_sequence_num; -}; - -struct ObserveClosureEventData { - uint64_t last_sequence_num; -}; - -struct MergePortEventData { - PortName new_port_name; - PortDescriptor new_port_descriptor; -}; - -#pragma pack(pop) - -inline const EventHeader* GetEventHeader(const Message& message) { - return static_cast(message.header_bytes()); -} - -inline EventHeader* GetMutableEventHeader(Message* message) { - return static_cast(message->mutable_header_bytes()); -} - -template -inline const EventData* GetEventData(const Message& message) { - return reinterpret_cast( - reinterpret_cast(GetEventHeader(message) + 1)); -} - -template -inline EventData* GetMutableEventData(Message* message) { - return reinterpret_cast( - reinterpret_cast(GetMutableEventHeader(message) + 1)); -} - -inline const PortDescriptor* GetPortDescriptors(const UserEventData* event) { - return reinterpret_cast( - reinterpret_cast(event + 1)); -} - -inline PortDescriptor* GetMutablePortDescriptors(UserEventData* event) { - return reinterpret_cast(reinterpret_cast(event + 1)); -} - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_EVENT_H_ diff --git a/mojo/edk/system/ports/message.cc b/mojo/edk/system/ports/message.cc deleted file mode 100644 index 5d3c000..0000000 --- a/mojo/edk/system/ports/message.cc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include - -#include "base/logging.h" -#include "mojo/edk/system/ports/event.h" - -namespace mojo { -namespace edk { -namespace ports { - -// static -bool Message::Parse(const void* bytes, - size_t num_bytes, - size_t* num_header_bytes, - size_t* num_payload_bytes, - size_t* num_ports_bytes) { - if (num_bytes < sizeof(EventHeader)) - return false; - const EventHeader* header = static_cast(bytes); - switch (header->type) { - case EventType::kUser: - // See below. - break; - case EventType::kPortAccepted: - *num_header_bytes = sizeof(EventHeader); - break; - case EventType::kObserveProxy: - *num_header_bytes = sizeof(EventHeader) + sizeof(ObserveProxyEventData); - break; - case EventType::kObserveProxyAck: - *num_header_bytes = - sizeof(EventHeader) + sizeof(ObserveProxyAckEventData); - break; - case EventType::kObserveClosure: - *num_header_bytes = sizeof(EventHeader) + sizeof(ObserveClosureEventData); - break; - case EventType::kMergePort: - *num_header_bytes = sizeof(EventHeader) + sizeof(MergePortEventData); - break; - default: - return false; - } - - if (header->type == EventType::kUser) { - if (num_bytes < sizeof(EventHeader) + sizeof(UserEventData)) - return false; - const UserEventData* event_data = - reinterpret_cast( - reinterpret_cast(header + 1)); - if (event_data->num_ports > std::numeric_limits::max()) - return false; - *num_header_bytes = sizeof(EventHeader) + - sizeof(UserEventData) + - event_data->num_ports * sizeof(PortDescriptor); - *num_ports_bytes = event_data->num_ports * sizeof(PortName); - if (num_bytes < *num_header_bytes + *num_ports_bytes) - return false; - *num_payload_bytes = num_bytes - *num_header_bytes - *num_ports_bytes; - } else { - if (*num_header_bytes != num_bytes) - return false; - *num_payload_bytes = 0; - *num_ports_bytes = 0; - } - - return true; -} - -Message::Message(size_t num_payload_bytes, size_t num_ports) - : Message(sizeof(EventHeader) + sizeof(UserEventData) + - num_ports * sizeof(PortDescriptor), - num_payload_bytes, num_ports * sizeof(PortName)) { - num_ports_ = num_ports; -} - -Message::Message(size_t num_header_bytes, - size_t num_payload_bytes, - size_t num_ports_bytes) - : start_(nullptr), - num_header_bytes_(num_header_bytes), - num_ports_bytes_(num_ports_bytes), - num_payload_bytes_(num_payload_bytes) { -} - -void Message::InitializeUserMessageHeader(void* start) { - start_ = static_cast(start); - memset(start_, 0, num_header_bytes_); - GetMutableEventHeader(this)->type = EventType::kUser; - GetMutableEventData(this)->num_ports = - static_cast(num_ports_); -} - -} // namespace ports -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/message.h b/mojo/edk/system/ports/message.h deleted file mode 100644 index 95fa046..0000000 --- a/mojo/edk/system/ports/message.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_MESSAGE_H_ -#define MOJO_EDK_SYSTEM_PORTS_MESSAGE_H_ - -#include - -#include - -#include "mojo/edk/system/ports/name.h" - -namespace mojo { -namespace edk { -namespace ports { - -// A message consists of a header (array of bytes), payload (array of bytes) -// and an array of ports. The header is used by the Node implementation. -// -// This class is designed to be subclassed, and the subclass is responsible for -// providing the underlying storage. The header size will be aligned, and it -// should be followed in memory by the array of ports and finally the payload. -// -// NOTE: This class does not manage the lifetime of the ports it references. -class Message { - public: - virtual ~Message() {} - - // Inspect the message at |bytes| and return the size of each section. Returns - // |false| if the message is malformed and |true| otherwise. - static bool Parse(const void* bytes, - size_t num_bytes, - size_t* num_header_bytes, - size_t* num_payload_bytes, - size_t* num_ports_bytes); - - void* mutable_header_bytes() { return start_; } - const void* header_bytes() const { return start_; } - size_t num_header_bytes() const { return num_header_bytes_; } - - void* mutable_payload_bytes() { - return start_ + num_header_bytes_ + num_ports_bytes_; - } - const void* payload_bytes() const { - return const_cast(this)->mutable_payload_bytes(); - } - size_t num_payload_bytes() const { return num_payload_bytes_; } - - PortName* mutable_ports() { - return reinterpret_cast(start_ + num_header_bytes_); - } - const PortName* ports() const { - return const_cast(this)->mutable_ports(); - } - size_t num_ports_bytes() const { return num_ports_bytes_; } - size_t num_ports() const { return num_ports_bytes_ / sizeof(PortName); } - - protected: - // Constructs a new Message base for a user message. - // - // Note: You MUST call InitializeUserMessageHeader() before this Message is - // ready for transmission. - Message(size_t num_payload_bytes, size_t num_ports); - - // Constructs a new Message base for an internal message. Do NOT call - // InitializeUserMessageHeader() when using this constructor. - Message(size_t num_header_bytes, - size_t num_payload_bytes, - size_t num_ports_bytes); - - Message(const Message& other) = delete; - void operator=(const Message& other) = delete; - - // Initializes the header in a newly allocated message buffer to carry a - // user message. - void InitializeUserMessageHeader(void* start); - - // Note: storage is [header][ports][payload]. - char* start_ = nullptr; - size_t num_ports_ = 0; - size_t num_header_bytes_ = 0; - size_t num_ports_bytes_ = 0; - size_t num_payload_bytes_ = 0; -}; - -using ScopedMessage = std::unique_ptr; - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_MESSAGE_H_ diff --git a/mojo/edk/system/ports/message_filter.h b/mojo/edk/system/ports/message_filter.h deleted file mode 100644 index bf8fa21..0000000 --- a/mojo/edk/system/ports/message_filter.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_MESSAGE_FILTER_H_ -#define MOJO_EDK_SYSTEM_PORTS_MESSAGE_FILTER_H_ - -namespace mojo { -namespace edk { -namespace ports { - -class Message; - -// An interface which can be implemented to filter port messages according to -// arbitrary policy. -class MessageFilter { - public: - virtual ~MessageFilter() {} - - // Returns true of |message| should be accepted by whomever is applying this - // filter. See MessageQueue::GetNextMessage(), for example. - virtual bool Match(const Message& message) = 0; -}; - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_MESSAGE_FILTER_H_ diff --git a/mojo/edk/system/ports/message_queue.cc b/mojo/edk/system/ports/message_queue.cc deleted file mode 100644 index defb1b6..0000000 --- a/mojo/edk/system/ports/message_queue.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/ports/message_queue.h" - -#include - -#include "base/logging.h" -#include "mojo/edk/system/ports/event.h" -#include "mojo/edk/system/ports/message_filter.h" - -namespace mojo { -namespace edk { -namespace ports { - -inline uint64_t GetSequenceNum(const ScopedMessage& message) { - return GetEventData(*message)->sequence_num; -} - -// Used by std::{push,pop}_heap functions -inline bool operator<(const ScopedMessage& a, const ScopedMessage& b) { - return GetSequenceNum(a) > GetSequenceNum(b); -} - -MessageQueue::MessageQueue() : MessageQueue(kInitialSequenceNum) {} - -MessageQueue::MessageQueue(uint64_t next_sequence_num) - : next_sequence_num_(next_sequence_num) { - // The message queue is blocked waiting for a message with sequence number - // equal to |next_sequence_num|. -} - -MessageQueue::~MessageQueue() { -#if DCHECK_IS_ON() - size_t num_leaked_ports = 0; - for (const auto& message : heap_) - num_leaked_ports += message->num_ports(); - DVLOG_IF(1, num_leaked_ports > 0) - << "Leaking " << num_leaked_ports << " ports in unreceived messages"; -#endif -} - -bool MessageQueue::HasNextMessage() const { - return !heap_.empty() && GetSequenceNum(heap_[0]) == next_sequence_num_; -} - -void MessageQueue::GetNextMessage(ScopedMessage* message, - MessageFilter* filter) { - if (!HasNextMessage() || (filter && !filter->Match(*heap_[0].get()))) { - message->reset(); - return; - } - - std::pop_heap(heap_.begin(), heap_.end()); - *message = std::move(heap_.back()); - heap_.pop_back(); - - next_sequence_num_++; -} - -void MessageQueue::AcceptMessage(ScopedMessage message, - bool* has_next_message) { - DCHECK(GetEventHeader(*message)->type == EventType::kUser); - - // TODO: Handle sequence number roll-over. - - heap_.emplace_back(std::move(message)); - std::push_heap(heap_.begin(), heap_.end()); - - if (!signalable_) { - *has_next_message = false; - } else { - *has_next_message = (GetSequenceNum(heap_[0]) == next_sequence_num_); - } -} - -void MessageQueue::GetReferencedPorts(std::deque* port_names) { - for (const auto& message : heap_) { - for (size_t i = 0; i < message->num_ports(); ++i) - port_names->push_back(message->ports()[i]); - } -} - -} // namespace ports -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/message_queue.h b/mojo/edk/system/ports/message_queue.h deleted file mode 100644 index d9a47ed..0000000 --- a/mojo/edk/system/ports/message_queue.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_MESSAGE_QUEUE_H_ -#define MOJO_EDK_SYSTEM_PORTS_MESSAGE_QUEUE_H_ - -#include - -#include -#include -#include -#include - -#include "base/macros.h" -#include "mojo/edk/system/ports/message.h" - -namespace mojo { -namespace edk { -namespace ports { - -const uint64_t kInitialSequenceNum = 1; -const uint64_t kInvalidSequenceNum = std::numeric_limits::max(); - -class MessageFilter; - -// An incoming message queue for a port. MessageQueue keeps track of the highest -// known sequence number and can indicate whether the next sequential message is -// available. Thus the queue enforces message ordering for the consumer without -// enforcing it for the producer (see AcceptMessage() below.) -class MessageQueue { - public: - explicit MessageQueue(); - explicit MessageQueue(uint64_t next_sequence_num); - ~MessageQueue(); - - void set_signalable(bool value) { signalable_ = value; } - - uint64_t next_sequence_num() const { return next_sequence_num_; } - - bool HasNextMessage() const; - - // Gives ownership of the message. If |filter| is non-null, the next message - // will only be retrieved if the filter successfully matches it. - void GetNextMessage(ScopedMessage* message, MessageFilter* filter); - - // Takes ownership of the message. Note: Messages are ordered, so while we - // have added a message to the queue, we may still be waiting on a message - // ahead of this one before we can let any of the messages be returned by - // GetNextMessage. - // - // Furthermore, once has_next_message is set to true, it will remain false - // until GetNextMessage is called enough times to return a null message. - // In other words, has_next_message acts like an edge trigger. - // - void AcceptMessage(ScopedMessage message, bool* has_next_message); - - // Returns all of the ports referenced by messages in this message queue. - void GetReferencedPorts(std::deque* ports); - - private: - std::vector heap_; - uint64_t next_sequence_num_; - bool signalable_ = true; - - DISALLOW_COPY_AND_ASSIGN(MessageQueue); -}; - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_MESSAGE_QUEUE_H_ diff --git a/mojo/edk/system/ports/name.cc b/mojo/edk/system/ports/name.cc deleted file mode 100644 index ea17698..0000000 --- a/mojo/edk/system/ports/name.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/ports/name.h" - -namespace mojo { -namespace edk { -namespace ports { - -extern const PortName kInvalidPortName = {0, 0}; - -extern const NodeName kInvalidNodeName = {0, 0}; - -std::ostream& operator<<(std::ostream& stream, const Name& name) { - std::ios::fmtflags flags(stream.flags()); - stream << std::hex << std::uppercase << name.v1; - if (name.v2 != 0) - stream << '.' << name.v2; - stream.flags(flags); - return stream; -} - -} // namespace ports -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/name.h b/mojo/edk/system/ports/name.h deleted file mode 100644 index 72e41b9..0000000 --- a/mojo/edk/system/ports/name.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_NAME_H_ -#define MOJO_EDK_SYSTEM_PORTS_NAME_H_ - -#include - -#include -#include - -#include "base/hash.h" - -namespace mojo { -namespace edk { -namespace ports { - -struct Name { - Name(uint64_t v1, uint64_t v2) : v1(v1), v2(v2) {} - uint64_t v1, v2; -}; - -inline bool operator==(const Name& a, const Name& b) { - return a.v1 == b.v1 && a.v2 == b.v2; -} - -inline bool operator!=(const Name& a, const Name& b) { - return !(a == b); -} - -inline bool operator<(const Name& a, const Name& b) { - return std::tie(a.v1, a.v2) < std::tie(b.v1, b.v2); -} - -std::ostream& operator<<(std::ostream& stream, const Name& name); - -struct PortName : Name { - PortName() : Name(0, 0) {} - PortName(uint64_t v1, uint64_t v2) : Name(v1, v2) {} -}; - -extern const PortName kInvalidPortName; - -struct NodeName : Name { - NodeName() : Name(0, 0) {} - NodeName(uint64_t v1, uint64_t v2) : Name(v1, v2) {} -}; - -extern const NodeName kInvalidNodeName; - -} // namespace ports -} // namespace edk -} // namespace mojo - -namespace std { - -template <> -struct hash { - std::size_t operator()(const mojo::edk::ports::PortName& name) const { - return base::HashInts64(name.v1, name.v2); - } -}; - -template <> -struct hash { - std::size_t operator()(const mojo::edk::ports::NodeName& name) const { - return base::HashInts64(name.v1, name.v2); - } -}; - -} // namespace std - -#endif // MOJO_EDK_SYSTEM_PORTS_NAME_H_ diff --git a/mojo/edk/system/ports/node.cc b/mojo/edk/system/ports/node.cc deleted file mode 100644 index f9a3feb..0000000 --- a/mojo/edk/system/ports/node.cc +++ /dev/null @@ -1,1385 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/ports/node.h" - -#include - -#include - -#include "base/atomicops.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/system/ports/node_delegate.h" - -namespace mojo { -namespace edk { -namespace ports { - -namespace { - -int DebugError(const char* message, int error_code) { - CHECK(false) << "Oops: " << message; - return error_code; -} - -#define OOPS(x) DebugError(#x, x) - -bool CanAcceptMoreMessages(const Port* port) { - // Have we already doled out the last message (i.e., do we expect to NOT - // receive further messages)? - uint64_t next_sequence_num = port->message_queue.next_sequence_num(); - if (port->state == Port::kClosed) - return false; - if (port->peer_closed || port->remove_proxy_on_last_message) { - if (port->last_sequence_num_to_receive == next_sequence_num - 1) - return false; - } - return true; -} - -} // namespace - -class Node::LockedPort { - public: - explicit LockedPort(Port* port) : port_(port) { - port_->lock.AssertAcquired(); - } - - Port* get() const { return port_; } - Port* operator->() const { return port_; } - - private: - Port* const port_; -}; - -Node::Node(const NodeName& name, NodeDelegate* delegate) - : name_(name), - delegate_(delegate) { -} - -Node::~Node() { - if (!ports_.empty()) - DLOG(WARNING) << "Unclean shutdown for node " << name_; -} - -bool Node::CanShutdownCleanly(ShutdownPolicy policy) { - base::AutoLock ports_lock(ports_lock_); - - if (policy == ShutdownPolicy::DONT_ALLOW_LOCAL_PORTS) { -#if DCHECK_IS_ON() - for (auto entry : ports_) { - DVLOG(2) << "Port " << entry.first << " referencing node " - << entry.second->peer_node_name << " is blocking shutdown of " - << "node " << name_ << " (state=" << entry.second->state << ")"; - } -#endif - return ports_.empty(); - } - - DCHECK_EQ(policy, ShutdownPolicy::ALLOW_LOCAL_PORTS); - - // NOTE: This is not efficient, though it probably doesn't need to be since - // relatively few ports should be open during shutdown and shutdown doesn't - // need to be blazingly fast. - bool can_shutdown = true; - for (auto entry : ports_) { - base::AutoLock lock(entry.second->lock); - if (entry.second->peer_node_name != name_ && - entry.second->state != Port::kReceiving) { - can_shutdown = false; -#if DCHECK_IS_ON() - DVLOG(2) << "Port " << entry.first << " referencing node " - << entry.second->peer_node_name << " is blocking shutdown of " - << "node " << name_ << " (state=" << entry.second->state << ")"; -#else - // Exit early when not debugging. - break; -#endif - } - } - - return can_shutdown; -} - -int Node::GetPort(const PortName& port_name, PortRef* port_ref) { - scoped_refptr port = GetPort(port_name); - if (!port) - return ERROR_PORT_UNKNOWN; - - *port_ref = PortRef(port_name, std::move(port)); - return OK; -} - -int Node::CreateUninitializedPort(PortRef* port_ref) { - PortName port_name; - delegate_->GenerateRandomPortName(&port_name); - - scoped_refptr port(new Port(kInitialSequenceNum, kInitialSequenceNum)); - int rv = AddPortWithName(port_name, port); - if (rv != OK) - return rv; - - *port_ref = PortRef(port_name, std::move(port)); - return OK; -} - -int Node::InitializePort(const PortRef& port_ref, - const NodeName& peer_node_name, - const PortName& peer_port_name) { - Port* port = port_ref.port(); - - { - base::AutoLock lock(port->lock); - if (port->state != Port::kUninitialized) - return ERROR_PORT_STATE_UNEXPECTED; - - port->state = Port::kReceiving; - port->peer_node_name = peer_node_name; - port->peer_port_name = peer_port_name; - } - - delegate_->PortStatusChanged(port_ref); - - return OK; -} - -int Node::CreatePortPair(PortRef* port0_ref, PortRef* port1_ref) { - int rv; - - rv = CreateUninitializedPort(port0_ref); - if (rv != OK) - return rv; - - rv = CreateUninitializedPort(port1_ref); - if (rv != OK) - return rv; - - rv = InitializePort(*port0_ref, name_, port1_ref->name()); - if (rv != OK) - return rv; - - rv = InitializePort(*port1_ref, name_, port0_ref->name()); - if (rv != OK) - return rv; - - return OK; -} - -int Node::SetUserData(const PortRef& port_ref, - scoped_refptr user_data) { - Port* port = port_ref.port(); - - base::AutoLock lock(port->lock); - if (port->state == Port::kClosed) - return ERROR_PORT_STATE_UNEXPECTED; - - port->user_data = std::move(user_data); - - return OK; -} - -int Node::GetUserData(const PortRef& port_ref, - scoped_refptr* user_data) { - Port* port = port_ref.port(); - - base::AutoLock lock(port->lock); - if (port->state == Port::kClosed) - return ERROR_PORT_STATE_UNEXPECTED; - - *user_data = port->user_data; - - return OK; -} - -int Node::ClosePort(const PortRef& port_ref) { - std::deque referenced_port_names; - - ObserveClosureEventData data; - - NodeName peer_node_name; - PortName peer_port_name; - Port* port = port_ref.port(); - { - // We may need to erase the port, which requires ports_lock_ to be held, - // but ports_lock_ must be acquired before any individual port locks. - base::AutoLock ports_lock(ports_lock_); - - base::AutoLock lock(port->lock); - if (port->state == Port::kUninitialized) { - // If the port was not yet initialized, there's nothing interesting to do. - ErasePort_Locked(port_ref.name()); - return OK; - } - - if (port->state != Port::kReceiving) - return ERROR_PORT_STATE_UNEXPECTED; - - port->state = Port::kClosed; - - // We pass along the sequence number of the last message sent from this - // port to allow the peer to have the opportunity to consume all inbound - // messages before notifying the embedder that this port is closed. - data.last_sequence_num = port->next_sequence_num_to_send - 1; - - peer_node_name = port->peer_node_name; - peer_port_name = port->peer_port_name; - - // If the port being closed still has unread messages, then we need to take - // care to close those ports so as to avoid leaking memory. - port->message_queue.GetReferencedPorts(&referenced_port_names); - - ErasePort_Locked(port_ref.name()); - } - - DVLOG(2) << "Sending ObserveClosure from " << port_ref.name() << "@" << name_ - << " to " << peer_port_name << "@" << peer_node_name; - - delegate_->ForwardMessage( - peer_node_name, - NewInternalMessage(peer_port_name, EventType::kObserveClosure, data)); - - for (const auto& name : referenced_port_names) { - PortRef ref; - if (GetPort(name, &ref) == OK) - ClosePort(ref); - } - return OK; -} - -int Node::GetStatus(const PortRef& port_ref, PortStatus* port_status) { - Port* port = port_ref.port(); - - base::AutoLock lock(port->lock); - - if (port->state != Port::kReceiving) - return ERROR_PORT_STATE_UNEXPECTED; - - port_status->has_messages = port->message_queue.HasNextMessage(); - port_status->receiving_messages = CanAcceptMoreMessages(port); - port_status->peer_closed = port->peer_closed; - return OK; -} - -int Node::GetMessage(const PortRef& port_ref, - ScopedMessage* message, - MessageFilter* filter) { - *message = nullptr; - - DVLOG(4) << "GetMessage for " << port_ref.name() << "@" << name_; - - Port* port = port_ref.port(); - { - base::AutoLock lock(port->lock); - - // This could also be treated like the port being unknown since the - // embedder should no longer be referring to a port that has been sent. - if (port->state != Port::kReceiving) - return ERROR_PORT_STATE_UNEXPECTED; - - // Let the embedder get messages until there are no more before reporting - // that the peer closed its end. - if (!CanAcceptMoreMessages(port)) - return ERROR_PORT_PEER_CLOSED; - - port->message_queue.GetNextMessage(message, filter); - } - - // Allow referenced ports to trigger PortStatusChanged calls. - if (*message) { - for (size_t i = 0; i < (*message)->num_ports(); ++i) { - const PortName& new_port_name = (*message)->ports()[i]; - scoped_refptr new_port = GetPort(new_port_name); - - DCHECK(new_port) << "Port " << new_port_name << "@" << name_ - << " does not exist!"; - - base::AutoLock lock(new_port->lock); - - DCHECK(new_port->state == Port::kReceiving); - new_port->message_queue.set_signalable(true); - } - } - - return OK; -} - -int Node::SendMessage(const PortRef& port_ref, ScopedMessage message) { - int rv = SendMessageInternal(port_ref, &message); - if (rv != OK) { - // If send failed, close all carried ports. Note that we're careful not to - // close the sending port itself if it happened to be one of the encoded - // ports (an invalid but possible condition.) - for (size_t i = 0; i < message->num_ports(); ++i) { - if (message->ports()[i] == port_ref.name()) - continue; - - PortRef port; - if (GetPort(message->ports()[i], &port) == OK) - ClosePort(port); - } - } - return rv; -} - -int Node::AcceptMessage(ScopedMessage message) { - const EventHeader* header = GetEventHeader(*message); - switch (header->type) { - case EventType::kUser: - return OnUserMessage(std::move(message)); - case EventType::kPortAccepted: - return OnPortAccepted(header->port_name); - case EventType::kObserveProxy: - return OnObserveProxy( - header->port_name, - *GetEventData(*message)); - case EventType::kObserveProxyAck: - return OnObserveProxyAck( - header->port_name, - GetEventData(*message)->last_sequence_num); - case EventType::kObserveClosure: - return OnObserveClosure( - header->port_name, - GetEventData(*message)->last_sequence_num); - case EventType::kMergePort: - return OnMergePort(header->port_name, - *GetEventData(*message)); - } - return OOPS(ERROR_NOT_IMPLEMENTED); -} - -int Node::MergePorts(const PortRef& port_ref, - const NodeName& destination_node_name, - const PortName& destination_port_name) { - Port* port = port_ref.port(); - MergePortEventData data; - { - base::AutoLock lock(port->lock); - - DVLOG(1) << "Sending MergePort from " << port_ref.name() << "@" << name_ - << " to " << destination_port_name << "@" << destination_node_name; - - // Send the port-to-merge over to the destination node so it can be merged - // into the port cycle atomically there. - data.new_port_name = port_ref.name(); - WillSendPort(LockedPort(port), destination_node_name, &data.new_port_name, - &data.new_port_descriptor); - } - delegate_->ForwardMessage( - destination_node_name, - NewInternalMessage(destination_port_name, - EventType::kMergePort, data)); - return OK; -} - -int Node::MergeLocalPorts(const PortRef& port0_ref, const PortRef& port1_ref) { - Port* port0 = port0_ref.port(); - Port* port1 = port1_ref.port(); - int rv; - { - // |ports_lock_| must be held when acquiring overlapping port locks. - base::AutoLock ports_lock(ports_lock_); - base::AutoLock port0_lock(port0->lock); - base::AutoLock port1_lock(port1->lock); - - DVLOG(1) << "Merging local ports " << port0_ref.name() << "@" << name_ - << " and " << port1_ref.name() << "@" << name_; - - if (port0->state != Port::kReceiving || port1->state != Port::kReceiving) - rv = ERROR_PORT_STATE_UNEXPECTED; - else - rv = MergePorts_Locked(port0_ref, port1_ref); - } - - if (rv != OK) { - ClosePort(port0_ref); - ClosePort(port1_ref); - } - - return rv; -} - -int Node::LostConnectionToNode(const NodeName& node_name) { - // We can no longer send events to the given node. We also can't expect any - // PortAccepted events. - - DVLOG(1) << "Observing lost connection from node " << name_ - << " to node " << node_name; - - DestroyAllPortsWithPeer(node_name, kInvalidPortName); - return OK; -} - -int Node::OnUserMessage(ScopedMessage message) { - PortName port_name = GetEventHeader(*message)->port_name; - const auto* event = GetEventData(*message); - -#if DCHECK_IS_ON() - std::ostringstream ports_buf; - for (size_t i = 0; i < message->num_ports(); ++i) { - if (i > 0) - ports_buf << ","; - ports_buf << message->ports()[i]; - } - - DVLOG(4) << "AcceptMessage " << event->sequence_num - << " [ports=" << ports_buf.str() << "] at " - << port_name << "@" << name_; -#endif - - scoped_refptr port = GetPort(port_name); - - // Even if this port does not exist, cannot receive anymore messages or is - // buffering or proxying messages, we still need these ports to be bound to - // this node. When the message is forwarded, these ports will get transferred - // following the usual method. If the message cannot be accepted, then the - // newly bound ports will simply be closed. - - for (size_t i = 0; i < message->num_ports(); ++i) { - int rv = AcceptPort(message->ports()[i], GetPortDescriptors(event)[i]); - if (rv != OK) - return rv; - } - - bool has_next_message = false; - bool message_accepted = false; - - if (port) { - // We may want to forward messages once the port lock is held, so we must - // acquire |ports_lock_| first. - base::AutoLock ports_lock(ports_lock_); - base::AutoLock lock(port->lock); - - // Reject spurious messages if we've already received the last expected - // message. - if (CanAcceptMoreMessages(port.get())) { - message_accepted = true; - port->message_queue.AcceptMessage(std::move(message), &has_next_message); - - if (port->state == Port::kBuffering) { - has_next_message = false; - } else if (port->state == Port::kProxying) { - has_next_message = false; - - // Forward messages. We forward messages in sequential order here so - // that we maintain the message queue's notion of next sequence number. - // That's useful for the proxy removal process as we can tell when this - // port has seen all of the messages it is expected to see. - int rv = ForwardMessages_Locked(LockedPort(port.get()), port_name); - if (rv != OK) - return rv; - - MaybeRemoveProxy_Locked(LockedPort(port.get()), port_name); - } - } - } - - if (!message_accepted) { - DVLOG(2) << "Message not accepted!\n"; - // Close all newly accepted ports as they are effectively orphaned. - for (size_t i = 0; i < message->num_ports(); ++i) { - PortRef port_ref; - if (GetPort(message->ports()[i], &port_ref) == OK) { - ClosePort(port_ref); - } else { - DLOG(WARNING) << "Cannot close non-existent port!\n"; - } - } - } else if (has_next_message) { - PortRef port_ref(port_name, port); - delegate_->PortStatusChanged(port_ref); - } - - return OK; -} - -int Node::OnPortAccepted(const PortName& port_name) { - scoped_refptr port = GetPort(port_name); - if (!port) - return ERROR_PORT_UNKNOWN; - - DVLOG(2) << "PortAccepted at " << port_name << "@" << name_ - << " pointing to " - << port->peer_port_name << "@" << port->peer_node_name; - - return BeginProxying(PortRef(port_name, std::move(port))); -} - -int Node::OnObserveProxy(const PortName& port_name, - const ObserveProxyEventData& event) { - if (port_name == kInvalidPortName) { - // An ObserveProxy with an invalid target port name is a broadcast used to - // inform ports when their peer (which was itself a proxy) has become - // defunct due to unexpected node disconnection. - // - // Receiving ports affected by this treat it as equivalent to peer closure. - // Proxies affected by this can be removed and will in turn broadcast their - // own death with a similar message. - CHECK_EQ(event.proxy_to_node_name, kInvalidNodeName); - CHECK_EQ(event.proxy_to_port_name, kInvalidPortName); - DestroyAllPortsWithPeer(event.proxy_node_name, event.proxy_port_name); - return OK; - } - - // The port may have already been closed locally, in which case the - // ObserveClosure message will contain the last_sequence_num field. - // We can then silently ignore this message. - scoped_refptr port = GetPort(port_name); - if (!port) { - DVLOG(1) << "ObserveProxy: " << port_name << "@" << name_ << " not found"; - return OK; - } - - DVLOG(2) << "ObserveProxy at " << port_name << "@" << name_ << ", proxy at " - << event.proxy_port_name << "@" - << event.proxy_node_name << " pointing to " - << event.proxy_to_port_name << "@" - << event.proxy_to_node_name; - - { - base::AutoLock lock(port->lock); - - if (port->peer_node_name == event.proxy_node_name && - port->peer_port_name == event.proxy_port_name) { - if (port->state == Port::kReceiving) { - port->peer_node_name = event.proxy_to_node_name; - port->peer_port_name = event.proxy_to_port_name; - - ObserveProxyAckEventData ack; - ack.last_sequence_num = port->next_sequence_num_to_send - 1; - - delegate_->ForwardMessage( - event.proxy_node_name, - NewInternalMessage(event.proxy_port_name, - EventType::kObserveProxyAck, - ack)); - } else { - // As a proxy ourselves, we don't know how to honor the ObserveProxy - // event or to populate the last_sequence_num field of ObserveProxyAck. - // Afterall, another port could be sending messages to our peer now - // that we've sent out our own ObserveProxy event. Instead, we will - // send an ObserveProxyAck indicating that the ObserveProxy event - // should be re-sent (last_sequence_num set to kInvalidSequenceNum). - // However, this has to be done after we are removed as a proxy. - // Otherwise, we might just find ourselves back here again, which - // would be akin to a busy loop. - - DVLOG(2) << "Delaying ObserveProxyAck to " - << event.proxy_port_name << "@" << event.proxy_node_name; - - ObserveProxyAckEventData ack; - ack.last_sequence_num = kInvalidSequenceNum; - - port->send_on_proxy_removal.reset( - new std::pair( - event.proxy_node_name, - NewInternalMessage(event.proxy_port_name, - EventType::kObserveProxyAck, - ack))); - } - } else { - // Forward this event along to our peer. Eventually, it should find the - // port referring to the proxy. - delegate_->ForwardMessage( - port->peer_node_name, - NewInternalMessage(port->peer_port_name, - EventType::kObserveProxy, - event)); - } - } - return OK; -} - -int Node::OnObserveProxyAck(const PortName& port_name, - uint64_t last_sequence_num) { - DVLOG(2) << "ObserveProxyAck at " << port_name << "@" << name_ - << " (last_sequence_num=" << last_sequence_num << ")"; - - scoped_refptr port = GetPort(port_name); - if (!port) - return ERROR_PORT_UNKNOWN; // The port may have observed closure first, so - // this is not an "Oops". - - { - base::AutoLock lock(port->lock); - - if (port->state != Port::kProxying) - return OOPS(ERROR_PORT_STATE_UNEXPECTED); - - if (last_sequence_num == kInvalidSequenceNum) { - // Send again. - InitiateProxyRemoval(LockedPort(port.get()), port_name); - return OK; - } - - // We can now remove this port once we have received and forwarded the last - // message addressed to this port. - port->remove_proxy_on_last_message = true; - port->last_sequence_num_to_receive = last_sequence_num; - } - TryRemoveProxy(PortRef(port_name, std::move(port))); - return OK; -} - -int Node::OnObserveClosure(const PortName& port_name, - uint64_t last_sequence_num) { - // OK if the port doesn't exist, as it may have been closed already. - scoped_refptr port = GetPort(port_name); - if (!port) - return OK; - - // This message tells the port that it should no longer expect more messages - // beyond last_sequence_num. This message is forwarded along until we reach - // the receiving end, and this message serves as an equivalent to - // ObserveProxyAck. - - bool notify_delegate = false; - ObserveClosureEventData forwarded_data; - NodeName peer_node_name; - PortName peer_port_name; - bool try_remove_proxy = false; - { - base::AutoLock lock(port->lock); - - port->peer_closed = true; - port->last_sequence_num_to_receive = last_sequence_num; - - DVLOG(2) << "ObserveClosure at " << port_name << "@" << name_ - << " (state=" << port->state << ") pointing to " - << port->peer_port_name << "@" << port->peer_node_name - << " (last_sequence_num=" << last_sequence_num << ")"; - - // We always forward ObserveClosure, even beyond the receiving port which - // cares about it. This ensures that any dead-end proxies beyond that port - // are notified to remove themselves. - - if (port->state == Port::kReceiving) { - notify_delegate = true; - - // When forwarding along the other half of the port cycle, this will only - // reach dead-end proxies. Tell them we've sent our last message so they - // can go away. - // - // TODO: Repurposing ObserveClosure for this has the desired result but - // may be semantically confusing since the forwarding port is not actually - // closed. Consider replacing this with a new event type. - forwarded_data.last_sequence_num = port->next_sequence_num_to_send - 1; - } else { - // We haven't yet reached the receiving peer of the closed port, so - // forward the message along as-is. - forwarded_data.last_sequence_num = last_sequence_num; - - // See about removing the port if it is a proxy as our peer won't be able - // to participate in proxy removal. - port->remove_proxy_on_last_message = true; - if (port->state == Port::kProxying) - try_remove_proxy = true; - } - - DVLOG(2) << "Forwarding ObserveClosure from " - << port_name << "@" << name_ << " to peer " - << port->peer_port_name << "@" << port->peer_node_name - << " (last_sequence_num=" << forwarded_data.last_sequence_num - << ")"; - - peer_node_name = port->peer_node_name; - peer_port_name = port->peer_port_name; - } - if (try_remove_proxy) - TryRemoveProxy(PortRef(port_name, port)); - - delegate_->ForwardMessage( - peer_node_name, - NewInternalMessage(peer_port_name, EventType::kObserveClosure, - forwarded_data)); - - if (notify_delegate) { - PortRef port_ref(port_name, std::move(port)); - delegate_->PortStatusChanged(port_ref); - } - return OK; -} - -int Node::OnMergePort(const PortName& port_name, - const MergePortEventData& event) { - scoped_refptr port = GetPort(port_name); - - DVLOG(1) << "MergePort at " << port_name << "@" << name_ << " (state=" - << (port ? port->state : -1) << ") merging with proxy " - << event.new_port_name - << "@" << name_ << " pointing to " - << event.new_port_descriptor.peer_port_name << "@" - << event.new_port_descriptor.peer_node_name << " referred by " - << event.new_port_descriptor.referring_port_name << "@" - << event.new_port_descriptor.referring_node_name; - - bool close_target_port = false; - bool close_new_port = false; - - // Accept the new port. This is now the receiving end of the other port cycle - // to be merged with ours. - int rv = AcceptPort(event.new_port_name, event.new_port_descriptor); - if (rv != OK) { - close_target_port = true; - } else if (port) { - // BeginProxying_Locked may call MaybeRemoveProxy_Locked, which in turn - // needs to hold |ports_lock_|. We also acquire multiple port locks within. - base::AutoLock ports_lock(ports_lock_); - base::AutoLock lock(port->lock); - - if (port->state != Port::kReceiving) { - close_new_port = true; - } else { - scoped_refptr new_port = GetPort_Locked(event.new_port_name); - base::AutoLock new_port_lock(new_port->lock); - DCHECK(new_port->state == Port::kReceiving); - - // Both ports are locked. Now all we have to do is swap their peer - // information and set them up as proxies. - - PortRef port0_ref(port_name, port); - PortRef port1_ref(event.new_port_name, new_port); - int rv = MergePorts_Locked(port0_ref, port1_ref); - if (rv == OK) - return rv; - - close_new_port = true; - close_target_port = true; - } - } else { - close_new_port = true; - } - - if (close_target_port) { - PortRef target_port; - rv = GetPort(port_name, &target_port); - DCHECK(rv == OK); - - ClosePort(target_port); - } - - if (close_new_port) { - PortRef new_port; - rv = GetPort(event.new_port_name, &new_port); - DCHECK(rv == OK); - - ClosePort(new_port); - } - - return ERROR_PORT_STATE_UNEXPECTED; -} - -int Node::AddPortWithName(const PortName& port_name, scoped_refptr port) { - base::AutoLock lock(ports_lock_); - - if (!ports_.insert(std::make_pair(port_name, std::move(port))).second) - return OOPS(ERROR_PORT_EXISTS); // Suggests a bad UUID generator. - - DVLOG(2) << "Created port " << port_name << "@" << name_; - return OK; -} - -void Node::ErasePort(const PortName& port_name) { - base::AutoLock lock(ports_lock_); - ErasePort_Locked(port_name); -} - -void Node::ErasePort_Locked(const PortName& port_name) { - ports_lock_.AssertAcquired(); - ports_.erase(port_name); - DVLOG(2) << "Deleted port " << port_name << "@" << name_; -} - -scoped_refptr Node::GetPort(const PortName& port_name) { - base::AutoLock lock(ports_lock_); - return GetPort_Locked(port_name); -} - -scoped_refptr Node::GetPort_Locked(const PortName& port_name) { - ports_lock_.AssertAcquired(); - auto iter = ports_.find(port_name); - if (iter == ports_.end()) - return nullptr; - -#if (defined(OS_ANDROID) || defined(__ANDROID__)) && defined(ARCH_CPU_ARM64) - // Workaround for https://crbug.com/665869. - base::subtle::MemoryBarrier(); -#endif - - return iter->second; -} - -int Node::SendMessageInternal(const PortRef& port_ref, ScopedMessage* message) { - ScopedMessage& m = *message; - for (size_t i = 0; i < m->num_ports(); ++i) { - if (m->ports()[i] == port_ref.name()) - return ERROR_PORT_CANNOT_SEND_SELF; - } - - Port* port = port_ref.port(); - NodeName peer_node_name; - { - // We must acquire |ports_lock_| before grabbing any port locks, because - // WillSendMessage_Locked may need to lock multiple ports out of order. - base::AutoLock ports_lock(ports_lock_); - base::AutoLock lock(port->lock); - - if (port->state != Port::kReceiving) - return ERROR_PORT_STATE_UNEXPECTED; - - if (port->peer_closed) - return ERROR_PORT_PEER_CLOSED; - - int rv = WillSendMessage_Locked(LockedPort(port), port_ref.name(), m.get()); - if (rv != OK) - return rv; - - // Beyond this point there's no sense in returning anything but OK. Even if - // message forwarding or acceptance fails, there's nothing the embedder can - // do to recover. Assume that failure beyond this point must be treated as a - // transport failure. - - peer_node_name = port->peer_node_name; - } - - if (peer_node_name != name_) { - delegate_->ForwardMessage(peer_node_name, std::move(m)); - return OK; - } - - int rv = AcceptMessage(std::move(m)); - if (rv != OK) { - // See comment above for why we don't return an error in this case. - DVLOG(2) << "AcceptMessage failed: " << rv; - } - - return OK; -} - -int Node::MergePorts_Locked(const PortRef& port0_ref, - const PortRef& port1_ref) { - Port* port0 = port0_ref.port(); - Port* port1 = port1_ref.port(); - - ports_lock_.AssertAcquired(); - port0->lock.AssertAcquired(); - port1->lock.AssertAcquired(); - - CHECK(port0->state == Port::kReceiving); - CHECK(port1->state == Port::kReceiving); - - // Ports cannot be merged with their own receiving peer! - if (port0->peer_node_name == name_ && - port0->peer_port_name == port1_ref.name()) - return ERROR_PORT_STATE_UNEXPECTED; - - if (port1->peer_node_name == name_ && - port1->peer_port_name == port0_ref.name()) - return ERROR_PORT_STATE_UNEXPECTED; - - // Only merge if both ports have never sent a message. - if (port0->next_sequence_num_to_send == kInitialSequenceNum && - port1->next_sequence_num_to_send == kInitialSequenceNum) { - // Swap the ports' peer information and switch them both into buffering - // (eventually proxying) mode. - - std::swap(port0->peer_node_name, port1->peer_node_name); - std::swap(port0->peer_port_name, port1->peer_port_name); - - port0->state = Port::kBuffering; - if (port0->peer_closed) - port0->remove_proxy_on_last_message = true; - - port1->state = Port::kBuffering; - if (port1->peer_closed) - port1->remove_proxy_on_last_message = true; - - int rv1 = BeginProxying_Locked(LockedPort(port0), port0_ref.name()); - int rv2 = BeginProxying_Locked(LockedPort(port1), port1_ref.name()); - - if (rv1 == OK && rv2 == OK) { - // If either merged port had a closed peer, its new peer needs to be - // informed of this. - if (port1->peer_closed) { - ObserveClosureEventData data; - data.last_sequence_num = port0->last_sequence_num_to_receive; - delegate_->ForwardMessage( - port0->peer_node_name, - NewInternalMessage(port0->peer_port_name, - EventType::kObserveClosure, data)); - } - - if (port0->peer_closed) { - ObserveClosureEventData data; - data.last_sequence_num = port1->last_sequence_num_to_receive; - delegate_->ForwardMessage( - port1->peer_node_name, - NewInternalMessage(port1->peer_port_name, - EventType::kObserveClosure, data)); - } - - return OK; - } - - // If either proxy failed to initialize (e.g. had undeliverable messages - // or ended up in a bad state somehow), we keep the system in a consistent - // state by undoing the peer swap. - std::swap(port0->peer_node_name, port1->peer_node_name); - std::swap(port0->peer_port_name, port1->peer_port_name); - port0->remove_proxy_on_last_message = false; - port1->remove_proxy_on_last_message = false; - port0->state = Port::kReceiving; - port1->state = Port::kReceiving; - } - - return ERROR_PORT_STATE_UNEXPECTED; -} - -void Node::WillSendPort(const LockedPort& port, - const NodeName& to_node_name, - PortName* port_name, - PortDescriptor* port_descriptor) { - port->lock.AssertAcquired(); - - PortName local_port_name = *port_name; - - PortName new_port_name; - delegate_->GenerateRandomPortName(&new_port_name); - - // Make sure we don't send messages to the new peer until after we know it - // exists. In the meantime, just buffer messages locally. - DCHECK(port->state == Port::kReceiving); - port->state = Port::kBuffering; - - // If we already know our peer is closed, we already know this proxy can - // be removed once it receives and forwards its last expected message. - if (port->peer_closed) - port->remove_proxy_on_last_message = true; - - *port_name = new_port_name; - - port_descriptor->peer_node_name = port->peer_node_name; - port_descriptor->peer_port_name = port->peer_port_name; - port_descriptor->referring_node_name = name_; - port_descriptor->referring_port_name = local_port_name; - port_descriptor->next_sequence_num_to_send = port->next_sequence_num_to_send; - port_descriptor->next_sequence_num_to_receive = - port->message_queue.next_sequence_num(); - port_descriptor->last_sequence_num_to_receive = - port->last_sequence_num_to_receive; - port_descriptor->peer_closed = port->peer_closed; - memset(port_descriptor->padding, 0, sizeof(port_descriptor->padding)); - - // Configure the local port to point to the new port. - port->peer_node_name = to_node_name; - port->peer_port_name = new_port_name; -} - -int Node::AcceptPort(const PortName& port_name, - const PortDescriptor& port_descriptor) { - scoped_refptr port = make_scoped_refptr( - new Port(port_descriptor.next_sequence_num_to_send, - port_descriptor.next_sequence_num_to_receive)); - port->state = Port::kReceiving; - port->peer_node_name = port_descriptor.peer_node_name; - port->peer_port_name = port_descriptor.peer_port_name; - port->last_sequence_num_to_receive = - port_descriptor.last_sequence_num_to_receive; - port->peer_closed = port_descriptor.peer_closed; - - DVLOG(2) << "Accepting port " << port_name << " [peer_closed=" - << port->peer_closed << "; last_sequence_num_to_receive=" - << port->last_sequence_num_to_receive << "]"; - - // A newly accepted port is not signalable until the message referencing the - // new port finds its way to the consumer (see GetMessage). - port->message_queue.set_signalable(false); - - int rv = AddPortWithName(port_name, std::move(port)); - if (rv != OK) - return rv; - - // Allow referring port to forward messages. - delegate_->ForwardMessage( - port_descriptor.referring_node_name, - NewInternalMessage(port_descriptor.referring_port_name, - EventType::kPortAccepted)); - return OK; -} - -int Node::WillSendMessage_Locked(const LockedPort& port, - const PortName& port_name, - Message* message) { - ports_lock_.AssertAcquired(); - port->lock.AssertAcquired(); - - DCHECK(message); - - // Messages may already have a sequence number if they're being forwarded - // by a proxy. Otherwise, use the next outgoing sequence number. - uint64_t* sequence_num = - &GetMutableEventData(message)->sequence_num; - if (*sequence_num == 0) - *sequence_num = port->next_sequence_num_to_send++; - -#if DCHECK_IS_ON() - std::ostringstream ports_buf; - for (size_t i = 0; i < message->num_ports(); ++i) { - if (i > 0) - ports_buf << ","; - ports_buf << message->ports()[i]; - } -#endif - - if (message->num_ports() > 0) { - // Note: Another thread could be trying to send the same ports, so we need - // to ensure that they are ours to send before we mutate their state. - - std::vector> ports; - ports.resize(message->num_ports()); - - { - for (size_t i = 0; i < message->num_ports(); ++i) { - ports[i] = GetPort_Locked(message->ports()[i]); - DCHECK(ports[i]); - - ports[i]->lock.Acquire(); - int error = OK; - if (ports[i]->state != Port::kReceiving) - error = ERROR_PORT_STATE_UNEXPECTED; - else if (message->ports()[i] == port->peer_port_name) - error = ERROR_PORT_CANNOT_SEND_PEER; - - if (error != OK) { - // Oops, we cannot send this port. - for (size_t j = 0; j <= i; ++j) - ports[i]->lock.Release(); - // Backpedal on the sequence number. - port->next_sequence_num_to_send--; - return error; - } - } - } - - PortDescriptor* port_descriptors = - GetMutablePortDescriptors(GetMutableEventData(message)); - - for (size_t i = 0; i < message->num_ports(); ++i) { - WillSendPort(LockedPort(ports[i].get()), - port->peer_node_name, - message->mutable_ports() + i, - port_descriptors + i); - } - - for (size_t i = 0; i < message->num_ports(); ++i) - ports[i]->lock.Release(); - } - -#if DCHECK_IS_ON() - DVLOG(4) << "Sending message " - << GetEventData(*message)->sequence_num - << " [ports=" << ports_buf.str() << "]" - << " from " << port_name << "@" << name_ - << " to " << port->peer_port_name << "@" << port->peer_node_name; -#endif - - GetMutableEventHeader(message)->port_name = port->peer_port_name; - return OK; -} - -int Node::BeginProxying_Locked(const LockedPort& port, - const PortName& port_name) { - ports_lock_.AssertAcquired(); - port->lock.AssertAcquired(); - - if (port->state != Port::kBuffering) - return OOPS(ERROR_PORT_STATE_UNEXPECTED); - - port->state = Port::kProxying; - - int rv = ForwardMessages_Locked(LockedPort(port), port_name); - if (rv != OK) - return rv; - - // We may have observed closure while buffering. In that case, we can advance - // to removing the proxy without sending out an ObserveProxy message. We - // already know the last expected message, etc. - - if (port->remove_proxy_on_last_message) { - MaybeRemoveProxy_Locked(LockedPort(port), port_name); - - // Make sure we propagate closure to our current peer. - ObserveClosureEventData data; - data.last_sequence_num = port->last_sequence_num_to_receive; - delegate_->ForwardMessage( - port->peer_node_name, - NewInternalMessage(port->peer_port_name, - EventType::kObserveClosure, data)); - } else { - InitiateProxyRemoval(LockedPort(port), port_name); - } - - return OK; -} - -int Node::BeginProxying(PortRef port_ref) { - Port* port = port_ref.port(); - { - base::AutoLock ports_lock(ports_lock_); - base::AutoLock lock(port->lock); - - if (port->state != Port::kBuffering) - return OOPS(ERROR_PORT_STATE_UNEXPECTED); - - port->state = Port::kProxying; - - int rv = ForwardMessages_Locked(LockedPort(port), port_ref.name()); - if (rv != OK) - return rv; - } - - bool should_remove; - NodeName peer_node_name; - ScopedMessage closure_message; - { - base::AutoLock lock(port->lock); - if (port->state != Port::kProxying) - return OOPS(ERROR_PORT_STATE_UNEXPECTED); - - should_remove = port->remove_proxy_on_last_message; - if (should_remove) { - // Make sure we propagate closure to our current peer. - ObserveClosureEventData data; - data.last_sequence_num = port->last_sequence_num_to_receive; - peer_node_name = port->peer_node_name; - closure_message = NewInternalMessage(port->peer_port_name, - EventType::kObserveClosure, data); - } else { - InitiateProxyRemoval(LockedPort(port), port_ref.name()); - } - } - - if (should_remove) { - TryRemoveProxy(port_ref); - delegate_->ForwardMessage(peer_node_name, std::move(closure_message)); - } - - return OK; -} - -int Node::ForwardMessages_Locked(const LockedPort& port, - const PortName &port_name) { - ports_lock_.AssertAcquired(); - port->lock.AssertAcquired(); - - for (;;) { - ScopedMessage message; - port->message_queue.GetNextMessage(&message, nullptr); - if (!message) - break; - - int rv = WillSendMessage_Locked(LockedPort(port), port_name, message.get()); - if (rv != OK) - return rv; - - delegate_->ForwardMessage(port->peer_node_name, std::move(message)); - } - return OK; -} - -void Node::InitiateProxyRemoval(const LockedPort& port, - const PortName& port_name) { - port->lock.AssertAcquired(); - - // To remove this node, we start by notifying the connected graph that we are - // a proxy. This allows whatever port is referencing this node to skip it. - // Eventually, this node will receive ObserveProxyAck (or ObserveClosure if - // the peer was closed in the meantime). - - ObserveProxyEventData data; - data.proxy_node_name = name_; - data.proxy_port_name = port_name; - data.proxy_to_node_name = port->peer_node_name; - data.proxy_to_port_name = port->peer_port_name; - - delegate_->ForwardMessage( - port->peer_node_name, - NewInternalMessage(port->peer_port_name, EventType::kObserveProxy, data)); -} - -void Node::MaybeRemoveProxy_Locked(const LockedPort& port, - const PortName& port_name) { - // |ports_lock_| must be held so we can potentilaly ErasePort_Locked(). - ports_lock_.AssertAcquired(); - port->lock.AssertAcquired(); - - DCHECK(port->state == Port::kProxying); - - // Make sure we have seen ObserveProxyAck before removing the port. - if (!port->remove_proxy_on_last_message) - return; - - if (!CanAcceptMoreMessages(port.get())) { - // This proxy port is done. We can now remove it! - ErasePort_Locked(port_name); - - if (port->send_on_proxy_removal) { - NodeName to_node = port->send_on_proxy_removal->first; - ScopedMessage& message = port->send_on_proxy_removal->second; - - delegate_->ForwardMessage(to_node, std::move(message)); - port->send_on_proxy_removal.reset(); - } - } else { - DVLOG(2) << "Cannot remove port " << port_name << "@" << name_ - << " now; waiting for more messages"; - } -} - -void Node::TryRemoveProxy(PortRef port_ref) { - Port* port = port_ref.port(); - bool should_erase = false; - ScopedMessage msg; - NodeName to_node; - { - base::AutoLock lock(port->lock); - - // Port already removed. Nothing to do. - if (port->state == Port::kClosed) - return; - - DCHECK(port->state == Port::kProxying); - - // Make sure we have seen ObserveProxyAck before removing the port. - if (!port->remove_proxy_on_last_message) - return; - - if (!CanAcceptMoreMessages(port)) { - // This proxy port is done. We can now remove it! - should_erase = true; - - if (port->send_on_proxy_removal) { - to_node = port->send_on_proxy_removal->first; - msg = std::move(port->send_on_proxy_removal->second); - port->send_on_proxy_removal.reset(); - } - } else { - DVLOG(2) << "Cannot remove port " << port_ref.name() << "@" << name_ - << " now; waiting for more messages"; - } - } - - if (should_erase) - ErasePort(port_ref.name()); - - if (msg) - delegate_->ForwardMessage(to_node, std::move(msg)); -} - -void Node::DestroyAllPortsWithPeer(const NodeName& node_name, - const PortName& port_name) { - // Wipes out all ports whose peer node matches |node_name| and whose peer port - // matches |port_name|. If |port_name| is |kInvalidPortName|, only the peer - // node is matched. - - std::vector ports_to_notify; - std::vector dead_proxies_to_broadcast; - std::deque referenced_port_names; - - { - base::AutoLock ports_lock(ports_lock_); - - for (auto iter = ports_.begin(); iter != ports_.end(); ++iter) { - Port* port = iter->second.get(); - { - base::AutoLock port_lock(port->lock); - - if (port->peer_node_name == node_name && - (port_name == kInvalidPortName || - port->peer_port_name == port_name)) { - if (!port->peer_closed) { - // Treat this as immediate peer closure. It's an exceptional - // condition akin to a broken pipe, so we don't care about losing - // messages. - - port->peer_closed = true; - port->last_sequence_num_to_receive = - port->message_queue.next_sequence_num() - 1; - - if (port->state == Port::kReceiving) - ports_to_notify.push_back(PortRef(iter->first, port)); - } - - // We don't expect to forward any further messages, and we don't - // expect to receive a Port{Accepted,Rejected} event. Because we're - // a proxy with no active peer, we cannot use the normal proxy removal - // procedure of forward-propagating an ObserveProxy. Instead we - // broadcast our own death so it can be back-propagated. This is - // inefficient but rare. - if (port->state != Port::kReceiving) { - dead_proxies_to_broadcast.push_back(iter->first); - iter->second->message_queue.GetReferencedPorts( - &referenced_port_names); - } - } - } - } - - for (const auto& proxy_name : dead_proxies_to_broadcast) { - ports_.erase(proxy_name); - DVLOG(2) << "Forcibly deleted port " << proxy_name << "@" << name_; - } - } - - // Wake up any receiving ports who have just observed simulated peer closure. - for (const auto& port : ports_to_notify) - delegate_->PortStatusChanged(port); - - for (const auto& proxy_name : dead_proxies_to_broadcast) { - // Broadcast an event signifying that this proxy is no longer functioning. - ObserveProxyEventData event; - event.proxy_node_name = name_; - event.proxy_port_name = proxy_name; - event.proxy_to_node_name = kInvalidNodeName; - event.proxy_to_port_name = kInvalidPortName; - delegate_->BroadcastMessage(NewInternalMessage( - kInvalidPortName, EventType::kObserveProxy, event)); - - // Also process death locally since the port that points this closed one - // could be on the current node. - // Note: Although this is recursive, only a single port is involved which - // limits the expected branching to 1. - DestroyAllPortsWithPeer(name_, proxy_name); - } - - // Close any ports referenced by the closed proxies. - for (const auto& name : referenced_port_names) { - PortRef ref; - if (GetPort(name, &ref) == OK) - ClosePort(ref); - } -} - -ScopedMessage Node::NewInternalMessage_Helper(const PortName& port_name, - const EventType& type, - const void* data, - size_t num_data_bytes) { - ScopedMessage message; - delegate_->AllocMessage(sizeof(EventHeader) + num_data_bytes, &message); - - EventHeader* header = GetMutableEventHeader(message.get()); - header->port_name = port_name; - header->type = type; - header->padding = 0; - - if (num_data_bytes) - memcpy(header + 1, data, num_data_bytes); - - return message; -} - -} // namespace ports -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/node.h b/mojo/edk/system/ports/node.h deleted file mode 100644 index 55b8d27..0000000 --- a/mojo/edk/system/ports/node.h +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_NODE_H_ -#define MOJO_EDK_SYSTEM_PORTS_NODE_H_ - -#include -#include - -#include -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/system/ports/event.h" -#include "mojo/edk/system/ports/message.h" -#include "mojo/edk/system/ports/name.h" -#include "mojo/edk/system/ports/port.h" -#include "mojo/edk/system/ports/port_ref.h" -#include "mojo/edk/system/ports/user_data.h" - -#undef SendMessage // Gah, windows - -namespace mojo { -namespace edk { -namespace ports { - -enum : int { - OK = 0, - ERROR_PORT_UNKNOWN = -10, - ERROR_PORT_EXISTS = -11, - ERROR_PORT_STATE_UNEXPECTED = -12, - ERROR_PORT_CANNOT_SEND_SELF = -13, - ERROR_PORT_PEER_CLOSED = -14, - ERROR_PORT_CANNOT_SEND_PEER = -15, - ERROR_NOT_IMPLEMENTED = -100, -}; - -struct PortStatus { - bool has_messages; - bool receiving_messages; - bool peer_closed; -}; - -class MessageFilter; -class NodeDelegate; - -class Node { - public: - enum class ShutdownPolicy { - DONT_ALLOW_LOCAL_PORTS, - ALLOW_LOCAL_PORTS, - }; - - // Does not take ownership of the delegate. - Node(const NodeName& name, NodeDelegate* delegate); - ~Node(); - - // Returns true iff there are no open ports referring to another node or ports - // in the process of being transferred from this node to another. If this - // returns false, then to ensure clean shutdown, it is necessary to keep the - // node alive and continue routing messages to it via AcceptMessage. This - // method may be called again after AcceptMessage to check if the Node is now - // ready to be destroyed. - // - // If |policy| is set to |ShutdownPolicy::ALLOW_LOCAL_PORTS|, this will return - // |true| even if some ports remain alive, as long as none of them are proxies - // to another node. - bool CanShutdownCleanly( - ShutdownPolicy policy = ShutdownPolicy::DONT_ALLOW_LOCAL_PORTS); - - // Lookup the named port. - int GetPort(const PortName& port_name, PortRef* port_ref); - - // Creates a port on this node. Before the port can be used, it must be - // initialized using InitializePort. This method is useful for bootstrapping - // a connection between two nodes. Generally, ports are created using - // CreatePortPair instead. - int CreateUninitializedPort(PortRef* port_ref); - - // Initializes a newly created port. - int InitializePort(const PortRef& port_ref, - const NodeName& peer_node_name, - const PortName& peer_port_name); - - // Generates a new connected pair of ports bound to this node. These ports - // are initialized and ready to go. - int CreatePortPair(PortRef* port0_ref, PortRef* port1_ref); - - // User data associated with the port. - int SetUserData(const PortRef& port_ref, scoped_refptr user_data); - int GetUserData(const PortRef& port_ref, - scoped_refptr* user_data); - - // Prevents further messages from being sent from this port or delivered to - // this port. The port is removed, and the port's peer is notified of the - // closure after it has consumed all pending messages. - int ClosePort(const PortRef& port_ref); - - // Returns the current status of the port. - int GetStatus(const PortRef& port_ref, PortStatus* port_status); - - // Returns the next available message on the specified port or returns a null - // message if there are none available. Returns ERROR_PORT_PEER_CLOSED to - // indicate that this port's peer has closed. In such cases GetMessage may - // be called until it yields a null message, indicating that no more messages - // may be read from the port. - // - // If |filter| is non-null, the next available message is returned only if it - // is matched by the filter. If the provided filter does not match the next - // available message, GetMessage() behaves as if there is no message - // available. Ownership of |filter| is not taken, and it must outlive the - // extent of this call. - int GetMessage(const PortRef& port_ref, - ScopedMessage* message, - MessageFilter* filter); - - // Sends a message from the specified port to its peer. Note that the message - // notification may arrive synchronously (via PortStatusChanged() on the - // delegate) if the peer is local to this Node. - int SendMessage(const PortRef& port_ref, ScopedMessage message); - - // Corresponding to NodeDelegate::ForwardMessage. - int AcceptMessage(ScopedMessage message); - - // Called to merge two ports with each other. If you have two independent - // port pairs A <=> B and C <=> D, the net result of merging B and C is a - // single connected port pair A <=> D. - // - // Note that the behavior of this operation is undefined if either port to be - // merged (B or C above) has ever been read from or written to directly, and - // this must ONLY be called on one side of the merge, though it doesn't matter - // which side. - // - // It is safe for the non-merged peers (A and D above) to be transferred, - // closed, and/or written to before, during, or after the merge. - int MergePorts(const PortRef& port_ref, - const NodeName& destination_node_name, - const PortName& destination_port_name); - - // Like above but merges two ports local to this node. Because both ports are - // local this can also verify that neither port has been written to before the - // merge. If this fails for any reason, both ports are closed. Otherwise OK - // is returned and the ports' receiving peers are connected to each other. - int MergeLocalPorts(const PortRef& port0_ref, const PortRef& port1_ref); - - // Called to inform this node that communication with another node is lost - // indefinitely. This triggers cleanup of ports bound to this node. - int LostConnectionToNode(const NodeName& node_name); - - private: - class LockedPort; - - // Note: Functions that end with _Locked require |ports_lock_| to be held - // before calling. - int OnUserMessage(ScopedMessage message); - int OnPortAccepted(const PortName& port_name); - int OnObserveProxy(const PortName& port_name, - const ObserveProxyEventData& event); - int OnObserveProxyAck(const PortName& port_name, uint64_t last_sequence_num); - int OnObserveClosure(const PortName& port_name, uint64_t last_sequence_num); - int OnMergePort(const PortName& port_name, const MergePortEventData& event); - - int AddPortWithName(const PortName& port_name, scoped_refptr port); - void ErasePort(const PortName& port_name); - void ErasePort_Locked(const PortName& port_name); - scoped_refptr GetPort(const PortName& port_name); - scoped_refptr GetPort_Locked(const PortName& port_name); - - int SendMessageInternal(const PortRef& port_ref, ScopedMessage* message); - int MergePorts_Locked(const PortRef& port0_ref, const PortRef& port1_ref); - void WillSendPort(const LockedPort& port, - const NodeName& to_node_name, - PortName* port_name, - PortDescriptor* port_descriptor); - int AcceptPort(const PortName& port_name, - const PortDescriptor& port_descriptor); - - int WillSendMessage_Locked(const LockedPort& port, - const PortName& port_name, - Message* message); - int BeginProxying_Locked(const LockedPort& port, const PortName& port_name); - int BeginProxying(PortRef port_ref); - int ForwardMessages_Locked(const LockedPort& port, const PortName& port_name); - void InitiateProxyRemoval(const LockedPort& port, const PortName& port_name); - void MaybeRemoveProxy_Locked(const LockedPort& port, - const PortName& port_name); - void TryRemoveProxy(PortRef port_ref); - void DestroyAllPortsWithPeer(const NodeName& node_name, - const PortName& port_name); - - ScopedMessage NewInternalMessage_Helper(const PortName& port_name, - const EventType& type, - const void* data, - size_t num_data_bytes); - - ScopedMessage NewInternalMessage(const PortName& port_name, - const EventType& type) { - return NewInternalMessage_Helper(port_name, type, nullptr, 0); - } - - template - ScopedMessage NewInternalMessage(const PortName& port_name, - const EventType& type, - const EventData& data) { - return NewInternalMessage_Helper(port_name, type, &data, sizeof(data)); - } - - const NodeName name_; - NodeDelegate* const delegate_; - - // Guards |ports_| as well as any operation which needs to hold multiple port - // locks simultaneously. Usage of this is subtle: it must NEVER be acquired - // after a Port lock is acquired, and it must ALWAYS be acquired before - // calling WillSendMessage_Locked or ForwardMessages_Locked. - base::Lock ports_lock_; - std::unordered_map> ports_; - - DISALLOW_COPY_AND_ASSIGN(Node); -}; - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_NODE_H_ diff --git a/mojo/edk/system/ports/node_delegate.h b/mojo/edk/system/ports/node_delegate.h deleted file mode 100644 index 8547302..0000000 --- a/mojo/edk/system/ports/node_delegate.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_NODE_DELEGATE_H_ -#define MOJO_EDK_SYSTEM_PORTS_NODE_DELEGATE_H_ - -#include - -#include "mojo/edk/system/ports/message.h" -#include "mojo/edk/system/ports/name.h" -#include "mojo/edk/system/ports/port_ref.h" - -namespace mojo { -namespace edk { -namespace ports { - -class NodeDelegate { - public: - virtual ~NodeDelegate() {} - - // Port names should be difficult to guess. - virtual void GenerateRandomPortName(PortName* port_name) = 0; - - // Allocate a message, including a header that can be used by the Node - // implementation. |num_header_bytes| will be aligned. The newly allocated - // memory need not be zero-filled. - virtual void AllocMessage(size_t num_header_bytes, - ScopedMessage* message) = 0; - - // Forward a message asynchronously to the specified node. This method MUST - // NOT synchronously call any methods on Node. - virtual void ForwardMessage(const NodeName& node, ScopedMessage message) = 0; - - // Broadcast a message to all nodes. - virtual void BroadcastMessage(ScopedMessage message) = 0; - - // Indicates that the port's status has changed recently. Use Node::GetStatus - // to query the latest status of the port. Note, this event could be spurious - // if another thread is simultaneously modifying the status of the port. - virtual void PortStatusChanged(const PortRef& port_ref) = 0; -}; - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_NODE_DELEGATE_H_ diff --git a/mojo/edk/system/ports/port.cc b/mojo/edk/system/ports/port.cc deleted file mode 100644 index e4403ae..0000000 --- a/mojo/edk/system/ports/port.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/ports/port.h" - -namespace mojo { -namespace edk { -namespace ports { - -Port::Port(uint64_t next_sequence_num_to_send, - uint64_t next_sequence_num_to_receive) - : state(kUninitialized), - next_sequence_num_to_send(next_sequence_num_to_send), - last_sequence_num_to_receive(0), - message_queue(next_sequence_num_to_receive), - remove_proxy_on_last_message(false), - peer_closed(false) {} - -Port::~Port() {} - -} // namespace ports -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/port.h b/mojo/edk/system/ports/port.h deleted file mode 100644 index ea53d43..0000000 --- a/mojo/edk/system/ports/port.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_PORT_H_ -#define MOJO_EDK_SYSTEM_PORTS_PORT_H_ - -#include -#include -#include -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/system/ports/message_queue.h" -#include "mojo/edk/system/ports/user_data.h" - -namespace mojo { -namespace edk { -namespace ports { - -class Port : public base::RefCountedThreadSafe { - public: - enum State { - kUninitialized, - kReceiving, - kBuffering, - kProxying, - kClosed - }; - - base::Lock lock; - State state; - NodeName peer_node_name; - PortName peer_port_name; - uint64_t next_sequence_num_to_send; - uint64_t last_sequence_num_to_receive; - MessageQueue message_queue; - std::unique_ptr> send_on_proxy_removal; - scoped_refptr user_data; - bool remove_proxy_on_last_message; - bool peer_closed; - - Port(uint64_t next_sequence_num_to_send, - uint64_t next_sequence_num_to_receive); - - private: - friend class base::RefCountedThreadSafe; - - ~Port(); - - DISALLOW_COPY_AND_ASSIGN(Port); -}; - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_PORT_H_ diff --git a/mojo/edk/system/ports/port_ref.cc b/mojo/edk/system/ports/port_ref.cc deleted file mode 100644 index 675754d..0000000 --- a/mojo/edk/system/ports/port_ref.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/ports/port_ref.h" - -#include "mojo/edk/system/ports/port.h" - -namespace mojo { -namespace edk { -namespace ports { - -PortRef::~PortRef() { -} - -PortRef::PortRef() { -} - -PortRef::PortRef(const PortName& name, scoped_refptr port) - : name_(name), port_(std::move(port)) {} - -PortRef::PortRef(const PortRef& other) - : name_(other.name_), port_(other.port_) { -} - -PortRef& PortRef::operator=(const PortRef& other) { - if (&other != this) { - name_ = other.name_; - port_ = other.port_; - } - return *this; -} - -} // namespace ports -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/port_ref.h b/mojo/edk/system/ports/port_ref.h deleted file mode 100644 index 59036c3..0000000 --- a/mojo/edk/system/ports/port_ref.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_PORT_REF_H_ -#define MOJO_EDK_SYSTEM_PORTS_PORT_REF_H_ - -#include "base/memory/ref_counted.h" -#include "mojo/edk/system/ports/name.h" - -namespace mojo { -namespace edk { -namespace ports { - -class Port; -class Node; - -class PortRef { - public: - ~PortRef(); - PortRef(); - PortRef(const PortName& name, scoped_refptr port); - - PortRef(const PortRef& other); - PortRef& operator=(const PortRef& other); - - const PortName& name() const { return name_; } - - private: - friend class Node; - Port* port() const { return port_.get(); } - - PortName name_; - scoped_refptr port_; -}; - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_PORT_REF_H_ diff --git a/mojo/edk/system/ports/ports_unittest.cc b/mojo/edk/system/ports/ports_unittest.cc deleted file mode 100644 index cb48b3e..0000000 --- a/mojo/edk/system/ports/ports_unittest.cc +++ /dev/null @@ -1,1478 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/rand_util.h" -#include "base/strings/string_piece.h" -#include "base/strings/stringprintf.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "mojo/edk/system/ports/event.h" -#include "mojo/edk/system/ports/node.h" -#include "mojo/edk/system/ports/node_delegate.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace ports { -namespace test { - -namespace { - -bool MessageEquals(const ScopedMessage& message, const base::StringPiece& s) { - return !strcmp(static_cast(message->payload_bytes()), s.data()); -} - -class TestMessage : public Message { - public: - static ScopedMessage NewUserMessage(size_t num_payload_bytes, - size_t num_ports) { - return ScopedMessage(new TestMessage(num_payload_bytes, num_ports)); - } - - TestMessage(size_t num_payload_bytes, size_t num_ports) - : Message(num_payload_bytes, num_ports) { - start_ = new char[num_header_bytes_ + num_ports_bytes_ + num_payload_bytes]; - InitializeUserMessageHeader(start_); - } - - TestMessage(size_t num_header_bytes, - size_t num_payload_bytes, - size_t num_ports_bytes) - : Message(num_header_bytes, - num_payload_bytes, - num_ports_bytes) { - start_ = new char[num_header_bytes + num_payload_bytes + num_ports_bytes]; - } - - ~TestMessage() override { - delete[] start_; - } -}; - -class TestNode; - -class MessageRouter { - public: - virtual ~MessageRouter() {} - - virtual void GeneratePortName(PortName* name) = 0; - virtual void ForwardMessage(TestNode* from_node, - const NodeName& node_name, - ScopedMessage message) = 0; - virtual void BroadcastMessage(TestNode* from_node, ScopedMessage message) = 0; -}; - -class TestNode : public NodeDelegate { - public: - explicit TestNode(uint64_t id) - : node_name_(id, 1), - node_(node_name_, this), - node_thread_(base::StringPrintf("Node %" PRIu64 " thread", id)), - messages_available_event_( - base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), - idle_event_( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::SIGNALED) { - } - - ~TestNode() override { - StopWhenIdle(); - node_thread_.Stop(); - } - - const NodeName& name() const { return node_name_; } - - // NOTE: Node is thread-safe. - Node& node() { return node_; } - - base::WaitableEvent& idle_event() { return idle_event_; } - - bool IsIdle() { - base::AutoLock lock(lock_); - return started_ && !dispatching_ && - (incoming_messages_.empty() || (block_on_event_ && blocked_)); - } - - void BlockOnEvent(EventType type) { - base::AutoLock lock(lock_); - blocked_event_type_ = type; - block_on_event_ = true; - } - - void Unblock() { - base::AutoLock lock(lock_); - block_on_event_ = false; - messages_available_event_.Signal(); - } - - void Start(MessageRouter* router) { - router_ = router; - node_thread_.Start(); - node_thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&TestNode::ProcessMessages, base::Unretained(this))); - } - - void StopWhenIdle() { - base::AutoLock lock(lock_); - should_quit_ = true; - messages_available_event_.Signal(); - } - - void WakeUp() { messages_available_event_.Signal(); } - - int SendStringMessage(const PortRef& port, const std::string& s) { - size_t size = s.size() + 1; - ScopedMessage message = TestMessage::NewUserMessage(size, 0); - memcpy(message->mutable_payload_bytes(), s.data(), size); - return node_.SendMessage(port, std::move(message)); - } - - int SendStringMessageWithPort(const PortRef& port, - const std::string& s, - const PortName& sent_port_name) { - size_t size = s.size() + 1; - ScopedMessage message = TestMessage::NewUserMessage(size, 1); - memcpy(message->mutable_payload_bytes(), s.data(), size); - message->mutable_ports()[0] = sent_port_name; - return node_.SendMessage(port, std::move(message)); - } - - int SendStringMessageWithPort(const PortRef& port, - const std::string& s, - const PortRef& sent_port) { - return SendStringMessageWithPort(port, s, sent_port.name()); - } - - void set_drop_messages(bool value) { - base::AutoLock lock(lock_); - drop_messages_ = value; - } - - void set_save_messages(bool value) { - base::AutoLock lock(lock_); - save_messages_ = value; - } - - bool ReadMessage(const PortRef& port, ScopedMessage* message) { - return node_.GetMessage(port, message, nullptr) == OK && *message; - } - - bool GetSavedMessage(ScopedMessage* message) { - base::AutoLock lock(lock_); - if (saved_messages_.empty()) { - message->reset(); - return false; - } - std::swap(*message, saved_messages_.front()); - saved_messages_.pop(); - return true; - } - - void EnqueueMessage(ScopedMessage message) { - idle_event_.Reset(); - - // NOTE: This may be called from ForwardMessage and thus must not reenter - // |node_|. - base::AutoLock lock(lock_); - incoming_messages_.emplace(std::move(message)); - messages_available_event_.Signal(); - } - - void GenerateRandomPortName(PortName* port_name) override { - DCHECK(router_); - router_->GeneratePortName(port_name); - } - - void AllocMessage(size_t num_header_bytes, ScopedMessage* message) override { - message->reset(new TestMessage(num_header_bytes, 0, 0)); - } - - void ForwardMessage(const NodeName& node_name, - ScopedMessage message) override { - { - base::AutoLock lock(lock_); - if (drop_messages_) { - DVLOG(1) << "Dropping ForwardMessage from node " - << node_name_ << " to " << node_name; - - base::AutoUnlock unlock(lock_); - ClosePortsInMessage(message.get()); - return; - } - } - - DCHECK(router_); - DVLOG(1) << "ForwardMessage from node " - << node_name_ << " to " << node_name; - router_->ForwardMessage(this, node_name, std::move(message)); - } - - void BroadcastMessage(ScopedMessage message) override { - router_->BroadcastMessage(this, std::move(message)); - } - - void PortStatusChanged(const PortRef& port) override { - // The port may be closed, in which case we ignore the notification. - base::AutoLock lock(lock_); - if (!save_messages_) - return; - - for (;;) { - ScopedMessage message; - { - base::AutoUnlock unlock(lock_); - if (!ReadMessage(port, &message)) - break; - } - - saved_messages_.emplace(std::move(message)); - } - } - - void ClosePortsInMessage(Message* message) { - for (size_t i = 0; i < message->num_ports(); ++i) { - PortRef port; - ASSERT_EQ(OK, node_.GetPort(message->ports()[i], &port)); - EXPECT_EQ(OK, node_.ClosePort(port)); - } - } - - private: - void ProcessMessages() { - for (;;) { - messages_available_event_.Wait(); - - base::AutoLock lock(lock_); - - if (should_quit_) - return; - - dispatching_ = true; - while (!incoming_messages_.empty()) { - if (block_on_event_ && - GetEventHeader(*incoming_messages_.front())->type == - blocked_event_type_) { - blocked_ = true; - // Go idle if we hit a blocked event type. - break; - } else { - blocked_ = false; - } - ScopedMessage message = std::move(incoming_messages_.front()); - incoming_messages_.pop(); - - // NOTE: AcceptMessage() can re-enter this object to call any of the - // NodeDelegate interface methods. - base::AutoUnlock unlock(lock_); - node_.AcceptMessage(std::move(message)); - } - - dispatching_ = false; - started_ = true; - idle_event_.Signal(); - }; - } - - const NodeName node_name_; - Node node_; - MessageRouter* router_ = nullptr; - - base::Thread node_thread_; - base::WaitableEvent messages_available_event_; - base::WaitableEvent idle_event_; - - // Guards fields below. - base::Lock lock_; - bool started_ = false; - bool dispatching_ = false; - bool should_quit_ = false; - bool drop_messages_ = false; - bool save_messages_ = false; - bool blocked_ = false; - bool block_on_event_ = false; - EventType blocked_event_type_; - std::queue incoming_messages_; - std::queue saved_messages_; -}; - -class PortsTest : public testing::Test, public MessageRouter { - public: - void AddNode(TestNode* node) { - { - base::AutoLock lock(lock_); - nodes_[node->name()] = node; - } - node->Start(this); - } - - void RemoveNode(TestNode* node) { - { - base::AutoLock lock(lock_); - nodes_.erase(node->name()); - } - - for (const auto& entry : nodes_) - entry.second->node().LostConnectionToNode(node->name()); - } - - // Waits until all known Nodes are idle. Message forwarding and processing - // is handled in such a way that idleness is a stable state: once all nodes in - // the system are idle, they will remain idle until the test explicitly - // initiates some further event (e.g. sending a message, closing a port, or - // removing a Node). - void WaitForIdle() { - for (;;) { - base::AutoLock global_lock(global_lock_); - bool all_nodes_idle = true; - for (const auto& entry : nodes_) { - if (!entry.second->IsIdle()) - all_nodes_idle = false; - entry.second->WakeUp(); - } - if (all_nodes_idle) - return; - - // Wait for any Node to signal that it's idle. - base::AutoUnlock global_unlock(global_lock_); - std::vector events; - for (const auto& entry : nodes_) - events.push_back(&entry.second->idle_event()); - base::WaitableEvent::WaitMany(events.data(), events.size()); - } - } - - void CreatePortPair(TestNode* node0, - PortRef* port0, - TestNode* node1, - PortRef* port1) { - if (node0 == node1) { - EXPECT_EQ(OK, node0->node().CreatePortPair(port0, port1)); - } else { - EXPECT_EQ(OK, node0->node().CreateUninitializedPort(port0)); - EXPECT_EQ(OK, node1->node().CreateUninitializedPort(port1)); - EXPECT_EQ(OK, node0->node().InitializePort(*port0, node1->name(), - port1->name())); - EXPECT_EQ(OK, node1->node().InitializePort(*port1, node0->name(), - port0->name())); - } - } - - private: - // MessageRouter: - void GeneratePortName(PortName* name) override { - base::AutoLock lock(lock_); - name->v1 = next_port_id_++; - name->v2 = 0; - } - - void ForwardMessage(TestNode* from_node, - const NodeName& node_name, - ScopedMessage message) override { - base::AutoLock global_lock(global_lock_); - base::AutoLock lock(lock_); - // Drop messages from nodes that have been removed. - if (nodes_.find(from_node->name()) == nodes_.end()) { - from_node->ClosePortsInMessage(message.get()); - return; - } - - auto it = nodes_.find(node_name); - if (it == nodes_.end()) { - DVLOG(1) << "Node not found: " << node_name; - return; - } - - it->second->EnqueueMessage(std::move(message)); - } - - void BroadcastMessage(TestNode* from_node, ScopedMessage message) override { - base::AutoLock global_lock(global_lock_); - base::AutoLock lock(lock_); - - // Drop messages from nodes that have been removed. - if (nodes_.find(from_node->name()) == nodes_.end()) - return; - - for (const auto& entry : nodes_) { - TestNode* node = entry.second; - // Broadcast doesn't deliver to the local node. - if (node == from_node) - continue; - - // NOTE: We only need to support broadcast of events. Events have no - // payload or ports bytes. - ScopedMessage new_message( - new TestMessage(message->num_header_bytes(), 0, 0)); - memcpy(new_message->mutable_header_bytes(), message->header_bytes(), - message->num_header_bytes()); - node->EnqueueMessage(std::move(new_message)); - } - } - - base::MessageLoop message_loop_; - - // Acquired before any operation which makes a Node busy, and before testing - // if all nodes are idle. - base::Lock global_lock_; - - base::Lock lock_; - uint64_t next_port_id_ = 1; - std::map nodes_; -}; - -} // namespace - -TEST_F(PortsTest, Basic1) { - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - PortRef x0, x1; - CreatePortPair(&node0, &x0, &node1, &x1); - - PortRef a0, a1; - EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1)); - EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "hello", a1)); - EXPECT_EQ(OK, node0.node().ClosePort(a0)); - - EXPECT_EQ(OK, node0.node().ClosePort(x0)); - EXPECT_EQ(OK, node1.node().ClosePort(x1)); - - WaitForIdle(); - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, Basic2) { - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - PortRef x0, x1; - CreatePortPair(&node0, &x0, &node1, &x1); - - PortRef b0, b1; - EXPECT_EQ(OK, node0.node().CreatePortPair(&b0, &b1)); - EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "hello", b1)); - EXPECT_EQ(OK, node0.SendStringMessage(b0, "hello again")); - - EXPECT_EQ(OK, node0.node().ClosePort(b0)); - - EXPECT_EQ(OK, node0.node().ClosePort(x0)); - EXPECT_EQ(OK, node1.node().ClosePort(x1)); - - WaitForIdle(); - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, Basic3) { - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - PortRef x0, x1; - CreatePortPair(&node0, &x0, &node1, &x1); - - PortRef a0, a1; - EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1)); - - EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "hello", a1)); - EXPECT_EQ(OK, node0.SendStringMessage(a0, "hello again")); - - EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "foo", a0)); - - PortRef b0, b1; - EXPECT_EQ(OK, node0.node().CreatePortPair(&b0, &b1)); - EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "bar", b1)); - EXPECT_EQ(OK, node0.SendStringMessage(b0, "baz")); - - EXPECT_EQ(OK, node0.node().ClosePort(b0)); - - EXPECT_EQ(OK, node0.node().ClosePort(x0)); - EXPECT_EQ(OK, node1.node().ClosePort(x1)); - - WaitForIdle(); - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, LostConnectionToNode1) { - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - node1.set_drop_messages(true); - - PortRef x0, x1; - CreatePortPair(&node0, &x0, &node1, &x1); - - // Transfer a port to node1 and simulate a lost connection to node1. - - PortRef a0, a1; - EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1)); - EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "foo", a1)); - - WaitForIdle(); - - RemoveNode(&node1); - - WaitForIdle(); - - EXPECT_EQ(OK, node0.node().ClosePort(a0)); - EXPECT_EQ(OK, node0.node().ClosePort(x0)); - EXPECT_EQ(OK, node1.node().ClosePort(x1)); - - WaitForIdle(); - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, LostConnectionToNode2) { - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - PortRef x0, x1; - CreatePortPair(&node0, &x0, &node1, &x1); - - PortRef a0, a1; - EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1)); - EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "take a1", a1)); - - WaitForIdle(); - - node1.set_drop_messages(true); - - RemoveNode(&node1); - - WaitForIdle(); - - // a0 should have eventually detected peer closure after node loss. - ScopedMessage message; - EXPECT_EQ(ERROR_PORT_PEER_CLOSED, - node0.node().GetMessage(a0, &message, nullptr)); - EXPECT_FALSE(message); - - EXPECT_EQ(OK, node0.node().ClosePort(a0)); - - EXPECT_EQ(OK, node0.node().ClosePort(x0)); - - EXPECT_EQ(OK, node1.node().GetMessage(x1, &message, nullptr)); - EXPECT_TRUE(message); - node1.ClosePortsInMessage(message.get()); - - EXPECT_EQ(OK, node1.node().ClosePort(x1)); - - WaitForIdle(); - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, LostConnectionToNodeWithSecondaryProxy) { - // Tests that a proxy gets cleaned up when its indirect peer lives on a lost - // node. - - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - TestNode node2(2); - AddNode(&node2); - - // Create A-B spanning nodes 0 and 1 and C-D spanning 1 and 2. - PortRef A, B, C, D; - CreatePortPair(&node0, &A, &node1, &B); - CreatePortPair(&node1, &C, &node2, &D); - - // Create E-F and send F over A to node 1. - PortRef E, F; - EXPECT_EQ(OK, node0.node().CreatePortPair(&E, &F)); - EXPECT_EQ(OK, node0.SendStringMessageWithPort(A, ".", F)); - - WaitForIdle(); - - ScopedMessage message; - ASSERT_TRUE(node1.ReadMessage(B, &message)); - ASSERT_EQ(1u, message->num_ports()); - - EXPECT_EQ(OK, node1.node().GetPort(message->ports()[0], &F)); - - // Send F over C to node 2 and then simulate node 2 loss from node 1. Node 1 - // will trivially become aware of the loss, and this test verifies that the - // port A on node 0 will eventually also become aware of it. - - // Make sure node2 stops processing events when it encounters an ObserveProxy. - node2.BlockOnEvent(EventType::kObserveProxy); - - EXPECT_EQ(OK, node1.SendStringMessageWithPort(C, ".", F)); - WaitForIdle(); - - // Simulate node 1 and 2 disconnecting. - EXPECT_EQ(OK, node1.node().LostConnectionToNode(node2.name())); - - // Let node2 continue processing events and wait for everyone to go idle. - node2.Unblock(); - WaitForIdle(); - - // Port F should be gone. - EXPECT_EQ(ERROR_PORT_UNKNOWN, node1.node().GetPort(F.name(), &F)); - - // Port E should have detected peer closure despite the fact that there is - // no longer a continuous route from F to E over which the event could travel. - PortStatus status; - EXPECT_EQ(OK, node0.node().GetStatus(E, &status)); - EXPECT_TRUE(status.peer_closed); - - EXPECT_EQ(OK, node0.node().ClosePort(A)); - EXPECT_EQ(OK, node1.node().ClosePort(B)); - EXPECT_EQ(OK, node1.node().ClosePort(C)); - EXPECT_EQ(OK, node0.node().ClosePort(E)); - - WaitForIdle(); - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, LostConnectionToNodeWithLocalProxy) { - // Tests that a proxy gets cleaned up when its direct peer lives on a lost - // node and it's predecessor lives on the same node. - - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - PortRef A, B; - CreatePortPair(&node0, &A, &node1, &B); - - PortRef C, D; - EXPECT_EQ(OK, node0.node().CreatePortPair(&C, &D)); - - // Send D but block node0 on an ObserveProxy event. - node0.BlockOnEvent(EventType::kObserveProxy); - EXPECT_EQ(OK, node0.SendStringMessageWithPort(A, ".", D)); - - // node0 won't collapse the proxy but node1 will receive the message before - // going idle. - WaitForIdle(); - - ScopedMessage message; - ASSERT_TRUE(node1.ReadMessage(B, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef E; - EXPECT_EQ(OK, node1.node().GetPort(message->ports()[0], &E)); - - RemoveNode(&node1); - - node0.Unblock(); - WaitForIdle(); - - // Port C should have detected peer closure. - PortStatus status; - EXPECT_EQ(OK, node0.node().GetStatus(C, &status)); - EXPECT_TRUE(status.peer_closed); - - EXPECT_EQ(OK, node0.node().ClosePort(A)); - EXPECT_EQ(OK, node1.node().ClosePort(B)); - EXPECT_EQ(OK, node0.node().ClosePort(C)); - EXPECT_EQ(OK, node1.node().ClosePort(E)); - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, GetMessage1) { - TestNode node(0); - AddNode(&node); - - PortRef a0, a1; - EXPECT_EQ(OK, node.node().CreatePortPair(&a0, &a1)); - - ScopedMessage message; - EXPECT_EQ(OK, node.node().GetMessage(a0, &message, nullptr)); - EXPECT_FALSE(message); - - EXPECT_EQ(OK, node.node().ClosePort(a1)); - - WaitForIdle(); - - EXPECT_EQ(ERROR_PORT_PEER_CLOSED, - node.node().GetMessage(a0, &message, nullptr)); - EXPECT_FALSE(message); - - EXPECT_EQ(OK, node.node().ClosePort(a0)); - - WaitForIdle(); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, GetMessage2) { - TestNode node(0); - AddNode(&node); - - PortRef a0, a1; - EXPECT_EQ(OK, node.node().CreatePortPair(&a0, &a1)); - - EXPECT_EQ(OK, node.SendStringMessage(a1, "1")); - - ScopedMessage message; - EXPECT_EQ(OK, node.node().GetMessage(a0, &message, nullptr)); - - ASSERT_TRUE(message); - EXPECT_TRUE(MessageEquals(message, "1")); - - EXPECT_EQ(OK, node.node().ClosePort(a0)); - EXPECT_EQ(OK, node.node().ClosePort(a1)); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, GetMessage3) { - TestNode node(0); - AddNode(&node); - - PortRef a0, a1; - EXPECT_EQ(OK, node.node().CreatePortPair(&a0, &a1)); - - const char* kStrings[] = { - "1", - "2", - "3" - }; - - for (size_t i = 0; i < sizeof(kStrings)/sizeof(kStrings[0]); ++i) - EXPECT_EQ(OK, node.SendStringMessage(a1, kStrings[i])); - - ScopedMessage message; - for (size_t i = 0; i < sizeof(kStrings)/sizeof(kStrings[0]); ++i) { - EXPECT_EQ(OK, node.node().GetMessage(a0, &message, nullptr)); - ASSERT_TRUE(message); - EXPECT_TRUE(MessageEquals(message, kStrings[i])); - } - - EXPECT_EQ(OK, node.node().ClosePort(a0)); - EXPECT_EQ(OK, node.node().ClosePort(a1)); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, Delegation1) { - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - PortRef x0, x1; - CreatePortPair(&node0, &x0, &node1, &x1); - - // In this test, we send a message to a port that has been moved. - - PortRef a0, a1; - EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1)); - EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "a1", a1)); - WaitForIdle(); - - ScopedMessage message; - ASSERT_TRUE(node1.ReadMessage(x1, &message)); - ASSERT_EQ(1u, message->num_ports()); - EXPECT_TRUE(MessageEquals(message, "a1")); - - // This is "a1" from the point of view of node1. - PortName a2_name = message->ports()[0]; - EXPECT_EQ(OK, node1.SendStringMessageWithPort(x1, "a2", a2_name)); - EXPECT_EQ(OK, node0.SendStringMessage(a0, "hello")); - - WaitForIdle(); - - ASSERT_TRUE(node0.ReadMessage(x0, &message)); - ASSERT_EQ(1u, message->num_ports()); - EXPECT_TRUE(MessageEquals(message, "a2")); - - // This is "a2" from the point of view of node1. - PortName a3_name = message->ports()[0]; - - PortRef a3; - EXPECT_EQ(OK, node0.node().GetPort(a3_name, &a3)); - - ASSERT_TRUE(node0.ReadMessage(a3, &message)); - EXPECT_EQ(0u, message->num_ports()); - EXPECT_TRUE(MessageEquals(message, "hello")); - - EXPECT_EQ(OK, node0.node().ClosePort(a0)); - EXPECT_EQ(OK, node0.node().ClosePort(a3)); - - EXPECT_EQ(OK, node0.node().ClosePort(x0)); - EXPECT_EQ(OK, node1.node().ClosePort(x1)); - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, Delegation2) { - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - for (int i = 0; i < 100; ++i) { - // Setup pipe a<->b between node0 and node1. - PortRef A, B; - CreatePortPair(&node0, &A, &node1, &B); - - PortRef C, D; - EXPECT_EQ(OK, node0.node().CreatePortPair(&C, &D)); - - PortRef E, F; - EXPECT_EQ(OK, node0.node().CreatePortPair(&E, &F)); - - node1.set_save_messages(true); - - // Pass D over A to B. - EXPECT_EQ(OK, node0.SendStringMessageWithPort(A, "1", D)); - - // Pass F over C to D. - EXPECT_EQ(OK, node0.SendStringMessageWithPort(C, "1", F)); - - // This message should find its way to node1. - EXPECT_EQ(OK, node0.SendStringMessage(E, "hello")); - - WaitForIdle(); - - EXPECT_EQ(OK, node0.node().ClosePort(C)); - EXPECT_EQ(OK, node0.node().ClosePort(E)); - - EXPECT_EQ(OK, node0.node().ClosePort(A)); - EXPECT_EQ(OK, node1.node().ClosePort(B)); - - bool got_hello = false; - ScopedMessage message; - while (node1.GetSavedMessage(&message)) { - node1.ClosePortsInMessage(message.get()); - if (MessageEquals(message, "hello")) { - got_hello = true; - break; - } - } - - EXPECT_TRUE(got_hello); - - WaitForIdle(); // Because closing ports may have generated tasks. - } - - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, SendUninitialized) { - TestNode node(0); - AddNode(&node); - - PortRef x0; - EXPECT_EQ(OK, node.node().CreateUninitializedPort(&x0)); - EXPECT_EQ(ERROR_PORT_STATE_UNEXPECTED, node.SendStringMessage(x0, "oops")); - EXPECT_EQ(OK, node.node().ClosePort(x0)); - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, SendFailure) { - TestNode node(0); - AddNode(&node); - - node.set_save_messages(true); - - PortRef A, B; - EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B)); - - // Try to send A over itself. - - EXPECT_EQ(ERROR_PORT_CANNOT_SEND_SELF, - node.SendStringMessageWithPort(A, "oops", A)); - - // Try to send B over A. - - EXPECT_EQ(ERROR_PORT_CANNOT_SEND_PEER, - node.SendStringMessageWithPort(A, "nope", B)); - - // B should be closed immediately. - EXPECT_EQ(ERROR_PORT_UNKNOWN, node.node().GetPort(B.name(), &B)); - - WaitForIdle(); - - // There should have been no messages accepted. - ScopedMessage message; - EXPECT_FALSE(node.GetSavedMessage(&message)); - - EXPECT_EQ(OK, node.node().ClosePort(A)); - - WaitForIdle(); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, DontLeakUnreceivedPorts) { - TestNode node(0); - AddNode(&node); - - PortRef A, B, C, D; - EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node.node().CreatePortPair(&C, &D)); - - EXPECT_EQ(OK, node.SendStringMessageWithPort(A, "foo", D)); - - EXPECT_EQ(OK, node.node().ClosePort(C)); - EXPECT_EQ(OK, node.node().ClosePort(A)); - EXPECT_EQ(OK, node.node().ClosePort(B)); - - WaitForIdle(); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, AllowShutdownWithLocalPortsOpen) { - TestNode node(0); - AddNode(&node); - - PortRef A, B, C, D; - EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node.node().CreatePortPair(&C, &D)); - - EXPECT_EQ(OK, node.SendStringMessageWithPort(A, "foo", D)); - - ScopedMessage message; - EXPECT_TRUE(node.ReadMessage(B, &message)); - ASSERT_EQ(1u, message->num_ports()); - EXPECT_TRUE(MessageEquals(message, "foo")); - PortRef E; - ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &E)); - - EXPECT_TRUE( - node.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)); - - WaitForIdle(); - - EXPECT_TRUE( - node.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)); - EXPECT_FALSE(node.node().CanShutdownCleanly()); - - EXPECT_EQ(OK, node.node().ClosePort(A)); - EXPECT_EQ(OK, node.node().ClosePort(B)); - EXPECT_EQ(OK, node.node().ClosePort(C)); - EXPECT_EQ(OK, node.node().ClosePort(E)); - - WaitForIdle(); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, ProxyCollapse1) { - TestNode node(0); - AddNode(&node); - - PortRef A, B; - EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B)); - - PortRef X, Y; - EXPECT_EQ(OK, node.node().CreatePortPair(&X, &Y)); - - ScopedMessage message; - - // Send B and receive it as C. - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", B)); - ASSERT_TRUE(node.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef C; - ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &C)); - - // Send C and receive it as D. - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", C)); - ASSERT_TRUE(node.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef D; - ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &D)); - - // Send D and receive it as E. - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", D)); - ASSERT_TRUE(node.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef E; - ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &E)); - - EXPECT_EQ(OK, node.node().ClosePort(X)); - EXPECT_EQ(OK, node.node().ClosePort(Y)); - - EXPECT_EQ(OK, node.node().ClosePort(A)); - EXPECT_EQ(OK, node.node().ClosePort(E)); - - // The node should not idle until all proxies are collapsed. - WaitForIdle(); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, ProxyCollapse2) { - TestNode node(0); - AddNode(&node); - - PortRef A, B; - EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B)); - - PortRef X, Y; - EXPECT_EQ(OK, node.node().CreatePortPair(&X, &Y)); - - ScopedMessage message; - - // Send B and A to create proxies in each direction. - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", B)); - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", A)); - - EXPECT_EQ(OK, node.node().ClosePort(X)); - EXPECT_EQ(OK, node.node().ClosePort(Y)); - - // At this point we have a scenario with: - // - // D -> [B] -> C -> [A] - // - // Ensure that the proxies can collapse. The sent ports will be closed - // eventually as a result of Y's closure. - - WaitForIdle(); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, SendWithClosedPeer) { - // This tests that if a port is sent when its peer is already known to be - // closed, the newly created port will be aware of that peer closure, and the - // proxy will eventually collapse. - - TestNode node(0); - AddNode(&node); - - // Send a message from A to B, then close A. - PortRef A, B; - EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node.SendStringMessage(A, "hey")); - EXPECT_EQ(OK, node.node().ClosePort(A)); - - // Now send B over X-Y as new port C. - PortRef X, Y; - EXPECT_EQ(OK, node.node().CreatePortPair(&X, &Y)); - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", B)); - ScopedMessage message; - ASSERT_TRUE(node.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef C; - ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &C)); - - EXPECT_EQ(OK, node.node().ClosePort(X)); - EXPECT_EQ(OK, node.node().ClosePort(Y)); - - WaitForIdle(); - - // C should have received the message originally sent to B, and it should also - // be aware of A's closure. - - ASSERT_TRUE(node.ReadMessage(C, &message)); - EXPECT_TRUE(MessageEquals(message, "hey")); - - PortStatus status; - EXPECT_EQ(OK, node.node().GetStatus(C, &status)); - EXPECT_FALSE(status.receiving_messages); - EXPECT_FALSE(status.has_messages); - EXPECT_TRUE(status.peer_closed); - - node.node().ClosePort(C); - - WaitForIdle(); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, SendWithClosedPeerSent) { - // This tests that if a port is closed while some number of proxies are still - // routing messages (directly or indirectly) to it, that the peer port is - // eventually notified of the closure, and the dead-end proxies will - // eventually be removed. - - TestNode node(0); - AddNode(&node); - - PortRef X, Y; - EXPECT_EQ(OK, node.node().CreatePortPair(&X, &Y)); - - PortRef A, B; - EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B)); - - ScopedMessage message; - - // Send A as new port C. - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", A)); - - ASSERT_TRUE(node.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef C; - ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &C)); - - // Send C as new port D. - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", C)); - - ASSERT_TRUE(node.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef D; - ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &D)); - - // Send a message to B through D, then close D. - EXPECT_EQ(OK, node.SendStringMessage(D, "hey")); - EXPECT_EQ(OK, node.node().ClosePort(D)); - - // Now send B as new port E. - - EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", B)); - EXPECT_EQ(OK, node.node().ClosePort(X)); - - ASSERT_TRUE(node.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef E; - ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &E)); - - EXPECT_EQ(OK, node.node().ClosePort(Y)); - - WaitForIdle(); - - // E should receive the message originally sent to B, and it should also be - // aware of D's closure. - - ASSERT_TRUE(node.ReadMessage(E, &message)); - EXPECT_TRUE(MessageEquals(message, "hey")); - - PortStatus status; - EXPECT_EQ(OK, node.node().GetStatus(E, &status)); - EXPECT_FALSE(status.receiving_messages); - EXPECT_FALSE(status.has_messages); - EXPECT_TRUE(status.peer_closed); - - EXPECT_EQ(OK, node.node().ClosePort(E)); - - WaitForIdle(); - - EXPECT_TRUE(node.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, MergePorts) { - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - // Setup two independent port pairs, A-B on node0 and C-D on node1. - PortRef A, B, C, D; - EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D)); - - // Write a message on A. - EXPECT_EQ(OK, node0.SendStringMessage(A, "hey")); - - // Initiate a merge between B and C. - EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name())); - - WaitForIdle(); - - // Expect all proxies to be gone once idle. - EXPECT_TRUE( - node0.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)); - EXPECT_TRUE( - node1.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)); - - // Expect D to have received the message sent on A. - ScopedMessage message; - ASSERT_TRUE(node1.ReadMessage(D, &message)); - EXPECT_TRUE(MessageEquals(message, "hey")); - - EXPECT_EQ(OK, node0.node().ClosePort(A)); - EXPECT_EQ(OK, node1.node().ClosePort(D)); - - // No more ports should be open. - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, MergePortWithClosedPeer1) { - // This tests that the right thing happens when initiating a merge on a port - // whose peer has already been closed. - - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - // Setup two independent port pairs, A-B on node0 and C-D on node1. - PortRef A, B, C, D; - EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D)); - - // Write a message on A. - EXPECT_EQ(OK, node0.SendStringMessage(A, "hey")); - - // Close A. - EXPECT_EQ(OK, node0.node().ClosePort(A)); - - // Initiate a merge between B and C. - EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name())); - - WaitForIdle(); - - // Expect all proxies to be gone once idle. node0 should have no ports since - // A was explicitly closed. - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE( - node1.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)); - - // Expect D to have received the message sent on A. - ScopedMessage message; - ASSERT_TRUE(node1.ReadMessage(D, &message)); - EXPECT_TRUE(MessageEquals(message, "hey")); - - EXPECT_EQ(OK, node1.node().ClosePort(D)); - - // No more ports should be open. - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, MergePortWithClosedPeer2) { - // This tests that the right thing happens when merging into a port whose peer - // has already been closed. - - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - // Setup two independent port pairs, A-B on node0 and C-D on node1. - PortRef A, B, C, D; - EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D)); - - // Write a message on D and close it. - EXPECT_EQ(OK, node0.SendStringMessage(D, "hey")); - EXPECT_EQ(OK, node1.node().ClosePort(D)); - - // Initiate a merge between B and C. - EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name())); - - WaitForIdle(); - - // Expect all proxies to be gone once idle. node1 should have no ports since - // D was explicitly closed. - EXPECT_TRUE( - node0.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); - - // Expect A to have received the message sent on D. - ScopedMessage message; - ASSERT_TRUE(node0.ReadMessage(A, &message)); - EXPECT_TRUE(MessageEquals(message, "hey")); - - EXPECT_EQ(OK, node0.node().ClosePort(A)); - - // No more ports should be open. - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, MergePortsWithClosedPeers) { - // This tests that no residual ports are left behind if two ports are merged - // when both of their peers have been closed. - - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - // Setup two independent port pairs, A-B on node0 and C-D on node1. - PortRef A, B, C, D; - EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D)); - - // Close A and D. - EXPECT_EQ(OK, node0.node().ClosePort(A)); - EXPECT_EQ(OK, node1.node().ClosePort(D)); - - WaitForIdle(); - - // Initiate a merge between B and C. - EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name())); - - WaitForIdle(); - - // Expect everything to have gone away. - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, MergePortsWithMovedPeers) { - // This tests that ports can be merged successfully even if their peers are - // moved around. - - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - // Setup two independent port pairs, A-B on node0 and C-D on node1. - PortRef A, B, C, D; - EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D)); - - // Set up another pair X-Y for moving ports on node0. - PortRef X, Y; - EXPECT_EQ(OK, node0.node().CreatePortPair(&X, &Y)); - - ScopedMessage message; - - // Move A to new port E. - EXPECT_EQ(OK, node0.SendStringMessageWithPort(X, "foo", A)); - ASSERT_TRUE(node0.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef E; - ASSERT_EQ(OK, node0.node().GetPort(message->ports()[0], &E)); - - EXPECT_EQ(OK, node0.node().ClosePort(X)); - EXPECT_EQ(OK, node0.node().ClosePort(Y)); - - // Write messages on E and D. - EXPECT_EQ(OK, node0.SendStringMessage(E, "hey")); - EXPECT_EQ(OK, node1.SendStringMessage(D, "hi")); - - // Initiate a merge between B and C. - EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name())); - - WaitForIdle(); - - // Expect to receive D's message on E and E's message on D. - ASSERT_TRUE(node0.ReadMessage(E, &message)); - EXPECT_TRUE(MessageEquals(message, "hi")); - ASSERT_TRUE(node1.ReadMessage(D, &message)); - EXPECT_TRUE(MessageEquals(message, "hey")); - - // Close E and D. - EXPECT_EQ(OK, node0.node().ClosePort(E)); - EXPECT_EQ(OK, node1.node().ClosePort(D)); - - WaitForIdle(); - - // Expect everything to have gone away. - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -TEST_F(PortsTest, MergePortsFailsGracefully) { - // This tests that the system remains in a well-defined state if something - // goes wrong during port merge. - - TestNode node0(0); - AddNode(&node0); - - TestNode node1(1); - AddNode(&node1); - - // Setup two independent port pairs, A-B on node0 and C-D on node1. - PortRef A, B, C, D; - EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B)); - EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D)); - - ScopedMessage message; - PortRef X, Y; - EXPECT_EQ(OK, node1.node().CreatePortPair(&X, &Y)); - - // Block the merge from proceeding until we can do something stupid with port - // C. This avoids the test logic racing with async merge logic. - node1.BlockOnEvent(EventType::kMergePort); - - // Initiate the merge between B and C. - EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name())); - - // Move C to a new port E. This is not a sane use of Node's public API but - // is still hypothetically possible. It allows us to force a merge failure - // because C will be in an invalid state by the term the merge is processed. - // As a result, B should be closed. - EXPECT_EQ(OK, node1.SendStringMessageWithPort(X, "foo", C)); - - node1.Unblock(); - - ASSERT_TRUE(node1.ReadMessage(Y, &message)); - ASSERT_EQ(1u, message->num_ports()); - PortRef E; - ASSERT_EQ(OK, node1.node().GetPort(message->ports()[0], &E)); - - EXPECT_EQ(OK, node1.node().ClosePort(X)); - EXPECT_EQ(OK, node1.node().ClosePort(Y)); - - WaitForIdle(); - - // C goes away as a result of normal proxy removal. B should have been closed - // cleanly by the failed MergePorts. - EXPECT_EQ(ERROR_PORT_UNKNOWN, node1.node().GetPort(C.name(), &C)); - EXPECT_EQ(ERROR_PORT_UNKNOWN, node0.node().GetPort(B.name(), &B)); - - // Close A, D, and E. - EXPECT_EQ(OK, node0.node().ClosePort(A)); - EXPECT_EQ(OK, node1.node().ClosePort(D)); - EXPECT_EQ(OK, node1.node().ClosePort(E)); - - WaitForIdle(); - - // Expect everything to have gone away. - EXPECT_TRUE(node0.node().CanShutdownCleanly()); - EXPECT_TRUE(node1.node().CanShutdownCleanly()); -} - -} // namespace test -} // namespace ports -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports/user_data.h b/mojo/edk/system/ports/user_data.h deleted file mode 100644 index 73e7d17..0000000 --- a/mojo/edk/system/ports/user_data.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_USER_DATA_H_ -#define MOJO_EDK_SYSTEM_PORTS_USER_DATA_H_ - -#include "base/memory/ref_counted.h" - -namespace mojo { -namespace edk { -namespace ports { - -class UserData : public base::RefCountedThreadSafe { - protected: - friend class base::RefCountedThreadSafe; - - virtual ~UserData() {} -}; - -} // namespace ports -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_USER_DATA_H_ diff --git a/mojo/edk/system/ports_message.cc b/mojo/edk/system/ports_message.cc deleted file mode 100644 index 5f3e8c0..0000000 --- a/mojo/edk/system/ports_message.cc +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/ports_message.h" - -#include "base/memory/ptr_util.h" -#include "mojo/edk/system/node_channel.h" - -namespace mojo { -namespace edk { - -// static -std::unique_ptr PortsMessage::NewUserMessage( - size_t num_payload_bytes, - size_t num_ports, - size_t num_handles) { - return base::WrapUnique( - new PortsMessage(num_payload_bytes, num_ports, num_handles)); -} - -PortsMessage::~PortsMessage() {} - -PortsMessage::PortsMessage(size_t num_payload_bytes, - size_t num_ports, - size_t num_handles) - : ports::Message(num_payload_bytes, num_ports) { - size_t size = num_header_bytes_ + num_ports_bytes_ + num_payload_bytes; - void* ptr; - channel_message_ = NodeChannel::CreatePortsMessage(size, &ptr, num_handles); - InitializeUserMessageHeader(ptr); -} - -PortsMessage::PortsMessage(size_t num_header_bytes, - size_t num_payload_bytes, - size_t num_ports_bytes, - Channel::MessagePtr channel_message) - : ports::Message(num_header_bytes, - num_payload_bytes, - num_ports_bytes) { - if (channel_message) { - channel_message_ = std::move(channel_message); - void* data; - size_t num_data_bytes; - NodeChannel::GetPortsMessageData(channel_message_.get(), &data, - &num_data_bytes); - start_ = static_cast(data); - } else { - // TODO: Clean this up. In practice this branch of the constructor should - // only be reached from Node-internal calls to AllocMessage, which never - // carry ports or non-header bytes. - CHECK_EQ(num_payload_bytes, 0u); - CHECK_EQ(num_ports_bytes, 0u); - void* ptr; - channel_message_ = - NodeChannel::CreatePortsMessage(num_header_bytes, &ptr, 0); - start_ = static_cast(ptr); - } -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/ports_message.h b/mojo/edk/system/ports_message.h deleted file mode 100644 index 542b981..0000000 --- a/mojo/edk/system/ports_message.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_PORTS_MESSAGE_H__ -#define MOJO_EDK_SYSTEM_PORTS_MESSAGE_H__ - -#include -#include - -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/system/channel.h" -#include "mojo/edk/system/ports/message.h" -#include "mojo/edk/system/ports/name.h" - -namespace mojo { -namespace edk { - -class NodeController; - -class PortsMessage : public ports::Message { - public: - static std::unique_ptr NewUserMessage(size_t num_payload_bytes, - size_t num_ports, - size_t num_handles); - - ~PortsMessage() override; - - size_t num_handles() const { return channel_message_->num_handles(); } - bool has_handles() const { return channel_message_->has_handles(); } - - void SetHandles(ScopedPlatformHandleVectorPtr handles) { - channel_message_->SetHandles(std::move(handles)); - } - - ScopedPlatformHandleVectorPtr TakeHandles() { - return channel_message_->TakeHandles(); - } - - Channel::MessagePtr TakeChannelMessage() { - return std::move(channel_message_); - } - - void set_source_node(const ports::NodeName& name) { source_node_ = name; } - const ports::NodeName& source_node() const { return source_node_; } - - private: - friend class NodeController; - - // Construct a new user PortsMessage backed by a new Channel::Message. - PortsMessage(size_t num_payload_bytes, size_t num_ports, size_t num_handles); - - // Construct a new PortsMessage backed by a Channel::Message. If - // |channel_message| is null, a new one is allocated internally. - PortsMessage(size_t num_header_bytes, - size_t num_payload_bytes, - size_t num_ports_bytes, - Channel::MessagePtr channel_message); - - Channel::MessagePtr channel_message_; - - // The node name from which this message was received, if known. - ports::NodeName source_node_ = ports::kInvalidNodeName; -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_PORTS_MESSAGE_H__ diff --git a/mojo/edk/system/request_context.cc b/mojo/edk/system/request_context.cc deleted file mode 100644 index 5de65d7..0000000 --- a/mojo/edk/system/request_context.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/request_context.h" - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/threading/thread_local.h" - -namespace mojo { -namespace edk { - -namespace { - -base::LazyInstance>::Leaky - g_current_context = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -RequestContext::RequestContext() : RequestContext(Source::LOCAL_API_CALL) {} - -RequestContext::RequestContext(Source source) - : source_(source), tls_context_(g_current_context.Pointer()) { - // We allow nested RequestContexts to exist as long as they aren't actually - // used for anything. - if (!tls_context_->Get()) - tls_context_->Set(this); -} - -RequestContext::~RequestContext() { - if (IsCurrent()) { - // NOTE: Callbacks invoked by this destructor are allowed to initiate new - // EDK requests on this thread, so we need to reset the thread-local context - // pointer before calling them. We persist the original notification source - // since we're starting over at the bottom of the stack. - tls_context_->Set(nullptr); - - MojoWatcherNotificationFlags flags = MOJO_WATCHER_NOTIFICATION_FLAG_NONE; - if (source_ == Source::SYSTEM) - flags |= MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM; - - // We send all cancellation notifications first. This is necessary because - // it's possible that cancelled watches have other pending notifications - // attached to this RequestContext. - // - // From the application's perspective the watch is cancelled as soon as this - // notification is received, and dispatching the cancellation notification - // updates some internal Watch state to ensure no further notifications - // fire. Because notifications on a single Watch are mutually exclusive, - // this is sufficient to guarantee that MOJO_RESULT_CANCELLED is the last - // notification received; which is the guarantee the API makes. - for (const scoped_refptr& watch : - watch_cancel_finalizers_.container()) { - static const HandleSignalsState closed_state = {0, 0}; - - // Establish a new RequestContext to capture and run any new notifications - // triggered by the callback invocation. - RequestContext inner_context(source_); - watch->InvokeCallback(MOJO_RESULT_CANCELLED, closed_state, flags); - } - - for (const WatchNotifyFinalizer& watch : - watch_notify_finalizers_.container()) { - RequestContext inner_context(source_); - watch.watch->InvokeCallback(watch.result, watch.state, flags); - } - } else { - // It should be impossible for nested contexts to have finalizers. - DCHECK(watch_notify_finalizers_.container().empty()); - DCHECK(watch_cancel_finalizers_.container().empty()); - } -} - -// static -RequestContext* RequestContext::current() { - DCHECK(g_current_context.Pointer()->Get()); - return g_current_context.Pointer()->Get(); -} - -void RequestContext::AddWatchNotifyFinalizer(scoped_refptr watch, - MojoResult result, - const HandleSignalsState& state) { - DCHECK(IsCurrent()); - watch_notify_finalizers_->push_back( - WatchNotifyFinalizer(std::move(watch), result, state)); -} - -void RequestContext::AddWatchCancelFinalizer(scoped_refptr watch) { - DCHECK(IsCurrent()); - watch_cancel_finalizers_->push_back(std::move(watch)); -} - -bool RequestContext::IsCurrent() const { - return tls_context_->Get() == this; -} - -RequestContext::WatchNotifyFinalizer::WatchNotifyFinalizer( - scoped_refptr watch, - MojoResult result, - const HandleSignalsState& state) - : watch(std::move(watch)), result(result), state(state) {} - -RequestContext::WatchNotifyFinalizer::WatchNotifyFinalizer( - const WatchNotifyFinalizer& other) = default; - -RequestContext::WatchNotifyFinalizer::~WatchNotifyFinalizer() {} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/request_context.h b/mojo/edk/system/request_context.h deleted file mode 100644 index d1f43bd..0000000 --- a/mojo/edk/system/request_context.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_REQUEST_CONTEXT_H_ -#define MOJO_EDK_SYSTEM_REQUEST_CONTEXT_H_ - -#include "base/containers/stack_container.h" -#include "base/macros.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/edk/system/watch.h" - -namespace base { -template class ThreadLocalPointer; -} - -namespace mojo { -namespace edk { - -// A RequestContext is a thread-local object which exists for the duration of -// a single system API call. It is constructed immediately upon EDK entry and -// destructed immediately before returning to the caller, after any internal -// locks have been released. -// -// NOTE: It is legal to construct a RequestContext while another one already -// exists on the current thread, but it is not safe to use the nested context -// for any reason. Therefore it is important to always use -// |RequestContext::current()| rather than referring to any local instance -// directly. -class MOJO_SYSTEM_IMPL_EXPORT RequestContext { - public: - // Identifies the source of the current stack frame's RequestContext. - enum class Source { - LOCAL_API_CALL, - SYSTEM, - }; - - // Constructs a RequestContext with a LOCAL_API_CALL Source. - RequestContext(); - - explicit RequestContext(Source source); - ~RequestContext(); - - // Returns the current thread-local RequestContext. - static RequestContext* current(); - - Source source() const { return source_; } - - // Adds a finalizer to this RequestContext corresponding to a watch callback - // which should be triggered in response to some handle state change. If - // the WatcherDispatcher hasn't been closed by the time this RequestContext is - // destroyed, its WatchCallback will be invoked with |result| and |state| - // arguments. - void AddWatchNotifyFinalizer(scoped_refptr watch, - MojoResult result, - const HandleSignalsState& state); - - // Adds a finalizer to this RequestContext corresponding to a watch callback - // which should be triggered to notify of watch cancellation. This appends to - // a separate finalizer list from AddWatchNotifyFinalizer, as pending - // cancellations must always preempt other pending notifications. - void AddWatchCancelFinalizer(scoped_refptr watch); - - private: - // Is this request context the current one? - bool IsCurrent() const; - - struct WatchNotifyFinalizer { - WatchNotifyFinalizer(scoped_refptr watch, - MojoResult result, - const HandleSignalsState& state); - WatchNotifyFinalizer(const WatchNotifyFinalizer& other); - ~WatchNotifyFinalizer(); - - scoped_refptr watch; - MojoResult result; - HandleSignalsState state; - }; - - // NOTE: This upper bound was chosen somewhat arbitrarily after observing some - // rare worst-case behavior in Chrome. A vast majority of RequestContexts only - // ever accumulate 0 or 1 finalizers. - static const size_t kStaticWatchFinalizersCapacity = 8; - - using WatchNotifyFinalizerList = - base::StackVector; - using WatchCancelFinalizerList = - base::StackVector, kStaticWatchFinalizersCapacity>; - - const Source source_; - - WatchNotifyFinalizerList watch_notify_finalizers_; - WatchCancelFinalizerList watch_cancel_finalizers_; - - // Pointer to the TLS context. Although this can easily be accessed via the - // global LazyInstance, accessing a LazyInstance has a large cost relative to - // the rest of this class and its usages. - base::ThreadLocalPointer* tls_context_; - - DISALLOW_COPY_AND_ASSIGN(RequestContext); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_REQUEST_CONTEXT_H_ diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc deleted file mode 100644 index df39105..0000000 --- a/mojo/edk/system/shared_buffer_dispatcher.cc +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/shared_buffer_dispatcher.h" - -#include -#include - -#include -#include -#include - -#include "base/logging.h" -#include "mojo/edk/embedder/embedder_internal.h" -#include "mojo/edk/system/configuration.h" -#include "mojo/edk/system/node_controller.h" -#include "mojo/edk/system/options_validation.h" - -namespace mojo { -namespace edk { - -namespace { - -#pragma pack(push, 1) - -struct SerializedState { - uint64_t num_bytes; - uint32_t flags; - uint32_t padding; -}; - -const uint32_t kSerializedStateFlagsReadOnly = 1 << 0; - -#pragma pack(pop) - -static_assert(sizeof(SerializedState) % 8 == 0, - "Invalid SerializedState size."); - -} // namespace - -// static -const MojoCreateSharedBufferOptions - SharedBufferDispatcher::kDefaultCreateOptions = { - static_cast(sizeof(MojoCreateSharedBufferOptions)), - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; - -// static -MojoResult SharedBufferDispatcher::ValidateCreateOptions( - const MojoCreateSharedBufferOptions* in_options, - MojoCreateSharedBufferOptions* out_options) { - const MojoCreateSharedBufferOptionsFlags kKnownFlags = - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; - - *out_options = kDefaultCreateOptions; - if (!in_options) - return MOJO_RESULT_OK; - - UserOptionsReader reader(in_options); - if (!reader.is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateSharedBufferOptions, flags, reader)) - return MOJO_RESULT_OK; - if ((reader.options().flags & ~kKnownFlags)) - return MOJO_RESULT_UNIMPLEMENTED; - out_options->flags = reader.options().flags; - - // Checks for fields beyond |flags|: - - // (Nothing here yet.) - - return MOJO_RESULT_OK; -} - -// static -MojoResult SharedBufferDispatcher::Create( - const MojoCreateSharedBufferOptions& /*validated_options*/, - NodeController* node_controller, - uint64_t num_bytes, - scoped_refptr* result) { - if (!num_bytes) - return MOJO_RESULT_INVALID_ARGUMENT; - if (num_bytes > GetConfiguration().max_shared_memory_num_bytes) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - scoped_refptr shared_buffer; - if (node_controller) { - shared_buffer = - node_controller->CreateSharedBuffer(static_cast(num_bytes)); - } else { - shared_buffer = - PlatformSharedBuffer::Create(static_cast(num_bytes)); - } - if (!shared_buffer) - return MOJO_RESULT_RESOURCE_EXHAUSTED; - - *result = CreateInternal(std::move(shared_buffer)); - return MOJO_RESULT_OK; -} - -// static -MojoResult SharedBufferDispatcher::CreateFromPlatformSharedBuffer( - const scoped_refptr& shared_buffer, - scoped_refptr* result) { - if (!shared_buffer) - return MOJO_RESULT_INVALID_ARGUMENT; - - *result = CreateInternal(shared_buffer); - return MOJO_RESULT_OK; -} - -// static -scoped_refptr SharedBufferDispatcher::Deserialize( - const void* bytes, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* platform_handles, - size_t num_platform_handles) { - if (num_bytes != sizeof(SerializedState)) { - LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; - return nullptr; - } - - const SerializedState* serialization = - static_cast(bytes); - if (!serialization->num_bytes) { - LOG(ERROR) - << "Invalid serialized shared buffer dispatcher (invalid num_bytes)"; - return nullptr; - } - - if (!platform_handles || num_platform_handles != 1 || num_ports) { - LOG(ERROR) - << "Invalid serialized shared buffer dispatcher (missing handles)"; - return nullptr; - } - - // Starts off invalid, which is what we want. - PlatformHandle platform_handle; - // We take ownership of the handle, so we have to invalidate the one in - // |platform_handles|. - std::swap(platform_handle, *platform_handles); - - // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be - // closed even if creation fails. - bool read_only = (serialization->flags & kSerializedStateFlagsReadOnly); - scoped_refptr shared_buffer( - PlatformSharedBuffer::CreateFromPlatformHandle( - static_cast(serialization->num_bytes), read_only, - ScopedPlatformHandle(platform_handle))); - if (!shared_buffer) { - LOG(ERROR) - << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; - return nullptr; - } - - return CreateInternal(std::move(shared_buffer)); -} - -scoped_refptr -SharedBufferDispatcher::PassPlatformSharedBuffer() { - base::AutoLock lock(lock_); - if (!shared_buffer_ || in_transit_) - return nullptr; - - scoped_refptr retval = shared_buffer_; - shared_buffer_ = nullptr; - return retval; -} - -Dispatcher::Type SharedBufferDispatcher::GetType() const { - return Type::SHARED_BUFFER; -} - -MojoResult SharedBufferDispatcher::Close() { - base::AutoLock lock(lock_); - if (in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - shared_buffer_ = nullptr; - return MOJO_RESULT_OK; -} - -MojoResult SharedBufferDispatcher::DuplicateBufferHandle( - const MojoDuplicateBufferHandleOptions* options, - scoped_refptr* new_dispatcher) { - MojoDuplicateBufferHandleOptions validated_options; - MojoResult result = ValidateDuplicateOptions(options, &validated_options); - if (result != MOJO_RESULT_OK) - return result; - - // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. - base::AutoLock lock(lock_); - if (in_transit_) - return MOJO_RESULT_INVALID_ARGUMENT; - - if ((validated_options.flags & - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY) && - (!shared_buffer_->IsReadOnly())) { - // If a read-only duplicate is requested and |shared_buffer_| is not - // read-only, make a read-only duplicate of |shared_buffer_|. - scoped_refptr read_only_buffer = - shared_buffer_->CreateReadOnlyDuplicate(); - if (!read_only_buffer) - return MOJO_RESULT_FAILED_PRECONDITION; - DCHECK(read_only_buffer->IsReadOnly()); - *new_dispatcher = CreateInternal(std::move(read_only_buffer)); - return MOJO_RESULT_OK; - } - - *new_dispatcher = CreateInternal(shared_buffer_); - return MOJO_RESULT_OK; -} - -MojoResult SharedBufferDispatcher::MapBuffer( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - std::unique_ptr* mapping) { - if (offset > static_cast(std::numeric_limits::max())) - return MOJO_RESULT_INVALID_ARGUMENT; - if (num_bytes > static_cast(std::numeric_limits::max())) - return MOJO_RESULT_INVALID_ARGUMENT; - - base::AutoLock lock(lock_); - DCHECK(shared_buffer_); - if (in_transit_ || - !shared_buffer_->IsValidMap(static_cast(offset), - static_cast(num_bytes))) { - return MOJO_RESULT_INVALID_ARGUMENT; - } - - DCHECK(mapping); - *mapping = shared_buffer_->MapNoCheck(static_cast(offset), - static_cast(num_bytes)); - if (!*mapping) { - LOG(ERROR) << "Unable to map: read_only" << shared_buffer_->IsReadOnly(); - return MOJO_RESULT_RESOURCE_EXHAUSTED; - } - - return MOJO_RESULT_OK; -} - -void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_platform_handles) { - *num_bytes = sizeof(SerializedState); - *num_ports = 0; - *num_platform_handles = 1; -} - -bool SharedBufferDispatcher::EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) { - SerializedState* serialization = - static_cast(destination); - base::AutoLock lock(lock_); - serialization->num_bytes = - static_cast(shared_buffer_->GetNumBytes()); - serialization->flags = - (shared_buffer_->IsReadOnly() ? kSerializedStateFlagsReadOnly : 0); - serialization->padding = 0; - - handle_for_transit_ = shared_buffer_->DuplicatePlatformHandle(); - if (!handle_for_transit_.is_valid()) { - shared_buffer_ = nullptr; - return false; - } - handles[0] = handle_for_transit_.get(); - return true; -} - -bool SharedBufferDispatcher::BeginTransit() { - base::AutoLock lock(lock_); - if (in_transit_) - return false; - in_transit_ = static_cast(shared_buffer_); - return in_transit_; -} - -void SharedBufferDispatcher::CompleteTransitAndClose() { - base::AutoLock lock(lock_); - in_transit_ = false; - shared_buffer_ = nullptr; - ignore_result(handle_for_transit_.release()); -} - -void SharedBufferDispatcher::CancelTransit() { - base::AutoLock lock(lock_); - in_transit_ = false; - handle_for_transit_.reset(); -} - -SharedBufferDispatcher::SharedBufferDispatcher( - scoped_refptr shared_buffer) - : shared_buffer_(shared_buffer) { - DCHECK(shared_buffer_); -} - -SharedBufferDispatcher::~SharedBufferDispatcher() { - DCHECK(!shared_buffer_ && !in_transit_); -} - -// static -MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( - const MojoDuplicateBufferHandleOptions* in_options, - MojoDuplicateBufferHandleOptions* out_options) { - const MojoDuplicateBufferHandleOptionsFlags kKnownFlags = - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY; - static const MojoDuplicateBufferHandleOptions kDefaultOptions = { - static_cast(sizeof(MojoDuplicateBufferHandleOptions)), - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; - - *out_options = kDefaultOptions; - if (!in_options) - return MOJO_RESULT_OK; - - UserOptionsReader reader(in_options); - if (!reader.is_valid()) - return MOJO_RESULT_INVALID_ARGUMENT; - - if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, - reader)) - return MOJO_RESULT_OK; - if ((reader.options().flags & ~kKnownFlags)) - return MOJO_RESULT_UNIMPLEMENTED; - out_options->flags = reader.options().flags; - - // Checks for fields beyond |flags|: - - // (Nothing here yet.) - - return MOJO_RESULT_OK; -} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/shared_buffer_dispatcher.h b/mojo/edk/system/shared_buffer_dispatcher.h deleted file mode 100644 index 6015595..0000000 --- a/mojo/edk/system/shared_buffer_dispatcher.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_ -#define MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_ - -#include -#include - -#include - -#include "base/macros.h" -#include "mojo/edk/embedder/platform_handle_vector.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/system_impl_export.h" - -namespace mojo { - -namespace edk { -class NodeController; - -class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher { - public: - // The default options to use for |MojoCreateSharedBuffer()|. (Real uses - // should obtain this via |ValidateCreateOptions()| with a null |in_options|; - // this is exposed directly for testing convenience.) - static const MojoCreateSharedBufferOptions kDefaultCreateOptions; - - // Validates and/or sets default options for |MojoCreateSharedBufferOptions|. - // If non-null, |in_options| must point to a struct of at least - // |in_options->struct_size| bytes. |out_options| must point to a (current) - // |MojoCreateSharedBufferOptions| and will be entirely overwritten on success - // (it may be partly overwritten on failure). - static MojoResult ValidateCreateOptions( - const MojoCreateSharedBufferOptions* in_options, - MojoCreateSharedBufferOptions* out_options); - - // Static factory method: |validated_options| must be validated (obviously). - // On failure, |*result| will be left as-is. - // TODO(vtl): This should probably be made to return a scoped_refptr and have - // a MojoResult out parameter instead. - static MojoResult Create( - const MojoCreateSharedBufferOptions& validated_options, - NodeController* node_controller, - uint64_t num_bytes, - scoped_refptr* result); - - // Create a |SharedBufferDispatcher| from |shared_buffer|. - static MojoResult CreateFromPlatformSharedBuffer( - const scoped_refptr& shared_buffer, - scoped_refptr* result); - - // The "opposite" of SerializeAndClose(). Called by Dispatcher::Deserialize(). - static scoped_refptr Deserialize( - const void* bytes, - size_t num_bytes, - const ports::PortName* ports, - size_t num_ports, - PlatformHandle* platform_handles, - size_t num_platform_handles); - - // Passes the underlying platform shared buffer. This dispatcher must be - // closed after calling this function. - scoped_refptr PassPlatformSharedBuffer(); - - // Dispatcher: - Type GetType() const override; - MojoResult Close() override; - MojoResult DuplicateBufferHandle( - const MojoDuplicateBufferHandleOptions* options, - scoped_refptr* new_dispatcher) override; - MojoResult MapBuffer( - uint64_t offset, - uint64_t num_bytes, - MojoMapBufferFlags flags, - std::unique_ptr* mapping) override; - void StartSerialize(uint32_t* num_bytes, - uint32_t* num_ports, - uint32_t* num_platform_handles) override; - bool EndSerialize(void* destination, - ports::PortName* ports, - PlatformHandle* handles) override; - bool BeginTransit() override; - void CompleteTransitAndClose() override; - void CancelTransit() override; - - private: - static scoped_refptr CreateInternal( - scoped_refptr shared_buffer) { - return make_scoped_refptr( - new SharedBufferDispatcher(std::move(shared_buffer))); - } - - explicit SharedBufferDispatcher( - scoped_refptr shared_buffer); - ~SharedBufferDispatcher() override; - - // Validates and/or sets default options for - // |MojoDuplicateBufferHandleOptions|. If non-null, |in_options| must point to - // a struct of at least |in_options->struct_size| bytes. |out_options| must - // point to a (current) |MojoDuplicateBufferHandleOptions| and will be - // entirely overwritten on success (it may be partly overwritten on failure). - static MojoResult ValidateDuplicateOptions( - const MojoDuplicateBufferHandleOptions* in_options, - MojoDuplicateBufferHandleOptions* out_options); - - // Guards access to |shared_buffer_|. - base::Lock lock_; - - bool in_transit_ = false; - - // We keep a copy of the buffer's platform handle during transit so we can - // close it if something goes wrong. - ScopedPlatformHandle handle_for_transit_; - - scoped_refptr shared_buffer_; - - DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcher); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_SHARED_BUFFER_DISPATCHER_H_ diff --git a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc deleted file mode 100644 index c95bdc3..0000000 --- a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/shared_buffer_dispatcher.h" - -#include -#include - -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/dispatcher.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -// NOTE(vtl): There's currently not much to test for in -// |SharedBufferDispatcher::ValidateCreateOptions()|, but the tests should be -// expanded if/when options are added, so I've kept the general form of the -// tests from data_pipe_unittest.cc. - -const uint32_t kSizeOfCreateOptions = sizeof(MojoCreateSharedBufferOptions); - -// Does a cursory sanity check of |validated_options|. Calls -// |ValidateCreateOptions()| on already-validated options. The validated options -// should be valid, and the revalidated copy should be the same. -void RevalidateCreateOptions( - const MojoCreateSharedBufferOptions& validated_options) { - EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size); - // Nothing to check for flags. - - MojoCreateSharedBufferOptions revalidated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - SharedBufferDispatcher::ValidateCreateOptions( - &validated_options, &revalidated_options)); - EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size); - EXPECT_EQ(validated_options.flags, revalidated_options.flags); -} - -class SharedBufferDispatcherTest : public testing::Test { - public: - SharedBufferDispatcherTest() {} - ~SharedBufferDispatcherTest() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcherTest); -}; - -// Tests valid inputs to |ValidateCreateOptions()|. -TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsValid) { - // Default options. - { - MojoCreateSharedBufferOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions( - nullptr, &validated_options)); - RevalidateCreateOptions(validated_options); - } - - // Different flags. - MojoCreateSharedBufferOptionsFlags flags_values[] = { - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; - for (size_t i = 0; i < arraysize(flags_values); i++) { - const MojoCreateSharedBufferOptionsFlags flags = flags_values[i]; - - // Different capacities (size 1). - for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) { - MojoCreateSharedBufferOptions options = { - kSizeOfCreateOptions, // |struct_size|. - flags // |flags|. - }; - MojoCreateSharedBufferOptions validated_options = {}; - EXPECT_EQ(MOJO_RESULT_OK, - SharedBufferDispatcher::ValidateCreateOptions( - &options, &validated_options)) - << capacity; - RevalidateCreateOptions(validated_options); - EXPECT_EQ(options.flags, validated_options.flags); - } - } -} - -TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) { - // Invalid |struct_size|. - { - MojoCreateSharedBufferOptions options = { - 1, // |struct_size|. - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE // |flags|. - }; - MojoCreateSharedBufferOptions unused; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - SharedBufferDispatcher::ValidateCreateOptions( - &options, &unused)); - } - - // Unknown |flags|. - { - MojoCreateSharedBufferOptions options = { - kSizeOfCreateOptions, // |struct_size|. - ~0u // |flags|. - }; - MojoCreateSharedBufferOptions unused; - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - SharedBufferDispatcher::ValidateCreateOptions( - &options, &unused)); - } -} - -TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { - scoped_refptr dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - SharedBufferDispatcher::kDefaultCreateOptions, - nullptr, 100, &dispatcher)); - ASSERT_TRUE(dispatcher); - EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType()); - - // Make a couple of mappings. - std::unique_ptr mapping1; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); - ASSERT_TRUE(mapping1); - ASSERT_TRUE(mapping1->GetBase()); - EXPECT_EQ(100u, mapping1->GetLength()); - // Write something. - static_cast(mapping1->GetBase())[50] = 'x'; - - std::unique_ptr mapping2; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( - 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); - ASSERT_TRUE(mapping2); - ASSERT_TRUE(mapping2->GetBase()); - EXPECT_EQ(50u, mapping2->GetLength()); - EXPECT_EQ('x', static_cast(mapping2->GetBase())[0]); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); - - // Check that we can still read/write to mappings after the dispatcher has - // gone away. - static_cast(mapping2->GetBase())[1] = 'y'; - EXPECT_EQ('y', static_cast(mapping1->GetBase())[51]); -} - -TEST_F(SharedBufferDispatcherTest, CreateAndMapBufferFromPlatformBuffer) { - scoped_refptr platform_shared_buffer = - PlatformSharedBuffer::Create(100); - ASSERT_TRUE(platform_shared_buffer); - scoped_refptr dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, - SharedBufferDispatcher::CreateFromPlatformSharedBuffer( - platform_shared_buffer, &dispatcher)); - ASSERT_TRUE(dispatcher); - EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType()); - - // Make a couple of mappings. - std::unique_ptr mapping1; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); - ASSERT_TRUE(mapping1); - ASSERT_TRUE(mapping1->GetBase()); - EXPECT_EQ(100u, mapping1->GetLength()); - // Write something. - static_cast(mapping1->GetBase())[50] = 'x'; - - std::unique_ptr mapping2; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( - 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); - ASSERT_TRUE(mapping2); - ASSERT_TRUE(mapping2->GetBase()); - EXPECT_EQ(50u, mapping2->GetLength()); - EXPECT_EQ('x', static_cast(mapping2->GetBase())[0]); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); - - // Check that we can still read/write to mappings after the dispatcher has - // gone away. - static_cast(mapping2->GetBase())[1] = 'y'; - EXPECT_EQ('y', static_cast(mapping1->GetBase())[51]); -} - -TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { - scoped_refptr dispatcher1; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - SharedBufferDispatcher::kDefaultCreateOptions, - nullptr, 100, &dispatcher1)); - - // Map and write something. - std::unique_ptr mapping; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - static_cast(mapping->GetBase())[0] = 'x'; - mapping.reset(); - - // Duplicate |dispatcher1| and then close it. - scoped_refptr dispatcher2; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle( - nullptr, &dispatcher2)); - ASSERT_TRUE(dispatcher2); - EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType()); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); - - // Map |dispatcher2| and read something. - EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer( - 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - EXPECT_EQ('x', static_cast(mapping->GetBase())[0]); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); -} - -TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) { - scoped_refptr dispatcher1; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - SharedBufferDispatcher::kDefaultCreateOptions, - nullptr, 100, &dispatcher1)); - - MojoDuplicateBufferHandleOptions options[] = { - {sizeof(MojoDuplicateBufferHandleOptions), - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}, - {sizeof(MojoDuplicateBufferHandleOptions), - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY}, - {sizeof(MojoDuplicateBufferHandleOptionsFlags), ~0u}}; - for (size_t i = 0; i < arraysize(options); i++) { - scoped_refptr dispatcher2; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle( - &options[i], &dispatcher2)); - ASSERT_TRUE(dispatcher2); - EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType()); - { - std::unique_ptr mapping; - EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer(0, 100, 0, &mapping)); - } - EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); - } - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); -} - -TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) { - scoped_refptr dispatcher1; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - SharedBufferDispatcher::kDefaultCreateOptions, - nullptr, 100, &dispatcher1)); - - // Invalid |struct_size|. - { - MojoDuplicateBufferHandleOptions options = { - 1u, MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; - scoped_refptr dispatcher2; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher1->DuplicateBufferHandle(&options, &dispatcher2)); - EXPECT_FALSE(dispatcher2); - } - - // Unknown |flags|. - { - MojoDuplicateBufferHandleOptions options = { - sizeof(MojoDuplicateBufferHandleOptions), ~0u}; - scoped_refptr dispatcher2; - EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, - dispatcher1->DuplicateBufferHandle(&options, &dispatcher2)); - EXPECT_FALSE(dispatcher2); - } - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); -} - -TEST_F(SharedBufferDispatcherTest, CreateInvalidNumBytes) { - // Size too big. - scoped_refptr dispatcher; - EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, - SharedBufferDispatcher::Create( - SharedBufferDispatcher::kDefaultCreateOptions, nullptr, - std::numeric_limits::max(), &dispatcher)); - EXPECT_FALSE(dispatcher); - - // Zero size. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - SharedBufferDispatcher::Create( - SharedBufferDispatcher::kDefaultCreateOptions, nullptr, 0, - &dispatcher)); - EXPECT_FALSE(dispatcher); -} - -TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) { - scoped_refptr dispatcher; - EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( - SharedBufferDispatcher::kDefaultCreateOptions, - nullptr, 100, &dispatcher)); - - std::unique_ptr mapping; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - EXPECT_FALSE(mapping); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher->MapBuffer(1, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - EXPECT_FALSE(mapping); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - dispatcher->MapBuffer(0, 0, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); - EXPECT_FALSE(mapping); - - EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/shared_buffer_unittest.cc b/mojo/edk/system/shared_buffer_unittest.cc deleted file mode 100644 index 3a72872..0000000 --- a/mojo/edk/system/shared_buffer_unittest.cc +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include -#include - -#include "base/logging.h" -#include "base/memory/shared_memory.h" -#include "base/strings/string_piece.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/public/c/system/types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -using SharedBufferTest = test::MojoTestBase; - -TEST_F(SharedBufferTest, CreateSharedBuffer) { - const std::string message = "hello"; - MojoHandle h = CreateBuffer(message.size()); - WriteToBuffer(h, 0, message); - ExpectBufferContents(h, 0, message); -} - -TEST_F(SharedBufferTest, DuplicateSharedBuffer) { - const std::string message = "hello"; - MojoHandle h = CreateBuffer(message.size()); - WriteToBuffer(h, 0, message); - - MojoHandle dupe = DuplicateBuffer(h, false); - ExpectBufferContents(dupe, 0, message); -} - -TEST_F(SharedBufferTest, PassSharedBufferLocal) { - const std::string message = "hello"; - MojoHandle h = CreateBuffer(message.size()); - WriteToBuffer(h, 0, message); - - MojoHandle dupe = DuplicateBuffer(h, false); - MojoHandle p0, p1; - CreateMessagePipe(&p0, &p1); - - WriteMessageWithHandles(p0, "...", &dupe, 1); - EXPECT_EQ("...", ReadMessageWithHandles(p1, &dupe, 1)); - - ExpectBufferContents(dupe, 0, message); -} - -#if !defined(OS_IOS) - -// Reads a single message with a shared buffer handle, maps the buffer, copies -// the message contents into it, then exits. -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CopyToBufferClient, SharedBufferTest, h) { - MojoHandle b; - std::string message = ReadMessageWithHandles(h, &b, 1); - WriteToBuffer(b, 0, message); - - EXPECT_EQ("quit", ReadMessage(h)); -} - -TEST_F(SharedBufferTest, PassSharedBufferCrossProcess) { - const std::string message = "hello"; - MojoHandle b = CreateBuffer(message.size()); - - RUN_CHILD_ON_PIPE(CopyToBufferClient, h) - MojoHandle dupe = DuplicateBuffer(b, false); - WriteMessageWithHandles(h, message, &dupe, 1); - WriteMessage(h, "quit"); - END_CHILD() - - ExpectBufferContents(b, 0, message); -} - -// Creates a new buffer, maps it, writes a message contents to it, unmaps it, -// and finally passes it back to the parent. -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateBufferClient, SharedBufferTest, h) { - std::string message = ReadMessage(h); - MojoHandle b = CreateBuffer(message.size()); - WriteToBuffer(b, 0, message); - WriteMessageWithHandles(h, "have a buffer", &b, 1); - - EXPECT_EQ("quit", ReadMessage(h)); -} - -TEST_F(SharedBufferTest, PassSharedBufferFromChild) { - const std::string message = "hello"; - MojoHandle b; - RUN_CHILD_ON_PIPE(CreateBufferClient, h) - WriteMessage(h, message); - ReadMessageWithHandles(h, &b, 1); - WriteMessage(h, "quit"); - END_CHILD() - - ExpectBufferContents(b, 0, message); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBuffer, SharedBufferTest, h) { - // Receive a pipe handle over the primordial pipe. This will be connected to - // another child process. - MojoHandle other_child; - std::string message = ReadMessageWithHandles(h, &other_child, 1); - - // Create a new shared buffer. - MojoHandle b = CreateBuffer(message.size()); - - // Send a copy of the buffer to the parent and the other child. - MojoHandle dupe = DuplicateBuffer(b, false); - WriteMessageWithHandles(h, "", &b, 1); - WriteMessageWithHandles(other_child, "", &dupe, 1); - - EXPECT_EQ("quit", ReadMessage(h)); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBuffer, SharedBufferTest, h) { - // Receive a pipe handle over the primordial pipe. This will be connected to - // another child process (running CreateAndPassBuffer). - MojoHandle other_child; - std::string message = ReadMessageWithHandles(h, &other_child, 1); - - // Receive a shared buffer from the other child. - MojoHandle b; - ReadMessageWithHandles(other_child, &b, 1); - - // Write the message from the parent into the buffer and exit. - WriteToBuffer(b, 0, message); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - EXPECT_EQ("quit", ReadMessage(h)); -} - -TEST_F(SharedBufferTest, PassSharedBufferFromChildToChild) { - const std::string message = "hello"; - MojoHandle p0, p1; - CreateMessagePipe(&p0, &p1); - - MojoHandle b; - RUN_CHILD_ON_PIPE(CreateAndPassBuffer, h0) - RUN_CHILD_ON_PIPE(ReceiveAndEditBuffer, h1) - // Send one end of the pipe to each child. The first child will create - // and pass a buffer to the second child and back to us. The second child - // will write our message into the buffer. - WriteMessageWithHandles(h0, message, &p0, 1); - WriteMessageWithHandles(h1, message, &p1, 1); - - // Receive the buffer back from the first child. - ReadMessageWithHandles(h0, &b, 1); - - WriteMessage(h1, "quit"); - END_CHILD() - WriteMessage(h0, "quit"); - END_CHILD() - - // The second child should have written this message. - ExpectBufferContents(b, 0, message); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBufferParent, SharedBufferTest, - parent) { - RUN_CHILD_ON_PIPE(CreateAndPassBuffer, child) - // Read a pipe from the parent and forward it to our child. - MojoHandle pipe; - std::string message = ReadMessageWithHandles(parent, &pipe, 1); - - WriteMessageWithHandles(child, message, &pipe, 1); - - // Read a buffer handle from the child and pass it back to the parent. - MojoHandle buffer; - EXPECT_EQ("", ReadMessageWithHandles(child, &buffer, 1)); - WriteMessageWithHandles(parent, "", &buffer, 1); - - EXPECT_EQ("quit", ReadMessage(parent)); - WriteMessage(child, "quit"); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBufferParent, SharedBufferTest, - parent) { - RUN_CHILD_ON_PIPE(ReceiveAndEditBuffer, child) - // Read a pipe from the parent and forward it to our child. - MojoHandle pipe; - std::string message = ReadMessageWithHandles(parent, &pipe, 1); - WriteMessageWithHandles(child, message, &pipe, 1); - - EXPECT_EQ("quit", ReadMessage(parent)); - WriteMessage(child, "quit"); - END_CHILD() -} - -#if defined(OS_ANDROID) || defined(OS_MACOSX) -// Android multi-process tests are not executing the new process. This is flaky. -// Passing shared memory handles between cousins is not currently supported on -// OSX. -#define MAYBE_PassHandleBetweenCousins DISABLED_PassHandleBetweenCousins -#else -#define MAYBE_PassHandleBetweenCousins PassHandleBetweenCousins -#endif -TEST_F(SharedBufferTest, MAYBE_PassHandleBetweenCousins) { - const std::string message = "hello"; - MojoHandle p0, p1; - CreateMessagePipe(&p0, &p1); - - // Spawn two children who will each spawn their own child. Make sure the - // grandchildren (cousins to each other) can pass platform handles. - MojoHandle b; - RUN_CHILD_ON_PIPE(CreateAndPassBufferParent, child1) - RUN_CHILD_ON_PIPE(ReceiveAndEditBufferParent, child2) - MojoHandle pipe[2]; - CreateMessagePipe(&pipe[0], &pipe[1]); - - WriteMessageWithHandles(child1, message, &pipe[0], 1); - WriteMessageWithHandles(child2, message, &pipe[1], 1); - - // Receive the buffer back from the first child. - ReadMessageWithHandles(child1, &b, 1); - - WriteMessage(child2, "quit"); - END_CHILD() - WriteMessage(child1, "quit"); - END_CHILD() - - // The second grandchild should have written this message. - ExpectBufferContents(b, 0, message); -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndMapWriteSharedBuffer, - SharedBufferTest, h) { - // Receive the shared buffer. - MojoHandle b; - EXPECT_EQ("hello", ReadMessageWithHandles(h, &b, 1)); - - // Read from the bufer. - ExpectBufferContents(b, 0, "hello"); - - // Extract the shared memory handle and try to map it writable. - base::SharedMemoryHandle shm_handle; - bool read_only = false; - ASSERT_EQ(MOJO_RESULT_OK, - PassSharedMemoryHandle(b, &shm_handle, nullptr, &read_only)); - base::SharedMemory shared_memory(shm_handle, false); - EXPECT_TRUE(read_only); - EXPECT_FALSE(shared_memory.Map(1234)); - - EXPECT_EQ("quit", ReadMessage(h)); - WriteMessage(h, "ok"); -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_CreateAndPassReadOnlyBuffer DISABLED_CreateAndPassReadOnlyBuffer -#else -#define MAYBE_CreateAndPassReadOnlyBuffer CreateAndPassReadOnlyBuffer -#endif -TEST_F(SharedBufferTest, MAYBE_CreateAndPassReadOnlyBuffer) { - RUN_CHILD_ON_PIPE(ReadAndMapWriteSharedBuffer, h) - // Create a new shared buffer. - MojoHandle b = CreateBuffer(1234); - WriteToBuffer(b, 0, "hello"); - - // Send a read-only copy of the buffer to the child. - MojoHandle dupe = DuplicateBuffer(b, true /* read_only */); - WriteMessageWithHandles(h, "hello", &dupe, 1); - - WriteMessage(h, "quit"); - EXPECT_EQ("ok", ReadMessage(h)); - END_CHILD() -} - -DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassReadOnlyBuffer, - SharedBufferTest, h) { - // Create a new shared buffer. - MojoHandle b = CreateBuffer(1234); - WriteToBuffer(b, 0, "hello"); - - // Send a read-only copy of the buffer to the parent. - MojoHandle dupe = DuplicateBuffer(b, true /* read_only */); - WriteMessageWithHandles(h, "", &dupe, 1); - - EXPECT_EQ("quit", ReadMessage(h)); - WriteMessage(h, "ok"); -} - -#if defined(OS_ANDROID) -// Android multi-process tests are not executing the new process. This is flaky. -#define MAYBE_CreateAndPassFromChildReadOnlyBuffer \ - DISABLED_CreateAndPassFromChildReadOnlyBuffer -#else -#define MAYBE_CreateAndPassFromChildReadOnlyBuffer \ - CreateAndPassFromChildReadOnlyBuffer -#endif -TEST_F(SharedBufferTest, MAYBE_CreateAndPassFromChildReadOnlyBuffer) { - RUN_CHILD_ON_PIPE(CreateAndPassReadOnlyBuffer, h) - MojoHandle b; - EXPECT_EQ("", ReadMessageWithHandles(h, &b, 1)); - ExpectBufferContents(b, 0, "hello"); - - // Extract the shared memory handle and try to map it writable. - base::SharedMemoryHandle shm_handle; - bool read_only = false; - ASSERT_EQ(MOJO_RESULT_OK, - PassSharedMemoryHandle(b, &shm_handle, nullptr, &read_only)); - base::SharedMemory shared_memory(shm_handle, false); - EXPECT_TRUE(read_only); - EXPECT_FALSE(shared_memory.Map(1234)); - - WriteMessage(h, "quit"); - EXPECT_EQ("ok", ReadMessage(h)); - END_CHILD() -} - -#endif // !defined(OS_IOS) - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/signals_unittest.cc b/mojo/edk/system/signals_unittest.cc deleted file mode 100644 index e8b0cd1..0000000 --- a/mojo/edk/system/signals_unittest.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/types.h" - -namespace mojo { -namespace edk { -namespace { - -using SignalsTest = test::MojoTestBase; - -TEST_F(SignalsTest, QueryInvalidArguments) { - MojoHandleSignalsState state = {0, 0}; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoQueryHandleSignalsState(MOJO_HANDLE_INVALID, &state)); - - MojoHandle a, b; - CreateMessagePipe(&a, &b); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoQueryHandleSignalsState(a, nullptr)); -} - -TEST_F(SignalsTest, QueryMessagePipeSignals) { - MojoHandleSignalsState state = {0, 0}; - - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(a, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - state.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - state.satisfiable_signals); - - WriteMessage(a, "ok"); - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &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, - state.satisfiable_signals); - - EXPECT_EQ("ok", ReadMessage(b)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED, - state.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - - EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_PEER_CLOSED)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/system_impl_export.h b/mojo/edk/system/system_impl_export.h deleted file mode 100644 index 5bbf005..0000000 --- a/mojo/edk/system/system_impl_export.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_ -#define MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION) -#define MOJO_SYSTEM_IMPL_EXPORT __declspec(dllexport) -#else -#define MOJO_SYSTEM_IMPL_EXPORT __declspec(dllimport) -#endif // defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION) -#define MOJO_SYSTEM_IMPL_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_SYSTEM_IMPL_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define MOJO_SYSTEM_IMPL_EXPORT -#endif - -#endif // MOJO_EDK_SYSTEM_SYSTEM_IMPL_EXPORT_H_ diff --git a/mojo/edk/system/test_utils.cc b/mojo/edk/system/test_utils.cc deleted file mode 100644 index 4a39cf7..0000000 --- a/mojo/edk/system/test_utils.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/test_utils.h" - -#include - -#include - -#include "base/logging.h" -#include "base/test/test_timeouts.h" -#include "base/threading/platform_thread.h" // For |Sleep()|. -#include "build/build_config.h" - -namespace mojo { -namespace edk { -namespace test { - -MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds) { - return static_cast(milliseconds) * 1000; -} - -MojoDeadline EpsilonDeadline() { -// Originally, our epsilon timeout was 10 ms, which was mostly fine but flaky on -// some Windows bots. I don't recall ever seeing flakes on other bots. At 30 ms -// tests seem reliable on Windows bots, but not at 25 ms. We'd like this timeout -// to be as small as possible (see the description in the .h file). -// -// Currently, |tiny_timeout()| is usually 100 ms (possibly scaled under ASAN, -// etc.). Based on this, set it to (usually be) 30 ms on Windows and 20 ms -// elsewhere. -#if defined(OS_WIN) || defined(OS_ANDROID) - return (TinyDeadline() * 3) / 10; -#else - return (TinyDeadline() * 2) / 10; -#endif -} - -MojoDeadline TinyDeadline() { - return static_cast( - TestTimeouts::tiny_timeout().InMicroseconds()); -} - -MojoDeadline ActionDeadline() { - return static_cast( - TestTimeouts::action_timeout().InMicroseconds()); -} - -void Sleep(MojoDeadline deadline) { - CHECK_LE(deadline, - static_cast(std::numeric_limits::max())); - base::PlatformThread::Sleep( - base::TimeDelta::FromMicroseconds(static_cast(deadline))); -} - -Stopwatch::Stopwatch() { -} - -Stopwatch::~Stopwatch() { -} - -void Stopwatch::Start() { - start_time_ = base::TimeTicks::Now(); -} - -MojoDeadline Stopwatch::Elapsed() { - int64_t result = (base::TimeTicks::Now() - start_time_).InMicroseconds(); - // |DCHECK_GE|, not |CHECK_GE|, since this may be performance-important. - DCHECK_GE(result, 0); - return static_cast(result); -} - -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/test_utils.h b/mojo/edk/system/test_utils.h deleted file mode 100644 index 1c90dc1..0000000 --- a/mojo/edk/system/test_utils.h +++ /dev/null @@ -1,59 +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_TEST_UTILS_H_ -#define MOJO_EDK_SYSTEM_TEST_UTILS_H_ - -#include "base/macros.h" -#include "base/time/time.h" -#include "mojo/public/c/system/types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace test { - -MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds); - -// A timeout smaller than |TestTimeouts::tiny_timeout()|, as a |MojoDeadline|. -// Warning: This may lead to flakiness, but this is unavoidable if, e.g., you're -// trying to ensure that functions with timeouts are reasonably accurate. We -// want this to be as small as possible without causing too much flakiness. -MojoDeadline EpsilonDeadline(); - -// |TestTimeouts::tiny_timeout()|, as a |MojoDeadline|. (Expect this to be on -// the order of 100 ms.) -MojoDeadline TinyDeadline(); - -// |TestTimeouts::action_timeout()|, as a |MojoDeadline|. (Expect this to be on -// the order of 10 s.) -MojoDeadline ActionDeadline(); - -// Sleeps for at least the specified duration. -void Sleep(MojoDeadline deadline); - -// Stopwatch ------------------------------------------------------------------- - -// A simple "stopwatch" for measuring time elapsed from a given starting point. -class Stopwatch { - public: - Stopwatch(); - ~Stopwatch(); - - void Start(); - // Returns the amount of time elapsed since the last call to |Start()| (in - // microseconds). - MojoDeadline Elapsed(); - - private: - base::TimeTicks start_time_; - - DISALLOW_COPY_AND_ASSIGN(Stopwatch); -}; - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_TEST_UTILS_H_ diff --git a/mojo/edk/system/watch.cc b/mojo/edk/system/watch.cc deleted file mode 100644 index cf08ac3..0000000 --- a/mojo/edk/system/watch.cc +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/watch.h" - -#include "mojo/edk/system/request_context.h" -#include "mojo/edk/system/watcher_dispatcher.h" - -namespace mojo { -namespace edk { - -Watch::Watch(const scoped_refptr& watcher, - const scoped_refptr& dispatcher, - uintptr_t context, - MojoHandleSignals signals) - : watcher_(watcher), - dispatcher_(dispatcher), - context_(context), - signals_(signals) {} - -bool Watch::NotifyState(const HandleSignalsState& state, - bool allowed_to_call_callback) { - AssertWatcherLockAcquired(); - - // NOTE: This method must NEVER call into |dispatcher_| directly, because it - // may be called while |dispatcher_| holds a lock. - - MojoResult rv = MOJO_RESULT_SHOULD_WAIT; - RequestContext* const request_context = RequestContext::current(); - if (state.satisfies(signals_)) { - rv = MOJO_RESULT_OK; - if (allowed_to_call_callback && rv != last_known_result_) { - request_context->AddWatchNotifyFinalizer(this, MOJO_RESULT_OK, state); - } - } else if (!state.can_satisfy(signals_)) { - rv = MOJO_RESULT_FAILED_PRECONDITION; - if (allowed_to_call_callback && rv != last_known_result_) { - request_context->AddWatchNotifyFinalizer( - this, MOJO_RESULT_FAILED_PRECONDITION, state); - } - } - - last_known_signals_state_ = - *static_cast(&state); - last_known_result_ = rv; - return ready(); -} - -void Watch::Cancel() { - RequestContext::current()->AddWatchCancelFinalizer(this); -} - -void Watch::InvokeCallback(MojoResult result, - const HandleSignalsState& state, - MojoWatcherNotificationFlags flags) { - // We hold the lock through invocation to ensure that only one notification - // callback runs for this context at any given time. - base::AutoLock lock(notification_lock_); - if (result == MOJO_RESULT_CANCELLED) { - // Make sure cancellation is the last notification we dispatch. - DCHECK(!is_cancelled_); - is_cancelled_ = true; - } else if (is_cancelled_) { - return; - } - - // NOTE: This will acquire |watcher_|'s internal lock. It's safe because a - // thread can only enter InvokeCallback() from within a RequestContext - // destructor where no dispatcher locks are held. - watcher_->InvokeWatchCallback(context_, result, state, flags); -} - -Watch::~Watch() {} - -#if DCHECK_IS_ON() -void Watch::AssertWatcherLockAcquired() const { - watcher_->lock_.AssertAcquired(); -} -#endif - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/watch.h b/mojo/edk/system/watch.h deleted file mode 100644 index f277de9..0000000 --- a/mojo/edk/system/watch.h +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_WATCH_H_ -#define MOJO_EDK_SYSTEM_WATCH_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/system/atomic_flag.h" -#include "mojo/edk/system/handle_signals_state.h" - -namespace mojo { -namespace edk { - -class Dispatcher; -class WatcherDispatcher; - -// Encapsulates the state associated with a single watch context within a -// watcher. -// -// Every Watch has its own cancellation state, and is captured by RequestContext -// notification finalizers to avoid redundant context resolution during -// finalizer execution. -class Watch : public base::RefCountedThreadSafe { - public: - // Constructs a Watch which represents a watch within |watcher| associated - // with |context|, watching |dispatcher| for |signals|. - Watch(const scoped_refptr& watcher, - const scoped_refptr& dispatcher, - uintptr_t context, - MojoHandleSignals signals); - - // Notifies the Watch of a potential state change. - // - // If |allowed_to_call_callback| is true, this may add a notification - // finalizer to the current RequestContext to invoke the watcher's callback - // with this watch's context. See return values below. - // - // This is called directly by WatcherDispatcher whenever the Watch's observed - // dispatcher notifies the WatcherDispatcher of a state change. - // - // Returns |true| if the Watch entered or remains in a ready state as a result - // of the state change. If |allowed_to_call_callback| was true in this case, - // the Watch will have also attached a notification finalizer to the current - // RequestContext. - // - // Returns |false| if the - bool NotifyState(const HandleSignalsState& state, - bool allowed_to_call_callback); - - // Notifies the watch of cancellation ASAP. This will always be the last - // notification sent for the watch. - void Cancel(); - - // Finalizer method for RequestContexts. This method is invoked once for every - // notification finalizer added to a RequestContext by this object. This calls - // down into the WatcherDispatcher to do the actual notification call. - void InvokeCallback(MojoResult result, - const HandleSignalsState& state, - MojoWatcherNotificationFlags flags); - - const scoped_refptr& dispatcher() const { return dispatcher_; } - uintptr_t context() const { return context_; } - - MojoResult last_known_result() const { - AssertWatcherLockAcquired(); - return last_known_result_; - } - - MojoHandleSignalsState last_known_signals_state() const { - AssertWatcherLockAcquired(); - return last_known_signals_state_; - } - - bool ready() const { - AssertWatcherLockAcquired(); - return last_known_result_ == MOJO_RESULT_OK || - last_known_result_ == MOJO_RESULT_FAILED_PRECONDITION; - } - - private: - friend class base::RefCountedThreadSafe; - - ~Watch(); - -#if DCHECK_IS_ON() - void AssertWatcherLockAcquired() const; -#else - void AssertWatcherLockAcquired() const {} -#endif - - const scoped_refptr watcher_; - const scoped_refptr dispatcher_; - const uintptr_t context_; - const MojoHandleSignals signals_; - - // The result code with which this Watch would notify if currently armed, - // based on the last known signaling state of |dispatcher_|. Guarded by the - // owning WatcherDispatcher's lock. - MojoResult last_known_result_ = MOJO_RESULT_UNKNOWN; - - // The last known signaling state of |dispatcher_|. Guarded by the owning - // WatcherDispatcher's lock. - MojoHandleSignalsState last_known_signals_state_ = {0, 0}; - - // Guards |is_cancelled_| below and mutually excludes individual watch - // notification executions for this same watch context. - // - // Note that this should only be acquired from a RequestContext finalizer to - // ensure that no other internal locks are already held. - base::Lock notification_lock_; - - // Guarded by |notification_lock_|. - bool is_cancelled_ = false; - - DISALLOW_COPY_AND_ASSIGN(Watch); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_WATCH_H_ diff --git a/mojo/edk/system/watcher_dispatcher.cc b/mojo/edk/system/watcher_dispatcher.cc deleted file mode 100644 index 409dd2a..0000000 --- a/mojo/edk/system/watcher_dispatcher.cc +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/watcher_dispatcher.h" - -#include -#include -#include - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "mojo/edk/system/watch.h" - -namespace mojo { -namespace edk { - -WatcherDispatcher::WatcherDispatcher(MojoWatcherCallback callback) - : callback_(callback) {} - -void WatcherDispatcher::NotifyHandleState(Dispatcher* dispatcher, - const HandleSignalsState& state) { - base::AutoLock lock(lock_); - auto it = watched_handles_.find(dispatcher); - if (it == watched_handles_.end()) - return; - - // Maybe fire a notification to the watch assoicated with this dispatcher, - // provided we're armed it cares about the new state. - if (it->second->NotifyState(state, armed_)) { - ready_watches_.insert(it->second.get()); - - // If we were armed and got here, we notified the watch. Disarm. - armed_ = false; - } else { - ready_watches_.erase(it->second.get()); - } -} - -void WatcherDispatcher::NotifyHandleClosed(Dispatcher* dispatcher) { - scoped_refptr watch; - { - base::AutoLock lock(lock_); - auto it = watched_handles_.find(dispatcher); - if (it == watched_handles_.end()) - return; - - watch = std::move(it->second); - - // Wipe out all state associated with the closed dispatcher. - watches_.erase(watch->context()); - ready_watches_.erase(watch.get()); - watched_handles_.erase(it); - } - - // NOTE: It's important that this is called outside of |lock_| since it - // acquires internal Watch locks. - watch->Cancel(); -} - -void WatcherDispatcher::InvokeWatchCallback( - uintptr_t context, - MojoResult result, - const HandleSignalsState& state, - MojoWatcherNotificationFlags flags) { - { - // We avoid holding the lock during dispatch. It's OK for notification - // callbacks to close this watcher, and it's OK for notifications to race - // with closure, if for example the watcher is closed from another thread - // between this test and the invocation of |callback_| below. - // - // Because cancellation synchronously blocks all future notifications, and - // because notifications themselves are mutually exclusive for any given - // context, we still guarantee that a single MOJO_RESULT_CANCELLED result - // is the last notification received for any given context. - // - // This guarantee is sufficient to make safe, synchronized, per-context - // state management possible in user code. - base::AutoLock lock(lock_); - if (closed_ && result != MOJO_RESULT_CANCELLED) - return; - } - - callback_(context, result, static_cast(state), flags); -} - -Dispatcher::Type WatcherDispatcher::GetType() const { - return Type::WATCHER; -} - -MojoResult WatcherDispatcher::Close() { - // We swap out all the watched handle information onto the stack so we can - // call into their dispatchers without our own lock held. - std::map> watches; - { - base::AutoLock lock(lock_); - DCHECK(!closed_); - closed_ = true; - std::swap(watches, watches_); - watched_handles_.clear(); - } - - // Remove all refs from our watched dispatchers and fire cancellations. - for (auto& entry : watches) { - entry.second->dispatcher()->RemoveWatcherRef(this, entry.first); - entry.second->Cancel(); - } - - return MOJO_RESULT_OK; -} - -MojoResult WatcherDispatcher::WatchDispatcher( - scoped_refptr dispatcher, - MojoHandleSignals signals, - uintptr_t context) { - // NOTE: Because it's critical to avoid acquiring any other dispatcher locks - // while |lock_| is held, we defer adding oursevles to the dispatcher until - // after we've updated all our own relevant state and released |lock_|. - { - base::AutoLock lock(lock_); - if (watches_.count(context) || watched_handles_.count(dispatcher.get())) - return MOJO_RESULT_ALREADY_EXISTS; - - scoped_refptr watch = new Watch(this, dispatcher, context, signals); - watches_.insert({context, watch}); - auto result = - watched_handles_.insert(std::make_pair(dispatcher.get(), watch)); - DCHECK(result.second); - } - - MojoResult rv = dispatcher->AddWatcherRef(this, context); - if (rv != MOJO_RESULT_OK) { - // Oops. This was not a valid handle to watch. Undo the above work and - // fail gracefully. - base::AutoLock lock(lock_); - watches_.erase(context); - watched_handles_.erase(dispatcher.get()); - return rv; - } - - return MOJO_RESULT_OK; -} - -MojoResult WatcherDispatcher::CancelWatch(uintptr_t context) { - // We may remove the last stored ref to the Watch below, so we retain - // a reference on the stack. - scoped_refptr watch; - { - base::AutoLock lock(lock_); - auto it = watches_.find(context); - if (it == watches_.end()) - return MOJO_RESULT_NOT_FOUND; - watch = it->second; - watches_.erase(it); - } - - // Mark the watch as cancelled so no further notifications get through. - watch->Cancel(); - - // We remove the watcher ref for this context before updating any more - // internal watcher state, ensuring that we don't receiving further - // notifications for this context. - watch->dispatcher()->RemoveWatcherRef(this, context); - - { - base::AutoLock lock(lock_); - auto handle_it = watched_handles_.find(watch->dispatcher().get()); - DCHECK(handle_it != watched_handles_.end()); - ready_watches_.erase(handle_it->second.get()); - watched_handles_.erase(handle_it); - } - - return MOJO_RESULT_OK; -} - -MojoResult WatcherDispatcher::Arm( - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) { - base::AutoLock lock(lock_); - if (num_ready_contexts && - (!ready_contexts || !ready_results || !ready_signals_states)) { - return MOJO_RESULT_INVALID_ARGUMENT; - } - - if (watched_handles_.empty()) - return MOJO_RESULT_NOT_FOUND; - - if (ready_watches_.empty()) { - // Fast path: No watches are ready to notify, so we're done. - armed_ = true; - return MOJO_RESULT_OK; - } - - if (num_ready_contexts) { - DCHECK_LE(ready_watches_.size(), std::numeric_limits::max()); - *num_ready_contexts = std::min( - *num_ready_contexts, static_cast(ready_watches_.size())); - - WatchSet::const_iterator next_ready_iter = ready_watches_.begin(); - if (last_watch_to_block_arming_) { - // Find the next watch to notify in simple round-robin order on the - // |ready_watches_| map, wrapping around to the beginning if necessary. - next_ready_iter = ready_watches_.find(last_watch_to_block_arming_); - if (next_ready_iter != ready_watches_.end()) - ++next_ready_iter; - if (next_ready_iter == ready_watches_.end()) - next_ready_iter = ready_watches_.begin(); - } - - for (size_t i = 0; i < *num_ready_contexts; ++i) { - const Watch* const watch = *next_ready_iter; - ready_contexts[i] = watch->context(); - ready_results[i] = watch->last_known_result(); - ready_signals_states[i] = watch->last_known_signals_state(); - - // Iterate and wrap around. - last_watch_to_block_arming_ = watch; - ++next_ready_iter; - if (next_ready_iter == ready_watches_.end()) - next_ready_iter = ready_watches_.begin(); - } - } - - return MOJO_RESULT_FAILED_PRECONDITION; -} - -WatcherDispatcher::~WatcherDispatcher() {} - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/watcher_dispatcher.h b/mojo/edk/system/watcher_dispatcher.h deleted file mode 100644 index 605a315..0000000 --- a/mojo/edk/system/watcher_dispatcher.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_WATCHER_DISPATCHER_H_ -#define MOJO_EDK_SYSTEM_WATCHER_DISPATCHER_H_ - -#include -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/watcher.h" - -namespace mojo { -namespace edk { - -class Watch; - -// The dispatcher type which backs watcher handles. -class WatcherDispatcher : public Dispatcher { - public: - // Constructs a new WatcherDispatcher which invokes |callback| when a - // registered watch observes some relevant state change. - explicit WatcherDispatcher(MojoWatcherCallback callback); - - // Methods used by watched dispatchers to notify watchers of events. - void NotifyHandleState(Dispatcher* dispatcher, - const HandleSignalsState& state); - void NotifyHandleClosed(Dispatcher* dispatcher); - - // Method used by RequestContext (indirectly, via Watch) to complete - // notification operations from a safe stack frame to avoid reentrancy. - void InvokeWatchCallback(uintptr_t context, - MojoResult result, - const HandleSignalsState& state, - MojoWatcherNotificationFlags flags); - - // Dispatcher: - Type GetType() const override; - MojoResult Close() override; - MojoResult WatchDispatcher(scoped_refptr dispatcher, - MojoHandleSignals signals, - uintptr_t context) override; - MojoResult CancelWatch(uintptr_t context) override; - MojoResult Arm(uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) override; - - private: - friend class Watch; - - using WatchSet = std::set; - - ~WatcherDispatcher() override; - - const MojoWatcherCallback callback_; - - // Guards access to the fields below. - // - // NOTE: This may be acquired while holding another dispatcher's lock, as - // watched dispatchers call into WatcherDispatcher methods which lock this - // when issuing state change notifications. WatcherDispatcher must therefore - // take caution to NEVER acquire other dispatcher locks while this is held. - base::Lock lock_; - - bool armed_ = false; - bool closed_ = false; - - // A mapping from context to Watch. - std::map> watches_; - - // A mapping from watched dispatcher to Watch. - std::map> watched_handles_; - - // The set of all Watch instances which are currently ready to signal. This is - // used for efficient arming behavior, as it allows for O(1) discovery of - // whether or not arming can succeed and quick determination of who's - // responsible if it can't. - WatchSet ready_watches_; - - // Tracks the last Watch whose state was returned by Arm(). This is used to - // ensure consistent round-robin behavior in the event that multiple Watches - // remain ready over the span of several Arm() attempts. - // - // NOTE: This pointer is only used to index |ready_watches_| and may point to - // an invalid object. It must therefore never be dereferenced. - const Watch* last_watch_to_block_arming_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(WatcherDispatcher); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_WATCHER_DISPATCHER_H_ diff --git a/mojo/edk/system/watcher_set.cc b/mojo/edk/system/watcher_set.cc deleted file mode 100644 index 0355b58..0000000 --- a/mojo/edk/system/watcher_set.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/watcher_set.h" - -#include - -namespace mojo { -namespace edk { - -WatcherSet::WatcherSet(Dispatcher* owner) : owner_(owner) {} - -WatcherSet::~WatcherSet() = default; - -void WatcherSet::NotifyState(const HandleSignalsState& state) { - // Avoid notifying watchers if they have already seen this state. - if (last_known_state_.has_value() && state.equals(last_known_state_.value())) - return; - last_known_state_ = state; - for (const auto& entry : watchers_) - entry.first->NotifyHandleState(owner_, state); -} - -void WatcherSet::NotifyClosed() { - for (const auto& entry : watchers_) - entry.first->NotifyHandleClosed(owner_); -} - -MojoResult WatcherSet::Add(const scoped_refptr& watcher, - uintptr_t context, - const HandleSignalsState& current_state) { - auto it = watchers_.find(watcher.get()); - if (it == watchers_.end()) { - auto result = - watchers_.insert(std::make_pair(watcher.get(), Entry{watcher})); - it = result.first; - } - - if (!it->second.contexts.insert(context).second) - return MOJO_RESULT_ALREADY_EXISTS; - - if (last_known_state_.has_value() && - !current_state.equals(last_known_state_.value())) { - // This new state may be relevant to everyone, in which case we just - // notify everyone. - NotifyState(current_state); - } else { - // Otherwise only notify the newly added Watcher. - watcher->NotifyHandleState(owner_, current_state); - } - return MOJO_RESULT_OK; -} - -MojoResult WatcherSet::Remove(WatcherDispatcher* watcher, uintptr_t context) { - auto it = watchers_.find(watcher); - if (it == watchers_.end()) - return MOJO_RESULT_NOT_FOUND; - - ContextSet& contexts = it->second.contexts; - auto context_it = contexts.find(context); - if (context_it == contexts.end()) - return MOJO_RESULT_NOT_FOUND; - - contexts.erase(context_it); - if (contexts.empty()) - watchers_.erase(it); - - return MOJO_RESULT_OK; -} - -WatcherSet::Entry::Entry(const scoped_refptr& dispatcher) - : dispatcher(dispatcher) {} - -WatcherSet::Entry::Entry(Entry&& other) = default; - -WatcherSet::Entry::~Entry() = default; - -WatcherSet::Entry& WatcherSet::Entry::operator=(Entry&& other) = default; - -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/system/watcher_set.h b/mojo/edk/system/watcher_set.h deleted file mode 100644 index 2b7ef2c..0000000 --- a/mojo/edk/system/watcher_set.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_WATCHER_SET_H_ -#define MOJO_EDK_SYSTEM_WATCHER_SET_H_ - -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/optional.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/watcher_dispatcher.h" - -namespace mojo { -namespace edk { - -// A WatcherSet maintains a set of references to WatcherDispatchers to be -// notified when a handle changes state. -// -// Dispatchers which may be watched by a watcher should own a WatcherSet and -// notify it of all relevant state changes. -class WatcherSet { - public: - // |owner| is the Dispatcher who owns this WatcherSet. - explicit WatcherSet(Dispatcher* owner); - ~WatcherSet(); - - // Notifies all watchers of the handle's current signals state. - void NotifyState(const HandleSignalsState& state); - - // Notifies all watchers that this handle has been closed. - void NotifyClosed(); - - // Adds a new watcher+context. - MojoResult Add(const scoped_refptr& watcher, - uintptr_t context, - const HandleSignalsState& current_state); - - // Removes a watcher+context. - MojoResult Remove(WatcherDispatcher* watcher, uintptr_t context); - - private: - using ContextSet = std::set; - - struct Entry { - Entry(const scoped_refptr& dispatcher); - Entry(Entry&& other); - ~Entry(); - - Entry& operator=(Entry&& other); - - scoped_refptr dispatcher; - ContextSet contexts; - - private: - DISALLOW_COPY_AND_ASSIGN(Entry); - }; - - Dispatcher* const owner_; - std::map watchers_; - base::Optional last_known_state_; - - DISALLOW_COPY_AND_ASSIGN(WatcherSet); -}; - -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_WATCHER_SET_H_ diff --git a/mojo/edk/system/watcher_unittest.cc b/mojo/edk/system/watcher_unittest.cc deleted file mode 100644 index dd396cd..0000000 --- a/mojo/edk/system/watcher_unittest.cc +++ /dev/null @@ -1,1637 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include -#include -#include - -#include "base/bind.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/platform_thread.h" -#include "base/threading/simple_thread.h" -#include "base/time/time.h" -#include "mojo/edk/test/mojo_test_base.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/c/system/watcher.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace { - -using WatcherTest = test::MojoTestBase; - -class WatchHelper { - public: - using ContextCallback = - base::Callback; - - WatchHelper() {} - ~WatchHelper() {} - - MojoResult CreateWatcher(MojoHandle* handle) { - return MojoCreateWatcher(&Notify, handle); - } - - uintptr_t CreateContext(const ContextCallback& callback) { - return CreateContextWithCancel(callback, base::Closure()); - } - - uintptr_t CreateContextWithCancel(const ContextCallback& callback, - const base::Closure& cancel_callback) { - auto context = base::MakeUnique(callback); - NotificationContext* raw_context = context.get(); - raw_context->SetCancelCallback(base::Bind( - [](std::unique_ptr context, - const base::Closure& cancel_callback) { - if (cancel_callback) - cancel_callback.Run(); - }, - base::Passed(&context), cancel_callback)); - return reinterpret_cast(raw_context); - } - - private: - class NotificationContext { - public: - explicit NotificationContext(const ContextCallback& callback) - : callback_(callback) {} - - ~NotificationContext() {} - - void SetCancelCallback(const base::Closure& cancel_callback) { - cancel_callback_ = cancel_callback; - } - - void Notify(MojoResult result, MojoHandleSignalsState state) { - if (result == MOJO_RESULT_CANCELLED) - cancel_callback_.Run(); - else - callback_.Run(result, state); - } - - private: - const ContextCallback callback_; - base::Closure cancel_callback_; - - DISALLOW_COPY_AND_ASSIGN(NotificationContext); - }; - - static void Notify(uintptr_t context, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { - reinterpret_cast(context)->Notify(result, state); - } - - DISALLOW_COPY_AND_ASSIGN(WatchHelper); -}; - -class ThreadedRunner : public base::SimpleThread { - public: - explicit ThreadedRunner(const base::Closure& callback) - : SimpleThread("ThreadedRunner"), callback_(callback) {} - ~ThreadedRunner() override {} - - void Run() override { callback_.Run(); } - - private: - const base::Closure callback_; - - DISALLOW_COPY_AND_ASSIGN(ThreadedRunner); -}; - -void ExpectNoNotification(uintptr_t context, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { - NOTREACHED(); -} - -void ExpectOnlyCancel(uintptr_t context, - MojoResult result, - MojoHandleSignalsState state, - MojoWatcherNotificationFlags flags) { - EXPECT_EQ(result, MOJO_RESULT_CANCELLED); -} - -TEST_F(WatcherTest, InvalidArguments) { - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoCreateWatcher(&ExpectNoNotification, nullptr)); - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); - - // Try to watch unwatchable handles. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWatch(w, w, MOJO_HANDLE_SIGNAL_READABLE, 0)); - MojoHandle buffer_handle = CreateBuffer(42); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWatch(w, buffer_handle, MOJO_HANDLE_SIGNAL_READABLE, 0)); - - // Try to cancel a watch on an invalid watcher handle. - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCancelWatch(buffer_handle, 0)); - - // Try to arm an invalid handle. - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - MojoArmWatcher(MOJO_HANDLE_INVALID, nullptr, nullptr, nullptr, nullptr)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoArmWatcher(buffer_handle, nullptr, nullptr, nullptr, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(buffer_handle)); - - // Try to arm with a non-null count but at least one null output buffer. - uint32_t num_ready_contexts = 1; - uintptr_t ready_context; - MojoResult ready_result; - MojoHandleSignalsState ready_state; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoArmWatcher(w, &num_ready_contexts, nullptr, &ready_result, - &ready_state)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoArmWatcher(w, &num_ready_contexts, &ready_context, nullptr, - &ready_state)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoArmWatcher(w, &num_ready_contexts, &ready_context, - &ready_result, nullptr)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); -} - -TEST_F(WatcherTest, WatchMessagePipeReadable) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - int num_expected_notifications = 1; - const uintptr_t readable_a_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, int* expected_count, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_GT(*expected_count, 0); - *expected_count -= 1; - - EXPECT_EQ(MOJO_RESULT_OK, result); - event->Signal(); - }, - &event, &num_expected_notifications)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - const char kMessage1[] = "hey hey hey hey"; - const char kMessage2[] = "i said hey"; - const char kMessage3[] = "what's goin' on?"; - - // Writing to |b| multiple times should notify exactly once. - WriteMessage(b, kMessage1); - WriteMessage(b, kMessage2); - event.Wait(); - - // This also shouldn't fire a notification; the watcher is still disarmed. - WriteMessage(b, kMessage3); - - // Arming should fail with relevant information. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(readable_a_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - - // Flush the three messages from above. - EXPECT_EQ(kMessage1, ReadMessage(a)); - EXPECT_EQ(kMessage2, ReadMessage(a)); - EXPECT_EQ(kMessage3, ReadMessage(a)); - - // Now we can rearm the watcher. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); -} - -TEST_F(WatcherTest, CloseWatchedMessagePipeHandle) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - const uintptr_t readable_a_context = helper.CreateContextWithCancel( - WatchHelper::ContextCallback(), - base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - - // Test that closing a watched handle fires an appropriate notification, even - // when the watcher is unarmed. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); -} - -TEST_F(WatcherTest, CloseWatchedMessagePipeHandlePeer) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - const uintptr_t readable_a_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - event->Signal(); - }, - &event)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - - // Test that closing a watched handle's peer with an armed watcher fires an - // appropriate notification. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - event.Wait(); - - // And now arming should fail with correct information about |a|'s state. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(readable_a_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); - EXPECT_TRUE(ready_states[0].satisfied_signals & - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - EXPECT_FALSE(ready_states[0].satisfiable_signals & - MOJO_HANDLE_SIGNAL_READABLE); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); -} - -TEST_F(WatcherTest, WatchDataPipeConsumerReadable) { - constexpr size_t kTestPipeCapacity = 64; - MojoHandle producer, consumer; - CreateDataPipe(&producer, &consumer, kTestPipeCapacity); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - int num_expected_notifications = 1; - const uintptr_t readable_consumer_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, int* expected_count, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_GT(*expected_count, 0); - *expected_count -= 1; - - EXPECT_EQ(MOJO_RESULT_OK, result); - event->Signal(); - }, - &event, &num_expected_notifications)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, - readable_consumer_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - const char kMessage1[] = "hey hey hey hey"; - const char kMessage2[] = "i said hey"; - const char kMessage3[] = "what's goin' on?"; - - // Writing to |producer| multiple times should notify exactly once. - WriteData(producer, kMessage1); - WriteData(producer, kMessage2); - event.Wait(); - - // This also shouldn't fire a notification; the watcher is still disarmed. - WriteData(producer, kMessage3); - - // Arming should fail with relevant information. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(readable_consumer_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - - // Flush the three messages from above. - EXPECT_EQ(kMessage1, ReadData(consumer, sizeof(kMessage1) - 1)); - EXPECT_EQ(kMessage2, ReadData(consumer, sizeof(kMessage2) - 1)); - EXPECT_EQ(kMessage3, ReadData(consumer, sizeof(kMessage3) - 1)); - - // Now we can rearm the watcher. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); -} - -TEST_F(WatcherTest, WatchDataPipeConsumerNewDataReadable) { - constexpr size_t kTestPipeCapacity = 64; - MojoHandle producer, consumer; - CreateDataPipe(&producer, &consumer, kTestPipeCapacity); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - int num_new_data_notifications = 0; - const uintptr_t new_data_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, int* notification_count, MojoResult result, - MojoHandleSignalsState state) { - *notification_count += 1; - - EXPECT_EQ(MOJO_RESULT_OK, result); - event->Signal(); - }, - &event, &num_new_data_notifications)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - new_data_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - const char kMessage1[] = "hey hey hey hey"; - const char kMessage2[] = "i said hey"; - const char kMessage3[] = "what's goin' on?"; - - // Writing to |producer| multiple times should notify exactly once. - WriteData(producer, kMessage1); - WriteData(producer, kMessage2); - event.Wait(); - - // This also shouldn't fire a notification; the watcher is still disarmed. - WriteData(producer, kMessage3); - - // Arming should fail with relevant information. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(new_data_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - - // Attempt to read more data than is available. Should fail but clear the - // NEW_DATA_READABLE signal. - char large_buffer[512]; - uint32_t large_read_size = 512; - EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, - MojoReadData(consumer, large_buffer, &large_read_size, - MOJO_READ_DATA_FLAG_ALL_OR_NONE)); - - // Attempt to arm again. Should succeed. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Write more data. Should notify. - event.Reset(); - WriteData(producer, kMessage1); - event.Wait(); - - // Reading some data should clear NEW_DATA_READABLE again so we can rearm. - EXPECT_EQ(kMessage1, ReadData(consumer, sizeof(kMessage1) - 1)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - EXPECT_EQ(2, num_new_data_notifications); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); -} - -TEST_F(WatcherTest, WatchDataPipeProducerWritable) { - constexpr size_t kTestPipeCapacity = 8; - MojoHandle producer, consumer; - CreateDataPipe(&producer, &consumer, kTestPipeCapacity); - - // Half the capacity of the data pipe. - const char kTestData[] = "aaaa"; - static_assert((sizeof(kTestData) - 1) * 2 == kTestPipeCapacity, - "Invalid test data for this test."); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - int num_expected_notifications = 1; - const uintptr_t writable_producer_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, int* expected_count, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_GT(*expected_count, 0); - *expected_count -= 1; - - EXPECT_EQ(MOJO_RESULT_OK, result); - event->Signal(); - }, - &event, &num_expected_notifications)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, - writable_producer_context)); - - // The producer is already writable, so arming should fail with relevant - // information. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(writable_producer_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); - - // Write some data, but don't fill the pipe yet. Arming should fail again. - WriteData(producer, kTestData); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(writable_producer_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); - - // Write more data, filling the pipe to capacity. Arming should succeed now. - WriteData(producer, kTestData); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Now read from the pipe, making the producer writable again. Should notify. - EXPECT_EQ(kTestData, ReadData(consumer, sizeof(kTestData) - 1)); - event.Wait(); - - // Arming should fail again. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(writable_producer_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); - - // Fill the pipe once more and arm the watcher. Should succeed. - WriteData(producer, kTestData); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); -}; - -TEST_F(WatcherTest, CloseWatchedDataPipeConsumerHandle) { - constexpr size_t kTestPipeCapacity = 8; - MojoHandle producer, consumer; - CreateDataPipe(&producer, &consumer, kTestPipeCapacity); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - const uintptr_t readable_consumer_context = helper.CreateContextWithCancel( - WatchHelper::ContextCallback(), - base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, - readable_consumer_context)); - - // Closing the consumer should fire a cancellation notification. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); -} - -TEST_F(WatcherTest, CloseWatcherDataPipeConsumerHandlePeer) { - constexpr size_t kTestPipeCapacity = 8; - MojoHandle producer, consumer; - CreateDataPipe(&producer, &consumer, kTestPipeCapacity); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - const uintptr_t readable_consumer_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - event->Signal(); - }, - &event)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, - readable_consumer_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Closing the producer should fire a notification for an unsatisfiable watch. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); - event.Wait(); - - // Now attempt to rearm and expect appropriate error feedback. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(readable_consumer_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); - EXPECT_FALSE(ready_states[0].satisfiable_signals & - MOJO_HANDLE_SIGNAL_READABLE); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); -} - -TEST_F(WatcherTest, CloseWatchedDataPipeProducerHandle) { - constexpr size_t kTestPipeCapacity = 8; - MojoHandle producer, consumer; - CreateDataPipe(&producer, &consumer, kTestPipeCapacity); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - const uintptr_t writable_producer_context = helper.CreateContextWithCancel( - WatchHelper::ContextCallback(), - base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, - writable_producer_context)); - - // Closing the consumer should fire a cancellation notification. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); -} - -TEST_F(WatcherTest, CloseWatchedDataPipeProducerHandlePeer) { - constexpr size_t kTestPipeCapacity = 8; - MojoHandle producer, consumer; - CreateDataPipe(&producer, &consumer, kTestPipeCapacity); - - const char kTestMessageFullCapacity[] = "xxxxxxxx"; - static_assert(sizeof(kTestMessageFullCapacity) - 1 == kTestPipeCapacity, - "Invalid test message size for this test."); - - // Make the pipe unwritable initially. - WriteData(producer, kTestMessageFullCapacity); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - const uintptr_t writable_producer_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); - event->Signal(); - }, - &event)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, - writable_producer_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Closing the consumer should fire a notification for an unsatisfiable watch, - // as the full data pipe can never be read from again and is therefore - // permanently full and unwritable. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); - event.Wait(); - - // Now attempt to rearm and expect appropriate error feedback. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(writable_producer_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); - EXPECT_FALSE(ready_states[0].satisfiable_signals & - MOJO_HANDLE_SIGNAL_WRITABLE); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); -} - -TEST_F(WatcherTest, ArmWithNoWatches) { - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); - EXPECT_EQ(MOJO_RESULT_NOT_FOUND, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); -} - -TEST_F(WatcherTest, WatchDuplicateContext) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, 0)); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, 0)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); -} - -TEST_F(WatcherTest, CancelUnknownWatch) { - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); - EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoCancelWatch(w, 1234)); -} - -TEST_F(WatcherTest, ArmWithWatchAlreadySatisfied) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_WRITABLE, 0)); - - // |a| is always writable, so we can never arm this watcher. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(0u, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); -} - -TEST_F(WatcherTest, ArmWithWatchAlreadyUnsatisfiable) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, 0)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - - // |b| is closed and never wrote any messages, so |a| won't be readable again. - // MojoArmWatcher() should fail, incidcating as much. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = kMaxReadyContexts; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(0u, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); - EXPECT_TRUE(ready_states[0].satisfied_signals & - MOJO_HANDLE_SIGNAL_PEER_CLOSED); - EXPECT_FALSE(ready_states[0].satisfiable_signals & - MOJO_HANDLE_SIGNAL_READABLE); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); -} - -TEST_F(WatcherTest, MultipleWatches) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - base::WaitableEvent a_event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - base::WaitableEvent b_event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - WatchHelper helper; - int num_a_notifications = 0; - int num_b_notifications = 0; - auto notify_callback = - base::Bind([](base::WaitableEvent* event, int* notification_count, - MojoResult result, MojoHandleSignalsState state) { - *notification_count += 1; - EXPECT_EQ(MOJO_RESULT_OK, result); - event->Signal(); - }); - uintptr_t readable_a_context = helper.CreateContext( - base::Bind(notify_callback, &a_event, &num_a_notifications)); - uintptr_t readable_b_context = helper.CreateContext( - base::Bind(notify_callback, &b_event, &num_b_notifications)); - - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - // Add two independent watch contexts to watch for |a| or |b| readability. - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, readable_b_context)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - const char kMessage1[] = "things are happening"; - const char kMessage2[] = "ok. ok. ok. ok."; - const char kMessage3[] = "plz wake up"; - - // Writing to |b| should signal |a|'s watch. - WriteMessage(b, kMessage1); - a_event.Wait(); - a_event.Reset(); - - // Subsequent messages on |b| should not trigger another notification. - WriteMessage(b, kMessage2); - WriteMessage(b, kMessage3); - - // Messages on |a| also shouldn't trigger |b|'s notification, since the - // watcher should be disarmed by now. - WriteMessage(a, kMessage1); - WriteMessage(a, kMessage2); - WriteMessage(a, kMessage3); - - // Arming should fail. Since we only ask for at most one context's information - // that's all we should get back. Which one we get is unspecified. - constexpr size_t kMaxReadyContexts = 10; - uint32_t num_ready_contexts = 1; - uintptr_t ready_contexts[kMaxReadyContexts]; - MojoResult ready_results[kMaxReadyContexts]; - MojoHandleSignalsState ready_states[kMaxReadyContexts]; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_TRUE(ready_contexts[0] == readable_a_context || - ready_contexts[0] == readable_b_context); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); - - // Now try arming again, verifying that both contexts are returned. - num_ready_contexts = kMaxReadyContexts; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(2u, num_ready_contexts); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[1]); - EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); - EXPECT_TRUE(ready_states[1].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); - EXPECT_TRUE((ready_contexts[0] == readable_a_context && - ready_contexts[1] == readable_b_context) || - (ready_contexts[0] == readable_b_context && - ready_contexts[1] == readable_a_context)); - - // Flush out the test messages so we should be able to successfully rearm. - EXPECT_EQ(kMessage1, ReadMessage(a)); - EXPECT_EQ(kMessage2, ReadMessage(a)); - EXPECT_EQ(kMessage3, ReadMessage(a)); - EXPECT_EQ(kMessage1, ReadMessage(b)); - EXPECT_EQ(kMessage2, ReadMessage(b)); - EXPECT_EQ(kMessage3, ReadMessage(b)); - - // Add a watch which is always satisfied, so we can't arm. Arming should fail - // with only this new watch's information. - uintptr_t writable_c_context = helper.CreateContext(base::Bind( - [](MojoResult result, MojoHandleSignalsState state) { NOTREACHED(); })); - MojoHandle c, d; - CreateMessagePipe(&c, &d); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, c, MOJO_HANDLE_SIGNAL_WRITABLE, writable_c_context)); - num_ready_contexts = kMaxReadyContexts; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(writable_c_context, ready_contexts[0]); - EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); - EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); - - // Cancel the new watch and arming should succeed once again. - EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, writable_c_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); -} - -TEST_F(WatcherTest, NotifyOtherFromNotificationCallback) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - static const char kTestMessageToA[] = "hello a"; - static const char kTestMessageToB[] = "hello b"; - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - WatchHelper helper; - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - uintptr_t readable_a_context = helper.CreateContext(base::Bind( - [](MojoHandle w, MojoHandle a, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ("hello a", ReadMessage(a)); - - // Re-arm the watcher and signal |b|. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - WriteMessage(a, kTestMessageToB); - }, - w, a)); - - uintptr_t readable_b_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, MojoHandle w, MojoHandle b, - MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToB, ReadMessage(b)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - event->Signal(); - }, - &event, w, b)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, readable_b_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Send a message to |a|. The relevant watch context should be notified, and - // should in turn send a message to |b|, waking up the other context. The - // second context signals |event|. - WriteMessage(b, kTestMessageToA); - event.Wait(); -} - -TEST_F(WatcherTest, NotifySelfFromNotificationCallback) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - static const char kTestMessageToA[] = "hello a"; - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - WatchHelper helper; - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - int expected_notifications = 10; - uintptr_t readable_a_context = helper.CreateContext(base::Bind( - [](int* expected_count, MojoHandle w, MojoHandle a, MojoHandle b, - base::WaitableEvent* event, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ("hello a", ReadMessage(a)); - - EXPECT_GT(*expected_count, 0); - *expected_count -= 1; - if (*expected_count == 0) { - event->Signal(); - return; - } else { - // Re-arm the watcher and signal |a| again. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - WriteMessage(b, kTestMessageToA); - } - }, - &expected_notifications, w, a, b, &event)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Send a message to |a|. When the watch above is notified, it will rearm and - // send another message to |a|. This will happen until - // |expected_notifications| reaches 0. - WriteMessage(b, kTestMessageToA); - event.Wait(); -} - -TEST_F(WatcherTest, ImplicitCancelOtherFromNotificationCallback) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - MojoHandle c, d; - CreateMessagePipe(&c, &d); - - static const char kTestMessageToA[] = "hi a"; - static const char kTestMessageToC[] = "hi c"; - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - WatchHelper helper; - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - uintptr_t readable_a_context = helper.CreateContextWithCancel( - base::Bind([](MojoResult result, MojoHandleSignalsState state) { - NOTREACHED(); - }), - base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event)); - - uintptr_t readable_c_context = helper.CreateContext(base::Bind( - [](MojoHandle w, MojoHandle a, MojoHandle b, MojoHandle c, - MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToC, ReadMessage(c)); - - // Now rearm the watcher. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Must result in exactly ONE notification on the above context, for - // CANCELLED only. Because we cannot dispatch notifications until the - // stack unwinds, and because we must never dispatch non-cancellation - // notifications for a handle once it's been closed, we must be certain - // that cancellation due to closure preemptively invalidates any - // pending non-cancellation notifications queued on the current - // RequestContext, such as the one resulting from the WriteMessage here. - WriteMessage(b, kTestMessageToA); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - - // Rearming should be fine since |a|'s watch should already be - // implicitly cancelled (even though the notification will not have - // been invoked yet.) - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Nothing interesting should happen as a result of this. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - }, - w, a, b, c)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE, readable_c_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - WriteMessage(d, kTestMessageToC); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); -} - -TEST_F(WatcherTest, ExplicitCancelOtherFromNotificationCallback) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - MojoHandle c, d; - CreateMessagePipe(&c, &d); - - static const char kTestMessageToA[] = "hi a"; - static const char kTestMessageToC[] = "hi c"; - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - WatchHelper helper; - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - uintptr_t readable_a_context = helper.CreateContext(base::Bind( - [](MojoResult result, MojoHandleSignalsState state) { NOTREACHED(); })); - - uintptr_t readable_c_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, uintptr_t readable_a_context, MojoHandle w, - MojoHandle a, MojoHandle b, MojoHandle c, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToC, ReadMessage(c)); - - // Now rearm the watcher. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Should result in no notifications on the above context, because the - // watch will have been cancelled by the time the notification callback - // can execute. - WriteMessage(b, kTestMessageToA); - WriteMessage(b, kTestMessageToA); - EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context)); - - // Rearming should be fine now. - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // Nothing interesting should happen as a result of these. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - - event->Signal(); - }, - &event, readable_a_context, w, a, b, c)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE, readable_c_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - WriteMessage(d, kTestMessageToC); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); -} - -TEST_F(WatcherTest, NestedCancellation) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - MojoHandle c, d; - CreateMessagePipe(&c, &d); - - static const char kTestMessageToA[] = "hey a"; - static const char kTestMessageToC[] = "hey c"; - static const char kTestMessageToD[] = "hey d"; - - // This is a tricky test. It establishes a watch on |b| using one watcher and - // watches on |c| and |d| using another watcher. - // - // A message is written to |d| to wake up |c|'s watch, and the notification - // handler for that event does the following: - // 1. Writes to |a| to eventually wake up |b|'s watcher. - // 2. Rearms |c|'s watcher. - // 3. Writes to |d| to eventually wake up |c|'s watcher again. - // - // Meanwhile, |b|'s watch notification handler cancels |c|'s watch altogether - // before writing to |c| to wake up |d|. - // - // The net result should be that |c|'s context only gets notified once (from - // the first write to |d| above) and everyone else gets notified as expected. - - MojoHandle b_watcher; - MojoHandle cd_watcher; - WatchHelper helper; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&b_watcher)); - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&cd_watcher)); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - uintptr_t readable_d_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, MojoHandle d, MojoResult result, - MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToD, ReadMessage(d)); - event->Signal(); - }, - &event, d)); - - static int num_expected_c_notifications = 1; - uintptr_t readable_c_context = helper.CreateContext(base::Bind( - [](MojoHandle cd_watcher, MojoHandle a, MojoHandle c, MojoHandle d, - MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_GT(num_expected_c_notifications--, 0); - - // Trigger an eventual |readable_b_context| notification. - WriteMessage(a, kTestMessageToA); - - EXPECT_EQ(kTestMessageToC, ReadMessage(c)); - EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(cd_watcher, nullptr, nullptr, - nullptr, nullptr)); - - // Trigger another eventual |readable_c_context| notification. - WriteMessage(d, kTestMessageToC); - }, - cd_watcher, a, c, d)); - - uintptr_t readable_b_context = helper.CreateContext(base::Bind( - [](MojoHandle cd_watcher, uintptr_t readable_c_context, MojoHandle c, - MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, - MojoCancelWatch(cd_watcher, readable_c_context)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(cd_watcher, nullptr, nullptr, - nullptr, nullptr)); - - WriteMessage(c, kTestMessageToD); - }, - cd_watcher, readable_c_context, c)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, - readable_b_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(cd_watcher, c, MOJO_HANDLE_SIGNAL_READABLE, - readable_c_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(cd_watcher, d, MOJO_HANDLE_SIGNAL_READABLE, - readable_d_context)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(b_watcher, nullptr, nullptr, nullptr, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(cd_watcher, nullptr, nullptr, nullptr, nullptr)); - - WriteMessage(d, kTestMessageToC); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(cd_watcher)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b_watcher)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); -} - -TEST_F(WatcherTest, CancelSelfInNotificationCallback) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - static const char kTestMessageToA[] = "hey a"; - - MojoHandle w; - WatchHelper helper; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - static uintptr_t readable_a_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, MojoHandle w, MojoHandle a, - MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - - // There should be no problem cancelling this watch from its own - // notification invocation. - EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context)); - EXPECT_EQ(kTestMessageToA, ReadMessage(a)); - - // Arming should fail because there are no longer any registered - // watches on the watcher. - EXPECT_EQ(MOJO_RESULT_NOT_FOUND, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // And closing |a| should be fine (and should not invoke this - // notification with MOJO_RESULT_CANCELLED) for the same reason. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - - event->Signal(); - }, - &event, w, a)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - WriteMessage(b, kTestMessageToA); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); -} - -TEST_F(WatcherTest, CloseWatcherInNotificationCallback) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - static const char kTestMessageToA1[] = "hey a"; - static const char kTestMessageToA2[] = "hey a again"; - - MojoHandle w; - WatchHelper helper; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - uintptr_t readable_a_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, MojoHandle w, MojoHandle a, MojoHandle b, - MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToA1, ReadMessage(a)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // There should be no problem closing this watcher from its own - // notification callback. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - - // And these should not trigger more notifications, because |w| has been - // closed already. - WriteMessage(b, kTestMessageToA2); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - - event->Signal(); - }, - &event, w, a, b)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - WriteMessage(b, kTestMessageToA1); - event.Wait(); -} - -TEST_F(WatcherTest, CloseWatcherAfterImplicitCancel) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - static const char kTestMessageToA[] = "hey a"; - - MojoHandle w; - WatchHelper helper; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - uintptr_t readable_a_context = helper.CreateContext(base::Bind( - [](base::WaitableEvent* event, MojoHandle w, MojoHandle a, - MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToA, ReadMessage(a)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - // This will cue up a notification for |MOJO_RESULT_CANCELLED|... - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - - // ...but it should never fire because we close the watcher here. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - - event->Signal(); - }, - &event, w, a)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - WriteMessage(b, kTestMessageToA); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); -} - -TEST_F(WatcherTest, OtherThreadCancelDuringNotification) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - static const char kTestMessageToA[] = "hey a"; - - MojoHandle w; - WatchHelper helper; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - base::WaitableEvent wait_for_notification( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - base::WaitableEvent wait_for_cancellation( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - static bool callback_done = false; - uintptr_t readable_a_context = helper.CreateContextWithCancel( - base::Bind( - [](base::WaitableEvent* wait_for_notification, MojoHandle w, - MojoHandle a, MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToA, ReadMessage(a)); - - wait_for_notification->Signal(); - - // Give the other thread sufficient time to race with the completion - // of this callback. There should be no race, since the cancellation - // notification must be mutually exclusive to this notification. - base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); - - callback_done = true; - }, - &wait_for_notification, w, a), - base::Bind( - [](base::WaitableEvent* wait_for_cancellation) { - EXPECT_TRUE(callback_done); - wait_for_cancellation->Signal(); - }, - &wait_for_cancellation)); - - ThreadedRunner runner(base::Bind( - [](base::WaitableEvent* wait_for_notification, - base::WaitableEvent* wait_for_cancellation, MojoHandle w, - uintptr_t readable_a_context) { - wait_for_notification->Wait(); - - // Cancel the watch while the notification is still running. - EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context)); - - wait_for_cancellation->Wait(); - - EXPECT_TRUE(callback_done); - }, - &wait_for_notification, &wait_for_cancellation, w, readable_a_context)); - runner.Start(); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); - - WriteMessage(b, kTestMessageToA); - runner.Join(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); -} - -TEST_F(WatcherTest, WatchesCancelEachOtherFromNotifications) { - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - static const char kTestMessageToA[] = "hey a"; - static const char kTestMessageToB[] = "hey b"; - - base::WaitableEvent wait_for_a_to_notify( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - base::WaitableEvent wait_for_b_to_notify( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - base::WaitableEvent wait_for_a_to_cancel( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - base::WaitableEvent wait_for_b_to_cancel( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - - MojoHandle a_watcher; - MojoHandle b_watcher; - WatchHelper helper; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&a_watcher)); - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&b_watcher)); - - // We set up two watchers, one on |a| and one on |b|. They cancel each other - // from within their respective watch notifications. This should be safe, - // i.e., it should not deadlock, in spite of the fact that we also guarantee - // mutually exclusive notification execution (including cancellations) on any - // given watch. - bool a_cancelled = false; - bool b_cancelled = false; - static uintptr_t readable_b_context; - uintptr_t readable_a_context = helper.CreateContextWithCancel( - base::Bind( - [](base::WaitableEvent* wait_for_a_to_notify, - base::WaitableEvent* wait_for_b_to_notify, MojoHandle b_watcher, - MojoHandle a, MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToA, ReadMessage(a)); - wait_for_a_to_notify->Signal(); - wait_for_b_to_notify->Wait(); - EXPECT_EQ(MOJO_RESULT_OK, - MojoCancelWatch(b_watcher, readable_b_context)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b_watcher)); - }, - &wait_for_a_to_notify, &wait_for_b_to_notify, b_watcher, a), - base::Bind( - [](base::WaitableEvent* wait_for_a_to_cancel, - base::WaitableEvent* wait_for_b_to_cancel, bool* a_cancelled) { - *a_cancelled = true; - wait_for_a_to_cancel->Signal(); - wait_for_b_to_cancel->Wait(); - }, - &wait_for_a_to_cancel, &wait_for_b_to_cancel, &a_cancelled)); - - readable_b_context = helper.CreateContextWithCancel( - base::Bind( - [](base::WaitableEvent* wait_for_a_to_notify, - base::WaitableEvent* wait_for_b_to_notify, - uintptr_t readable_a_context, MojoHandle a_watcher, MojoHandle b, - MojoResult result, MojoHandleSignalsState state) { - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(kTestMessageToB, ReadMessage(b)); - wait_for_b_to_notify->Signal(); - wait_for_a_to_notify->Wait(); - EXPECT_EQ(MOJO_RESULT_OK, - MojoCancelWatch(a_watcher, readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a_watcher)); - }, - &wait_for_a_to_notify, &wait_for_b_to_notify, readable_a_context, - a_watcher, b), - base::Bind( - [](base::WaitableEvent* wait_for_a_to_cancel, - base::WaitableEvent* wait_for_b_to_cancel, bool* b_cancelled) { - *b_cancelled = true; - wait_for_b_to_cancel->Signal(); - wait_for_a_to_cancel->Wait(); - }, - &wait_for_a_to_cancel, &wait_for_b_to_cancel, &b_cancelled)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a_watcher, a, MOJO_HANDLE_SIGNAL_READABLE, - readable_a_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(a_watcher, nullptr, nullptr, nullptr, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, - readable_b_context)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoArmWatcher(b_watcher, nullptr, nullptr, nullptr, nullptr)); - - ThreadedRunner runner( - base::Bind([](MojoHandle b) { WriteMessage(b, kTestMessageToA); }, b)); - runner.Start(); - - WriteMessage(a, kTestMessageToB); - - wait_for_a_to_cancel.Wait(); - wait_for_b_to_cancel.Wait(); - runner.Join(); - - EXPECT_TRUE(a_cancelled); - EXPECT_TRUE(b_cancelled); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); -} - -TEST_F(WatcherTest, AlwaysCancel) { - // Basic sanity check to ensure that all possible ways to cancel a watch - // result in a final MOJO_RESULT_CANCELLED notification. - - MojoHandle a, b; - CreateMessagePipe(&a, &b); - - MojoHandle w; - WatchHelper helper; - EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); - - base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - const base::Closure signal_event = - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)); - - // Cancel via |MojoCancelWatch()|. - uintptr_t context = helper.CreateContextWithCancel( - WatchHelper::ContextCallback(), signal_event); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, context)); - EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, context)); - event.Wait(); - event.Reset(); - - // Cancel by closing the watched handle. - context = helper.CreateContextWithCancel(WatchHelper::ContextCallback(), - signal_event); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, context)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); - event.Wait(); - event.Reset(); - - // Cancel by closing the watcher handle. - context = helper.CreateContextWithCancel(WatchHelper::ContextCallback(), - signal_event); - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, context)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); - event.Wait(); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); -} - -TEST_F(WatcherTest, ArmFailureCirculation) { - // Sanity check to ensure that all ready handles will eventually be returned - // over a finite number of calls to MojoArmWatcher(). - - constexpr size_t kNumTestPipes = 100; - constexpr size_t kNumTestHandles = kNumTestPipes * 2; - MojoHandle handles[kNumTestHandles]; - - // Create a bunch of pipes and make sure they're all readable. - for (size_t i = 0; i < kNumTestPipes; ++i) { - CreateMessagePipe(&handles[i], &handles[i + kNumTestPipes]); - WriteMessage(handles[i], "hey"); - WriteMessage(handles[i + kNumTestPipes], "hay"); - WaitForSignals(handles[i], MOJO_HANDLE_SIGNAL_READABLE); - WaitForSignals(handles[i + kNumTestPipes], MOJO_HANDLE_SIGNAL_READABLE); - } - - // Create a watcher and watch all of them. - MojoHandle w; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); - for (size_t i = 0; i < kNumTestHandles; ++i) { - EXPECT_EQ(MOJO_RESULT_OK, - MojoWatch(w, handles[i], MOJO_HANDLE_SIGNAL_READABLE, i)); - } - - // Keep trying to arm |w| until every watch gets an entry in |ready_contexts|. - // If MojoArmWatcher() is well-behaved, this should terminate eventually. - std::set ready_contexts; - while (ready_contexts.size() < kNumTestHandles) { - uint32_t num_ready_contexts = 1; - uintptr_t ready_context; - MojoResult ready_result; - MojoHandleSignalsState ready_state; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoArmWatcher(w, &num_ready_contexts, &ready_context, - &ready_result, &ready_state)); - EXPECT_EQ(1u, num_ready_contexts); - EXPECT_EQ(MOJO_RESULT_OK, ready_result); - ready_contexts.insert(ready_context); - } - - for (size_t i = 0; i < kNumTestHandles; ++i) - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[i])); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); -} - -} // namespace -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/test/BUILD.gn b/mojo/edk/test/BUILD.gn deleted file mode 100644 index a15456a..0000000 --- a/mojo/edk/test/BUILD.gn +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//testing/test.gni") - -static_library("test_support") { - testonly = true - sources = [ - "mojo_test_base.cc", - "mojo_test_base.h", - "test_utils.h", - "test_utils_posix.cc", - "test_utils_win.cc", - ] - - if (!is_ios) { - sources += [ - "multiprocess_test_helper.cc", - "multiprocess_test_helper.h", - ] - } - - deps = [ - "//base", - "//base/test:test_support", - "//mojo/edk/system", - "//mojo/public/cpp/system", - "//testing/gtest", - ] -} - -source_set("run_all_unittests") { - testonly = true - sources = [ - "run_all_unittests.cc", - ] - - deps = [ - ":test_support", - ":test_support_impl", - "//base", - "//base/test:test_support", - "//mojo/edk/system", - "//mojo/public/c/test_support", - "//testing/gtest", - ] - - if (is_linux && !is_component_build) { - public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } -} - -source_set("run_all_perftests") { - testonly = true - deps = [ - ":test_support_impl", - "//base", - "//base/test:test_support", - "//mojo/edk/system", - "//mojo/edk/test:test_support", - "//mojo/public/c/test_support", - ] - - sources = [ - "run_all_perftests.cc", - ] - - if (is_linux && !is_component_build) { - public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } -} - -static_library("test_support_impl") { - testonly = true - deps = [ - "//base", - "//base/test:test_support", - "//mojo/public/c/test_support", - "//mojo/public/cpp/system", - ] - - sources = [ - "test_support_impl.cc", - "test_support_impl.h", - ] -} - -# Public SDK test targets follow. These targets are not defined within the -# public SDK itself as running the unittests requires the EDK. -# TODO(vtl): These don't really belong here. (They should be converted to -# apptests, but even apart from that these targets belong somewhere else.) - -group("public_tests") { - testonly = true - deps = [ - ":mojo_public_bindings_unittests", - ":mojo_public_system_perftests", - ":mojo_public_system_unittests", - ] -} - -test("mojo_public_bindings_perftests") { - deps = [ - ":run_all_perftests", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/bindings/tests:perftests", - ] -} - -test("mojo_public_bindings_unittests") { - deps = [ - ":run_all_unittests", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/bindings/tests", - ] -} - -test("mojo_public_system_perftests") { - deps = [ - ":run_all_perftests", - "//mojo/public/c/system/tests:perftests", - ] -} - -test("mojo_public_system_unittests") { - deps = [ - ":run_all_unittests", - "//mojo/public/cpp/system/tests", - ] -} diff --git a/mojo/edk/test/mojo_test_base.cc b/mojo/edk/test/mojo_test_base.cc deleted file mode 100644 index 71a5e3b..0000000 --- a/mojo/edk/test/mojo_test_base.cc +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/test/mojo_test_base.h" - -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/synchronization/waitable_event.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/c/system/watcher.h" -#include "mojo/public/cpp/system/wait.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_MACOSX) && !defined(OS_IOS) -#include "base/mac/mach_port_broker.h" -#endif - -namespace mojo { -namespace edk { -namespace test { - -#if defined(OS_MACOSX) && !defined(OS_IOS) -namespace { -base::MachPortBroker* g_mach_broker = nullptr; -} -#endif - -MojoTestBase::MojoTestBase() { -#if defined(OS_MACOSX) && !defined(OS_IOS) - if (!g_mach_broker) { - g_mach_broker = new base::MachPortBroker("mojo_test"); - CHECK(g_mach_broker->Init()); - SetMachPortProvider(g_mach_broker); - } -#endif -} - -MojoTestBase::~MojoTestBase() {} - -MojoTestBase::ClientController& MojoTestBase::StartClient( - const std::string& client_name) { - clients_.push_back(base::MakeUnique( - client_name, this, process_error_callback_, launch_type_)); - return *clients_.back(); -} - -MojoTestBase::ClientController::ClientController( - const std::string& client_name, - MojoTestBase* test, - const ProcessErrorCallback& process_error_callback, - LaunchType launch_type) { -#if !defined(OS_IOS) -#if defined(OS_MACOSX) - // This lock needs to be held while launching the child because the Mach port - // broker only allows task ports to be received from known child processes. - // However, it can only know the child process's pid after the child has - // launched. To prevent a race where the child process sends its task port - // before the pid has been registered, the lock needs to be held over both - // launch and child pid registration. - base::AutoLock lock(g_mach_broker->GetLock()); -#endif - helper_.set_process_error_callback(process_error_callback); - pipe_ = helper_.StartChild(client_name, launch_type); -#if defined(OS_MACOSX) - g_mach_broker->AddPlaceholderForPid(helper_.test_child().Handle()); -#endif -#endif -} - -MojoTestBase::ClientController::~ClientController() { - CHECK(was_shutdown_) - << "Test clients should be waited on explicitly with WaitForShutdown()."; -} - -void MojoTestBase::ClientController::ClosePeerConnection() { -#if !defined(OS_IOS) - helper_.ClosePeerConnection(); -#endif -} - -int MojoTestBase::ClientController::WaitForShutdown() { - was_shutdown_ = true; -#if !defined(OS_IOS) - int retval = helper_.WaitForChildShutdown(); -#if defined(OS_MACOSX) - base::AutoLock lock(g_mach_broker->GetLock()); - g_mach_broker->InvalidatePid(helper_.test_child().Handle()); -#endif - return retval; -#else - NOTREACHED(); - return 1; -#endif -} - -// static -void MojoTestBase::CloseHandle(MojoHandle h) { - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h)); -} - -// static -void MojoTestBase::CreateMessagePipe(MojoHandle *p0, MojoHandle* p1) { - MojoCreateMessagePipe(nullptr, p0, p1); - CHECK_NE(*p0, MOJO_HANDLE_INVALID); - CHECK_NE(*p1, MOJO_HANDLE_INVALID); -} - -// static -void MojoTestBase::WriteMessageWithHandles(MojoHandle mp, - const std::string& message, - const MojoHandle *handles, - uint32_t num_handles) { - CHECK_EQ(MojoWriteMessage(mp, message.data(), - static_cast(message.size()), - handles, num_handles, MOJO_WRITE_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); -} - -// static -void MojoTestBase::WriteMessage(MojoHandle mp, const std::string& message) { - WriteMessageWithHandles(mp, message, nullptr, 0); -} - -// static -std::string MojoTestBase::ReadMessageWithHandles( - MojoHandle mp, - MojoHandle* handles, - uint32_t expected_num_handles) { - CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK); - - uint32_t message_size = 0; - uint32_t num_handles = 0; - CHECK_EQ(MojoReadMessage(mp, nullptr, &message_size, nullptr, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_RESOURCE_EXHAUSTED); - CHECK_EQ(expected_num_handles, num_handles); - - std::string message(message_size, 'x'); - CHECK_EQ(MojoReadMessage(mp, &message[0], &message_size, handles, - &num_handles, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - CHECK_EQ(message_size, message.size()); - CHECK_EQ(num_handles, expected_num_handles); - - return message; -} - -// static -std::string MojoTestBase::ReadMessageWithOptionalHandle(MojoHandle mp, - MojoHandle* handle) { - CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK); - - uint32_t message_size = 0; - uint32_t num_handles = 0; - CHECK_EQ(MojoReadMessage(mp, nullptr, &message_size, nullptr, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_RESOURCE_EXHAUSTED); - CHECK(num_handles == 0 || num_handles == 1); - - CHECK(handle); - - std::string message(message_size, 'x'); - CHECK_EQ(MojoReadMessage(mp, &message[0], &message_size, handle, - &num_handles, MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - CHECK_EQ(message_size, message.size()); - CHECK(num_handles == 0 || num_handles == 1); - - if (num_handles) - CHECK_NE(*handle, MOJO_HANDLE_INVALID); - else - *handle = MOJO_HANDLE_INVALID; - - return message; -} - -// static -std::string MojoTestBase::ReadMessage(MojoHandle mp) { - return ReadMessageWithHandles(mp, nullptr, 0); -} - -// static -void MojoTestBase::ReadMessage(MojoHandle mp, - char* data, - size_t num_bytes) { - CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK); - - uint32_t message_size = 0; - uint32_t num_handles = 0; - CHECK_EQ(MojoReadMessage(mp, nullptr, &message_size, nullptr, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_RESOURCE_EXHAUSTED); - CHECK_EQ(num_handles, 0u); - CHECK_EQ(message_size, num_bytes); - - CHECK_EQ(MojoReadMessage(mp, data, &message_size, nullptr, &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE), - MOJO_RESULT_OK); - CHECK_EQ(num_handles, 0u); - CHECK_EQ(message_size, num_bytes); -} - -// static -void MojoTestBase::VerifyTransmission(MojoHandle source, - MojoHandle dest, - const std::string& message) { - WriteMessage(source, message); - - // We don't use EXPECT_EQ; failures on really long messages make life hard. - EXPECT_TRUE(message == ReadMessage(dest)); -} - -// static -void MojoTestBase::VerifyEcho(MojoHandle mp, - const std::string& message) { - VerifyTransmission(mp, mp, message); -} - -// static -MojoHandle MojoTestBase::CreateBuffer(uint64_t size) { - MojoHandle h; - EXPECT_EQ(MojoCreateSharedBuffer(nullptr, size, &h), MOJO_RESULT_OK); - return h; -} - -// static -MojoHandle MojoTestBase::DuplicateBuffer(MojoHandle h, bool read_only) { - MojoHandle new_handle; - MojoDuplicateBufferHandleOptions options = { - sizeof(MojoDuplicateBufferHandleOptions), - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE - }; - if (read_only) - options.flags |= MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY; - EXPECT_EQ(MOJO_RESULT_OK, - MojoDuplicateBufferHandle(h, &options, &new_handle)); - return new_handle; -} - -// static -void MojoTestBase::WriteToBuffer(MojoHandle h, - size_t offset, - const base::StringPiece& s) { - char* data; - EXPECT_EQ(MOJO_RESULT_OK, - MojoMapBuffer(h, offset, s.size(), reinterpret_cast(&data), - MOJO_MAP_BUFFER_FLAG_NONE)); - memcpy(data, s.data(), s.size()); - EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(static_cast(data))); -} - -// static -void MojoTestBase::ExpectBufferContents(MojoHandle h, - size_t offset, - const base::StringPiece& s) { - char* data; - EXPECT_EQ(MOJO_RESULT_OK, - MojoMapBuffer(h, offset, s.size(), reinterpret_cast(&data), - MOJO_MAP_BUFFER_FLAG_NONE)); - EXPECT_EQ(s, base::StringPiece(data, s.size())); - EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(static_cast(data))); -} - -// static -void MojoTestBase::CreateDataPipe(MojoHandle *p0, - MojoHandle* p1, - size_t capacity) { - MojoCreateDataPipeOptions options; - options.struct_size = static_cast(sizeof(options)); - options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; - options.element_num_bytes = 1; - options.capacity_num_bytes = static_cast(capacity); - - MojoCreateDataPipe(&options, p0, p1); - CHECK_NE(*p0, MOJO_HANDLE_INVALID); - CHECK_NE(*p1, MOJO_HANDLE_INVALID); -} - -// static -void MojoTestBase::WriteData(MojoHandle producer, const std::string& data) { - CHECK_EQ(WaitForSignals(producer, MOJO_HANDLE_SIGNAL_WRITABLE), - MOJO_RESULT_OK); - uint32_t num_bytes = static_cast(data.size()); - CHECK_EQ(MojoWriteData(producer, data.data(), &num_bytes, - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE), - MOJO_RESULT_OK); - CHECK_EQ(num_bytes, static_cast(data.size())); -} - -// static -std::string MojoTestBase::ReadData(MojoHandle consumer, size_t size) { - CHECK_EQ(WaitForSignals(consumer, MOJO_HANDLE_SIGNAL_READABLE), - MOJO_RESULT_OK); - std::vector buffer(size); - uint32_t num_bytes = static_cast(size); - CHECK_EQ(MojoReadData(consumer, buffer.data(), &num_bytes, - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE), - MOJO_RESULT_OK); - CHECK_EQ(num_bytes, static_cast(size)); - - return std::string(buffer.data(), buffer.size()); -} - -// static -MojoHandleSignalsState MojoTestBase::GetSignalsState(MojoHandle handle) { - MojoHandleSignalsState signals_state; - CHECK_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(handle, &signals_state)); - return signals_state; -} - -// static -MojoResult MojoTestBase::WaitForSignals(MojoHandle handle, - MojoHandleSignals signals, - MojoHandleSignalsState* state) { - return Wait(Handle(handle), signals, state); -} - -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/test/mojo_test_base.h b/mojo/edk/test/mojo_test_base.h deleted file mode 100644 index 35e2c2b..0000000 --- a/mojo/edk/test/mojo_test_base.h +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_TEST_MOJO_TEST_BASE_H_ -#define MOJO_EDK_TEST_MOJO_TEST_BASE_H_ - -#include -#include -#include - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/test/multiprocess_test_helper.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace test { - -class MojoTestBase : public testing::Test { - public: - MojoTestBase(); - ~MojoTestBase() override; - - using LaunchType = MultiprocessTestHelper::LaunchType; - using HandlerCallback = base::Callback; - - class ClientController { - public: - ClientController(const std::string& client_name, - MojoTestBase* test, - const ProcessErrorCallback& process_error_callback, - LaunchType launch_type); - ~ClientController(); - - MojoHandle pipe() const { return pipe_.get().value(); } - - void ClosePeerConnection(); - int WaitForShutdown(); - - private: - friend class MojoTestBase; - -#if !defined(OS_IOS) - MultiprocessTestHelper helper_; -#endif - ScopedMessagePipeHandle pipe_; - bool was_shutdown_ = false; - - DISALLOW_COPY_AND_ASSIGN(ClientController); - }; - - // Set the callback to handle bad messages received from test client - // processes. This can be set to a different callback before starting each - // client. - void set_process_error_callback(const ProcessErrorCallback& callback) { - process_error_callback_ = callback; - } - - ClientController& StartClient(const std::string& client_name); - - template - void StartClientWithHandler(const std::string& client_name, - HandlerFunc handler) { - int expected_exit_code = 0; - ClientController& c = StartClient(client_name); - handler(c.pipe(), &expected_exit_code); - EXPECT_EQ(expected_exit_code, c.WaitForShutdown()); - } - - // Closes a handle and expects success. - static void CloseHandle(MojoHandle h); - - ////// Message pipe test utilities /////// - - // Creates a new pipe, returning endpoint handles in |p0| and |p1|. - static void CreateMessagePipe(MojoHandle* p0, MojoHandle* p1); - - // Writes a string to the pipe, transferring handles in the process. - static void WriteMessageWithHandles(MojoHandle mp, - const std::string& message, - const MojoHandle* handles, - uint32_t num_handles); - - // Writes a string to the pipe with no handles. - static void WriteMessage(MojoHandle mp, const std::string& message); - - // Reads a string from the pipe, expecting to read an exact number of handles - // in the process. Returns the read string. - static std::string ReadMessageWithHandles(MojoHandle mp, - MojoHandle* handles, - uint32_t expected_num_handles); - - // Reads a string from the pipe, expecting either zero or one handles. - // If no handle is read, |handle| will be reset. - static std::string ReadMessageWithOptionalHandle(MojoHandle mp, - MojoHandle* handle); - - // Reads a string from the pipe, expecting to read no handles. - // Returns the string. - static std::string ReadMessage(MojoHandle mp); - - // Reads a string from the pipe, expecting to read no handles and exactly - // |num_bytes| bytes, which are read into |data|. - static void ReadMessage(MojoHandle mp, char* data, size_t num_bytes); - - // Writes |message| to |in| and expects to read it back from |out|. - static void VerifyTransmission(MojoHandle in, - MojoHandle out, - const std::string& message); - - // Writes |message| to |mp| and expects to read it back from the same handle. - static void VerifyEcho(MojoHandle mp, const std::string& message); - - //////// Shared buffer test utilities ///////// - - // Creates a new shared buffer. - static MojoHandle CreateBuffer(uint64_t size); - - // Duplicates a shared buffer to a new handle. - static MojoHandle DuplicateBuffer(MojoHandle h, bool read_only); - - // Maps a buffer, writes some data into it, and unmaps it. - static void WriteToBuffer(MojoHandle h, - size_t offset, - const base::StringPiece& s); - - // Maps a buffer, tests the value of some of its contents, and unmaps it. - static void ExpectBufferContents(MojoHandle h, - size_t offset, - const base::StringPiece& s); - - //////// Data pipe test utilities ///////// - - // Creates a new data pipe. - static void CreateDataPipe(MojoHandle* producer, - MojoHandle* consumer, - size_t capacity); - - // Writes data to a data pipe. - static void WriteData(MojoHandle producer, const std::string& data); - - // Reads data from a data pipe. - static std::string ReadData(MojoHandle consumer, size_t size); - - // Queries the signals state of |handle|. - static MojoHandleSignalsState GetSignalsState(MojoHandle handle); - - // Helper to block the calling thread waiting for signals to be raised. - static MojoResult WaitForSignals(MojoHandle handle, - MojoHandleSignals signals, - MojoHandleSignalsState* state = nullptr); - - void set_launch_type(LaunchType launch_type) { launch_type_ = launch_type; } - - private: - friend class ClientController; - - std::vector> clients_; - - ProcessErrorCallback process_error_callback_; - - LaunchType launch_type_ = LaunchType::CHILD; - - DISALLOW_COPY_AND_ASSIGN(MojoTestBase); -}; - -// Launches a new child process running the test client |client_name| connected -// to a new message pipe bound to |pipe_name|. |pipe_name| is automatically -// closed on test teardown. -#define RUN_CHILD_ON_PIPE(client_name, pipe_name) \ - StartClientWithHandler( \ - #client_name, \ - [&](MojoHandle pipe_name, int *expected_exit_code) { { - -// Waits for the client to terminate and expects a return code of zero. -#define END_CHILD() \ - } \ - *expected_exit_code = 0; \ - }); - -// Wait for the client to terminate with a specific return code. -#define END_CHILD_AND_EXPECT_EXIT_CODE(code) \ - } \ - *expected_exit_code = code; \ - }); - -// Use this to declare the child process's "main()" function for tests using -// MojoTestBase and MultiprocessTestHelper. It returns an |int|, which will -// will be the process's exit code (but see the comment about -// WaitForChildShutdown()). -// -// The function is defined as a subclass of |test_base| to facilitate shared -// code between test clients and to allow clients to spawn children themselves. -// -// |pipe_name| will be bound to the MojoHandle of a message pipe connected -// to the parent process (see RUN_CHILD_ON_PIPE above.) This pipe handle is -// automatically closed on test client teardown. -#if !defined(OS_IOS) -#define DEFINE_TEST_CLIENT_WITH_PIPE(client_name, test_base, pipe_name) \ - class client_name##_MainFixture : public test_base { \ - void TestBody() override {} \ - public: \ - int Main(MojoHandle); \ - }; \ - MULTIPROCESS_TEST_MAIN_WITH_SETUP( \ - client_name##TestChildMain, \ - ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) { \ - client_name##_MainFixture test; \ - return ::mojo::edk::test::MultiprocessTestHelper::RunClientMain( \ - base::Bind(&client_name##_MainFixture::Main, \ - base::Unretained(&test))); \ - } \ - int client_name##_MainFixture::Main(MojoHandle pipe_name) - -// This is a version of DEFINE_TEST_CLIENT_WITH_PIPE which can be used with -// gtest ASSERT/EXPECT macros. -#define DEFINE_TEST_CLIENT_TEST_WITH_PIPE(client_name, test_base, pipe_name) \ - class client_name##_MainFixture : public test_base { \ - void TestBody() override {} \ - public: \ - void Main(MojoHandle); \ - }; \ - MULTIPROCESS_TEST_MAIN_WITH_SETUP( \ - client_name##TestChildMain, \ - ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) { \ - client_name##_MainFixture test; \ - return ::mojo::edk::test::MultiprocessTestHelper::RunClientTestMain( \ - base::Bind(&client_name##_MainFixture::Main, \ - base::Unretained(&test))); \ - } \ - void client_name##_MainFixture::Main(MojoHandle pipe_name) -#else // !defined(OS_IOS) -#define DEFINE_TEST_CLIENT_WITH_PIPE(client_name, test_base, pipe_name) -#define DEFINE_TEST_CLIENT_TEST_WITH_PIPE(client_name, test_base, pipe_name) -#endif // !defined(OS_IOS) - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_TEST_MOJO_TEST_BASE_H_ diff --git a/mojo/edk/test/multiprocess_test_helper.cc b/mojo/edk/test/multiprocess_test_helper.cc deleted file mode 100644 index cf37782..0000000 --- a/mojo/edk/test/multiprocess_test_helper.cc +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/test/multiprocess_test_helper.h" - -#include -#include -#include - -#include "base/base_paths.h" -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/path_service.h" -#include "base/process/kill.h" -#include "base/process/process_handle.h" -#include "base/run_loop.h" -#include "base/strings/stringprintf.h" -#include "base/task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/named_platform_handle.h" -#include "mojo/edk/embedder/named_platform_handle_utils.h" -#include "mojo/edk/embedder/pending_process_connection.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#elif defined(OS_MACOSX) && !defined(OS_IOS) -#include "base/mac/mach_port_broker.h" -#endif - -namespace mojo { -namespace edk { -namespace test { - -namespace { - -const char kMojoPrimordialPipeToken[] = "mojo-primordial-pipe-token"; -const char kMojoNamedPipeName[] = "mojo-named-pipe-name"; - -template -int RunClientFunction(Func handler, bool pass_pipe_ownership_to_main) { - CHECK(MultiprocessTestHelper::primordial_pipe.is_valid()); - ScopedMessagePipeHandle pipe = - std::move(MultiprocessTestHelper::primordial_pipe); - MessagePipeHandle pipe_handle = - pass_pipe_ownership_to_main ? pipe.release() : pipe.get(); - return handler(pipe_handle.value()); -} - -} // namespace - -MultiprocessTestHelper::MultiprocessTestHelper() {} - -MultiprocessTestHelper::~MultiprocessTestHelper() { - CHECK(!test_child_.process.IsValid()); -} - -ScopedMessagePipeHandle MultiprocessTestHelper::StartChild( - const std::string& test_child_name, - LaunchType launch_type) { - return StartChildWithExtraSwitch(test_child_name, std::string(), - std::string(), launch_type); -} - -ScopedMessagePipeHandle MultiprocessTestHelper::StartChildWithExtraSwitch( - const std::string& test_child_name, - const std::string& switch_string, - const std::string& switch_value, - LaunchType launch_type) { - CHECK(!test_child_name.empty()); - CHECK(!test_child_.process.IsValid()); - - std::string test_child_main = test_child_name + "TestChildMain"; - - // Manually construct the new child's commandline to avoid copying unwanted - // values. - base::CommandLine command_line( - base::GetMultiProcessTestChildBaseCommandLine().GetProgram()); - - std::set uninherited_args; - uninherited_args.insert("mojo-platform-channel-handle"); - uninherited_args.insert(switches::kTestChildProcess); - - // Copy commandline switches from the parent process, except for the - // multiprocess client name and mojo message pipe handle; this allows test - // clients to spawn other test clients. - for (const auto& entry : - base::CommandLine::ForCurrentProcess()->GetSwitches()) { - if (uninherited_args.find(entry.first) == uninherited_args.end()) - command_line.AppendSwitchNative(entry.first, entry.second); - } - - PlatformChannelPair channel; - NamedPlatformHandle named_pipe; - HandlePassingInformation handle_passing_info; - if (launch_type == LaunchType::CHILD || launch_type == LaunchType::PEER) { - channel.PrepareToPassClientHandleToChildProcess(&command_line, - &handle_passing_info); - } else if (launch_type == LaunchType::NAMED_CHILD || - launch_type == LaunchType::NAMED_PEER) { -#if defined(OS_POSIX) - base::FilePath temp_dir; - CHECK(base::PathService::Get(base::DIR_TEMP, &temp_dir)); - named_pipe = NamedPlatformHandle( - temp_dir.AppendASCII(GenerateRandomToken()).value()); -#else - named_pipe = NamedPlatformHandle(GenerateRandomToken()); -#endif - command_line.AppendSwitchNative(kMojoNamedPipeName, named_pipe.name); - } - - if (!switch_string.empty()) { - CHECK(!command_line.HasSwitch(switch_string)); - if (!switch_value.empty()) - command_line.AppendSwitchASCII(switch_string, switch_value); - else - command_line.AppendSwitch(switch_string); - } - - base::LaunchOptions options; -#if defined(OS_POSIX) - options.fds_to_remap = &handle_passing_info; -#elif defined(OS_WIN) - options.start_hidden = true; - if (base::win::GetVersion() >= base::win::VERSION_VISTA) - options.handles_to_inherit = &handle_passing_info; - else - options.inherit_handles = true; -#else -#error "Not supported yet." -#endif - - // NOTE: In the case of named pipes, it's important that the server handle be - // created before the child process is launched; otherwise the server binding - // the pipe path can race with child's connection to the pipe. - ScopedPlatformHandle server_handle; - if (launch_type == LaunchType::CHILD || launch_type == LaunchType::PEER) { - server_handle = channel.PassServerHandle(); - } else if (launch_type == LaunchType::NAMED_CHILD || - launch_type == LaunchType::NAMED_PEER) { - server_handle = CreateServerHandle(named_pipe); - } - - PendingProcessConnection process; - ScopedMessagePipeHandle pipe; - if (launch_type == LaunchType::CHILD || - launch_type == LaunchType::NAMED_CHILD) { - std::string pipe_token; - pipe = process.CreateMessagePipe(&pipe_token); - command_line.AppendSwitchASCII(kMojoPrimordialPipeToken, pipe_token); - } else if (launch_type == LaunchType::PEER || - launch_type == LaunchType::NAMED_PEER) { - peer_token_ = mojo::edk::GenerateRandomToken(); - pipe = ConnectToPeerProcess(std::move(server_handle), peer_token_); - } - - test_child_ = - base::SpawnMultiProcessTestChild(test_child_main, command_line, options); - if (launch_type == LaunchType::CHILD || launch_type == LaunchType::PEER) - channel.ChildProcessLaunched(); - - if (launch_type == LaunchType::CHILD || - launch_type == LaunchType::NAMED_CHILD) { - DCHECK(server_handle.is_valid()); - process.Connect(test_child_.process.Handle(), - ConnectionParams(std::move(server_handle)), - process_error_callback_); - } - - CHECK(test_child_.process.IsValid()); - return pipe; -} - -int MultiprocessTestHelper::WaitForChildShutdown() { - CHECK(test_child_.process.IsValid()); - - int rv = -1; - WaitForMultiprocessTestChildExit(test_child_.process, - TestTimeouts::action_timeout(), &rv); - test_child_.process.Close(); - return rv; -} - -void MultiprocessTestHelper::ClosePeerConnection() { - DCHECK(!peer_token_.empty()); - ::mojo::edk::ClosePeerConnection(peer_token_); - peer_token_.clear(); -} - -bool MultiprocessTestHelper::WaitForChildTestShutdown() { - return WaitForChildShutdown() == 0; -} - -// static -void MultiprocessTestHelper::ChildSetup() { - CHECK(base::CommandLine::InitializedForCurrentProcess()); - - std::string primordial_pipe_token = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - kMojoPrimordialPipeToken); - NamedPlatformHandle named_pipe( - base::CommandLine::ForCurrentProcess()->GetSwitchValueNative( - kMojoNamedPipeName)); - if (!primordial_pipe_token.empty()) { - primordial_pipe = CreateChildMessagePipe(primordial_pipe_token); -#if defined(OS_MACOSX) && !defined(OS_IOS) - CHECK(base::MachPortBroker::ChildSendTaskPortToParent("mojo_test")); -#endif - if (named_pipe.is_valid()) { - SetParentPipeHandle(CreateClientHandle(named_pipe)); - } else { - SetParentPipeHandle( - PlatformChannelPair::PassClientHandleFromParentProcess( - *base::CommandLine::ForCurrentProcess())); - } - } else { - if (named_pipe.is_valid()) { - primordial_pipe = ConnectToPeerProcess(CreateClientHandle(named_pipe)); - } else { - primordial_pipe = ConnectToPeerProcess( - PlatformChannelPair::PassClientHandleFromParentProcess( - *base::CommandLine::ForCurrentProcess())); - } - } -} - -// static -int MultiprocessTestHelper::RunClientMain( - const base::Callback& main, - bool pass_pipe_ownership_to_main) { - return RunClientFunction( - [main](MojoHandle handle) { return main.Run(handle); }, - pass_pipe_ownership_to_main); -} - -// static -int MultiprocessTestHelper::RunClientTestMain( - const base::Callback& main) { - return RunClientFunction( - [main](MojoHandle handle) { - main.Run(handle); - return (::testing::Test::HasFatalFailure() || - ::testing::Test::HasNonfatalFailure()) - ? 1 - : 0; - }, - true /* close_pipe_on_exit */); -} - -// static -mojo::ScopedMessagePipeHandle MultiprocessTestHelper::primordial_pipe; - -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/test/multiprocess_test_helper.h b/mojo/edk/test/multiprocess_test_helper.h deleted file mode 100644 index dc1c9bc..0000000 --- a/mojo/edk/test/multiprocess_test_helper.h +++ /dev/null @@ -1,110 +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_TEST_MULTIPROCESS_TEST_HELPER_H_ -#define MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_ - -#include - -#include "base/callback.h" -#include "base/macros.h" -#include "base/process/process.h" -#include "base/test/multiprocess_test.h" -#include "base/test/test_timeouts.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/public/cpp/system/message_pipe.h" -#include "testing/multiprocess_func_list.h" - -namespace mojo { - -namespace edk { - -namespace test { - -class MultiprocessTestHelper { - public: - using HandlerCallback = base::Callback; - - enum class LaunchType { - // Launch the child process as a child in the mojo system. - CHILD, - - // Launch the child process as an unrelated peer process in the mojo system. - PEER, - - // Launch the child process as a child in the mojo system, using a named - // pipe. - NAMED_CHILD, - - // Launch the child process as an unrelated peer process in the mojo - // system, using a named pipe. - NAMED_PEER, - }; - - MultiprocessTestHelper(); - ~MultiprocessTestHelper(); - - // Start a child process and run the "main" function "named" |test_child_name| - // declared using |MOJO_MULTIPROCESS_TEST_CHILD_MAIN()| or - // |MOJO_MULTIPROCESS_TEST_CHILD_TEST()| (below). - ScopedMessagePipeHandle StartChild( - const std::string& test_child_name, - LaunchType launch_type = LaunchType::CHILD); - - // Like |StartChild()|, but appends an extra switch (with ASCII value) to the - // command line. (The switch must not already be present in the default - // command line.) - ScopedMessagePipeHandle StartChildWithExtraSwitch( - const std::string& test_child_name, - const std::string& switch_string, - const std::string& switch_value, - LaunchType launch_type); - - void set_process_error_callback(const ProcessErrorCallback& callback) { - process_error_callback_ = callback; - } - - void ClosePeerConnection(); - - // Wait for the child process to terminate. - // Returns the exit code of the child process. Note that, though it's declared - // to be an |int|, the exit code is subject to mangling by the OS. E.g., we - // usually return -1 on error in the child (e.g., if |test_child_name| was not - // found), but this is mangled to 255 on Linux. You should only rely on codes - // 0-127 being preserved, and -1 being outside the range 0-127. - int WaitForChildShutdown(); - - // Like |WaitForChildShutdown()|, but returns true on success (exit code of 0) - // and false otherwise. You probably want to do something like - // |EXPECT_TRUE(WaitForChildTestShutdown());|. - bool WaitForChildTestShutdown(); - - const base::Process& test_child() const { return test_child_.process; } - - // Used by macros in mojo/edk/test/mojo_test_base.h to support multiprocess - // test client initialization. - static void ChildSetup(); - static int RunClientMain(const base::Callback& main, - bool pass_pipe_ownership_to_main = false); - static int RunClientTestMain(const base::Callback& main); - - // For use (and only valid) in the child process: - static mojo::ScopedMessagePipeHandle primordial_pipe; - - private: - // Valid after |StartChild()| and before |WaitForChildShutdown()|. - base::SpawnChildResult test_child_; - - ProcessErrorCallback process_error_callback_; - - std::string peer_token_; - - DISALLOW_COPY_AND_ASSIGN(MultiprocessTestHelper); -}; - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_ diff --git a/mojo/edk/test/multiprocess_test_helper_unittest.cc b/mojo/edk/test/multiprocess_test_helper_unittest.cc deleted file mode 100644 index f7e9e83..0000000 --- a/mojo/edk/test/multiprocess_test_helper_unittest.cc +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/test/multiprocess_test_helper.h" - -#include - -#include - -#include "base/logging.h" -#include "build/build_config.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/edk/test/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_POSIX) -#include -#endif - -namespace mojo { -namespace edk { -namespace test { -namespace { - -bool IsNonBlocking(const PlatformHandle& handle) { -#if defined(OS_WIN) - // Haven't figured out a way to query whether a HANDLE was created with - // FILE_FLAG_OVERLAPPED. - return true; -#else - return fcntl(handle.handle, F_GETFL) & O_NONBLOCK; -#endif -} - -bool WriteByte(const PlatformHandle& handle, char c) { - size_t bytes_written = 0; - BlockingWrite(handle, &c, 1, &bytes_written); - return bytes_written == 1; -} - -bool ReadByte(const PlatformHandle& handle, char* c) { - size_t bytes_read = 0; - BlockingRead(handle, c, 1, &bytes_read); - return bytes_read == 1; -} - -using MultiprocessTestHelperTest = testing::Test; - -TEST_F(MultiprocessTestHelperTest, RunChild) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - - helper.StartChild("RunChild"); - EXPECT_EQ(123, helper.WaitForChildShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild) { - CHECK(MultiprocessTestHelper::client_platform_handle.is_valid()); - return 123; -} - -TEST_F(MultiprocessTestHelperTest, TestChildMainNotFound) { - MultiprocessTestHelper helper; - helper.StartChild("NoSuchTestChildMain"); - int result = helper.WaitForChildShutdown(); - EXPECT_FALSE(result >= 0 && result <= 127); -} - -TEST_F(MultiprocessTestHelperTest, PassedChannel) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - helper.StartChild("PassedChannel"); - - // Take ownership of the handle. - ScopedPlatformHandle handle = std::move(helper.server_platform_handle); - - // The handle should be non-blocking. - EXPECT_TRUE(IsNonBlocking(handle.get())); - - // Write a byte. - const char c = 'X'; - EXPECT_TRUE(WriteByte(handle.get(), c)); - - // It'll echo it back to us, incremented. - char d = 0; - EXPECT_TRUE(ReadByte(handle.get(), &d)); - EXPECT_EQ(c + 1, d); - - // And return it, incremented again. - EXPECT_EQ(c + 2, helper.WaitForChildShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannel) { - CHECK(MultiprocessTestHelper::client_platform_handle.is_valid()); - - // Take ownership of the handle. - ScopedPlatformHandle handle = - std::move(MultiprocessTestHelper::client_platform_handle); - - // The handle should be non-blocking. - EXPECT_TRUE(IsNonBlocking(handle.get())); - - // Read a byte. - char c = 0; - EXPECT_TRUE(ReadByte(handle.get(), &c)); - - // Write it back, incremented. - c++; - EXPECT_TRUE(WriteByte(handle.get(), c)); - - // And return it, incremented again. - c++; - return static_cast(c); -} - -TEST_F(MultiprocessTestHelperTest, ChildTestPasses) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - helper.StartChild("ChildTestPasses"); - EXPECT_TRUE(helper.WaitForChildTestShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestPasses) { - ASSERT_TRUE(MultiprocessTestHelper::client_platform_handle.is_valid()); - EXPECT_TRUE( - IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get())); -} - -TEST_F(MultiprocessTestHelperTest, ChildTestFailsAssert) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - helper.StartChild("ChildTestFailsAssert"); - EXPECT_FALSE(helper.WaitForChildTestShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsAssert) { - ASSERT_FALSE(MultiprocessTestHelper::client_platform_handle.is_valid()) - << "DISREGARD: Expected failure in child process"; - ASSERT_FALSE( - IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get())) - << "Not reached"; - CHECK(false) << "Not reached"; -} - -TEST_F(MultiprocessTestHelperTest, ChildTestFailsExpect) { - MultiprocessTestHelper helper; - EXPECT_TRUE(helper.server_platform_handle.is_valid()); - helper.StartChild("ChildTestFailsExpect"); - EXPECT_FALSE(helper.WaitForChildTestShutdown()); -} - -MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsExpect) { - EXPECT_FALSE(MultiprocessTestHelper::client_platform_handle.is_valid()) - << "DISREGARD: Expected failure #1 in child process"; - EXPECT_FALSE( - IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get())) - << "DISREGARD: Expected failure #2 in child process"; -} - -} // namespace -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/test/run_all_perftests.cc b/mojo/edk/test/run_all_perftests.cc deleted file mode 100644 index 3ce3b47..0000000 --- a/mojo/edk/test/run_all_perftests.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/command_line.h" -#include "base/test/multiprocess_test.h" -#include "base/test/perf_test_suite.h" -#include "base/test/test_io_thread.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" -#include "mojo/edk/test/multiprocess_test_helper.h" -#include "mojo/edk/test/test_support_impl.h" -#include "mojo/public/tests/test_support_private.h" - -int main(int argc, char** argv) { - base::PerfTestSuite test(argc, argv); - - mojo::edk::Init(); - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - mojo::edk::ScopedIPCSupport ipc_support( - test_io_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); - mojo::test::TestSupport::Init(new mojo::edk::test::TestSupportImpl()); - - return test.Run(); -} diff --git a/mojo/edk/test/run_all_unittests.cc b/mojo/edk/test/run_all_unittests.cc deleted file mode 100644 index a057825..0000000 --- a/mojo/edk/test/run_all_unittests.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/multiprocess_test.h" -#include "base/test/test_io_thread.h" -#include "base/test/test_suite.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" -#include "mojo/edk/test/multiprocess_test_helper.h" -#include "mojo/edk/test/test_support_impl.h" -#include "mojo/public/tests/test_support_private.h" -#include "testing/gtest/include/gtest/gtest.h" - -int main(int argc, char** argv) { -#if !defined(OS_ANDROID) - // Silence death test thread warnings on Linux. We can afford to run our death - // tests a little more slowly (< 10 ms per death test on a Z620). - // On android, we need to run in the default mode, as the threadsafe mode - // relies on execve which is not available. - testing::GTEST_FLAG(death_test_style) = "threadsafe"; -#endif -#if defined(OS_ANDROID) - // On android, the test framework has a signal handler that will print a - // [ CRASH ] line when the application crashes. This breaks death test has the - // test runner will consider the death of the child process a test failure. - // Removing the signal handler solves this issue. - signal(SIGABRT, SIG_DFL); -#endif - - base::TestSuite test_suite(argc, argv); - - mojo::edk::Init(); - - mojo::test::TestSupport::Init(new mojo::edk::test::TestSupportImpl()); - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); - - mojo::edk::ScopedIPCSupport ipc_support( - test_io_thread.task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN); - return base::LaunchUnitTests( - argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); -} diff --git a/mojo/edk/test/test_support_impl.cc b/mojo/edk/test/test_support_impl.cc deleted file mode 100644 index 25684e4..0000000 --- a/mojo/edk/test/test_support_impl.cc +++ /dev/null @@ -1,84 +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/test/test_support_impl.h" - -#include -#include -#include - -#include - -#include "base/files/file_enumerator.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/test/perf_log.h" - -namespace mojo { -namespace edk { -namespace test { -namespace { - -base::FilePath ResolveSourceRootRelativePath(const char* relative_path) { - base::FilePath path; - if (!PathService::Get(base::DIR_SOURCE_ROOT, &path)) - return base::FilePath(); - - for (const base::StringPiece& component : base::SplitStringPiece( - relative_path, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { - if (!component.empty()) - path = path.AppendASCII(component); - } - - return path; -} - -} // namespace - -TestSupportImpl::TestSupportImpl() { -} - -TestSupportImpl::~TestSupportImpl() { -} - -void TestSupportImpl::LogPerfResult(const char* test_name, - const char* sub_test_name, - double value, - const char* units) { - DCHECK(test_name); - if (sub_test_name) { - std::string name = base::StringPrintf("%s/%s", test_name, sub_test_name); - base::LogPerfResult(name.c_str(), value, units); - } else { - base::LogPerfResult(test_name, value, units); - } -} - -FILE* TestSupportImpl::OpenSourceRootRelativeFile(const char* relative_path) { - return base::OpenFile(ResolveSourceRootRelativePath(relative_path), "rb"); -} - -char** TestSupportImpl::EnumerateSourceRootRelativeDirectory( - const char* relative_path) { - std::vector names; - base::FileEnumerator e(ResolveSourceRootRelativePath(relative_path), false, - base::FileEnumerator::FILES); - for (base::FilePath name = e.Next(); !name.empty(); name = e.Next()) - names.push_back(name.BaseName().AsUTF8Unsafe()); - - // |names.size() + 1| for null terminator. - char** rv = static_cast(calloc(names.size() + 1, sizeof(char*))); - for (size_t i = 0; i < names.size(); ++i) - rv[i] = base::strdup(names[i].c_str()); - return rv; -} - -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/test/test_support_impl.h b/mojo/edk/test/test_support_impl.h deleted file mode 100644 index ebb5ce6..0000000 --- a/mojo/edk/test/test_support_impl.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_ -#define MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_ - -#include - -#include "base/macros.h" -#include "mojo/public/tests/test_support_private.h" - -namespace mojo { -namespace edk { -namespace test { - -class TestSupportImpl : public mojo::test::TestSupport { - public: - TestSupportImpl(); - ~TestSupportImpl() override; - - void LogPerfResult(const char* test_name, - const char* sub_test_name, - double value, - const char* units) override; - FILE* OpenSourceRootRelativeFile(const char* relative_path) override; - char** EnumerateSourceRootRelativeDirectory( - const char* relative_path) override; - - private: - DISALLOW_COPY_AND_ASSIGN(TestSupportImpl); -}; - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_TEST_TEST_SUPPORT_IMPL_H_ diff --git a/mojo/edk/test/test_utils.h b/mojo/edk/test/test_utils.h deleted file mode 100644 index 939171b..0000000 --- a/mojo/edk/test/test_utils.h +++ /dev/null @@ -1,55 +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_TEST_TEST_UTILS_H_ -#define MOJO_EDK_TEST_TEST_UTILS_H_ - -#include -#include - -#include - -#include "base/files/scoped_file.h" -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" - -namespace mojo { -namespace edk { -namespace test { - -// On success, |bytes_written| is updated to the number of bytes written; -// otherwise it is untouched. -bool BlockingWrite(const PlatformHandle& handle, - const void* buffer, - size_t bytes_to_write, - size_t* bytes_written); - -// On success, |bytes_read| is updated to the number of bytes read; otherwise it -// is untouched. -bool BlockingRead(const PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read); - -// If the read is done successfully or would block, the function returns true -// and updates |bytes_read| to the number of bytes read (0 if the read would -// block); otherwise it returns false and leaves |bytes_read| untouched. -// |handle| must already be in non-blocking mode. -bool NonBlockingRead(const PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read); - -// Gets a (scoped) |PlatformHandle| from the given (scoped) |FILE|. -ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp); - -// Gets a (scoped) |FILE| from a (scoped) |PlatformHandle|. -base::ScopedFILE FILEFromPlatformHandle(ScopedPlatformHandle h, - const char* mode); - -} // namespace test -} // namespace edk -} // namespace mojo - -#endif // MOJO_EDK_TEST_TEST_UTILS_H_ diff --git a/mojo/edk/test/test_utils_posix.cc b/mojo/edk/test/test_utils_posix.cc deleted file mode 100644 index 60d5db5..0000000 --- a/mojo/edk/test/test_utils_posix.cc +++ /dev/null @@ -1,94 +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/test/test_utils.h" - -#include -#include -#include - -#include "base/posix/eintr_wrapper.h" - -namespace mojo { -namespace edk { -namespace test { - -bool BlockingWrite(const PlatformHandle& handle, - const void* buffer, - size_t bytes_to_write, - size_t* bytes_written) { - int original_flags = fcntl(handle.handle, F_GETFL); - if (original_flags == -1 || - fcntl(handle.handle, F_SETFL, original_flags & (~O_NONBLOCK)) != 0) { - return false; - } - - ssize_t result = HANDLE_EINTR(write(handle.handle, buffer, bytes_to_write)); - - fcntl(handle.handle, F_SETFL, original_flags); - - if (result < 0) - return false; - - *bytes_written = result; - return true; -} - -bool BlockingRead(const PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read) { - int original_flags = fcntl(handle.handle, F_GETFL); - if (original_flags == -1 || - fcntl(handle.handle, F_SETFL, original_flags & (~O_NONBLOCK)) != 0) { - return false; - } - - ssize_t result = HANDLE_EINTR(read(handle.handle, buffer, buffer_size)); - - fcntl(handle.handle, F_SETFL, original_flags); - - if (result < 0) - return false; - - *bytes_read = result; - return true; -} - -bool NonBlockingRead(const PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read) { - ssize_t result = HANDLE_EINTR(read(handle.handle, buffer, buffer_size)); - - if (result < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) - return false; - - *bytes_read = 0; - } else { - *bytes_read = result; - } - - return true; -} - -ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) { - CHECK(fp); - int rv = dup(fileno(fp.get())); - PCHECK(rv != -1) << "dup"; - return ScopedPlatformHandle(PlatformHandle(rv)); -} - -base::ScopedFILE FILEFromPlatformHandle(ScopedPlatformHandle h, - const char* mode) { - CHECK(h.is_valid()); - base::ScopedFILE rv(fdopen(h.release().handle, mode)); - PCHECK(rv) << "fdopen"; - return rv; -} - -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/edk/test/test_utils_win.cc b/mojo/edk/test/test_utils_win.cc deleted file mode 100644 index 17bf5bb..0000000 --- a/mojo/edk/test/test_utils_win.cc +++ /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. - -#include "mojo/edk/test/test_utils.h" - -#include -#include -#include -#include -#include - -namespace mojo { -namespace edk { -namespace test { - -bool BlockingWrite(const PlatformHandle& handle, - const void* buffer, - size_t bytes_to_write, - size_t* bytes_written) { - OVERLAPPED overlapped = {0}; - DWORD bytes_written_dword = 0; - - if (!WriteFile(handle.handle, buffer, static_cast(bytes_to_write), - &bytes_written_dword, &overlapped)) { - if (GetLastError() != ERROR_IO_PENDING || - !GetOverlappedResult(handle.handle, &overlapped, &bytes_written_dword, - TRUE)) { - return false; - } - } - - *bytes_written = bytes_written_dword; - return true; -} - -bool BlockingRead(const PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read) { - OVERLAPPED overlapped = {0}; - DWORD bytes_read_dword = 0; - - if (!ReadFile(handle.handle, buffer, static_cast(buffer_size), - &bytes_read_dword, &overlapped)) { - if (GetLastError() != ERROR_IO_PENDING || - !GetOverlappedResult(handle.handle, &overlapped, &bytes_read_dword, - TRUE)) { - return false; - } - } - - *bytes_read = bytes_read_dword; - return true; -} - -bool NonBlockingRead(const PlatformHandle& handle, - void* buffer, - size_t buffer_size, - size_t* bytes_read) { - OVERLAPPED overlapped = {0}; - DWORD bytes_read_dword = 0; - - if (!ReadFile(handle.handle, buffer, static_cast(buffer_size), - &bytes_read_dword, &overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) - return false; - - CancelIo(handle.handle); - - if (!GetOverlappedResult(handle.handle, &overlapped, &bytes_read_dword, - TRUE)) { - *bytes_read = 0; - return true; - } - } - - *bytes_read = bytes_read_dword; - return true; -} - -ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) { - CHECK(fp); - - HANDLE rv = INVALID_HANDLE_VALUE; - PCHECK(DuplicateHandle( - GetCurrentProcess(), - reinterpret_cast(_get_osfhandle(_fileno(fp.get()))), - GetCurrentProcess(), &rv, 0, TRUE, DUPLICATE_SAME_ACCESS)) - << "DuplicateHandle"; - return ScopedPlatformHandle(PlatformHandle(rv)); -} - -base::ScopedFILE FILEFromPlatformHandle(ScopedPlatformHandle h, - const char* mode) { - CHECK(h.is_valid()); - // Microsoft's documentation for |_open_osfhandle()| only discusses these - // flags (and |_O_WTEXT|). Hmmm. - int flags = 0; - if (strchr(mode, 'a')) - flags |= _O_APPEND; - if (strchr(mode, 'r')) - flags |= _O_RDONLY; - if (strchr(mode, 't')) - flags |= _O_TEXT; - base::ScopedFILE rv(_fdopen( - _open_osfhandle(reinterpret_cast(h.release().handle), flags), - mode)); - PCHECK(rv) << "_fdopen"; - return rv; -} - -} // namespace test -} // namespace edk -} // namespace mojo diff --git a/mojo/public/BUILD.gn b/mojo/public/BUILD.gn deleted file mode 100644 index 3baf667..0000000 --- a/mojo/public/BUILD.gn +++ /dev/null @@ -1,28 +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. - -group("public") { - # Meta-target, don't link into production code. - testonly = true - deps = [ - ":sdk", - "cpp/bindings", - "interfaces/bindings/tests:test_interfaces", - ] - - if (is_android) { - deps += [ - "java:bindings_java", - "java:system_java", - ] - } -} - -group("sdk") { - deps = [ - "c/system", - "cpp/bindings", - "js", - ] -} diff --git a/mojo/public/DEPS b/mojo/public/DEPS deleted file mode 100644 index 2e49995..0000000 --- a/mojo/public/DEPS +++ /dev/null @@ -1,11 +0,0 @@ -include_rules = [ - # This code is checked into the chromium repo so it's fine to depend on this. - "+base", - "+build", - "+testing", - - "+ipc/ipc_param_traits.h", - - # internal includes. - "+mojo", -] diff --git a/mojo/public/LICENSE b/mojo/public/LICENSE deleted file mode 100644 index 972bb2e..0000000 --- a/mojo/public/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -// 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/mojo/public/c/system/BUILD.gn b/mojo/public/c/system/BUILD.gn deleted file mode 100644 index 08185c7..0000000 --- a/mojo/public/c/system/BUILD.gn +++ /dev/null @@ -1,37 +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. - -component("system") { - output_name = "mojo_public_system" - - sources = [ - "buffer.h", - "core.h", - "data_pipe.h", - "functions.h", - "macros.h", - "message_pipe.h", - "platform_handle.h", - "system_export.h", - "thunks.cc", - "thunks.h", - "types.h", - "watcher.h", - ] - - defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ] -} - -# This should ONLY be depended upon directly by shared_library targets which -# need to export the MojoSetSystemThunks symbol, like targets generated by the -# mojo_native_application template in //services/service_manager/public/cpp/service.gni. -source_set("set_thunks_for_app") { - sources = [ - "set_thunks_for_app.cc", - ] - - public_deps = [ - ":system", - ] -} diff --git a/mojo/public/c/system/README.md b/mojo/public/c/system/README.md deleted file mode 100644 index 2abe80f..0000000 --- a/mojo/public/c/system/README.md +++ /dev/null @@ -1,869 +0,0 @@ -# ![Mojo Graphic](https://goo.gl/6CdlbH) Mojo C System API -This document is a subset of the [Mojo documentation](/mojo). - -[TOC] - -## Overview -The Mojo C System API is a lightweight API (with an eventually-stable ABI) upon -which all higher layers of the Mojo system are built. - -This API exposes the fundamental capabilities to: create, read from, and write -to **message pipes**; create, read from, and write to **data pipes**; create -**shared buffers** and generate sharable handles to them; wrap platform-specific -handle objects (such as **file descriptors**, **Windows handles**, and -**Mach ports**) for seamless transit over message pipes; and efficiently watch -handles for various types of state transitions. - -This document provides a brief guide to API usage with example code snippets. -For a detailed API references please consult the headers in -[//mojo/public/c/system](https://cs.chromium.org/chromium/src/mojo/public/c/system/). - -### A Note About Multithreading - -The Mojo C System API is entirely thread-agnostic. This means that all functions -may be called from any thread in a process, and there are no restrictions on how -many threads can use the same object at the same time. - -Of course this does not mean you can completely ignore potential concurrency -issues -- such as a handle being closed on one thread while another thread is -trying to perform an operation on the same handle -- but there is nothing -fundamentally incorrect about using any given API or handle from multiple -threads. - -### A Note About Synchronization - -Every Mojo API call is non-blocking and synchronously yields some kind of status -result code, but the call's side effects -- such as affecting the state of -one or more handles in the system -- may or may not occur asynchronously. - -Mojo objects can be observed for interesting state changes in a way that is -thread-agnostic and in some ways similar to POSIX signal handlers: *i.e.* -user-provided notification handlers may be invoked at any time on arbitrary -threads in the process. It is entirely up to the API user to take appropriate -measures to synchronize operations against other application state. - -The higher level [system](/mojo#High-Level-System-APIs) and -[bindings](/mojo#High-Level-Bindings-APIs) APIs provide helpers to simplify Mojo -usage in this regard, at the expense of some flexibility. - -## Result Codes - -Most API functions return a value of type `MojoResult`. This is an integral -result code used to convey some meaningful level of detail about the result of a -requested operation. - -See [//mojo/public/c/system/types.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/types.h) -for different possible values. See documentation for individual API calls for -more specific contextual meaning of various result codes. - -## Handles - -Every Mojo IPC primitive is identified by a generic, opaque integer handle of -type `MojoHandle`. Handles can be acquired by creating new objects using various -API calls, or by reading messages which contain attached handles. - -A `MojoHandle` can represent a message pipe endpoint, a data pipe consumer, -a data pipe producer, a shared buffer reference, a wrapped native platform -handle such as a POSIX file descriptor or a Windows system handle, or a watcher -object (see [Signals & Watchers](#Signals-Watchers) below.) - -All types of handles except for watchers (which are an inherently local concept) -can be attached to messages and sent over message pipes. - -Any `MojoHandle` may be closed by calling `MojoClose`: - -``` c -MojoHandle x = DoSomethingToGetAValidHandle(); -MojoResult result = MojoClose(x); -``` - -If the handle passed to `MojoClose` was a valid handle, it will be closed and -`MojoClose` returns `MOJO_RESULT_OK`. Otherwise it returns -`MOJO_RESULT_INVALID_ARGUMENT`. - -Similar to native system handles on various popular platforms, `MojoHandle` -values may be reused over time. Thus it is important to avoid logical errors -which lead to misplaced handle ownership, double-closes, *etc.* - -## Message Pipes - -A message pipe is a bidirectional messaging channel which can carry arbitrary -unstructured binary messages with zero or more `MojoHandle` attachments to be -transferred from one end of a pipe to the other. Message pipes work seamlessly -across process boundaries or within a single process. - -The [Embedder Development Kit (EDK)](/mojo/edk/embedder) provides the means to -bootstrap one or more primordial cross-process message pipes, and it's up to -Mojo embedders to expose this capability in some useful way. Once such a pipe is -established, additional handles -- including other message pipe handles -- may -be sent to a remote process using that pipe (or in turn, over other pipes sent -over that pipe, or pipes sent over *that* pipe, and so on...) - -The public C System API exposes the ability to read and write messages on pipes -and to create new message pipes. - -See [//mojo/public/c/system/message_pipe.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/message_pipe.h) -for detailed message pipe API documentation. - -### Creating Message Pipes - -`MojoCreateMessagePipe` can be used to create a new message pipe: - -``` c -MojoHandle a, b; -MojoResult result = MojoCreateMessagePipe(NULL, &a, &b); -``` - -After this snippet, `result` should be `MOJO_RESULT_OK` (it's really hard for -this to fail!), and `a` and `b` will contain valid Mojo handles, one for each -end of the new message pipe. - -Any messages written to `a` are eventually readable from `b`, and any messages -written to `b` are eventually readable from `a`. If `a` is closed at any point, -`b` will eventually become aware of this fact; likewise if `b` is closed, `a` -will become aware of that. - -The state of these conditions can be queried and watched asynchronously as -described in the [Signals & Watchers](#Signals-Watchers) section below. - -### Allocating Messages - -In order to avoid redundant internal buffer copies, Mojo would like to allocate -your message storage buffers for you. This is easy: - -``` c -MojoMessageHandle message; -MojoResult result = MojoAllocMessage(6, NULL, 0, MOJO_ALLOC_MESSAGE_FLAG_NONE, - &message); -``` - -Note that we have a special `MojoMessageHandle` type for message objects. - -The code above allocates a buffer for a message payload of 6 bytes with no -handles attached. - -If we change our mind and decide not to send this message, we can delete it: - -``` c -MojoResult result = MojoFreeMessage(message); -``` - -If we instead decide to send our newly allocated message, we first need to fill -in the payload data with something interesting. How about a pleasant greeting: - -``` c -void* buffer = NULL; -MojoResult result = MojoGetMessageBuffer(message, &buffer); -memcpy(buffer, "hello", 6); -``` - -Now we can write the message to a pipe. Note that attempting to write a message -transfers ownership of the message object (and any attached handles) into the -target pipe and there is therefore no need to subsequently call -`MojoFreeMessage` on that message. - -### Writing Messages - -``` c -result = MojoWriteMessageNew(a, message, MOJO_WRITE_MESSAGE_FLAG_NONE); -``` - -`MojoWriteMessage` is a *non-blocking* call: it always returns -immediately. If its return code is `MOJO_RESULT_OK` the message will eventually -find its way to the other end of the pipe -- assuming that end isn't closed -first, of course. If the return code is anything else, the message is deleted -and not transferred. - -In this case since we know `b` is still open, we also know the message will -eventually arrive at `b`. `b` can be queried or watched to become aware of when -the message arrives, but we'll ignore that complexity for now. See -[Signals & Watchers](#Signals-Watchers) below for more information. - -*** aside -**NOTE**: Although this is an implementation detail and not strictly guaranteed by the -System API, it is true in the current implementation that the message will -arrive at `b` before the above `MojoWriteMessage` call even returns, because `b` -is in the same process as `a` and has never been transferred over another pipe. -*** - -### Reading Messages - -We can read a new message object from a pipe: - -``` c -MojoMessageHandle message; -uint32_t num_bytes; -MojoResult result = MojoReadMessageNew(b, &message, &num_bytes, NULL, NULL, - MOJO_READ_MESSAGE_FLAG_NONE); -``` - -and map its buffer to retrieve the contents: - -``` c -void* buffer = NULL; -MojoResult result = MojoGetMessageBuffer(message, &buffer); -printf("Pipe says: %s", (const char*)buffer); -``` - -`result` should be `MOJO_RESULT_OK` and this snippet should write `"hello"` to -`stdout`. - -If we try were to try reading again now that there are no messages on `b`: - -``` c -MojoMessageHandle message; -MojoResult result = MojoReadMessageNew(b, &message, NULL, NULL, NULL, - MOJO_READ_MESSAGE_FLAG_NONE); -``` - -We'll get a `result` of `MOJO_RESULT_SHOULD_WAIT`, indicating that the pipe is -not yet readable. - -### Messages With Handles - -Probably the most useful feature of Mojo IPC is that message pipes can carry -arbitrary Mojo handles, including other message pipes. This is also -straightforward. - -Here's an example which creates two pipes, using the first pipe to transfer -one end of the second pipe. If you have a good imagination you can pretend the -first pipe spans a process boundary, which makes the example more practically -interesting: - -``` c -MojoHandle a, b; -MojoHandle c, d; -MojoMessage message; - -// Allocate a message with an empty payload and handle |c| attached. Note that -// this takes ownership of |c|, effectively invalidating its handle value. -MojoResult result = MojoAllocMessage(0, &c, 1, MOJO_ALLOC_MESSAGE_FLAG_NONE, - message); - -result = MojoWriteMessageNew(a, message, MOJO_WRITE_MESSAGE_FLAG_NONE); - -// Some time later... -uint32_t num_bytes; -MojoHandle e; -uint32_t num_handles = 1; -MojoResult result = MojoReadMessageNew(b, &message, &num_bytes, &e, - &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE); -``` - -At this point the handle in `e` is now referencing the same message pipe -endpoint which was originally referenced by `c`. - -Note that `num_handles` above is initialized to 1 before we pass its address to -`MojoReadMessageNew`. This is to indicate how much `MojoHandle` storage is -available at the output buffer we gave it (`&e` above). - -If we didn't know how many handles to expect in an incoming message -- which is -often the case -- we can use `MojoReadMessageNew` to query for this information -first: - -``` c -MojoMessageHandle message; -uint32_t num_bytes = 0; -uint32_t num_handles = 0; -MojoResult result = MojoReadMessageNew(b, &message, &num_bytes, NULL, - &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE); -``` - -If in this case there were a received message on `b` with some nonzero number -of handles, `result` would be `MOJO_RESULT_RESOURCE_EXHAUSTED`, and both -`num_bytes` and `num_handles` would be updated to reflect the payload size and -number of attached handles on the next available message. - -It's also worth noting that if there did happen to be a message available with -no payload and no handles (*i.e.* an empty message), this would actually return -`MOJO_RESULT_OK`. - -## Data Pipes - -Data pipes provide an efficient unidirectional channel for moving large amounts -of unframed data between two endpoints. Every data pipe has a fixed -**element size** and **capacity**. Reads and writes must be done in sizes that -are a multiple of the element size, and writes to the pipe can only be queued -up to the pipe's capacity before reads must be done to make more space -available. - -Every data pipe has a single **producer** handle used to write data into the -pipe and a single **consumer** handle used to read data out of the pipe. - -Finally, data pipes support both immediate I/O -- reading into and writing out -from user-supplied buffers -- as well as two-phase I/O, allowing callers to -temporarily lock some portion of the data pipe in order to read or write its -contents directly. - -See [//mojo/public/c/system/data_pipe.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/data_pipe.h) -for detailed data pipe API documentation. - -### Creating Data Pipes - -Use `MojoCreateDataPipe` to create a new data pipe. The -`MojoCreateDataPipeOptions` structure is used to configure the new pipe, but -this can be omitted to assume the default options of a single-byte element size -and an implementation-defined default capacity (64 kB at the time of this -writing.) - -``` c -MojoHandle producer, consumer; -MojoResult result = MojoCreateDataPipe(NULL, &producer, &consumer); -``` - -### Immediate I/O - -Data can be written into or read out of a data pipe using buffers provided by -the caller. This is generally more convenient than two-phase I/O but is -also less efficient due to extra copying. - -``` c -uint32_t num_bytes = 12; -MojoResult result = MojoWriteData(producer, "datadatadata", &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE); -``` - -The above snippet will attempt to write 12 bytes into the data pipe, which -should succeed and return `MOJO_RESULT_OK`. If the available capacity on the -pipe was less than the amount requested (the input value of `*num_bytes`) this -will copy what it can into the pipe and return the number of bytes written in -`*num_bytes`. If no data could be copied this will instead return -`MOJO_RESULT_SHOULD_WAIT`. - -Reading from the consumer is a similar operation. - -``` c -char buffer[64]; -uint32_t num_bytes = 64; -MojoResult result = MojoReadData(consumer, buffer, &num_bytes, - MOJO_READ_DATA_FLAG_NONE); -``` - -This will attempt to read up to 64 bytes, returning the actual number of bytes -read in `*num_bytes`. - -`MojoReadData` supports a number of interesting flags to change the behavior: -you can peek at the data (copy bytes out without removing them from the pipe), -query the number of bytes available without doing any actual reading of the -contents, or discard data from the pipe without bothering to copy it anywhere. - -This also supports a `MOJO_READ_DATA_FLAG_ALL_OR_NONE` which ensures that the -call succeeds **only** if the exact number of bytes requested could be read. -Otherwise such a request will fail with `MOJO_READ_DATA_OUT_OF_RANGE`. - -### Two-Phase I/O - -Data pipes also support two-phase I/O operations, allowing a caller to -temporarily lock a portion of the data pipe's storage for direct memory access. - -``` c -void* buffer; -uint32_t num_bytes = 1024; -MojoResult result = MojoBeginWriteData(producer, &buffer, &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE); -``` - -This requests write access to a region of up to 1024 bytes of the data pipe's -next available capacity. Upon success, `buffer` will point to the writable -storage and `num_bytes` will indicate the size of the buffer there. - -The caller should then write some data into the memory region and release it -ASAP, indicating the number of bytes actually written: - -``` c -memcpy(buffer, "hello", 6); -MojoResult result = MojoEndWriteData(producer, 6); -``` - -Two-phase reads look similar: - -``` c -void* buffer; -uint32_t num_bytes = 1024; -MojoResult result = MojoBeginReadData(consumer, &buffer, &num_bytes, - MOJO_READ_DATA_FLAG_NONE); -// result should be MOJO_RESULT_OK, since there is some data available. - -printf("Pipe says: %s", (const char*)buffer); // Should say "hello". - -result = MojoEndReadData(consumer, 1); // Say we only consumed one byte. - -num_bytes = 1024; -result = MojoBeginReadData(consumer, &buffer, &num_bytes, - MOJO_READ_DATA_FLAG_NONE); -printf("Pipe says: %s", (const char*)buffer); // Should say "ello". -result = MojoEndReadData(consumer, 5); -``` - -## Shared Buffers - -Shared buffers are chunks of memory which can be mapped simultaneously by -multiple processes. Mojo provides a simple API to make these available to -applications. - -See [//mojo/public/c/system/buffer.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/buffer.h) -for detailed shared buffer API documentation. - -### Creating Buffer Handles - -Usage is straightforward. You can create a new buffer: - -``` c -// Allocate a shared buffer of 4 kB. -MojoHandle buffer; -MojoResult result = MojoCreateSharedBuffer(NULL, 4096, &buffer); -``` - -You can also duplicate an existing shared buffer handle: - -``` c -MojoHandle another_name_for_buffer; -MojoResult result = MojoDuplicateBufferHandle(buffer, NULL, - &another_name_for_buffer); -``` - -This is useful if you want to retain a handle to the buffer while also sharing -handles with one or more other clients. The allocated buffer remains valid as -long as at least one shared buffer handle exists to reference it. - -### Mapping Buffers - -You can map (and later unmap) a specified range of the buffer to get direct -memory access to its contents: - -``` c -void* data; -MojoResult result = MojoMapBuffer(buffer, 0, 64, &data, - MOJO_MAP_BUFFER_FLAG_NONE); - -*(int*)data = 42; -result = MojoUnmapBuffer(data); -``` - -A buffer may have any number of active mappings at a time, in any number of -processes. - -### Read-Only Handles - -An option can also be specified on `MojoDuplicateBufferHandle` to ensure -that the newly duplicated handle can only be mapped to read-only memory: - -``` c -MojoHandle read_only_buffer; -MojoDuplicateBufferHandleOptions options; -options.struct_size = sizeof(options); -options.flags = MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY; -MojoResult result = MojoDuplicateBufferHandle(buffer, &options, - &read_only_buffer); - -// Attempt to map and write to the buffer using the read-only handle: -void* data; -result = MojoMapBuffer(read_only_buffer, 0, 64, &data, - MOJO_MAP_BUFFER_FLAG_NONE); -*(int*)data = 42; // CRASH -``` - -*** note -**NOTE:** One important limitation of the current implementation is that -read-only handles can only be produced from a handle that was originally created -by `MojoCreateSharedBuffer` (*i.e.*, you cannot create a read-only duplicate -from a non-read-only duplicate), and the handle cannot have been transferred -over a message pipe first. -*** - -## Native Platform Handles (File Descriptors, Windows Handles, *etc.*) - -Native platform handles to system objects can be wrapped as Mojo handles for -seamless transit over message pipes. Mojo currently supports wrapping POSIX -file descriptors, Windows handles, and Mach ports. - -See [//mojo/public/c/system/platform_handle.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/platform_handle.h) -for detailed platform handle API documentation. - -### Wrapping Basic Handle Types - -Wrapping a POSIX file descriptor is simple: - -``` c -MojoPlatformHandle platform_handle; -platform_handle.struct_size = sizeof(platform_handle); -platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; -platform_handle.value = (uint64_t)fd; -MojoHandle handle; -MojoResult result = MojoWrapPlatformHandle(&platform_handle, &handle); -``` - -Note that at this point `handle` effectively owns the file descriptor -and if you were to call `MojoClose(handle)`, the file descriptor would be closed -too; but we're not going to close it here! We're going to pretend we've sent it -over a message pipe, and now we want to unwrap it on the other side: - -``` c -MojoPlatformHandle platform_handle; -platform_handle.struct_size = sizeof(platform_handle); -MojoResult result = MojoUnwrapPlatformHandle(handle, &platform_handle); -int fd = (int)platform_handle.value; -``` - -The situation looks nearly identical for wrapping and unwrapping Windows handles -and Mach ports. - -### Wrapping Shared Buffer Handles - -Unlike other handle types, shared buffers have special meaning in Mojo, and it -may be desirable to wrap a native platform handle -- along with some extra -metadata -- such that be treated like a real Mojo shared buffer handle. -Conversely it can also be useful to unpack a Mojo shared buffer handle into -a native platform handle which references the buffer object. Both of these -things can be done using the `MojoWrapPlatformSharedBuffer` and -`MojoUnwrapPlatformSharedBuffer` APIs. - -On Windows, the wrapped platform handle must always be a Windows handle to -a file mapping object. - -On OS X, the wrapped platform handle must be a memory-object send right. - -On all other POSIX systems, the wrapped platform handle must be a file -descriptor for a shared memory object. - -## Signals & Watchers - -Message pipe and data pipe (producer and consumer) handles can change state in -ways that may be interesting to a Mojo API user. For example, you may wish to -know when a message pipe handle has messages available to be read or when its -peer has been closed. Such states are reflected by a fixed set of boolean -signals on each pipe handle. - -### Signals - -Every message pipe and data pipe handle maintains a notion of -**signaling state** which may be queried at any time. For example: - -``` c -MojoHandle a, b; -MojoCreateMessagePipe(NULL, &a, &b); - -MojoHandleSignalsState state; -MojoResult result = MojoQueryHandleSignalsState(a, &state); -``` - -The `MojoHandleSignalsState` structure exposes two fields: `satisfied_signals` -and `satisfiable_signals`. Both of these are bitmasks of the type -`MojoHandleSignals` (see [//mojo/public/c/system/types.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/types.h) -for more details.) - -The `satisfied_signals` bitmask indicates signals which were satisfied on the -handle at the time of the call, while the `satisfiable_signals` bitmask -indicates signals which were still possible to satisfy at the time of the call. -It is thus by definition always true that: - -``` c -(satisfied_signals | satisfiable_signals) == satisfiable_signals -``` - -In other words a signal obviously cannot be satisfied if it is no longer -satisfiable. Furthermore once a signal is unsatisfiable, *i.e.* is no longer -set in `sastisfiable_signals`, it can **never** become satisfiable again. - -To illustrate this more clearly, consider the message pipe created above. Both -ends of the pipe are still open and neither has been written to yet. Thus both -handles start out with the same signaling state: - -| Field | State | -|-----------------------|-------| -| `satisfied_signals` | `MOJO_HANDLE_SIGNAL_WRITABLE` -| `satisfiable_signals` | `MOJO_HANDLE_SIGNAL_READABLE + MOJO_HANDLE_SIGNAL_WRITABLE + MOJO_HANDLE_SIGNAL_PEER_CLOSED` - -Writing a message to handle `b` will eventually alter the signaling state of `a` -such that `MOJO_HANDLE_SIGNAL_READABLE` also becomes satisfied. If we were to -then close `b`, the signaling state of `a` would look like: - -| Field | State | -|-----------------------|-------| -| `satisfied_signals` | `MOJO_HANDLE_SIGNAL_READABLE + MOJO_HANDLE_SIGNAL_PEER_CLOSED` -| `satisfiable_signals` | `MOJO_HANDLE_SIGNAL_READABLE + MOJO_HANDLE_SIGNAL_PEER_CLOSED` - -Note that even though `a`'s peer is known to be closed (hence making `a` -permanently unwritable) it remains readable because there's still an unread -received message waiting to be read from `a`. - -Finally if we read the last message from `a` its signaling state becomes: - -| Field | State | -|-----------------------|-------| -| `satisfied_signals` | `MOJO_HANDLE_SIGNAL_PEER_CLOSED` -| `satisfiable_signals` | `MOJO_HANDLE_SIGNAL_PEER_CLOSED` - -and we know definitively that `a` can never be read from again. - -### Watching Signals - -The ability to query a handle's signaling state can be useful, but it's not -sufficient to support robust and efficient pipe usage. Mojo watchers empower -users with the ability to **watch** a handle's signaling state for interesting -changes and automatically invoke a notification handler in response. - -When a watcher is created it must be bound to a function pointer matching -the following signature, defined in -[//mojo/public/c/system/watcher.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/watcher.h): - -``` c -typedef void (*MojoWatcherNotificationCallback)( - uintptr_t context, - MojoResult result, - MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags); -``` - -The `context` argument corresponds to a specific handle being watched by the -watcher (read more below), and the remaining arguments provide details regarding -the specific reason for the notification. It's important to be aware that a -watcher's registered handler may be called **at any time** and -**on any thread**. - -It's also helpful to understand a bit about the mechanism by which the handler -can be invoked. Essentially, any Mojo C System API call may elicit a handle -state change of some kind. If such a change is relevant to conditions watched by -a watcher, and that watcher is in a state which allows it raise a corresponding -notification, its notification handler will be invoked synchronously some time -before the outermost System API call on the current thread's stack returns. - -Handle state changes can also occur as a result of incoming IPC from an external -process. If a pipe in the current process is connected to an endpoint in another -process and the internal Mojo system receives an incoming message bound for the -local endpoint, the arrival of that message will trigger a state change on the -receiving handle and may thus invoke one or more watchers' notification handlers -as a result. - -The `MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM` flag on the notification -handler's `flags` argument is used to indicate whether the handler was invoked -due to such an internal system IPC event (if the flag is set), or if it was -invoked synchronously due to some local API call (if the flag is unset.) -This distinction can be useful to make in certain cases to *e.g.* avoid -accidental reentrancy in user code. - -### Creating a Watcher - -Creating a watcher is simple: - -``` c - -void OnNotification(uintptr_t context, - MojoResult result, - MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags) { - // ... -} - -MojoHandle w; -MojoResult result = MojoCreateWatcher(&OnNotification, &w); -``` - -Like all other `MojoHandle` types, watchers may be destroyed by closing them -with `MojoClose`. Unlike other `MojoHandle` types, watcher handles are **not** -transferrable across message pipes. - -In order for a watcher to be useful, it has to watch at least one handle. - -### Adding a Handle to a Watcher - -Any given watcher can watch any given (message or data pipe) handle for some set -of signaling conditions. A handle may be watched simultaneously by multiple -watchers, and a single watcher can watch multiple different handles -simultaneously. - -``` c -MojoHandle a, b; -MojoCreateMessagePipe(NULL, &a, &b); - -// Watch handle |a| for readability. -const uintptr_t context = 1234; -MojoResult result = MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, context); -``` - -We've successfully instructed watcher `w` to begin watching pipe handle `a` for -readability. However, our recently created watcher is still in a **disarmed** -state, meaning that it will never fire a notification pertaining to this watched -signaling condition. It must be **armed** before that can happen. - -### Arming a Watcher - -In order for a watcher to invoke its notification handler in response to a -relevant signaling state change on a watched handle, it must first be armed. A -watcher may only be armed if none of its watched handles would elicit a -notification immediately once armed. - -In this case `a` is clearly not yet readable, so arming should succeed: - -``` c -MojoResult result = MojoArmWatcher(w, NULL, NULL, NULL, NULL); -``` - -Now we can write to `b` to make `a` readable: - -``` c -MojoWriteMessage(b, NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_NONE); -``` - -Eventually -- and in practice possibly before `MojoWriteMessage` even -returns -- this will cause `OnNotification` to be invoked on the calling thread -with the `context` value (*i.e.* 1234) that was given when the handle was added -to the watcher. - -The `result` parameter will be `MOJO_RESULT_OK` to indicate that the watched -signaling condition has been *satisfied*. If the watched condition had instead -become permanently *unsatisfiable* (*e.g.*, if `b` were instead closed), `result` -would instead indicate `MOJO_RESULT_FAILED_PRECONDITION`. - -**NOTE:** Immediately before a watcher decides to invoke its notification -handler, it automatically disarms itself to prevent another state change from -eliciting another notification. Therefore a watcher must be repeatedly rearmed -in order to continue dispatching signaling notifications. - -As noted above, arming a watcher may fail if any of the watched conditions for -a handle are already partially satisfied or fully unsatisfiable. In that case -the caller may provide buffers for `MojoArmWatcher` to store information about -a subset of the relevant watches which caused it to fail: - -``` c -// Provide some storage for information about watches that are already ready. -uint32_t num_ready_contexts = 4; -uintptr_t ready_contexts[4]; -MojoResult ready_results[4]; -struct MojoHandleSignalsStates ready_states[4]; -MojoResult result = MojoArmWatcher(w, &num_ready_contexts, ready_contexts, - ready_results, ready_states); -``` - -Because `a` is still readable this operation will fail with -`MOJO_RESULT_FAILED_PRECONDITION`. The input value of `num_ready_contexts` -informs `MojoArmWatcher` that it may store information regarding up to 4 watches -which currently prevent arming. In this case of course there is only one active -watch, so upon return we will see: - -* `num_ready_contexts` is `1`. -* `ready_contexts[0]` is `1234`. -* `ready_results[0]` is `MOJO_RESULT_OK` -* `ready_states[0]` is the last known signaling state of handle `a`. - -In other words the stored information mirrors what would have been the -notification handler's arguments if the watcher were allowed to arm and thus -notify immediately. - -### Cancelling a Watch - -There are three ways a watch can be cancelled: - -* The watched handle is closed -* The watcher handle is closed (in which case all of its watches are cancelled.) -* `MojoCancelWatch` is explicitly called for a given `context`. - -In the above example this means any of the following operations will cancel the -watch on `a`: - -``` c -// Close the watched handle... -MojoClose(a); - -// OR close the watcher handle... -MojoClose(w); - -// OR explicitly cancel. -MojoResult result = MojoCancelWatch(w, 1234); -``` - -In every case the watcher's notification handler is invoked for the cancelled -watch(es) regardless of whether or not the watcher is or was armed at the time. -The notification handler receives a `result` of `MOJO_RESULT_CANCELLED` for -these notifications, and this is guaranteed to be the final notification for any -given watch context. - -### Practical Watch Context Usage - -It is common and probably wise to treat a watch's `context` value as an opaque -pointer to some thread-safe state associated in some way with the handle being -watched. Here's a small example which uses a single watcher to watch both ends -of a message pipe and accumulate a count of messages received at each end. - -``` c -// NOTE: For the sake of simplicity this example code is not in fact -// thread-safe. As long as there's only one thread running in the process and -// no external process connections, this is fine. - -struct WatchedHandleState { - MojoHandle watcher; - MojoHandle handle; - int message_count; -}; - -void OnNotification(uintptr_t context, - MojoResult result, - MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags) { - struct WatchedHandleState* state = (struct WatchedHandleState*)(context); - MojoResult rv; - - if (result == MOJO_RESULT_CANCELLED) { - // Cancellation is always the last notification and is guaranteed to - // eventually happen for every context, assuming no handles are leaked. We - // treat this as an opportunity to free the WatchedHandleState. - free(state); - return; - } - - if (result == MOJO_RESULT_FAILED_PRECONDITION) { - // No longer readable, i.e. the other handle must have been closed. Better - // cancel. Note that we could also just call MojoClose(state->watcher) here - // since we know |context| is its only registered watch. - MojoCancelWatch(state->watcher, context); - return; - } - - // This is the only handle watched by the watcher, so as long as we can't arm - // the watcher we know something's up with this handle. Try to read messages - // until we can successfully arm again or something goes terribly wrong. - while (MojoArmWatcher(state->watcher, NULL, NULL, NULL, NULL) == - MOJO_RESULT_FAILED_PRECONDITION) { - rv = MojoReadMessageNew(state->handle, NULL, NULL, NULL, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); - if (rv == MOJO_RESULT_OK) { - state->message_count++; - } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) { - MojoCancelWatch(state->watcher, context); - return; - } - } -} - -MojoHandle a, b; -MojoCreateMessagePipe(NULL, &a, &b); - -MojoHandle a_watcher, b_watcher; -MojoCreateWatcher(&OnNotification, &a_watcher); -MojoCreateWatcher(&OnNotification, &b_watcher) - -struct WatchedHandleState* a_state = malloc(sizeof(struct WatchedHandleState)); -a_state->watcher = a_watcher; -a_state->handle = a; -a_state->message_count = 0; - -struct WatchedHandleState* b_state = malloc(sizeof(struct WatchedHandleState)); -b_state->watcher = b_watcher; -b_state->handle = b; -b_state->message_count = 0; - -MojoWatch(a_watcher, a, MOJO_HANDLE_SIGNAL_READABLE, (uintptr_t)a_state); -MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, (uintptr_t)b_state); - -MojoArmWatcher(a_watcher, NULL, NULL, NULL, NULL); -MojoArmWatcher(b_watcher, NULL, NULL, NULL, NULL); -``` - -Now any writes to `a` will increment `message_count` in `b_state`, and any -writes to `b` will increment `message_count` in `a_state`. - -If either `a` or `b` is closed, both watches will be cancelled - one because -watch cancellation is implicit in handle closure, and the other because its -watcher will eventually detect that the handle is no longer readable. diff --git a/mojo/public/c/system/buffer.h b/mojo/public/c/system/buffer.h deleted file mode 100644 index 285e0d7..0000000 --- a/mojo/public/c/system/buffer.h +++ /dev/null @@ -1,188 +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. - -// This file contains types/constants and functions specific to shared buffers. -// -// Note: This header should be compilable as C. - -#ifndef MOJO_PUBLIC_C_SYSTEM_BUFFER_H_ -#define MOJO_PUBLIC_C_SYSTEM_BUFFER_H_ - -#include - -#include "mojo/public/c/system/macros.h" -#include "mojo/public/c/system/system_export.h" -#include "mojo/public/c/system/types.h" - -// |MojoCreateSharedBufferOptions|: Used to specify creation parameters for a -// shared buffer to |MojoCreateSharedBuffer()|. -// -// |uint32_t struct_size|: Set to the size of the -// |MojoCreateSharedBufferOptions| struct. (Used to allow for future -// extensions.) -// -// |MojoCreateSharedBufferOptionsFlags flags|: Reserved for future use. -// |MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE|: No flags; default mode. - -typedef uint32_t MojoCreateSharedBufferOptionsFlags; - -#ifdef __cplusplus -const MojoCreateSharedBufferOptionsFlags - MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE = 0; -#else -#define MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE \ - ((MojoCreateSharedBufferOptionsFlags)0) -#endif - -MOJO_STATIC_ASSERT(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment"); -struct MOJO_ALIGNAS(8) MojoCreateSharedBufferOptions { - uint32_t struct_size; - MojoCreateSharedBufferOptionsFlags flags; -}; -MOJO_STATIC_ASSERT(sizeof(MojoCreateSharedBufferOptions) == 8, - "MojoCreateSharedBufferOptions has wrong size"); - -// |MojoDuplicateBufferHandleOptions|: Used to specify parameters in duplicating -// access to a shared buffer to |MojoDuplicateBufferHandle()|. -// -// |uint32_t struct_size|: Set to the size of the -// |MojoDuplicateBufferHandleOptions| struct. (Used to allow for future -// extensions.) -// -// |MojoDuplicateBufferHandleOptionsFlags flags|: Flags to control the -// behavior of |MojoDuplicateBufferHandle()|. May be some combination of -// the following: -// -// |MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE|: No flags; default -// mode. -// |MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY|: The duplicate -// shared buffer can only be mapped read-only. A read-only duplicate -// may only be created before any handles to the buffer are passed -// over a message pipe. - -typedef uint32_t MojoDuplicateBufferHandleOptionsFlags; - -#ifdef __cplusplus -const MojoDuplicateBufferHandleOptionsFlags - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE = 0; -const MojoDuplicateBufferHandleOptionsFlags - MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY = 1 << 0; -#else -#define MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE \ - ((MojoDuplicateBufferHandleOptionsFlags)0) -#define MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY \ - ((MojoDuplicateBufferHandleOptionsFlags)1 << 0) -#endif - -struct MojoDuplicateBufferHandleOptions { - uint32_t struct_size; - MojoDuplicateBufferHandleOptionsFlags flags; -}; -MOJO_STATIC_ASSERT(sizeof(MojoDuplicateBufferHandleOptions) == 8, - "MojoDuplicateBufferHandleOptions has wrong size"); - -// |MojoMapBufferFlags|: Used to specify different modes to |MojoMapBuffer()|. -// |MOJO_MAP_BUFFER_FLAG_NONE| - No flags; default mode. - -typedef uint32_t MojoMapBufferFlags; - -#ifdef __cplusplus -const MojoMapBufferFlags MOJO_MAP_BUFFER_FLAG_NONE = 0; -#else -#define MOJO_MAP_BUFFER_FLAG_NONE ((MojoMapBufferFlags)0) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// Note: See the comment in functions.h about the meaning of the "optional" -// label for pointer parameters. - -// Creates a buffer of size |num_bytes| bytes that can be shared between -// processes. The returned handle may be duplicated any number of times by -// |MojoDuplicateBufferHandle()|. -// -// To access the buffer's storage, one must call |MojoMapBuffer()|. -// -// |options| may be set to null for a shared buffer with the default options. -// -// On success, |*shared_buffer_handle| will be set to the handle for the shared -// buffer. On failure it is not modified. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |*options| is invalid). -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has -// been reached (e.g., if the requested size was too large, or if the -// maximum number of handles was exceeded). -// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|. -MOJO_SYSTEM_EXPORT MojoResult MojoCreateSharedBuffer( - const struct MojoCreateSharedBufferOptions* options, // Optional. - uint64_t num_bytes, // In. - MojoHandle* shared_buffer_handle); // Out. - -// Duplicates the handle |buffer_handle| as a new shared buffer handle. On -// success this returns the new handle in |*new_buffer_handle|. A shared buffer -// remains allocated as long as there is at least one shared buffer handle -// referencing it in at least one process in the system. -// -// |options| may be set to null to duplicate the buffer handle with the default -// options. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |buffer_handle| is not a valid buffer handle or |*options| is invalid). -// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|. -MOJO_SYSTEM_EXPORT MojoResult MojoDuplicateBufferHandle( - MojoHandle buffer_handle, - const struct MojoDuplicateBufferHandleOptions* options, // Optional. - MojoHandle* new_buffer_handle); // Out. - -// Maps the part (at offset |offset| of length |num_bytes|) of the buffer given -// by |buffer_handle| into memory, with options specified by |flags|. |offset + -// num_bytes| must be less than or equal to the size of the buffer. On success, -// |*buffer| points to memory with the requested part of the buffer. On -// failure |*buffer| it is not modified. -// -// A single buffer handle may have multiple active mappings The permissions -// (e.g., writable or executable) of the returned memory depend on th -// properties of the buffer and properties attached to the buffer handle, as -// well as |flags|. -// -// A mapped buffer must eventually be unmapped by calling |MojoUnmapBuffer()| -// with the value of |*buffer| returned by this function. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |buffer_handle| is not a valid buffer handle or the range specified by -// |offset| and |num_bytes| is not valid). -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if the mapping operation itself failed -// (e.g., due to not having appropriate address space available). -MOJO_SYSTEM_EXPORT MojoResult MojoMapBuffer(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - void** buffer, // Out. - MojoMapBufferFlags flags); - -// Unmaps a buffer pointer that was mapped by |MojoMapBuffer()|. |buffer| must -// have been the result of |MojoMapBuffer()| (not some other pointer inside -// the mapped memory), and the entire mapping will be removed. -// -// A mapping may only be unmapped once. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if |buffer| is invalid (e.g., is not the -// result of |MojoMapBuffer()| or has already been unmapped). -MOJO_SYSTEM_EXPORT MojoResult MojoUnmapBuffer(void* buffer); // In. - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_BUFFER_H_ diff --git a/mojo/public/c/system/core.h b/mojo/public/c/system/core.h deleted file mode 100644 index 03c0652..0000000 --- a/mojo/public/c/system/core.h +++ /dev/null @@ -1,22 +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. - -// This is a catch-all header that includes everything. -// -// Note: This header should be compilable as C. - -#ifndef MOJO_PUBLIC_C_SYSTEM_CORE_H_ -#define MOJO_PUBLIC_C_SYSTEM_CORE_H_ - -#include "mojo/public/c/system/buffer.h" -#include "mojo/public/c/system/data_pipe.h" -#include "mojo/public/c/system/functions.h" -#include "mojo/public/c/system/macros.h" -#include "mojo/public/c/system/message_pipe.h" -#include "mojo/public/c/system/platform_handle.h" -#include "mojo/public/c/system/system_export.h" -#include "mojo/public/c/system/types.h" -#include "mojo/public/c/system/watcher.h" - -#endif // MOJO_PUBLIC_C_SYSTEM_CORE_H_ diff --git a/mojo/public/c/system/data_pipe.h b/mojo/public/c/system/data_pipe.h deleted file mode 100644 index f51e36c..0000000 --- a/mojo/public/c/system/data_pipe.h +++ /dev/null @@ -1,344 +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. - -// This file contains types/constants and functions specific to data pipes. -// -// Note: This header should be compilable as C. - -#ifndef MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_ -#define MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_ - -#include - -#include "mojo/public/c/system/macros.h" -#include "mojo/public/c/system/system_export.h" -#include "mojo/public/c/system/types.h" - -// |MojoCreateDataPipeOptions|: Used to specify creation parameters for a data -// pipe to |MojoCreateDataPipe()|. -// -// |uint32_t struct_size|: Set to the size of the |MojoCreateDataPipeOptions| -// struct. (Used to allow for future extensions.) -// -// |MojoCreateDataPipeOptionsFlags flags|: Used to specify different modes of -// operation. May be some combination of the following values: -// -// |MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE|: No flags; default mode. -// -// |uint32_t element_num_bytes|: The size of an element, in bytes. All -// transactions and buffers will consist of an integral number of -// elements. Must be nonzero. -// -// |uint32_t capacity_num_bytes|: The capacity of the data pipe, in number of -// bytes; must be a multiple of |element_num_bytes|. The data pipe will -// always be able to queue AT LEAST this much data. Set to zero to opt for -// a system-dependent automatically-calculated capacity (which will always -// be at least one element). - -typedef uint32_t MojoCreateDataPipeOptionsFlags; - -#ifdef __cplusplus -const MojoCreateDataPipeOptionsFlags MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE = - 0; -#else -#define MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE \ - ((MojoCreateDataPipeOptionsFlags)0) -#endif - -MOJO_STATIC_ASSERT(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment"); -struct MOJO_ALIGNAS(8) MojoCreateDataPipeOptions { - MOJO_ALIGNAS(4) uint32_t struct_size; - MOJO_ALIGNAS(4) MojoCreateDataPipeOptionsFlags flags; - MOJO_ALIGNAS(4) uint32_t element_num_bytes; - MOJO_ALIGNAS(4) uint32_t capacity_num_bytes; -}; -MOJO_STATIC_ASSERT(sizeof(MojoCreateDataPipeOptions) == 16, - "MojoCreateDataPipeOptions has wrong size"); - -// |MojoWriteDataFlags|: Used to specify different modes to |MojoWriteData()| -// and |MojoBeginWriteData()|. May be some combination of the following values: -// -// |MOJO_WRITE_DATA_FLAG_NONE| - No flags; default mode. -// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| - Write either all the elements -// requested or none of them. - -typedef uint32_t MojoWriteDataFlags; - -#ifdef __cplusplus -const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_NONE = 0; -const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_ALL_OR_NONE = 1 << 0; -#else -#define MOJO_WRITE_DATA_FLAG_NONE ((MojoWriteDataFlags)0) -#define MOJO_WRITE_DATA_FLAG_ALL_OR_NONE ((MojoWriteDataFlags)1 << 0) -#endif - -// |MojoReadDataFlags|: Used to specify different modes to |MojoReadData()| and -// |MojoBeginReadData()|. May be some combination of the following values: -// -// |MOJO_READ_DATA_FLAG_NONE| - No flags; default mode. -// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| - Read (or discard) either the requested -// number of elements or none. NOTE: This flag is not currently supported -// by |MojoBeginReadData()|. -// |MOJO_READ_DATA_FLAG_DISCARD| - Discard (up to) the requested number of -// elements. -// |MOJO_READ_DATA_FLAG_QUERY| - Query the number of elements available to -// read. For use with |MojoReadData()| only. Mutually exclusive with -// |MOJO_READ_DATA_FLAG_DISCARD|, and |MOJO_READ_DATA_FLAG_ALL_OR_NONE| -// is ignored if this flag is set. -// |MOJO_READ_DATA_FLAG_PEEK| - Read elements without removing them. For use -// with |MojoReadData()| only. Mutually exclusive with -// |MOJO_READ_DATA_FLAG_DISCARD| and |MOJO_READ_DATA_FLAG_QUERY|. - -typedef uint32_t MojoReadDataFlags; - -#ifdef __cplusplus -const MojoReadDataFlags MOJO_READ_DATA_FLAG_NONE = 0; -const MojoReadDataFlags MOJO_READ_DATA_FLAG_ALL_OR_NONE = 1 << 0; -const MojoReadDataFlags MOJO_READ_DATA_FLAG_DISCARD = 1 << 1; -const MojoReadDataFlags MOJO_READ_DATA_FLAG_QUERY = 1 << 2; -const MojoReadDataFlags MOJO_READ_DATA_FLAG_PEEK = 1 << 3; -#else -#define MOJO_READ_DATA_FLAG_NONE ((MojoReadDataFlags)0) -#define MOJO_READ_DATA_FLAG_ALL_OR_NONE ((MojoReadDataFlags)1 << 0) -#define MOJO_READ_DATA_FLAG_DISCARD ((MojoReadDataFlags)1 << 1) -#define MOJO_READ_DATA_FLAG_QUERY ((MojoReadDataFlags)1 << 2) -#define MOJO_READ_DATA_FLAG_PEEK ((MojoReadDataFlags)1 << 3) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// Note: See the comment in functions.h about the meaning of the "optional" -// label for pointer parameters. - -// Creates a data pipe, which is a unidirectional communication channel for -// unframed data. Data must be read and written in multiples of discrete -// discrete elements of size given in |options|. -// -// See |MojoCreateDataPipeOptions| for a description of the different options -// available for data pipes. -// -// |options| may be set to null for a data pipe with the default options (which -// will have an element size of one byte and have some system-dependent -// capacity). -// -// On success, |*data_pipe_producer_handle| will be set to the handle for the -// producer and |*data_pipe_consumer_handle| will be set to the handle for the -// consumer. On failure they are not modified. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |*options| is invalid). -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has -// been reached (e.g., if the requested capacity was too large, or if the -// maximum number of handles was exceeded). -// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|. -MOJO_SYSTEM_EXPORT MojoResult MojoCreateDataPipe( - const struct MojoCreateDataPipeOptions* options, // Optional. - MojoHandle* data_pipe_producer_handle, // Out. - MojoHandle* data_pipe_consumer_handle); // Out. - -// Writes the data pipe producer given by |data_pipe_producer_handle|. -// -// |elements| points to data of size |*num_bytes|; |*num_bytes| must be a -// multiple of the data pipe's element size. If -// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| is set in |flags|, either all the data -// is written (if enough write capacity is available) or none is. -// -// On success |*num_bytes| is set to the amount of data that was actually -// written. On failure it is unmodified. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |data_pipe_producer_dispatcher| is not a handle to a data pipe -// producer or |*num_bytes| is not a multiple of the data pipe's element -// size.) -// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been -// closed. -// |MOJO_RESULT_OUT_OF_RANGE| if |flags| has -// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and the required amount of data -// (specified by |*num_bytes|) could not be written. -// |MOJO_RESULT_BUSY| if there is a two-phase write ongoing with -// |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been -// called, but not yet the matching |MojoEndWriteData()|). -// |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the -// consumer is still open) and |flags| does *not* have -// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set. -MOJO_SYSTEM_EXPORT MojoResult - MojoWriteData(MojoHandle data_pipe_producer_handle, - const void* elements, - uint32_t* num_bytes, // In/out. - MojoWriteDataFlags flags); - -// Begins a two-phase write to the data pipe producer given by -// |data_pipe_producer_handle|. On success |*buffer| will be a pointer to which -// the caller can write up to |*buffer_num_bytes| bytes of data. -// -// During a two-phase write, |data_pipe_producer_handle| is *not* writable. -// If another caller tries to write to it by calling |MojoWriteData()| or -// |MojoBeginWriteData()|, their request will fail with |MOJO_RESULT_BUSY|. -// -// If |MojoBeginWriteData()| returns MOJO_RESULT_OK and once the caller has -// finished writing data to |*buffer|, |MojoEndWriteData()| must be called to -// indicate the amount of data actually written and to complete the two-phase -// write operation. |MojoEndWriteData()| need not be called when -// |MojoBeginWriteData()| fails. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |data_pipe_producer_handle| is not a handle to a data pipe producer or -// flags has |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set. -// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been -// closed. -// |MOJO_RESULT_BUSY| if there is already a two-phase write ongoing with -// |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been -// called, but not yet the matching |MojoEndWriteData()|). -// |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the -// consumer is still open). -MOJO_SYSTEM_EXPORT MojoResult - MojoBeginWriteData(MojoHandle data_pipe_producer_handle, - void** buffer, // Out. - uint32_t* buffer_num_bytes, // In/out. - MojoWriteDataFlags flags); - -// Ends a two-phase write that was previously initiated by -// |MojoBeginWriteData()| for the same |data_pipe_producer_handle|. -// -// |num_bytes_written| must indicate the number of bytes actually written into -// the two-phase write buffer. It must be less than or equal to the value of -// |*buffer_num_bytes| output by |MojoBeginWriteData()|, and it must be a -// multiple of the data pipe's element size. -// -// On failure, the two-phase write (if any) is ended (so the handle may become -// writable again if there's space available) but no data written to |*buffer| -// is "put into" the data pipe. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |data_pipe_producer_handle| is not a handle to a data pipe producer or -// |num_bytes_written| is invalid (greater than the maximum value provided -// by |MojoBeginWriteData()| or not a multiple of the element size). -// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer is not in a -// two-phase write (e.g., |MojoBeginWriteData()| was not called or -// |MojoEndWriteData()| has already been called). -MOJO_SYSTEM_EXPORT MojoResult - MojoEndWriteData(MojoHandle data_pipe_producer_handle, - uint32_t num_bytes_written); - -// Reads data from the data pipe consumer given by |data_pipe_consumer_handle|. -// May also be used to discard data or query the amount of data available. -// -// If |flags| has neither |MOJO_READ_DATA_FLAG_DISCARD| nor -// |MOJO_READ_DATA_FLAG_QUERY| set, this tries to read up to |*num_bytes| (which -// must be a multiple of the data pipe's element size) bytes of data to -// |elements| and set |*num_bytes| to the amount actually read. If flags has -// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, it will either read exactly -// |*num_bytes| bytes of data or none. Additionally, if flags has -// |MOJO_READ_DATA_FLAG_PEEK| set, the data read will remain in the pipe and be -// available to future reads. -// -// If flags has |MOJO_READ_DATA_FLAG_DISCARD| set, it discards up to -// |*num_bytes| (which again must be a multiple of the element size) bytes of -// data, setting |*num_bytes| to the amount actually discarded. If flags has -// |MOJO_READ_DATA_FLAG_ALL_OR_NONE|, it will either discard exactly -// |*num_bytes| bytes of data or none. In this case, |MOJO_READ_DATA_FLAG_QUERY| -// must not be set, and |elements| is ignored (and should typically be set to -// null). -// -// If flags has |MOJO_READ_DATA_FLAG_QUERY| set, it queries the amount of data -// available, setting |*num_bytes| to the number of bytes available. In this -// case, |MOJO_READ_DATA_FLAG_DISCARD| must not be set, and -// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is ignored, as are |elements| and the input -// value of |*num_bytes|. -// -// Returns: -// |MOJO_RESULT_OK| on success (see above for a description of the different -// operations). -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |data_pipe_consumer_handle| is invalid, the combination of flags in -// |flags| is invalid, etc.). -// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been -// closed and data (or the required amount of data) was not available to -// be read or discarded. -// |MOJO_RESULT_OUT_OF_RANGE| if |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE| -// set and the required amount of data is not available to be read or -// discarded (and the producer is still open). -// |MOJO_RESULT_BUSY| if there is a two-phase read ongoing with -// |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been -// called, but not yet the matching |MojoEndReadData()|). -// |MOJO_RESULT_SHOULD_WAIT| if there is no data to be read or discarded (and -// the producer is still open) and |flags| does *not* have -// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set. -MOJO_SYSTEM_EXPORT MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle, - void* elements, // Out. - uint32_t* num_bytes, // In/out. - MojoReadDataFlags flags); - -// Begins a two-phase read from the data pipe consumer given by -// |data_pipe_consumer_handle|. On success, |*buffer| will be a pointer from -// which the caller can read up to |*buffer_num_bytes| bytes of data. -// -// During a two-phase read, |data_pipe_consumer_handle| is *not* readable. -// If another caller tries to read from it by calling |MojoReadData()| or -// |MojoBeginReadData()|, their request will fail with |MOJO_RESULT_BUSY|. -// -// Once the caller has finished reading data from |*buffer|, |MojoEndReadData()| -// must be called to indicate the number of bytes read and to complete the -// two-phase read operation. -// -// |flags| must not have |MOJO_READ_DATA_FLAG_DISCARD|, -// |MOJO_READ_DATA_FLAG_QUERY|, |MOJO_READ_DATA_FLAG_PEEK|, or -// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |data_pipe_consumer_handle| is not a handle to a data pipe consumer, -// or |flags| has invalid flags set.) -// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been -// closed. -// |MOJO_RESULT_BUSY| if there is already a two-phase read ongoing with -// |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been -// called, but not yet the matching |MojoEndReadData()|). -// |MOJO_RESULT_SHOULD_WAIT| if no data can currently be read (and the -// producer is still open). -MOJO_SYSTEM_EXPORT MojoResult - MojoBeginReadData(MojoHandle data_pipe_consumer_handle, - const void** buffer, // Out. - uint32_t* buffer_num_bytes, // In/out. - MojoReadDataFlags flags); - -// Ends a two-phase read from the data pipe consumer given by -// |data_pipe_consumer_handle| that was begun by a call to |MojoBeginReadData()| -// on the same handle. |num_bytes_read| should indicate the amount of data -// actually read; it must be less than or equal to the value of -// |*buffer_num_bytes| output by |MojoBeginReadData()| and must be a multiple of -// the element size. -// -// On failure, the two-phase read (if any) is ended (so the handle may become -// readable again) but no data is "removed" from the data pipe. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |data_pipe_consumer_handle| is not a handle to a data pipe consumer or -// |num_bytes_written| is greater than the maximum value provided by -// |MojoBeginReadData()| or not a multiple of the element size). -// |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer is not in a -// two-phase read (e.g., |MojoBeginReadData()| was not called or -// |MojoEndReadData()| has already been called). -MOJO_SYSTEM_EXPORT MojoResult - MojoEndReadData(MojoHandle data_pipe_consumer_handle, - uint32_t num_bytes_read); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_ diff --git a/mojo/public/c/system/functions.h b/mojo/public/c/system/functions.h deleted file mode 100644 index d0656c6..0000000 --- a/mojo/public/c/system/functions.h +++ /dev/null @@ -1,78 +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. - -// This file contains basic functions common to different Mojo system APIs. -// -// Note: This header should be compilable as C. - -#ifndef MOJO_PUBLIC_C_SYSTEM_FUNCTIONS_H_ -#define MOJO_PUBLIC_C_SYSTEM_FUNCTIONS_H_ - -#include -#include - -#include "mojo/public/c/system/system_export.h" -#include "mojo/public/c/system/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Note: Pointer parameters that are labelled "optional" may be null (at least -// under some circumstances). Non-const pointer parameters are also labeled -// "in", "out", or "in/out", to indicate how they are used. (Note that how/if -// such a parameter is used may depend on other parameters or the requested -// operation's success/failure. E.g., a separate |flags| parameter may control -// whether a given "in/out" parameter is used for input, output, or both.) - -// Returns the time, in microseconds, since some undefined point in the past. -// The values are only meaningful relative to other values that were obtained -// from the same device without an intervening system restart. Such values are -// guaranteed to be monotonically non-decreasing with the passage of real time. -// Although the units are microseconds, the resolution of the clock may vary and -// is typically in the range of ~1-15 ms. -MOJO_SYSTEM_EXPORT MojoTimeTicks MojoGetTimeTicksNow(void); - -// Closes the given |handle|. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle. -// -// Concurrent operations on |handle| may succeed (or fail as usual) if they -// happen before the close, be cancelled with result |MOJO_RESULT_CANCELLED| if -// they properly overlap (this is likely the case with watchers), or fail with -// |MOJO_RESULT_INVALID_ARGUMENT| if they happen after. -MOJO_SYSTEM_EXPORT MojoResult MojoClose(MojoHandle handle); - -// Queries the last known signals state of a handle. -// -// Note that no guarantees can be made about the accuracy of the returned -// signals state by the time this returns, as other threads in the system may -// change the handle's state at any time. Use with appropriate discretion. -// -// Returns: -// |MOJO_RESULT_OK| on success. |*signals_state| is populated with the -// last known signals state of |handle|. -// |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle or -// |signals_state| is null. -MOJO_SYSTEM_EXPORT MojoResult -MojoQueryHandleSignalsState(MojoHandle handle, - struct MojoHandleSignalsState* signals_state); - -// Retrieves system properties. See the documentation for |MojoPropertyType| for -// supported property types and their corresponding output value type. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if |type| is not recognized. In this case, -// |value| is untouched. -MOJO_SYSTEM_EXPORT MojoResult MojoGetProperty(MojoPropertyType type, - void* value); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_FUNCTIONS_H_ diff --git a/mojo/public/c/system/macros.h b/mojo/public/c/system/macros.h deleted file mode 100644 index 917c69c..0000000 --- a/mojo/public/c/system/macros.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_C_SYSTEM_MACROS_H_ -#define MOJO_PUBLIC_C_SYSTEM_MACROS_H_ - -#include - -// Assert things at compile time. (|msg| should be a valid identifier name.) -// This macro is currently C++-only, but we want to use it in the C core.h. -// Use like: -// MOJO_STATIC_ASSERT(sizeof(Foo) == 12, "Foo has invalid size"); -#if defined(__cplusplus) -#define MOJO_STATIC_ASSERT(expr, msg) static_assert(expr, msg) -#else -#define MOJO_STATIC_ASSERT(expr, msg) -#endif - -// Like the C++11 |alignof| operator. -#if __cplusplus >= 201103L -#define MOJO_ALIGNOF(type) alignof(type) -#elif defined(__GNUC__) -#define MOJO_ALIGNOF(type) __alignof__(type) -#elif defined(_MSC_VER) -// The use of |sizeof| is to work around a bug in MSVC 2010 (see -// http://goo.gl/isH0C; supposedly fixed since then). -#define MOJO_ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type)) -#else -#error "Please define MOJO_ALIGNOF() for your compiler." -#endif - -// Specify the alignment of a |struct|, etc. -// Use like: -// struct MOJO_ALIGNAS(8) Foo { ... }; -// Unlike the C++11 |alignas()|, |alignment| must be an integer. It may not be a -// type, nor can it be an expression like |MOJO_ALIGNOF(type)| (due to the -// non-C++11 MSVS version). -#if __cplusplus >= 201103L -#define MOJO_ALIGNAS(alignment) alignas(alignment) -#elif defined(__GNUC__) -#define MOJO_ALIGNAS(alignment) __attribute__((aligned(alignment))) -#elif defined(_MSC_VER) -#define MOJO_ALIGNAS(alignment) __declspec(align(alignment)) -#else -#error "Please define MOJO_ALIGNAS() for your compiler." -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_MACROS_H_ diff --git a/mojo/public/c/system/message_pipe.h b/mojo/public/c/system/message_pipe.h deleted file mode 100644 index b759bc7..0000000 --- a/mojo/public/c/system/message_pipe.h +++ /dev/null @@ -1,341 +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. - -// This file contains types/constants and functions specific to message pipes. -// -// Note: This header should be compilable as C. - -#ifndef MOJO_PUBLIC_C_SYSTEM_MESSAGE_PIPE_H_ -#define MOJO_PUBLIC_C_SYSTEM_MESSAGE_PIPE_H_ - -#include - -#include "mojo/public/c/system/macros.h" -#include "mojo/public/c/system/system_export.h" -#include "mojo/public/c/system/types.h" - -// |MojoMessageHandle|: Used to refer to message objects created by -// |MojoAllocMessage()| and transferred by |MojoWriteMessageNew()| or -// |MojoReadMessageNew()|. - -typedef uintptr_t MojoMessageHandle; - -#ifdef __cplusplus -const MojoMessageHandle MOJO_MESSAGE_HANDLE_INVALID = 0; -#else -#define MOJO_MESSAGE_HANDLE_INVALID ((MojoMessageHandle)0) -#endif - -// |MojoCreateMessagePipeOptions|: Used to specify creation parameters for a -// message pipe to |MojoCreateMessagePipe()|. -// |uint32_t struct_size|: Set to the size of the -// |MojoCreateMessagePipeOptions| struct. (Used to allow for future -// extensions.) -// |MojoCreateMessagePipeOptionsFlags flags|: Used to specify different modes -// of operation. -// |MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE|: No flags; default mode. - -typedef uint32_t MojoCreateMessagePipeOptionsFlags; - -#ifdef __cplusplus -const MojoCreateMessagePipeOptionsFlags - MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE = 0; -#else -#define MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE \ - ((MojoCreateMessagePipeOptionsFlags)0) -#endif - -MOJO_STATIC_ASSERT(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment"); -struct MOJO_ALIGNAS(8) MojoCreateMessagePipeOptions { - uint32_t struct_size; - MojoCreateMessagePipeOptionsFlags flags; -}; -MOJO_STATIC_ASSERT(sizeof(MojoCreateMessagePipeOptions) == 8, - "MojoCreateMessagePipeOptions has wrong size"); - -// |MojoWriteMessageFlags|: Used to specify different modes to -// |MojoWriteMessage()|. -// |MOJO_WRITE_MESSAGE_FLAG_NONE| - No flags; default mode. - -typedef uint32_t MojoWriteMessageFlags; - -#ifdef __cplusplus -const MojoWriteMessageFlags MOJO_WRITE_MESSAGE_FLAG_NONE = 0; -#else -#define MOJO_WRITE_MESSAGE_FLAG_NONE ((MojoWriteMessageFlags)0) -#endif - -// |MojoReadMessageFlags|: Used to specify different modes to -// |MojoReadMessage()|. -// |MOJO_READ_MESSAGE_FLAG_NONE| - No flags; default mode. -// |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| - If the message is unable to be read -// for whatever reason (e.g., the caller-supplied buffer is too small), -// discard the message (i.e., simply dequeue it). - -typedef uint32_t MojoReadMessageFlags; - -#ifdef __cplusplus -const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_NONE = 0; -const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_MAY_DISCARD = 1 << 0; -#else -#define MOJO_READ_MESSAGE_FLAG_NONE ((MojoReadMessageFlags)0) -#define MOJO_READ_MESSAGE_FLAG_MAY_DISCARD ((MojoReadMessageFlags)1 << 0) -#endif - -// |MojoAllocMessageFlags|: Used to specify different options for -// |MojoAllocMessage()|. -// |MOJO_ALLOC_MESSAGE_FLAG_NONE| - No flags; default mode. - -typedef uint32_t MojoAllocMessageFlags; - -#ifdef __cplusplus -const MojoAllocMessageFlags MOJO_ALLOC_MESSAGE_FLAG_NONE = 0; -#else -#define MOJO_ALLOC_MESSAGE_FLAG_NONE ((MojoAllocMessageFlags)0) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -// Note: See the comment in functions.h about the meaning of the "optional" -// label for pointer parameters. - -// Creates a message pipe, which is a bidirectional communication channel for -// framed data (i.e., messages). Messages can contain plain data and/or Mojo -// handles. -// -// |options| may be set to null for a message pipe with the default options. -// -// On success, |*message_pipe_handle0| and |*message_pipe_handle1| are set to -// handles for the two endpoints (ports) for the message pipe. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., -// |*options| is invalid). -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has -// been reached. -MOJO_SYSTEM_EXPORT MojoResult MojoCreateMessagePipe( - const struct MojoCreateMessagePipeOptions* options, // Optional. - MojoHandle* message_pipe_handle0, // Out. - MojoHandle* message_pipe_handle1); // Out. - -// Writes a message to the message pipe endpoint given by |message_pipe_handle|, -// with message data specified by |bytes| of size |num_bytes| and attached -// handles specified by |handles| of count |num_handles|, and options specified -// by |flags|. If there is no message data, |bytes| may be null, in which case -// |num_bytes| must be zero. If there are no attached handles, |handles| may be -// null, in which case |num_handles| must be zero. -// -// If handles are attached, the handles will no longer be valid (on success the -// receiver will receive equivalent, but logically different, handles). Handles -// to be sent should not be in simultaneous use (e.g., on another thread). -// -// Returns: -// |MOJO_RESULT_OK| on success (i.e., the message was enqueued). -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if -// |message_pipe_handle| is not a valid handle, or some of the -// requirements above are not satisfied). -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if some system limit has been reached, or -// the number of handles to send is too large (TODO(vtl): reconsider the -// latter case). -// |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed. -// Note that closing an endpoint is not necessarily synchronous (e.g., -// across processes), so this function may succeed even if the other -// endpoint has been closed (in which case the message would be dropped). -// |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|. -// |MOJO_RESULT_BUSY| if some handle to be sent is currently in use. -// -// TODO(vtl): Add a notion of capacity for message pipes, and return -// |MOJO_RESULT_SHOULD_WAIT| if the message pipe is full. -MOJO_SYSTEM_EXPORT MojoResult - MojoWriteMessage(MojoHandle message_pipe_handle, - const void* bytes, // Optional. - uint32_t num_bytes, - const MojoHandle* handles, // Optional. - uint32_t num_handles, - MojoWriteMessageFlags flags); - -// Writes a message to the message pipe endpoint given by |message_pipe_handle|. -// -// |message|: A message object allocated by |MojoAllocMessage()|. Ownership of -// the message is passed into Mojo. -// -// Returns results corresponding to |MojoWriteMessage()| above. -MOJO_SYSTEM_EXPORT MojoResult - MojoWriteMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags); - -// Reads the next message from a message pipe, or indicates the size of the -// message if it cannot fit in the provided buffers. The message will be read -// in its entirety or not at all; if it is not, it will remain enqueued unless -// the |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| flag was passed. At most one -// message will be consumed from the queue, and the return value will indicate -// whether a message was successfully read. -// -// |num_bytes| and |num_handles| are optional in/out parameters that on input -// must be set to the sizes of the |bytes| and |handles| arrays, and on output -// will be set to the actual number of bytes or handles contained in the -// message (even if the message was not retrieved due to being too large). -// Either |num_bytes| or |num_handles| may be null if the message is not -// expected to contain the corresponding type of data, but such a call would -// fail with |MOJO_RESULT_RESOURCE_EXHAUSTED| if the message in fact did -// contain that type of data. -// -// |bytes| and |handles| will receive the contents of the message, if it is -// retrieved. Either or both may be null, in which case the corresponding size -// parameter(s) must also be set to zero or passed as null. -// -// Returns: -// |MOJO_RESULT_OK| on success (i.e., a message was actually read). -// |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid. -// |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed. -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if the message was too large to fit in the -// provided buffer(s). The message will have been left in the queue or -// discarded, depending on flags. -// |MOJO_RESULT_SHOULD_WAIT| if no message was available to be read. -// -// TODO(vtl): Reconsider the |MOJO_RESULT_RESOURCE_EXHAUSTED| error code; should -// distinguish this from the hitting-system-limits case. -MOJO_SYSTEM_EXPORT MojoResult - MojoReadMessage(MojoHandle message_pipe_handle, - void* bytes, // Optional out. - uint32_t* num_bytes, // Optional in/out. - MojoHandle* handles, // Optional out. - uint32_t* num_handles, // Optional in/out. - MojoReadMessageFlags flags); - -// Reads the next message from a message pipe and returns a message containing -// the message bytes. The returned message must eventually be freed using -// |MojoFreeMessage()|. -// -// Message payload can be accessed using |MojoGetMessageBuffer()|. -// -// |message_pipe_handle|, |num_bytes|, |handles|, |num_handles|, and |flags| -// correspond to their use in |MojoReadMessage()| above, with the -// exception that |num_bytes| is only an output argument. -// |message| must be non-null unless |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| is -// set in flags. -// -// Return values correspond to the return values for |MojoReadMessage()| above. -// On success (MOJO_RESULT_OK), |*message| will contain a handle to a message -// object which may be passed to |MojoGetMessageBuffer()|. The caller owns the -// message object and is responsible for freeing it via |MojoFreeMessage()|. -MOJO_SYSTEM_EXPORT MojoResult - MojoReadMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle* message, // Optional out. - uint32_t* num_bytes, // Optional out. - MojoHandle* handles, // Optional out. - uint32_t* num_handles, // Optional in/out. - MojoReadMessageFlags flags); - -// Fuses two message pipe endpoints together. Given two pipes: -// -// A <-> B and C <-> D -// -// Fusing handle B and handle C results in a single pipe: -// -// A <-> D -// -// Handles B and C are ALWAYS closed. Any unread messages at C will eventually -// be delivered to A, and any unread messages at B will eventually be delivered -// to D. -// -// NOTE: A handle may only be fused if it is an open message pipe handle which -// has not been written to. -// -// Returns: -// |MOJO_RESULT_OK| on success. -// |MOJO_RESULT_FAILED_PRECONDITION| if both handles were valid message pipe -// handles but could not be merged (e.g. one of them has been written to). -// |MOJO_INVALID_ARGUMENT| if either handle is not a fusable message pipe -// handle. -MOJO_SYSTEM_EXPORT MojoResult - MojoFuseMessagePipes(MojoHandle handle0, MojoHandle handle1); - -// Allocates a new message whose ownership may be passed to -// |MojoWriteMessageNew()|. Use |MojoGetMessageBuffer()| to retrieve the address -// of the mutable message payload. -// -// |num_bytes|: The size of the message payload in bytes. -// |handles|: An array of handles to transfer in the message. This takes -// ownership of and invalidates all contained handles. Must be null if and -// only if |num_handles| is 0. -// |num_handles|: The number of handles contained in |handles|. -// |flags|: Must be |MOJO_CREATE_MESSAGE_FLAG_NONE|. -// |message|: The address of a handle to be filled with the allocated message's -// handle. Must be non-null. -// -// Returns: -// |MOJO_RESULT_OK| if the message was successfully allocated. In this case -// |*message| will be populated with a handle to an allocated message -// with a buffer large enough to hold |num_bytes| contiguous bytes. -// |MOJO_RESULT_INVALID_ARGUMENT| if one or more handles in |handles| was -// invalid, or |handles| was null with a non-zero |num_handles|. -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if allocation failed because either -// |num_bytes| or |num_handles| exceeds an implementation-defined maximum. -// |MOJO_RESULT_BUSY| if one or more handles in |handles| cannot be sent at -// the time of this call. -// -// Only upon successful message allocation will all handles in |handles| be -// transferred into the message and invalidated. -MOJO_SYSTEM_EXPORT MojoResult -MojoAllocMessage(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message); // Out - -// Frees a message allocated by |MojoAllocMessage()| or |MojoReadMessageNew()|. -// -// |message|: The message to free. This must correspond to a message previously -// allocated by |MojoAllocMessage()| or |MojoReadMessageNew()|. Note that if -// the message has already been passed to |MojoWriteMessageNew()| it should -// NOT also be freed with this API. -// -// Returns: -// |MOJO_RESULT_OK| if |message| was valid and has been freed. -// |MOJO_RESULT_INVALID_ARGUMENT| if |message| was not a valid message. -MOJO_SYSTEM_EXPORT MojoResult MojoFreeMessage(MojoMessageHandle message); - -// Retrieves the address of mutable message bytes for a message allocated by -// either |MojoAllocMessage()| or |MojoReadMessageNew()|. -// -// Returns: -// |MOJO_RESULT_OK| if |message| is a valid message object. |*buffer| will -// be updated to point to mutable message bytes. -// |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message object. -// -// NOTE: A returned buffer address is always guaranteed to be 8-byte aligned. -MOJO_SYSTEM_EXPORT MojoResult MojoGetMessageBuffer(MojoMessageHandle message, - void** buffer); // Out - -// Notifies the system that a bad message was received on a message pipe, -// according to whatever criteria the caller chooses. This ultimately tries to -// notify the embedder about the bad message, and the embedder may enforce some -// policy for dealing with the source of the message (e.g. close the pipe, -// terminate, a process, etc.) The embedder may not be notified if the calling -// process has lost its connection to the source process. -// -// |message|: The message to report as bad. This must have come from a call to -// |MojoReadMessageNew()|. -// |error|: An error string which may provide the embedder with context when -// notified of this error. -// |error_num_bytes|: The length of |error| in bytes. -// -// Returns: -// |MOJO_RESULT_OK| if successful. -// |MOJO_RESULT_INVALID_ARGUMENT| if |message| is not a valid message. -MOJO_SYSTEM_EXPORT MojoResult -MojoNotifyBadMessage(MojoMessageHandle message, - const char* error, - size_t error_num_bytes); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_MESSAGE_PIPE_H_ diff --git a/mojo/public/c/system/platform_handle.h b/mojo/public/c/system/platform_handle.h deleted file mode 100644 index 7449c2e..0000000 --- a/mojo/public/c/system/platform_handle.h +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains types/functions and constants for platform handle wrapping -// and unwrapping APIs. -// -// Note: This header should be compilable as C. - -#ifndef MOJO_PUBLIC_C_SYSTEM_PLATFORM_HANDLE_H_ -#define MOJO_PUBLIC_C_SYSTEM_PLATFORM_HANDLE_H_ - -#include - -#include "mojo/public/c/system/system_export.h" -#include "mojo/public/c/system/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// |MojoPlatformHandleType|: A value indicating the specific type of platform -// handle encapsulated by a MojoPlatformHandle (see below.) This is stored -// in the MojoPlatformHandle's |type| field and determines how the |value| -// field is interpreted. -// -// |MOJO_PLATFORM_HANDLE_TYPE_INVALID| - An invalid platform handle. -// |MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR| - A file descriptor. Only valid -// on POSIX systems. -// |MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT| - A Mach port. Only valid on OS X. -// |MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE| - A Windows HANDLE value. Only -// valid on Windows. - -typedef uint32_t MojoPlatformHandleType; - -#ifdef __cplusplus -const MojoPlatformHandleType MOJO_PLATFORM_HANDLE_TYPE_INVALID = 0; -const MojoPlatformHandleType MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR = 1; -const MojoPlatformHandleType MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT = 2; -const MojoPlatformHandleType MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE = 3; -#else -#define MOJO_PLATFORM_HANDLE_TYPE_INVALID ((MojoPlatformHandleType)0) -#define MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR ((MojoPlatformHandleType)1) -#define MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT ((MojoPlatformHandleType)2) -#define MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE ((MojoPlatformHandleType)3) -#endif - -// |MojoPlatformHandle|: A handle to a native platform object. -// -// |uint32_t struct_size|: The size of this structure. Used for versioning -// to allow for future extensions. -// -// |MojoPlatformHandleType type|: The type of handle stored in |value|. -// -// |uint64_t value|: The value of this handle. Ignored if |type| is -// MOJO_PLATFORM_HANDLE_TYPE_INVALID. Otherwise the meaning of this -// value depends on the value of |type|. -// - -struct MOJO_ALIGNAS(8) MojoPlatformHandle { - uint32_t struct_size; - MojoPlatformHandleType type; - uint64_t value; -}; -MOJO_STATIC_ASSERT(sizeof(MojoPlatformHandle) == 16, - "MojoPlatformHandle has wrong size"); - -// |MojoPlatformSharedBufferHandleFlags|: Flags relevant to wrapped platform -// shared buffers. -// -// |MOJO_PLATFORM_SHARED_BUFFER_HANDLE_NONE| - No flags. -// |MOJO_PLATFORM_SHARED_BUFFER_HANDLE_READ_ONLY| - Indicates that the wrapped -// buffer handle may only be mapped for reading. - -typedef uint32_t MojoPlatformSharedBufferHandleFlags; - -#ifdef __cplusplus -const MojoPlatformSharedBufferHandleFlags -MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE = 0; - -const MojoPlatformSharedBufferHandleFlags -MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY = 1 << 0; -#else -#define MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE \ - ((MojoPlatformSharedBufferHandleFlags)0) - -#define MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY \ - ((MojoPlatformSharedBufferHandleFlags)1 << 0) -#endif - -// Wraps a native platform handle as a Mojo handle which can be transferred -// over a message pipe. Takes ownership of the underlying native platform -// object. -// -// |platform_handle|: The platform handle to wrap. -// -// Returns: -// |MOJO_RESULT_OK| if the handle was successfully wrapped. In this case -// |*mojo_handle| contains the Mojo handle of the wrapped object. -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if the system is out of handles. -// |MOJO_RESULT_INVALID_ARGUMENT| if |platform_handle| was not a valid -// platform handle. -// -// NOTE: It is not always possible to detect if |platform_handle| is valid, -// particularly when |platform_handle->type| is valid but -// |platform_handle->value| does not represent a valid platform object. -MOJO_SYSTEM_EXPORT MojoResult -MojoWrapPlatformHandle(const struct MojoPlatformHandle* platform_handle, - MojoHandle* mojo_handle); // Out - -// Unwraps a native platform handle from a Mojo handle. If this call succeeds, -// ownership of the underlying platform object is assumed by the caller. The -// The Mojo handle is always closed regardless of success or failure. -// -// |mojo_handle|: The Mojo handle from which to unwrap the native platform -// handle. -// -// Returns: -// |MOJO_RESULT_OK| if the handle was successfully unwrapped. In this case -// |*platform_handle| contains the unwrapped platform handle. -// |MOJO_RESULT_INVALID_ARGUMENT| if |mojo_handle| was not a valid Mojo -// handle wrapping a platform handle. -MOJO_SYSTEM_EXPORT MojoResult -MojoUnwrapPlatformHandle(MojoHandle mojo_handle, - struct MojoPlatformHandle* platform_handle); // Out - -// Wraps a native platform shared buffer handle as a Mojo shared buffer handle -// which can be used exactly like a shared buffer handle created by -// |MojoCreateSharedBuffer()| or |MojoDuplicateBufferHandle()|. -// -// Takes ownership of the native platform shared buffer handle. -// -// |platform_handle|: The platform handle to wrap. Must be a native handle to a -// shared buffer object. -// |num_bytes|: The size of the shared buffer in bytes. -// |flags|: Flags which influence the treatment of the shared buffer object. See -// below. -// -// Flags: -// |MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE| indicates default behavior. -// No flags set. -// |MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY| indicates that the -// buffer handled to be wrapped may only be mapped as read-only. This -// flag does NOT change the access control of the buffer in any way. -// -// Returns: -// |MOJO_RESULT_OK| if the handle was successfully wrapped. In this case -// |*mojo_handle| contains a Mojo shared buffer handle. -// |MOJO_RESULT_INVALID_ARGUMENT| if |platform_handle| was not a valid -// platform shared buffer handle. -MOJO_SYSTEM_EXPORT MojoResult -MojoWrapPlatformSharedBufferHandle( - const struct MojoPlatformHandle* platform_handle, - size_t num_bytes, - MojoPlatformSharedBufferHandleFlags flags, - MojoHandle* mojo_handle); // Out - -// Unwraps a native platform shared buffer handle from a Mojo shared buffer -// handle. If this call succeeds, ownership of the underlying shared buffer -// object is assumed by the caller. -// -// The Mojo handle is always closed regardless of success or failure. -// -// |mojo_handle|: The Mojo shared buffer handle to unwrap. -// -// |platform_handle|, |num_bytes| and |flags| are used to receive output values -// and MUST always be non-null. -// -// Returns: -// |MOJO_RESULT_OK| if the handle was successfully unwrapped. In this case -// |*platform_handle| contains a platform shared buffer handle, -// |*num_bytes| contains the size of the shared buffer object, and -// |*flags| indicates flags relevant to the wrapped buffer (see below). -// |MOJO_RESULT_INVALID_ARGUMENT| if |mojo_handle| is not a valid Mojo -// shared buffer handle. -// -// Flags which may be set in |*flags| upon success: -// |MOJO_PLATFORM_SHARED_BUFFER_FLAG_READ_ONLY| is set iff the unwrapped -// shared buffer handle may only be mapped as read-only. -MOJO_SYSTEM_EXPORT MojoResult -MojoUnwrapPlatformSharedBufferHandle( - MojoHandle mojo_handle, - struct MojoPlatformHandle* platform_handle, - size_t* num_bytes, - MojoPlatformSharedBufferHandleFlags* flags); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_PLATFORM_HANDLE_H_ diff --git a/mojo/public/c/system/set_thunks_for_app.cc b/mojo/public/c/system/set_thunks_for_app.cc deleted file mode 100644 index 335cc02..0000000 --- a/mojo/public/c/system/set_thunks_for_app.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/c/system/thunks.h" - -extern "C" { - -#if defined(WIN32) -#define THUNKS_EXPORT __declspec(dllexport) -#else -#define THUNKS_EXPORT __attribute__((visibility("default"))) -#endif - -THUNKS_EXPORT size_t MojoSetSystemThunks( - const MojoSystemThunks* system_thunks) { - return MojoEmbedderSetSystemThunks(system_thunks); -} - -} // extern "C" diff --git a/mojo/public/c/system/system_export.h b/mojo/public/c/system/system_export.h deleted file mode 100644 index 775f667..0000000 --- a/mojo/public/c/system/system_export.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_ -#define MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_ - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(MOJO_SYSTEM_IMPLEMENTATION) -#define MOJO_SYSTEM_EXPORT __declspec(dllexport) -#else -#define MOJO_SYSTEM_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(MOJO_SYSTEM_IMPLEMENTATION) -#define MOJO_SYSTEM_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_SYSTEM_EXPORT -#endif - -#endif // defined(WIN32) - -#else // !defined(COMPONENT_BUILD) - -#define MOJO_SYSTEM_EXPORT - -#endif // defined(COMPONENT_BUILD) - -#endif // MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_ diff --git a/mojo/public/c/system/tests/BUILD.gn b/mojo/public/c/system/tests/BUILD.gn deleted file mode 100644 index bace63c..0000000 --- a/mojo/public/c/system/tests/BUILD.gn +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("tests") { - testonly = true - - visibility = [ - "//mojo/public/cpp/system/tests:mojo_public_system_unittests", - "//mojo/public/cpp/system/tests:tests", - ] - - sources = [ - "core_unittest.cc", - "core_unittest_pure_c.c", - "macros_unittest.cc", - ] - - deps = [ - "//mojo/public/c/system", - "//mojo/public/cpp/system", - "//testing/gtest", - ] -} - -source_set("perftests") { - testonly = true - - sources = [ - "core_perftest.cc", - ] - - deps = [ - "//mojo/public/cpp/system", - "//mojo/public/cpp/test_support:test_utils", - "//testing/gtest", - ] -} diff --git a/mojo/public/c/system/tests/core_perftest.cc b/mojo/public/c/system/tests/core_perftest.cc deleted file mode 100644 index cab465b..0000000 --- a/mojo/public/c/system/tests/core_perftest.cc +++ /dev/null @@ -1,329 +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. - -// This tests the performance of the C API. - -#include "mojo/public/c/system/core.h" - -#include -#include -#include - -#include "base/macros.h" -#include "base/threading/simple_thread.h" -#include "mojo/public/cpp/system/wait.h" -#include "mojo/public/cpp/test_support/test_support.h" -#include "mojo/public/cpp/test_support/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if !defined(WIN32) -#include -#endif // !defined(WIN32) - -namespace { - -#if !defined(WIN32) -class MessagePipeWriterThread : public base::SimpleThread { - public: - MessagePipeWriterThread(MojoHandle handle, uint32_t num_bytes) - : SimpleThread("MessagePipeWriterThread"), - handle_(handle), - num_bytes_(num_bytes), - num_writes_(0) {} - ~MessagePipeWriterThread() override {} - - void Run() override { - char buffer[10000]; - assert(num_bytes_ <= sizeof(buffer)); - - // TODO(vtl): Should I throttle somehow? - for (;;) { - MojoResult result = MojoWriteMessage(handle_, buffer, num_bytes_, nullptr, - 0, MOJO_WRITE_MESSAGE_FLAG_NONE); - if (result == MOJO_RESULT_OK) { - num_writes_++; - continue; - } - - // We failed to write. - // Either |handle_| or its peer was closed. - assert(result == MOJO_RESULT_INVALID_ARGUMENT || - result == MOJO_RESULT_FAILED_PRECONDITION); - break; - } - } - - // Use only after joining the thread. - int64_t num_writes() const { return num_writes_; } - - private: - const MojoHandle handle_; - const uint32_t num_bytes_; - int64_t num_writes_; - - DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread); -}; - -class MessagePipeReaderThread : public base::SimpleThread { - public: - explicit MessagePipeReaderThread(MojoHandle handle) - : SimpleThread("MessagePipeReaderThread"), - handle_(handle), - num_reads_(0) {} - ~MessagePipeReaderThread() override {} - - void Run() override { - char buffer[10000]; - - for (;;) { - uint32_t num_bytes = static_cast(sizeof(buffer)); - MojoResult result = MojoReadMessage(handle_, buffer, &num_bytes, nullptr, - nullptr, MOJO_READ_MESSAGE_FLAG_NONE); - if (result == MOJO_RESULT_OK) { - num_reads_++; - continue; - } - - if (result == MOJO_RESULT_SHOULD_WAIT) { - result = mojo::Wait(mojo::Handle(handle_), MOJO_HANDLE_SIGNAL_READABLE); - if (result == MOJO_RESULT_OK) { - // Go to the top of the loop to read again. - continue; - } - } - - // We failed to read and possibly failed to wait. - // Either |handle_| or its peer was closed. - assert(result == MOJO_RESULT_INVALID_ARGUMENT || - result == MOJO_RESULT_FAILED_PRECONDITION); - break; - } - } - - // Use only after joining the thread. - int64_t num_reads() const { return num_reads_; } - - private: - const MojoHandle handle_; - int64_t num_reads_; - - DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread); -}; -#endif // !defined(WIN32) - -class CorePerftest : public testing::Test { - public: - CorePerftest() : buffer_(nullptr), num_bytes_(0) {} - ~CorePerftest() override {} - - static void NoOp(void* /*closure*/) {} - - static void MessagePipe_CreateAndClose(void* closure) { - CorePerftest* self = static_cast(closure); - MojoResult result = MojoCreateMessagePipe(nullptr, &self->h0_, &self->h1_); - ALLOW_UNUSED_LOCAL(result); - assert(result == MOJO_RESULT_OK); - result = MojoClose(self->h0_); - assert(result == MOJO_RESULT_OK); - result = MojoClose(self->h1_); - assert(result == MOJO_RESULT_OK); - } - - static void MessagePipe_WriteAndRead(void* closure) { - CorePerftest* self = static_cast(closure); - MojoResult result = - MojoWriteMessage(self->h0_, self->buffer_, self->num_bytes_, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE); - ALLOW_UNUSED_LOCAL(result); - assert(result == MOJO_RESULT_OK); - uint32_t read_bytes = self->num_bytes_; - 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(closure); - MojoResult result = - MojoReadMessage(self->h0_, nullptr, nullptr, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); - ALLOW_UNUSED_LOCAL(result); - assert(result == MOJO_RESULT_SHOULD_WAIT); - } - - protected: -#if !defined(WIN32) - void DoMessagePipeThreadedTest(unsigned num_writers, - unsigned num_readers, - uint32_t num_bytes) { - static const int64_t kPerftestTimeMicroseconds = 3 * 1000000; - - assert(num_writers > 0); - assert(num_readers > 0); - - MojoResult result = MojoCreateMessagePipe(nullptr, &h0_, &h1_); - ALLOW_UNUSED_LOCAL(result); - assert(result == MOJO_RESULT_OK); - - std::vector writers; - for (unsigned i = 0; i < num_writers; i++) - writers.push_back(new MessagePipeWriterThread(h0_, num_bytes)); - - std::vector readers; - for (unsigned i = 0; i < num_readers; i++) - readers.push_back(new MessagePipeReaderThread(h1_)); - - // Start time here, just before we fire off the threads. - const MojoTimeTicks start_time = MojoGetTimeTicksNow(); - - // Interleave the starts. - for (unsigned i = 0; i < num_writers || i < num_readers; i++) { - if (i < num_writers) - writers[i]->Start(); - if (i < num_readers) - readers[i]->Start(); - } - - Sleep(kPerftestTimeMicroseconds); - - // Close both handles to make writers and readers stop immediately. - result = MojoClose(h0_); - assert(result == MOJO_RESULT_OK); - result = MojoClose(h1_); - assert(result == MOJO_RESULT_OK); - - // Join everything. - for (unsigned i = 0; i < num_writers; i++) - writers[i]->Join(); - for (unsigned i = 0; i < num_readers; i++) - readers[i]->Join(); - - // Stop time here. - MojoTimeTicks end_time = MojoGetTimeTicksNow(); - - // Add up write and read counts, and destroy the threads. - int64_t num_writes = 0; - for (unsigned i = 0; i < num_writers; i++) { - num_writes += writers[i]->num_writes(); - delete writers[i]; - } - writers.clear(); - int64_t num_reads = 0; - for (unsigned i = 0; i < num_readers; i++) { - num_reads += readers[i]->num_reads(); - delete readers[i]; - } - readers.clear(); - - char sub_test_name[200]; - sprintf(sub_test_name, "%uw_%ur_%ubytes", num_writers, num_readers, - static_cast(num_bytes)); - mojo::test::LogPerfResult( - "MessagePipe_Threaded_Writes", sub_test_name, - 1000000.0 * static_cast(num_writes) / (end_time - start_time), - "writes/second"); - mojo::test::LogPerfResult( - "MessagePipe_Threaded_Reads", sub_test_name, - 1000000.0 * static_cast(num_reads) / (end_time - start_time), - "reads/second"); - } -#endif // !defined(WIN32) - - MojoHandle h0_; - MojoHandle h1_; - - void* buffer_; - uint32_t num_bytes_; - - private: -#if !defined(WIN32) - void Sleep(int64_t microseconds) { - struct timespec req = { - static_cast(microseconds / 1000000), // Seconds. - static_cast(microseconds % 1000000) * 1000L // Nanoseconds. - }; - int rv = nanosleep(&req, nullptr); - ALLOW_UNUSED_LOCAL(rv); - assert(rv == 0); - } -#endif // !defined(WIN32) - - DISALLOW_COPY_AND_ASSIGN(CorePerftest); -}; - -// A no-op test so we can compare performance. -TEST_F(CorePerftest, NoOp) { - mojo::test::IterateAndReportPerf("Iterate_NoOp", nullptr, &CorePerftest::NoOp, - this); -} - -TEST_F(CorePerftest, MessagePipe_CreateAndClose) { - mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose", nullptr, - &CorePerftest::MessagePipe_CreateAndClose, - this); -} - -TEST_F(CorePerftest, MessagePipe_WriteAndRead) { - MojoResult result = MojoCreateMessagePipe(nullptr, &h0_, &h1_); - ALLOW_UNUSED_LOCAL(result); - assert(result == MOJO_RESULT_OK); - char buffer[10000] = {0}; - buffer_ = buffer; - num_bytes_ = 10u; - mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead", "10bytes", - &CorePerftest::MessagePipe_WriteAndRead, - this); - num_bytes_ = 100u; - mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead", "100bytes", - &CorePerftest::MessagePipe_WriteAndRead, - this); - num_bytes_ = 1000u; - mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead", "1000bytes", - &CorePerftest::MessagePipe_WriteAndRead, - this); - num_bytes_ = 10000u; - mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead", "10000bytes", - &CorePerftest::MessagePipe_WriteAndRead, - this); - result = MojoClose(h0_); - assert(result == MOJO_RESULT_OK); - result = MojoClose(h1_); - assert(result == MOJO_RESULT_OK); -} - -TEST_F(CorePerftest, MessagePipe_EmptyRead) { - MojoResult result = MojoCreateMessagePipe(nullptr, &h0_, &h1_); - ALLOW_UNUSED_LOCAL(result); - assert(result == MOJO_RESULT_OK); - mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead", nullptr, - &CorePerftest::MessagePipe_EmptyRead, this); - result = MojoClose(h0_); - assert(result == MOJO_RESULT_OK); - result = MojoClose(h1_); - assert(result == MOJO_RESULT_OK); -} - -#if !defined(WIN32) -TEST_F(CorePerftest, MessagePipe_Threaded) { - DoMessagePipeThreadedTest(1u, 1u, 100u); - DoMessagePipeThreadedTest(2u, 2u, 100u); - DoMessagePipeThreadedTest(3u, 3u, 100u); - DoMessagePipeThreadedTest(10u, 10u, 100u); - DoMessagePipeThreadedTest(10u, 1u, 100u); - DoMessagePipeThreadedTest(1u, 10u, 100u); - - // For comparison of overhead: - DoMessagePipeThreadedTest(1u, 1u, 10u); - // 100 was done above. - DoMessagePipeThreadedTest(1u, 1u, 1000u); - DoMessagePipeThreadedTest(1u, 1u, 10000u); - - DoMessagePipeThreadedTest(3u, 3u, 10u); - // 100 was done above. - DoMessagePipeThreadedTest(3u, 3u, 1000u); - DoMessagePipeThreadedTest(3u, 3u, 10000u); -} -#endif // !defined(WIN32) - -} // namespace diff --git a/mojo/public/c/system/tests/core_unittest.cc b/mojo/public/c/system/tests/core_unittest.cc deleted file mode 100644 index a9da255..0000000 --- a/mojo/public/c/system/tests/core_unittest.cc +++ /dev/null @@ -1,322 +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. - -// This file tests the C API. - -#include "mojo/public/c/system/core.h" - -#include -#include - -#include "mojo/public/cpp/system/wait.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -const MojoHandleSignals kSignalReadadableWritable = - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; - -const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE | - MOJO_HANDLE_SIGNAL_PEER_CLOSED; - -TEST(CoreTest, GetTimeTicksNow) { - const MojoTimeTicks start = MojoGetTimeTicksNow(); - EXPECT_NE(static_cast(0), start) - << "MojoGetTimeTicksNow should return nonzero value"; -} - -// The only handle that's guaranteed to be invalid is |MOJO_HANDLE_INVALID|. -// Tests that everything that takes a handle properly recognizes it. -TEST(CoreTest, InvalidHandle) { - MojoHandle h0, h1; - char buffer[10] = {0}; - uint32_t buffer_size; - void* write_pointer; - const void* read_pointer; - - // Close: - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(MOJO_HANDLE_INVALID)); - - // Message pipe: - h0 = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWriteMessage(h0, buffer, 3, nullptr, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - buffer_size = static_cast(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Data pipe: - buffer_size = static_cast(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWriteData(h0, buffer, &buffer_size, MOJO_WRITE_DATA_FLAG_NONE)); - write_pointer = nullptr; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoBeginWriteData(h0, &write_pointer, &buffer_size, - MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoEndWriteData(h0, 1)); - buffer_size = static_cast(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoReadData(h0, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE)); - read_pointer = nullptr; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoBeginReadData(h0, &read_pointer, &buffer_size, - MOJO_READ_DATA_FLAG_NONE)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoEndReadData(h0, 1)); - - // Shared buffer: - h1 = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoDuplicateBufferHandle(h0, nullptr, &h1)); - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoMapBuffer(h0, 0, 1, &write_pointer, MOJO_MAP_BUFFER_FLAG_NONE)); -} - -TEST(CoreTest, BasicMessagePipe) { - MojoHandle h0, h1; - MojoHandleSignals sig; - char buffer[10] = {0}; - uint32_t buffer_size; - - h0 = MOJO_HANDLE_INVALID; - h1 = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &h0, &h1)); - EXPECT_NE(h0, MOJO_HANDLE_INVALID); - EXPECT_NE(h1, MOJO_HANDLE_INVALID); - - // Shouldn't be readable, we haven't written anything. Should be writable. - MojoHandleSignalsState state; - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(h0, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - // Try to read. - buffer_size = static_cast(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - - // Write to |h1|. - static const char kHello[] = "hello"; - buffer_size = static_cast(sizeof(kHello)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h1, kHello, buffer_size, nullptr, - 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // |h0| should be readable. - size_t result_index = 1; - MojoHandleSignalsState states[1]; - sig = MOJO_HANDLE_SIGNAL_READABLE; - Handle handle0(h0); - EXPECT_EQ(MOJO_RESULT_OK, - mojo::WaitMany(&handle0, &sig, 1, &result_index, states)); - - EXPECT_EQ(0u, result_index); - EXPECT_EQ(kSignalReadadableWritable, states[0].satisfied_signals); - EXPECT_EQ(kSignalAll, states[0].satisfiable_signals); - - // Read from |h0|. - buffer_size = static_cast(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr, - MOJO_READ_MESSAGE_FLAG_NONE)); - EXPECT_EQ(static_cast(sizeof(kHello)), buffer_size); - EXPECT_STREQ(kHello, buffer); - - // |h0| should no longer be readable. - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(h0, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); - EXPECT_EQ(kSignalAll, state.satisfiable_signals); - - // Close |h0|. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0)); - - EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h1), - MOJO_HANDLE_SIGNAL_PEER_CLOSED, &state)); - - // |h1| should no longer be readable or writable. - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - mojo::Wait(mojo::Handle(h1), - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, - &state)); - - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1)); -} - -TEST(CoreTest, BasicDataPipe) { - MojoHandle hp, hc; - MojoHandleSignals sig; - char buffer[20] = {0}; - uint32_t buffer_size; - void* write_pointer; - const void* read_pointer; - - hp = MOJO_HANDLE_INVALID; - hc = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &hp, &hc)); - EXPECT_NE(hp, MOJO_HANDLE_INVALID); - EXPECT_NE(hc, MOJO_HANDLE_INVALID); - - // The consumer |hc| shouldn't be readable. - MojoHandleSignalsState state; - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(hc, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - state.satisfiable_signals); - - // The producer |hp| should be writable. - EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(hp, &state)); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - state.satisfiable_signals); - - // Try to read from |hc|. - buffer_size = static_cast(sizeof(buffer)); - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE)); - - // Try to begin a two-phase read from |hc|. - read_pointer = nullptr; - EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - MojoBeginReadData(hc, &read_pointer, &buffer_size, - MOJO_READ_DATA_FLAG_NONE)); - - // Write to |hp|. - static const char kHello[] = "hello "; - // Don't include terminating null. - buffer_size = static_cast(strlen(kHello)); - EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(hp, kHello, &buffer_size, - MOJO_WRITE_MESSAGE_FLAG_NONE)); - - // |hc| should be(come) readable. - size_t result_index = 1; - MojoHandleSignalsState states[1]; - sig = MOJO_HANDLE_SIGNAL_READABLE; - Handle consumer_handle(hc); - EXPECT_EQ(MOJO_RESULT_OK, - mojo::WaitMany(&consumer_handle, &sig, 1, &result_index, states)); - - EXPECT_EQ(0u, result_index); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - states[0].satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED | - MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, - states[0].satisfiable_signals); - - // Do a two-phase write to |hp|. - EXPECT_EQ(MOJO_RESULT_OK, MojoBeginWriteData(hp, &write_pointer, &buffer_size, - MOJO_WRITE_DATA_FLAG_NONE)); - static const char kWorld[] = "world"; - ASSERT_GE(buffer_size, sizeof(kWorld)); - // Include the terminating null. - memcpy(write_pointer, kWorld, sizeof(kWorld)); - EXPECT_EQ(MOJO_RESULT_OK, - MojoEndWriteData(hp, static_cast(sizeof(kWorld)))); - - // Read one character from |hc|. - memset(buffer, 0, sizeof(buffer)); - buffer_size = 1; - EXPECT_EQ(MOJO_RESULT_OK, - MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE)); - - // Close |hp|. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hp)); - - // |hc| should still be readable. - EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(hc), - MOJO_HANDLE_SIGNAL_PEER_CLOSED, &state)); - - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - state.satisfiable_signals); - - // Do a two-phase read from |hc|. - 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); - memcpy(&buffer[1], read_pointer, buffer_size); - EXPECT_EQ(MOJO_RESULT_OK, MojoEndReadData(hc, buffer_size)); - EXPECT_STREQ("hello world", buffer); - - // |hc| should no longer be readable. - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - mojo::Wait(mojo::Handle(hc), MOJO_HANDLE_SIGNAL_READABLE, &state)); - - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hc)); - - // TODO(vtl): Test the other way around -- closing the consumer should make - // the producer never-writable? -} - -TEST(CoreTest, BasicSharedBuffer) { - MojoHandle h0, h1; - void* pointer; - - // Create a shared buffer (|h0|). - h0 = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 100, &h0)); - EXPECT_NE(h0, MOJO_HANDLE_INVALID); - - // Map everything. - pointer = nullptr; - EXPECT_EQ(MOJO_RESULT_OK, - MojoMapBuffer(h0, 0, 100, &pointer, MOJO_MAP_BUFFER_FLAG_NONE)); - ASSERT_TRUE(pointer); - static_cast(pointer)[50] = 'x'; - - // Duplicate |h0| to |h1|. - h1 = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(h0, nullptr, &h1)); - EXPECT_NE(h1, MOJO_HANDLE_INVALID); - - // Close |h0|. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0)); - - // The mapping should still be good. - static_cast(pointer)[51] = 'y'; - - // Unmap it. - EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer)); - - // Map half of |h1|. - pointer = nullptr; - EXPECT_EQ(MOJO_RESULT_OK, - MojoMapBuffer(h1, 50, 50, &pointer, MOJO_MAP_BUFFER_FLAG_NONE)); - ASSERT_TRUE(pointer); - - // It should have what we wrote. - EXPECT_EQ('x', static_cast(pointer)[0]); - EXPECT_EQ('y', static_cast(pointer)[1]); - - // Unmap it. - EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer)); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1)); -} - -// Defined in core_unittest_pure_c.c. -extern "C" const char* MinimalCTest(void); - -// This checks that things actually work in C (not C++). -TEST(CoreTest, MinimalCTest) { - const char* failure = MinimalCTest(); - EXPECT_FALSE(failure) << failure; -} - -// TODO(vtl): Add multi-threaded tests. - -} // namespace -} // namespace mojo diff --git a/mojo/public/c/system/tests/core_unittest_pure_c.c b/mojo/public/c/system/tests/core_unittest_pure_c.c deleted file mode 100644 index 3164649..0000000 --- a/mojo/public/c/system/tests/core_unittest_pure_c.c +++ /dev/null @@ -1,77 +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. - -#ifdef __cplusplus -#error "This file should be compiled as C, not C++." -#endif - -#include -#include -#include - -// Include all the header files that are meant to be compilable as C. Start with -// core.h, since it's the most important one. -#include "mojo/public/c/system/core.h" -#include "mojo/public/c/system/macros.h" - -// The joys of the C preprocessor.... -#define STRINGIFY(x) #x -#define STRINGIFY2(x) STRINGIFY(x) -#define FAILURE(message) \ - __FILE__ "(" STRINGIFY2(__LINE__) "): Failure: " message - -// Makeshift gtest. -#define EXPECT_EQ(a, b) \ - do { \ - if ((a) != (b)) \ - return FAILURE(STRINGIFY(a) " != " STRINGIFY(b) " (expected ==)"); \ - } while (0) -#define EXPECT_NE(a, b) \ - do { \ - if ((a) == (b)) \ - return FAILURE(STRINGIFY(a) " == " STRINGIFY(b) " (expected !=)"); \ - } while (0) - -// This function exists mainly to be compiled and linked. We do some cursory -// checks and call it from a unit test, to make sure that link problems aren't -// missed due to deadstripping. Returns null on success and a string on failure -// (describing the failure). -const char* MinimalCTest(void) { - // MSVS before 2013 *really* only supports C90: All variables must be declared - // at the top. (MSVS 2013 is more reasonable.) - MojoTimeTicks ticks; - MojoHandle handle0, handle1; - const char kHello[] = "hello"; - char buffer[200] = {0}; - uint32_t num_bytes; - - ticks = MojoGetTimeTicksNow(); - EXPECT_NE(ticks, 0); - - handle0 = MOJO_HANDLE_INVALID; - EXPECT_NE(MOJO_RESULT_OK, MojoClose(handle0)); - - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoQueryHandleSignalsState(handle0, NULL)); - - handle1 = MOJO_HANDLE_INVALID; - EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(NULL, &handle0, &handle1)); - - EXPECT_EQ(MOJO_RESULT_OK, - MojoWriteMessage(handle0, kHello, (uint32_t)sizeof(kHello), NULL, - 0u, MOJO_WRITE_DATA_FLAG_NONE)); - - 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((uint32_t)sizeof(kHello), num_bytes); - EXPECT_EQ(0, memcmp(buffer, kHello, sizeof(kHello))); - - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handle0)); - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handle1)); - - // TODO(vtl): data pipe - - return NULL; -} diff --git a/mojo/public/c/system/tests/macros_unittest.cc b/mojo/public/c/system/tests/macros_unittest.cc deleted file mode 100644 index fb9ff76..0000000 --- a/mojo/public/c/system/tests/macros_unittest.cc +++ /dev/null @@ -1,68 +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. - -// This file tests the C Mojo system macros and consists of "positive" tests, -// i.e., those verifying that things work (without compile errors, or even -// warnings if warnings are treated as errors). -// TODO(vtl): Fix no-compile tests (which are all disabled; crbug.com/105388) -// and write some "negative" tests. - -#include "mojo/public/c/system/macros.h" - -#include -#include -#include - -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace { - -// First test |MOJO_STATIC_ASSERT()| in a global scope. -MOJO_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), - "Bad static_assert() failure in global scope"); - -TEST(MacrosTest, CompileAssert) { - // Then in a local scope. - MOJO_STATIC_ASSERT(sizeof(int32_t) == 2 * sizeof(int16_t), - "Bad static_assert() failure"); -} - -TEST(MacrosTest, Alignof) { - // Strictly speaking, this isn't a portable test, but I think it'll pass on - // all the platforms we currently support. - EXPECT_EQ(1u, MOJO_ALIGNOF(char)); - EXPECT_EQ(4u, MOJO_ALIGNOF(int32_t)); - EXPECT_EQ(8u, MOJO_ALIGNOF(int64_t)); - EXPECT_EQ(8u, MOJO_ALIGNOF(double)); -} - -// These structs are used in the Alignas test. Define them globally to avoid -// MSVS warnings/errors. -#if defined(_MSC_VER) -#pragma warning(push) -// Disable the warning "structure was padded due to __declspec(align())". -#pragma warning(disable : 4324) -#endif -struct MOJO_ALIGNAS(1) StructAlignas1 { - char x; -}; -struct MOJO_ALIGNAS(4) StructAlignas4 { - char x; -}; -struct MOJO_ALIGNAS(8) StructAlignas8 { - char x; -}; -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -TEST(MacrosTest, Alignas) { - EXPECT_EQ(1u, MOJO_ALIGNOF(StructAlignas1)); - EXPECT_EQ(4u, MOJO_ALIGNOF(StructAlignas4)); - EXPECT_EQ(8u, MOJO_ALIGNOF(StructAlignas8)); -} - -} // namespace -} // namespace mojo diff --git a/mojo/public/c/system/thunks.cc b/mojo/public/c/system/thunks.cc deleted file mode 100644 index 67c568f..0000000 --- a/mojo/public/c/system/thunks.cc +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/c/system/thunks.h" - -#include -#include -#include - -extern "C" { - -static MojoSystemThunks g_thunks = {0}; - -MojoTimeTicks MojoGetTimeTicksNow() { - assert(g_thunks.GetTimeTicksNow); - return g_thunks.GetTimeTicksNow(); -} - -MojoResult MojoClose(MojoHandle handle) { - assert(g_thunks.Close); - return g_thunks.Close(handle); -} - -MojoResult MojoQueryHandleSignalsState( - MojoHandle handle, - struct MojoHandleSignalsState* signals_state) { - assert(g_thunks.QueryHandleSignalsState); - return g_thunks.QueryHandleSignalsState(handle, signals_state); -} - -MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options, - MojoHandle* message_pipe_handle0, - MojoHandle* message_pipe_handle1) { - assert(g_thunks.CreateMessagePipe); - return g_thunks.CreateMessagePipe(options, message_pipe_handle0, - message_pipe_handle1); -} - -MojoResult MojoWriteMessage(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags) { - assert(g_thunks.WriteMessage); - return g_thunks.WriteMessage(message_pipe_handle, bytes, num_bytes, handles, - num_handles, flags); -} - -MojoResult MojoReadMessage(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - assert(g_thunks.ReadMessage); - return g_thunks.ReadMessage(message_pipe_handle, bytes, num_bytes, handles, - num_handles, flags); -} - -MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options, - MojoHandle* data_pipe_producer_handle, - MojoHandle* data_pipe_consumer_handle) { - assert(g_thunks.CreateDataPipe); - return g_thunks.CreateDataPipe(options, data_pipe_producer_handle, - data_pipe_consumer_handle); -} - -MojoResult MojoWriteData(MojoHandle data_pipe_producer_handle, - const void* elements, - uint32_t* num_elements, - MojoWriteDataFlags flags) { - assert(g_thunks.WriteData); - return g_thunks.WriteData(data_pipe_producer_handle, elements, num_elements, - flags); -} - -MojoResult MojoBeginWriteData(MojoHandle data_pipe_producer_handle, - void** buffer, - uint32_t* buffer_num_elements, - MojoWriteDataFlags flags) { - assert(g_thunks.BeginWriteData); - return g_thunks.BeginWriteData(data_pipe_producer_handle, buffer, - buffer_num_elements, flags); -} - -MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle, - uint32_t num_elements_written) { - assert(g_thunks.EndWriteData); - return g_thunks.EndWriteData(data_pipe_producer_handle, num_elements_written); -} - -MojoResult MojoReadData(MojoHandle data_pipe_consumer_handle, - void* elements, - uint32_t* num_elements, - MojoReadDataFlags flags) { - assert(g_thunks.ReadData); - return g_thunks.ReadData(data_pipe_consumer_handle, elements, num_elements, - flags); -} - -MojoResult MojoBeginReadData(MojoHandle data_pipe_consumer_handle, - const void** buffer, - uint32_t* buffer_num_elements, - MojoReadDataFlags flags) { - assert(g_thunks.BeginReadData); - return g_thunks.BeginReadData(data_pipe_consumer_handle, buffer, - buffer_num_elements, flags); -} - -MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle, - uint32_t num_elements_read) { - assert(g_thunks.EndReadData); - return g_thunks.EndReadData(data_pipe_consumer_handle, num_elements_read); -} - -MojoResult MojoCreateSharedBuffer( - const struct MojoCreateSharedBufferOptions* options, - uint64_t num_bytes, - MojoHandle* shared_buffer_handle) { - assert(g_thunks.CreateSharedBuffer); - return g_thunks.CreateSharedBuffer(options, num_bytes, shared_buffer_handle); -} - -MojoResult MojoDuplicateBufferHandle( - MojoHandle buffer_handle, - const struct MojoDuplicateBufferHandleOptions* options, - MojoHandle* new_buffer_handle) { - assert(g_thunks.DuplicateBufferHandle); - return g_thunks.DuplicateBufferHandle(buffer_handle, options, - new_buffer_handle); -} - -MojoResult MojoMapBuffer(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - void** buffer, - MojoMapBufferFlags flags) { - assert(g_thunks.MapBuffer); - return g_thunks.MapBuffer(buffer_handle, offset, num_bytes, buffer, flags); -} - -MojoResult MojoUnmapBuffer(void* buffer) { - assert(g_thunks.UnmapBuffer); - return g_thunks.UnmapBuffer(buffer); -} - -MojoResult MojoCreateWatcher(MojoWatcherCallback callback, - MojoHandle* watcher_handle) { - assert(g_thunks.CreateWatcher); - return g_thunks.CreateWatcher(callback, watcher_handle); -} - -MojoResult MojoWatch(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - uintptr_t context) { - assert(g_thunks.Watch); - return g_thunks.Watch(watcher_handle, handle, signals, context); -} - -MojoResult MojoCancelWatch(MojoHandle watcher_handle, uintptr_t context) { - assert(g_thunks.CancelWatch); - return g_thunks.CancelWatch(watcher_handle, context); -} - -MojoResult MojoArmWatcher(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states) { - assert(g_thunks.ArmWatcher); - return g_thunks.ArmWatcher(watcher_handle, num_ready_contexts, ready_contexts, - ready_results, ready_signals_states); -} - -MojoResult MojoFuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { - assert(g_thunks.FuseMessagePipes); - return g_thunks.FuseMessagePipes(handle0, handle1); -} - -MojoResult MojoWriteMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags flags) { - assert(g_thunks.WriteMessageNew); - return g_thunks.WriteMessageNew(message_pipe_handle, message, flags); -} - -MojoResult MojoReadMessageNew(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) { - assert(g_thunks.ReadMessageNew); - return g_thunks.ReadMessageNew(message_pipe_handle, message, num_bytes, - handles, num_handles, flags); -} - -MojoResult MojoAllocMessage(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message) { - assert(g_thunks.AllocMessage); - return g_thunks.AllocMessage( - num_bytes, handles, num_handles, flags, message); -} - -MojoResult MojoFreeMessage(MojoMessageHandle message) { - assert(g_thunks.FreeMessage); - return g_thunks.FreeMessage(message); -} - -MojoResult MojoGetMessageBuffer(MojoMessageHandle message, void** buffer) { - assert(g_thunks.GetMessageBuffer); - return g_thunks.GetMessageBuffer(message, buffer); -} - -MojoResult MojoWrapPlatformHandle( - const struct MojoPlatformHandle* platform_handle, - MojoHandle* mojo_handle) { - assert(g_thunks.WrapPlatformHandle); - return g_thunks.WrapPlatformHandle(platform_handle, mojo_handle); -} - -MojoResult MojoUnwrapPlatformHandle( - MojoHandle mojo_handle, - struct MojoPlatformHandle* platform_handle) { - assert(g_thunks.UnwrapPlatformHandle); - return g_thunks.UnwrapPlatformHandle(mojo_handle, platform_handle); -} - -MojoResult MojoWrapPlatformSharedBufferHandle( - const struct MojoPlatformHandle* platform_handle, - size_t num_bytes, - MojoPlatformSharedBufferHandleFlags flags, - MojoHandle* mojo_handle) { - assert(g_thunks.WrapPlatformSharedBufferHandle); - return g_thunks.WrapPlatformSharedBufferHandle(platform_handle, num_bytes, - flags, mojo_handle); -} - -MojoResult MojoUnwrapPlatformSharedBufferHandle( - MojoHandle mojo_handle, - struct MojoPlatformHandle* platform_handle, - size_t* num_bytes, - MojoPlatformSharedBufferHandleFlags* flags) { - assert(g_thunks.UnwrapPlatformSharedBufferHandle); - return g_thunks.UnwrapPlatformSharedBufferHandle(mojo_handle, platform_handle, - num_bytes, flags); -} - -MojoResult MojoNotifyBadMessage(MojoMessageHandle message, - const char* error, - size_t error_num_bytes) { - assert(g_thunks.NotifyBadMessage); - return g_thunks.NotifyBadMessage(message, error, error_num_bytes); -} - -MojoResult MojoGetProperty(MojoPropertyType type, void* value) { - assert(g_thunks.GetProperty); - return g_thunks.GetProperty(type, value); -} - -} // extern "C" - -size_t MojoEmbedderSetSystemThunks(const MojoSystemThunks* system_thunks) { - if (system_thunks->size >= sizeof(g_thunks)) - g_thunks = *system_thunks; - return sizeof(g_thunks); -} diff --git a/mojo/public/c/system/thunks.h b/mojo/public/c/system/thunks.h deleted file mode 100644 index e61bb46..0000000 --- a/mojo/public/c/system/thunks.h +++ /dev/null @@ -1,148 +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. - -// Note: This header should be compilable as C. - -#ifndef MOJO_PUBLIC_C_SYSTEM_THUNKS_H_ -#define MOJO_PUBLIC_C_SYSTEM_THUNKS_H_ - -#include -#include - -#include "mojo/public/c/system/core.h" -#include "mojo/public/c/system/system_export.h" - -// Structure used to bind the basic Mojo Core functions to an embedder -// implementation. This is intended to eventually be used as a stable ABI -// between a Mojo embedder and some loaded application code, but for now it is -// still effectively safe to rearrange entries as needed. -#pragma pack(push, 8) -struct MojoSystemThunks { - size_t size; // Should be set to sizeof(MojoSystemThunks). - MojoTimeTicks (*GetTimeTicksNow)(); - MojoResult (*Close)(MojoHandle handle); - MojoResult (*QueryHandleSignalsState)( - MojoHandle handle, - struct MojoHandleSignalsState* signals_state); - MojoResult (*CreateMessagePipe)( - const struct MojoCreateMessagePipeOptions* options, - MojoHandle* message_pipe_handle0, - MojoHandle* message_pipe_handle1); - MojoResult (*WriteMessage)(MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags); - MojoResult (*ReadMessage)(MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags); - MojoResult (*CreateDataPipe)(const struct MojoCreateDataPipeOptions* options, - MojoHandle* data_pipe_producer_handle, - MojoHandle* data_pipe_consumer_handle); - MojoResult (*WriteData)(MojoHandle data_pipe_producer_handle, - const void* elements, - uint32_t* num_elements, - MojoWriteDataFlags flags); - MojoResult (*BeginWriteData)(MojoHandle data_pipe_producer_handle, - void** buffer, - uint32_t* buffer_num_elements, - MojoWriteDataFlags flags); - MojoResult (*EndWriteData)(MojoHandle data_pipe_producer_handle, - uint32_t num_elements_written); - MojoResult (*ReadData)(MojoHandle data_pipe_consumer_handle, - void* elements, - uint32_t* num_elements, - MojoReadDataFlags flags); - MojoResult (*BeginReadData)(MojoHandle data_pipe_consumer_handle, - const void** buffer, - uint32_t* buffer_num_elements, - MojoReadDataFlags flags); - MojoResult (*EndReadData)(MojoHandle data_pipe_consumer_handle, - uint32_t num_elements_read); - MojoResult (*CreateSharedBuffer)( - const struct MojoCreateSharedBufferOptions* options, - uint64_t num_bytes, - MojoHandle* shared_buffer_handle); - MojoResult (*DuplicateBufferHandle)( - MojoHandle buffer_handle, - const struct MojoDuplicateBufferHandleOptions* options, - MojoHandle* new_buffer_handle); - MojoResult (*MapBuffer)(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - void** buffer, - MojoMapBufferFlags flags); - MojoResult (*UnmapBuffer)(void* buffer); - MojoResult (*CreateWatcher)(MojoWatcherCallback callback, - MojoHandle* watcher_handle); - MojoResult (*Watch)(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - uintptr_t context); - MojoResult (*CancelWatch)(MojoHandle watcher_handle, uintptr_t context); - MojoResult (*ArmWatcher)(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - MojoHandleSignalsState* ready_signals_states); - MojoResult (*FuseMessagePipes)(MojoHandle handle0, MojoHandle handle1); - MojoResult (*WriteMessageNew)(MojoHandle message_pipe_handle, - MojoMessageHandle message, - MojoWriteMessageFlags flags); - MojoResult (*ReadMessageNew)(MojoHandle message_pipe_handle, - MojoMessageHandle* message, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags); - MojoResult (*AllocMessage)(uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoAllocMessageFlags flags, - MojoMessageHandle* message); - MojoResult (*FreeMessage)(MojoMessageHandle message); - MojoResult (*GetMessageBuffer)(MojoMessageHandle message, void** buffer); - MojoResult (*WrapPlatformHandle)( - const struct MojoPlatformHandle* platform_handle, - MojoHandle* mojo_handle); - MojoResult (*UnwrapPlatformHandle)( - MojoHandle mojo_handle, - struct MojoPlatformHandle* platform_handle); - MojoResult (*WrapPlatformSharedBufferHandle)( - const struct MojoPlatformHandle* platform_handle, - size_t num_bytes, - MojoPlatformSharedBufferHandleFlags flags, - MojoHandle* mojo_handle); - MojoResult (*UnwrapPlatformSharedBufferHandle)( - MojoHandle mojo_handle, - struct MojoPlatformHandle* platform_handle, - size_t* num_bytes, - MojoPlatformSharedBufferHandleFlags* flags); - MojoResult (*NotifyBadMessage)(MojoMessageHandle message, - const char* error, - size_t error_num_bytes); - MojoResult (*GetProperty)(MojoPropertyType type, void* value); -}; -#pragma pack(pop) - -// Use this type for the function found by dynamically discovering it in -// a DSO linked with mojo_system. For example: -// MojoSetSystemThunksFn mojo_set_system_thunks_fn = -// reinterpret_cast(app_library.GetFunctionPointer( -// "MojoSetSystemThunks")); -// The expected size of |system_thunks| is returned. -// The contents of |system_thunks| are copied. -typedef size_t (*MojoSetSystemThunksFn)( - const struct MojoSystemThunks* system_thunks); - -// A function for setting up the embedder's own system thunks. This should only -// be called by Mojo embedder code. -MOJO_SYSTEM_EXPORT size_t MojoEmbedderSetSystemThunks( - const struct MojoSystemThunks* system_thunks); - -#endif // MOJO_PUBLIC_C_SYSTEM_THUNKS_H_ diff --git a/mojo/public/c/system/types.h b/mojo/public/c/system/types.h deleted file mode 100644 index 15813b6..0000000 --- a/mojo/public/c/system/types.h +++ /dev/null @@ -1,223 +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. - -// This file contains types and constants/macros common to different Mojo system -// APIs. -// -// Note: This header should be compilable as C. - -#ifndef MOJO_PUBLIC_C_SYSTEM_TYPES_H_ -#define MOJO_PUBLIC_C_SYSTEM_TYPES_H_ - -#include - -#include "mojo/public/c/system/macros.h" - -// |MojoTimeTicks|: A time delta, in microseconds, the meaning of which is -// source-dependent. - -typedef int64_t MojoTimeTicks; - -// |MojoHandle|: Handles to Mojo objects. -// |MOJO_HANDLE_INVALID| - A value that is never a valid handle. - -typedef uint32_t MojoHandle; - -#ifdef __cplusplus -const MojoHandle MOJO_HANDLE_INVALID = 0; -#else -#define MOJO_HANDLE_INVALID ((MojoHandle)0) -#endif - -// |MojoResult|: Result codes for Mojo operations. The only success code is zero -// (|MOJO_RESULT_OK|); all non-zero values should be considered as error/failure -// codes (even if the value is not recognized). -// |MOJO_RESULT_OK| - Not an error; returned on success. -// |MOJO_RESULT_CANCELLED| - Operation was cancelled, typically by the caller. -// |MOJO_RESULT_UNKNOWN| - Unknown error (e.g., if not enough information is -// available for a more specific error). -// |MOJO_RESULT_INVALID_ARGUMENT| - Caller specified an invalid argument. This -// differs from |MOJO_RESULT_FAILED_PRECONDITION| in that the former -// indicates arguments that are invalid regardless of the state of the -// system. -// |MOJO_RESULT_DEADLINE_EXCEEDED| - Deadline expired before the operation -// could complete. -// |MOJO_RESULT_NOT_FOUND| - Some requested entity was not found (i.e., does -// not exist). -// |MOJO_RESULT_ALREADY_EXISTS| - Some entity or condition that we attempted -// to create already exists. -// |MOJO_RESULT_PERMISSION_DENIED| - The caller does not have permission to -// for the operation (use |MOJO_RESULT_RESOURCE_EXHAUSTED| for rejections -// caused by exhausting some resource instead). -// |MOJO_RESULT_RESOURCE_EXHAUSTED| - Some resource required for the call -// (possibly some quota) has been exhausted. -// |MOJO_RESULT_FAILED_PRECONDITION| - The system is not in a state required -// for the operation (use this if the caller must do something to rectify -// the state before retrying). -// |MOJO_RESULT_ABORTED| - The operation was aborted by the system, possibly -// due to a concurrency issue (use this if the caller may retry at a -// higher level). -// |MOJO_RESULT_OUT_OF_RANGE| - The operation was attempted past the valid -// range. Unlike |MOJO_RESULT_INVALID_ARGUMENT|, this indicates that the -// operation may be/become valid depending on the system state. (This -// error is similar to |MOJO_RESULT_FAILED_PRECONDITION|, but is more -// specific.) -// |MOJO_RESULT_UNIMPLEMENTED| - The operation is not implemented, supported, -// or enabled. -// |MOJO_RESULT_INTERNAL| - Internal error: this should never happen and -// indicates that some invariant expected by the system has been broken. -// |MOJO_RESULT_UNAVAILABLE| - The operation is (temporarily) currently -// unavailable. The caller may simply retry the operation (possibly with a -// backoff). -// |MOJO_RESULT_DATA_LOSS| - Unrecoverable data loss or corruption. -// |MOJO_RESULT_BUSY| - One of the resources involved is currently being used -// (possibly on another thread) in a way that prevents the current -// operation from proceeding, e.g., if the other operation may result in -// the resource being invalidated. -// |MOJO_RESULT_SHOULD_WAIT| - The request cannot currently be completed -// (e.g., if the data requested is not yet available). The caller should -// wait for it to be feasible using a watcher. -// -// The codes from |MOJO_RESULT_OK| to |MOJO_RESULT_DATA_LOSS| come from -// Google3's canonical error codes. - -typedef uint32_t MojoResult; - -#ifdef __cplusplus -const MojoResult MOJO_RESULT_OK = 0; -const MojoResult MOJO_RESULT_CANCELLED = 1; -const MojoResult MOJO_RESULT_UNKNOWN = 2; -const MojoResult MOJO_RESULT_INVALID_ARGUMENT = 3; -const MojoResult MOJO_RESULT_DEADLINE_EXCEEDED = 4; -const MojoResult MOJO_RESULT_NOT_FOUND = 5; -const MojoResult MOJO_RESULT_ALREADY_EXISTS = 6; -const MojoResult MOJO_RESULT_PERMISSION_DENIED = 7; -const MojoResult MOJO_RESULT_RESOURCE_EXHAUSTED = 8; -const MojoResult MOJO_RESULT_FAILED_PRECONDITION = 9; -const MojoResult MOJO_RESULT_ABORTED = 10; -const MojoResult MOJO_RESULT_OUT_OF_RANGE = 11; -const MojoResult MOJO_RESULT_UNIMPLEMENTED = 12; -const MojoResult MOJO_RESULT_INTERNAL = 13; -const MojoResult MOJO_RESULT_UNAVAILABLE = 14; -const MojoResult MOJO_RESULT_DATA_LOSS = 15; -const MojoResult MOJO_RESULT_BUSY = 16; -const MojoResult MOJO_RESULT_SHOULD_WAIT = 17; -#else -#define MOJO_RESULT_OK ((MojoResult)0) -#define MOJO_RESULT_CANCELLED ((MojoResult)1) -#define MOJO_RESULT_UNKNOWN ((MojoResult)2) -#define MOJO_RESULT_INVALID_ARGUMENT ((MojoResult)3) -#define MOJO_RESULT_DEADLINE_EXCEEDED ((MojoResult)4) -#define MOJO_RESULT_NOT_FOUND ((MojoResult)5) -#define MOJO_RESULT_ALREADY_EXISTS ((MojoResult)6) -#define MOJO_RESULT_PERMISSION_DENIED ((MojoResult)7) -#define MOJO_RESULT_RESOURCE_EXHAUSTED ((MojoResult)8) -#define MOJO_RESULT_FAILED_PRECONDITION ((MojoResult)9) -#define MOJO_RESULT_ABORTED ((MojoResult)10) -#define MOJO_RESULT_OUT_OF_RANGE ((MojoResult)11) -#define MOJO_RESULT_UNIMPLEMENTED ((MojoResult)12) -#define MOJO_RESULT_INTERNAL ((MojoResult)13) -#define MOJO_RESULT_UNAVAILABLE ((MojoResult)14) -#define MOJO_RESULT_DATA_LOSS ((MojoResult)15) -#define MOJO_RESULT_BUSY ((MojoResult)16) -#define MOJO_RESULT_SHOULD_WAIT ((MojoResult)17) -#endif - -// |MojoDeadline|: Used to specify deadlines (timeouts), in microseconds (except -// for |MOJO_DEADLINE_INDEFINITE|). -// |MOJO_DEADLINE_INDEFINITE| - Used to indicate "forever". - -typedef uint64_t MojoDeadline; - -#ifdef __cplusplus -const MojoDeadline MOJO_DEADLINE_INDEFINITE = static_cast(-1); -#else -#define MOJO_DEADLINE_INDEFINITE ((MojoDeadline) - 1) -#endif - -// |MojoHandleSignals|: Used to specify signals that can be watched for on a -// handle (and which can be triggered), e.g., the ability to read or write to -// the handle. -// |MOJO_HANDLE_SIGNAL_NONE| - No flags. A registered watch will always fail -// to arm with |MOJO_RESULT_FAILED_PRECONDITION| when watching for this. -// |MOJO_HANDLE_SIGNAL_READABLE| - Can read (e.g., a message) from the handle. -// |MOJO_HANDLE_SIGNAL_WRITABLE| - Can write (e.g., a message) to the handle. -// |MOJO_HANDLE_SIGNAL_PEER_CLOSED| - The peer handle is closed. -// |MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE| - Can read data from a data pipe -// consumer handle (implying MOJO_HANDLE_SIGNAL_READABLE is also set), -// AND there is some nonzero quantity of new data available on the pipe -// since the last |MojoReadData()| or |MojoBeginReadData()| call on the -// handle. - -typedef uint32_t MojoHandleSignals; - -#ifdef __cplusplus -const MojoHandleSignals MOJO_HANDLE_SIGNAL_NONE = 0; -const MojoHandleSignals MOJO_HANDLE_SIGNAL_READABLE = 1 << 0; -const MojoHandleSignals MOJO_HANDLE_SIGNAL_WRITABLE = 1 << 1; -const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_CLOSED = 1 << 2; -const MojoHandleSignals MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE = 1 << 3; -#else -#define MOJO_HANDLE_SIGNAL_NONE ((MojoHandleSignals)0) -#define MOJO_HANDLE_SIGNAL_READABLE ((MojoHandleSignals)1 << 0) -#define MOJO_HANDLE_SIGNAL_WRITABLE ((MojoHandleSignals)1 << 1) -#define MOJO_HANDLE_SIGNAL_PEER_CLOSED ((MojoHandleSignals)1 << 2) -#define MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE ((MojoHandleSignals)1 << 3); -#endif - -// |MojoHandleSignalsState|: Returned by watch notification callbacks and -// |MojoQueryHandleSignalsState| functions to indicate the signaling state of -// handles. Members are as follows: -// - |satisfied signals|: Bitmask of signals that were satisfied at some time -// before the call returned. -// - |satisfiable signals|: These are the signals that are possible to -// satisfy. For example, if the return value was -// |MOJO_RESULT_FAILED_PRECONDITION|, you can use this field to -// determine which, if any, of the signals can still be satisfied. -// Note: This struct is not extensible (and only has 32-bit quantities), so it's -// 32-bit-aligned. -MOJO_STATIC_ASSERT(MOJO_ALIGNOF(int32_t) == 4, "int32_t has weird alignment"); -struct MOJO_ALIGNAS(4) MojoHandleSignalsState { - MojoHandleSignals satisfied_signals; - MojoHandleSignals satisfiable_signals; -}; -MOJO_STATIC_ASSERT(sizeof(MojoHandleSignalsState) == 8, - "MojoHandleSignalsState has wrong size"); - -// |MojoWatcherNotificationFlags|: Passed to a callback invoked by a watcher -// when some observed signals are raised or a watched handle is closed. May take -// on any combination of the following values: -// -// |MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM| - The callback is being -// invoked as a result of a system-level event rather than a direct API -// call from user code. This may be used as an indication that user code -// is safe to call without fear of reentry. - -typedef uint32_t MojoWatcherNotificationFlags; - -#ifdef __cplusplus -const MojoWatcherNotificationFlags MOJO_WATCHER_NOTIFICATION_FLAG_NONE = 0; -const MojoWatcherNotificationFlags MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM = - 1 << 0; -#else -#define MOJO_WATCHER_NOTIFICATION_FLAG_NONE ((MojoWatcherNotificationFlags)0) -#define MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM \ - ((MojoWatcherNotificationFlags)1 << 0); -#endif - -// |MojoPropertyType|: Property types that can be passed to |MojoGetProperty()| -// to retrieve system properties. May take the following values: -// |MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED| - Whether making synchronous calls -// (i.e., blocking to wait for a response to an outbound message) is -// allowed. The property value is of boolean type. If the value is true, -// users should refrain from making sync calls. -typedef uint32_t MojoPropertyType; - -#ifdef __cplusplus -const MojoPropertyType MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED = 0; -#else -#define MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED ((MojoPropertyType)0) -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_TYPES_H_ diff --git a/mojo/public/c/system/watcher.h b/mojo/public/c/system/watcher.h deleted file mode 100644 index e32856b..0000000 --- a/mojo/public/c/system/watcher.h +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_C_SYSTEM_WATCHER_H_ -#define MOJO_PUBLIC_C_SYSTEM_WATCHER_H_ - -#include - -#include "mojo/public/c/system/system_export.h" -#include "mojo/public/c/system/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// A callback used to notify watchers about events on their watched handles. -// -// See documentation for |MojoWatcherNotificationFlags| for details regarding -// the possible values of |flags|. -// -// See documentation for |MojoWatch()| for details regarding the other arguments -// this callback receives when called. -typedef void (*MojoWatcherCallback)(uintptr_t context, - MojoResult result, - struct MojoHandleSignalsState signals_state, - MojoWatcherNotificationFlags flags); - -// Creates a new watcher. -// -// Watchers are used to trigger arbitrary code execution when one or more -// handles change state to meet certain conditions. -// -// A newly registered watcher is initially disarmed and may be armed using -// |MojoArmWatcher()|. A watcher is also always disarmed immediately before any -// invocation of one or more notification callbacks in response to a single -// handle's state changing in some relevant way. -// -// Parameters: -// |callback|: The |MojoWatcherCallback| to invoke any time the watcher is -// notified of an event. See |MojoWatch()| for details regarding arguments -// passed to the callback. Note that this may be called from any arbitrary -// thread. -// |watcher_handle|: The address at which to store the MojoHandle -// corresponding to the new watcher if successfully created. -// -// Returns: -// |MOJO_RESULT_OK| if the watcher has been successfully created. -// |MOJO_RESULT_RESOURCE_EXHAUSTED| if a handle could not be allocated for -// this watcher. -MOJO_SYSTEM_EXPORT MojoResult MojoCreateWatcher(MojoWatcherCallback callback, - MojoHandle* watcher_handle); - -// Adds a watch to a watcher. This allows the watcher to fire notifications -// regarding state changes on the handle corresponding to the arguments given. -// -// Note that notifications for a given watch context are guaranteed to be -// mutually exclusive in execution: the callback will never be entered for a -// given context while another invocation of the callback is still executing for -// the same context. As a result it is generally a good idea to ensure that -// callbacks do as little work as necessary in order to process the -// notification. -// -// Parameters: -// |watcher_handle|: The watcher to which |handle| is to be added. -// |handle|: The handle to add to the watcher. -// |signals|: The signals to watch for on |handle|. -// |context|: An arbitrary context value given to any invocation of the -// watcher's callback when invoked as a result of some state change -// relevant to this combination of |handle| and |signals|. Must be -// unique within any given watcher. -// -// Callback parameters (see |MojoWatcherNotificationCallback| above): -// When the watcher invokes its callback as a result of some notification -// relevant to this watch operation, |context| receives the value given here -// and |signals_state| receives the last known signals state of this handle. -// -// |result| is one of the following: -// |MOJO_RESULT_OK| if at least one of the watched signals is satisfied. The -// watcher must be armed for this notification to fire. -// |MOJO_RESULT_FAILED_PRECONDITION| if all of the watched signals are -// permanently unsatisfiable. The watcher must be armed for this -// notification to fire. -// |MOJO_RESULT_CANCELLED| if the watch has been cancelled. The may occur if -// the watcher has been closed, the watched handle has been closed, or -// the watch for |context| has been explicitly cancelled. This is always -// the last result received for any given context, and it is guaranteed -// to be received exactly once per watch, regardless of how the watch -// was cancelled. -// -// Returns: -// |MOJO_RESULT_OK| if the handle is now being watched by the watcher. -// |MOJO_RESULT_INVALID_ARGUMENT| if |watcher_handle| is not a watcher handle, -// |handle| is not a valid message pipe or data pipe handle. -// |MOJO_RESULT_ALREADY_EXISTS| if the watcher already has a watch registered -// for the given value of |context| or for the given |handle|. -MOJO_SYSTEM_EXPORT MojoResult MojoWatch(MojoHandle watcher_handle, - MojoHandle handle, - MojoHandleSignals signals, - uintptr_t context); - -// Removes a watch from a watcher. -// -// This ensures that the watch is cancelled as soon as possible. Cancellation -// may be deferred (or may even block) an aritrarily long time if the watch is -// already dispatching one or more notifications. -// -// When cancellation is complete, the watcher's callback is invoked one final -// time for |context|, with the result |MOJO_RESULT_CANCELLED|. -// -// The same behavior can be elicted by either closing the watched handle -// associated with this context, or by closing |watcher_handle| itself. In the -// lastter case, all registered contexts on the watcher are implicitly cancelled -// in a similar fashion. -// -// Parameters: -// |watcher_handle|: The handle of the watcher from which to remove a watch. -// |context|: The context of the watch to be removed. -// -// Returns: -// |MOJO_RESULT_OK| if the watch has been cancelled. -// |MOJO_RESULT_INVALID_ARGUMENT| if |watcher_handle| is not a watcher handle. -// |MOJO_RESULT_NOT_FOUND| if there is no watch registered on this watcher for -// the given value of |context|. -MOJO_SYSTEM_EXPORT MojoResult MojoCancelWatch(MojoHandle watcher_handle, - uintptr_t context); - -// Arms a watcher, enabling a single future event on one of the watched handles -// to trigger a single notification for each relevant watch context associated -// with that handle. -// -// Parameters: -// |watcher_handle|: The handle of the watcher. -// |num_ready_contexts|: An address pointing to the number of elements -// available for storage in the remaining output buffers. Optional and -// only used on failure. See |MOJO_RESULT_FAILED_PRECONDITION| below for -// more details. -// |ready_contexts|: An output buffer for contexts corresponding to the -// watches which would have notified if the watcher were armed. Optional -// and only uesd on failure. See |MOJO_RESULT_FAILED_PRECONDITION| below -// for more details. -// |ready_results|: An output buffer for MojoResult values corresponding to -// each context in |ready_contexts|. Optional and only used on failure. -// See |MOJO_RESULT_FAILED_PRECONDITION| below for more details. -// |ready_signals_states|: An output buffer for |MojoHandleSignalsState| -// structures corresponding to each context in |ready_contexts|. Optional -// and only used on failure. See |MOJO_RESULT_FAILED_PRECONDITION| below -// for more details. -// -// Returns: -// |MOJO_RESULT_OK| if the watcher has been successfully armed. All arguments -// other than |watcher_handle| are ignored in this case. -// |MOJO_RESULT_NOT_FOUND| if the watcher does not have any registered watch -// contexts. All arguments other than |watcher_handle| are ignored in this -// case. -// |MOJO_RESULT_INVALID_ARGUMENT| if |watcher_handle| is not a valid watcher -// handle, or if |num_ready_contexts| is non-null but any of the output -// buffer paramters is null. -// |MOJO_RESULT_FAILED_PRECONDITION| if one or more watches would have -// notified immediately upon arming the watcher. If |num_handles| is -// non-null, this assumes there is enough space for |*num_handles| entries -// in each of the subsequent output buffer arguments. -// -// At most that many entries are placed in the output buffers, -// corresponding to the watches which would have signalled if the watcher -// had been armed successfully. The actual number of entries placed in the -// output buffers is written to |*num_ready_contexts| before returning. -// -// If more than (input) |*num_ready_contexts| watch contexts were ready to -// notify, the subset presented in output buffers is arbitrary, but the -// implementation makes a best effort to circulate the outputs across -// consecutive calls so that callers may reliably avoid handle starvation. -MOJO_SYSTEM_EXPORT MojoResult -MojoArmWatcher(MojoHandle watcher_handle, - uint32_t* num_ready_contexts, - uintptr_t* ready_contexts, - MojoResult* ready_results, - struct MojoHandleSignalsState* ready_signals_states); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // MOJO_PUBLIC_C_SYSTEM_WATCHER_H_ diff --git a/mojo/public/c/test_support/BUILD.gn b/mojo/public/c/test_support/BUILD.gn deleted file mode 100644 index e2abd58..0000000 --- a/mojo/public/c/test_support/BUILD.gn +++ /dev/null @@ -1,15 +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. - -static_library("test_support") { - output_name = "mojo_public_test_support" - - sources = [ - "test_support.h", - - # TODO(vtl): Convert this to thunks http://crbug.com/386799 - "../../tests/test_support_private.cc", - "../../tests/test_support_private.h", - ] -} diff --git a/mojo/public/c/test_support/test_support.h b/mojo/public/c/test_support/test_support.h deleted file mode 100644 index 8e50441..0000000 --- a/mojo/public/c/test_support/test_support.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_H_ -#define MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_H_ - -// Note: This header should be compilable as C. - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// |sub_test_name| is optional. If not null, it usually describes one particular -// configuration of the test. For example, if |test_name| is "TestPacketRate", -// |sub_test_name| could be "100BytesPerPacket". -// When the perf data is visualized by the performance dashboard, data with -// different |sub_test_name|s (but the same |test_name|) are depicted as -// different traces on the same chart. -void MojoTestSupportLogPerfResult( - const char* test_name, - const char* sub_test_name, - double value, - const char* units); - -// Opens a "/"-delimited file path relative to the source root. -FILE* MojoTestSupportOpenSourceRootRelativeFile( - const char* source_root_relative_path); - -// Enumerates a "/"-delimited directory path relative to the source root. -// Returns only regular files. The return value is a heap-allocated array of -// heap-allocated strings. Each must be free'd separately. -// -// The return value is built like so: -// -// char** rv = (char**) calloc(N + 1, sizeof(char*)); -// rv[0] = strdup("a"); -// rv[1] = strdup("b"); -// rv[2] = strdup("c"); -// ... -// rv[N] = NULL; -// -char** MojoTestSupportEnumerateSourceRootRelativeDirectory( - const char* source_root_relative_path); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // MOJO_PUBLIC_C_TEST_SUPPORT_TEST_SUPPORT_H_ diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn deleted file mode 100644 index bd87965..0000000 --- a/mojo/public/cpp/bindings/BUILD.gn +++ /dev/null @@ -1,194 +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. - -interfaces_bindings_gen_dir = "$root_gen_dir/mojo/public/interfaces/bindings" - -component("bindings") { - sources = [ - # Normally, targets should depend on the source_sets generated by mojom - # targets. However, the generated source_sets use portions of the bindings - # library. In order to avoid linker warnings about locally-defined imports - # in Windows components build, this target depends on the generated C++ - # files directly so that the EXPORT macro defintions match. - "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared-internal.h", - "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared.cc", - "$interfaces_bindings_gen_dir/interface_control_messages.mojom-shared.h", - "$interfaces_bindings_gen_dir/interface_control_messages.mojom.cc", - "$interfaces_bindings_gen_dir/interface_control_messages.mojom.h", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared-internal.h", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared.cc", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom-shared.h", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom.cc", - "$interfaces_bindings_gen_dir/pipe_control_messages.mojom.h", - "array_data_view.h", - "array_traits.h", - "array_traits_carray.h", - "array_traits_stl.h", - "associated_binding.h", - "associated_binding_set.h", - "associated_group.h", - "associated_group_controller.h", - "associated_interface_ptr.h", - "associated_interface_ptr_info.h", - "associated_interface_request.h", - "binding.h", - "binding_set.h", - "bindings_export.h", - "clone_traits.h", - "connection_error_callback.h", - "connector.h", - "disconnect_reason.h", - "filter_chain.h", - "interface_data_view.h", - "interface_endpoint_client.h", - "interface_endpoint_controller.h", - "interface_id.h", - "interface_ptr.h", - "interface_ptr_info.h", - "interface_ptr_set.h", - "interface_request.h", - "lib/array_internal.cc", - "lib/array_internal.h", - "lib/array_serialization.h", - "lib/associated_binding.cc", - "lib/associated_group.cc", - "lib/associated_group_controller.cc", - "lib/associated_interface_ptr.cc", - "lib/associated_interface_ptr_state.h", - "lib/binding_state.cc", - "lib/binding_state.h", - "lib/bindings_internal.h", - "lib/buffer.h", - "lib/connector.cc", - "lib/control_message_handler.cc", - "lib/control_message_handler.h", - "lib/control_message_proxy.cc", - "lib/control_message_proxy.h", - "lib/equals_traits.h", - "lib/filter_chain.cc", - "lib/fixed_buffer.cc", - "lib/fixed_buffer.h", - "lib/handle_interface_serialization.h", - "lib/hash_util.h", - "lib/interface_endpoint_client.cc", - "lib/interface_ptr_state.h", - "lib/map_data_internal.h", - "lib/map_serialization.h", - "lib/may_auto_lock.h", - "lib/message.cc", - "lib/message_buffer.cc", - "lib/message_buffer.h", - "lib/message_builder.cc", - "lib/message_builder.h", - "lib/message_header_validator.cc", - "lib/message_internal.h", - "lib/multiplex_router.cc", - "lib/multiplex_router.h", - "lib/native_enum_data.h", - "lib/native_enum_serialization.h", - "lib/native_struct.cc", - "lib/native_struct_data.cc", - "lib/native_struct_data.h", - "lib/native_struct_serialization.cc", - "lib/native_struct_serialization.h", - "lib/pipe_control_message_handler.cc", - "lib/pipe_control_message_proxy.cc", - "lib/scoped_interface_endpoint_handle.cc", - "lib/serialization.h", - "lib/serialization_context.cc", - "lib/serialization_context.h", - "lib/serialization_forward.h", - "lib/serialization_util.h", - "lib/string_serialization.h", - "lib/string_traits_string16.cc", - "lib/sync_call_restrictions.cc", - "lib/sync_event_watcher.cc", - "lib/sync_handle_registry.cc", - "lib/sync_handle_watcher.cc", - "lib/template_util.h", - "lib/union_accessor.h", - "lib/validate_params.h", - "lib/validation_context.cc", - "lib/validation_context.h", - "lib/validation_errors.cc", - "lib/validation_errors.h", - "lib/validation_util.cc", - "lib/validation_util.h", - "map.h", - "map_data_view.h", - "map_traits.h", - "map_traits_stl.h", - "message.h", - "message_header_validator.h", - "native_enum.h", - "native_struct.h", - "native_struct_data_view.h", - "pipe_control_message_handler.h", - "pipe_control_message_handler_delegate.h", - "pipe_control_message_proxy.h", - "raw_ptr_impl_ref_traits.h", - "scoped_interface_endpoint_handle.h", - "string_data_view.h", - "string_traits.h", - "string_traits_stl.h", - "string_traits_string16.h", - "string_traits_string_piece.h", - "strong_associated_binding.h", - "strong_binding.h", - "strong_binding_set.h", - "struct_ptr.h", - "sync_call_restrictions.h", - "sync_event_watcher.h", - "sync_handle_registry.h", - "sync_handle_watcher.h", - "thread_safe_interface_ptr.h", - "type_converter.h", - "union_traits.h", - "unique_ptr_impl_ref_traits.h", - ] - - public_deps = [ - ":struct_traits", - "//base", - "//ipc:param_traits", - "//mojo/public/cpp/system", - ] - - deps = [ - "//base", - "//mojo/public/interfaces/bindings:bindings__generator", - "//mojo/public/interfaces/bindings:bindings_shared__generator", - ] - - defines = [ "MOJO_CPP_BINDINGS_IMPLEMENTATION" ] -} - -source_set("struct_traits") { - sources = [ - "enum_traits.h", - "struct_traits.h", - ] -} - -if (!is_ios) { - # TODO(yzshen): crbug.com/617718 Consider moving this into blink. - source_set("wtf_support") { - sources = [ - "array_traits_wtf_vector.h", - "lib/string_traits_wtf.cc", - "lib/wtf_clone_equals_util.h", - "lib/wtf_hash_util.h", - "lib/wtf_serialization.h", - "map_traits_wtf_hash_map.h", - "string_traits_wtf.h", - ] - - public_deps = [ - ":bindings", - "//third_party/WebKit/Source/wtf", - ] - - public_configs = [ "//third_party/WebKit/Source:config" ] - } -} diff --git a/mojo/public/cpp/bindings/DEPS b/mojo/public/cpp/bindings/DEPS deleted file mode 100644 index 36eba44..0000000 --- a/mojo/public/cpp/bindings/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+third_party/WebKit/Source/wtf", -] diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md deleted file mode 100644 index b37267a..0000000 --- a/mojo/public/cpp/bindings/README.md +++ /dev/null @@ -1,1231 +0,0 @@ -# ![Mojo Graphic](https://goo.gl/6CdlbH) Mojo C++ Bindings API -This document is a subset of the [Mojo documentation](/mojo). - -[TOC] - -## Overview -The Mojo C++ Bindings API leverages the -[C++ System API](/mojo/public/cpp/system) to provide a more natural set of -primitives for communicating over Mojo message pipes. Combined with generated -code from the [Mojom IDL and bindings generator](/mojo/public/tools/bindings), -users can easily connect interface clients and implementations across arbitrary -intra- and inter-process bounaries. - -This document provides a detailed guide to bindings API usage with example code -snippets. For a detailed API references please consult the headers in -[//mojo/public/cpp/bindings](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/). - -## Getting Started - -When a Mojom IDL file is processed by the bindings generator, C++ code is -emitted in a series of `.h` and `.cc` files with names based on the input -`.mojom` file. Suppose we create the following Mojom file at -`//services/db/public/interfaces/db.mojom`: - -``` -module db.mojom; - -interface Table { - AddRow(int32 key, string data); -}; - -interface Database { - CreateTable(Table& table); -}; -``` - -And a GN target to generate the bindings in -`//services/db/public/interfaces/BUILD.gn`: - -``` -import("//mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "db.mojom", - ] -} -``` - -If we then build this target: - -``` -ninja -C out/r services/db/public/interfaces -``` - -This will produce several generated source files, some of which are relevant to -C++ bindings. Two of these files are: - -``` -out/gen/services/business/public/interfaces/factory.mojom.cc -out/gen/services/business/public/interfaces/factory.mojom.h -``` - -You can include the above generated header in your sources in order to use the -definitions therein: - -``` cpp -#include "services/business/public/interfaces/factory.mojom.h" - -class TableImpl : public db::mojom::Table { - // ... -}; -``` - -This document covers the different kinds of definitions generated by Mojom IDL -for C++ consumers and how they can effectively be used to communicate across -message pipes. - -*** note -**NOTE:** Using C++ bindings from within Blink code is typically subject to -special constraints which require the use of a different generated header. -For details, see [Blink Type Mapping](#Blink-Type-Mapping). -*** - -## Interfaces - -Mojom IDL interfaces are translated to corresponding C++ (pure virtual) class -interface definitions in the generated header, consisting of a single generated -method signature for each request message on the interface. Internally there is -also generated code for serialization and deserialization of messages, but this -detail is hidden from bindings consumers. - -### Basic Usage - -Let's consider a new `//sample/logger.mojom` to define a simple logging -interface which clients can use to log simple string messages: - -``` cpp -module sample.mojom; - -interface Logger { - Log(string message); -}; -``` - -Running this through the bindings generator will produce a `logging.mojom.h` -with the following definitions (modulo unimportant details): - -``` cpp -namespace sample { -namespace mojom { - -class Logger { - virtual ~Logger() {} - - virtual void Log(const std::string& message) = 0; -}; - -using LoggerPtr = mojo::InterfacePtr; -using LoggerRequest = mojo::InterfaceRequest; - -} // namespace mojom -} // namespace sample -``` - -Makes sense. Let's take a closer look at those type aliases at the end. - -### InterfacePtr and InterfaceRequest - -You will notice the type aliases for `LoggerPtr` and -`LoggerRequest` are using two of the most fundamental template types in the C++ -bindings library: **`InterfacePtr`** and **`InterfaceRequest`**. - -In the world of Mojo bindings libraries these are effectively strongly-typed -message pipe endpoints. If an `InterfacePtr` is bound to a message pipe -endpoint, it can be dereferenced to make calls on an opaque `T` interface. These -calls immediately serialize their arguments (using generated code) and write a -corresponding message to the pipe. - -An `InterfaceRequest` is essentially just a typed container to hold the other -end of an `InterfacePtr`'s pipe -- the receiving end -- until it can be -routed to some implementation which will **bind** it. The `InterfaceRequest` -doesn't actually *do* anything other than hold onto a pipe endpoint and carry -useful compile-time type information. - -![Diagram illustrating InterfacePtr and InterfaceRequest on either end of a message pipe](https://docs.google.com/drawings/d/17d5gvErbQ6DthEBMS7I1WhCh9bz0n12pvNjydzuRfTI/pub?w=600&h=100) - -So how do we create a strongly-typed message pipe? - -### Creating Interface Pipes - -One way to do this is by manually creating a pipe and binding each end: - -``` cpp -#include "sample/logger.mojom.h" - -mojo::MessagePipe pipe; -sample::mojom::LoggerPtr logger; -sample::mojom::LoggerRequest request; - -logger.Bind(sample::mojom::LoggerPtrInfo(std::move(pipe.handle0), 0u)); -request.Bind(std::move(pipe.handle1)); -``` - -That's pretty verbose, but the C++ Bindings library provides more convenient -ways to accomplish the same thing. [interface_request.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/interface_request.h) -defines a `MakeRequest` function: - -``` cpp -sample::mojom::LoggerPtr logger; -sample::mojom::LoggerRequest request = mojo::MakeRequest(&logger); -``` - -and the `InterfaceRequest` constructor can also take an explicit -`InterfacePtr*` output argument: - -``` cpp -sample::mojom::LoggerPtr logger; -sample::mojom::LoggerRequest request(&logger); -``` - -Both of these last two snippets are equivalent to the first one. - -*** note -**NOTE:** In the first example above you may notice usage of the `LoggerPtrInfo` -type, which is a generated alias for `mojo::InterfacePtrInfo`. This is -similar to an `InterfaceRequest` in that it merely holds onto a pipe handle -and cannot actually read or write messages on the pipe. Both this type and -`InterfaceRequest` are safe to move freely from thread to thread, whereas a -bound `InterfacePtr` is bound to a single thread. - -An `InterfacePtr` may be unbound by calling its `PassInterface()` method, -which returns a new `InterfacePtrInfo`. Conversely, an `InterfacePtr` may -bind (and thus take ownership of) an `InterfacePtrInfo` so that interface -calls can be made on the pipe. - -The thread-bound nature of `InterfacePtr` is necessary to support safe -dispatch of its [message responses](#Receiving-Responses) and -[connection error notifications](#Connection-Errors). -*** - -Once the `LoggerPtr` is bound we can immediately begin calling `Logger` -interface methods on it, which will immediately write messages into the pipe. -These messages will stay queued on the receiving end of the pipe until someone -binds to it and starts reading them. - -``` cpp -logger->Log("Hello!"); -``` - -This actually writes a `Log` message to the pipe. - -![Diagram illustrating a message traveling on a pipe from LoggerPtr to LoggerRequest](https://docs.google.com/a/google.com/drawings/d/1jWEc6jJIP2ed77Gg4JJ3EVC7hvnwcImNqQJywFwpT8g/pub?w=648&h=123) - -But as mentioned above, `InterfaceRequest` *doesn't actually do anything*, so -that message will just sit on the pipe forever. We need a way to read messages -off the other end of the pipe and dispatch them. We have to -**bind the interface request**. - -### Binding an Interface Request - -There are many different helper classes in the bindings library for binding the -receiving end of a message pipe. The most primitive among them is the aptly -named `mojo::Binding`. A `mojo::Binding` bridges an implementation of `T` -with a single bound message pipe endpoint (via a `mojo::InterfaceRequest`), -which it continuously watches for readability. - -Any time the bound pipe becomes readable, the `Binding` will schedule a task to -read, deserialize (using generated code), and dispatch all available messages to -the bound `T` implementation. Below is a sample implementation of the `Logger` -interface. Notice that the implementation itself owns a `mojo::Binding`. This is -a common pattern, since a bound implementation must outlive any `mojo::Binding` -which binds it. - -``` cpp -#include "base/logging.h" -#include "base/macros.h" -#include "sample/logger.mojom.h" - -class LoggerImpl : public sample::mojom::Logger { - public: - // NOTE: A common pattern for interface implementations which have one - // instance per client is to take an InterfaceRequest in the constructor. - - explicit LoggerImpl(sample::mojom::LoggerRequest request) - : binding_(this, std::move(request)) {} - ~Logger() override {} - - // sample::mojom::Logger: - void Log(const std::string& message) override { - LOG(ERROR) << "[Logger] " << message; - } - - private: - mojo::Binding binding_; - - DISALLOW_COPY_AND_ASSIGN(LoggerImpl); -}; -``` - -Now we can construct a `LoggerImpl` over our pending `LoggerRequest`, and the -previously queued `Log` message will be dispatched ASAP on the `LoggerImpl`'s -thread: - -``` cpp -LoggerImpl impl(std::move(request)); -``` - -The diagram below illustrates the following sequence of events, all set in -motion by the above line of code: - -1. The `LoggerImpl` constructor is called, passing the `LoggerRequest` along - to the `Binding`. -2. The `Binding` takes ownership of the `LoggerRequest`'s pipe endpoint and - begins watching it for readability. The pipe is readable immediately, so a - task is scheduled to read the pending `Log` message from the pipe ASAP. -3. The `Log` message is read and deserialized, causing the `Binding` to invoke - the `Logger::Log` implementation on its bound `LoggerImpl`. - -![Diagram illustrating the progression of binding a request, reading a pending message, and dispatching it](https://docs.google.com/drawings/d/1c73-PegT4lmjfHoxhWrHTQXRvzxgb0wdeBa35WBwZ3Q/pub?w=550&h=500) - -As a result, our implementation will eventually log the client's `"Hello!"` -message via `LOG(ERROR)`. - -*** note -**NOTE:** Messages will only be read and dispatched from a pipe as long as the -object which binds it (*i.e.* the `mojo::Binding` in the above example) remains -alive. -*** - -### Receiving Responses - -Some Mojom interface methods expect a response. Suppose we modify our `Logger` -interface so that the last logged line can be queried like so: - -``` cpp -module sample.mojom; - -interface Logger { - Log(string message); - GetTail() => (string message); -}; -``` - -The generated C++ interface will now look like: - -``` cpp -namespace sample { -namespace mojom { - -class Logger { - public: - virtual ~Logger() {} - - virtual void Log(const std::string& message) = 0; - - using GetTailCallback = base::Callback; - - virtual void GetTail(const GetTailCallback& callback) = 0; -} - -} // namespace mojom -} // namespace sample -``` - -As before, both clients and implementations of this interface use the same -signature for the `GetTail` method: implementations use the `callback` argument -to *respond* to the request, while clients pass a `callback` argument to -asynchronously `receive` the response. Here's an updated implementation: - -```cpp -class LoggerImpl : public sample::mojom::Logger { - public: - // NOTE: A common pattern for interface implementations which have one - // instance per client is to take an InterfaceRequest in the constructor. - - explicit LoggerImpl(sample::mojom::LoggerRequest request) - : binding_(this, std::move(request)) {} - ~Logger() override {} - - // sample::mojom::Logger: - void Log(const std::string& message) override { - LOG(ERROR) << "[Logger] " << message; - lines_.push_back(message); - } - - void GetTail(const GetTailCallback& callback) override { - callback.Run(lines_.back()); - } - - private: - mojo::Binding binding_; - std::vector lines_; - - DISALLOW_COPY_AND_ASSIGN(LoggerImpl); -}; -``` - -And an updated client call: - -``` cpp -void OnGetTail(const std::string& message) { - LOG(ERROR) << "Tail was: " << message; -} - -logger->GetTail(base::Bind(&OnGetTail)); -``` - -Behind the scenes, the implementation-side callback is actually serializing the -response arguments and writing them onto the pipe for delivery back to the -client. Meanwhile the client-side callback is invoked by some internal logic -which watches the pipe for an incoming response message, reads and deserializes -it once it arrives, and then invokes the callback with the deserialized -parameters. - -### Connection Errors - -If there are no remaining messages available on a pipe and the remote end has -been closed, a connection error will be triggered on the local end. Connection -errors may also be triggered by automatic forced local pipe closure due to -*e.g.* a validation error when processing a received message. - -Regardless of the underlying cause, when a connection error is encountered on -a binding endpoint, that endpoint's **connection error handler** (if set) is -invoked. This handler is a simple `base::Closure` and may only be invoked -*once* as long as the endpoint is bound to the same pipe. Typically clients and -implementations use this handler to do some kind of cleanup or -- particuarly if -the error was unexpected -- create a new pipe and attempt to establish a new -connection with it. - -All message pipe-binding C++ objects (*e.g.*, `mojo::Binding`, -`mojo::InterfacePtr`, *etc.*) support setting their connection error handler -via a `set_connection_error_handler` method. - -We can set up another end-to-end `Logger` example to demonstrate error handler -invocation: - -``` cpp -sample::mojom::LoggerPtr logger; -LoggerImpl impl(mojo::MakeRequest(&logger)); -impl.set_connection_error_handler(base::Bind([] { LOG(ERROR) << "Bye."; })); -logger->Log("OK cool"); -logger.reset(); // Closes the client end. -``` - -As long as `impl` stays alive here, it will eventually receive the `Log` message -followed immediately by an invocation of the bound callback which outputs -`"Bye."`. Like all other bindings callbacks, a connection error handler will -**never** be invoked once its corresponding binding object has been destroyed. - -In fact, suppose instead that `LoggerImpl` had set up the following error -handler within its constructor: - -``` cpp -LoggerImpl::LoggerImpl(sample::mojom::LoggerRequest request) - : binding_(this, std::move(request)) { - binding_.set_connection_error_handler( - base::Bind(&LoggerImpl::OnError, base::Unretained(this))); -} - -void LoggerImpl::OnError() { - LOG(ERROR) << "Client disconnected! Purging log lines."; - lines_.clear(); -} -``` - -The use of `base::Unretained` is *safe* because the error handler will never be -invoked beyond the lifetime of `binding_`, and `this` owns `binding_`. - -### A Note About Ordering - -As mentioned in the previous section, closing one end of a pipe will eventually -trigger a connection error on the other end. However it's important to note that -this event is itself ordered with respect to any other event (*e.g.* writing a -message) on the pipe. - -This means that it's safe to write something contrived like: - -``` cpp -void GoBindALogger(sample::mojom::LoggerRequest request) { - LoggerImpl impl(std::move(request)); - base::RunLoop loop; - impl.set_connection_error_handler(loop.QuitClosure()); - loop.Run(); -} - -void LogSomething() { - sample::mojom::LoggerPtr logger; - bg_thread->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&GoBindALogger, mojo::MakeRequest(&logger))); - logger->Log("OK Computer"); -} -``` - -When `logger` goes out of scope it immediately closes its end of the message -pipe, but the impl-side won't notice this until it receives the sent `Log` -message. Thus the `impl` above will first log our message and *then* see a -connection error and break out of the run loop. - -### Sending Interfaces Over Interfaces - -Now we know how to create interface pipes and use their Ptr and Request -endpoints in some interesting ways. This still doesn't add up to interesting -IPC! The bread and butter of Mojo IPC is the ability to transfer interface -endpoints across other interfaces, so let's take a look at how to accomplish -that. - -#### Sending Interface Requests - -Consider a new example Mojom in `//sample/db.mojom`: - -``` cpp -module db.mojom; - -interface Table { - void AddRow(int32 key, string data); -}; - -interface Database { - AddTable(Table& table); -}; -``` - -As noted in the -[Mojom IDL documentation](/mojo/public/tools/bindings#Primitive-Types), -the `Table&` syntax denotes a `Table` interface request. This corresponds -precisely to the `InterfaceRequest` type discussed in the sections above, and -in fact the generated code for these interfaces is approximately: - -``` cpp -namespace db { -namespace mojom { - -class Table { - public: - virtual ~Table() {} - - virtual void AddRow(int32_t key, const std::string& data) = 0; -} - -using TablePtr = mojo::InterfacePtr; -using TableRequest = mojo::InterfaceRequest
; - -class Database { - public: - virtual ~Database() {} - - virtual void AddTable(TableRequest table); -}; - -using DatabasePtr = mojo::InterfacePtr; -using DatabaseRequest = mojo::InterfaceRequest; - -} // namespace mojom -} // namespace db -``` - -We can put this all together now with an implementation of `Table` and -`Database`: - -``` cpp -#include "sample/db.mojom.h" - -class TableImpl : public db::mojom:Table { - public: - explicit TableImpl(db::mojom::TableRequest request) - : binding_(this, std::move(request)) {} - ~TableImpl() override {} - - // db::mojom::Table: - void AddRow(int32_t key, const std::string& data) override { - rows_.insert({key, data}); - } - - private: - mojo::Binding binding_; - std::map rows_; -}; - -class DatabaseImpl : public db::mojom::Database { - public: - explicit DatabaseImpl(db::mojom::DatabaseRequest request) - : binding_(this, std::move(request)) {} - ~DatabaseImpl() override {} - - // db::mojom::Database: - void AddTable(db::mojom::TableRequest table) { - tables_.emplace_back(base::MakeUnique(std::move(table))); - } - - private: - mojo::Binding binding_; - std::vector> tables_; -}; -``` - -Pretty straightforward. The `Table&` Mojom paramter to `AddTable` translates to -a C++ `db::mojom::TableRequest`, aliased from -`mojo::InterfaceRequest`, which we know is just a -strongly-typed message pipe handle. When `DatabaseImpl` gets an `AddTable` call, -it constructs a new `TableImpl` and binds it to the received `TableRequest`. - -Let's see how this can be used. - -``` cpp -db::mojom::DatabasePtr database; -DatabaseImpl db_impl(mojo::MakeRequest(&database)); - -db::mojom::TablePtr table1, table2; -database->AddTable(mojo::MakeRequest(&table1)); -database->AddTable(mojo::MakeRequest(&table2)); - -table1->AddRow(1, "hiiiiiiii"); -table2->AddRow(2, "heyyyyyy"); -``` - -Notice that we can again start using the new `Table` pipes immediately, even -while their `TableRequest` endpoints are still in transit. - -#### Sending InterfacePtrs - -Of course we can also send `InterfacePtr`s: - -``` cpp -interface TableListener { - OnRowAdded(int32 key, string data); -}; - -interface Table { - AddRow(int32 key, string data); - - AddListener(TableListener listener); -}; -``` - -This would generate a `Table::AddListener` signature like so: - -``` cpp - virtual void AddListener(TableListenerPtr listener) = 0; -``` - -and this could be used like so: - -``` cpp -db::mojom::TableListenerPtr listener; -TableListenerImpl impl(mojo::MakeRequest(&listener)); -table->AddListener(std::move(listener)); -``` - -## Other Interface Binding Types - -The [Interfaces](#Interfaces) section above covers basic usage of the most -common bindings object types: `InterfacePtr`, `InterfaceRequest`, and `Binding`. -While these types are probably the most commonly used in practice, there are -several other ways of binding both client- and implementation-side interface -pipes. - -### Strong Bindings - -A **strong binding** exists as a standalone object which owns its interface -implementation and automatically cleans itself up when its bound interface -endpoint detects an error. The -[**`MakeStrongBinding`**](https://cs.chromim.org/chromium/src//mojo/public/cpp/bindings/strong_binding.h) -function is used to create such a binding. -. - -``` cpp -class LoggerImpl : public sample::mojom::Logger { - public: - LoggerImpl() {} - ~LoggerImpl() override {} - - // sample::mojom::Logger: - void Log(const std::string& message) override { - LOG(ERROR) << "[Logger] " << message; - } - - private: - // NOTE: This doesn't own any Binding object! -}; - -db::mojom::LoggerPtr logger; -mojo::MakeStrongBinding(base::MakeUnique(), - mojo::MakeRequest(&logger)); - -logger->Log("NOM NOM NOM MESSAGES"); -``` - -Now as long as `logger` remains open somewhere in the system, the bound -`DatabaseImpl` on the other end will remain alive. - -### Binding Sets - -Sometimes it's useful to share a single implementation instance with multiple -clients. [**`BindingSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/binding_set.h) -makes this easy. Consider the Mojom: - -``` cpp -module system.mojom; - -interface Logger { - Log(string message); -}; - -interface LoggerProvider { - GetLogger(Logger& logger); -}; -``` - -We can use `BindingSet` to bind multiple `Logger` requests to a single -implementation instance: - -``` cpp -class LogManager : public system::mojom::LoggerProvider, - public system::mojom::Logger { - public: - explicit LogManager(system::mojom::LoggerProviderRequest request) - : provider_binding_(this, std::move(request)) {} - ~LogManager() {} - - // system::mojom::LoggerProvider: - void GetLogger(LoggerRequest request) override { - logger_bindings_.AddBinding(this, std::move(request)); - } - - // system::mojom::Logger: - void Log(const std::string& message) override { - LOG(ERROR) << "[Logger] " << message; - } - - private: - mojo::Binding provider_binding_; - mojo::BindingSet logger_bindings_; -}; - -``` - - -### InterfacePtr Sets - -Similar to the `BindingSet` above, sometimes it's useful to maintain a set of -`InterfacePtr`s for *e.g.* a set of clients observing some event. -[**`InterfacePtrSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/interface_ptr_set.h) -is here to help. Take the Mojom: - -``` cpp -module db.mojom; - -interface TableListener { - OnRowAdded(int32 key, string data); -}; - -interface Table { - AddRow(int32 key, string data); - AddListener(TableListener listener); -}; -``` - -An implementation of `Table` might look something like like this: - -``` cpp -class TableImpl : public db::mojom::Table { - public: - TableImpl() {} - ~TableImpl() override {} - - // db::mojom::Table: - void AddRow(int32_t key, const std::string& data) override { - rows_.insert({key, data}); - listeners_.ForEach([key, &data](db::mojom::TableListener* listener) { - listener->OnRowAdded(key, data); - }); - } - - void AddListener(db::mojom::TableListenerPtr listener) { - listeners_.AddPtr(std::move(listener)); - } - - private: - mojo::InterfacePtrSet listeners_; - std::map rows_; -}; -``` - -## Associated Interfaces - -See [this document](https://www.chromium.org/developers/design-documents/mojo/associated-interfaces). - -TODO: Move the above doc into the repository markdown docs. - -## Synchronous Calls - -See [this document](https://www.chromium.org/developers/design-documents/mojo/synchronous-calls) - -TODO: Move the above doc into the repository markdown docs. - -## Type Mapping - -In many instances you might prefer that your generated C++ bindings use a more -natural type to represent certain Mojom types in your interface methods. For one -example consider a Mojom struct such as the `Rect` below: - -``` cpp -module gfx.mojom; - -struct Rect { - int32 x; - int32 y; - int32 width; - int32 height; -}; - -interface Canvas { - void FillRect(Rect rect); -}; -``` - -The `Canvas` Mojom interface would normally generate a C++ interface like: - -``` cpp -class Canvas { - public: - virtual void FillRect(RectPtr rect) = 0; -}; -``` - -However, the Chromium tree already defines a native -[`gfx::Rect`](https://cs.chromium.org/chromium/src/ui/gfx/geometry/rect.h) which -is equivalent in meaning but which also has useful helper methods. Instead of -manually converting between a `gfx::Rect` and the Mojom-generated `RectPtr` at -every message boundary, wouldn't it be nice if the Mojom bindings generator -could instead generate: - -``` cpp -class Canvas { - public: - virtual void FillRect(const gfx::Rect& rect) = 0; -} -``` - -The correct answer is, "Yes! That would be nice!" And fortunately, it can! - -### Global Configuration - -While this feature is quite powerful, it introduces some unavoidable complexity -into build system. This stems from the fact that type-mapping is an inherently -viral concept: if `gfx::mojom::Rect` is mapped to `gfx::Rect` anywhere, the -mapping needs to apply *everywhere*. - -For this reason we have a few global typemap configurations defined in -[chromium_bindings_configuration.gni](https://cs.chromium.com/chromium/src/mojo/public/tools/bindings/chromium_bindings_configuration.gni) -and -[blink_bindings_configuration.gni](https://cs.chromium.com/chromium/src/mojo/public/tools/bindings/blink_bindings_configuration.gni). These configure the two supported [variants](#Variants) of Mojom generated -bindings in the repository. Read more on this in the sections that follow. - -For now, let's take a look at how to express the mapping from `gfx::mojom::Rect` -to `gfx::Rect`. - -### Defining `StructTraits` - -In order to teach generated bindings code how to serialize an arbitrary native -type `T` as an arbitrary Mojom type `mojom::U`, we need to define an appropriate -specialization of the -[`mojo::StructTraits`](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/struct_traits.h) -template. - -A valid specialization of `StructTraits` MUST define the following static -methods: - -* A single static accessor for every field of the Mojom struct, with the exact - same name as the struct field. These accessors must all take a const ref to - an object of the native type, and must return a value compatible with the - Mojom struct field's type. This is used to safely and consistently extract - data from the native type during message serialization without incurring extra - copying costs. - -* A single static `Read` method which initializes an instance of the the native - type given a serialized representation of the Mojom struct. The `Read` method - must return a `bool` to indicate whether the incoming data is accepted - (`true`) or rejected (`false`). - -There are other methods a `StructTraits` specialization may define to satisfy -some less common requirements. See -[Advanced StructTraits Usage](#Advanced-StructTraits-Usage) for details. - -In order to define the mapping for `gfx::Rect`, we want the following -`StructTraits` specialization, which we'll define in -`//ui/gfx/geometry/mojo/geometry_struct_traits.h`: - -``` cpp -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/mojo/geometry.mojom.h" - -namespace mojo { - -template <> -class StructTraits { - public: - static int32_t x(const gfx::Rect& r) { return r.x(); } - static int32_t y(const gfx::Rect& r) { return r.y(); } - static int32_t width(const gfx::Rect& r) { return r.width(); } - static int32_t height(const gfx::Rect& r) { return r.height(); } - - static bool Read(gfx::mojom::RectDataView data, gfx::Rect* out_rect); -}; - -} // namespace mojo -``` - -And in `//ui/gfx/geometry/mojo/geometry_struct_traits.cc`: - -``` cpp -#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" - -namespace mojo { - -// static -template <> -bool StructTraits::Read( - gfx::mojom::RectDataView data, - gfx::Rect* out_rect) { - if (data.width() < 0 || data.height() < 0) - return false; - - out_rect->SetRect(data.x(), data.y(), data.width(), data.height()); - return true; -}; - -} // namespace mojo -``` - -Note that the `Read()` method returns `false` if either the incoming `width` or -`height` fields are negative. This acts as a validation step during -deserialization: if a client sends a `gfx::Rect` with a negative width or -height, its message will be rejected and the pipe will be closed. In this way, -type mapping can serve to enable custom validation logic in addition to making -callsites and interface implemention more convenient. - -### Enabling a New Type Mapping - -We've defined the `StructTraits` necessary, but we still need to teach the -bindings generator (and hence the build system) about the mapping. To do this we -must create a **typemap** file, which uses familiar GN syntax to describe the -new type mapping. - -Let's place this `geometry.typemap` file alongside our Mojom file: - -``` -mojom = "//ui/gfx/geometry/mojo/geometry.mojom" -public_headers = [ "//ui/gfx/geometry/rect.h" ] -traits_headers = [ "//ui/gfx/geometry/mojo/geometry_struct_traits.h" ] -sources = [ "//ui/gfx/geometry/mojo/geometry_struct_traits.cc" ] -public_deps = [ "//ui/gfx/geometry" ] -type_mappings = [ - "gfx.mojom.Rect=gfx::Rect", -] -``` - -Let's look at each of the variables above: - -* `mojom`: Specifies the `mojom` file to which the typemap applies. Many - typemaps may apply to the same `mojom` file, but any given typemap may only - apply to a single `mojom` file. -* `public_headers`: Additional headers required by any code which would depend - on the Mojom definition of `gfx.mojom.Rect` now that the typemap is applied. - Any headers required for the native target type definition should be listed - here. -* `traits_headers`: Headers which contain the relevant `StructTraits` - specialization(s) for any type mappings described by this file. -* `sources`: Any private implementation sources needed for the `StructTraits` - definition. -* `public_deps`: Target dependencies exposed by the `public_headers` and - `traits_headers`. -* `deps`: Target dependencies exposed by `sources` but not already covered by - `public_deps`. -* `type_mappings`: A list of type mappings to be applied for this typemap. The - strings in this list are of the format `"MojomType=CppType"`, where - `MojomType` must be a fully qualified Mojom typename and `CppType` must be a - fully qualified C++ typename. Additional attributes may be specified in square - brackets following the `CppType`: - * `move_only`: The `CppType` is move-only and should be passed by value - in any generated method signatures. Note that `move_only` is transitive, - so containers of `MojomType` will translate to containers of `CppType` - also passed by value. - * `copyable_pass_by_value`: Forces values of type `CppType` to be passed by - value without moving them. Unlike `move_only`, this is not transitive. - * `nullable_is_same_type`: By default a non-nullable `MojomType` will be - mapped to `CppType` while a nullable `MojomType?` will be mapped to - `base::Optional`. If this attribute is set, the `base::Optional` - wrapper is omitted for nullable `MojomType?` values, but the - `StructTraits` definition for this type mapping must define additional - `IsNull` and `SetToNull` methods. See - [Specializing Nullability](#Specializing-Nullability) below. - - -Now that we have the typemap file we need to add it to a local list of typemaps -that can be added to the global configuration. We create a new -`//ui/gfx/typemaps.gni` file with the following contents: - -``` -typemaps = [ - "//ui/gfx/geometry/mojo/geometry.typemap", -] -``` - -And finally we can reference this file in the global default (Chromium) bindings -configuration by adding it to `_typemap_imports` in -[chromium_bindings_configuration.gni](https://cs.chromium.com/chromium/src/mojo/public/tools/bindings/chromium_bindings_configuration.gni): - -``` -_typemap_imports = [ - ..., - "//ui/gfx/typemaps.gni", - ..., -] -``` - -### StructTraits Reference - -Each of a `StructTraits` specialization's static getter methods -- one per -struct field -- must return a type which can be used as a data source for the -field during serialization. This is a quick reference mapping Mojom field type -to valid getter return types: - -| Mojom Field Type | C++ Getter Return Type | -|------------------------------|------------------------| -| `bool` | `bool` -| `int8` | `int8_t` -| `uint8` | `uint8_t` -| `int16` | `int16_t` -| `uint16` | `uint16_t` -| `int32` | `int32_t` -| `uint32` | `uint32_t` -| `int64` | `int64_t` -| `uint64` | `uint64_t` -| `float` | `float` -| `double` | `double` -| `handle` | `mojo::ScopedHandle` -| `handle` | `mojo::ScopedMessagePipeHandle` -| `handle` | `mojo::ScopedDataPipeConsumerHandle` -| `handle` | `mojo::ScopedDataPipeProducerHandle` -| `handle` | `mojo::ScopedSharedBufferHandle` -| `FooInterface` | `FooInterfacePtr` -| `FooInterface&` | `FooInterfaceRequest` -| `associated FooInterface` | `FooAssociatedInterfacePtr` -| `associated FooInterface&` | `FooAssociatedInterfaceRequest` -| `string` | Value or reference to any type `T` that has a `mojo::StringTraits` specialization defined. By default this includes `std::string`, `base::StringPiece`, and `WTF::String` (Blink). -| `array` | Value or reference to any type `T` that has a `mojo::ArrayTraits` specialization defined. By default this includes `std::vector`, `mojo::CArray`, and `WTF::Vector` (Blink). -| `map` | Value or reference to any type `T` that has a `mojo::MapTraits` specialization defined. By default this includes `std::map`, `mojo::unordered_map`, and `WTF::HashMap` (Blink). -| `FooEnum` | Value of any type that has an appropriate `EnumTraits` specialization defined. By default this inlcudes only the generated `FooEnum` type. -| `FooStruct` | Value or reference to any type that has an appropriate `StructTraits` specialization defined. By default this includes only the generated `FooStructPtr` type. -| `FooUnion` | Value of reference to any type that has an appropriate `UnionTraits` specialization defined. By default this includes only the generated `FooUnionPtr` type. - -### Using Generated DataView Types - -Static `Read` methods on `StructTraits` specializations get a generated -`FooDataView` argument (such as the `RectDataView` in the example above) which -exposes a direct view of the serialized Mojom structure within an incoming -message's contents. In order to make this as easy to work with as possible, the -generated `FooDataView` types have a generated method corresponding to every -struct field: - -* For POD field types (*e.g.* bools, floats, integers) these are simple accessor - methods with names identical to the field name. Hence in the `Rect` example we - can access things like `data.x()` and `data.width()`. The return types - correspond exactly to the mappings listed in the table above, under - [StructTraits Reference](#StructTraits-Reference). - -* For handle and interface types (*e.g* `handle` or `FooInterface&`) these - are named `TakeFieldName` (for a field named `field_name`) and they return an - appropriate move-only handle type by value. The return types correspond - exactly to the mappings listed in the table above, under - [StructTraits Reference](#StructTraits-Reference). - -* For all other field types (*e.g.*, enums, strings, arrays, maps, structs) - these are named `ReadFieldName` (for a field named `field_name`) and they - return a `bool` (to indicate success or failure in reading). On success they - fill their output argument with the deserialized field value. The output - argument may be a pointer to any type with an appropriate `StructTraits` - specialization defined, as mentioned in the table above, under - [StructTraits Reference](#StructTraits-Reference). - -An example would be useful here. Suppose we introduced a new Mojom struct: - -``` cpp -struct RectPair { - Rect left; - Rect right; -}; -``` - -and a corresponding C++ type: - -``` cpp -class RectPair { - public: - RectPair() {} - - const gfx::Rect& left() const { return left_; } - const gfx::Rect& right() const { return right_; } - - void Set(const gfx::Rect& left, const gfx::Rect& right) { - left_ = left; - right_ = right; - } - - // ... some other stuff - - private: - gfx::Rect left_; - gfx::Rect right_; -}; -``` - -Our traits to map `gfx::mojom::RectPair` to `gfx::RectPair` might look like -this: - -``` cpp -namespace mojo { - -template <> -class StructTraits - public: - static const gfx::Rect& left(const gfx::RectPair& pair) { - return pair.left(); - } - - static const gfx::Rect& right(const gfx::RectPair& pair) { - return pair.right(); - } - - static bool Read(gfx::mojom::RectPairDataView data, gfx::RectPair* out_pair) { - gfx::Rect left, right; - if (!data.ReadLeft(&left) || !data.ReadRight(&right)) - return false; - out_pair->Set(left, right); - return true; - } -} // namespace mojo -``` - -Generated `ReadFoo` methods always convert `multi_word_field_name` fields to -`ReadMultiWordFieldName` methods. - -### Variants - -By now you may have noticed that additional C++ sources are generated when a -Mojom is processed. These exist due to type mapping, and the source files we -refer to throughout this docuemnt (namely `foo.mojom.cc` and `foo.mojom.h`) are -really only one **variant** (the *default* or *chromium* variant) of the C++ -bindings for a given Mojom file. - -The only other variant currently defined in the tree is the *blink* variant, -which produces a few additional files: - -``` -out/gen/sample/db.mojom-blink.cc -out/gen/sample/db.mojom-blink.h -``` - -These files mirror the definitions in the default variant but with different -C++ types in place of certain builtin field and parameter types. For example, -Mojom strings are represented by `WTF::String` instead of `std::string`. To -avoid symbol collisions, the variant's symbols are nested in an extra inner -namespace, so Blink consumer of the interface might write something like: - -``` -#include "sample/db.mojom-blink.h" - -class TableImpl : public db::mojom::blink::Table { - public: - void AddRow(int32_t key, const WTF::String& data) override { - // ... - } -}; -``` - -In addition to using different C++ types for builtin strings, arrays, and maps, -the global typemap configuration for default and "blink" variants are completely -separate. To add a typemap for the Blink configuration, you can modify -[blink_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/blink_bindings_configuration.gni). - -All variants share some definitions which are unaffected by differences in the -type mapping configuration (enums, for example). These definitions are generated -in *shared* sources: - -``` -out/gen/sample/db.mojom-shared.cc -out/gen/sample/db.mojom-shared.h -out/gen/sample/db.mojom-shared-internal.h -``` - -Including either variant's header (`db.mojom.h` or `db.mojom-blink.h`) -implicitly includes the shared header, but you have on some occasions wish to -include *only* the shared header in some instances. - -Finally, note that for `mojom` GN targets, there is implicitly a corresponding -`mojom_{variant}` target defined for any supported bindings configuration. So -for example if you've defined in `//sample/BUILD.gn`: - -``` -import("mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "db.mojom", - ] -} -``` - -Code in Blink which wishes to use the generated Blink-variant definitions must -depend on `"//sample:interfaces_blink"`. - -## Versioning Considerations - -For general documentation of versioning in the Mojom IDL see -[Versioning](/mojo/public/tools/bindings#Versioning). - -This section briefly discusses some C++-specific considerations relevant to -versioned Mojom types. - -### Querying Interface Versions - -`InterfacePtr` defines the following methods to query or assert remote interface -version: - -```cpp -void QueryVersion(const base::Callback& callback); -``` - -This queries the remote endpoint for the version number of its binding. When a -response is received `callback` is invoked with the remote version number. Note -that this value is cached by the `InterfacePtr` instance to avoid redundant -queries. - -```cpp -void RequireVersion(uint32_t version); -``` - -Informs the remote endpoint that a minimum version of `version` is required by -the client. If the remote endpoint cannot support that version, it will close -its end of the pipe immediately, preventing any other requests from being -received. - -### Versioned Enums - -For convenience, every extensible enum has a generated helper function to -determine whether a received enum value is known by the implementation's current -version of the enum definition. For example: - -```cpp -[Extensible] -enum Department { - SALES, - DEV, - RESEARCH, -}; -``` - -generates the function in the same namespace as the generated C++ enum type: - -```cpp -inline bool IsKnownEnumValue(Department value); -``` - -### Additional Documentation - -[Calling Mojo From Blink](https://www.chromium.org/developers/design-documents/mojo/calling-mojo-from-blink) -: A brief overview of what it looks like to use Mojom C++ bindings from - within Blink code. diff --git a/mojo/public/cpp/bindings/array_data_view.h b/mojo/public/cpp/bindings/array_data_view.h deleted file mode 100644 index d02a884..0000000 --- a/mojo/public/cpp/bindings/array_data_view.h +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_ - -#include - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" - -namespace mojo { -namespace internal { - -template -class ArrayDataViewImpl; - -template -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo::value>::type> { - public: - using Data_ = typename MojomTypeTraits>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - T operator[](size_t index) const { return data_->at(index); } - - const T* data() const { return data_->storage(); } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo::value>::type> { - public: - using Data_ = typename MojomTypeTraits>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - bool operator[](size_t index) const { return data_->at(index); } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo::value>::type> { - public: - static_assert(sizeof(T) == sizeof(int32_t), "Unexpected enum size"); - - using Data_ = typename MojomTypeTraits>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - T operator[](size_t index) const { return static_cast(data_->at(index)); } - - const T* data() const { return reinterpret_cast(data_->storage()); } - - template - bool Read(size_t index, U* output) { - return Deserialize(data_->at(index), output); - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo::value>::type> { - public: - using Data_ = typename MojomTypeTraits>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - template - U Take(size_t index) { - U result; - bool ret = Deserialize(&data_->at(index), &result, context_); - DCHECK(ret); - return result; - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo::value>::type> { - public: - using Data_ = typename MojomTypeTraits>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - T Take(size_t index) { - T result; - bool ret = Deserialize(&data_->at(index), &result, context_); - DCHECK(ret); - return result; - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template -class ArrayDataViewImpl::value>::type> { - public: - using Data_ = typename MojomTypeTraits>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - void GetDataView(size_t index, T* output) { - *output = T(data_->at(index).Get(), context_); - } - - template - bool Read(size_t index, U* output) { - return Deserialize(data_->at(index).Get(), output, context_); - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -template -class ArrayDataViewImpl< - T, - typename std::enable_if< - BelongsTo::value>::type> { - public: - using Data_ = typename MojomTypeTraits>::Data; - - ArrayDataViewImpl(Data_* data, SerializationContext* context) - : data_(data), context_(context) {} - - void GetDataView(size_t index, T* output) { - *output = T(&data_->at(index), context_); - } - - template - bool Read(size_t index, U* output) { - return Deserialize(&data_->at(index), output, context_); - } - - protected: - Data_* data_; - SerializationContext* context_; -}; - -} // namespace internal - -template -class MapDataView; - -template -class ArrayDataView : public internal::ArrayDataViewImpl { - public: - using Element = T; - using Data_ = typename internal::ArrayDataViewImpl::Data_; - - ArrayDataView() : internal::ArrayDataViewImpl(nullptr, nullptr) {} - - ArrayDataView(Data_* data, internal::SerializationContext* context) - : internal::ArrayDataViewImpl(data, context) {} - - bool is_null() const { return !this->data_; } - - size_t size() const { return this->data_->size(); } - - // Methods to access elements are different for different element types. They - // are inherited from internal::ArrayDataViewImpl: - - // POD types except boolean and enums: - // T operator[](size_t index) const; - // const T* data() const; - - // Boolean: - // bool operator[](size_t index) const; - - // Enums: - // T operator[](size_t index) const; - // const T* data() const; - // template - // bool Read(size_t index, U* output); - - // Handles: - // T Take(size_t index); - - // Interfaces: - // template - // U Take(size_t index); - - // Object types: - // void GetDataView(size_t index, T* output); - // template - // bool Read(size_t index, U* output); - - private: - template - friend class MapDataView; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_DATA_VIEW_H_ diff --git a/mojo/public/cpp/bindings/array_traits.h b/mojo/public/cpp/bindings/array_traits.h deleted file mode 100644 index 594b2e0..0000000 --- a/mojo/public/cpp/bindings/array_traits.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ - -namespace mojo { - -// This must be specialized for any type |T| to be serialized/deserialized as -// a mojom array. -// -// Usually you would like to do a partial specialization for a container (e.g. -// vector) template. Imagine you want to specialize it for Container<>, you need -// to implement: -// -// template -// struct ArrayTraits> { -// using Element = T; -// // These two statements are optional. Use them if you'd like to serialize -// // a container that supports iterators but does not support O(1) random -// // access and so GetAt(...) would be expensive. -// // using Iterator = T::iterator; -// // using ConstIterator = T::const_iterator; -// -// // These two methods are optional. Please see comments in struct_traits.h -// static bool IsNull(const Container& input); -// static void SetToNull(Container* output); -// -// static size_t GetSize(const Container& input); -// -// // These two methods are optional. They are used to access the -// // underlying storage of the array to speed up copy of POD types. -// static T* GetData(Container& input); -// static const T* GetData(const Container& input); -// -// // The following six methods are optional if the GetAt(...) methods are -// // implemented. These methods specify how to read the elements of -// // Container in some sequential order specified by the iterator. -// // -// // Acquires an iterator positioned at the first element in the container. -// static ConstIterator GetBegin(const Container& input); -// static Iterator GetBegin(Container& input); -// -// // Advances |iterator| to the next position within the container. -// static void AdvanceIterator(ConstIterator& iterator); -// static void AdvanceIterator(Iterator& iterator); -// -// // Returns a reference to the value at the current position of -// // |iterator|. Optionally, the ConstIterator version of GetValue can -// // return by value instead of by reference if it makes sense for the -// // type. -// static const T& GetValue(ConstIterator& iterator); -// static T& GetValue(Iterator& iterator); -// -// // These two methods are optional if the iterator methods are -// // implemented. -// static T& GetAt(Container& input, size_t index); -// static const T& GetAt(const Container& input, size_t index); -// -// // Returning false results in deserialization failure and causes the -// // message pipe receiving it to be disconnected. -// static bool Resize(Container& input, size_t size); -// }; -// -template -struct ArrayTraits; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/array_traits_carray.h b/mojo/public/cpp/bindings/array_traits_carray.h deleted file mode 100644 index 3ff694b..0000000 --- a/mojo/public/cpp/bindings/array_traits_carray.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_ - -#include "mojo/public/cpp/bindings/array_traits.h" - -namespace mojo { - -template -struct CArray { - CArray() : size(0), max_size(0), data(nullptr) {} - CArray(size_t size, size_t max_size, T* data) - : size(size), max_size(max_size), data(data) {} - size_t size; - const size_t max_size; - T* data; -}; - -template -struct ConstCArray { - ConstCArray() : size(0), data(nullptr) {} - ConstCArray(size_t size, const T* data) : size(size), data(data) {} - size_t size; - const T* data; -}; - -template -struct ArrayTraits> { - using Element = T; - - static bool IsNull(const CArray& input) { return !input.data; } - - static void SetToNull(CArray* output) { output->data = nullptr; } - - static size_t GetSize(const CArray& input) { return input.size; } - - static T* GetData(CArray& input) { return input.data; } - - static const T* GetData(const CArray& input) { return input.data; } - - static T& GetAt(CArray& input, size_t index) { return input.data[index]; } - - static const T& GetAt(const CArray& input, size_t index) { - return input.data[index]; - } - - static bool Resize(CArray& input, size_t size) { - if (size > input.max_size) - return false; - - input.size = size; - return true; - } -}; - -template -struct ArrayTraits> { - using Element = T; - - static bool IsNull(const ConstCArray& input) { return !input.data; } - - static size_t GetSize(const ConstCArray& input) { return input.size; } - - static const T* GetData(const ConstCArray& input) { return input.data; } - - static const T& GetAt(const ConstCArray& input, size_t index) { - return input.data[index]; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_CARRAY_H_ diff --git a/mojo/public/cpp/bindings/array_traits_stl.h b/mojo/public/cpp/bindings/array_traits_stl.h deleted file mode 100644 index dec47bf..0000000 --- a/mojo/public/cpp/bindings/array_traits_stl.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ - -#include -#include -#include - -#include "mojo/public/cpp/bindings/array_traits.h" - -namespace mojo { - -template -struct ArrayTraits> { - using Element = T; - - static bool IsNull(const std::vector& input) { - // std::vector<> is always converted to non-null mojom array. - return false; - } - - static void SetToNull(std::vector* output) { - // std::vector<> doesn't support null state. Set it to empty instead. - output->clear(); - } - - static size_t GetSize(const std::vector& input) { return input.size(); } - - static T* GetData(std::vector& input) { return input.data(); } - - static const T* GetData(const std::vector& input) { return input.data(); } - - static typename std::vector::reference GetAt(std::vector& input, - size_t index) { - return input[index]; - } - - static typename std::vector::const_reference GetAt( - const std::vector& input, - size_t index) { - return input[index]; - } - - static inline bool Resize(std::vector& input, size_t size) { - // Instead of calling std::vector::resize() directly, this is a hack to - // make compilers happy. Some compilers (e.g., Mac, Android, Linux MSan) - // currently don't allow resizing types like - // std::vector>. - // Because the deserialization code doesn't care about the original contents - // of |input|, we discard them directly. - // - // The "inline" keyword of this method matters. Without it, we have observed - // significant perf regression with some tests on Mac. crbug.com/631415 - if (input.size() != size) { - std::vector temp(size); - input.swap(temp); - } - - return true; - } -}; - -// This ArrayTraits specialization is used only for serialization. -template -struct ArrayTraits> { - using Element = T; - using ConstIterator = typename std::set::const_iterator; - - static bool IsNull(const std::set& input) { - // std::set<> is always converted to non-null mojom array. - return false; - } - - static size_t GetSize(const std::set& input) { return input.size(); } - - static ConstIterator GetBegin(const std::set& input) { - return input.begin(); - } - static void AdvanceIterator(ConstIterator& iterator) { - ++iterator; - } - static const T& GetValue(ConstIterator& iterator) { - return *iterator; - } -}; - -template -struct MapValuesArrayView { - explicit MapValuesArrayView(const std::map& map) : map(map) {} - const std::map& map; -}; - -// Convenience function to create a MapValuesArrayView<> that infers the -// template arguments from its argument type. -template -MapValuesArrayView MapValuesToArray(const std::map& map) { - return MapValuesArrayView(map); -} - -// This ArrayTraits specialization is used only for serialization and converts -// a map into an array, discarding the keys. -template -struct ArrayTraits> { - using Element = V; - using ConstIterator = typename std::map::const_iterator; - - static bool IsNull(const MapValuesArrayView& input) { - // std::map<> is always converted to non-null mojom array. - return false; - } - - static size_t GetSize(const MapValuesArrayView& input) { - return input.map.size(); - } - static ConstIterator GetBegin(const MapValuesArrayView& input) { - return input.map.begin(); - } - static void AdvanceIterator(ConstIterator& iterator) { ++iterator; } - static const V& GetValue(ConstIterator& iterator) { return iterator->second; } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_STL_H_ diff --git a/mojo/public/cpp/bindings/array_traits_wtf_vector.h b/mojo/public/cpp/bindings/array_traits_wtf_vector.h deleted file mode 100644 index 6e20735..0000000 --- a/mojo/public/cpp/bindings/array_traits_wtf_vector.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ - -#include "mojo/public/cpp/bindings/array_traits.h" -#include "third_party/WebKit/Source/wtf/Vector.h" - -namespace mojo { - -template -struct ArrayTraits> { - using Element = U; - - static bool IsNull(const WTF::Vector& input) { - // WTF::Vector<> is always converted to non-null mojom array. - return false; - } - - static void SetToNull(WTF::Vector* output) { - // WTF::Vector<> doesn't support null state. Set it to empty instead. - output->clear(); - } - - static size_t GetSize(const WTF::Vector& input) { return input.size(); } - - static U* GetData(WTF::Vector& input) { return input.data(); } - - static const U* GetData(const WTF::Vector& input) { return input.data(); } - - static U& GetAt(WTF::Vector& input, size_t index) { return input[index]; } - - static const U& GetAt(const WTF::Vector& input, size_t index) { - return input[index]; - } - - static bool Resize(WTF::Vector& input, size_t size) { - input.resize(size); - return true; - } -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_TRAITS_WTF_VECTOR_H_ diff --git a/mojo/public/cpp/bindings/associated_binding.h b/mojo/public/cpp/bindings/associated_binding.h deleted file mode 100644 index 5941166..0000000 --- a/mojo/public/cpp/bindings/associated_binding.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ - -#include -#include -#include - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -class MessageReceiver; - -// Base class used to factor out code in AssociatedBinding expansions, in -// particular for Bind(). -class MOJO_CPP_BINDINGS_EXPORT AssociatedBindingBase { - public: - AssociatedBindingBase(); - ~AssociatedBindingBase(); - - // Adds a message filter to be notified of each incoming message before - // dispatch. If a filter returns |false| from Accept(), the message is not - // dispatched and the pipe is closed. Filters cannot be removed. - void AddFilter(std::unique_ptr filter); - - // Closes the associated interface. Puts this object into a state where it can - // be rebound. - void Close(); - - // Similar to the method above, but also specifies a disconnect reason. - void CloseWithReason(uint32_t custom_reason, const std::string& description); - - // Sets an error handler that will be called if a connection error occurs. - // - // This method may only be called after this AssociatedBinding has been bound - // to a message pipe. The error handler will be reset when this - // AssociatedBinding is unbound or closed. - void set_connection_error_handler(const base::Closure& error_handler); - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler); - - // Indicates whether the associated binding has been completed. - bool is_bound() const { return !!endpoint_client_; } - - // Sends a message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting(); - - protected: - void BindImpl(ScopedInterfaceEndpointHandle handle, - MessageReceiverWithResponderStatus* receiver, - std::unique_ptr payload_validator, - bool expect_sync_requests, - scoped_refptr runner, - uint32_t interface_version); - - std::unique_ptr endpoint_client_; -}; - -// Represents the implementation side of an associated interface. It is similar -// to Binding, except that it doesn't own a message pipe handle. -// -// When you bind this class to a request, optionally you can specify a -// base::SingleThreadTaskRunner. This task runner must belong to the same -// thread. It will be used to dispatch incoming method calls and connection -// error notification. It is useful when you attach multiple task runners to a -// single thread for the purposes of task scheduling. Please note that incoming -// synchrounous method calls may not be run from this task runner, when they -// reenter outgoing synchrounous calls on the same thread. -template > -class AssociatedBinding : public AssociatedBindingBase { - public: - using ImplPointerType = typename ImplRefTraits::PointerType; - - // Constructs an incomplete associated binding that will use the - // implementation |impl|. It may be completed with a subsequent call to the - // |Bind| method. Does not take ownership of |impl|, which must outlive this - // object. - explicit AssociatedBinding(ImplPointerType impl) { stub_.set_sink(impl); } - - // Constructs a completed associated binding of |impl|. The output |ptr_info| - // should be sent by another interface. |impl| must outlive this object. - AssociatedBinding(ImplPointerType impl, - AssociatedInterfacePtrInfo* ptr_info, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) - : AssociatedBinding(std::move(impl)) { - Bind(ptr_info, std::move(runner)); - } - - // Constructs a completed associated binding of |impl|. |impl| must outlive - // the binding. - AssociatedBinding(ImplPointerType impl, - AssociatedInterfaceRequest request, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) - : AssociatedBinding(std::move(impl)) { - Bind(std::move(request), std::move(runner)); - } - - ~AssociatedBinding() {} - - // Creates an associated inteface and sets up this object as the - // implementation side. The output |ptr_info| should be sent by another - // interface. - void Bind(AssociatedInterfacePtrInfo* ptr_info, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - auto request = MakeRequest(ptr_info); - ptr_info->set_version(Interface::Version_); - Bind(std::move(request), std::move(runner)); - } - - // Sets up this object as the implementation side of an associated interface. - void Bind(AssociatedInterfaceRequest request, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - BindImpl(request.PassHandle(), &stub_, - base::WrapUnique(new typename Interface::RequestValidator_()), - Interface::HasSyncMethods_, std::move(runner), - Interface::Version_); - } - - // Unbinds and returns the associated interface request so it can be - // used in another context, such as on another thread or with a different - // implementation. Puts this object into a state where it can be rebound. - AssociatedInterfaceRequest Unbind() { - DCHECK(endpoint_client_); - - AssociatedInterfaceRequest request; - request.Bind(endpoint_client_->PassHandle()); - - endpoint_client_.reset(); - - return request; - } - - // Returns the interface implementation that was previously specified. - Interface* impl() { return ImplRefTraits::GetRawPointer(&stub_.sink()); } - - private: - typename Interface::template Stub_ stub_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedBinding); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_ diff --git a/mojo/public/cpp/bindings/associated_binding_set.h b/mojo/public/cpp/bindings/associated_binding_set.h deleted file mode 100644 index 59600c6..0000000 --- a/mojo/public/cpp/bindings/associated_binding_set.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_SET_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_SET_H_ - -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/binding_set.h" - -namespace mojo { - -template -struct BindingSetTraits> { - using ProxyType = AssociatedInterfacePtr; - using RequestType = AssociatedInterfaceRequest; - using BindingType = AssociatedBinding; - using ImplPointerType = typename BindingType::ImplPointerType; -}; - -template -using AssociatedBindingSet = - BindingSetBase, ContextType>; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_SET_H_ diff --git a/mojo/public/cpp/bindings/associated_group.h b/mojo/public/cpp/bindings/associated_group.h deleted file mode 100644 index 14e78ec..0000000 --- a/mojo/public/cpp/bindings/associated_group.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_ - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -class AssociatedGroupController; - -// AssociatedGroup refers to all the interface endpoints running at one end of a -// message pipe. -// It is thread safe and cheap to make copies. -class MOJO_CPP_BINDINGS_EXPORT AssociatedGroup { - public: - AssociatedGroup(); - - explicit AssociatedGroup(scoped_refptr controller); - - explicit AssociatedGroup(const ScopedInterfaceEndpointHandle& handle); - - AssociatedGroup(const AssociatedGroup& other); - - ~AssociatedGroup(); - - AssociatedGroup& operator=(const AssociatedGroup& other); - - // The return value of this getter if this object is initialized with a - // ScopedInterfaceEndpointHandle: - // - If the handle is invalid, the return value will always be null. - // - If the handle is valid and non-pending, the return value will be - // non-null and remain unchanged even if the handle is later reset. - // - If the handle is pending asssociation, the return value will initially - // be null, change to non-null when/if the handle is associated, and - // remain unchanged ever since. - AssociatedGroupController* GetController(); - - private: - base::Callback controller_getter_; - scoped_refptr controller_; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_H_ diff --git a/mojo/public/cpp/bindings/associated_group_controller.h b/mojo/public/cpp/bindings/associated_group_controller.h deleted file mode 100644 index d33c277..0000000 --- a/mojo/public/cpp/bindings/associated_group_controller.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_CONTROLLER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_CONTROLLER_H_ - -#include - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -class InterfaceEndpointClient; -class InterfaceEndpointController; - -// An internal interface used to manage endpoints within an associated group, -// which corresponds to one end of a message pipe. -class MOJO_CPP_BINDINGS_EXPORT AssociatedGroupController - : public base::RefCountedThreadSafe { - public: - // Associates an interface with this AssociatedGroupController's message pipe. - // It takes ownership of |handle_to_send| and returns an interface ID that - // could be sent by any endpoints within the same associated group. - // If |handle_to_send| is not in pending association state, it returns - // kInvalidInterfaceId. Otherwise, the peer handle of |handle_to_send| joins - // the associated group and is no longer pending. - virtual InterfaceId AssociateInterface( - ScopedInterfaceEndpointHandle handle_to_send) = 0; - - // Creates an interface endpoint handle from a given interface ID. The handle - // joins this associated group. - // Typically, this method is used to (1) create an endpoint handle for the - // master interface; or (2) create an endpoint handle on receiving an - // interface ID from the message pipe. - // - // On failure, the method returns an invalid handle. Usually that is because - // the ID has already been used to create a handle. - virtual ScopedInterfaceEndpointHandle CreateLocalEndpointHandle( - InterfaceId id) = 0; - - // Closes an interface endpoint handle. - virtual void CloseEndpointHandle( - InterfaceId id, - const base::Optional& reason) = 0; - - // Attaches a client to the specified endpoint to send and receive messages. - // The returned object is still owned by the controller. It must only be used - // on the same thread as this call, and only before the client is detached - // using DetachEndpointClient(). - virtual InterfaceEndpointController* AttachEndpointClient( - const ScopedInterfaceEndpointHandle& handle, - InterfaceEndpointClient* endpoint_client, - scoped_refptr runner) = 0; - - // Detaches the client attached to the specified endpoint. It must be called - // on the same thread as the corresponding AttachEndpointClient() call. - virtual void DetachEndpointClient( - const ScopedInterfaceEndpointHandle& handle) = 0; - - // Raises an error on the underlying message pipe. It disconnects the pipe - // and notifies all interfaces running on this pipe. - virtual void RaiseError() = 0; - - protected: - friend class base::RefCountedThreadSafe; - - // Creates a new ScopedInterfaceEndpointHandle within this associated group. - ScopedInterfaceEndpointHandle CreateScopedInterfaceEndpointHandle( - InterfaceId id); - - // Notifies that the interface represented by |handle_to_send| and its peer - // has been associated with this AssociatedGroupController's message pipe, and - // |handle_to_send|'s peer has joined this associated group. (Note: it is the - // peer who has joined the associated group; |handle_to_send| will be sent to - // the remote side.) - // Returns false if |handle_to_send|'s peer has closed. - bool NotifyAssociation(ScopedInterfaceEndpointHandle* handle_to_send, - InterfaceId id); - - virtual ~AssociatedGroupController(); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_GROUP_CONTROLLER_H_ diff --git a/mojo/public/cpp/bindings/associated_interface_ptr.h b/mojo/public/cpp/bindings/associated_interface_ptr.h deleted file mode 100644 index 8806a3e..0000000 --- a/mojo/public/cpp/bindings/associated_interface_ptr.h +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ - -#include - -#include -#include - -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h" -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { - -// Represents the client side of an associated interface. It is similar to -// InterfacePtr, except that it doesn't own a message pipe handle. -template -class AssociatedInterfacePtr { - public: - using InterfaceType = Interface; - using PtrInfoType = AssociatedInterfacePtrInfo; - - // Constructs an unbound AssociatedInterfacePtr. - AssociatedInterfacePtr() {} - AssociatedInterfacePtr(decltype(nullptr)) {} - - AssociatedInterfacePtr(AssociatedInterfacePtr&& other) { - internal_state_.Swap(&other.internal_state_); - } - - AssociatedInterfacePtr& operator=(AssociatedInterfacePtr&& other) { - reset(); - internal_state_.Swap(&other.internal_state_); - return *this; - } - - // Assigning nullptr to this class causes it to closes the associated - // interface (if any) and returns the pointer to the unbound state. - AssociatedInterfacePtr& operator=(decltype(nullptr)) { - reset(); - return *this; - } - - ~AssociatedInterfacePtr() {} - - // Sets up this object as the client side of an associated interface. - // Calling with an invalid |info| has the same effect as reset(). In this - // case, the AssociatedInterfacePtr is not considered as bound. - // - // |runner| must belong to the same thread. It will be used to dispatch all - // callbacks and connection error notification. It is useful when you attach - // multiple task runners to a single thread for the purposes of task - // scheduling. - // - // NOTE: The corresponding AssociatedInterfaceRequest must be sent over - // another interface before using this object to make calls. Please see the - // comments of MakeRequest(AssociatedInterfacePtr*) for more - // details. - void Bind(AssociatedInterfacePtrInfo info, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - reset(); - - if (info.is_valid()) - internal_state_.Bind(std::move(info), std::move(runner)); - } - - bool is_bound() const { return internal_state_.is_bound(); } - - Interface* get() const { return internal_state_.instance(); } - - // Functions like a pointer to Interface. Must already be bound. - Interface* operator->() const { return get(); } - Interface& operator*() const { return *get(); } - - // Returns the version number of the interface that the remote side supports. - uint32_t version() const { return internal_state_.version(); } - - // Queries the max version that the remote side supports. On completion, the - // result will be returned as the input of |callback|. The version number of - // this object will also be updated. - void QueryVersion(const base::Callback& callback) { - internal_state_.QueryVersion(callback); - } - - // If the remote side doesn't support the specified version, it will close the - // associated interface asynchronously. This does nothing if it's already - // known that the remote side supports the specified version, i.e., if - // |version <= this->version()|. - // - // After calling RequireVersion() with a version not supported by the remote - // side, all subsequent calls to interface methods will be ignored. - void RequireVersion(uint32_t version) { - internal_state_.RequireVersion(version); - } - - // Sends a message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting() { internal_state_.FlushForTesting(); } - - // Closes the associated interface (if any) and returns the pointer to the - // unbound state. - void reset() { - State doomed; - internal_state_.Swap(&doomed); - } - - // Similar to the method above, but also specifies a disconnect reason. - void ResetWithReason(uint32_t custom_reason, const std::string& description) { - if (internal_state_.is_bound()) - internal_state_.CloseWithReason(custom_reason, description); - reset(); - } - - // Indicates whether an error has been encountered. If true, method calls made - // on this interface will be dropped (and may already have been dropped). - bool encountered_error() const { return internal_state_.encountered_error(); } - - // Registers a handler to receive error notifications. - // - // This method may only be called after the AssociatedInterfacePtr has been - // bound. - void set_connection_error_handler(const base::Closure& error_handler) { - internal_state_.set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - internal_state_.set_connection_error_with_reason_handler(error_handler); - } - - // Unbinds and returns the associated interface pointer information which - // could be used to setup an AssociatedInterfacePtr again. This method may be - // used to move the proxy to a different thread. - // - // It is an error to call PassInterface() while there are pending responses. - // TODO: fix this restriction, it's not always obvious when there is a - // pending response. - AssociatedInterfacePtrInfo PassInterface() { - DCHECK(!internal_state_.has_pending_callbacks()); - State state; - internal_state_.Swap(&state); - - return state.PassInterface(); - } - - // DO NOT USE. Exposed only for internal use and for testing. - internal::AssociatedInterfacePtrState* internal_state() { - return &internal_state_; - } - - // Allow AssociatedInterfacePtr<> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - private: - // TODO(dcheng): Use an explicit conversion operator. - typedef internal::AssociatedInterfacePtrState - AssociatedInterfacePtr::*Testable; - - public: - operator Testable() const { - return internal_state_.is_bound() ? &AssociatedInterfacePtr::internal_state_ - : nullptr; - } - - private: - // Forbid the == and != operators explicitly, otherwise AssociatedInterfacePtr - // will be converted to Testable to do == or != comparison. - template - bool operator==(const AssociatedInterfacePtr& other) const = delete; - template - bool operator!=(const AssociatedInterfacePtr& other) const = delete; - - typedef internal::AssociatedInterfacePtrState State; - mutable State internal_state_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtr); -}; - -// Creates an associated interface. The returned request is supposed to be sent -// over another interface (either associated or non-associated). -// -// NOTE: |ptr| must NOT be used to make calls before the request is sent. -// Violating that will lead to crash. On the other hand, as soon as the request -// is sent, |ptr| is usable. There is no need to wait until the request is bound -// to an implementation at the remote side. -template -AssociatedInterfaceRequest MakeRequest( - AssociatedInterfacePtr* ptr, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - AssociatedInterfacePtrInfo ptr_info; - auto request = MakeRequest(&ptr_info); - ptr->Bind(std::move(ptr_info), std::move(runner)); - return request; -} - -// Creates an associated interface. One of the two endpoints is supposed to be -// sent over another interface (either associated or non-associated); while the -// other is used locally. -// -// NOTE: If |ptr_info| is used locally and bound to an AssociatedInterfacePtr, -// the interface pointer must NOT be used to make calls before the request is -// sent. Please see NOTE of the previous function for more details. -template -AssociatedInterfaceRequest MakeRequest( - AssociatedInterfacePtrInfo* ptr_info) { - ScopedInterfaceEndpointHandle handle0; - ScopedInterfaceEndpointHandle handle1; - ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&handle0, - &handle1); - - ptr_info->set_handle(std::move(handle0)); - ptr_info->set_version(0); - - AssociatedInterfaceRequest request; - request.Bind(std::move(handle1)); - return request; -} - -// Like MakeRequest() above, but it creates a dedicated message pipe. The -// returned request can be bound directly to an implementation, without being -// first passed through a message pipe endpoint. -// -// This function has two main uses: -// -// * In testing, where the returned request is bound to e.g. a mock and there -// are no other interfaces involved. -// -// * When discarding messages sent on an interface, which can be done by -// discarding the returned request. -template -AssociatedInterfaceRequest MakeIsolatedRequest( - AssociatedInterfacePtr* ptr) { - MessagePipe pipe; - scoped_refptr router0 = - new internal::MultiplexRouter(std::move(pipe.handle0), - internal::MultiplexRouter::MULTI_INTERFACE, - false, base::ThreadTaskRunnerHandle::Get()); - scoped_refptr router1 = - new internal::MultiplexRouter(std::move(pipe.handle1), - internal::MultiplexRouter::MULTI_INTERFACE, - true, base::ThreadTaskRunnerHandle::Get()); - - ScopedInterfaceEndpointHandle endpoint0, endpoint1; - ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&endpoint0, - &endpoint1); - InterfaceId id = router1->AssociateInterface(std::move(endpoint0)); - endpoint0 = router0->CreateLocalEndpointHandle(id); - - ptr->Bind(AssociatedInterfacePtrInfo(std::move(endpoint0), - Interface::Version_)); - - AssociatedInterfaceRequest request; - request.Bind(std::move(endpoint1)); - return request; -} - -// |handle| is supposed to be the request of an associated interface. This -// method associates the interface with a dedicated, disconnected message pipe. -// That way, the corresponding associated interface pointer of |handle| can -// safely make calls (although those calls are silently dropped). -MOJO_CPP_BINDINGS_EXPORT void GetIsolatedInterface( - ScopedInterfaceEndpointHandle handle); - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ diff --git a/mojo/public/cpp/bindings/associated_interface_ptr_info.h b/mojo/public/cpp/bindings/associated_interface_ptr_info.h deleted file mode 100644 index 3c6ca54..0000000 --- a/mojo/public/cpp/bindings/associated_interface_ptr_info.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ - -#include -#include - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -// AssociatedInterfacePtrInfo stores necessary information to construct an -// associated interface pointer. It is similar to InterfacePtrInfo except that -// it doesn't own a message pipe handle. -template -class AssociatedInterfacePtrInfo { - public: - AssociatedInterfacePtrInfo() : version_(0u) {} - AssociatedInterfacePtrInfo(std::nullptr_t) : version_(0u) {} - - AssociatedInterfacePtrInfo(AssociatedInterfacePtrInfo&& other) - : handle_(std::move(other.handle_)), version_(other.version_) { - other.version_ = 0u; - } - - AssociatedInterfacePtrInfo(ScopedInterfaceEndpointHandle handle, - uint32_t version) - : handle_(std::move(handle)), version_(version) {} - - ~AssociatedInterfacePtrInfo() {} - - AssociatedInterfacePtrInfo& operator=(AssociatedInterfacePtrInfo&& other) { - if (this != &other) { - handle_ = std::move(other.handle_); - version_ = other.version_; - other.version_ = 0u; - } - - return *this; - } - - bool is_valid() const { return handle_.is_valid(); } - - ScopedInterfaceEndpointHandle PassHandle() { - return std::move(handle_); - } - const ScopedInterfaceEndpointHandle& handle() const { return handle_; } - void set_handle(ScopedInterfaceEndpointHandle handle) { - handle_ = std::move(handle); - } - - uint32_t version() const { return version_; } - void set_version(uint32_t version) { version_ = version; } - - bool Equals(const AssociatedInterfacePtrInfo& other) const { - if (this == &other) - return true; - - // Now that the two refer to different objects, they are equivalent if - // and only if they are both invalid. - return !is_valid() && !other.is_valid(); - } - - private: - ScopedInterfaceEndpointHandle handle_; - uint32_t version_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrInfo); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_INFO_H_ diff --git a/mojo/public/cpp/bindings/associated_interface_request.h b/mojo/public/cpp/bindings/associated_interface_request.h deleted file mode 100644 index c37636c..0000000 --- a/mojo/public/cpp/bindings/associated_interface_request.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ - -#include -#include - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -// AssociatedInterfaceRequest represents an associated interface request. It is -// similar to InterfaceRequest except that it doesn't own a message pipe handle. -template -class AssociatedInterfaceRequest { - public: - // Constructs an empty AssociatedInterfaceRequest, representing that the - // client is not requesting an implementation of Interface. - AssociatedInterfaceRequest() {} - AssociatedInterfaceRequest(decltype(nullptr)) {} - - // Takes the interface endpoint handle from another - // AssociatedInterfaceRequest. - AssociatedInterfaceRequest(AssociatedInterfaceRequest&& other) { - handle_ = std::move(other.handle_); - } - AssociatedInterfaceRequest& operator=(AssociatedInterfaceRequest&& other) { - if (this != &other) - handle_ = std::move(other.handle_); - return *this; - } - - // Assigning to nullptr resets the AssociatedInterfaceRequest to an empty - // state, closing the interface endpoint handle currently bound to it (if - // any). - AssociatedInterfaceRequest& operator=(decltype(nullptr)) { - handle_.reset(); - return *this; - } - - // Indicates whether the request currently contains a valid interface endpoint - // handle. - bool is_pending() const { return handle_.is_valid(); } - - void Bind(ScopedInterfaceEndpointHandle handle) { - handle_ = std::move(handle); - } - - ScopedInterfaceEndpointHandle PassHandle() { - return std::move(handle_); - } - - const ScopedInterfaceEndpointHandle& handle() const { return handle_; } - - bool Equals(const AssociatedInterfaceRequest& other) const { - if (this == &other) - return true; - - // Now that the two refer to different objects, they are equivalent if - // and only if they are both invalid. - return !is_pending() && !other.is_pending(); - } - - void ResetWithReason(uint32_t custom_reason, const std::string& description) { - handle_.ResetWithReason(custom_reason, description); - } - - private: - ScopedInterfaceEndpointHandle handle_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedInterfaceRequest); -}; - -// Makes an AssociatedInterfaceRequest bound to the specified associated -// endpoint. -template -AssociatedInterfaceRequest MakeAssociatedRequest( - ScopedInterfaceEndpointHandle handle) { - AssociatedInterfaceRequest request; - request.Bind(std::move(handle)); - return request; -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_REQUEST_H_ diff --git a/mojo/public/cpp/bindings/binding.h b/mojo/public/cpp/bindings/binding.h deleted file mode 100644 index 88d2f4b..0000000 --- a/mojo/public/cpp/bindings/binding.h +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_ - -#include -#include - -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/lib/binding_state.h" -#include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -class MessageReceiver; - -// Represents the binding of an interface implementation to a message pipe. -// When the |Binding| object is destroyed, the binding between the message pipe -// and the interface is torn down and the message pipe is closed, leaving the -// interface implementation in an unbound state. -// -// Example: -// -// #include "foo.mojom.h" -// -// class FooImpl : public Foo { -// public: -// explicit FooImpl(InterfaceRequest request) -// : binding_(this, std::move(request)) {} -// -// // Foo implementation here. -// -// private: -// Binding binding_; -// }; -// -// class MyFooFactory : public InterfaceFactory { -// public: -// void Create(..., InterfaceRequest request) override { -// auto f = new FooImpl(std::move(request)); -// // Do something to manage the lifetime of |f|. Use StrongBinding<> to -// // delete FooImpl on connection errors. -// } -// }; -// -// This class is thread hostile while bound to a message pipe. All calls to this -// class must be from the thread that bound it. The interface implementation's -// methods will be called from the thread that bound this. If a Binding is not -// bound to a message pipe, it may be bound or destroyed on any thread. -// -// When you bind this class to a message pipe, optionally you can specify a -// base::SingleThreadTaskRunner. This task runner must belong to the same -// thread. It will be used to dispatch incoming method calls and connection -// error notification. It is useful when you attach multiple task runners to a -// single thread for the purposes of task scheduling. Please note that incoming -// synchrounous method calls may not be run from this task runner, when they -// reenter outgoing synchrounous calls on the same thread. -template > -class Binding { - public: - using ImplPointerType = typename ImplRefTraits::PointerType; - - // 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. - explicit Binding(ImplPointerType impl) : internal_state_(std::move(impl)) {} - - // Constructs a completed binding of message pipe |handle| to implementation - // |impl|. Does not take ownership of |impl|, which must outlive the binding. - Binding(ImplPointerType impl, - ScopedMessagePipeHandle handle, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) - : Binding(std::move(impl)) { - Bind(std::move(handle), std::move(runner)); - } - - // Constructs a completed binding of |impl| to a new message pipe, passing the - // client end to |ptr|, which takes ownership of it. The caller is expected to - // pass |ptr| on to the client of the service. Does not take ownership of any - // of the parameters. |impl| must outlive the binding. |ptr| only needs to - // last until the constructor returns. - Binding(ImplPointerType impl, - InterfacePtr* ptr, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) - : Binding(std::move(impl)) { - Bind(ptr, std::move(runner)); - } - - // Constructs a completed binding of |impl| to the message pipe endpoint in - // |request|, taking ownership of the endpoint. Does not take ownership of - // |impl|, which must outlive the binding. - Binding(ImplPointerType impl, - InterfaceRequest request, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) - : Binding(std::move(impl)) { - Bind(request.PassMessagePipe(), std::move(runner)); - } - - // Tears down the binding, closing the message pipe and leaving the interface - // implementation unbound. - ~Binding() {} - - // Returns an InterfacePtr bound to one end of a pipe whose other end is - // bound to |this|. - InterfacePtr CreateInterfacePtrAndBind( - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - InterfacePtr interface_ptr; - Bind(&interface_ptr, std::move(runner)); - return interface_ptr; - } - - // Completes a binding that was constructed with only an interface - // implementation. Takes ownership of |handle| and binds it to the previously - // specified implementation. - void Bind(ScopedMessagePipeHandle handle, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - internal_state_.Bind(std::move(handle), std::move(runner)); - } - - // Completes a binding that was constructed with only an interface - // implementation by creating a new message pipe, binding one end of it to the - // previously specified implementation, and passing the other to |ptr|, which - // takes ownership of it. The caller is expected to pass |ptr| on to the - // eventual client of the service. Does not take ownership of |ptr|. - void Bind(InterfacePtr* ptr, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - MessagePipe pipe; - ptr->Bind(InterfacePtrInfo(std::move(pipe.handle0), - Interface::Version_), - runner); - Bind(std::move(pipe.handle1), std::move(runner)); - } - - // Completes a binding that was constructed with only an interface - // implementation by removing the message pipe endpoint from |request| and - // binding it to the previously specified implementation. - void Bind(InterfaceRequest request, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - Bind(request.PassMessagePipe(), std::move(runner)); - } - - // Adds a message filter to be notified of each incoming message before - // dispatch. If a filter returns |false| from Accept(), the message is not - // dispatched and the pipe is closed. Filters cannot be removed. - void AddFilter(std::unique_ptr filter) { - DCHECK(is_bound()); - internal_state_.AddFilter(std::move(filter)); - } - - // Whether there are any associated interfaces running on the pipe currently. - bool HasAssociatedInterfaces() const { - return internal_state_.HasAssociatedInterfaces(); - } - - // Stops processing incoming messages until - // ResumeIncomingMethodCallProcessing(), or WaitForIncomingMethodCall(). - // Outgoing messages are still sent. - // - // No errors are detected on the message pipe while paused. - // - // This method may only be called if the object has been bound to a message - // pipe and there are no associated interfaces running. - void PauseIncomingMethodCallProcessing() { - CHECK(!HasAssociatedInterfaces()); - internal_state_.PauseIncomingMethodCallProcessing(); - } - void ResumeIncomingMethodCallProcessing() { - internal_state_.ResumeIncomingMethodCallProcessing(); - } - - // Blocks the calling thread until either a call arrives on the previously - // bound message pipe, the deadline is exceeded, or an error occurs. Returns - // true if a method was successfully read and dispatched. - // - // This method may only be called if the object has been bound to a message - // pipe. This returns once a message is received either on the master - // interface or any associated interfaces. - bool WaitForIncomingMethodCall( - MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) { - return internal_state_.WaitForIncomingMethodCall(deadline); - } - - // Closes the message pipe that was previously bound. Put this object into a - // state where it can be rebound to a new pipe. - void Close() { internal_state_.Close(); } - - // Similar to the method above, but also specifies a disconnect reason. - void CloseWithReason(uint32_t custom_reason, const std::string& description) { - internal_state_.CloseWithReason(custom_reason, description); - } - - // Unbinds the underlying pipe from this binding and returns it so it can be - // used in another context, such as on another thread or with a different - // implementation. Put this object into a state where it can be rebound to a - // new pipe. - // - // This method may only be called if the object has been bound to a message - // pipe and there are no associated interfaces running. - // - // TODO(yzshen): For now, users need to make sure there is no one holding - // on to associated interface endpoint handles at both sides of the - // message pipe in order to call this method. We need a way to forcefully - // invalidate associated interface endpoint handles. - InterfaceRequest Unbind() { - CHECK(!HasAssociatedInterfaces()); - return internal_state_.Unbind(); - } - - // Sets an error handler that will be called if a connection error occurs on - // the bound message pipe. - // - // This method may only be called after this Binding has been bound to a - // message pipe. The error handler will be reset when this Binding is unbound - // or closed. - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(is_bound()); - internal_state_.set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(is_bound()); - internal_state_.set_connection_error_with_reason_handler(error_handler); - } - - // Returns the interface implementation that was previously specified. Caller - // does not take ownership. - Interface* impl() { return internal_state_.impl(); } - - // 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_state_.is_bound(); } - - // Returns the value of the handle currently bound to this Binding which can - // be used to make explicit Wait/WaitMany calls. Requires that the Binding be - // bound. Ownership of the handle is retained by the Binding, it is not - // transferred to the caller. - MessagePipeHandle handle() const { return internal_state_.handle(); } - - // Sends a no-op message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting() { internal_state_.FlushForTesting(); } - - // Exposed for testing, should not generally be used. - void EnableTestingMode() { internal_state_.EnableTestingMode(); } - - private: - internal::BindingState internal_state_; - - DISALLOW_COPY_AND_ASSIGN(Binding); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_ diff --git a/mojo/public/cpp/bindings/binding_set.h b/mojo/public/cpp/bindings/binding_set.h deleted file mode 100644 index 919f9c0..0000000 --- a/mojo/public/cpp/bindings/binding_set.h +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ - -#include -#include - -#include "base/bind.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -template -struct BindingSetTraits; - -template -struct BindingSetTraits> { - using ProxyType = InterfacePtr; - using RequestType = InterfaceRequest; - using BindingType = Binding; - using ImplPointerType = typename BindingType::ImplPointerType; - - static RequestType MakeRequest(ProxyType* proxy) { - return mojo::MakeRequest(proxy); - } -}; - -using BindingId = size_t; - -template -struct BindingSetContextTraits { - using Type = ContextType; - - static constexpr bool SupportsContext() { return true; } -}; - -template <> -struct BindingSetContextTraits { - // NOTE: This choice of Type only matters insofar as it affects the size of - // the |context_| field of a BindingSetBase::Entry with void context. The - // context value is never used in this case. - using Type = bool; - - static constexpr bool SupportsContext() { return false; } -}; - -// Generic definition used for BindingSet and AssociatedBindingSet to own a -// collection of bindings which point to the same implementation. -// -// If |ContextType| is non-void, then every added binding must include a context -// value of that type, and |dispatch_context()| will return that value during -// the extent of any message dispatch targeting that specific binding. -template -class BindingSetBase { - public: - using ContextTraits = BindingSetContextTraits; - using Context = typename ContextTraits::Type; - using PreDispatchCallback = base::Callback; - using Traits = BindingSetTraits; - using ProxyType = typename Traits::ProxyType; - using RequestType = typename Traits::RequestType; - using ImplPointerType = typename Traits::ImplPointerType; - - BindingSetBase() {} - - void set_connection_error_handler(const base::Closure& error_handler) { - error_handler_ = error_handler; - error_with_reason_handler_.Reset(); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - error_with_reason_handler_ = error_handler; - error_handler_.Reset(); - } - - // Sets a callback to be invoked immediately before dispatching any message or - // error received by any of the bindings in the set. This may only be used - // with a non-void |ContextType|. - void set_pre_dispatch_handler(const PreDispatchCallback& handler) { - static_assert(ContextTraits::SupportsContext(), - "Pre-dispatch handler usage requires non-void context type."); - pre_dispatch_handler_ = handler; - } - - // Adds a new binding to the set which binds |request| to |impl| with no - // additional context. - BindingId AddBinding(ImplPointerType impl, RequestType request) { - static_assert(!ContextTraits::SupportsContext(), - "Context value required for non-void context type."); - return AddBindingImpl(std::move(impl), std::move(request), false); - } - - // Adds a new binding associated with |context|. - BindingId AddBinding(ImplPointerType impl, - RequestType request, - Context context) { - static_assert(ContextTraits::SupportsContext(), - "Context value unsupported for void context type."); - return AddBindingImpl(std::move(impl), std::move(request), - std::move(context)); - } - - // Removes a binding from the set. Note that this is safe to call even if the - // binding corresponding to |id| has already been removed. - // - // Returns |true| if the binding was removed and |false| if it didn't exist. - bool RemoveBinding(BindingId id) { - auto it = bindings_.find(id); - if (it == bindings_.end()) - return false; - bindings_.erase(it); - return true; - } - - // Returns a proxy bound to one end of a pipe whose other end is bound to - // |this|. If |id_storage| is not null, |*id_storage| will be set to the ID - // of the added binding. - ProxyType CreateInterfacePtrAndBind(ImplPointerType impl, - BindingId* id_storage = nullptr) { - ProxyType proxy; - BindingId id = AddBinding(std::move(impl), Traits::MakeRequest(&proxy)); - if (id_storage) - *id_storage = id; - return proxy; - } - - void CloseAllBindings() { bindings_.clear(); } - - bool empty() const { return bindings_.empty(); } - - // Implementations may call this when processing a dispatched message or - // error. During the extent of message or error dispatch, this will return the - // context associated with the specific binding which received the message or - // error. Use AddBinding() to associated a context with a specific binding. - const Context& dispatch_context() const { - static_assert(ContextTraits::SupportsContext(), - "dispatch_context() requires non-void context type."); - DCHECK(dispatch_context_); - return *dispatch_context_; - } - - void FlushForTesting() { - for (auto& binding : bindings_) - binding.second->FlushForTesting(); - } - - private: - friend class Entry; - - class Entry { - public: - Entry(ImplPointerType impl, - RequestType request, - BindingSetBase* binding_set, - BindingId binding_id, - Context context) - : binding_(std::move(impl), std::move(request)), - binding_set_(binding_set), - binding_id_(binding_id), - context_(std::move(context)) { - if (ContextTraits::SupportsContext()) - binding_.AddFilter(base::MakeUnique(this)); - binding_.set_connection_error_with_reason_handler( - base::Bind(&Entry::OnConnectionError, base::Unretained(this))); - } - - void FlushForTesting() { binding_.FlushForTesting(); } - - private: - class DispatchFilter : public MessageReceiver { - public: - explicit DispatchFilter(Entry* entry) : entry_(entry) {} - ~DispatchFilter() override {} - - private: - // MessageReceiver: - bool Accept(Message* message) override { - entry_->WillDispatch(); - return true; - } - - Entry* entry_; - - DISALLOW_COPY_AND_ASSIGN(DispatchFilter); - }; - - void WillDispatch() { - DCHECK(ContextTraits::SupportsContext()); - binding_set_->SetDispatchContext(&context_); - } - - void OnConnectionError(uint32_t custom_reason, - const std::string& description) { - if (ContextTraits::SupportsContext()) - WillDispatch(); - binding_set_->OnConnectionError(binding_id_, custom_reason, description); - } - - BindingType binding_; - BindingSetBase* const binding_set_; - const BindingId binding_id_; - Context const context_; - - DISALLOW_COPY_AND_ASSIGN(Entry); - }; - - void SetDispatchContext(const Context* context) { - DCHECK(ContextTraits::SupportsContext()); - dispatch_context_ = context; - if (!pre_dispatch_handler_.is_null()) - pre_dispatch_handler_.Run(*context); - } - - BindingId AddBindingImpl(ImplPointerType impl, - RequestType request, - Context context) { - BindingId id = next_binding_id_++; - DCHECK_GE(next_binding_id_, 0u); - auto entry = base::MakeUnique(std::move(impl), std::move(request), - this, id, std::move(context)); - bindings_.insert(std::make_pair(id, std::move(entry))); - return id; - } - - void OnConnectionError(BindingId id, - uint32_t custom_reason, - const std::string& description) { - auto it = bindings_.find(id); - DCHECK(it != bindings_.end()); - - // We keep the Entry alive throughout error dispatch. - std::unique_ptr entry = std::move(it->second); - bindings_.erase(it); - - if (!error_handler_.is_null()) - error_handler_.Run(); - else if (!error_with_reason_handler_.is_null()) - error_with_reason_handler_.Run(custom_reason, description); - } - - base::Closure error_handler_; - ConnectionErrorWithReasonCallback error_with_reason_handler_; - PreDispatchCallback pre_dispatch_handler_; - BindingId next_binding_id_ = 0; - std::map> bindings_; - const Context* dispatch_context_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(BindingSetBase); -}; - -template -using BindingSet = BindingSetBase, ContextType>; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_SET_H_ diff --git a/mojo/public/cpp/bindings/bindings_export.h b/mojo/public/cpp/bindings/bindings_export.h deleted file mode 100644 index 9fd7a27..0000000 --- a/mojo/public/cpp/bindings/bindings_export.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_BINDINGS_EXPORT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_BINDINGS_EXPORT_H_ - -#if defined(COMPONENT_BUILD) - -#if defined(WIN32) - -#if defined(MOJO_CPP_BINDINGS_IMPLEMENTATION) -#define MOJO_CPP_BINDINGS_EXPORT __declspec(dllexport) -#else -#define MOJO_CPP_BINDINGS_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(MOJO_CPP_BINDINGS_IMPLEMENTATION) -#define MOJO_CPP_BINDINGS_EXPORT __attribute((visibility("default"))) -#else -#define MOJO_CPP_BINDINGS_EXPORT -#endif - -#endif // defined(WIN32) - -#else // !defined(COMPONENT_BUILD) - -#define MOJO_CPP_BINDINGS_EXPORT - -#endif // defined(COMPONENT_BUILD) - -#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDINGS_EXPORT_H_ diff --git a/mojo/public/cpp/bindings/clone_traits.h b/mojo/public/cpp/bindings/clone_traits.h deleted file mode 100644 index 203ab34..0000000 --- a/mojo/public/cpp/bindings/clone_traits.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_CLONE_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_CLONE_TRAITS_H_ - -#include -#include -#include - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" - -namespace mojo { - -template -struct HasCloneMethod { - template - static char Test(decltype(&U::Clone)); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - internal::EnsureTypeIsComplete check_t_; -}; - -template ::value> -struct CloneTraits; - -template -T Clone(const T& input); - -template -struct CloneTraits { - static T Clone(const T& input) { return input.Clone(); } -}; - -template -struct CloneTraits { - static T Clone(const T& input) { return input; } -}; - -template -struct CloneTraits, false> { - static base::Optional Clone(const base::Optional& input) { - if (!input) - return base::nullopt; - - return base::Optional(mojo::Clone(*input)); - } -}; - -template -struct CloneTraits, false> { - static std::vector Clone(const std::vector& input) { - std::vector result; - result.reserve(input.size()); - for (const auto& element : input) - result.push_back(mojo::Clone(element)); - - return result; - } -}; - -template -struct CloneTraits, false> { - static std::unordered_map Clone(const std::unordered_map& input) { - std::unordered_map result; - for (const auto& element : input) { - result.insert(std::make_pair(mojo::Clone(element.first), - mojo::Clone(element.second))); - } - return result; - } -}; - -template -T Clone(const T& input) { - return CloneTraits::Clone(input); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_CLONE_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/connection_error_callback.h b/mojo/public/cpp/bindings/connection_error_callback.h deleted file mode 100644 index 306e99e..0000000 --- a/mojo/public/cpp/bindings/connection_error_callback.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_ERROR_CALLBACK_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_ERROR_CALLBACK_H_ - -#include "base/callback.h" - -namespace mojo { - -// This callback type accepts user-defined disconnect reason and description. If -// the other side specifies a reason on closing the connection, it will be -// passed to the error handler. -using ConnectionErrorWithReasonCallback = - base::Callback; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_CONNECTION_ERROR_CALLBACK_H_ diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h deleted file mode 100644 index cb065c1..0000000 --- a/mojo/public/cpp/bindings/connector.h +++ /dev/null @@ -1,241 +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_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ - -#include - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/sync_handle_watcher.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/simple_watcher.h" - -namespace base { -class Lock; -} - -namespace mojo { - -// The Connector class is responsible for performing read/write operations on a -// MessagePipe. It writes messages it receives through the MessageReceiver -// interface that it subclasses, and it forwards messages it reads through the -// MessageReceiver interface assigned as its incoming receiver. -// -// NOTE: -// - MessagePipe I/O is non-blocking. -// - Sending messages can be configured to be thread safe (please see comments -// of the constructor). Other than that, the object should only be accessed -// on the creating thread. -class MOJO_CPP_BINDINGS_EXPORT Connector - : NON_EXPORTED_BASE(public MessageReceiver) { - public: - enum ConnectorConfig { - // Connector::Accept() is only called from a single thread. - SINGLE_THREADED_SEND, - // Connector::Accept() is allowed to be called from multiple threads. - MULTI_THREADED_SEND - }; - - // The Connector takes ownership of |message_pipe|. - Connector(ScopedMessagePipeHandle message_pipe, - ConnectorConfig config, - scoped_refptr runner); - ~Connector() override; - - // Sets the receiver to handle messages read from the message pipe. The - // Connector will read messages from the pipe regardless of whether or not an - // incoming receiver has been set. - void set_incoming_receiver(MessageReceiver* receiver) { - DCHECK(thread_checker_.CalledOnValidThread()); - incoming_receiver_ = receiver; - } - - // Errors from incoming receivers will force the connector into an error - // state, where no more messages will be processed. This method is used - // during testing to prevent that from happening. - void set_enforce_errors_from_incoming_receiver(bool enforce) { - DCHECK(thread_checker_.CalledOnValidThread()); - enforce_errors_from_incoming_receiver_ = enforce; - } - - // Sets the error handler to receive notifications when an error is - // encountered while reading from the pipe or waiting to read from the pipe. - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(thread_checker_.CalledOnValidThread()); - connection_error_handler_ = error_handler; - } - - // Returns true if an error was encountered while reading from the pipe or - // waiting to read from the pipe. - bool encountered_error() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return error_; - } - - // Closes the pipe. The connector is put into a quiescent state. - // - // Please note that this method shouldn't be called unless it results from an - // explicit request of the user of bindings (e.g., the user sets an - // InterfacePtr to null or closes a Binding). - void CloseMessagePipe(); - - // Releases the pipe. Connector is put into a quiescent state. - ScopedMessagePipeHandle PassMessagePipe(); - - // Enters the error state. The upper layer may do this for unrecoverable - // issues such as invalid messages are received. If a connection error handler - // has been set, it will be called asynchronously. - // - // It is a no-op if the connector is already in the error state or there isn't - // a bound message pipe. Otherwise, it closes the message pipe, which notifies - // the other end and also prevents potential danger (say, the caller raises - // an error because it believes the other end is malicious). In order to - // appear to the user that the connector still binds to a message pipe, it - // creates a new message pipe, closes one end and binds to the other. - void RaiseError(); - - // Is the connector bound to a MessagePipe handle? - bool is_valid() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return message_pipe_.is_valid(); - } - - // Waits for the next message on the pipe, blocking until one arrives, - // |deadline| elapses, or an error happens. Returns |true| if a message has - // been delivered, |false| otherwise. - bool WaitForIncomingMessage(MojoDeadline deadline); - - // See Binding for details of pause/resume. - void PauseIncomingMethodCallProcessing(); - void ResumeIncomingMethodCallProcessing(); - - // MessageReceiver implementation: - bool Accept(Message* message) override; - - MessagePipeHandle handle() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return message_pipe_.get(); - } - - // Allows |message_pipe_| to be watched while others perform sync handle - // watching on the same thread. Please see comments of - // SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread(). - void AllowWokenUpBySyncWatchOnSameThread(); - - // Watches |message_pipe_| (as well as other handles registered to be watched - // together) synchronously. - // This method: - // - returns true when |should_stop| is set to true; - // - return false when any error occurs, including |message_pipe_| being - // closed. - bool SyncWatch(const bool* should_stop); - - // Whether currently the control flow is inside the sync handle watcher - // callback. - // It always returns false after CloseMessagePipe()/PassMessagePipe(). - bool during_sync_handle_watcher_callback() const { - return sync_handle_watcher_callback_count_ > 0; - } - - base::SingleThreadTaskRunner* task_runner() const { - return task_runner_.get(); - } - - // Sets the tag used by the heap profiler. - // |tag| must be a const string literal. - void SetWatcherHeapProfilerTag(const char* tag); - - private: - class ActiveDispatchTracker; - class MessageLoopNestingObserver; - - // Callback of mojo::SimpleWatcher. - void OnWatcherHandleReady(MojoResult result); - // Callback of SyncHandleWatcher. - void OnSyncHandleWatcherHandleReady(MojoResult result); - void OnHandleReadyInternal(MojoResult result); - - void WaitToReadMore(); - - // Returns false if it is impossible to receive more messages in the future. - // |this| may have been destroyed in that case. - WARN_UNUSED_RESULT bool ReadSingleMessage(MojoResult* read_result); - - // |this| can be destroyed during message dispatch. - void ReadAllAvailableMessages(); - - // If |force_pipe_reset| is true, this method replaces the existing - // |message_pipe_| with a dummy message pipe handle (whose peer is closed). - // If |force_async_handler| is true, |connection_error_handler_| is called - // asynchronously. - void HandleError(bool force_pipe_reset, bool force_async_handler); - - // Cancels any calls made to |waiter_|. - void CancelWait(); - - void EnsureSyncWatcherExists(); - - base::Closure connection_error_handler_; - - ScopedMessagePipeHandle message_pipe_; - MessageReceiver* incoming_receiver_ = nullptr; - - scoped_refptr task_runner_; - std::unique_ptr handle_watcher_; - - bool error_ = false; - bool drop_writes_ = false; - bool enforce_errors_from_incoming_receiver_ = true; - - bool paused_ = false; - - // If sending messages is allowed from multiple threads, |lock_| is used to - // protect modifications to |message_pipe_| and |drop_writes_|. - base::Optional lock_; - - std::unique_ptr sync_watcher_; - bool allow_woken_up_by_others_ = false; - // If non-zero, currently the control flow is inside the sync handle watcher - // callback. - size_t sync_handle_watcher_callback_count_ = 0; - - base::ThreadChecker thread_checker_; - - base::Lock connected_lock_; - bool connected_ = true; - - // The tag used to track heap allocations that originated from a Watcher - // notification. - const char* heap_profiler_tag_ = nullptr; - - // A cached pointer to the MessageLoopNestingObserver for the MessageLoop on - // which this Connector was created. - MessageLoopNestingObserver* const nesting_observer_; - - // |true| iff the Connector is currently dispatching a message. Used to detect - // nested dispatch operations. - bool is_dispatching_ = false; - - // Create a single weak ptr and use it everywhere, to avoid the malloc/free - // cost of creating a new weak ptr whenever it is needed. - // NOTE: This weak pointer is invalidated when the message pipe is closed or - // transferred (i.e., when |connected_| is set to false). - base::WeakPtr weak_self_; - base::WeakPtrFactory weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(Connector); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_CONNECTOR_H_ diff --git a/mojo/public/cpp/bindings/disconnect_reason.h b/mojo/public/cpp/bindings/disconnect_reason.h deleted file mode 100644 index c04e8ad..0000000 --- a/mojo/public/cpp/bindings/disconnect_reason.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_DISCONNECT_REASON_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_DISCONNECT_REASON_H_ - -#include - -#include - -namespace mojo { - -struct DisconnectReason { - public: - DisconnectReason(uint32_t in_custom_reason, const std::string& in_description) - : custom_reason(in_custom_reason), description(in_description) {} - - uint32_t custom_reason; - std::string description; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_DISCONNECT_REASON_H_ diff --git a/mojo/public/cpp/bindings/enum_traits.h b/mojo/public/cpp/bindings/enum_traits.h deleted file mode 100644 index 2c528f3..0000000 --- a/mojo/public/cpp/bindings/enum_traits.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_ENUM_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_ENUM_TRAITS_H_ - -namespace mojo { - -// This must be specialized for any type |T| to be serialized/deserialized as a -// mojom enum |MojomType|. Each specialization needs to implement: -// -// template <> -// struct EnumTraits { -// static MojomType ToMojom(T input); -// -// // Returning false results in deserialization failure and causes the -// // message pipe receiving it to be disconnected. -// static bool FromMojom(MojomType input, T* output); -// }; -// -template -struct EnumTraits; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_ENUM_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/filter_chain.h b/mojo/public/cpp/bindings/filter_chain.h deleted file mode 100644 index 1262f39..0000000 --- a/mojo/public/cpp/bindings/filter_chain.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_ - -#include -#include - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -class MOJO_CPP_BINDINGS_EXPORT FilterChain - : NON_EXPORTED_BASE(public MessageReceiver) { - public: - // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while - // this object is alive. - explicit FilterChain(MessageReceiver* sink = nullptr); - - FilterChain(FilterChain&& other); - FilterChain& operator=(FilterChain&& other); - ~FilterChain() override; - - template - inline void Append(Args&&... args); - - void Append(std::unique_ptr filter); - - // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while - // this object is alive. - void SetSink(MessageReceiver* sink); - - // MessageReceiver: - bool Accept(Message* message) override; - - private: - std::vector> filters_; - - MessageReceiver* sink_; - - DISALLOW_COPY_AND_ASSIGN(FilterChain); -}; - -template -inline void FilterChain::Append(Args&&... args) { - Append(base::MakeUnique(std::forward(args)...)); -} - -template <> -inline void FilterChain::Append() { -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_ diff --git a/mojo/public/cpp/bindings/interface_data_view.h b/mojo/public/cpp/bindings/interface_data_view.h deleted file mode 100644 index ef12254..0000000 --- a/mojo/public/cpp/bindings/interface_data_view.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_DATA_VIEW_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_DATA_VIEW_H_ - -namespace mojo { - -// They are used for type identification purpose only. -template -class AssociatedInterfacePtrInfoDataView {}; - -template -class AssociatedInterfaceRequestDataView {}; - -template -class InterfacePtrDataView {}; - -template -class InterfaceRequestDataView {}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_DATA_VIEW_H_ diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h deleted file mode 100644 index b519fe9..0000000 --- a/mojo/public/cpp/bindings/interface_endpoint_client.h +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ - -#include - -#include -#include - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/lib/control_message_handler.h" -#include "mojo/public/cpp/bindings/lib/control_message_proxy.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { - -class AssociatedGroup; -class InterfaceEndpointController; - -// InterfaceEndpointClient handles message sending and receiving of an interface -// endpoint, either the implementation side or the client side. -// It should only be accessed and destructed on the creating thread. -class MOJO_CPP_BINDINGS_EXPORT InterfaceEndpointClient - : NON_EXPORTED_BASE(public MessageReceiverWithResponder) { - public: - // |receiver| is okay to be null. If it is not null, it must outlive this - // object. - InterfaceEndpointClient(ScopedInterfaceEndpointHandle handle, - MessageReceiverWithResponderStatus* receiver, - std::unique_ptr payload_validator, - bool expect_sync_requests, - scoped_refptr runner, - uint32_t interface_version); - ~InterfaceEndpointClient() override; - - // Sets the error handler to receive notifications when an error is - // encountered. - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(thread_checker_.CalledOnValidThread()); - error_handler_ = error_handler; - error_with_reason_handler_.Reset(); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(thread_checker_.CalledOnValidThread()); - error_with_reason_handler_ = error_handler; - error_handler_.Reset(); - } - - // Returns true if an error was encountered. - bool encountered_error() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return encountered_error_; - } - - // Returns true if this endpoint has any pending callbacks. - bool has_pending_responders() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return !async_responders_.empty() || !sync_responses_.empty(); - } - - AssociatedGroup* associated_group(); - - // Adds a MessageReceiver which can filter a message after validation but - // before dispatch. - void AddFilter(std::unique_ptr filter); - - // After this call the object is in an invalid state and shouldn't be reused. - ScopedInterfaceEndpointHandle PassHandle(); - - // Raises an error on the underlying message pipe. It disconnects the pipe - // and notifies all interfaces running on this pipe. - void RaiseError(); - - void CloseWithReason(uint32_t custom_reason, const std::string& description); - - // MessageReceiverWithResponder implementation: - // They must only be called when the handle is not in pending association - // state. - bool Accept(Message* message) override; - bool AcceptWithResponder(Message* message, - std::unique_ptr responder) override; - - // The following methods are called by the router. They must be called - // outside of the router's lock. - - // NOTE: |message| must have passed message header validation. - bool HandleIncomingMessage(Message* message); - void NotifyError(const base::Optional& reason); - - // The following methods send interface control messages. - // They must only be called when the handle is not in pending association - // state. - void QueryVersion(const base::Callback& callback); - void RequireVersion(uint32_t version); - void FlushForTesting(); - - private: - // Maps from the id of a response to the MessageReceiver that handles the - // response. - using AsyncResponderMap = - std::map>; - - struct SyncResponseInfo { - public: - explicit SyncResponseInfo(bool* in_response_received); - ~SyncResponseInfo(); - - Message response; - - // Points to a stack-allocated variable. - bool* response_received; - - private: - DISALLOW_COPY_AND_ASSIGN(SyncResponseInfo); - }; - - using SyncResponseMap = std::map>; - - // Used as the sink for |payload_validator_| and forwards messages to - // HandleValidatedMessage(). - class HandleIncomingMessageThunk : public MessageReceiver { - public: - explicit HandleIncomingMessageThunk(InterfaceEndpointClient* owner); - ~HandleIncomingMessageThunk() override; - - // MessageReceiver implementation: - bool Accept(Message* message) override; - - private: - InterfaceEndpointClient* const owner_; - - DISALLOW_COPY_AND_ASSIGN(HandleIncomingMessageThunk); - }; - - void InitControllerIfNecessary(); - - void OnAssociationEvent( - ScopedInterfaceEndpointHandle::AssociationEvent event); - - bool HandleValidatedMessage(Message* message); - - const bool expect_sync_requests_ = false; - - ScopedInterfaceEndpointHandle handle_; - std::unique_ptr associated_group_; - InterfaceEndpointController* controller_ = nullptr; - - MessageReceiverWithResponderStatus* const incoming_receiver_ = nullptr; - HandleIncomingMessageThunk thunk_; - FilterChain filters_; - - AsyncResponderMap async_responders_; - SyncResponseMap sync_responses_; - - uint64_t next_request_id_ = 1; - - base::Closure error_handler_; - ConnectionErrorWithReasonCallback error_with_reason_handler_; - bool encountered_error_ = false; - - scoped_refptr task_runner_; - - internal::ControlMessageProxy control_message_proxy_; - internal::ControlMessageHandler control_message_handler_; - - base::ThreadChecker thread_checker_; - - base::WeakPtrFactory weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceEndpointClient); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CLIENT_H_ diff --git a/mojo/public/cpp/bindings/interface_endpoint_controller.h b/mojo/public/cpp/bindings/interface_endpoint_controller.h deleted file mode 100644 index 8d99d4a..0000000 --- a/mojo/public/cpp/bindings/interface_endpoint_controller.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CONTROLLER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CONTROLLER_H_ - -namespace mojo { - -class Message; - -// A control interface exposed by AssociatedGroupController for interface -// endpoints. -class InterfaceEndpointController { - public: - virtual ~InterfaceEndpointController() {} - - virtual bool SendMessage(Message* message) = 0; - - // Allows the interface endpoint to watch for incoming sync messages while - // others perform sync handle watching on the same thread. Please see comments - // of SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread(). - virtual void AllowWokenUpBySyncWatchOnSameThread() = 0; - - // Watches the interface endpoint for incoming sync messages. (It also watches - // other other handles registered to be watched together.) - // This method: - // - returns true when |should_stop| is set to true; - // - return false otherwise, including - // MultiplexRouter::DetachEndpointClient() being called for the same - // interface endpoint. - virtual bool SyncWatch(const bool* should_stop) = 0; -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ENDPOINT_CONTROLLER_H_ diff --git a/mojo/public/cpp/bindings/interface_id.h b/mojo/public/cpp/bindings/interface_id.h deleted file mode 100644 index 53475d6..0000000 --- a/mojo/public/cpp/bindings/interface_id.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ID_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ID_H_ - -#include - -namespace mojo { - -// The size of the type matters because it is directly used in messages. -using InterfaceId = uint32_t; - -// IDs of associated interface can be generated at both sides of the message -// pipe. In order to avoid collision, the highest bit is used as namespace bit: -// at the side where the client-side of the master interface lives, IDs are -// generated with the namespace bit set to 1; at the opposite side IDs are -// generated with the namespace bit set to 0. -const uint32_t kInterfaceIdNamespaceMask = 0x80000000; - -const InterfaceId kMasterInterfaceId = 0x00000000; -const InterfaceId kInvalidInterfaceId = 0xFFFFFFFF; - -inline bool IsMasterInterfaceId(InterfaceId id) { - return id == kMasterInterfaceId; -} - -inline bool IsValidInterfaceId(InterfaceId id) { - return id != kInvalidInterfaceId; -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_ID_H_ diff --git a/mojo/public/cpp/bindings/interface_ptr.h b/mojo/public/cpp/bindings/interface_ptr.h deleted file mode 100644 index e88be74..0000000 --- a/mojo/public/cpp/bindings/interface_ptr.h +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ - -#include - -#include -#include - -#include "base/callback_forward.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/bindings/lib/interface_ptr_state.h" - -namespace mojo { - -// A pointer to a local proxy of a remote Interface implementation. Uses a -// message pipe to communicate with the remote implementation, and automatically -// 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. -// -// This class is thread hostile, as is the local proxy it manages, while bound -// to a message pipe. All calls to this class or the proxy should be from the -// same thread that bound it. If you need to move the proxy to a different -// thread, extract the InterfacePtrInfo (containing just the message pipe and -// any version information) using PassInterface(), pass it to a different -// thread, and create and bind a new InterfacePtr from that thread. If an -// InterfacePtr is not bound to a message pipe, it may be bound or destroyed on -// any thread. -template -class InterfacePtr { - public: - using InterfaceType = Interface; - using PtrInfoType = InterfacePtrInfo; - - // Constructs an unbound InterfacePtr. - InterfacePtr() {} - InterfacePtr(decltype(nullptr)) {} - - // Takes over the binding of another InterfacePtr. - InterfacePtr(InterfacePtr&& other) { - internal_state_.Swap(&other.internal_state_); - } - - // Takes over the binding of another InterfacePtr, and closes any message pipe - // already bound to this pointer. - InterfacePtr& operator=(InterfacePtr&& other) { - reset(); - internal_state_.Swap(&other.internal_state_); - return *this; - } - - // Assigning nullptr to this class causes it to close the currently bound - // message pipe (if any) and returns the pointer to the unbound state. - InterfacePtr& operator=(decltype(nullptr)) { - reset(); - return *this; - } - - // Closes the bound message pipe (if any) on destruction. - ~InterfacePtr() {} - - // Binds the InterfacePtr to a remote implementation of Interface. - // - // Calling with an invalid |info| (containing an invalid message pipe handle) - // has the same effect as reset(). In this case, the InterfacePtr is not - // considered as bound. - // - // |runner| must belong to the same thread. It will be used to dispatch all - // callbacks and connection error notification. It is useful when you attach - // multiple task runners to a single thread for the purposes of task - // scheduling. - void Bind(InterfacePtrInfo info, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - reset(); - if (info.is_valid()) - internal_state_.Bind(std::move(info), std::move(runner)); - } - - // Returns whether or not this InterfacePtr is bound to a message pipe. - bool is_bound() const { return internal_state_.is_bound(); } - - // Returns a raw pointer to the local proxy. Caller does not take ownership. - // Note that the local proxy is thread hostile, as stated above. - Interface* get() const { return internal_state_.instance(); } - - // Functions like a pointer to Interface. Must already be bound. - Interface* operator->() const { return get(); } - Interface& operator*() const { return *get(); } - - // Returns the version number of the interface that the remote side supports. - uint32_t version() const { return internal_state_.version(); } - - // Queries the max version that the remote side supports. On completion, the - // result will be returned as the input of |callback|. The version number of - // this interface pointer will also be updated. - void QueryVersion(const base::Callback& callback) { - internal_state_.QueryVersion(callback); - } - - // If the remote side doesn't support the specified version, it will close its - // end of the message pipe asynchronously. This does nothing if it's already - // known that the remote side supports the specified version, i.e., if - // |version <= this->version()|. - // - // After calling RequireVersion() with a version not supported by the remote - // side, all subsequent calls to interface methods will be ignored. - void RequireVersion(uint32_t version) { - internal_state_.RequireVersion(version); - } - - // Sends a no-op message on the underlying message pipe and runs the current - // message loop until its response is received. This can be used in tests to - // verify that no message was sent on a message pipe in response to some - // stimulus. - void FlushForTesting() { internal_state_.FlushForTesting(); } - - // Closes the bound message pipe (if any) and returns the pointer to the - // unbound state. - void reset() { - State doomed; - internal_state_.Swap(&doomed); - } - - // Similar to the method above, but also specifies a disconnect reason. - void ResetWithReason(uint32_t custom_reason, const std::string& description) { - if (internal_state_.is_bound()) - internal_state_.CloseWithReason(custom_reason, description); - reset(); - } - - // Whether there are any associated interfaces running on the pipe currently. - bool HasAssociatedInterfaces() const { - return internal_state_.HasAssociatedInterfaces(); - } - - // 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). - bool encountered_error() const { return internal_state_.encountered_error(); } - - // Registers a handler to receive error notifications. The handler will be - // called from the thread that owns this InterfacePtr. - // - // This method may only be called after the InterfacePtr has been bound to a - // message pipe. - void set_connection_error_handler(const base::Closure& error_handler) { - internal_state_.set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - internal_state_.set_connection_error_with_reason_handler(error_handler); - } - - // Unbinds the InterfacePtr and returns the information which could be used - // to setup an InterfacePtr again. This method may be used to move the proxy - // to a different thread (see class comments for details). - // - // It is an error to call PassInterface() while: - // - there are pending responses; or - // TODO: fix this restriction, it's not always obvious when there is a - // pending response. - // - there are associated interfaces running. - // TODO(yzshen): For now, users need to make sure there is no one holding - // on to associated interface endpoint handles at both sides of the - // message pipe in order to call this method. We need a way to forcefully - // invalidate associated interface endpoint handles. - InterfacePtrInfo PassInterface() { - CHECK(!HasAssociatedInterfaces()); - CHECK(!internal_state_.has_pending_callbacks()); - State state; - internal_state_.Swap(&state); - - return state.PassInterface(); - } - - bool Equals(const InterfacePtr& other) const { - if (this == &other) - return true; - - // Now that the two refer to different objects, they are equivalent if - // and only if they are both null. - return !(*this) && !other; - } - - // DO NOT USE. Exposed only for internal use and for testing. - internal::InterfacePtrState* internal_state() { - return &internal_state_; - } - - // Allow InterfacePtr<> to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - private: - // TODO(dcheng): Use an explicit conversion operator. - typedef internal::InterfacePtrState InterfacePtr::*Testable; - - public: - operator Testable() const { - return internal_state_.is_bound() ? &InterfacePtr::internal_state_ - : nullptr; - } - - private: - // Forbid the == and != operators explicitly, otherwise InterfacePtr will be - // converted to Testable to do == or != comparison. - template - bool operator==(const InterfacePtr& other) const = delete; - template - bool operator!=(const InterfacePtr& other) const = delete; - - typedef internal::InterfacePtrState State; - mutable State internal_state_; - - DISALLOW_COPY_AND_ASSIGN(InterfacePtr); -}; - -// If |info| is valid (containing a valid message pipe handle), returns an -// InterfacePtr bound to it. Otherwise, returns an unbound InterfacePtr. -template -InterfacePtr MakeProxy( - InterfacePtrInfo info, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - InterfacePtr ptr; - if (info.is_valid()) - ptr.Bind(std::move(info), std::move(runner)); - return std::move(ptr); -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ diff --git a/mojo/public/cpp/bindings/interface_ptr_info.h b/mojo/public/cpp/bindings/interface_ptr_info.h deleted file mode 100644 index 0b2d808..0000000 --- a/mojo/public/cpp/bindings/interface_ptr_info.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_INFO_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_INFO_H_ - -#include -#include - -#include "base/macros.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { - -// InterfacePtrInfo stores necessary information to communicate with a remote -// interface implementation, which could be used to construct an InterfacePtr. -template -class InterfacePtrInfo { - public: - InterfacePtrInfo() : version_(0u) {} - - InterfacePtrInfo(ScopedMessagePipeHandle handle, uint32_t version) - : handle_(std::move(handle)), version_(version) {} - - InterfacePtrInfo(InterfacePtrInfo&& other) - : handle_(std::move(other.handle_)), version_(other.version_) { - other.version_ = 0u; - } - - ~InterfacePtrInfo() {} - - InterfacePtrInfo& operator=(InterfacePtrInfo&& other) { - if (this != &other) { - handle_ = std::move(other.handle_); - version_ = other.version_; - other.version_ = 0u; - } - - return *this; - } - - bool is_valid() const { return handle_.is_valid(); } - - ScopedMessagePipeHandle PassHandle() { return std::move(handle_); } - const ScopedMessagePipeHandle& handle() const { return handle_; } - void set_handle(ScopedMessagePipeHandle handle) { - handle_ = std::move(handle); - } - - uint32_t version() const { return version_; } - void set_version(uint32_t version) { version_ = version; } - - private: - ScopedMessagePipeHandle handle_; - uint32_t version_; - - DISALLOW_COPY_AND_ASSIGN(InterfacePtrInfo); -}; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_INFO_H_ diff --git a/mojo/public/cpp/bindings/interface_ptr_set.h b/mojo/public/cpp/bindings/interface_ptr_set.h deleted file mode 100644 index 09a2682..0000000 --- a/mojo/public/cpp/bindings/interface_ptr_set.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ - -#include -#include - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" - -namespace mojo { -namespace internal { - -// TODO(blundell): This class should be rewritten to be structured -// similarly to BindingSet if possible, with PtrSet owning its -// Elements and those Elements calling back into PtrSet on connection -// error. -template class Ptr> -class PtrSet { - public: - PtrSet() {} - ~PtrSet() { CloseAll(); } - - void AddPtr(Ptr ptr) { - auto weak_interface_ptr = new Element(std::move(ptr)); - ptrs_.push_back(weak_interface_ptr->GetWeakPtr()); - ClearNullPtrs(); - } - - template - void ForAllPtrs(FunctionType function) { - for (const auto& it : ptrs_) { - if (it) - function(it->get()); - } - ClearNullPtrs(); - } - - void CloseAll() { - for (const auto& it : ptrs_) { - if (it) - it->Close(); - } - ptrs_.clear(); - } - - private: - class Element { - public: - explicit Element(Ptr ptr) - : ptr_(std::move(ptr)), weak_ptr_factory_(this) { - ptr_.set_connection_error_handler(base::Bind(&DeleteElement, this)); - } - - ~Element() {} - - void Close() { - ptr_.reset(); - - // Resetting the interface ptr means that it won't call this object back - // on connection error anymore, so this object must delete itself now. - DeleteElement(this); - } - - Interface* get() { return ptr_.get(); } - - base::WeakPtr GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - private: - static void DeleteElement(Element* element) { delete element; } - - Ptr ptr_; - base::WeakPtrFactory weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(Element); - }; - - void ClearNullPtrs() { - ptrs_.erase(std::remove_if(ptrs_.begin(), ptrs_.end(), - [](const base::WeakPtr& p) { - return p.get() == nullptr; - }), - ptrs_.end()); - } - - std::vector> ptrs_; -}; - -} // namespace internal - -template -using InterfacePtrSet = internal::PtrSet; - -template -using AssociatedInterfacePtrSet = - internal::PtrSet; - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_SET_H_ diff --git a/mojo/public/cpp/bindings/interface_request.h b/mojo/public/cpp/bindings/interface_request.h deleted file mode 100644 index 29d8836..0000000 --- a/mojo/public/cpp/bindings/interface_request.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ - -#include -#include - -#include "base/macros.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/disconnect_reason.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { - -// Represents a request from a remote client for an implementation of Interface -// over a specified message pipe. The implementor of the interface should -// remove the message pipe by calling PassMessagePipe() and bind it to the -// implementation. If this is not done, the InterfaceRequest will automatically -// close the pipe on destruction. Can also represent the absence of a request -// if the client did not provide a message pipe. -template -class InterfaceRequest { - public: - // Constructs an empty InterfaceRequest, representing that the client is not - // requesting an implementation of Interface. - InterfaceRequest() {} - InterfaceRequest(decltype(nullptr)) {} - - // Creates a new message pipe over which Interface is to be served, binding - // the specified InterfacePtr to one end of the message pipe and this - // InterfaceRequest to the other. For example usage, see comments on - // MakeRequest(InterfacePtr*) below. - explicit InterfaceRequest(InterfacePtr* ptr, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - MessagePipe pipe; - ptr->Bind(InterfacePtrInfo(std::move(pipe.handle0), 0u), - std::move(runner)); - Bind(std::move(pipe.handle1)); - } - - // Takes the message pipe from another InterfaceRequest. - InterfaceRequest(InterfaceRequest&& other) { - handle_ = std::move(other.handle_); - } - InterfaceRequest& operator=(InterfaceRequest&& other) { - handle_ = std::move(other.handle_); - return *this; - } - - // Assigning to nullptr resets the InterfaceRequest to an empty state, - // closing the message pipe currently bound to it (if any). - InterfaceRequest& operator=(decltype(nullptr)) { - handle_.reset(); - return *this; - } - - // Binds the request to a message pipe over which Interface is to be - // requested. If the request is already bound to a message pipe, the current - // message pipe will be closed. - void Bind(ScopedMessagePipeHandle handle) { handle_ = std::move(handle); } - - // Indicates whether the request currently contains a valid message pipe. - bool is_pending() const { return handle_.is_valid(); } - - // Removes the message pipe from the request and returns it. - ScopedMessagePipeHandle PassMessagePipe() { return std::move(handle_); } - - bool Equals(const InterfaceRequest& other) const { - if (this == &other) - return true; - - // Now that the two refer to different objects, they are equivalent if - // and only if they are both invalid. - return !is_pending() && !other.is_pending(); - } - - void ResetWithReason(uint32_t custom_reason, const std::string& description) { - if (!handle_.is_valid()) - return; - - Message message = - PipeControlMessageProxy::ConstructPeerEndpointClosedMessage( - kMasterInterfaceId, DisconnectReason(custom_reason, description)); - MojoResult result = WriteMessageNew( - handle_.get(), message.TakeMojoMessage(), MOJO_WRITE_MESSAGE_FLAG_NONE); - DCHECK_EQ(MOJO_RESULT_OK, result); - - handle_.reset(); - } - - private: - ScopedMessagePipeHandle handle_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceRequest); -}; - -// Makes an InterfaceRequest bound to the specified message pipe. If |handle| -// is empty or invalid, the resulting InterfaceRequest will represent the -// absence of a request. -template -InterfaceRequest MakeRequest(ScopedMessagePipeHandle handle) { - InterfaceRequest request; - request.Bind(std::move(handle)); - return std::move(request); -} - -// Creates a new message pipe over which Interface is to be served. Binds the -// specified InterfacePtr to one end of the message pipe, and returns an -// InterfaceRequest bound to the other. The InterfacePtr should be passed to -// the client, and the InterfaceRequest should be passed to whatever will -// provide the implementation. The implementation should typically be bound to -// the InterfaceRequest using the Binding or StrongBinding classes. The client -// may begin to issue calls even before an implementation has been bound, since -// messages sent over the pipe will just queue up until they are consumed by -// the implementation. -// -// Example #1: Requesting a remote implementation of an interface. -// =============================================================== -// -// Given the following interface: -// -// interface Database { -// OpenTable(Table& table); -// } -// -// The client would have code similar to the following: -// -// DatabasePtr database = ...; // Connect to database. -// TablePtr table; -// database->OpenTable(MakeRequest(&table)); -// -// Upon return from MakeRequest, |table| is ready to have methods called on it. -// -// Example #2: Registering a local implementation with a remote service. -// ===================================================================== -// -// Given the following interface -// interface Collector { -// RegisterSource(Source source); -// } -// -// The client would have code similar to the following: -// -// CollectorPtr collector = ...; // Connect to Collector. -// SourcePtr source; -// InterfaceRequest source_request(&source); -// collector->RegisterSource(std::move(source)); -// CreateSource(std::move(source_request)); // Create implementation locally. -// -template -InterfaceRequest MakeRequest( - InterfacePtr* ptr, - scoped_refptr runner = - base::ThreadTaskRunnerHandle::Get()) { - return InterfaceRequest(ptr, runner); -} - -// Fuses an InterfaceRequest endpoint with an InterfacePtrInfo endpoint. -// Returns |true| on success or |false| on failure. -template -bool FuseInterface(InterfaceRequest request, - InterfacePtrInfo proxy_info) { - MojoResult result = FuseMessagePipes(request.PassMessagePipe(), - proxy_info.PassHandle()); - return result == MOJO_RESULT_OK; -} - -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_REQUEST_H_ diff --git a/mojo/public/cpp/bindings/lib/array_internal.cc b/mojo/public/cpp/bindings/lib/array_internal.cc deleted file mode 100644 index dd24eac..0000000 --- a/mojo/public/cpp/bindings/lib/array_internal.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/array_internal.h" - -#include -#include - -#include - -namespace mojo { -namespace internal { - -std::string MakeMessageWithArrayIndex(const char* message, - size_t size, - size_t index) { - std::ostringstream stream; - stream << message << ": array size - " << size << "; index - " << index; - return stream.str(); -} - -std::string MakeMessageWithExpectedArraySize(const char* message, - size_t size, - size_t expected_size) { - std::ostringstream stream; - stream << message << ": array size - " << size << "; expected size - " - << expected_size; - return stream.str(); -} - -ArrayDataTraits::BitRef::~BitRef() { -} - -ArrayDataTraits::BitRef::BitRef(uint8_t* storage, uint8_t mask) - : storage_(storage), mask_(mask) { -} - -ArrayDataTraits::BitRef& ArrayDataTraits::BitRef::operator=( - bool value) { - if (value) { - *storage_ |= mask_; - } else { - *storage_ &= ~mask_; - } - return *this; -} - -ArrayDataTraits::BitRef& ArrayDataTraits::BitRef::operator=( - const BitRef& value) { - return (*this) = static_cast(value); -} - -ArrayDataTraits::BitRef::operator bool() const { - return (*storage_ & mask_) != 0; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/array_internal.h b/mojo/public/cpp/bindings/lib/array_internal.h deleted file mode 100644 index eecfcfb..0000000 --- a/mojo/public/cpp/bindings/lib/array_internal.h +++ /dev/null @@ -1,368 +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_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ - -#include -#include - -#include -#include - -#include "base/logging.h" -#include "mojo/public/c/system/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/lib/validate_params.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" - -namespace mojo { -namespace internal { - -template -class Map_Data; - -MOJO_CPP_BINDINGS_EXPORT std::string -MakeMessageWithArrayIndex(const char* message, size_t size, size_t index); - -MOJO_CPP_BINDINGS_EXPORT std::string MakeMessageWithExpectedArraySize( - const char* message, - size_t size, - size_t expected_size); - -template -struct ArrayDataTraits { - using StorageType = T; - using Ref = T&; - using ConstRef = const T&; - - static const uint32_t kMaxNumElements = - (std::numeric_limits::max() - sizeof(ArrayHeader)) / - sizeof(StorageType); - - static uint32_t GetStorageSize(uint32_t num_elements) { - DCHECK(num_elements <= kMaxNumElements); - return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; - } - static Ref ToRef(StorageType* storage, size_t offset) { - return storage[offset]; - } - static ConstRef ToConstRef(const StorageType* storage, size_t offset) { - return storage[offset]; - } -}; - -// Specialization of Arrays for bools, optimized for space. It has the -// following differences from a generalized Array: -// * Each element takes up a single bit of memory. -// * Accessing a non-const single element uses a helper class |BitRef|, which -// emulates a reference to a bool. -template <> -struct ArrayDataTraits { - // Helper class to emulate a reference to a bool, used for direct element - // access. - class MOJO_CPP_BINDINGS_EXPORT BitRef { - public: - ~BitRef(); - BitRef& operator=(bool value); - BitRef& operator=(const BitRef& value); - operator bool() const; - - private: - friend struct ArrayDataTraits; - BitRef(uint8_t* storage, uint8_t mask); - BitRef(); - uint8_t* storage_; - uint8_t mask_; - }; - - // Because each element consumes only 1/8 byte. - static const uint32_t kMaxNumElements = std::numeric_limits::max(); - - using StorageType = uint8_t; - using Ref = BitRef; - using ConstRef = bool; - - static uint32_t GetStorageSize(uint32_t num_elements) { - return sizeof(ArrayHeader) + ((num_elements + 7) / 8); - } - static BitRef ToRef(StorageType* storage, size_t offset) { - return BitRef(&storage[offset / 8], 1 << (offset % 8)); - } - static bool ToConstRef(const StorageType* storage, size_t offset) { - return (storage[offset / 8] & (1 << (offset % 8))) != 0; - } -}; - -// What follows is code to support the serialization/validation of -// Array_Data. There are four interesting cases: arrays of primitives, -// arrays of handles/interfaces, arrays of objects and arrays of unions. -// Arrays of objects are represented as arrays of pointers to objects. Arrays -// of unions are inlined so they are not pointers, but comparing with primitives -// they require more work for serialization/validation. -// -// TODO(yzshen): Validation code should be organzied in a way similar to -// Serializer<>, or merged into it. It should be templatized with the mojo -// data view type instead of the data type, that way we can use MojomTypeTraits -// to determine the categories. - -template -struct ArraySerializationHelper; - -template -struct ArraySerializationHelper { - using ElementType = typename ArrayDataTraits::StorageType; - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - if (!validate_params->validate_enum_func) - return true; - - // Enum validation. - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->validate_enum_func(elements[i], validation_context)) - return false; - } - return true; - } -}; - -template -struct ArraySerializationHelper { - using ElementType = typename ArrayDataTraits::StorageType; - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - DCHECK(!validate_params->element_validate_params) - << "Handle or interface type should not have array validate params"; - - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->element_is_nullable && - !IsHandleOrInterfaceValid(elements[i])) { - static const ValidationError kError = - std::is_same::value || - std::is_same::value - ? VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE - : VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID; - ReportValidationError( - validation_context, kError, - MakeMessageWithArrayIndex( - "invalid handle or interface ID in array expecting valid " - "handles or interface IDs", - header->num_elements, i) - .c_str()); - return false; - } - if (!ValidateHandleOrInterface(elements[i], validation_context)) - return false; - } - return true; - } -}; - -template -struct ArraySerializationHelper, false, false> { - using ElementType = typename ArrayDataTraits>::StorageType; - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->element_is_nullable && !elements[i].offset) { - ReportValidationError( - validation_context, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid pointers", - header->num_elements, - i).c_str()); - return false; - } - if (!ValidateCaller::Run(elements[i], validation_context, - validate_params->element_validate_params)) { - return false; - } - } - return true; - } - - private: - template ::value || - IsSpecializationOf::value> - struct ValidateCaller { - static bool Run(const Pointer& data, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - DCHECK(!validate_params) - << "Struct type should not have array validate params"; - - return ValidateStruct(data, validation_context); - } - }; - - template - struct ValidateCaller { - static bool Run(const Pointer& data, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - return ValidateContainer(data, validation_context, validate_params); - } - }; -}; - -template -struct ArraySerializationHelper { - using ElementType = typename ArrayDataTraits::StorageType; - - static bool ValidateElements(const ArrayHeader* header, - const ElementType* elements, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - for (uint32_t i = 0; i < header->num_elements; ++i) { - if (!validate_params->element_is_nullable && elements[i].is_null()) { - ReportValidationError( - validation_context, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid unions", - header->num_elements, i) - .c_str()); - return false; - } - if (!ValidateInlinedUnion(elements[i], validation_context)) - return false; - } - return true; - } -}; - -template -class Array_Data { - public: - using Traits = ArrayDataTraits; - using StorageType = typename Traits::StorageType; - using Ref = typename Traits::Ref; - using ConstRef = typename Traits::ConstRef; - using Helper = ArraySerializationHelper< - T, - IsUnionDataType::value, - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value>; - using Element = T; - - // Returns null if |num_elements| or the corresponding storage size cannot be - // stored in uint32_t. - static Array_Data* New(size_t num_elements, Buffer* buf) { - if (num_elements > Traits::kMaxNumElements) - return nullptr; - - uint32_t num_bytes = - Traits::GetStorageSize(static_cast(num_elements)); - return new (buf->Allocate(num_bytes)) - Array_Data(num_bytes, static_cast(num_elements)); - } - - static bool Validate(const void* data, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - if (!data) - return true; - if (!IsAligned(data)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_MISALIGNED_OBJECT); - return false; - } - if (!validation_context->IsValidRange(data, sizeof(ArrayHeader))) { - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - const ArrayHeader* header = static_cast(data); - if (header->num_elements > Traits::kMaxNumElements || - header->num_bytes < Traits::GetStorageSize(header->num_elements)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); - return false; - } - if (validate_params->expected_num_elements != 0 && - header->num_elements != validate_params->expected_num_elements) { - ReportValidationError( - validation_context, - VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, - MakeMessageWithExpectedArraySize( - "fixed-size array has wrong number of elements", - header->num_elements, - validate_params->expected_num_elements).c_str()); - return false; - } - if (!validation_context->ClaimMemory(data, header->num_bytes)) { - ReportValidationError(validation_context, - VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - - const Array_Data* object = static_cast*>(data); - return Helper::ValidateElements(&object->header_, object->storage(), - validation_context, validate_params); - } - - size_t size() const { return header_.num_elements; } - - Ref at(size_t offset) { - DCHECK(offset < static_cast(header_.num_elements)); - return Traits::ToRef(storage(), offset); - } - - ConstRef at(size_t offset) const { - DCHECK(offset < static_cast(header_.num_elements)); - return Traits::ToConstRef(storage(), offset); - } - - StorageType* storage() { - return reinterpret_cast(reinterpret_cast(this) + - sizeof(*this)); - } - - const StorageType* storage() const { - return reinterpret_cast( - reinterpret_cast(this) + sizeof(*this)); - } - - private: - Array_Data(uint32_t num_bytes, uint32_t num_elements) { - header_.num_bytes = num_bytes; - header_.num_elements = num_elements; - } - ~Array_Data() = delete; - - internal::ArrayHeader header_; - - // Elements of type internal::ArrayDataTraits::StorageType follow. -}; -static_assert(sizeof(Array_Data) == 8, "Bad sizeof(Array_Data)"); - -// UTF-8 encoded -using String_Data = Array_Data; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ diff --git a/mojo/public/cpp/bindings/lib/array_serialization.h b/mojo/public/cpp/bindings/lib/array_serialization.h deleted file mode 100644 index d2f8ecf..0000000 --- a/mojo/public/cpp/bindings/lib/array_serialization.h +++ /dev/null @@ -1,555 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ - -#include -#include // For |memcpy()|. - -#include -#include -#include -#include - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/array_data_view.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" - -namespace mojo { -namespace internal { - -template ::value> -class ArrayIterator {}; - -// Used as the UserTypeIterator template parameter of ArraySerializer. -template -class ArrayIterator { - public: - using IteratorType = decltype( - CallGetBeginIfExists(std::declval())); - - explicit ArrayIterator(MaybeConstUserType& input) - : input_(input), iter_(CallGetBeginIfExists(input)) {} - ~ArrayIterator() {} - - size_t GetSize() const { return Traits::GetSize(input_); } - - using GetNextResult = - decltype(Traits::GetValue(std::declval())); - GetNextResult GetNext() { - GetNextResult value = Traits::GetValue(iter_); - Traits::AdvanceIterator(iter_); - return value; - } - - using GetDataIfExistsResult = decltype( - CallGetDataIfExists(std::declval())); - GetDataIfExistsResult GetDataIfExists() { - return CallGetDataIfExists(input_); - } - - private: - MaybeConstUserType& input_; - IteratorType iter_; -}; - -// Used as the UserTypeIterator template parameter of ArraySerializer. -template -class ArrayIterator { - public: - explicit ArrayIterator(MaybeConstUserType& input) : input_(input), iter_(0) {} - ~ArrayIterator() {} - - size_t GetSize() const { return Traits::GetSize(input_); } - - using GetNextResult = - decltype(Traits::GetAt(std::declval(), 0)); - GetNextResult GetNext() { - DCHECK_LT(iter_, Traits::GetSize(input_)); - return Traits::GetAt(input_, iter_++); - } - - using GetDataIfExistsResult = decltype( - CallGetDataIfExists(std::declval())); - GetDataIfExistsResult GetDataIfExists() { - return CallGetDataIfExists(input_); - } - - private: - MaybeConstUserType& input_; - size_t iter_; -}; - -// ArraySerializer is also used to serialize map keys and values. Therefore, it -// has a UserTypeIterator parameter which is an adaptor for reading to hide the -// difference between ArrayTraits and MapTraits. -template -struct ArraySerializer; - -// Handles serialization and deserialization of arrays of pod types. -template -struct ArraySerializer< - MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if::value>::type> { - using UserType = typename std::remove_const::type; - using Data = typename MojomTypeTraits::Data; - using DataElement = typename Data::Element; - using Element = typename MojomType::Element; - using Traits = ArrayTraits; - - static_assert(std::is_same::value, - "Incorrect array serializer"); - static_assert(std::is_same::value, - "Incorrect array serializer"); - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement)); - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - size_t size = input->GetSize(); - if (size == 0) - return; - - auto data = input->GetDataIfExists(); - if (data) { - memcpy(output->storage(), data, size * sizeof(DataElement)); - } else { - for (size_t i = 0; i < size; ++i) - output->at(i) = input->GetNext(); - } - } - - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator iterator(*output); - if (input->size()) { - auto data = iterator.GetDataIfExists(); - if (data) { - memcpy(data, input->storage(), input->size() * sizeof(DataElement)); - } else { - for (size_t i = 0; i < input->size(); ++i) - iterator.GetNext() = input->at(i); - } - } - return true; - } -}; - -// Handles serialization and deserialization of arrays of enum types. -template -struct ArraySerializer< - MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if::value>::type> { - using UserType = typename std::remove_const::type; - using Data = typename MojomTypeTraits::Data; - using DataElement = typename Data::Element; - using Element = typename MojomType::Element; - using Traits = ArrayTraits; - - static_assert(sizeof(Element) == sizeof(DataElement), - "Incorrect array serializer"); - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement)); - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) - Serialize(input->GetNext(), output->storage() + i); - } - - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator iterator(*output); - for (size_t i = 0; i < input->size(); ++i) { - if (!Deserialize(input->at(i), &iterator.GetNext())) - return false; - } - return true; - } -}; - -// Serializes and deserializes arrays of bools. -template -struct ArraySerializer::value>::type> { - using UserType = typename std::remove_const::type; - using Traits = ArrayTraits; - using Data = typename MojomTypeTraits::Data; - - static_assert(std::is_same::value, - "Incorrect array serializer"); - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - return sizeof(Data) + Align((input->GetSize() + 7) / 8); - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_is_nullable) - << "Primitive type should be non-nullable"; - DCHECK(!validate_params->element_validate_params) - << "Primitive type should not have array validate params"; - - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) - output->at(i) = input->GetNext(); - } - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator iterator(*output); - for (size_t i = 0; i < input->size(); ++i) - iterator.GetNext() = input->at(i); - return true; - } -}; - -// Serializes and deserializes arrays of handles or interfaces. -template -struct ArraySerializer< - MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if< - BelongsTo::value>::type> { - using UserType = typename std::remove_const::type; - using Data = typename MojomTypeTraits::Data; - using Element = typename MojomType::Element; - using Traits = ArrayTraits; - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - size_t element_count = input->GetSize(); - if (BelongsTo::value) { - for (size_t i = 0; i < element_count; ++i) { - typename UserTypeIterator::GetNextResult next = input->GetNext(); - size_t size = PrepareToSerialize(next, context); - DCHECK_EQ(size, 0u); - } - } - return sizeof(Data) + Align(element_count * sizeof(typename Data::Element)); - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(!validate_params->element_validate_params) - << "Handle or interface type should not have array validate params"; - - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) { - typename UserTypeIterator::GetNextResult next = input->GetNext(); - Serialize(next, &output->at(i), context); - - static const ValidationError kError = - BelongsTo::value - ? VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID - : VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE; - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && - !IsHandleOrInterfaceValid(output->at(i)), - kError, - MakeMessageWithArrayIndex("invalid handle or interface ID in array " - "expecting valid handles or interface IDs", - size, i)); - } - } - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator iterator(*output); - for (size_t i = 0; i < input->size(); ++i) { - bool result = - Deserialize(&input->at(i), &iterator.GetNext(), context); - DCHECK(result); - } - return true; - } -}; - -// This template must only apply to pointer mojo entity (strings, structs, -// arrays and maps). -template -struct ArraySerializer::value>::type> { - using UserType = typename std::remove_const::type; - using Data = typename MojomTypeTraits::Data; - using Element = typename MojomType::Element; - using DataElementPtr = typename MojomTypeTraits::Data*; - using Traits = ArrayTraits; - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - size_t element_count = input->GetSize(); - size_t size = sizeof(Data) + element_count * sizeof(typename Data::Element); - for (size_t i = 0; i < element_count; ++i) { - typename UserTypeIterator::GetNextResult next = input->GetNext(); - size += PrepareToSerialize(next, context); - } - return size; - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) { - DataElementPtr data_ptr; - typename UserTypeIterator::GetNextResult next = input->GetNext(); - SerializeCaller::Run(next, buf, &data_ptr, - validate_params->element_validate_params, - context); - output->at(i).Set(data_ptr); - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && !data_ptr, - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid pointers", - size, i)); - } - } - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator iterator(*output); - for (size_t i = 0; i < input->size(); ++i) { - if (!Deserialize(input->at(i).Get(), &iterator.GetNext(), - context)) - return false; - } - return true; - } - - private: - template ::value> - struct SerializeCaller { - template - static void Run(InputElementType&& input, - Buffer* buf, - DataElementPtr* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - Serialize(std::forward(input), buf, output, context); - } - }; - - template - struct SerializeCaller { - template - static void Run(InputElementType&& input, - Buffer* buf, - DataElementPtr* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - Serialize(std::forward(input), buf, output, - validate_params, context); - } - }; -}; - -// Handles serialization and deserialization of arrays of unions. -template -struct ArraySerializer< - MojomType, - MaybeConstUserType, - UserTypeIterator, - typename std::enable_if::value>::type> { - using UserType = typename std::remove_const::type; - using Data = typename MojomTypeTraits::Data; - using Element = typename MojomType::Element; - using Traits = ArrayTraits; - - static size_t GetSerializedSize(UserTypeIterator* input, - SerializationContext* context) { - size_t element_count = input->GetSize(); - size_t size = sizeof(Data); - for (size_t i = 0; i < element_count; ++i) { - // Call with |inlined| set to false, so that it will account for both the - // data in the union and the space in the array used to hold the union. - typename UserTypeIterator::GetNextResult next = input->GetNext(); - size += PrepareToSerialize(next, false, context); - } - return size; - } - - static void SerializeElements(UserTypeIterator* input, - Buffer* buf, - Data* output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - size_t size = input->GetSize(); - for (size_t i = 0; i < size; ++i) { - typename Data::Element* result = output->storage() + i; - typename UserTypeIterator::GetNextResult next = input->GetNext(); - Serialize(next, buf, &result, true, context); - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - !validate_params->element_is_nullable && output->at(i).is_null(), - VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, - MakeMessageWithArrayIndex("null in array expecting valid unions", - size, i)); - } - } - - static bool DeserializeElements(Data* input, - UserType* output, - SerializationContext* context) { - if (!Traits::Resize(*output, input->size())) - return false; - ArrayIterator iterator(*output); - for (size_t i = 0; i < input->size(); ++i) { - if (!Deserialize(&input->at(i), &iterator.GetNext(), context)) - return false; - } - return true; - } -}; - -template -struct Serializer, MaybeConstUserType> { - using UserType = typename std::remove_const::type; - using Traits = ArrayTraits; - using Impl = ArraySerializer, - MaybeConstUserType, - ArrayIterator>; - using Data = typename MojomTypeTraits>::Data; - - static size_t PrepareToSerialize(MaybeConstUserType& input, - SerializationContext* context) { - if (CallIsNullIfExists(input)) - return 0; - ArrayIterator iterator(input); - return Impl::GetSerializedSize(&iterator, context); - } - - static void Serialize(MaybeConstUserType& input, - Buffer* buf, - Data** output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - if (!CallIsNullIfExists(input)) { - MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( - validate_params->expected_num_elements != 0 && - Traits::GetSize(input) != validate_params->expected_num_elements, - internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, - internal::MakeMessageWithExpectedArraySize( - "fixed-size array has wrong number of elements", - Traits::GetSize(input), validate_params->expected_num_elements)); - Data* result = Data::New(Traits::GetSize(input), buf); - if (result) { - ArrayIterator iterator(input); - Impl::SerializeElements(&iterator, buf, result, validate_params, - context); - } - *output = result; - } else { - *output = nullptr; - } - } - - static bool Deserialize(Data* input, - UserType* output, - SerializationContext* context) { - if (!input) - return CallSetToNullIfExists(output); - return Impl::DeserializeElements(input, output, context); - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/associated_binding.cc b/mojo/public/cpp/bindings/lib/associated_binding.cc deleted file mode 100644 index 6788e68..0000000 --- a/mojo/public/cpp/bindings/lib/associated_binding.cc +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/associated_binding.h" - -namespace mojo { - -AssociatedBindingBase::AssociatedBindingBase() {} - -AssociatedBindingBase::~AssociatedBindingBase() {} - -void AssociatedBindingBase::AddFilter(std::unique_ptr filter) { - DCHECK(endpoint_client_); - endpoint_client_->AddFilter(std::move(filter)); -} - -void AssociatedBindingBase::Close() { - endpoint_client_.reset(); -} - -void AssociatedBindingBase::CloseWithReason(uint32_t custom_reason, - const std::string& description) { - if (endpoint_client_) - endpoint_client_->CloseWithReason(custom_reason, description); - Close(); -} - -void AssociatedBindingBase::set_connection_error_handler( - const base::Closure& error_handler) { - DCHECK(is_bound()); - endpoint_client_->set_connection_error_handler(error_handler); -} - -void AssociatedBindingBase::set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(is_bound()); - endpoint_client_->set_connection_error_with_reason_handler(error_handler); -} - -void AssociatedBindingBase::FlushForTesting() { - endpoint_client_->FlushForTesting(); -} - -void AssociatedBindingBase::BindImpl( - ScopedInterfaceEndpointHandle handle, - MessageReceiverWithResponderStatus* receiver, - std::unique_ptr payload_validator, - bool expect_sync_requests, - scoped_refptr runner, - uint32_t interface_version) { - if (!handle.is_valid()) { - endpoint_client_.reset(); - return; - } - - endpoint_client_.reset(new InterfaceEndpointClient( - std::move(handle), receiver, std::move(payload_validator), - expect_sync_requests, std::move(runner), interface_version)); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/associated_group.cc b/mojo/public/cpp/bindings/lib/associated_group.cc deleted file mode 100644 index 3e95eeb..0000000 --- a/mojo/public/cpp/bindings/lib/associated_group.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/associated_group.h" - -#include "mojo/public/cpp/bindings/associated_group_controller.h" - -namespace mojo { - -AssociatedGroup::AssociatedGroup() = default; - -AssociatedGroup::AssociatedGroup( - scoped_refptr controller) - : controller_(std::move(controller)) {} - -AssociatedGroup::AssociatedGroup(const ScopedInterfaceEndpointHandle& handle) - : controller_getter_(handle.CreateGroupControllerGetter()) {} - -AssociatedGroup::AssociatedGroup(const AssociatedGroup& other) = default; - -AssociatedGroup::~AssociatedGroup() = default; - -AssociatedGroup& AssociatedGroup::operator=(const AssociatedGroup& other) = - default; - -AssociatedGroupController* AssociatedGroup::GetController() { - if (controller_) - return controller_.get(); - - return controller_getter_.Run(); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/associated_group_controller.cc b/mojo/public/cpp/bindings/lib/associated_group_controller.cc deleted file mode 100644 index f4a9aa2..0000000 --- a/mojo/public/cpp/bindings/lib/associated_group_controller.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/associated_group_controller.h" - -#include "mojo/public/cpp/bindings/associated_group.h" - -namespace mojo { - -AssociatedGroupController::~AssociatedGroupController() {} - -ScopedInterfaceEndpointHandle -AssociatedGroupController::CreateScopedInterfaceEndpointHandle(InterfaceId id) { - return ScopedInterfaceEndpointHandle(id, this); -} - -bool AssociatedGroupController::NotifyAssociation( - ScopedInterfaceEndpointHandle* handle_to_send, - InterfaceId id) { - return handle_to_send->NotifyAssociation(id, this); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc b/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc deleted file mode 100644 index 78281ed..0000000 --- a/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/associated_interface_ptr.h" - -namespace mojo { - -void GetIsolatedInterface(ScopedInterfaceEndpointHandle handle) { - MessagePipe pipe; - scoped_refptr router = - new internal::MultiplexRouter(std::move(pipe.handle0), - internal::MultiplexRouter::MULTI_INTERFACE, - false, base::ThreadTaskRunnerHandle::Get()); - router->AssociateInterface(std::move(handle)); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h deleted file mode 100644 index a4b5188..0000000 --- a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ - -#include - -#include // For |std::swap()|. -#include -#include -#include - -#include "base/bind.h" -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/associated_group.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace mojo { -namespace internal { - -template -class AssociatedInterfacePtrState { - public: - AssociatedInterfacePtrState() : version_(0u) {} - - ~AssociatedInterfacePtrState() { - endpoint_client_.reset(); - proxy_.reset(); - } - - Interface* instance() { - // This will be null if the object is not bound. - return proxy_.get(); - } - - uint32_t version() const { return version_; } - - void QueryVersion(const base::Callback& callback) { - // It is safe to capture |this| because the callback won't be run after this - // object goes away. - endpoint_client_->QueryVersion( - base::Bind(&AssociatedInterfacePtrState::OnQueryVersion, - base::Unretained(this), callback)); - } - - void RequireVersion(uint32_t version) { - if (version <= version_) - return; - - version_ = version; - endpoint_client_->RequireVersion(version); - } - - void FlushForTesting() { endpoint_client_->FlushForTesting(); } - - void CloseWithReason(uint32_t custom_reason, const std::string& description) { - endpoint_client_->CloseWithReason(custom_reason, description); - } - - void Swap(AssociatedInterfacePtrState* other) { - using std::swap; - swap(other->endpoint_client_, endpoint_client_); - swap(other->proxy_, proxy_); - swap(other->version_, version_); - } - - void Bind(AssociatedInterfacePtrInfo info, - scoped_refptr runner) { - DCHECK(!endpoint_client_); - DCHECK(!proxy_); - DCHECK_EQ(0u, version_); - DCHECK(info.is_valid()); - - version_ = info.version(); - // The version is only queried from the client so the value passed here - // will not be used. - endpoint_client_.reset(new InterfaceEndpointClient( - info.PassHandle(), nullptr, - base::WrapUnique(new typename Interface::ResponseValidator_()), false, - std::move(runner), 0u)); - proxy_.reset(new Proxy(endpoint_client_.get())); - } - - // After this method is called, the object is in an invalid state and - // shouldn't be reused. - AssociatedInterfacePtrInfo PassInterface() { - ScopedInterfaceEndpointHandle handle = endpoint_client_->PassHandle(); - endpoint_client_.reset(); - proxy_.reset(); - return AssociatedInterfacePtrInfo(std::move(handle), version_); - } - - bool is_bound() const { return !!endpoint_client_; } - - bool encountered_error() const { - return endpoint_client_ ? endpoint_client_->encountered_error() : false; - } - - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(endpoint_client_); - endpoint_client_->set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(endpoint_client_); - endpoint_client_->set_connection_error_with_reason_handler(error_handler); - } - - // Returns true if bound and awaiting a response to a message. - bool has_pending_callbacks() const { - return endpoint_client_ && endpoint_client_->has_pending_responders(); - } - - AssociatedGroup* associated_group() { - return endpoint_client_ ? endpoint_client_->associated_group() : nullptr; - } - - void ForwardMessage(Message message) { endpoint_client_->Accept(&message); } - - void ForwardMessageWithResponder(Message message, - std::unique_ptr responder) { - endpoint_client_->AcceptWithResponder(&message, std::move(responder)); - } - - private: - using Proxy = typename Interface::Proxy_; - - void OnQueryVersion(const base::Callback& callback, - uint32_t version) { - version_ = version; - callback.Run(version); - } - - std::unique_ptr endpoint_client_; - std::unique_ptr proxy_; - - uint32_t version_; - - DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrState); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_ diff --git a/mojo/public/cpp/bindings/lib/binding_state.cc b/mojo/public/cpp/bindings/lib/binding_state.cc deleted file mode 100644 index b34cb47..0000000 --- a/mojo/public/cpp/bindings/lib/binding_state.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/binding_state.h" - -namespace mojo { -namespace internal { - -BindingStateBase::BindingStateBase() = default; - -BindingStateBase::~BindingStateBase() = default; - -void BindingStateBase::AddFilter(std::unique_ptr filter) { - DCHECK(endpoint_client_); - endpoint_client_->AddFilter(std::move(filter)); -} - -bool BindingStateBase::HasAssociatedInterfaces() const { - return router_ ? router_->HasAssociatedEndpoints() : false; -} - -void BindingStateBase::PauseIncomingMethodCallProcessing() { - DCHECK(router_); - router_->PauseIncomingMethodCallProcessing(); -} -void BindingStateBase::ResumeIncomingMethodCallProcessing() { - DCHECK(router_); - router_->ResumeIncomingMethodCallProcessing(); -} - -bool BindingStateBase::WaitForIncomingMethodCall(MojoDeadline deadline) { - DCHECK(router_); - return router_->WaitForIncomingMessage(deadline); -} - -void BindingStateBase::Close() { - if (!router_) - return; - - endpoint_client_.reset(); - router_->CloseMessagePipe(); - router_ = nullptr; -} - -void BindingStateBase::CloseWithReason(uint32_t custom_reason, - const std::string& description) { - if (endpoint_client_) - endpoint_client_->CloseWithReason(custom_reason, description); - - Close(); -} - -void BindingStateBase::FlushForTesting() { - endpoint_client_->FlushForTesting(); -} - -void BindingStateBase::EnableTestingMode() { - DCHECK(is_bound()); - router_->EnableTestingMode(); -} - -void BindingStateBase::BindInternal( - ScopedMessagePipeHandle handle, - scoped_refptr runner, - const char* interface_name, - std::unique_ptr request_validator, - bool passes_associated_kinds, - bool has_sync_methods, - MessageReceiverWithResponderStatus* stub, - uint32_t interface_version) { - DCHECK(!router_); - - MultiplexRouter::Config config = - passes_associated_kinds - ? MultiplexRouter::MULTI_INTERFACE - : (has_sync_methods - ? MultiplexRouter::SINGLE_INTERFACE_WITH_SYNC_METHODS - : MultiplexRouter::SINGLE_INTERFACE); - router_ = new MultiplexRouter(std::move(handle), config, false, runner); - router_->SetMasterInterfaceName(interface_name); - - endpoint_client_.reset(new InterfaceEndpointClient( - router_->CreateLocalEndpointHandle(kMasterInterfaceId), stub, - std::move(request_validator), has_sync_methods, std::move(runner), - interface_version)); -} - -} // namesapce internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h deleted file mode 100644 index 0b0dbee..0000000 --- a/mojo/public/cpp/bindings/lib/binding_state.h +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ - -#include -#include -#include - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/bindings/message_header_validator.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace internal { - -class MOJO_CPP_BINDINGS_EXPORT BindingStateBase { - public: - BindingStateBase(); - ~BindingStateBase(); - - void AddFilter(std::unique_ptr filter); - - bool HasAssociatedInterfaces() const; - - void PauseIncomingMethodCallProcessing(); - void ResumeIncomingMethodCallProcessing(); - - bool WaitForIncomingMethodCall( - MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE); - - void Close(); - void CloseWithReason(uint32_t custom_reason, const std::string& description); - - void set_connection_error_handler(const base::Closure& error_handler) { - DCHECK(is_bound()); - endpoint_client_->set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - DCHECK(is_bound()); - endpoint_client_->set_connection_error_with_reason_handler(error_handler); - } - - bool is_bound() const { return !!router_; } - - MessagePipeHandle handle() const { - DCHECK(is_bound()); - return router_->handle(); - } - - void FlushForTesting(); - - void EnableTestingMode(); - - protected: - void BindInternal(ScopedMessagePipeHandle handle, - scoped_refptr runner, - const char* interface_name, - std::unique_ptr request_validator, - bool passes_associated_kinds, - bool has_sync_methods, - MessageReceiverWithResponderStatus* stub, - uint32_t interface_version); - - scoped_refptr router_; - std::unique_ptr endpoint_client_; -}; - -template -class BindingState : public BindingStateBase { - public: - using ImplPointerType = typename ImplRefTraits::PointerType; - - explicit BindingState(ImplPointerType impl) { - stub_.set_sink(std::move(impl)); - } - - ~BindingState() { Close(); } - - void Bind(ScopedMessagePipeHandle handle, - scoped_refptr runner) { - BindingStateBase::BindInternal( - std::move(handle), runner, Interface::Name_, - base::MakeUnique(), - Interface::PassesAssociatedKinds_, Interface::HasSyncMethods_, &stub_, - Interface::Version_); - } - - InterfaceRequest Unbind() { - endpoint_client_.reset(); - InterfaceRequest request = - MakeRequest(router_->PassMessagePipe()); - router_ = nullptr; - return request; - } - - Interface* impl() { return ImplRefTraits::GetRawPointer(&stub_.sink()); } - - private: - typename Interface::template Stub_ stub_; - - DISALLOW_COPY_AND_ASSIGN(BindingState); -}; - -} // namesapce internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h deleted file mode 100644 index 631daec..0000000 --- a/mojo/public/cpp/bindings/lib/bindings_internal.h +++ /dev/null @@ -1,336 +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_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_ - -#include - -#include - -#include "base/template_util.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { - -template -class ArrayDataView; - -template -class AssociatedInterfacePtrInfoDataView; - -template -class AssociatedInterfaceRequestDataView; - -template -class InterfacePtrDataView; - -template -class InterfaceRequestDataView; - -template -class MapDataView; - -class NativeStructDataView; - -class StringDataView; - -namespace internal { - -// Please note that this is a different value than |mojo::kInvalidHandleValue|, -// which is the "decoded" invalid handle. -const uint32_t kEncodedInvalidHandleValue = static_cast(-1); - -// A serialized union always takes 16 bytes: -// 4-byte size + 4-byte tag + 8-byte payload. -const uint32_t kUnionDataSize = 16; - -template -class Array_Data; - -template -class Map_Data; - -class NativeStruct_Data; - -using String_Data = Array_Data; - -inline size_t Align(size_t size) { - return (size + 7) & ~0x7; -} - -inline bool IsAligned(const void* ptr) { - return !(reinterpret_cast(ptr) & 0x7); -} - -// Pointers are encoded as relative offsets. The offsets are relative to the -// address of where the offset value is stored, such that the pointer may be -// recovered with the expression: -// -// ptr = reinterpret_cast(offset) + *offset -// -// A null pointer is encoded as an offset value of 0. -// -inline void EncodePointer(const void* ptr, uint64_t* offset) { - if (!ptr) { - *offset = 0; - return; - } - - const char* p_obj = reinterpret_cast(ptr); - const char* p_slot = reinterpret_cast(offset); - DCHECK(p_obj > p_slot); - - *offset = static_cast(p_obj - p_slot); -} - -// Note: This function doesn't validate the encoded pointer value. -inline const void* DecodePointer(const uint64_t* offset) { - if (!*offset) - return nullptr; - return reinterpret_cast(offset) + *offset; -} - -#pragma pack(push, 1) - -struct StructHeader { - uint32_t num_bytes; - uint32_t version; -}; -static_assert(sizeof(StructHeader) == 8, "Bad sizeof(StructHeader)"); - -struct ArrayHeader { - uint32_t num_bytes; - uint32_t num_elements; -}; -static_assert(sizeof(ArrayHeader) == 8, "Bad_sizeof(ArrayHeader)"); - -template -struct Pointer { - using BaseType = T; - - void Set(T* ptr) { EncodePointer(ptr, &offset); } - const T* Get() const { return static_cast(DecodePointer(&offset)); } - T* Get() { - return static_cast(const_cast(DecodePointer(&offset))); - } - - bool is_null() const { return offset == 0; } - - uint64_t offset; -}; -static_assert(sizeof(Pointer) == 8, "Bad_sizeof(Pointer)"); - -using GenericPointer = Pointer; - -struct Handle_Data { - Handle_Data() = default; - explicit Handle_Data(uint32_t value) : value(value) {} - - bool is_valid() const { return value != kEncodedInvalidHandleValue; } - - uint32_t value; -}; -static_assert(sizeof(Handle_Data) == 4, "Bad_sizeof(Handle_Data)"); - -struct Interface_Data { - Handle_Data handle; - uint32_t version; -}; -static_assert(sizeof(Interface_Data) == 8, "Bad_sizeof(Interface_Data)"); - -struct AssociatedEndpointHandle_Data { - AssociatedEndpointHandle_Data() = default; - explicit AssociatedEndpointHandle_Data(uint32_t value) : value(value) {} - - bool is_valid() const { return value != kEncodedInvalidHandleValue; } - - uint32_t value; -}; -static_assert(sizeof(AssociatedEndpointHandle_Data) == 4, - "Bad_sizeof(AssociatedEndpointHandle_Data)"); - -struct AssociatedInterface_Data { - AssociatedEndpointHandle_Data handle; - uint32_t version; -}; -static_assert(sizeof(AssociatedInterface_Data) == 8, - "Bad_sizeof(AssociatedInterface_Data)"); - -#pragma pack(pop) - -template -T FetchAndReset(T* ptr) { - T temp = *ptr; - *ptr = T(); - return temp; -} - -template -struct IsUnionDataType { - private: - template - static YesType Test(const typename U::MojomUnionDataType*); - - template - static NoType Test(...); - - EnsureTypeIsComplete check_t_; - - public: - static const bool value = - sizeof(Test(0)) == sizeof(YesType) && !IsConst::value; -}; - -enum class MojomTypeCategory : uint32_t { - ARRAY = 1 << 0, - ASSOCIATED_INTERFACE = 1 << 1, - ASSOCIATED_INTERFACE_REQUEST = 1 << 2, - BOOLEAN = 1 << 3, - ENUM = 1 << 4, - HANDLE = 1 << 5, - INTERFACE = 1 << 6, - INTERFACE_REQUEST = 1 << 7, - MAP = 1 << 8, - // POD except boolean and enum. - POD = 1 << 9, - STRING = 1 << 10, - STRUCT = 1 << 11, - UNION = 1 << 12 -}; - -inline constexpr MojomTypeCategory operator&(MojomTypeCategory x, - MojomTypeCategory y) { - return static_cast(static_cast(x) & - static_cast(y)); -} - -inline constexpr MojomTypeCategory operator|(MojomTypeCategory x, - MojomTypeCategory y) { - return static_cast(static_cast(x) | - static_cast(y)); -} - -template ::value> -struct MojomTypeTraits { - using Data = T; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::POD; -}; - -template -struct MojomTypeTraits, false> { - using Data = Array_Data::DataAsArrayElement>; - using DataAsArrayElement = Pointer; - - static const MojomTypeCategory category = MojomTypeCategory::ARRAY; -}; - -template -struct MojomTypeTraits, false> { - using Data = AssociatedInterface_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = - MojomTypeCategory::ASSOCIATED_INTERFACE; -}; - -template -struct MojomTypeTraits, false> { - using Data = AssociatedEndpointHandle_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = - MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST; -}; - -template <> -struct MojomTypeTraits { - using Data = bool; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::BOOLEAN; -}; - -template -struct MojomTypeTraits { - using Data = int32_t; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::ENUM; -}; - -template -struct MojomTypeTraits, false> { - using Data = Handle_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::HANDLE; -}; - -template -struct MojomTypeTraits, false> { - using Data = Interface_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = MojomTypeCategory::INTERFACE; -}; - -template -struct MojomTypeTraits, false> { - using Data = Handle_Data; - using DataAsArrayElement = Data; - - static const MojomTypeCategory category = - MojomTypeCategory::INTERFACE_REQUEST; -}; - -template -struct MojomTypeTraits, false> { - using Data = Map_Data::DataAsArrayElement, - typename MojomTypeTraits::DataAsArrayElement>; - using DataAsArrayElement = Pointer; - - static const MojomTypeCategory category = MojomTypeCategory::MAP; -}; - -template <> -struct MojomTypeTraits { - using Data = internal::NativeStruct_Data; - using DataAsArrayElement = Pointer; - - static const MojomTypeCategory category = MojomTypeCategory::STRUCT; -}; - -template <> -struct MojomTypeTraits { - using Data = String_Data; - using DataAsArrayElement = Pointer; - - static const MojomTypeCategory category = MojomTypeCategory::STRING; -}; - -template -struct BelongsTo { - static const bool value = - static_cast(MojomTypeTraits::category & categories) != 0; -}; - -template -struct EnumHashImpl { - static_assert(std::is_enum::value, "Incorrect hash function."); - - size_t operator()(T input) const { - using UnderlyingType = typename base::underlying_type::type; - return std::hash()(static_cast(input)); - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_ diff --git a/mojo/public/cpp/bindings/lib/buffer.h b/mojo/public/cpp/bindings/lib/buffer.h deleted file mode 100644 index 213a445..0000000 --- a/mojo/public/cpp/bindings/lib/buffer.h +++ /dev/null @@ -1,70 +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_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ - -#include - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" - -namespace mojo { -namespace internal { - -// Buffer provides an interface to allocate memory blocks which are 8-byte -// aligned and zero-initialized. It doesn't own the underlying memory. Users -// must ensure that the memory stays valid while using the allocated blocks from -// Buffer. -class Buffer { - public: - Buffer() {} - - // The memory must have been zero-initialized. |data| must be 8-byte - // aligned. - void Initialize(void* data, size_t size) { - DCHECK(IsAligned(data)); - - data_ = data; - size_ = size; - cursor_ = reinterpret_cast(data); - data_end_ = cursor_ + size; - } - - size_t size() const { return size_; } - - void* data() const { return data_; } - - // Allocates |num_bytes| from the buffer and returns a pointer to the start of - // the allocated block. - // The resulting address is 8-byte aligned, and the content of the memory is - // zero-filled. - void* Allocate(size_t num_bytes) { - num_bytes = Align(num_bytes); - uintptr_t result = cursor_; - cursor_ += num_bytes; - if (cursor_ > data_end_ || cursor_ < result) { - NOTREACHED(); - cursor_ -= num_bytes; - return nullptr; - } - - return reinterpret_cast(result); - } - - private: - void* data_ = nullptr; - size_t size_ = 0; - - uintptr_t cursor_ = 0; - uintptr_t data_end_ = 0; - - DISALLOW_COPY_AND_ASSIGN(Buffer); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc deleted file mode 100644 index d93e45e..0000000 --- a/mojo/public/cpp/bindings/lib/connector.cc +++ /dev/null @@ -1,493 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/connector.h" - -#include -#include - -#include "base/bind.h" -#include "base/lazy_instance.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread_local.h" -#include "mojo/public/cpp/bindings/lib/may_auto_lock.h" -#include "mojo/public/cpp/bindings/sync_handle_watcher.h" -#include "mojo/public/cpp/system/wait.h" - -namespace mojo { - -namespace { - -// The NestingObserver for each thread. Note that this is always a -// Connector::MessageLoopNestingObserver; we use the base type here because that -// subclass is private to Connector. -base::LazyInstance< - base::ThreadLocalPointer>::Leaky - g_tls_nesting_observer = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// Used to efficiently maintain a doubly-linked list of all Connectors -// currently dispatching on any given thread. -class Connector::ActiveDispatchTracker { - public: - explicit ActiveDispatchTracker(const base::WeakPtr& connector); - ~ActiveDispatchTracker(); - - void NotifyBeginNesting(); - - private: - const base::WeakPtr connector_; - MessageLoopNestingObserver* const nesting_observer_; - ActiveDispatchTracker* outer_tracker_ = nullptr; - ActiveDispatchTracker* inner_tracker_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(ActiveDispatchTracker); -}; - -// Watches the MessageLoop on the current thread. Notifies the current chain of -// ActiveDispatchTrackers when a nested message loop is started. -class Connector::MessageLoopNestingObserver - : public base::MessageLoop::NestingObserver, - public base::MessageLoop::DestructionObserver { - public: - MessageLoopNestingObserver() { - base::MessageLoop::current()->AddNestingObserver(this); - base::MessageLoop::current()->AddDestructionObserver(this); - } - - ~MessageLoopNestingObserver() override {} - - // base::MessageLoop::NestingObserver: - void OnBeginNestedMessageLoop() override { - if (top_tracker_) - top_tracker_->NotifyBeginNesting(); - } - - // base::MessageLoop::DestructionObserver: - void WillDestroyCurrentMessageLoop() override { - base::MessageLoop::current()->RemoveNestingObserver(this); - base::MessageLoop::current()->RemoveDestructionObserver(this); - DCHECK_EQ(this, g_tls_nesting_observer.Get().Get()); - g_tls_nesting_observer.Get().Set(nullptr); - delete this; - } - - static MessageLoopNestingObserver* GetForThread() { - if (!base::MessageLoop::current() || - !base::MessageLoop::current()->nesting_allowed()) - return nullptr; - auto* observer = static_cast( - g_tls_nesting_observer.Get().Get()); - if (!observer) { - observer = new MessageLoopNestingObserver; - g_tls_nesting_observer.Get().Set(observer); - } - return observer; - } - - private: - friend class ActiveDispatchTracker; - - ActiveDispatchTracker* top_tracker_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(MessageLoopNestingObserver); -}; - -Connector::ActiveDispatchTracker::ActiveDispatchTracker( - const base::WeakPtr& connector) - : connector_(connector), nesting_observer_(connector_->nesting_observer_) { - DCHECK(nesting_observer_); - if (nesting_observer_->top_tracker_) { - outer_tracker_ = nesting_observer_->top_tracker_; - outer_tracker_->inner_tracker_ = this; - } - nesting_observer_->top_tracker_ = this; -} - -Connector::ActiveDispatchTracker::~ActiveDispatchTracker() { - if (nesting_observer_->top_tracker_ == this) - nesting_observer_->top_tracker_ = outer_tracker_; - else if (inner_tracker_) - inner_tracker_->outer_tracker_ = outer_tracker_; - if (outer_tracker_) - outer_tracker_->inner_tracker_ = inner_tracker_; -} - -void Connector::ActiveDispatchTracker::NotifyBeginNesting() { - if (connector_ && connector_->handle_watcher_) - connector_->handle_watcher_->ArmOrNotify(); - if (outer_tracker_) - outer_tracker_->NotifyBeginNesting(); -} - -Connector::Connector(ScopedMessagePipeHandle message_pipe, - ConnectorConfig config, - scoped_refptr runner) - : message_pipe_(std::move(message_pipe)), - task_runner_(std::move(runner)), - nesting_observer_(MessageLoopNestingObserver::GetForThread()), - weak_factory_(this) { - if (config == MULTI_THREADED_SEND) - lock_.emplace(); - - weak_self_ = weak_factory_.GetWeakPtr(); - // Even though we don't have an incoming receiver, we still want to monitor - // the message pipe to know if is closed or encounters an error. - WaitToReadMore(); -} - -Connector::~Connector() { - { - // Allow for quick destruction on any thread if the pipe is already closed. - base::AutoLock lock(connected_lock_); - if (!connected_) - return; - } - - DCHECK(thread_checker_.CalledOnValidThread()); - CancelWait(); -} - -void Connector::CloseMessagePipe() { - // Throw away the returned message pipe. - PassMessagePipe(); -} - -ScopedMessagePipeHandle Connector::PassMessagePipe() { - DCHECK(thread_checker_.CalledOnValidThread()); - - CancelWait(); - internal::MayAutoLock locker(&lock_); - ScopedMessagePipeHandle message_pipe = std::move(message_pipe_); - weak_factory_.InvalidateWeakPtrs(); - sync_handle_watcher_callback_count_ = 0; - - base::AutoLock lock(connected_lock_); - connected_ = false; - return message_pipe; -} - -void Connector::RaiseError() { - DCHECK(thread_checker_.CalledOnValidThread()); - - HandleError(true, true); -} - -bool Connector::WaitForIncomingMessage(MojoDeadline deadline) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (error_) - return false; - - ResumeIncomingMethodCallProcessing(); - - // TODO(rockot): Use a timed Wait here. Nobody uses anything but 0 or - // INDEFINITE deadlines at present, so we only support those. - DCHECK(deadline == 0 || deadline == MOJO_DEADLINE_INDEFINITE); - - MojoResult rv = MOJO_RESULT_UNKNOWN; - if (deadline == 0 && !message_pipe_->QuerySignalsState().readable()) - return false; - - if (deadline == MOJO_DEADLINE_INDEFINITE) { - rv = Wait(message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE); - if (rv != MOJO_RESULT_OK) { - // Users that call WaitForIncomingMessage() should expect their code to be - // re-entered, so we call the error handler synchronously. - HandleError(rv != MOJO_RESULT_FAILED_PRECONDITION, false); - return false; - } - } - - ignore_result(ReadSingleMessage(&rv)); - return (rv == MOJO_RESULT_OK); -} - -void Connector::PauseIncomingMethodCallProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (paused_) - return; - - paused_ = true; - CancelWait(); -} - -void Connector::ResumeIncomingMethodCallProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!paused_) - return; - - paused_ = false; - WaitToReadMore(); -} - -bool Connector::Accept(Message* message) { - DCHECK(lock_ || thread_checker_.CalledOnValidThread()); - - // It shouldn't hurt even if |error_| may be changed by a different thread at - // the same time. The outcome is that we may write into |message_pipe_| after - // encountering an error, which should be fine. - if (error_) - return false; - - internal::MayAutoLock locker(&lock_); - - if (!message_pipe_.is_valid() || drop_writes_) - return true; - - MojoResult rv = - WriteMessageNew(message_pipe_.get(), message->TakeMojoMessage(), - MOJO_WRITE_MESSAGE_FLAG_NONE); - - switch (rv) { - case MOJO_RESULT_OK: - break; - case MOJO_RESULT_FAILED_PRECONDITION: - // There's no point in continuing to write to this pipe since the other - // end is gone. Avoid writing any future messages. Hide write failures - // from the caller since we'd like them to continue consuming any backlog - // of incoming messages before regarding the message pipe as closed. - drop_writes_ = true; - break; - case MOJO_RESULT_BUSY: - // We'd get a "busy" result if one of the message's handles is: - // - |message_pipe_|'s own handle; - // - simultaneously being used on another thread; or - // - in a "busy" state that prohibits it from being transferred (e.g., - // a data pipe handle in the middle of a two-phase read/write, - // regardless of which thread that two-phase read/write is happening - // on). - // TODO(vtl): I wonder if this should be a |DCHECK()|. (But, until - // crbug.com/389666, etc. are resolved, this will make tests fail quickly - // rather than hanging.) - CHECK(false) << "Race condition or other bug detected"; - return false; - default: - // This particular write was rejected, presumably because of bad input. - // The pipe is not necessarily in a bad state. - return false; - } - return true; -} - -void Connector::AllowWokenUpBySyncWatchOnSameThread() { - DCHECK(thread_checker_.CalledOnValidThread()); - - allow_woken_up_by_others_ = true; - - EnsureSyncWatcherExists(); - sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); -} - -bool Connector::SyncWatch(const bool* should_stop) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (error_) - return false; - - ResumeIncomingMethodCallProcessing(); - - EnsureSyncWatcherExists(); - return sync_watcher_->SyncWatch(should_stop); -} - -void Connector::SetWatcherHeapProfilerTag(const char* tag) { - heap_profiler_tag_ = tag; - if (handle_watcher_) { - handle_watcher_->set_heap_profiler_tag(tag); - } -} - -void Connector::OnWatcherHandleReady(MojoResult result) { - OnHandleReadyInternal(result); -} - -void Connector::OnSyncHandleWatcherHandleReady(MojoResult result) { - base::WeakPtr weak_self(weak_self_); - - sync_handle_watcher_callback_count_++; - OnHandleReadyInternal(result); - // At this point, this object might have been deleted. - if (weak_self) { - DCHECK_LT(0u, sync_handle_watcher_callback_count_); - sync_handle_watcher_callback_count_--; - } -} - -void Connector::OnHandleReadyInternal(MojoResult result) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (result != MOJO_RESULT_OK) { - HandleError(result != MOJO_RESULT_FAILED_PRECONDITION, false); - return; - } - - ReadAllAvailableMessages(); - // At this point, this object might have been deleted. Return. -} - -void Connector::WaitToReadMore() { - CHECK(!paused_); - DCHECK(!handle_watcher_); - - handle_watcher_.reset(new SimpleWatcher( - FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL, task_runner_)); - if (heap_profiler_tag_) - handle_watcher_->set_heap_profiler_tag(heap_profiler_tag_); - MojoResult rv = handle_watcher_->Watch( - message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&Connector::OnWatcherHandleReady, base::Unretained(this))); - - if (rv != MOJO_RESULT_OK) { - // If the watch failed because the handle is invalid or its conditions can - // no longer be met, we signal the error asynchronously to avoid reentry. - task_runner_->PostTask( - FROM_HERE, - base::Bind(&Connector::OnWatcherHandleReady, weak_self_, rv)); - } else { - handle_watcher_->ArmOrNotify(); - } - - if (allow_woken_up_by_others_) { - EnsureSyncWatcherExists(); - sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); - } -} - -bool Connector::ReadSingleMessage(MojoResult* read_result) { - CHECK(!paused_); - - bool receiver_result = false; - - // Detect if |this| was destroyed or the message pipe was closed/transferred - // during message dispatch. - base::WeakPtr weak_self = weak_self_; - - Message message; - const MojoResult rv = ReadMessage(message_pipe_.get(), &message); - *read_result = rv; - - if (rv == MOJO_RESULT_OK) { - base::Optional dispatch_tracker; - if (!is_dispatching_ && nesting_observer_) { - is_dispatching_ = true; - dispatch_tracker.emplace(weak_self); - } - - receiver_result = - incoming_receiver_ && incoming_receiver_->Accept(&message); - - if (!weak_self) - return false; - - if (dispatch_tracker) { - is_dispatching_ = false; - dispatch_tracker.reset(); - } - } else if (rv == MOJO_RESULT_SHOULD_WAIT) { - return true; - } else { - HandleError(rv != MOJO_RESULT_FAILED_PRECONDITION, false); - return false; - } - - if (enforce_errors_from_incoming_receiver_ && !receiver_result) { - HandleError(true, false); - return false; - } - return true; -} - -void Connector::ReadAllAvailableMessages() { - while (!error_) { - base::WeakPtr weak_self = weak_self_; - MojoResult rv; - - // May delete |this.| - if (!ReadSingleMessage(&rv)) - return; - - if (!weak_self || paused_) - return; - - DCHECK(rv == MOJO_RESULT_OK || rv == MOJO_RESULT_SHOULD_WAIT); - - if (rv == MOJO_RESULT_SHOULD_WAIT) { - // Attempt to re-arm the Watcher. - MojoResult ready_result; - MojoResult arm_result = handle_watcher_->Arm(&ready_result); - if (arm_result == MOJO_RESULT_OK) - return; - - // The watcher is already ready to notify again. - DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, arm_result); - - if (ready_result == MOJO_RESULT_FAILED_PRECONDITION) { - HandleError(false, false); - return; - } - - // There's more to read now, so we'll just keep looping. - DCHECK_EQ(MOJO_RESULT_OK, ready_result); - } - } -} - -void Connector::CancelWait() { - handle_watcher_.reset(); - sync_watcher_.reset(); -} - -void Connector::HandleError(bool force_pipe_reset, bool force_async_handler) { - if (error_ || !message_pipe_.is_valid()) - return; - - if (paused_) { - // Enforce calling the error handler asynchronously if the user has paused - // receiving messages. We need to wait until the user starts receiving - // messages again. - force_async_handler = true; - } - - if (!force_pipe_reset && force_async_handler) - force_pipe_reset = true; - - if (force_pipe_reset) { - CancelWait(); - internal::MayAutoLock locker(&lock_); - message_pipe_.reset(); - MessagePipe dummy_pipe; - message_pipe_ = std::move(dummy_pipe.handle0); - } else { - CancelWait(); - } - - if (force_async_handler) { - if (!paused_) - WaitToReadMore(); - } else { - error_ = true; - if (!connection_error_handler_.is_null()) - connection_error_handler_.Run(); - } -} - -void Connector::EnsureSyncWatcherExists() { - if (sync_watcher_) - return; - sync_watcher_.reset(new SyncHandleWatcher( - message_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&Connector::OnSyncHandleWatcherHandleReady, - base::Unretained(this)))); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.cc b/mojo/public/cpp/bindings/lib/control_message_handler.cc deleted file mode 100644 index 1b7bb78..0000000 --- a/mojo/public/cpp/bindings/lib/control_message_handler.cc +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/control_message_handler.h" - -#include -#include -#include - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" -#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" - -namespace mojo { -namespace internal { -namespace { - -bool ValidateControlRequestWithResponse(Message* message) { - ValidationContext validation_context(message->payload(), - message->payload_num_bytes(), 0, 0, - message, "ControlRequestValidator"); - if (!ValidateMessageIsRequestExpectingResponse(message, &validation_context)) - return false; - - switch (message->header()->name) { - case interface_control::kRunMessageId: - return ValidateMessagePayload< - interface_control::internal::RunMessageParams_Data>( - message, &validation_context); - } - return false; -} - -bool ValidateControlRequestWithoutResponse(Message* message) { - ValidationContext validation_context(message->payload(), - message->payload_num_bytes(), 0, 0, - message, "ControlRequestValidator"); - if (!ValidateMessageIsRequestWithoutResponse(message, &validation_context)) - return false; - - switch (message->header()->name) { - case interface_control::kRunOrClosePipeMessageId: - return ValidateMessageIsRequestWithoutResponse(message, - &validation_context) && - ValidateMessagePayload< - interface_control::internal::RunOrClosePipeMessageParams_Data>( - message, &validation_context); - } - return false; -} - -} // namespace - -// static -bool ControlMessageHandler::IsControlMessage(const Message* message) { - return message->header()->name == interface_control::kRunMessageId || - message->header()->name == interface_control::kRunOrClosePipeMessageId; -} - -ControlMessageHandler::ControlMessageHandler(uint32_t interface_version) - : interface_version_(interface_version) { -} - -ControlMessageHandler::~ControlMessageHandler() { -} - -bool ControlMessageHandler::Accept(Message* message) { - if (!ValidateControlRequestWithoutResponse(message)) - return false; - - if (message->header()->name == interface_control::kRunOrClosePipeMessageId) - return RunOrClosePipe(message); - - NOTREACHED(); - return false; -} - -bool ControlMessageHandler::AcceptWithResponder( - Message* message, - std::unique_ptr responder) { - if (!ValidateControlRequestWithResponse(message)) - return false; - - if (message->header()->name == interface_control::kRunMessageId) - return Run(message, std::move(responder)); - - NOTREACHED(); - return false; -} - -bool ControlMessageHandler::Run( - Message* message, - std::unique_ptr responder) { - interface_control::internal::RunMessageParams_Data* params = - reinterpret_cast( - message->mutable_payload()); - interface_control::RunMessageParamsPtr params_ptr; - Deserialize(params, ¶ms_ptr, - &context_); - auto& input = *params_ptr->input; - interface_control::RunOutputPtr output = interface_control::RunOutput::New(); - if (input.is_query_version()) { - output->set_query_version_result( - interface_control::QueryVersionResult::New()); - output->get_query_version_result()->version = interface_version_; - } else if (input.is_flush_for_testing()) { - output.reset(); - } else { - output.reset(); - } - - auto response_params_ptr = interface_control::RunResponseMessageParams::New(); - response_params_ptr->output = std::move(output); - size_t size = - PrepareToSerialize( - response_params_ptr, &context_); - MessageBuilder builder(interface_control::kRunMessageId, - Message::kFlagIsResponse, size, 0); - builder.message()->set_request_id(message->request_id()); - - interface_control::internal::RunResponseMessageParams_Data* response_params = - nullptr; - Serialize( - response_params_ptr, builder.buffer(), &response_params, &context_); - ignore_result(responder->Accept(builder.message())); - - return true; -} - -bool ControlMessageHandler::RunOrClosePipe(Message* message) { - interface_control::internal::RunOrClosePipeMessageParams_Data* params = - reinterpret_cast< - interface_control::internal::RunOrClosePipeMessageParams_Data*>( - message->mutable_payload()); - interface_control::RunOrClosePipeMessageParamsPtr params_ptr; - Deserialize( - params, ¶ms_ptr, &context_); - auto& input = *params_ptr->input; - if (input.is_require_version()) - return interface_version_ >= input.get_require_version()->version; - - return false; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.h b/mojo/public/cpp/bindings/lib/control_message_handler.h deleted file mode 100644 index 5d1f716..0000000 --- a/mojo/public/cpp/bindings/lib/control_message_handler.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_HANDLER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_HANDLER_H_ - -#include - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { -namespace internal { - -// Handlers for request messages defined in interface_control_messages.mojom. -class MOJO_CPP_BINDINGS_EXPORT ControlMessageHandler - : NON_EXPORTED_BASE(public MessageReceiverWithResponderStatus) { - public: - static bool IsControlMessage(const Message* message); - - explicit ControlMessageHandler(uint32_t interface_version); - ~ControlMessageHandler() override; - - // Call the following methods only if IsControlMessage() returned true. - bool Accept(Message* message) override; - bool AcceptWithResponder( - Message* message, - std::unique_ptr responder) override; - - private: - bool Run(Message* message, - std::unique_ptr responder); - bool RunOrClosePipe(Message* message); - - uint32_t interface_version_; - SerializationContext context_; - - DISALLOW_COPY_AND_ASSIGN(ControlMessageHandler); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_HANDLER_H_ diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/mojo/public/cpp/bindings/lib/control_message_proxy.cc deleted file mode 100644 index d082b49..0000000 --- a/mojo/public/cpp/bindings/lib/control_message_proxy.cc +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/control_message_proxy.h" - -#include -#include -#include - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" -#include "mojo/public/cpp/bindings/message.h" -#include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" - -namespace mojo { -namespace internal { - -namespace { - -bool ValidateControlResponse(Message* message) { - ValidationContext validation_context(message->payload(), - message->payload_num_bytes(), 0, 0, - message, "ControlResponseValidator"); - if (!ValidateMessageIsResponse(message, &validation_context)) - return false; - - switch (message->header()->name) { - case interface_control::kRunMessageId: - return ValidateMessagePayload< - interface_control::internal::RunResponseMessageParams_Data>( - message, &validation_context); - } - return false; -} - -using RunCallback = - base::Callback; - -class RunResponseForwardToCallback : public MessageReceiver { - public: - explicit RunResponseForwardToCallback(const RunCallback& callback) - : callback_(callback) {} - bool Accept(Message* message) override; - - private: - RunCallback callback_; - DISALLOW_COPY_AND_ASSIGN(RunResponseForwardToCallback); -}; - -bool RunResponseForwardToCallback::Accept(Message* message) { - if (!ValidateControlResponse(message)) - return false; - - interface_control::internal::RunResponseMessageParams_Data* params = - reinterpret_cast< - interface_control::internal::RunResponseMessageParams_Data*>( - message->mutable_payload()); - interface_control::RunResponseMessageParamsPtr params_ptr; - SerializationContext context; - Deserialize( - params, ¶ms_ptr, &context); - - callback_.Run(std::move(params_ptr)); - return true; -} - -void SendRunMessage(MessageReceiverWithResponder* receiver, - interface_control::RunInputPtr input_ptr, - const RunCallback& callback) { - SerializationContext context; - - auto params_ptr = interface_control::RunMessageParams::New(); - params_ptr->input = std::move(input_ptr); - size_t size = PrepareToSerialize( - params_ptr, &context); - MessageBuilder builder(interface_control::kRunMessageId, - Message::kFlagExpectsResponse, size, 0); - - interface_control::internal::RunMessageParams_Data* params = nullptr; - Serialize( - params_ptr, builder.buffer(), ¶ms, &context); - std::unique_ptr responder = - base::MakeUnique(callback); - ignore_result( - receiver->AcceptWithResponder(builder.message(), std::move(responder))); -} - -Message ConstructRunOrClosePipeMessage( - interface_control::RunOrClosePipeInputPtr input_ptr) { - SerializationContext context; - - auto params_ptr = interface_control::RunOrClosePipeMessageParams::New(); - params_ptr->input = std::move(input_ptr); - - size_t size = PrepareToSerialize< - interface_control::RunOrClosePipeMessageParamsDataView>(params_ptr, - &context); - MessageBuilder builder(interface_control::kRunOrClosePipeMessageId, 0, size, - 0); - - interface_control::internal::RunOrClosePipeMessageParams_Data* params = - nullptr; - Serialize( - params_ptr, builder.buffer(), ¶ms, &context); - return std::move(*builder.message()); -} - -void SendRunOrClosePipeMessage( - MessageReceiverWithResponder* receiver, - interface_control::RunOrClosePipeInputPtr input_ptr) { - Message message(ConstructRunOrClosePipeMessage(std::move(input_ptr))); - - ignore_result(receiver->Accept(&message)); -} - -void RunVersionCallback( - const base::Callback& callback, - interface_control::RunResponseMessageParamsPtr run_response) { - uint32_t version = 0u; - if (run_response->output && run_response->output->is_query_version_result()) - version = run_response->output->get_query_version_result()->version; - callback.Run(version); -} - -void RunClosure(const base::Closure& callback, - interface_control::RunResponseMessageParamsPtr run_response) { - callback.Run(); -} - -} // namespace - -ControlMessageProxy::ControlMessageProxy(MessageReceiverWithResponder* receiver) - : receiver_(receiver) { -} - -ControlMessageProxy::~ControlMessageProxy() = default; - -void ControlMessageProxy::QueryVersion( - const base::Callback& callback) { - auto input_ptr = interface_control::RunInput::New(); - input_ptr->set_query_version(interface_control::QueryVersion::New()); - SendRunMessage(receiver_, std::move(input_ptr), - base::Bind(&RunVersionCallback, callback)); -} - -void ControlMessageProxy::RequireVersion(uint32_t version) { - auto require_version = interface_control::RequireVersion::New(); - require_version->version = version; - auto input_ptr = interface_control::RunOrClosePipeInput::New(); - input_ptr->set_require_version(std::move(require_version)); - SendRunOrClosePipeMessage(receiver_, std::move(input_ptr)); -} - -void ControlMessageProxy::FlushForTesting() { - if (encountered_error_) - return; - - auto input_ptr = interface_control::RunInput::New(); - input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New()); - base::RunLoop run_loop; - run_loop_quit_closure_ = run_loop.QuitClosure(); - SendRunMessage( - receiver_, std::move(input_ptr), - base::Bind(&RunClosure, - base::Bind(&ControlMessageProxy::RunFlushForTestingClosure, - base::Unretained(this)))); - run_loop.Run(); -} - -void ControlMessageProxy::RunFlushForTestingClosure() { - DCHECK(!run_loop_quit_closure_.is_null()); - base::ResetAndReturn(&run_loop_quit_closure_).Run(); -} - -void ControlMessageProxy::OnConnectionError() { - encountered_error_ = true; - if (!run_loop_quit_closure_.is_null()) - RunFlushForTestingClosure(); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.h b/mojo/public/cpp/bindings/lib/control_message_proxy.h deleted file mode 100644 index 2f9314e..0000000 --- a/mojo/public/cpp/bindings/lib/control_message_proxy.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_PROXY_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_PROXY_H_ - -#include - -#include "base/callback.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -namespace mojo { - -class MessageReceiverWithResponder; - -namespace internal { - -// Proxy for request messages defined in interface_control_messages.mojom. -class MOJO_CPP_BINDINGS_EXPORT ControlMessageProxy { - public: - // Doesn't take ownership of |receiver|. It must outlive this object. - explicit ControlMessageProxy(MessageReceiverWithResponder* receiver); - ~ControlMessageProxy(); - - void QueryVersion(const base::Callback& callback); - void RequireVersion(uint32_t version); - - void FlushForTesting(); - void OnConnectionError(); - - private: - void RunFlushForTestingClosure(); - - // Not owned. - MessageReceiverWithResponder* receiver_; - bool encountered_error_ = false; - - base::Closure run_loop_quit_closure_; - - DISALLOW_COPY_AND_ASSIGN(ControlMessageProxy); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CONTROL_MESSAGE_PROXY_H_ diff --git a/mojo/public/cpp/bindings/lib/equals_traits.h b/mojo/public/cpp/bindings/lib/equals_traits.h deleted file mode 100644 index 53c7dce..0000000 --- a/mojo/public/cpp/bindings/lib/equals_traits.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ - -#include -#include -#include - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" - -namespace mojo { -namespace internal { - -template -struct HasEqualsMethod { - template - static char Test(decltype(&U::Equals)); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template ::value> -struct EqualsTraits; - -template -bool Equals(const T& a, const T& b); - -template -struct EqualsTraits { - static bool Equals(const T& a, const T& b) { return a.Equals(b); } -}; - -template -struct EqualsTraits { - static bool Equals(const T& a, const T& b) { return a == b; } -}; - -template -struct EqualsTraits, false> { - static bool Equals(const base::Optional& a, const base::Optional& b) { - if (!a && !b) - return true; - if (!a || !b) - return false; - - return internal::Equals(*a, *b); - } -}; - -template -struct EqualsTraits, false> { - static bool Equals(const std::vector& a, const std::vector& b) { - if (a.size() != b.size()) - return false; - for (size_t i = 0; i < a.size(); ++i) { - if (!internal::Equals(a[i], b[i])) - return false; - } - return true; - } -}; - -template -struct EqualsTraits, false> { - static bool Equals(const std::unordered_map& a, - const std::unordered_map& b) { - if (a.size() != b.size()) - return false; - for (const auto& element : a) { - auto iter = b.find(element.first); - if (iter == b.end() || !internal::Equals(element.second, iter->second)) - return false; - } - return true; - } -}; - -template -bool Equals(const T& a, const T& b) { - return EqualsTraits::Equals(a, b); -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ diff --git a/mojo/public/cpp/bindings/lib/filter_chain.cc b/mojo/public/cpp/bindings/lib/filter_chain.cc deleted file mode 100644 index 5d919fe..0000000 --- a/mojo/public/cpp/bindings/lib/filter_chain.cc +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/filter_chain.h" - -#include - -#include "base/logging.h" - -namespace mojo { - -FilterChain::FilterChain(MessageReceiver* sink) : sink_(sink) { -} - -FilterChain::FilterChain(FilterChain&& other) : sink_(other.sink_) { - other.sink_ = nullptr; - filters_.swap(other.filters_); -} - -FilterChain& FilterChain::operator=(FilterChain&& other) { - std::swap(sink_, other.sink_); - filters_.swap(other.filters_); - return *this; -} - -FilterChain::~FilterChain() { -} - -void FilterChain::SetSink(MessageReceiver* sink) { - DCHECK(!sink_); - sink_ = sink; -} - -bool FilterChain::Accept(Message* message) { - DCHECK(sink_); - for (auto& filter : filters_) - if (!filter->Accept(message)) - return false; - return sink_->Accept(message); -} - -void FilterChain::Append(std::unique_ptr filter) { - filters_.emplace_back(std::move(filter)); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/mojo/public/cpp/bindings/lib/fixed_buffer.cc deleted file mode 100644 index 725a193..0000000 --- a/mojo/public/cpp/bindings/lib/fixed_buffer.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" - -#include - -namespace mojo { -namespace internal { - -FixedBufferForTesting::FixedBufferForTesting(size_t size) { - size = internal::Align(size); - // Use calloc here to ensure all message memory is zero'd out. - void* ptr = calloc(size, 1); - Initialize(ptr, size); -} - -FixedBufferForTesting::~FixedBufferForTesting() { - free(data()); -} - -void* FixedBufferForTesting::Leak() { - void* ptr = data(); - Initialize(nullptr, 0); - return ptr; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.h b/mojo/public/cpp/bindings/lib/fixed_buffer.h deleted file mode 100644 index 070b0c8..0000000 --- a/mojo/public/cpp/bindings/lib/fixed_buffer.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_ - -#include - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" - -namespace mojo { -namespace internal { - -// FixedBufferForTesting owns its buffer. The Leak method may be used to steal -// the underlying memory. -class MOJO_CPP_BINDINGS_EXPORT FixedBufferForTesting - : NON_EXPORTED_BASE(public Buffer) { - public: - explicit FixedBufferForTesting(size_t size); - ~FixedBufferForTesting(); - - // Returns the internal memory owned by the Buffer to the caller. The Buffer - // relinquishes its pointer, effectively resetting the state of the Buffer - // and leaving the caller responsible for freeing the returned memory address - // when no longer needed. - void* Leak(); - - private: - DISALLOW_COPY_AND_ASSIGN(FixedBufferForTesting); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_FIXED_BUFFER_H_ diff --git a/mojo/public/cpp/bindings/lib/handle_interface_serialization.h b/mojo/public/cpp/bindings/lib/handle_interface_serialization.h deleted file mode 100644 index 14ed21f..0000000 --- a/mojo/public/cpp/bindings/lib/handle_interface_serialization.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_HANDLE_INTERFACE_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_HANDLE_INTERFACE_SERIALIZATION_H_ - -#include - -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" -#include "mojo/public/cpp/bindings/associated_interface_request.h" -#include "mojo/public/cpp/bindings/interface_data_view.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { -namespace internal { - -template -struct Serializer, - AssociatedInterfacePtrInfo> { - static_assert(std::is_base_of::value, "Interface type mismatch."); - - static size_t PrepareToSerialize(const AssociatedInterfacePtrInfo& input, - SerializationContext* context) { - if (input.handle().is_valid()) - context->associated_endpoint_count++; - return 0; - } - - static void Serialize(AssociatedInterfacePtrInfo& input, - AssociatedInterface_Data* output, - SerializationContext* context) { - DCHECK(!input.handle().is_valid() || input.handle().pending_association()); - if (input.handle().is_valid()) { - // Set to the index of the element pushed to the back of the vector. - output->handle.value = - static_cast(context->associated_endpoint_handles.size()); - context->associated_endpoint_handles.push_back(input.PassHandle()); - } else { - output->handle.value = kEncodedInvalidHandleValue; - } - output->version = input.version(); - } - - static bool Deserialize(AssociatedInterface_Data* input, - AssociatedInterfacePtrInfo* output, - SerializationContext* context) { - if (input->handle.is_valid()) { - DCHECK_LT(input->handle.value, - context->associated_endpoint_handles.size()); - output->set_handle( - std::move(context->associated_endpoint_handles[input->handle.value])); - } else { - output->set_handle(ScopedInterfaceEndpointHandle()); - } - output->set_version(input->version); - return true; - } -}; - -template -struct Serializer, - AssociatedInterfaceRequest> { - static_assert(std::is_base_of::value, "Interface type mismatch."); - - static size_t PrepareToSerialize(const AssociatedInterfaceRequest& input, - SerializationContext* context) { - if (input.handle().is_valid()) - context->associated_endpoint_count++; - return 0; - } - - static void Serialize(AssociatedInterfaceRequest& input, - AssociatedEndpointHandle_Data* output, - SerializationContext* context) { - DCHECK(!input.handle().is_valid() || input.handle().pending_association()); - if (input.handle().is_valid()) { - // Set to the index of the element pushed to the back of the vector. - output->value = - static_cast(context->associated_endpoint_handles.size()); - context->associated_endpoint_handles.push_back(input.PassHandle()); - } else { - output->value = kEncodedInvalidHandleValue; - } - } - - static bool Deserialize(AssociatedEndpointHandle_Data* input, - AssociatedInterfaceRequest* output, - SerializationContext* context) { - if (input->is_valid()) { - DCHECK_LT(input->value, context->associated_endpoint_handles.size()); - output->Bind( - std::move(context->associated_endpoint_handles[input->value])); - } else { - output->Bind(ScopedInterfaceEndpointHandle()); - } - return true; - } -}; - -template -struct Serializer, InterfacePtr> { - static_assert(std::is_base_of::value, "Interface type mismatch."); - - static size_t PrepareToSerialize(const InterfacePtr& input, - SerializationContext* context) { - return 0; - } - - static void Serialize(InterfacePtr& input, - Interface_Data* output, - SerializationContext* context) { - InterfacePtrInfo info = input.PassInterface(); - output->handle = context->handles.AddHandle(info.PassHandle().release()); - output->version = info.version(); - } - - static bool Deserialize(Interface_Data* input, - InterfacePtr* output, - SerializationContext* context) { - output->Bind(InterfacePtrInfo( - context->handles.TakeHandleAs(input->handle), - input->version)); - return true; - } -}; - -template -struct Serializer, InterfaceRequest> { - static_assert(std::is_base_of::value, "Interface type mismatch."); - - static size_t PrepareToSerialize(const InterfaceRequest& input, - SerializationContext* context) { - return 0; - } - - static void Serialize(InterfaceRequest& input, - Handle_Data* output, - SerializationContext* context) { - *output = context->handles.AddHandle(input.PassMessagePipe().release()); - } - - static bool Deserialize(Handle_Data* input, - InterfaceRequest* output, - SerializationContext* context) { - output->Bind(context->handles.TakeHandleAs(*input)); - return true; - } -}; - -template -struct Serializer, ScopedHandleBase> { - static size_t PrepareToSerialize(const ScopedHandleBase& input, - SerializationContext* context) { - return 0; - } - - static void Serialize(ScopedHandleBase& input, - Handle_Data* output, - SerializationContext* context) { - *output = context->handles.AddHandle(input.release()); - } - - static bool Deserialize(Handle_Data* input, - ScopedHandleBase* output, - SerializationContext* context) { - *output = context->handles.TakeHandleAs(*input); - return true; - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_HANDLE_INTERFACE_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/hash_util.h b/mojo/public/cpp/bindings/lib/hash_util.h deleted file mode 100644 index 93280d6..0000000 --- a/mojo/public/cpp/bindings/lib/hash_util.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_ - -#include -#include -#include -#include - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" - -namespace mojo { -namespace internal { - -template -size_t HashCombine(size_t seed, const T& value) { - // Based on proposal in: - // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf - return seed ^ (std::hash()(value) + (seed << 6) + (seed >> 2)); -} - -template -struct HasHashMethod { - template - static char Test(decltype(&U::Hash)); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template ::value> -struct HashTraits; - -template -size_t Hash(size_t seed, const T& value); - -template -struct HashTraits { - static size_t Hash(size_t seed, const T& value) { return value.Hash(seed); } -}; - -template -struct HashTraits { - static size_t Hash(size_t seed, const T& value) { - return HashCombine(seed, value); - } -}; - -template -struct HashTraits, false> { - static size_t Hash(size_t seed, const std::vector& value) { - for (const auto& element : value) { - seed = HashCombine(seed, element); - } - return seed; - } -}; - -template -struct HashTraits>, false> { - static size_t Hash(size_t seed, const base::Optional>& value) { - if (!value) - return HashCombine(seed, 0); - - return Hash(seed, *value); - } -}; - -template -size_t Hash(size_t seed, const T& value) { - return HashTraits::Hash(seed, value); -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_HASH_UTIL_H_ diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc deleted file mode 100644 index 4682e72..0000000 --- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" - -#include - -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "mojo/public/cpp/bindings/associated_group.h" -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/interface_endpoint_controller.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" -#include "mojo/public/cpp/bindings/sync_call_restrictions.h" - -namespace mojo { - -// ---------------------------------------------------------------------------- - -namespace { - -void DCheckIfInvalid(const base::WeakPtr& client, - const std::string& message) { - bool is_valid = client && !client->encountered_error(); - DCHECK(!is_valid) << message; -} - -// When receiving an incoming message which expects a repsonse, -// InterfaceEndpointClient creates a ResponderThunk object and passes it to the -// incoming message receiver. When the receiver finishes processing the message, -// it can provide a response using this object. -class ResponderThunk : public MessageReceiverWithStatus { - public: - explicit ResponderThunk( - const base::WeakPtr& endpoint_client, - scoped_refptr runner) - : endpoint_client_(endpoint_client), - accept_was_invoked_(false), - task_runner_(std::move(runner)) {} - ~ResponderThunk() override { - if (!accept_was_invoked_) { - // The Service handled a message that was expecting a response - // but did not send a response. - // We raise an error to signal the calling application that an error - // condition occurred. Without this the calling application would have no - // way of knowing it should stop waiting for a response. - if (task_runner_->RunsTasksOnCurrentThread()) { - // Please note that even if this code is run from a different task - // runner on the same thread as |task_runner_|, it is okay to directly - // call InterfaceEndpointClient::RaiseError(), because it will raise - // error from the correct task runner asynchronously. - if (endpoint_client_) { - endpoint_client_->RaiseError(); - } - } else { - task_runner_->PostTask( - FROM_HERE, - base::Bind(&InterfaceEndpointClient::RaiseError, endpoint_client_)); - } - } - } - - // MessageReceiver implementation: - bool Accept(Message* message) override { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - accept_was_invoked_ = true; - DCHECK(message->has_flag(Message::kFlagIsResponse)); - - bool result = false; - - if (endpoint_client_) - result = endpoint_client_->Accept(message); - - return result; - } - - // MessageReceiverWithStatus implementation: - bool IsValid() override { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - return endpoint_client_ && !endpoint_client_->encountered_error(); - } - - void DCheckInvalid(const std::string& message) override { - if (task_runner_->RunsTasksOnCurrentThread()) { - DCheckIfInvalid(endpoint_client_, message); - } else { - task_runner_->PostTask( - FROM_HERE, base::Bind(&DCheckIfInvalid, endpoint_client_, message)); - } - } - - private: - base::WeakPtr endpoint_client_; - bool accept_was_invoked_; - scoped_refptr task_runner_; - - DISALLOW_COPY_AND_ASSIGN(ResponderThunk); -}; - -} // namespace - -// ---------------------------------------------------------------------------- - -InterfaceEndpointClient::SyncResponseInfo::SyncResponseInfo( - bool* in_response_received) - : response_received(in_response_received) {} - -InterfaceEndpointClient::SyncResponseInfo::~SyncResponseInfo() {} - -// ---------------------------------------------------------------------------- - -InterfaceEndpointClient::HandleIncomingMessageThunk::HandleIncomingMessageThunk( - InterfaceEndpointClient* owner) - : owner_(owner) {} - -InterfaceEndpointClient::HandleIncomingMessageThunk:: - ~HandleIncomingMessageThunk() {} - -bool InterfaceEndpointClient::HandleIncomingMessageThunk::Accept( - Message* message) { - return owner_->HandleValidatedMessage(message); -} - -// ---------------------------------------------------------------------------- - -InterfaceEndpointClient::InterfaceEndpointClient( - ScopedInterfaceEndpointHandle handle, - MessageReceiverWithResponderStatus* receiver, - std::unique_ptr payload_validator, - bool expect_sync_requests, - scoped_refptr runner, - uint32_t interface_version) - : expect_sync_requests_(expect_sync_requests), - handle_(std::move(handle)), - incoming_receiver_(receiver), - thunk_(this), - filters_(&thunk_), - task_runner_(std::move(runner)), - control_message_proxy_(this), - control_message_handler_(interface_version), - weak_ptr_factory_(this) { - DCHECK(handle_.is_valid()); - - // TODO(yzshen): the way to use validator (or message filter in general) - // directly is a little awkward. - if (payload_validator) - filters_.Append(std::move(payload_validator)); - - if (handle_.pending_association()) { - handle_.SetAssociationEventHandler(base::Bind( - &InterfaceEndpointClient::OnAssociationEvent, base::Unretained(this))); - } else { - InitControllerIfNecessary(); - } -} - -InterfaceEndpointClient::~InterfaceEndpointClient() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (controller_) - handle_.group_controller()->DetachEndpointClient(handle_); -} - -AssociatedGroup* InterfaceEndpointClient::associated_group() { - if (!associated_group_) - associated_group_ = base::MakeUnique(handle_); - return associated_group_.get(); -} - -ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!has_pending_responders()); - - if (!handle_.is_valid()) - return ScopedInterfaceEndpointHandle(); - - handle_.SetAssociationEventHandler( - ScopedInterfaceEndpointHandle::AssociationEventCallback()); - - if (controller_) { - controller_ = nullptr; - handle_.group_controller()->DetachEndpointClient(handle_); - } - - return std::move(handle_); -} - -void InterfaceEndpointClient::AddFilter( - std::unique_ptr filter) { - filters_.Append(std::move(filter)); -} - -void InterfaceEndpointClient::RaiseError() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!handle_.pending_association()) - handle_.group_controller()->RaiseError(); -} - -void InterfaceEndpointClient::CloseWithReason(uint32_t custom_reason, - const std::string& description) { - DCHECK(thread_checker_.CalledOnValidThread()); - - auto handle = PassHandle(); - handle.ResetWithReason(custom_reason, description); -} - -bool InterfaceEndpointClient::Accept(Message* message) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!message->has_flag(Message::kFlagExpectsResponse)); - DCHECK(!handle_.pending_association()); - - // This has to been done even if connection error has occurred. For example, - // the message contains a pending associated request. The user may try to use - // the corresponding associated interface pointer after sending this message. - // That associated interface pointer has to join an associated group in order - // to work properly. - if (!message->associated_endpoint_handles()->empty()) - message->SerializeAssociatedEndpointHandles(handle_.group_controller()); - - if (encountered_error_) - return false; - - InitControllerIfNecessary(); - - return controller_->SendMessage(message); -} - -bool InterfaceEndpointClient::AcceptWithResponder( - Message* message, - std::unique_ptr responder) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(message->has_flag(Message::kFlagExpectsResponse)); - DCHECK(!handle_.pending_association()); - - // Please see comments in Accept(). - if (!message->associated_endpoint_handles()->empty()) - message->SerializeAssociatedEndpointHandles(handle_.group_controller()); - - if (encountered_error_) - return false; - - InitControllerIfNecessary(); - - // Reserve 0 in case we want it to convey special meaning in the future. - uint64_t request_id = next_request_id_++; - if (request_id == 0) - request_id = next_request_id_++; - - message->set_request_id(request_id); - - bool is_sync = message->has_flag(Message::kFlagIsSync); - if (!controller_->SendMessage(message)) - return false; - - if (!is_sync) { - async_responders_[request_id] = std::move(responder); - return true; - } - - SyncCallRestrictions::AssertSyncCallAllowed(); - - bool response_received = false; - sync_responses_.insert(std::make_pair( - request_id, base::MakeUnique(&response_received))); - - base::WeakPtr weak_self = - weak_ptr_factory_.GetWeakPtr(); - controller_->SyncWatch(&response_received); - // Make sure that this instance hasn't been destroyed. - if (weak_self) { - DCHECK(base::ContainsKey(sync_responses_, request_id)); - auto iter = sync_responses_.find(request_id); - DCHECK_EQ(&response_received, iter->second->response_received); - if (response_received) - ignore_result(responder->Accept(&iter->second->response)); - sync_responses_.erase(iter); - } - - return true; -} - -bool InterfaceEndpointClient::HandleIncomingMessage(Message* message) { - DCHECK(thread_checker_.CalledOnValidThread()); - return filters_.Accept(message); -} - -void InterfaceEndpointClient::NotifyError( - const base::Optional& reason) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (encountered_error_) - return; - encountered_error_ = true; - - // Response callbacks may hold on to resource, and there's no need to keep - // them alive any longer. Note that it's allowed that a pending response - // callback may own this endpoint, so we simply move the responders onto the - // stack here and let them be destroyed when the stack unwinds. - AsyncResponderMap responders = std::move(async_responders_); - - control_message_proxy_.OnConnectionError(); - - if (!error_handler_.is_null()) { - base::Closure error_handler = std::move(error_handler_); - error_handler.Run(); - } else if (!error_with_reason_handler_.is_null()) { - ConnectionErrorWithReasonCallback error_with_reason_handler = - std::move(error_with_reason_handler_); - if (reason) { - error_with_reason_handler.Run(reason->custom_reason, reason->description); - } else { - error_with_reason_handler.Run(0, std::string()); - } - } -} - -void InterfaceEndpointClient::QueryVersion( - const base::Callback& callback) { - control_message_proxy_.QueryVersion(callback); -} - -void InterfaceEndpointClient::RequireVersion(uint32_t version) { - control_message_proxy_.RequireVersion(version); -} - -void InterfaceEndpointClient::FlushForTesting() { - control_message_proxy_.FlushForTesting(); -} - -void InterfaceEndpointClient::InitControllerIfNecessary() { - if (controller_ || handle_.pending_association()) - return; - - controller_ = handle_.group_controller()->AttachEndpointClient(handle_, this, - task_runner_); - if (expect_sync_requests_) - controller_->AllowWokenUpBySyncWatchOnSameThread(); -} - -void InterfaceEndpointClient::OnAssociationEvent( - ScopedInterfaceEndpointHandle::AssociationEvent event) { - if (event == ScopedInterfaceEndpointHandle::ASSOCIATED) { - InitControllerIfNecessary(); - } else if (event == - ScopedInterfaceEndpointHandle::PEER_CLOSED_BEFORE_ASSOCIATION) { - task_runner_->PostTask(FROM_HERE, - base::Bind(&InterfaceEndpointClient::NotifyError, - weak_ptr_factory_.GetWeakPtr(), - handle_.disconnect_reason())); - } -} - -bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) { - DCHECK_EQ(handle_.id(), message->interface_id()); - - if (encountered_error_) { - // This message is received after error has been encountered. For associated - // interfaces, this means the remote side sends a - // PeerAssociatedEndpointClosed event but continues to send more messages - // for the same interface. Close the pipe because this shouldn't happen. - DVLOG(1) << "A message is received for an interface after it has been " - << "disconnected. Closing the pipe."; - return false; - } - - if (message->has_flag(Message::kFlagExpectsResponse)) { - std::unique_ptr responder = - base::MakeUnique(weak_ptr_factory_.GetWeakPtr(), - task_runner_); - if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) { - return control_message_handler_.AcceptWithResponder(message, - std::move(responder)); - } else { - return incoming_receiver_->AcceptWithResponder(message, - std::move(responder)); - } - } else if (message->has_flag(Message::kFlagIsResponse)) { - uint64_t request_id = message->request_id(); - - if (message->has_flag(Message::kFlagIsSync)) { - auto it = sync_responses_.find(request_id); - if (it == sync_responses_.end()) - return false; - it->second->response = std::move(*message); - *it->second->response_received = true; - return true; - } - - auto it = async_responders_.find(request_id); - if (it == async_responders_.end()) - return false; - std::unique_ptr responder = std::move(it->second); - async_responders_.erase(it); - return responder->Accept(message); - } else { - if (mojo::internal::ControlMessageHandler::IsControlMessage(message)) - return control_message_handler_.Accept(message); - - return incoming_receiver_->Accept(message); - } -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/mojo/public/cpp/bindings/lib/interface_ptr_state.h deleted file mode 100644 index fa54979..0000000 --- a/mojo/public/cpp/bindings/lib/interface_ptr_state.h +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_ - -#include - -#include // For |std::swap()|. -#include -#include -#include - -#include "base/bind.h" -#include "base/callback_forward.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/associated_group.h" -#include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/interface_ptr_info.h" -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" -#include "mojo/public/cpp/bindings/message_header_validator.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace mojo { -namespace internal { - -template -class InterfacePtrState { - public: - InterfacePtrState() : version_(0u) {} - - ~InterfacePtrState() { - endpoint_client_.reset(); - proxy_.reset(); - if (router_) - router_->CloseMessagePipe(); - } - - Interface* instance() { - ConfigureProxyIfNecessary(); - - // This will be null if the object is not bound. - return proxy_.get(); - } - - uint32_t version() const { return version_; } - - void QueryVersion(const base::Callback& callback) { - ConfigureProxyIfNecessary(); - - // It is safe to capture |this| because the callback won't be run after this - // object goes away. - endpoint_client_->QueryVersion(base::Bind( - &InterfacePtrState::OnQueryVersion, base::Unretained(this), callback)); - } - - void RequireVersion(uint32_t version) { - ConfigureProxyIfNecessary(); - - if (version <= version_) - return; - - version_ = version; - endpoint_client_->RequireVersion(version); - } - - void FlushForTesting() { - ConfigureProxyIfNecessary(); - endpoint_client_->FlushForTesting(); - } - - void CloseWithReason(uint32_t custom_reason, const std::string& description) { - ConfigureProxyIfNecessary(); - endpoint_client_->CloseWithReason(custom_reason, description); - } - - void Swap(InterfacePtrState* other) { - using std::swap; - swap(other->router_, router_); - swap(other->endpoint_client_, endpoint_client_); - swap(other->proxy_, proxy_); - handle_.swap(other->handle_); - runner_.swap(other->runner_); - swap(other->version_, version_); - } - - void Bind(InterfacePtrInfo info, - scoped_refptr runner) { - DCHECK(!router_); - DCHECK(!endpoint_client_); - DCHECK(!proxy_); - DCHECK(!handle_.is_valid()); - DCHECK_EQ(0u, version_); - DCHECK(info.is_valid()); - - handle_ = info.PassHandle(); - version_ = info.version(); - runner_ = std::move(runner); - } - - bool HasAssociatedInterfaces() const { - return router_ ? router_->HasAssociatedEndpoints() : false; - } - - // After this method is called, the object is in an invalid state and - // shouldn't be reused. - InterfacePtrInfo PassInterface() { - endpoint_client_.reset(); - proxy_.reset(); - return InterfacePtrInfo( - router_ ? router_->PassMessagePipe() : std::move(handle_), version_); - } - - bool is_bound() const { return handle_.is_valid() || endpoint_client_; } - - bool encountered_error() const { - return endpoint_client_ ? endpoint_client_->encountered_error() : false; - } - - void set_connection_error_handler(const base::Closure& error_handler) { - ConfigureProxyIfNecessary(); - - DCHECK(endpoint_client_); - endpoint_client_->set_connection_error_handler(error_handler); - } - - void set_connection_error_with_reason_handler( - const ConnectionErrorWithReasonCallback& error_handler) { - ConfigureProxyIfNecessary(); - - DCHECK(endpoint_client_); - endpoint_client_->set_connection_error_with_reason_handler(error_handler); - } - - // Returns true if bound and awaiting a response to a message. - bool has_pending_callbacks() const { - return endpoint_client_ && endpoint_client_->has_pending_responders(); - } - - AssociatedGroup* associated_group() { - ConfigureProxyIfNecessary(); - return endpoint_client_->associated_group(); - } - - void EnableTestingMode() { - ConfigureProxyIfNecessary(); - router_->EnableTestingMode(); - } - - void ForwardMessage(Message message) { - ConfigureProxyIfNecessary(); - endpoint_client_->Accept(&message); - } - - void ForwardMessageWithResponder(Message message, - std::unique_ptr responder) { - ConfigureProxyIfNecessary(); - endpoint_client_->AcceptWithResponder(&message, std::move(responder)); - } - - private: - using Proxy = typename Interface::Proxy_; - - void ConfigureProxyIfNecessary() { - // The proxy has been configured. - if (proxy_) { - DCHECK(router_); - DCHECK(endpoint_client_); - return; - } - // The object hasn't been bound. - if (!handle_.is_valid()) - return; - - MultiplexRouter::Config config = - Interface::PassesAssociatedKinds_ - ? MultiplexRouter::MULTI_INTERFACE - : (Interface::HasSyncMethods_ - ? MultiplexRouter::SINGLE_INTERFACE_WITH_SYNC_METHODS - : MultiplexRouter::SINGLE_INTERFACE); - router_ = new MultiplexRouter(std::move(handle_), config, true, runner_); - router_->SetMasterInterfaceName(Interface::Name_); - endpoint_client_.reset(new InterfaceEndpointClient( - router_->CreateLocalEndpointHandle(kMasterInterfaceId), nullptr, - base::WrapUnique(new typename Interface::ResponseValidator_()), false, - std::move(runner_), - // The version is only queried from the client so the value passed here - // will not be used. - 0u)); - proxy_.reset(new Proxy(endpoint_client_.get())); - } - - void OnQueryVersion(const base::Callback& callback, - uint32_t version) { - version_ = version; - callback.Run(version); - } - - scoped_refptr router_; - - std::unique_ptr endpoint_client_; - std::unique_ptr proxy_; - - // |router_| (as well as other members above) is not initialized until - // read/write with the message pipe handle is needed. |handle_| is valid - // between the Bind() call and the initialization of |router_|. - ScopedMessagePipeHandle handle_; - scoped_refptr runner_; - - uint32_t version_; - - DISALLOW_COPY_AND_ASSIGN(InterfacePtrState); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_ diff --git a/mojo/public/cpp/bindings/lib/map_data_internal.h b/mojo/public/cpp/bindings/lib/map_data_internal.h deleted file mode 100644 index f8e3d29..0000000 --- a/mojo/public/cpp/bindings/lib/map_data_internal.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_DATA_INTERNAL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_DATA_INTERNAL_H_ - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/validate_params.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" - -namespace mojo { -namespace internal { - -// Map serializes into a struct which has two arrays as struct fields, the keys -// and the values. -template -class Map_Data { - public: - static Map_Data* New(Buffer* buf) { - return new (buf->Allocate(sizeof(Map_Data))) Map_Data(); - } - - // |validate_params| must have non-null |key_validate_params| and - // |element_validate_params| members. - static bool Validate(const void* data, - ValidationContext* validation_context, - const ContainerValidateParams* validate_params) { - if (!data) - return true; - - if (!ValidateStructHeaderAndClaimMemory(data, validation_context)) - return false; - - const Map_Data* object = static_cast(data); - if (object->header_.num_bytes != sizeof(Map_Data) || - object->header_.version != 0) { - ReportValidationError(validation_context, - VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); - return false; - } - - if (!ValidatePointerNonNullable( - object->keys, "null key array in map struct", validation_context) || - !ValidateContainer(object->keys, validation_context, - validate_params->key_validate_params)) { - return false; - } - - if (!ValidatePointerNonNullable(object->values, - "null value array in map struct", - validation_context) || - !ValidateContainer(object->values, validation_context, - validate_params->element_validate_params)) { - return false; - } - - if (object->keys.Get()->size() != object->values.Get()->size()) { - ReportValidationError(validation_context, - VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP); - return false; - } - - return true; - } - - StructHeader header_; - - Pointer> keys; - Pointer> values; - - private: - Map_Data() { - header_.num_bytes = sizeof(*this); - header_.version = 0; - } - ~Map_Data() = delete; -}; -static_assert(sizeof(Map_Data) == 24, "Bad sizeof(Map_Data)"); - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_DATA_INTERNAL_H_ diff --git a/mojo/public/cpp/bindings/lib/map_serialization.h b/mojo/public/cpp/bindings/lib/map_serialization.h deleted file mode 100644 index 718a763..0000000 --- a/mojo/public/cpp/bindings/lib/map_serialization.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ - -#include -#include - -#include "mojo/public/cpp/bindings/array_data_view.h" -#include "mojo/public/cpp/bindings/lib/array_serialization.h" -#include "mojo/public/cpp/bindings/lib/map_data_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/map_data_view.h" - -namespace mojo { -namespace internal { - -template -class MapReaderBase { - public: - using UserType = typename std::remove_const::type; - using Traits = MapTraits; - using MaybeConstIterator = - decltype(Traits::GetBegin(std::declval())); - - explicit MapReaderBase(MaybeConstUserType& input) - : input_(input), iter_(Traits::GetBegin(input_)) {} - ~MapReaderBase() {} - - size_t GetSize() const { return Traits::GetSize(input_); } - - // Return null because key or value elements are not stored continuously in - // memory. - void* GetDataIfExists() { return nullptr; } - - protected: - MaybeConstUserType& input_; - MaybeConstIterator iter_; -}; - -// Used as the UserTypeReader template parameter of ArraySerializer. -template -class MapKeyReader : public MapReaderBase { - public: - using Base = MapReaderBase; - using Traits = typename Base::Traits; - using MaybeConstIterator = typename Base::MaybeConstIterator; - - explicit MapKeyReader(MaybeConstUserType& input) : Base(input) {} - ~MapKeyReader() {} - - using GetNextResult = - decltype(Traits::GetKey(std::declval())); - GetNextResult GetNext() { - GetNextResult key = Traits::GetKey(this->iter_); - Traits::AdvanceIterator(this->iter_); - return key; - } -}; - -// Used as the UserTypeReader template parameter of ArraySerializer. -template -class MapValueReader : public MapReaderBase { - public: - using Base = MapReaderBase; - using Traits = typename Base::Traits; - using MaybeConstIterator = typename Base::MaybeConstIterator; - - explicit MapValueReader(MaybeConstUserType& input) : Base(input) {} - ~MapValueReader() {} - - using GetNextResult = - decltype(Traits::GetValue(std::declval())); - GetNextResult GetNext() { - GetNextResult value = Traits::GetValue(this->iter_); - Traits::AdvanceIterator(this->iter_); - return value; - } -}; - -template -struct Serializer, MaybeConstUserType> { - using UserType = typename std::remove_const::type; - using Traits = MapTraits; - using UserKey = typename Traits::Key; - using UserValue = typename Traits::Value; - using Data = typename MojomTypeTraits>::Data; - using KeyArraySerializer = ArraySerializer, - std::vector, - MapKeyReader>; - using ValueArraySerializer = - ArraySerializer, - std::vector, - MapValueReader>; - - static size_t PrepareToSerialize(MaybeConstUserType& input, - SerializationContext* context) { - if (CallIsNullIfExists(input)) - return 0; - - size_t struct_overhead = sizeof(Data); - MapKeyReader key_reader(input); - size_t keys_size = - KeyArraySerializer::GetSerializedSize(&key_reader, context); - MapValueReader value_reader(input); - size_t values_size = - ValueArraySerializer::GetSerializedSize(&value_reader, context); - - return struct_overhead + keys_size + values_size; - } - - static void Serialize(MaybeConstUserType& input, - Buffer* buf, - Data** output, - const ContainerValidateParams* validate_params, - SerializationContext* context) { - DCHECK(validate_params->key_validate_params); - DCHECK(validate_params->element_validate_params); - if (CallIsNullIfExists(input)) { - *output = nullptr; - return; - } - - auto result = Data::New(buf); - if (result) { - auto keys_ptr = MojomTypeTraits>::Data::New( - Traits::GetSize(input), buf); - if (keys_ptr) { - MapKeyReader key_reader(input); - KeyArraySerializer::SerializeElements( - &key_reader, buf, keys_ptr, validate_params->key_validate_params, - context); - result->keys.Set(keys_ptr); - } - - auto values_ptr = MojomTypeTraits>::Data::New( - Traits::GetSize(input), buf); - if (values_ptr) { - MapValueReader value_reader(input); - ValueArraySerializer::SerializeElements( - &value_reader, buf, values_ptr, - validate_params->element_validate_params, context); - result->values.Set(values_ptr); - } - } - *output = result; - } - - static bool Deserialize(Data* input, - UserType* output, - SerializationContext* context) { - if (!input) - return CallSetToNullIfExists(output); - - std::vector keys; - std::vector values; - - if (!KeyArraySerializer::DeserializeElements(input->keys.Get(), &keys, - context) || - !ValueArraySerializer::DeserializeElements(input->values.Get(), &values, - context)) { - return false; - } - - DCHECK_EQ(keys.size(), values.size()); - size_t size = keys.size(); - Traits::SetToEmpty(output); - - for (size_t i = 0; i < size; ++i) { - if (!Traits::Insert(*output, std::move(keys[i]), std::move(values[i]))) - return false; - } - return true; - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/may_auto_lock.h b/mojo/public/cpp/bindings/lib/may_auto_lock.h deleted file mode 100644 index 06091fe..0000000 --- a/mojo/public/cpp/bindings/lib/may_auto_lock.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAY_AUTO_LOCK_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAY_AUTO_LOCK_H_ - -#include "base/macros.h" -#include "base/optional.h" -#include "base/synchronization/lock.h" - -namespace mojo { -namespace internal { - -// Similar to base::AutoLock, except that it does nothing if |lock| passed into -// the constructor is null. -class MayAutoLock { - public: - explicit MayAutoLock(base::Optional* lock) - : lock_(lock->has_value() ? &lock->value() : nullptr) { - if (lock_) - lock_->Acquire(); - } - - ~MayAutoLock() { - if (lock_) { - lock_->AssertAcquired(); - lock_->Release(); - } - } - - private: - base::Lock* lock_; - DISALLOW_COPY_AND_ASSIGN(MayAutoLock); -}; - -// Similar to base::AutoUnlock, except that it does nothing if |lock| passed -// into the constructor is null. -class MayAutoUnlock { - public: - explicit MayAutoUnlock(base::Optional* lock) - : lock_(lock->has_value() ? &lock->value() : nullptr) { - if (lock_) { - lock_->AssertAcquired(); - lock_->Release(); - } - } - - ~MayAutoUnlock() { - if (lock_) - lock_->Acquire(); - } - - private: - base::Lock* lock_; - DISALLOW_COPY_AND_ASSIGN(MayAutoUnlock); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAY_AUTO_LOCK_H_ diff --git a/mojo/public/cpp/bindings/lib/message.cc b/mojo/public/cpp/bindings/lib/message.cc deleted file mode 100644 index e5f3808..0000000 --- a/mojo/public/cpp/bindings/lib/message.cc +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/message.h" - -#include -#include -#include - -#include -#include - -#include "base/bind.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_local.h" -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" - -namespace mojo { - -namespace { - -base::LazyInstance>:: - DestructorAtExit g_tls_message_dispatch_context = LAZY_INSTANCE_INITIALIZER; - -base::LazyInstance>:: - DestructorAtExit g_tls_sync_response_context = LAZY_INSTANCE_INITIALIZER; - -void DoNotifyBadMessage(Message message, const std::string& error) { - message.NotifyBadMessage(error); -} - -} // namespace - -Message::Message() { -} - -Message::Message(Message&& other) - : buffer_(std::move(other.buffer_)), - handles_(std::move(other.handles_)), - associated_endpoint_handles_( - std::move(other.associated_endpoint_handles_)) {} - -Message::~Message() { - CloseHandles(); -} - -Message& Message::operator=(Message&& other) { - Reset(); - std::swap(other.buffer_, buffer_); - std::swap(other.handles_, handles_); - std::swap(other.associated_endpoint_handles_, associated_endpoint_handles_); - return *this; -} - -void Message::Reset() { - CloseHandles(); - handles_.clear(); - associated_endpoint_handles_.clear(); - buffer_.reset(); -} - -void Message::Initialize(size_t capacity, bool zero_initialized) { - DCHECK(!buffer_); - buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized)); -} - -void Message::InitializeFromMojoMessage(ScopedMessageHandle message, - uint32_t num_bytes, - std::vector* handles) { - DCHECK(!buffer_); - buffer_.reset(new internal::MessageBuffer(std::move(message), num_bytes)); - handles_.swap(*handles); -} - -const uint8_t* Message::payload() const { - if (version() < 2) - return data() + header()->num_bytes; - - return static_cast(header_v2()->payload.Get()); -} - -uint32_t Message::payload_num_bytes() const { - DCHECK_GE(data_num_bytes(), header()->num_bytes); - size_t num_bytes; - if (version() < 2) { - num_bytes = data_num_bytes() - header()->num_bytes; - } else { - auto payload = reinterpret_cast(header_v2()->payload.Get()); - if (!payload) { - num_bytes = 0; - } else { - auto payload_end = - reinterpret_cast(header_v2()->payload_interface_ids.Get()); - if (!payload_end) - payload_end = reinterpret_cast(data() + data_num_bytes()); - DCHECK_GE(payload_end, payload); - num_bytes = payload_end - payload; - } - } - DCHECK_LE(num_bytes, std::numeric_limits::max()); - return static_cast(num_bytes); -} - -uint32_t Message::payload_num_interface_ids() const { - auto* array_pointer = - version() < 2 ? nullptr : header_v2()->payload_interface_ids.Get(); - return array_pointer ? static_cast(array_pointer->size()) : 0; -} - -const uint32_t* Message::payload_interface_ids() const { - auto* array_pointer = - version() < 2 ? nullptr : header_v2()->payload_interface_ids.Get(); - return array_pointer ? array_pointer->storage() : nullptr; -} - -ScopedMessageHandle Message::TakeMojoMessage() { - // If there are associated endpoints transferred, - // SerializeAssociatedEndpointHandles() must be called before this method. - DCHECK(associated_endpoint_handles_.empty()); - - if (handles_.empty()) // Fast path for the common case: No handles. - return buffer_->TakeMessage(); - - // Allocate a new message with space for the handles, then copy the buffer - // contents into it. - // - // TODO(rockot): We could avoid this copy by extending GetSerializedSize() - // behavior to collect handles. It's unoptimized for now because it's much - // more common to have messages with no handles. - ScopedMessageHandle new_message; - MojoResult rv = AllocMessage( - data_num_bytes(), - handles_.empty() ? nullptr - : reinterpret_cast(handles_.data()), - handles_.size(), - MOJO_ALLOC_MESSAGE_FLAG_NONE, - &new_message); - CHECK_EQ(rv, MOJO_RESULT_OK); - handles_.clear(); - - void* new_buffer = nullptr; - rv = GetMessageBuffer(new_message.get(), &new_buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - - memcpy(new_buffer, data(), data_num_bytes()); - buffer_.reset(); - - return new_message; -} - -void Message::NotifyBadMessage(const std::string& error) { - DCHECK(buffer_); - buffer_->NotifyBadMessage(error); -} - -void Message::CloseHandles() { - for (std::vector::iterator it = handles_.begin(); - it != handles_.end(); ++it) { - if (it->is_valid()) - CloseRaw(*it); - } -} - -void Message::SerializeAssociatedEndpointHandles( - AssociatedGroupController* group_controller) { - if (associated_endpoint_handles_.empty()) - return; - - DCHECK_GE(version(), 2u); - DCHECK(header_v2()->payload_interface_ids.is_null()); - - size_t size = associated_endpoint_handles_.size(); - auto* data = internal::Array_Data::New(size, buffer()); - header_v2()->payload_interface_ids.Set(data); - - for (size_t i = 0; i < size; ++i) { - ScopedInterfaceEndpointHandle& handle = associated_endpoint_handles_[i]; - - DCHECK(handle.pending_association()); - data->storage()[i] = - group_controller->AssociateInterface(std::move(handle)); - } - associated_endpoint_handles_.clear(); -} - -bool Message::DeserializeAssociatedEndpointHandles( - AssociatedGroupController* group_controller) { - associated_endpoint_handles_.clear(); - - uint32_t num_ids = payload_num_interface_ids(); - if (num_ids == 0) - return true; - - associated_endpoint_handles_.reserve(num_ids); - uint32_t* ids = header_v2()->payload_interface_ids.Get()->storage(); - bool result = true; - for (uint32_t i = 0; i < num_ids; ++i) { - auto handle = group_controller->CreateLocalEndpointHandle(ids[i]); - if (IsValidInterfaceId(ids[i]) && !handle.is_valid()) { - // |ids[i]| itself is valid but handle creation failed. In that case, mark - // deserialization as failed but continue to deserialize the rest of - // handles. - result = false; - } - - associated_endpoint_handles_.push_back(std::move(handle)); - ids[i] = kInvalidInterfaceId; - } - return result; -} - -PassThroughFilter::PassThroughFilter() {} - -PassThroughFilter::~PassThroughFilter() {} - -bool PassThroughFilter::Accept(Message* message) { return true; } - -SyncMessageResponseContext::SyncMessageResponseContext() - : outer_context_(current()) { - g_tls_sync_response_context.Get().Set(this); -} - -SyncMessageResponseContext::~SyncMessageResponseContext() { - DCHECK_EQ(current(), this); - g_tls_sync_response_context.Get().Set(outer_context_); -} - -// static -SyncMessageResponseContext* SyncMessageResponseContext::current() { - return g_tls_sync_response_context.Get().Get(); -} - -void SyncMessageResponseContext::ReportBadMessage(const std::string& error) { - GetBadMessageCallback().Run(error); -} - -const ReportBadMessageCallback& -SyncMessageResponseContext::GetBadMessageCallback() { - if (bad_message_callback_.is_null()) { - bad_message_callback_ = - base::Bind(&DoNotifyBadMessage, base::Passed(&response_)); - } - return bad_message_callback_; -} - -MojoResult ReadMessage(MessagePipeHandle handle, Message* message) { - MojoResult rv; - - std::vector handles; - ScopedMessageHandle mojo_message; - uint32_t num_bytes = 0, num_handles = 0; - rv = ReadMessageNew(handle, - &mojo_message, - &num_bytes, - nullptr, - &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE); - if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) { - DCHECK_GT(num_handles, 0u); - handles.resize(num_handles); - rv = ReadMessageNew(handle, - &mojo_message, - &num_bytes, - reinterpret_cast(handles.data()), - &num_handles, - MOJO_READ_MESSAGE_FLAG_NONE); - } - - if (rv != MOJO_RESULT_OK) - return rv; - - message->InitializeFromMojoMessage( - std::move(mojo_message), num_bytes, &handles); - return MOJO_RESULT_OK; -} - -void ReportBadMessage(const std::string& error) { - internal::MessageDispatchContext* context = - internal::MessageDispatchContext::current(); - DCHECK(context); - context->GetBadMessageCallback().Run(error); -} - -ReportBadMessageCallback GetBadMessageCallback() { - internal::MessageDispatchContext* context = - internal::MessageDispatchContext::current(); - DCHECK(context); - return context->GetBadMessageCallback(); -} - -namespace internal { - -MessageHeaderV2::MessageHeaderV2() = default; - -MessageDispatchContext::MessageDispatchContext(Message* message) - : outer_context_(current()), message_(message) { - g_tls_message_dispatch_context.Get().Set(this); -} - -MessageDispatchContext::~MessageDispatchContext() { - DCHECK_EQ(current(), this); - g_tls_message_dispatch_context.Get().Set(outer_context_); -} - -// static -MessageDispatchContext* MessageDispatchContext::current() { - return g_tls_message_dispatch_context.Get().Get(); -} - -const ReportBadMessageCallback& -MessageDispatchContext::GetBadMessageCallback() { - if (bad_message_callback_.is_null()) { - bad_message_callback_ = - base::Bind(&DoNotifyBadMessage, base::Passed(message_)); - } - return bad_message_callback_; -} - -// static -void SyncMessageResponseSetup::SetCurrentSyncResponseMessage(Message* message) { - SyncMessageResponseContext* context = SyncMessageResponseContext::current(); - if (context) - context->response_ = std::move(*message); -} - -} // namespace internal - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_buffer.cc b/mojo/public/cpp/bindings/lib/message_buffer.cc deleted file mode 100644 index cc12ef6..0000000 --- a/mojo/public/cpp/bindings/lib/message_buffer.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/message_buffer.h" - -#include - -#include "mojo/public/cpp/bindings/lib/serialization_util.h" - -namespace mojo { -namespace internal { - -MessageBuffer::MessageBuffer(size_t capacity, bool zero_initialized) { - DCHECK_LE(capacity, std::numeric_limits::max()); - - MojoResult rv = AllocMessage(capacity, nullptr, 0, - MOJO_ALLOC_MESSAGE_FLAG_NONE, &message_); - CHECK_EQ(rv, MOJO_RESULT_OK); - - void* buffer = nullptr; - if (capacity != 0) { - rv = GetMessageBuffer(message_.get(), &buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - - if (zero_initialized) - memset(buffer, 0, capacity); - } - Initialize(buffer, capacity); -} - -MessageBuffer::MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes) { - message_ = std::move(message); - - void* buffer = nullptr; - if (num_bytes != 0) { - MojoResult rv = GetMessageBuffer(message_.get(), &buffer); - CHECK_EQ(rv, MOJO_RESULT_OK); - } - Initialize(buffer, num_bytes); -} - -MessageBuffer::~MessageBuffer() {} - -void MessageBuffer::NotifyBadMessage(const std::string& error) { - DCHECK(message_.is_valid()); - MojoResult result = mojo::NotifyBadMessage(message_.get(), error); - DCHECK_EQ(result, MOJO_RESULT_OK); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_buffer.h b/mojo/public/cpp/bindings/lib/message_buffer.h deleted file mode 100644 index 96d5140..0000000 --- a/mojo/public/cpp/bindings/lib/message_buffer.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ - -#include - -#include - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/system/message.h" - -namespace mojo { -namespace internal { - -// A fixed-size Buffer using a Mojo message object for storage. -class MessageBuffer : public Buffer { - public: - // Initializes this buffer to carry a fixed byte capacity and no handles. - MessageBuffer(size_t capacity, bool zero_initialized); - - // Initializes this buffer from an existing Mojo MessageHandle. - MessageBuffer(ScopedMessageHandle message, uint32_t num_bytes); - - ~MessageBuffer(); - - ScopedMessageHandle TakeMessage() { return std::move(message_); } - - void NotifyBadMessage(const std::string& error); - - private: - ScopedMessageHandle message_; - - DISALLOW_COPY_AND_ASSIGN(MessageBuffer); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_LIB_MESSAGE_BUFFER_H_ diff --git a/mojo/public/cpp/bindings/lib/message_builder.cc b/mojo/public/cpp/bindings/lib/message_builder.cc deleted file mode 100644 index 6806a73..0000000 --- a/mojo/public/cpp/bindings/lib/message_builder.cc +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/message_builder.h" - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/message_internal.h" - -namespace mojo { -namespace internal { - -template -void Allocate(Buffer* buf, Header** header) { - *header = static_cast(buf->Allocate(sizeof(Header))); - (*header)->num_bytes = sizeof(Header); -} - -MessageBuilder::MessageBuilder(uint32_t name, - uint32_t flags, - size_t payload_size, - size_t payload_interface_id_count) { - if (payload_interface_id_count > 0) { - // Version 2 - InitializeMessage( - sizeof(MessageHeaderV2) + Align(payload_size) + - ArrayDataTraits::GetStorageSize( - static_cast(payload_interface_id_count))); - - MessageHeaderV2* header; - Allocate(message_.buffer(), &header); - header->version = 2; - header->name = name; - header->flags = flags; - // The payload immediately follows the header. - header->payload.Set(header + 1); - } else if (flags & - (Message::kFlagExpectsResponse | Message::kFlagIsResponse)) { - // Version 1 - InitializeMessage(sizeof(MessageHeaderV1) + payload_size); - - MessageHeaderV1* header; - Allocate(message_.buffer(), &header); - header->version = 1; - header->name = name; - header->flags = flags; - } else { - InitializeMessage(sizeof(MessageHeader) + payload_size); - - MessageHeader* header; - Allocate(message_.buffer(), &header); - header->version = 0; - header->name = name; - header->flags = flags; - } -} - -MessageBuilder::~MessageBuilder() { -} - -void MessageBuilder::InitializeMessage(size_t size) { - message_.Initialize(static_cast(Align(size)), - true /* zero_initialized */); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_builder.h b/mojo/public/cpp/bindings/lib/message_builder.h deleted file mode 100644 index 8a4d5c4..0000000 --- a/mojo/public/cpp/bindings/lib/message_builder.h +++ /dev/null @@ -1,45 +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_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_ - -#include -#include - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace mojo { - -class Message; - -namespace internal { - -class Buffer; - -class MOJO_CPP_BINDINGS_EXPORT MessageBuilder { - public: - MessageBuilder(uint32_t name, - uint32_t flags, - size_t payload_size, - size_t payload_interface_id_count); - ~MessageBuilder(); - - Buffer* buffer() { return message_.buffer(); } - Message* message() { return &message_; } - - private: - void InitializeMessage(size_t size); - - Message message_; - - DISALLOW_COPY_AND_ASSIGN(MessageBuilder); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_BUILDER_H_ diff --git a/mojo/public/cpp/bindings/lib/message_header_validator.cc b/mojo/public/cpp/bindings/lib/message_header_validator.cc deleted file mode 100644 index 9f8c627..0000000 --- a/mojo/public/cpp/bindings/lib/message_header_validator.cc +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/message_header_validator.h" - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/validate_params.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" - -namespace mojo { -namespace { - -// TODO(yzshen): Define a mojom struct for message header and use the generated -// validation and data view code. -bool IsValidMessageHeader(const internal::MessageHeader* header, - internal::ValidationContext* validation_context) { - // NOTE: Our goal is to preserve support for future extension of the message - // header. If we encounter fields we do not understand, we must ignore them. - - // Extra validation of the struct header: - do { - if (header->version == 0) { - if (header->num_bytes == sizeof(internal::MessageHeader)) - break; - } else if (header->version == 1) { - if (header->num_bytes == sizeof(internal::MessageHeaderV1)) - break; - } else if (header->version == 2) { - if (header->num_bytes == sizeof(internal::MessageHeaderV2)) - break; - } else if (header->version > 2) { - if (header->num_bytes >= sizeof(internal::MessageHeaderV2)) - break; - } - internal::ReportValidationError( - validation_context, - internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); - return false; - } while (false); - - // Validate flags (allow unknown bits): - - // These flags require a RequestID. - constexpr uint32_t kRequestIdFlags = - Message::kFlagExpectsResponse | Message::kFlagIsResponse; - if (header->version == 0 && (header->flags & kRequestIdFlags)) { - internal::ReportValidationError( - validation_context, - internal::VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID); - return false; - } - - // These flags are mutually exclusive. - if ((header->flags & kRequestIdFlags) == kRequestIdFlags) { - internal::ReportValidationError( - validation_context, - internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); - return false; - } - - if (header->version < 2) - return true; - - auto* header_v2 = static_cast(header); - // For the payload pointer: - // - Check that the pointer can be safely decoded. - // - Claim one byte that the pointer points to. It makes sure not only the - // address is within the message, but also the address precedes the array - // storing interface IDs (which is important for safely calculating the - // payload size). - // - Validation of the payload contents will be done separately based on the - // payload type. - if (!header_v2->payload.is_null() && - (!internal::ValidatePointer(header_v2->payload, validation_context) || - !validation_context->ClaimMemory(header_v2->payload.Get(), 1))) { - return false; - } - - const internal::ContainerValidateParams validate_params(0, false, nullptr); - if (!internal::ValidateContainer(header_v2->payload_interface_ids, - validation_context, &validate_params)) { - return false; - } - - if (!header_v2->payload_interface_ids.is_null()) { - size_t num_ids = header_v2->payload_interface_ids.Get()->size(); - const uint32_t* ids = header_v2->payload_interface_ids.Get()->storage(); - for (size_t i = 0; i < num_ids; ++i) { - if (!IsValidInterfaceId(ids[i]) || IsMasterInterfaceId(ids[i])) { - internal::ReportValidationError( - validation_context, - internal::VALIDATION_ERROR_ILLEGAL_INTERFACE_ID); - return false; - } - } - } - - return true; -} - -} // namespace - -MessageHeaderValidator::MessageHeaderValidator() - : MessageHeaderValidator("MessageHeaderValidator") {} - -MessageHeaderValidator::MessageHeaderValidator(const std::string& description) - : description_(description) { -} - -void MessageHeaderValidator::SetDescription(const std::string& description) { - description_ = description; -} - -bool MessageHeaderValidator::Accept(Message* message) { - // Pass 0 as number of handles and associated endpoint handles because we - // don't expect any in the header, even if |message| contains handles. - internal::ValidationContext validation_context( - message->data(), message->data_num_bytes(), 0, 0, message, description_); - - if (!internal::ValidateStructHeaderAndClaimMemory(message->data(), - &validation_context)) - return false; - - if (!IsValidMessageHeader(message->header(), &validation_context)) - return false; - - return true; -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/message_internal.h b/mojo/public/cpp/bindings/lib/message_internal.h deleted file mode 100644 index 6693198..0000000 --- a/mojo/public/cpp/bindings/lib/message_internal.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_ - -#include - -#include - -#include "base/callback.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" - -namespace mojo { - -class Message; - -namespace internal { - -template -class Array_Data; - -#pragma pack(push, 1) - -struct MessageHeader : internal::StructHeader { - // Interface ID for identifying multiple interfaces running on the same - // message pipe. - uint32_t interface_id; - // Message name, which is scoped to the interface that the message belongs to. - uint32_t name; - // 0 or either of the enum values defined above. - uint32_t flags; - // Unused padding to make the struct size a multiple of 8 bytes. - uint32_t padding; -}; -static_assert(sizeof(MessageHeader) == 24, "Bad sizeof(MessageHeader)"); - -struct MessageHeaderV1 : MessageHeader { - // Only used if either kFlagExpectsResponse or kFlagIsResponse is set in - // order to match responses with corresponding requests. - uint64_t request_id; -}; -static_assert(sizeof(MessageHeaderV1) == 32, "Bad sizeof(MessageHeaderV1)"); - -struct MessageHeaderV2 : MessageHeaderV1 { - MessageHeaderV2(); - GenericPointer payload; - Pointer> payload_interface_ids; -}; -static_assert(sizeof(MessageHeaderV2) == 48, "Bad sizeof(MessageHeaderV2)"); - -#pragma pack(pop) - -class MOJO_CPP_BINDINGS_EXPORT MessageDispatchContext { - public: - explicit MessageDispatchContext(Message* message); - ~MessageDispatchContext(); - - static MessageDispatchContext* current(); - - const base::Callback& GetBadMessageCallback(); - - private: - MessageDispatchContext* outer_context_; - Message* message_; - base::Callback bad_message_callback_; - - DISALLOW_COPY_AND_ASSIGN(MessageDispatchContext); -}; - -class MOJO_CPP_BINDINGS_EXPORT SyncMessageResponseSetup { - public: - static void SetCurrentSyncResponseMessage(Message* message); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MESSAGE_INTERNAL_H_ diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc deleted file mode 100644 index ff7c678..0000000 --- a/mojo/public/cpp/bindings/lib/multiplex_router.cc +++ /dev/null @@ -1,960 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/multiplex_router.h" - -#include - -#include - -#include "base/bind.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" -#include "base/stl_util.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/interface_endpoint_client.h" -#include "mojo/public/cpp/bindings/interface_endpoint_controller.h" -#include "mojo/public/cpp/bindings/lib/may_auto_lock.h" -#include "mojo/public/cpp/bindings/sync_event_watcher.h" - -namespace mojo { -namespace internal { - -// InterfaceEndpoint stores the information of an interface endpoint registered -// with the router. -// No one other than the router's |endpoints_| and |tasks_| should hold refs to -// this object. -class MultiplexRouter::InterfaceEndpoint - : public base::RefCountedThreadSafe, - public InterfaceEndpointController { - public: - InterfaceEndpoint(MultiplexRouter* router, InterfaceId id) - : router_(router), - id_(id), - closed_(false), - peer_closed_(false), - handle_created_(false), - client_(nullptr) {} - - // --------------------------------------------------------------------------- - // The following public methods are safe to call from any threads without - // locking. - - InterfaceId id() const { return id_; } - - // --------------------------------------------------------------------------- - // The following public methods are called under the router's lock. - - bool closed() const { return closed_; } - void set_closed() { - router_->AssertLockAcquired(); - closed_ = true; - } - - bool peer_closed() const { return peer_closed_; } - void set_peer_closed() { - router_->AssertLockAcquired(); - peer_closed_ = true; - } - - bool handle_created() const { return handle_created_; } - void set_handle_created() { - router_->AssertLockAcquired(); - handle_created_ = true; - } - - const base::Optional& disconnect_reason() const { - return disconnect_reason_; - } - void set_disconnect_reason( - const base::Optional& disconnect_reason) { - router_->AssertLockAcquired(); - disconnect_reason_ = disconnect_reason; - } - - base::SingleThreadTaskRunner* task_runner() const { - return task_runner_.get(); - } - - InterfaceEndpointClient* client() const { return client_; } - - void AttachClient(InterfaceEndpointClient* client, - scoped_refptr runner) { - router_->AssertLockAcquired(); - DCHECK(!client_); - DCHECK(!closed_); - DCHECK(runner->BelongsToCurrentThread()); - - task_runner_ = std::move(runner); - client_ = client; - } - - // This method must be called on the same thread as the corresponding - // AttachClient() call. - void DetachClient() { - router_->AssertLockAcquired(); - DCHECK(client_); - DCHECK(task_runner_->BelongsToCurrentThread()); - DCHECK(!closed_); - - task_runner_ = nullptr; - client_ = nullptr; - sync_watcher_.reset(); - } - - void SignalSyncMessageEvent() { - router_->AssertLockAcquired(); - if (sync_message_event_signaled_) - return; - sync_message_event_signaled_ = true; - if (sync_message_event_) - sync_message_event_->Signal(); - } - - void ResetSyncMessageSignal() { - router_->AssertLockAcquired(); - if (!sync_message_event_signaled_) - return; - sync_message_event_signaled_ = false; - if (sync_message_event_) - sync_message_event_->Reset(); - } - - // --------------------------------------------------------------------------- - // The following public methods (i.e., InterfaceEndpointController - // implementation) are called by the client on the same thread as the - // AttachClient() call. They are called outside of the router's lock. - - bool SendMessage(Message* message) override { - DCHECK(task_runner_->BelongsToCurrentThread()); - message->set_interface_id(id_); - return router_->connector_.Accept(message); - } - - void AllowWokenUpBySyncWatchOnSameThread() override { - DCHECK(task_runner_->BelongsToCurrentThread()); - - EnsureSyncWatcherExists(); - sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); - } - - bool SyncWatch(const bool* should_stop) override { - DCHECK(task_runner_->BelongsToCurrentThread()); - - EnsureSyncWatcherExists(); - return sync_watcher_->SyncWatch(should_stop); - } - - private: - friend class base::RefCountedThreadSafe; - - ~InterfaceEndpoint() override { - router_->AssertLockAcquired(); - - DCHECK(!client_); - DCHECK(closed_); - DCHECK(peer_closed_); - DCHECK(!sync_watcher_); - } - - void OnSyncEventSignaled() { - DCHECK(task_runner_->BelongsToCurrentThread()); - scoped_refptr router_protector(router_); - - MayAutoLock locker(&router_->lock_); - scoped_refptr self_protector(this); - - bool more_to_process = router_->ProcessFirstSyncMessageForEndpoint(id_); - - if (!more_to_process) - ResetSyncMessageSignal(); - - // Currently there are no queued sync messages and the peer has closed so - // there won't be incoming sync messages in the future. - if (!more_to_process && peer_closed_) { - // If a SyncWatch() call (or multiple ones) of this interface endpoint is - // on the call stack, resetting the sync watcher will allow it to exit - // when the call stack unwinds to that frame. - sync_watcher_.reset(); - } - } - - void EnsureSyncWatcherExists() { - DCHECK(task_runner_->BelongsToCurrentThread()); - if (sync_watcher_) - return; - - { - MayAutoLock locker(&router_->lock_); - if (!sync_message_event_) { - sync_message_event_.emplace( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - if (sync_message_event_signaled_) - sync_message_event_->Signal(); - } - } - sync_watcher_.reset( - new SyncEventWatcher(&sync_message_event_.value(), - base::Bind(&InterfaceEndpoint::OnSyncEventSignaled, - base::Unretained(this)))); - } - - // --------------------------------------------------------------------------- - // The following members are safe to access from any threads. - - MultiplexRouter* const router_; - const InterfaceId id_; - - // --------------------------------------------------------------------------- - // The following members are accessed under the router's lock. - - // Whether the endpoint has been closed. - bool closed_; - // Whether the peer endpoint has been closed. - bool peer_closed_; - - // Whether there is already a ScopedInterfaceEndpointHandle created for this - // endpoint. - bool handle_created_; - - base::Optional disconnect_reason_; - - // The task runner on which |client_|'s methods can be called. - scoped_refptr task_runner_; - // Not owned. It is null if no client is attached to this endpoint. - InterfaceEndpointClient* client_; - - // An event used to signal that sync messages are available. The event is - // initialized under the router's lock and remains unchanged afterwards. It - // may be accessed outside of the router's lock later. - base::Optional sync_message_event_; - bool sync_message_event_signaled_ = false; - - // --------------------------------------------------------------------------- - // The following members are only valid while a client is attached. They are - // used exclusively on the client's thread. They may be accessed outside of - // the router's lock. - - std::unique_ptr sync_watcher_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceEndpoint); -}; - -// MessageWrapper objects are always destroyed under the router's lock. On -// destruction, if the message it wrappers contains -// ScopedInterfaceEndpointHandles (which cannot be destructed under the -// router's lock), the wrapper unlocks to clean them up. -class MultiplexRouter::MessageWrapper { - public: - MessageWrapper() = default; - - MessageWrapper(MultiplexRouter* router, Message message) - : router_(router), value_(std::move(message)) {} - - MessageWrapper(MessageWrapper&& other) - : router_(other.router_), value_(std::move(other.value_)) {} - - ~MessageWrapper() { - if (value_.associated_endpoint_handles()->empty()) - return; - - router_->AssertLockAcquired(); - { - MayAutoUnlock unlocker(&router_->lock_); - value_.mutable_associated_endpoint_handles()->clear(); - } - } - - MessageWrapper& operator=(MessageWrapper&& other) { - router_ = other.router_; - value_ = std::move(other.value_); - return *this; - } - - Message& value() { return value_; } - - private: - MultiplexRouter* router_ = nullptr; - Message value_; - - DISALLOW_COPY_AND_ASSIGN(MessageWrapper); -}; - -struct MultiplexRouter::Task { - public: - // Doesn't take ownership of |message| but takes its contents. - static std::unique_ptr CreateMessageTask( - MessageWrapper message_wrapper) { - Task* task = new Task(MESSAGE); - task->message_wrapper = std::move(message_wrapper); - return base::WrapUnique(task); - } - static std::unique_ptr CreateNotifyErrorTask( - InterfaceEndpoint* endpoint) { - Task* task = new Task(NOTIFY_ERROR); - task->endpoint_to_notify = endpoint; - return base::WrapUnique(task); - } - - ~Task() {} - - bool IsMessageTask() const { return type == MESSAGE; } - bool IsNotifyErrorTask() const { return type == NOTIFY_ERROR; } - - MessageWrapper message_wrapper; - scoped_refptr endpoint_to_notify; - - enum Type { MESSAGE, NOTIFY_ERROR }; - Type type; - - private: - explicit Task(Type in_type) : type(in_type) {} - - DISALLOW_COPY_AND_ASSIGN(Task); -}; - -MultiplexRouter::MultiplexRouter( - ScopedMessagePipeHandle message_pipe, - Config config, - bool set_interface_id_namesapce_bit, - scoped_refptr runner) - : set_interface_id_namespace_bit_(set_interface_id_namesapce_bit), - task_runner_(runner), - header_validator_(nullptr), - filters_(this), - connector_(std::move(message_pipe), - config == MULTI_INTERFACE ? Connector::MULTI_THREADED_SEND - : Connector::SINGLE_THREADED_SEND, - std::move(runner)), - control_message_handler_(this), - control_message_proxy_(&connector_), - next_interface_id_value_(1), - posted_to_process_tasks_(false), - encountered_error_(false), - paused_(false), - testing_mode_(false) { - DCHECK(task_runner_->BelongsToCurrentThread()); - - if (config == MULTI_INTERFACE) - lock_.emplace(); - - if (config == SINGLE_INTERFACE_WITH_SYNC_METHODS || - config == MULTI_INTERFACE) { - // Always participate in sync handle watching in multi-interface mode, - // because even if it doesn't expect sync requests during sync handle - // watching, it may still need to dispatch messages to associated endpoints - // on a different thread. - connector_.AllowWokenUpBySyncWatchOnSameThread(); - } - connector_.set_incoming_receiver(&filters_); - connector_.set_connection_error_handler( - base::Bind(&MultiplexRouter::OnPipeConnectionError, - base::Unretained(this))); - - std::unique_ptr header_validator = - base::MakeUnique(); - header_validator_ = header_validator.get(); - filters_.Append(std::move(header_validator)); -} - -MultiplexRouter::~MultiplexRouter() { - MayAutoLock locker(&lock_); - - sync_message_tasks_.clear(); - tasks_.clear(); - - for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { - InterfaceEndpoint* endpoint = iter->second.get(); - // Increment the iterator before calling UpdateEndpointStateMayRemove() - // because it may remove the corresponding value from the map. - ++iter; - - if (!endpoint->closed()) { - // This happens when a NotifyPeerEndpointClosed message been received, but - // the interface ID hasn't been used to create local endpoint handle. - DCHECK(!endpoint->client()); - DCHECK(endpoint->peer_closed()); - UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); - } else { - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - } - } - - DCHECK(endpoints_.empty()); -} - -void MultiplexRouter::SetMasterInterfaceName(const char* name) { - DCHECK(thread_checker_.CalledOnValidThread()); - header_validator_->SetDescription( - std::string(name) + " [master] MessageHeaderValidator"); - control_message_handler_.SetDescription( - std::string(name) + " [master] PipeControlMessageHandler"); - connector_.SetWatcherHeapProfilerTag(name); -} - -InterfaceId MultiplexRouter::AssociateInterface( - ScopedInterfaceEndpointHandle handle_to_send) { - if (!handle_to_send.pending_association()) - return kInvalidInterfaceId; - - uint32_t id = 0; - { - MayAutoLock locker(&lock_); - do { - if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) - next_interface_id_value_ = 1; - id = next_interface_id_value_++; - if (set_interface_id_namespace_bit_) - id |= kInterfaceIdNamespaceMask; - } while (base::ContainsKey(endpoints_, id)); - - InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); - endpoints_[id] = endpoint; - if (encountered_error_) - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - endpoint->set_handle_created(); - } - - if (!NotifyAssociation(&handle_to_send, id)) { - // The peer handle of |handle_to_send|, which is supposed to join this - // associated group, has been closed. - { - MayAutoLock locker(&lock_); - InterfaceEndpoint* endpoint = FindEndpoint(id); - if (endpoint) - UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); - } - - control_message_proxy_.NotifyPeerEndpointClosed( - id, handle_to_send.disconnect_reason()); - } - return id; -} - -ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( - InterfaceId id) { - if (!IsValidInterfaceId(id)) - return ScopedInterfaceEndpointHandle(); - - MayAutoLock locker(&lock_); - bool inserted = false; - InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); - if (inserted) { - DCHECK(!endpoint->handle_created()); - - if (encountered_error_) - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - } else { - // If the endpoint already exist, it is because we have received a - // notification that the peer endpoint has closed. - CHECK(!endpoint->closed()); - CHECK(endpoint->peer_closed()); - - if (endpoint->handle_created()) - return ScopedInterfaceEndpointHandle(); - } - - endpoint->set_handle_created(); - return CreateScopedInterfaceEndpointHandle(id); -} - -void MultiplexRouter::CloseEndpointHandle( - InterfaceId id, - const base::Optional& reason) { - if (!IsValidInterfaceId(id)) - return; - - MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); - InterfaceEndpoint* endpoint = endpoints_[id].get(); - DCHECK(!endpoint->client()); - DCHECK(!endpoint->closed()); - UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); - - if (!IsMasterInterfaceId(id) || reason) { - MayAutoUnlock unlocker(&lock_); - control_message_proxy_.NotifyPeerEndpointClosed(id, reason); - } - - ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); -} - -InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( - const ScopedInterfaceEndpointHandle& handle, - InterfaceEndpointClient* client, - scoped_refptr runner) { - const InterfaceId id = handle.id(); - - DCHECK(IsValidInterfaceId(id)); - DCHECK(client); - - MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); - - InterfaceEndpoint* endpoint = endpoints_[id].get(); - endpoint->AttachClient(client, std::move(runner)); - - if (endpoint->peer_closed()) - tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); - ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); - - return endpoint; -} - -void MultiplexRouter::DetachEndpointClient( - const ScopedInterfaceEndpointHandle& handle) { - const InterfaceId id = handle.id(); - - DCHECK(IsValidInterfaceId(id)); - - MayAutoLock locker(&lock_); - DCHECK(base::ContainsKey(endpoints_, id)); - - InterfaceEndpoint* endpoint = endpoints_[id].get(); - endpoint->DetachClient(); -} - -void MultiplexRouter::RaiseError() { - if (task_runner_->BelongsToCurrentThread()) { - connector_.RaiseError(); - } else { - task_runner_->PostTask(FROM_HERE, - base::Bind(&MultiplexRouter::RaiseError, this)); - } -} - -void MultiplexRouter::CloseMessagePipe() { - DCHECK(thread_checker_.CalledOnValidThread()); - connector_.CloseMessagePipe(); - // CloseMessagePipe() above won't trigger connection error handler. - // Explicitly call OnPipeConnectionError() so that associated endpoints will - // get notified. - OnPipeConnectionError(); -} - -void MultiplexRouter::PauseIncomingMethodCallProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); - connector_.PauseIncomingMethodCallProcessing(); - - MayAutoLock locker(&lock_); - paused_ = true; - - for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter) - iter->second->ResetSyncMessageSignal(); -} - -void MultiplexRouter::ResumeIncomingMethodCallProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); - connector_.ResumeIncomingMethodCallProcessing(); - - MayAutoLock locker(&lock_); - paused_ = false; - - for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter) { - auto sync_iter = sync_message_tasks_.find(iter->first); - if (iter->second->peer_closed() || - (sync_iter != sync_message_tasks_.end() && - !sync_iter->second.empty())) { - iter->second->SignalSyncMessageEvent(); - } - } - - ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); -} - -bool MultiplexRouter::HasAssociatedEndpoints() const { - DCHECK(thread_checker_.CalledOnValidThread()); - MayAutoLock locker(&lock_); - - if (endpoints_.size() > 1) - return true; - if (endpoints_.size() == 0) - return false; - - return !base::ContainsKey(endpoints_, kMasterInterfaceId); -} - -void MultiplexRouter::EnableTestingMode() { - DCHECK(thread_checker_.CalledOnValidThread()); - MayAutoLock locker(&lock_); - - testing_mode_ = true; - connector_.set_enforce_errors_from_incoming_receiver(false); -} - -bool MultiplexRouter::Accept(Message* message) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!message->DeserializeAssociatedEndpointHandles(this)) - return false; - - scoped_refptr protector(this); - MayAutoLock locker(&lock_); - - DCHECK(!paused_); - - ClientCallBehavior client_call_behavior = - connector_.during_sync_handle_watcher_callback() - ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES - : ALLOW_DIRECT_CLIENT_CALLS; - - bool processed = - tasks_.empty() && ProcessIncomingMessage(message, client_call_behavior, - connector_.task_runner()); - - if (!processed) { - // Either the task queue is not empty or we cannot process the message - // directly. In both cases, there is no need to call ProcessTasks(). - tasks_.push_back( - Task::CreateMessageTask(MessageWrapper(this, std::move(*message)))); - Task* task = tasks_.back().get(); - - if (task->message_wrapper.value().has_flag(Message::kFlagIsSync)) { - InterfaceId id = task->message_wrapper.value().interface_id(); - sync_message_tasks_[id].push_back(task); - InterfaceEndpoint* endpoint = FindEndpoint(id); - if (endpoint) - endpoint->SignalSyncMessageEvent(); - } - } else if (!tasks_.empty()) { - // Processing the message may result in new tasks (for error notification) - // being added to the queue. In this case, we have to attempt to process the - // tasks. - ProcessTasks(client_call_behavior, connector_.task_runner()); - } - - // Always return true. If we see errors during message processing, we will - // explicitly call Connector::RaiseError() to disconnect the message pipe. - return true; -} - -bool MultiplexRouter::OnPeerAssociatedEndpointClosed( - InterfaceId id, - const base::Optional& reason) { - DCHECK(!IsMasterInterfaceId(id) || reason); - - MayAutoLock locker(&lock_); - InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, nullptr); - - if (reason) - endpoint->set_disconnect_reason(reason); - - // It is possible that this endpoint has been set as peer closed. That is - // because when the message pipe is closed, all the endpoints are updated with - // PEER_ENDPOINT_CLOSED. We continue to process remaining tasks in the queue, - // as long as there are refs keeping the router alive. If there is a - // PeerAssociatedEndpointClosedEvent control message in the queue, we will get - // here and see that the endpoint has been marked as peer closed. - if (!endpoint->peer_closed()) { - if (endpoint->client()) - tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - } - - // No need to trigger a ProcessTasks() because it is already on the stack. - - return true; -} - -void MultiplexRouter::OnPipeConnectionError() { - DCHECK(thread_checker_.CalledOnValidThread()); - - scoped_refptr protector(this); - MayAutoLock locker(&lock_); - - encountered_error_ = true; - - for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { - InterfaceEndpoint* endpoint = iter->second.get(); - // Increment the iterator before calling UpdateEndpointStateMayRemove() - // because it may remove the corresponding value from the map. - ++iter; - - if (endpoint->client()) - tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); - - UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); - } - - ProcessTasks(connector_.during_sync_handle_watcher_callback() - ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES - : ALLOW_DIRECT_CLIENT_CALLS, - connector_.task_runner()); -} - -void MultiplexRouter::ProcessTasks( - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner) { - AssertLockAcquired(); - - if (posted_to_process_tasks_) - return; - - while (!tasks_.empty() && !paused_) { - std::unique_ptr task(std::move(tasks_.front())); - tasks_.pop_front(); - - InterfaceId id = kInvalidInterfaceId; - bool sync_message = - task->IsMessageTask() && !task->message_wrapper.value().IsNull() && - task->message_wrapper.value().has_flag(Message::kFlagIsSync); - if (sync_message) { - id = task->message_wrapper.value().interface_id(); - auto& sync_message_queue = sync_message_tasks_[id]; - DCHECK_EQ(task.get(), sync_message_queue.front()); - sync_message_queue.pop_front(); - } - - bool processed = - task->IsNotifyErrorTask() - ? ProcessNotifyErrorTask(task.get(), client_call_behavior, - current_task_runner) - : ProcessIncomingMessage(&task->message_wrapper.value(), - client_call_behavior, current_task_runner); - - if (!processed) { - if (sync_message) { - auto& sync_message_queue = sync_message_tasks_[id]; - sync_message_queue.push_front(task.get()); - } - tasks_.push_front(std::move(task)); - break; - } else { - if (sync_message) { - auto iter = sync_message_tasks_.find(id); - if (iter != sync_message_tasks_.end() && iter->second.empty()) - sync_message_tasks_.erase(iter); - } - } - } -} - -bool MultiplexRouter::ProcessFirstSyncMessageForEndpoint(InterfaceId id) { - AssertLockAcquired(); - - auto iter = sync_message_tasks_.find(id); - if (iter == sync_message_tasks_.end()) - return false; - - if (paused_) - return true; - - MultiplexRouter::Task* task = iter->second.front(); - iter->second.pop_front(); - - DCHECK(task->IsMessageTask()); - MessageWrapper message_wrapper = std::move(task->message_wrapper); - - // Note: after this call, |task| and |iter| may be invalidated. - bool processed = ProcessIncomingMessage( - &message_wrapper.value(), ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES, - nullptr); - DCHECK(processed); - - iter = sync_message_tasks_.find(id); - if (iter == sync_message_tasks_.end()) - return false; - - if (iter->second.empty()) { - sync_message_tasks_.erase(iter); - return false; - } - - return true; -} - -bool MultiplexRouter::ProcessNotifyErrorTask( - Task* task, - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner) { - DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); - DCHECK(!paused_); - - AssertLockAcquired(); - InterfaceEndpoint* endpoint = task->endpoint_to_notify.get(); - if (!endpoint->client()) - return true; - - if (client_call_behavior != ALLOW_DIRECT_CLIENT_CALLS || - endpoint->task_runner() != current_task_runner) { - MaybePostToProcessTasks(endpoint->task_runner()); - return false; - } - - DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); - - InterfaceEndpointClient* client = endpoint->client(); - base::Optional disconnect_reason( - endpoint->disconnect_reason()); - - { - // We must unlock before calling into |client| because it may call this - // object within NotifyError(). Holding the lock will lead to deadlock. - // - // It is safe to call into |client| without the lock. Because |client| is - // always accessed on the same thread, including DetachEndpointClient(). - MayAutoUnlock unlocker(&lock_); - client->NotifyError(disconnect_reason); - } - return true; -} - -bool MultiplexRouter::ProcessIncomingMessage( - Message* message, - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner) { - DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); - DCHECK(!paused_); - DCHECK(message); - AssertLockAcquired(); - - if (message->IsNull()) { - // This is a sync message and has been processed during sync handle - // watching. - return true; - } - - if (PipeControlMessageHandler::IsPipeControlMessage(message)) { - bool result = false; - - { - MayAutoUnlock unlocker(&lock_); - result = control_message_handler_.Accept(message); - } - - if (!result) - RaiseErrorInNonTestingMode(); - - return true; - } - - InterfaceId id = message->interface_id(); - DCHECK(IsValidInterfaceId(id)); - - InterfaceEndpoint* endpoint = FindEndpoint(id); - if (!endpoint || endpoint->closed()) - return true; - - if (!endpoint->client()) { - // We need to wait until a client is attached in order to dispatch further - // messages. - return false; - } - - bool can_direct_call; - if (message->has_flag(Message::kFlagIsSync)) { - can_direct_call = client_call_behavior != NO_DIRECT_CLIENT_CALLS && - endpoint->task_runner()->BelongsToCurrentThread(); - } else { - can_direct_call = client_call_behavior == ALLOW_DIRECT_CLIENT_CALLS && - endpoint->task_runner() == current_task_runner; - } - - if (!can_direct_call) { - MaybePostToProcessTasks(endpoint->task_runner()); - return false; - } - - DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); - - InterfaceEndpointClient* client = endpoint->client(); - bool result = false; - { - // We must unlock before calling into |client| because it may call this - // object within HandleIncomingMessage(). Holding the lock will lead to - // deadlock. - // - // It is safe to call into |client| without the lock. Because |client| is - // always accessed on the same thread, including DetachEndpointClient(). - MayAutoUnlock unlocker(&lock_); - result = client->HandleIncomingMessage(message); - } - if (!result) - RaiseErrorInNonTestingMode(); - - return true; -} - -void MultiplexRouter::MaybePostToProcessTasks( - base::SingleThreadTaskRunner* task_runner) { - AssertLockAcquired(); - if (posted_to_process_tasks_) - return; - - posted_to_process_tasks_ = true; - posted_to_task_runner_ = task_runner; - task_runner->PostTask( - FROM_HERE, base::Bind(&MultiplexRouter::LockAndCallProcessTasks, this)); -} - -void MultiplexRouter::LockAndCallProcessTasks() { - // There is no need to hold a ref to this class in this case because this is - // always called using base::Bind(), which holds a ref. - MayAutoLock locker(&lock_); - posted_to_process_tasks_ = false; - scoped_refptr runner( - std::move(posted_to_task_runner_)); - ProcessTasks(ALLOW_DIRECT_CLIENT_CALLS, runner.get()); -} - -void MultiplexRouter::UpdateEndpointStateMayRemove( - InterfaceEndpoint* endpoint, - EndpointStateUpdateType type) { - if (type == ENDPOINT_CLOSED) { - endpoint->set_closed(); - } else { - endpoint->set_peer_closed(); - // If the interface endpoint is performing a sync watch, this makes sure - // it is notified and eventually exits the sync watch. - endpoint->SignalSyncMessageEvent(); - } - if (endpoint->closed() && endpoint->peer_closed()) - endpoints_.erase(endpoint->id()); -} - -void MultiplexRouter::RaiseErrorInNonTestingMode() { - AssertLockAcquired(); - if (!testing_mode_) - RaiseError(); -} - -MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint( - InterfaceId id, - bool* inserted) { - AssertLockAcquired(); - // Either |inserted| is nullptr or it points to a boolean initialized as - // false. - DCHECK(!inserted || !*inserted); - - InterfaceEndpoint* endpoint = FindEndpoint(id); - if (!endpoint) { - endpoint = new InterfaceEndpoint(this, id); - endpoints_[id] = endpoint; - if (inserted) - *inserted = true; - } - - return endpoint; -} - -MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindEndpoint( - InterfaceId id) { - AssertLockAcquired(); - auto iter = endpoints_.find(id); - return iter != endpoints_.end() ? iter->second.get() : nullptr; -} - -void MultiplexRouter::AssertLockAcquired() { -#if DCHECK_IS_ON() - if (lock_) - lock_->AssertAcquired(); -#endif -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h deleted file mode 100644 index cac138b..0000000 --- a/mojo/public/cpp/bindings/lib/multiplex_router.h +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ - -#include - -#include -#include -#include -#include - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/connector.h" -#include "mojo/public/cpp/bindings/filter_chain.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/message_header_validator.h" -#include "mojo/public/cpp/bindings/pipe_control_message_handler.h" -#include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h" -#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace mojo { - -namespace internal { - -// MultiplexRouter supports routing messages for multiple interfaces over a -// single message pipe. -// -// It is created on the thread where the master interface of the message pipe -// lives. Although it is ref-counted, it is guarateed to be destructed on the -// same thread. -// Some public methods are only allowed to be called on the creating thread; -// while the others are safe to call from any threads. Please see the method -// comments for more details. -// -// NOTE: CloseMessagePipe() or PassMessagePipe() MUST be called on |runner|'s -// thread before this object is destroyed. -class MOJO_CPP_BINDINGS_EXPORT MultiplexRouter - : NON_EXPORTED_BASE(public MessageReceiver), - public AssociatedGroupController, - NON_EXPORTED_BASE(public PipeControlMessageHandlerDelegate) { - public: - enum Config { - // There is only the master interface running on this router. Please note - // that because of interface versioning, the other side of the message pipe - // may use a newer master interface definition which passes associated - // interfaces. In that case, this router may still receive pipe control - // messages or messages targetting associated interfaces. - SINGLE_INTERFACE, - // Similar to the mode above, there is only the master interface running on - // this router. Besides, the master interface has sync methods. - SINGLE_INTERFACE_WITH_SYNC_METHODS, - // There may be associated interfaces running on this router. - MULTI_INTERFACE - }; - - // If |set_interface_id_namespace_bit| is true, the interface IDs generated by - // this router will have the highest bit set. - MultiplexRouter(ScopedMessagePipeHandle message_pipe, - Config config, - bool set_interface_id_namespace_bit, - scoped_refptr runner); - - // Sets the master interface name for this router. Only used when reporting - // message header or control message validation errors. - // |name| must be a string literal. - void SetMasterInterfaceName(const char* name); - - // --------------------------------------------------------------------------- - // The following public methods are safe to call from any threads. - - // AssociatedGroupController implementation: - InterfaceId AssociateInterface( - ScopedInterfaceEndpointHandle handle_to_send) override; - ScopedInterfaceEndpointHandle CreateLocalEndpointHandle( - InterfaceId id) override; - void CloseEndpointHandle( - InterfaceId id, - const base::Optional& reason) override; - InterfaceEndpointController* AttachEndpointClient( - const ScopedInterfaceEndpointHandle& handle, - InterfaceEndpointClient* endpoint_client, - scoped_refptr runner) override; - void DetachEndpointClient( - const ScopedInterfaceEndpointHandle& handle) override; - void RaiseError() override; - - // --------------------------------------------------------------------------- - // The following public methods are called on the creating thread. - - // Please note that this method shouldn't be called unless it results from an - // explicit request of the user of bindings (e.g., the user sets an - // InterfacePtr to null or closes a Binding). - void CloseMessagePipe(); - - // Extracts the underlying message pipe. - ScopedMessagePipeHandle PassMessagePipe() { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!HasAssociatedEndpoints()); - return connector_.PassMessagePipe(); - } - - // Blocks the current thread until the first incoming message, or |deadline|. - bool WaitForIncomingMessage(MojoDeadline deadline) { - DCHECK(thread_checker_.CalledOnValidThread()); - return connector_.WaitForIncomingMessage(deadline); - } - - // See Binding for details of pause/resume. - void PauseIncomingMethodCallProcessing(); - void ResumeIncomingMethodCallProcessing(); - - // Whether there are any associated interfaces running currently. - bool HasAssociatedEndpoints() const; - - // Sets this object to testing mode. - // In testing mode, the object doesn't disconnect the underlying message pipe - // when it receives unexpected or invalid messages. - void EnableTestingMode(); - - // Is the router bound to a message pipe handle? - bool is_valid() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return connector_.is_valid(); - } - - // TODO(yzshen): consider removing this getter. - MessagePipeHandle handle() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return connector_.handle(); - } - - bool SimulateReceivingMessageForTesting(Message* message) { - return filters_.Accept(message); - } - - private: - class InterfaceEndpoint; - class MessageWrapper; - struct Task; - - ~MultiplexRouter() override; - - // MessageReceiver implementation: - bool Accept(Message* message) override; - - // PipeControlMessageHandlerDelegate implementation: - bool OnPeerAssociatedEndpointClosed( - InterfaceId id, - const base::Optional& reason) override; - - void OnPipeConnectionError(); - - // Specifies whether we are allowed to directly call into - // InterfaceEndpointClient (given that we are already on the same thread as - // the client). - enum ClientCallBehavior { - // Don't call any InterfaceEndpointClient methods directly. - NO_DIRECT_CLIENT_CALLS, - // Only call InterfaceEndpointClient::HandleIncomingMessage directly to - // handle sync messages. - ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES, - // Allow to call any InterfaceEndpointClient methods directly. - ALLOW_DIRECT_CLIENT_CALLS - }; - - // Processes enqueued tasks (incoming messages and error notifications). - // |current_task_runner| is only used when |client_call_behavior| is - // ALLOW_DIRECT_CLIENT_CALLS to determine whether we are on the right task - // runner to make client calls for async messages or connection error - // notifications. - // - // Note: Because calling into InterfaceEndpointClient may lead to destruction - // of this object, if direct calls are allowed, the caller needs to hold on to - // a ref outside of |lock_| before calling this method. - void ProcessTasks(ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner); - - // Processes the first queued sync message for the endpoint corresponding to - // |id|; returns whether there are more sync messages for that endpoint in the - // queue. - // - // This method is only used by enpoints during sync watching. Therefore, not - // all sync messages are handled by it. - bool ProcessFirstSyncMessageForEndpoint(InterfaceId id); - - // Returns true to indicate that |task|/|message| has been processed. - bool ProcessNotifyErrorTask( - Task* task, - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner); - bool ProcessIncomingMessage( - Message* message, - ClientCallBehavior client_call_behavior, - base::SingleThreadTaskRunner* current_task_runner); - - void MaybePostToProcessTasks(base::SingleThreadTaskRunner* task_runner); - void LockAndCallProcessTasks(); - - // Updates the state of |endpoint|. If both the endpoint and its peer have - // been closed, removes it from |endpoints_|. - // NOTE: The method may invalidate |endpoint|. - enum EndpointStateUpdateType { ENDPOINT_CLOSED, PEER_ENDPOINT_CLOSED }; - void UpdateEndpointStateMayRemove(InterfaceEndpoint* endpoint, - EndpointStateUpdateType type); - - void RaiseErrorInNonTestingMode(); - - InterfaceEndpoint* FindOrInsertEndpoint(InterfaceId id, bool* inserted); - InterfaceEndpoint* FindEndpoint(InterfaceId id); - - void AssertLockAcquired(); - - // Whether to set the namespace bit when generating interface IDs. Please see - // comments of kInterfaceIdNamespaceMask. - const bool set_interface_id_namespace_bit_; - - scoped_refptr task_runner_; - - // Owned by |filters_| below. - MessageHeaderValidator* header_validator_; - - FilterChain filters_; - Connector connector_; - - base::ThreadChecker thread_checker_; - - // Protects the following members. - // Not set in Config::SINGLE_INTERFACE* mode. - mutable base::Optional lock_; - PipeControlMessageHandler control_message_handler_; - - // NOTE: It is unsafe to call into this object while holding |lock_|. - PipeControlMessageProxy control_message_proxy_; - - std::map> endpoints_; - uint32_t next_interface_id_value_; - - std::deque> tasks_; - // It refers to tasks in |tasks_| and doesn't own any of them. - std::map> sync_message_tasks_; - - bool posted_to_process_tasks_; - scoped_refptr posted_to_task_runner_; - - bool encountered_error_; - - bool paused_; - - bool testing_mode_; - - DISALLOW_COPY_AND_ASSIGN(MultiplexRouter); -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MULTIPLEX_ROUTER_H_ diff --git a/mojo/public/cpp/bindings/lib/native_enum_data.h b/mojo/public/cpp/bindings/lib/native_enum_data.h deleted file mode 100644 index dcafce2..0000000 --- a/mojo/public/cpp/bindings/lib/native_enum_data.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_DATA_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_DATA_H_ - -namespace mojo { -namespace internal { - -class ValidationContext; - -class NativeEnum_Data { - public: - static bool const kIsExtensible = true; - - static bool IsKnownValue(int32_t value) { return false; } - - static bool Validate(int32_t value, - ValidationContext* validation_context) { return true; } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_DATA_H_ diff --git a/mojo/public/cpp/bindings/lib/native_enum_serialization.h b/mojo/public/cpp/bindings/lib/native_enum_serialization.h deleted file mode 100644 index 4faf957..0000000 --- a/mojo/public/cpp/bindings/lib/native_enum_serialization.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_SERIALIZATION_H_ - -#include -#include - -#include - -#include "base/logging.h" -#include "base/pickle.h" -#include "ipc/ipc_param_traits.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/native_enum.h" - -namespace mojo { -namespace internal { - -template -struct NativeEnumSerializerImpl { - using UserType = typename std::remove_const::type; - using Traits = IPC::ParamTraits; - - // IPC_ENUM_TRAITS* macros serialize enum as int, make sure that fits into - // mojo native-only enum. - static_assert(sizeof(NativeEnum) >= sizeof(int), - "Cannot store the serialization result in NativeEnum."); - - static void Serialize(UserType input, int32_t* output) { - base::Pickle pickle; - Traits::Write(&pickle, input); - - CHECK_GE(sizeof(int32_t), pickle.payload_size()); - *output = 0; - memcpy(reinterpret_cast(output), pickle.payload(), - pickle.payload_size()); - } - - struct PickleData { - uint32_t payload_size; - int32_t value; - }; - static_assert(sizeof(PickleData) == 8, "PickleData size mismatch."); - - static bool Deserialize(int32_t input, UserType* output) { - PickleData data = {sizeof(int32_t), input}; - base::Pickle pickle_view(reinterpret_cast(&data), - sizeof(PickleData)); - base::PickleIterator iter(pickle_view); - return Traits::Read(&pickle_view, &iter, output); - } -}; - -struct UnmappedNativeEnumSerializerImpl { - static void Serialize(NativeEnum input, int32_t* output) { - *output = static_cast(input); - } - static bool Deserialize(int32_t input, NativeEnum* output) { - *output = static_cast(input); - return true; - } -}; - -template <> -struct NativeEnumSerializerImpl - : public UnmappedNativeEnumSerializerImpl {}; - -template <> -struct NativeEnumSerializerImpl - : public UnmappedNativeEnumSerializerImpl {}; - -template -struct Serializer - : public NativeEnumSerializerImpl {}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_ENUM_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/native_struct.cc b/mojo/public/cpp/bindings/lib/native_struct.cc deleted file mode 100644 index 7b1a1a6..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/native_struct.h" - -#include "mojo/public/cpp/bindings/lib/hash_util.h" - -namespace mojo { - -// static -NativeStructPtr NativeStruct::New() { - return NativeStructPtr(base::in_place); -} - -NativeStruct::NativeStruct() {} - -NativeStruct::~NativeStruct() {} - -NativeStructPtr NativeStruct::Clone() const { - NativeStructPtr rv(New()); - rv->data = data; - return rv; -} - -bool NativeStruct::Equals(const NativeStruct& other) const { - return data == other.data; -} - -size_t NativeStruct::Hash(size_t seed) const { - return internal::Hash(seed, data); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/native_struct_data.cc b/mojo/public/cpp/bindings/lib/native_struct_data.cc deleted file mode 100644 index 0e5d245..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct_data.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" - -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" - -namespace mojo { -namespace internal { - -// static -bool NativeStruct_Data::Validate(const void* data, - ValidationContext* validation_context) { - const ContainerValidateParams data_validate_params(0, false, nullptr); - return Array_Data::Validate(data, validation_context, - &data_validate_params); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/native_struct_data.h b/mojo/public/cpp/bindings/lib/native_struct_data.h deleted file mode 100644 index 1c7cd81..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct_data.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ - -#include - -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { -namespace internal { - -class ValidationContext; - -class MOJO_CPP_BINDINGS_EXPORT NativeStruct_Data { - public: - static bool Validate(const void* data, ValidationContext* validation_context); - - // Unlike normal structs, the memory layout is exactly the same as an array - // of uint8_t. - Array_Data data; - - private: - NativeStruct_Data() = delete; - ~NativeStruct_Data() = delete; -}; - -static_assert(sizeof(Array_Data) == sizeof(NativeStruct_Data), - "Mismatched NativeStruct_Data and Array_Data size"); - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_DATA_H_ diff --git a/mojo/public/cpp/bindings/lib/native_struct_serialization.cc b/mojo/public/cpp/bindings/lib/native_struct_serialization.cc deleted file mode 100644 index fa0dbf3..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct_serialization.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" - -#include "mojo/public/cpp/bindings/lib/serialization.h" - -namespace mojo { -namespace internal { - -// static -size_t UnmappedNativeStructSerializerImpl::PrepareToSerialize( - const NativeStructPtr& input, - SerializationContext* context) { - if (!input) - return 0; - return internal::PrepareToSerialize>(input->data, - context); -} - -// static -void UnmappedNativeStructSerializerImpl::Serialize( - const NativeStructPtr& input, - Buffer* buffer, - NativeStruct_Data** output, - SerializationContext* context) { - if (!input) { - *output = nullptr; - return; - } - - Array_Data* data = nullptr; - const ContainerValidateParams params(0, false, nullptr); - internal::Serialize>(input->data, buffer, &data, - ¶ms, context); - *output = reinterpret_cast(data); -} - -// static -bool UnmappedNativeStructSerializerImpl::Deserialize( - NativeStruct_Data* input, - NativeStructPtr* output, - SerializationContext* context) { - Array_Data* data = reinterpret_cast*>(input); - - NativeStructPtr result(NativeStruct::New()); - if (!internal::Deserialize>(data, &result->data, - context)) { - output = nullptr; - return false; - } - if (!result->data) - *output = nullptr; - else - result.Swap(output); - return true; -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/native_struct_serialization.h b/mojo/public/cpp/bindings/lib/native_struct_serialization.h deleted file mode 100644 index 457435b..0000000 --- a/mojo/public/cpp/bindings/lib/native_struct_serialization.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ - -#include -#include - -#include - -#include "base/logging.h" -#include "base/pickle.h" -#include "ipc/ipc_param_traits.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/native_struct_data.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/native_struct.h" -#include "mojo/public/cpp/bindings/native_struct_data_view.h" - -namespace mojo { -namespace internal { - -template -struct NativeStructSerializerImpl { - using UserType = typename std::remove_const::type; - using Traits = IPC::ParamTraits; - - static size_t PrepareToSerialize(MaybeConstUserType& value, - SerializationContext* context) { - base::PickleSizer sizer; - Traits::GetSize(&sizer, value); - return Align(sizer.payload_size() + sizeof(ArrayHeader)); - } - - static void Serialize(MaybeConstUserType& value, - Buffer* buffer, - NativeStruct_Data** out, - SerializationContext* context) { - base::Pickle pickle; - Traits::Write(&pickle, value); - -#if DCHECK_IS_ON() - base::PickleSizer sizer; - Traits::GetSize(&sizer, value); - DCHECK_EQ(sizer.payload_size(), pickle.payload_size()); -#endif - - size_t total_size = pickle.payload_size() + sizeof(ArrayHeader); - DCHECK_LT(total_size, std::numeric_limits::max()); - - // Allocate a uint8 array, initialize its header, and copy the Pickle in. - ArrayHeader* header = - reinterpret_cast(buffer->Allocate(total_size)); - header->num_bytes = static_cast(total_size); - header->num_elements = static_cast(pickle.payload_size()); - memcpy(reinterpret_cast(header) + sizeof(ArrayHeader), - pickle.payload(), pickle.payload_size()); - - *out = reinterpret_cast(header); - } - - static bool Deserialize(NativeStruct_Data* data, - UserType* out, - SerializationContext* context) { - if (!data) - return false; - - // Construct a temporary base::Pickle view over the array data. Note that - // the Array_Data is laid out like this: - // - // [num_bytes (4 bytes)] [num_elements (4 bytes)] [elements...] - // - // and base::Pickle expects to view data like this: - // - // [payload_size (4 bytes)] [header bytes ...] [payload...] - // - // Because ArrayHeader's num_bytes includes the length of the header and - // Pickle's payload_size does not, we need to adjust the stored value - // momentarily so Pickle can view the data. - ArrayHeader* header = reinterpret_cast(data); - DCHECK_GE(header->num_bytes, sizeof(ArrayHeader)); - header->num_bytes -= sizeof(ArrayHeader); - - { - // Construct a view over the full Array_Data, including our hacked up - // header. Pickle will infer from this that the header is 8 bytes long, - // and the payload will contain all of the pickled bytes. - base::Pickle pickle_view(reinterpret_cast(header), - header->num_bytes + sizeof(ArrayHeader)); - base::PickleIterator iter(pickle_view); - if (!Traits::Read(&pickle_view, &iter, out)) - return false; - } - - // Return the header to its original state. - header->num_bytes += sizeof(ArrayHeader); - - return true; - } -}; - -struct MOJO_CPP_BINDINGS_EXPORT UnmappedNativeStructSerializerImpl { - static size_t PrepareToSerialize(const NativeStructPtr& input, - SerializationContext* context); - static void Serialize(const NativeStructPtr& input, - Buffer* buffer, - NativeStruct_Data** output, - SerializationContext* context); - static bool Deserialize(NativeStruct_Data* input, - NativeStructPtr* output, - SerializationContext* context); -}; - -template <> -struct NativeStructSerializerImpl - : public UnmappedNativeStructSerializerImpl {}; - -template <> -struct NativeStructSerializerImpl - : public UnmappedNativeStructSerializerImpl {}; - -template -struct Serializer - : public NativeStructSerializerImpl {}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_NATIVE_STRUCT_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc deleted file mode 100644 index d451c05..0000000 --- a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/pipe_control_message_handler.h" - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/interface_id.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" -#include "mojo/public/cpp/bindings/lib/validation_context.h" -#include "mojo/public/cpp/bindings/lib/validation_util.h" -#include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h" -#include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h" - -namespace mojo { - -PipeControlMessageHandler::PipeControlMessageHandler( - PipeControlMessageHandlerDelegate* delegate) - : delegate_(delegate) {} - -PipeControlMessageHandler::~PipeControlMessageHandler() {} - -void PipeControlMessageHandler::SetDescription(const std::string& description) { - description_ = description; -} - -// static -bool PipeControlMessageHandler::IsPipeControlMessage(const Message* message) { - return !IsValidInterfaceId(message->interface_id()); -} - -bool PipeControlMessageHandler::Accept(Message* message) { - if (!Validate(message)) - return false; - - if (message->name() == pipe_control::kRunOrClosePipeMessageId) - return RunOrClosePipe(message); - - NOTREACHED(); - return false; -} - -bool PipeControlMessageHandler::Validate(Message* message) { - internal::ValidationContext validation_context(message->payload(), - message->payload_num_bytes(), - 0, 0, message, description_); - - if (message->name() == pipe_control::kRunOrClosePipeMessageId) { - if (!internal::ValidateMessageIsRequestWithoutResponse( - message, &validation_context)) { - return false; - } - return internal::ValidateMessagePayload< - pipe_control::internal::RunOrClosePipeMessageParams_Data>( - message, &validation_context); - } - - return false; -} - -bool PipeControlMessageHandler::RunOrClosePipe(Message* message) { - internal::SerializationContext context; - pipe_control::internal::RunOrClosePipeMessageParams_Data* params = - reinterpret_cast< - pipe_control::internal::RunOrClosePipeMessageParams_Data*>( - message->mutable_payload()); - pipe_control::RunOrClosePipeMessageParamsPtr params_ptr; - internal::Deserialize( - params, ¶ms_ptr, &context); - - if (params_ptr->input->is_peer_associated_endpoint_closed_event()) { - const auto& event = - params_ptr->input->get_peer_associated_endpoint_closed_event(); - - base::Optional reason; - if (event->disconnect_reason) { - reason.emplace(event->disconnect_reason->custom_reason, - event->disconnect_reason->description); - } - return delegate_->OnPeerAssociatedEndpointClosed(event->id, reason); - } - - DVLOG(1) << "Unsupported command in a RunOrClosePipe message pipe control " - << "message. Closing the pipe."; - return false; -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc deleted file mode 100644 index 1029c2c..0000000 --- a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" - -#include -#include - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/message_builder.h" -#include "mojo/public/cpp/bindings/lib/serialization.h" -#include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h" - -namespace mojo { -namespace { - -Message ConstructRunOrClosePipeMessage( - pipe_control::RunOrClosePipeInputPtr input_ptr) { - internal::SerializationContext context; - - auto params_ptr = pipe_control::RunOrClosePipeMessageParams::New(); - params_ptr->input = std::move(input_ptr); - - size_t size = internal::PrepareToSerialize< - pipe_control::RunOrClosePipeMessageParamsDataView>(params_ptr, &context); - internal::MessageBuilder builder(pipe_control::kRunOrClosePipeMessageId, 0, - size, 0); - - pipe_control::internal::RunOrClosePipeMessageParams_Data* params = nullptr; - internal::Serialize( - params_ptr, builder.buffer(), ¶ms, &context); - builder.message()->set_interface_id(kInvalidInterfaceId); - return std::move(*builder.message()); -} - -} // namespace - -PipeControlMessageProxy::PipeControlMessageProxy(MessageReceiver* receiver) - : receiver_(receiver) {} - -void PipeControlMessageProxy::NotifyPeerEndpointClosed( - InterfaceId id, - const base::Optional& reason) { - Message message(ConstructPeerEndpointClosedMessage(id, reason)); - ignore_result(receiver_->Accept(&message)); -} - -// static -Message PipeControlMessageProxy::ConstructPeerEndpointClosedMessage( - InterfaceId id, - const base::Optional& reason) { - auto event = pipe_control::PeerAssociatedEndpointClosedEvent::New(); - event->id = id; - if (reason) { - event->disconnect_reason = pipe_control::DisconnectReason::New(); - event->disconnect_reason->custom_reason = reason->custom_reason; - event->disconnect_reason->description = reason->description; - } - - auto input = pipe_control::RunOrClosePipeInput::New(); - input->set_peer_associated_endpoint_closed_event(std::move(event)); - - return ConstructRunOrClosePipeMessage(std::move(input)); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc deleted file mode 100644 index c134507..0000000 --- a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/synchronization/lock.h" -#include "mojo/public/cpp/bindings/associated_group_controller.h" -#include "mojo/public/cpp/bindings/lib/may_auto_lock.h" - -namespace mojo { - -// ScopedInterfaceEndpointHandle::State ---------------------------------------- - -// State could be called from multiple threads. -class ScopedInterfaceEndpointHandle::State - : public base::RefCountedThreadSafe { - public: - State() = default; - - State(InterfaceId id, - scoped_refptr group_controller) - : id_(id), group_controller_(group_controller) {} - - void InitPendingState(scoped_refptr peer) { - DCHECK(!lock_); - DCHECK(!pending_association_); - - lock_.emplace(); - pending_association_ = true; - peer_state_ = std::move(peer); - } - - void Close(const base::Optional& reason) { - scoped_refptr cached_group_controller; - InterfaceId cached_id = kInvalidInterfaceId; - scoped_refptr cached_peer_state; - - { - internal::MayAutoLock locker(&lock_); - - if (!association_event_handler_.is_null()) { - association_event_handler_.Reset(); - runner_ = nullptr; - } - - if (!pending_association_) { - if (IsValidInterfaceId(id_)) { - // Intentionally keep |group_controller_| unchanged. - // That is because the callback created by - // CreateGroupControllerGetter() could still be used after this point, - // potentially from another thread. We would like it to continue - // returning the same group controller. - // - // Imagine there is a ThreadSafeForwarder A: - // (1) On the IO thread, A's underlying associated interface pointer - // is closed. - // (2) On the proxy thread, the user makes a call on A to pass an - // associated request B_asso_req. The callback returned by - // CreateGroupControllerGetter() is used to associate B_asso_req. - // (3) On the proxy thread, the user immediately binds B_asso_ptr_info - // to B_asso_ptr and makes calls on it. - // - // If we reset |group_controller_| in step (1), step (2) won't be able - // to associate B_asso_req. Therefore, in step (3) B_asso_ptr won't be - // able to serialize associated endpoints or send message because it - // is still in "pending_association" state and doesn't have a group - // controller. - // - // We could "address" this issue by ignoring messages if there isn't a - // group controller. But the side effect is that we cannot detect - // programming errors of "using associated interface pointer before - // sending associated request". - - cached_group_controller = group_controller_; - cached_id = id_; - id_ = kInvalidInterfaceId; - } - } else { - pending_association_ = false; - cached_peer_state = std::move(peer_state_); - } - } - - if (cached_group_controller) { - cached_group_controller->CloseEndpointHandle(cached_id, reason); - } else if (cached_peer_state) { - cached_peer_state->OnPeerClosedBeforeAssociation(reason); - } - } - - void SetAssociationEventHandler(AssociationEventCallback handler) { - internal::MayAutoLock locker(&lock_); - - if (!pending_association_ && !IsValidInterfaceId(id_)) - return; - - association_event_handler_ = std::move(handler); - if (association_event_handler_.is_null()) { - runner_ = nullptr; - return; - } - - runner_ = base::ThreadTaskRunnerHandle::Get(); - if (!pending_association_) { - runner_->PostTask( - FROM_HERE, - base::Bind( - &ScopedInterfaceEndpointHandle::State::RunAssociationEventHandler, - this, runner_, ASSOCIATED)); - } else if (!peer_state_) { - runner_->PostTask( - FROM_HERE, - base::Bind( - &ScopedInterfaceEndpointHandle::State::RunAssociationEventHandler, - this, runner_, PEER_CLOSED_BEFORE_ASSOCIATION)); - } - } - - bool NotifyAssociation( - InterfaceId id, - scoped_refptr peer_group_controller) { - scoped_refptr cached_peer_state; - { - internal::MayAutoLock locker(&lock_); - - DCHECK(pending_association_); - pending_association_ = false; - cached_peer_state = std::move(peer_state_); - } - - if (cached_peer_state) { - cached_peer_state->OnAssociated(id, std::move(peer_group_controller)); - return true; - } - return false; - } - - bool is_valid() const { - internal::MayAutoLock locker(&lock_); - return pending_association_ || IsValidInterfaceId(id_); - } - - bool pending_association() const { - internal::MayAutoLock locker(&lock_); - return pending_association_; - } - - InterfaceId id() const { - internal::MayAutoLock locker(&lock_); - return id_; - } - - AssociatedGroupController* group_controller() const { - internal::MayAutoLock locker(&lock_); - return group_controller_.get(); - } - - const base::Optional& disconnect_reason() const { - internal::MayAutoLock locker(&lock_); - return disconnect_reason_; - } - - private: - friend class base::RefCountedThreadSafe; - - ~State() { - DCHECK(!pending_association_); - DCHECK(!IsValidInterfaceId(id_)); - } - - // Called by the peer, maybe from a different thread. - void OnAssociated(InterfaceId id, - scoped_refptr group_controller) { - AssociationEventCallback handler; - { - internal::MayAutoLock locker(&lock_); - - // There may be race between Close() of endpoint A and - // NotifyPeerAssociation() of endpoint A_peer on different threads. - // Therefore, it is possible that endpoint A has been closed but it - // still gets OnAssociated() call from its peer. - if (!pending_association_) - return; - - pending_association_ = false; - peer_state_ = nullptr; - id_ = id; - group_controller_ = std::move(group_controller); - - if (!association_event_handler_.is_null()) { - if (runner_->BelongsToCurrentThread()) { - handler = std::move(association_event_handler_); - runner_ = nullptr; - } else { - runner_->PostTask(FROM_HERE, - base::Bind(&ScopedInterfaceEndpointHandle::State:: - RunAssociationEventHandler, - this, runner_, ASSOCIATED)); - } - } - } - - if (!handler.is_null()) - std::move(handler).Run(ASSOCIATED); - } - - // Called by the peer, maybe from a different thread. - void OnPeerClosedBeforeAssociation( - const base::Optional& reason) { - AssociationEventCallback handler; - { - internal::MayAutoLock locker(&lock_); - - // There may be race between Close()/NotifyPeerAssociation() of endpoint - // A and Close() of endpoint A_peer on different threads. - // Therefore, it is possible that endpoint A is not in pending association - // state but still gets OnPeerClosedBeforeAssociation() call from its - // peer. - if (!pending_association_) - return; - - disconnect_reason_ = reason; - // NOTE: This handle itself is still pending. - peer_state_ = nullptr; - - if (!association_event_handler_.is_null()) { - if (runner_->BelongsToCurrentThread()) { - handler = std::move(association_event_handler_); - runner_ = nullptr; - } else { - runner_->PostTask( - FROM_HERE, - base::Bind(&ScopedInterfaceEndpointHandle::State:: - RunAssociationEventHandler, - this, runner_, PEER_CLOSED_BEFORE_ASSOCIATION)); - } - } - } - - if (!handler.is_null()) - std::move(handler).Run(PEER_CLOSED_BEFORE_ASSOCIATION); - } - - void RunAssociationEventHandler( - scoped_refptr posted_to_runner, - AssociationEvent event) { - AssociationEventCallback handler; - - { - internal::MayAutoLock locker(&lock_); - if (posted_to_runner == runner_) { - runner_ = nullptr; - handler = std::move(association_event_handler_); - } - } - - if (!handler.is_null()) - std::move(handler).Run(event); - } - - // Protects the following members if the handle is initially set to pending - // association. - mutable base::Optional lock_; - - bool pending_association_ = false; - base::Optional disconnect_reason_; - - scoped_refptr peer_state_; - - AssociationEventCallback association_event_handler_; - scoped_refptr runner_; - - InterfaceId id_ = kInvalidInterfaceId; - scoped_refptr group_controller_; - - DISALLOW_COPY_AND_ASSIGN(State); -}; - -// ScopedInterfaceEndpointHandle ----------------------------------------------- - -// static -void ScopedInterfaceEndpointHandle::CreatePairPendingAssociation( - ScopedInterfaceEndpointHandle* handle0, - ScopedInterfaceEndpointHandle* handle1) { - ScopedInterfaceEndpointHandle result0; - ScopedInterfaceEndpointHandle result1; - result0.state_->InitPendingState(result1.state_); - result1.state_->InitPendingState(result0.state_); - - *handle0 = std::move(result0); - *handle1 = std::move(result1); -} - -ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle() - : state_(new State) {} - -ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle( - ScopedInterfaceEndpointHandle&& other) - : state_(new State) { - state_.swap(other.state_); -} - -ScopedInterfaceEndpointHandle::~ScopedInterfaceEndpointHandle() { - state_->Close(base::nullopt); -} - -ScopedInterfaceEndpointHandle& ScopedInterfaceEndpointHandle::operator=( - ScopedInterfaceEndpointHandle&& other) { - reset(); - state_.swap(other.state_); - return *this; -} - -bool ScopedInterfaceEndpointHandle::is_valid() const { - return state_->is_valid(); -} - -bool ScopedInterfaceEndpointHandle::pending_association() const { - return state_->pending_association(); -} - -InterfaceId ScopedInterfaceEndpointHandle::id() const { - return state_->id(); -} - -AssociatedGroupController* ScopedInterfaceEndpointHandle::group_controller() - const { - return state_->group_controller(); -} - -const base::Optional& -ScopedInterfaceEndpointHandle::disconnect_reason() const { - return state_->disconnect_reason(); -} - -void ScopedInterfaceEndpointHandle::SetAssociationEventHandler( - AssociationEventCallback handler) { - state_->SetAssociationEventHandler(std::move(handler)); -} - -void ScopedInterfaceEndpointHandle::reset() { - ResetInternal(base::nullopt); -} - -void ScopedInterfaceEndpointHandle::ResetWithReason( - uint32_t custom_reason, - const std::string& description) { - ResetInternal(DisconnectReason(custom_reason, description)); -} - -ScopedInterfaceEndpointHandle::ScopedInterfaceEndpointHandle( - InterfaceId id, - scoped_refptr group_controller) - : state_(new State(id, std::move(group_controller))) { - DCHECK(!IsValidInterfaceId(state_->id()) || state_->group_controller()); -} - -bool ScopedInterfaceEndpointHandle::NotifyAssociation( - InterfaceId id, - scoped_refptr peer_group_controller) { - return state_->NotifyAssociation(id, peer_group_controller); -} - -void ScopedInterfaceEndpointHandle::ResetInternal( - const base::Optional& reason) { - scoped_refptr new_state(new State); - state_->Close(reason); - state_.swap(new_state); -} - -base::Callback -ScopedInterfaceEndpointHandle::CreateGroupControllerGetter() const { - // We allow this callback to be run on any thread. If this handle is created - // in non-pending state, we don't have a lock but it should still be safe - // because the group controller never changes. - return base::Bind(&State::group_controller, state_); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/serialization.h b/mojo/public/cpp/bindings/lib/serialization.h deleted file mode 100644 index 2a7d288..0000000 --- a/mojo/public/cpp/bindings/lib/serialization.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ - -#include - -#include "mojo/public/cpp/bindings/array_traits_carray.h" -#include "mojo/public/cpp/bindings/array_traits_stl.h" -#include "mojo/public/cpp/bindings/lib/array_serialization.h" -#include "mojo/public/cpp/bindings/lib/buffer.h" -#include "mojo/public/cpp/bindings/lib/handle_interface_serialization.h" -#include "mojo/public/cpp/bindings/lib/map_serialization.h" -#include "mojo/public/cpp/bindings/lib/native_enum_serialization.h" -#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h" -#include "mojo/public/cpp/bindings/lib/string_serialization.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/map_traits_stl.h" -#include "mojo/public/cpp/bindings/string_traits_stl.h" -#include "mojo/public/cpp/bindings/string_traits_string16.h" -#include "mojo/public/cpp/bindings/string_traits_string_piece.h" - -namespace mojo { -namespace internal { - -template -DataArrayType StructSerializeImpl(UserType* input) { - static_assert(BelongsTo::value, - "Unexpected type."); - - SerializationContext context; - size_t size = PrepareToSerialize(*input, &context); - DCHECK_EQ(size, Align(size)); - - DataArrayType result(size); - if (size == 0) - return result; - - void* result_buffer = &result.front(); - // The serialization logic requires that the buffer is 8-byte aligned. If the - // result buffer is not properly aligned, we have to do an extra copy. In - // practice, this should never happen for std::vector. - bool need_copy = !IsAligned(result_buffer); - - if (need_copy) { - // calloc sets the memory to all zero. - result_buffer = calloc(size, 1); - DCHECK(IsAligned(result_buffer)); - } - - Buffer buffer; - buffer.Initialize(result_buffer, size); - typename MojomTypeTraits::Data* data = nullptr; - Serialize(*input, &buffer, &data, &context); - - if (need_copy) { - memcpy(&result.front(), result_buffer, size); - free(result_buffer); - } - - return result; -} - -template -bool StructDeserializeImpl(const DataArrayType& input, - UserType* output, - bool (*validate_func)(const void*, - ValidationContext*)) { - static_assert(BelongsTo::value, - "Unexpected type."); - using DataType = typename MojomTypeTraits::Data; - - // TODO(sammc): Use DataArrayType::empty() once WTF::Vector::empty() exists. - void* input_buffer = - input.size() == 0 - ? nullptr - : const_cast(reinterpret_cast(&input.front())); - - // Please see comments in StructSerializeImpl. - bool need_copy = !IsAligned(input_buffer); - - if (need_copy) { - input_buffer = malloc(input.size()); - DCHECK(IsAligned(input_buffer)); - memcpy(input_buffer, &input.front(), input.size()); - } - - ValidationContext validation_context(input_buffer, input.size(), 0, 0); - bool result = false; - if (validate_func(input_buffer, &validation_context)) { - auto data = reinterpret_cast(input_buffer); - SerializationContext context; - result = Deserialize(data, output, &context); - } - - if (need_copy) - free(input_buffer); - - return result; -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/serialization_context.cc b/mojo/public/cpp/bindings/lib/serialization_context.cc deleted file mode 100644 index e2fd5c6..0000000 --- a/mojo/public/cpp/bindings/lib/serialization_context.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -#include - -#include "base/logging.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace internal { - -SerializedHandleVector::SerializedHandleVector() {} - -SerializedHandleVector::~SerializedHandleVector() { - for (auto handle : handles_) { - if (handle.is_valid()) { - MojoResult rv = MojoClose(handle.value()); - DCHECK_EQ(rv, MOJO_RESULT_OK); - } - } -} - -Handle_Data SerializedHandleVector::AddHandle(mojo::Handle handle) { - Handle_Data data; - if (!handle.is_valid()) { - data.value = kEncodedInvalidHandleValue; - } else { - DCHECK_LT(handles_.size(), std::numeric_limits::max()); - data.value = static_cast(handles_.size()); - handles_.push_back(handle); - } - return data; -} - -mojo::Handle SerializedHandleVector::TakeHandle( - const Handle_Data& encoded_handle) { - if (!encoded_handle.is_valid()) - return mojo::Handle(); - DCHECK_LT(encoded_handle.value, handles_.size()); - return FetchAndReset(&handles_[encoded_handle.value]); -} - -void SerializedHandleVector::Swap(std::vector* other) { - handles_.swap(*other); -} - -SerializationContext::SerializationContext() {} - -SerializationContext::~SerializationContext() { - DCHECK(!custom_contexts || custom_contexts->empty()); -} - -} // namespace internal -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/serialization_context.h b/mojo/public/cpp/bindings/lib/serialization_context.h deleted file mode 100644 index a34fe3d..0000000 --- a/mojo/public/cpp/bindings/lib/serialization_context.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ - -#include - -#include -#include -#include - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/bindings_export.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" -#include "mojo/public/cpp/system/handle.h" - -namespace mojo { -namespace internal { - -// A container for handles during serialization/deserialization. -class MOJO_CPP_BINDINGS_EXPORT SerializedHandleVector { - public: - SerializedHandleVector(); - ~SerializedHandleVector(); - - size_t size() const { return handles_.size(); } - - // Adds a handle to the handle list and returns its index for encoding. - Handle_Data AddHandle(mojo::Handle handle); - - // Takes a handle from the list of serialized handle data. - mojo::Handle TakeHandle(const Handle_Data& encoded_handle); - - // Takes a handle from the list of serialized handle data and returns it in - // |*out_handle| as a specific scoped handle type. - template - ScopedHandleBase TakeHandleAs(const Handle_Data& encoded_handle) { - return MakeScopedHandle(T(TakeHandle(encoded_handle).value())); - } - - // Swaps all owned handles out with another Handle vector. - void Swap(std::vector* other); - - private: - // Handles are owned by this object. - std::vector handles_; - - DISALLOW_COPY_AND_ASSIGN(SerializedHandleVector); -}; - -// Context information for serialization/deserialization routines. -struct MOJO_CPP_BINDINGS_EXPORT SerializationContext { - SerializationContext(); - - ~SerializationContext(); - - // Opaque context pointers returned by StringTraits::SetUpContext(). - std::unique_ptr> custom_contexts; - - // Stashes handles encoded in a message by index. - SerializedHandleVector handles; - - // The number of ScopedInterfaceEndpointHandles that need to be serialized. - // It is calculated by PrepareToSerialize(). - uint32_t associated_endpoint_count = 0; - - // Stashes ScopedInterfaceEndpointHandles encoded in a message by index. - std::vector associated_endpoint_handles; -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_SERIALIZATION_CONTEXT_H_ diff --git a/mojo/public/cpp/bindings/lib/serialization_forward.h b/mojo/public/cpp/bindings/lib/serialization_forward.h deleted file mode 100644 index 55c9982..0000000 --- a/mojo/public/cpp/bindings/lib/serialization_forward.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ - -#include "base/optional.h" -#include "mojo/public/cpp/bindings/array_traits.h" -#include "mojo/public/cpp/bindings/enum_traits.h" -#include "mojo/public/cpp/bindings/lib/template_util.h" -#include "mojo/public/cpp/bindings/map_traits.h" -#include "mojo/public/cpp/bindings/string_traits.h" -#include "mojo/public/cpp/bindings/struct_traits.h" -#include "mojo/public/cpp/bindings/union_traits.h" - -// This file is included by serialization implementation files to avoid circular -// includes. -// Users of the serialization funtions should include serialization.h (and also -// wtf_serialization.h if necessary). - -namespace mojo { -namespace internal { - -template -struct Serializer; - -template -struct IsOptionalWrapper { - static const bool value = IsSpecializationOf< - base::Optional, - typename std::remove_const< - typename std::remove_reference::type>::type>::value; -}; - -// PrepareToSerialize() must be matched by a Serialize() for the same input -// later. Moreover, within the same SerializationContext if PrepareToSerialize() -// is called for |input_1|, ..., |input_n|, Serialize() must be called for -// those objects in the exact same order. -template ::value>::type* = nullptr> -size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { - return Serializer::type>:: - PrepareToSerialize(std::forward(input), - std::forward(args)...); -} - -template ::value>::type* = nullptr> -void Serialize(InputUserType&& input, Args&&... args) { - Serializer::type>:: - Serialize(std::forward(input), - std::forward(args)...); -} - -template ::value>::type* = nullptr> -bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { - return Serializer::Deserialize( - std::forward(input), output, std::forward(args)...); -} - -// Specialization that unwraps base::Optional<>. -template ::value>::type* = nullptr> -size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { - if (!input) - return 0; - return PrepareToSerialize(*input, std::forward(args)...); -} - -template ::value>::type* = nullptr> -void Serialize(InputUserType&& input, - Buffer* buffer, - DataType** output, - Args&&... args) { - if (!input) { - *output = nullptr; - return; - } - Serialize(*input, buffer, output, std::forward(args)...); -} - -template ::value>::type* = nullptr> -bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { - if (!input) { - *output = base::nullopt; - return true; - } - if (!*output) - output->emplace(); - return Deserialize(std::forward(input), &output->value(), - std::forward(args)...); -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ diff --git a/mojo/public/cpp/bindings/lib/serialization_util.h b/mojo/public/cpp/bindings/lib/serialization_util.h deleted file mode 100644 index 4820a01..0000000 --- a/mojo/public/cpp/bindings/lib/serialization_util.h +++ /dev/null @@ -1,213 +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_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ - -#include -#include - -#include - -#include "base/logging.h" -#include "base/macros.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_context.h" - -namespace mojo { -namespace internal { - -template -struct HasIsNullMethod { - template - static char Test(decltype(U::IsNull)*); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template < - typename Traits, - typename UserType, - typename std::enable_if::value>::type* = nullptr> -bool CallIsNullIfExists(const UserType& input) { - return Traits::IsNull(input); -} - -template < - typename Traits, - typename UserType, - typename std::enable_if::value>::type* = nullptr> -bool CallIsNullIfExists(const UserType& input) { - return false; -} -template -struct HasSetToNullMethod { - template - static char Test(decltype(U::SetToNull)*); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template < - typename Traits, - typename UserType, - typename std::enable_if::value>::type* = nullptr> -bool CallSetToNullIfExists(UserType* output) { - Traits::SetToNull(output); - return true; -} - -template ::value>::type* = - nullptr> -bool CallSetToNullIfExists(UserType* output) { - LOG(ERROR) << "A null value is received. But the Struct/Array/StringTraits " - << "class doesn't define a SetToNull() function and therefore is " - << "unable to deserialize the value."; - return false; -} - -template -struct HasSetUpContextMethod { - template - static char Test(decltype(U::SetUpContext)*); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template ::value> -struct CustomContextHelper; - -template -struct CustomContextHelper { - template - static void* SetUp(MaybeConstUserType& input, SerializationContext* context) { - void* custom_context = Traits::SetUpContext(input); - if (!context->custom_contexts) - context->custom_contexts.reset(new std::queue()); - context->custom_contexts->push(custom_context); - return custom_context; - } - - static void* GetNext(SerializationContext* context) { - void* custom_context = context->custom_contexts->front(); - context->custom_contexts->pop(); - return custom_context; - } - - template - static void TearDown(MaybeConstUserType& input, void* custom_context) { - Traits::TearDownContext(input, custom_context); - } -}; - -template -struct CustomContextHelper { - template - static void* SetUp(MaybeConstUserType& input, SerializationContext* context) { - return nullptr; - } - - static void* GetNext(SerializationContext* context) { return nullptr; } - - template - static void TearDown(MaybeConstUserType& input, void* custom_context) { - DCHECK(!custom_context); - } -}; - -template -ReturnType CallWithContext(ReturnType (*f)(ParamType, void*), - InputUserType&& input, - void* context) { - return f(std::forward(input), context); -} - -template -ReturnType CallWithContext(ReturnType (*f)(ParamType), - InputUserType&& input, - void* context) { - return f(std::forward(input)); -} - -template -struct HasGetBeginMethod { - template - static char Test(decltype(U::GetBegin(std::declval()))*); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template < - typename Traits, - typename MaybeConstUserType, - typename std::enable_if< - HasGetBeginMethod::value>::type* = nullptr> -decltype(Traits::GetBegin(std::declval())) -CallGetBeginIfExists(MaybeConstUserType& input) { - return Traits::GetBegin(input); -} - -template < - typename Traits, - typename MaybeConstUserType, - typename std::enable_if< - !HasGetBeginMethod::value>::type* = nullptr> -size_t CallGetBeginIfExists(MaybeConstUserType& input) { - return 0; -} - -template -struct HasGetDataMethod { - template - static char Test(decltype(U::GetData(std::declval()))*); - template - static int Test(...); - static const bool value = sizeof(Test(0)) == sizeof(char); - - private: - EnsureTypeIsComplete check_t_; -}; - -template < - typename Traits, - typename MaybeConstUserType, - typename std::enable_if< - HasGetDataMethod::value>::type* = nullptr> -decltype(Traits::GetData(std::declval())) -CallGetDataIfExists(MaybeConstUserType& input) { - return Traits::GetData(input); -} - -template < - typename Traits, - typename MaybeConstUserType, - typename std::enable_if< - !HasGetDataMethod::value>::type* = nullptr> -void* CallGetDataIfExists(MaybeConstUserType& input) { - return nullptr; -} - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ diff --git a/mojo/public/cpp/bindings/lib/string_serialization.h b/mojo/public/cpp/bindings/lib/string_serialization.h deleted file mode 100644 index 6e0c758..0000000 --- a/mojo/public/cpp/bindings/lib/string_serialization.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_ - -#include -#include - -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "mojo/public/cpp/bindings/lib/serialization_forward.h" -#include "mojo/public/cpp/bindings/lib/serialization_util.h" -#include "mojo/public/cpp/bindings/string_data_view.h" -#include "mojo/public/cpp/bindings/string_traits.h" - -namespace mojo { -namespace internal { - -template -struct Serializer { - using UserType = typename std::remove_const::type; - using Traits = StringTraits; - - static size_t PrepareToSerialize(MaybeConstUserType& input, - SerializationContext* context) { - if (CallIsNullIfExists(input)) - return 0; - - void* custom_context = CustomContextHelper::SetUp(input, context); - return Align(sizeof(String_Data) + - CallWithContext(Traits::GetSize, input, custom_context)); - } - - static void Serialize(MaybeConstUserType& input, - Buffer* buffer, - String_Data** output, - SerializationContext* context) { - if (CallIsNullIfExists(input)) { - *output = nullptr; - return; - } - - void* custom_context = CustomContextHelper::GetNext(context); - - String_Data* result = String_Data::New( - CallWithContext(Traits::GetSize, input, custom_context), buffer); - if (result) { - memcpy(result->storage(), - CallWithContext(Traits::GetData, input, custom_context), - CallWithContext(Traits::GetSize, input, custom_context)); - } - *output = result; - - CustomContextHelper::TearDown(input, custom_context); - } - - static bool Deserialize(String_Data* input, - UserType* output, - SerializationContext* context) { - if (!input) - return CallSetToNullIfExists(output); - return Traits::Read(StringDataView(input, context), output); - } -}; - -} // namespace internal -} // namespace mojo - -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_STRING_SERIALIZATION_H_ diff --git a/mojo/public/cpp/bindings/lib/string_traits_string16.cc b/mojo/public/cpp/bindings/lib/string_traits_string16.cc deleted file mode 100644 index 95ff6cc..0000000 --- a/mojo/public/cpp/bindings/lib/string_traits_string16.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/string_traits_string16.h" - -#include - -#include "base/strings/utf_string_conversions.h" - -namespace mojo { - -// static -void* StringTraits::SetUpContext(const base::string16& input) { - return new std::string(base::UTF16ToUTF8(input)); -} - -// static -void StringTraits::TearDownContext(const base::string16& input, - void* context) { - delete static_cast(context); -} - -// static -size_t StringTraits::GetSize(const base::string16& input, - void* context) { - return static_cast(context)->size(); -} - -// static -const char* StringTraits::GetData(const base::string16& input, - void* context) { - return static_cast(context)->data(); -} - -// static -bool StringTraits::Read(StringDataView input, - base::string16* output) { - return base::UTF8ToUTF16(input.storage(), input.size(), output); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/string_traits_wtf.cc b/mojo/public/cpp/bindings/lib/string_traits_wtf.cc deleted file mode 100644 index 203f6f5..0000000 --- a/mojo/public/cpp/bindings/lib/string_traits_wtf.cc +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/string_traits_wtf.h" - -#include - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" -#include "third_party/WebKit/Source/wtf/text/StringUTF8Adaptor.h" - -namespace mojo { -namespace { - -struct UTF8AdaptorInfo { - explicit UTF8AdaptorInfo(const WTF::String& input) : utf8_adaptor(input) { -#if DCHECK_IS_ON() - original_size_in_bytes = input.charactersSizeInBytes(); -#endif - } - - ~UTF8AdaptorInfo() {} - - WTF::StringUTF8Adaptor utf8_adaptor; - -#if DCHECK_IS_ON() - // For sanity check only. - size_t original_size_in_bytes; -#endif -}; - -UTF8AdaptorInfo* ToAdaptor(const WTF::String& input, void* context) { - UTF8AdaptorInfo* adaptor = static_cast(context); - -#if DCHECK_IS_ON() - DCHECK_EQ(adaptor->original_size_in_bytes, input.charactersSizeInBytes()); -#endif - return adaptor; -} - -} // namespace - -// static -void StringTraits::SetToNull(WTF::String* output) { - if (output->isNull()) - return; - - WTF::String result; - output->swap(result); -} - -// static -void* StringTraits::SetUpContext(const WTF::String& input) { - return new UTF8AdaptorInfo(input); -} - -// static -void StringTraits::TearDownContext(const WTF::String& input, - void* context) { - delete ToAdaptor(input, context); -} - -// static -size_t StringTraits::GetSize(const WTF::String& input, - void* context) { - return ToAdaptor(input, context)->utf8_adaptor.length(); -} - -// static -const char* StringTraits::GetData(const WTF::String& input, - void* context) { - return ToAdaptor(input, context)->utf8_adaptor.data(); -} - -// static -bool StringTraits::Read(StringDataView input, - WTF::String* output) { - WTF::String result = WTF::String::fromUTF8(input.storage(), input.size()); - output->swap(result); - return true; -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc b/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc deleted file mode 100644 index 585a8f0..0000000 --- a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/sync_call_restrictions.h" - -#if ENABLE_SYNC_CALL_RESTRICTIONS - -#include "base/debug/leak_annotations.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/threading/thread_local.h" -#include "mojo/public/c/system/core.h" - -namespace mojo { - -namespace { - -class SyncCallSettings { - public: - static SyncCallSettings* current(); - - bool allowed() const { - return scoped_allow_count_ > 0 || system_defined_value_; - } - - void IncreaseScopedAllowCount() { scoped_allow_count_++; } - void DecreaseScopedAllowCount() { - DCHECK_LT(0u, scoped_allow_count_); - scoped_allow_count_--; - } - - private: - SyncCallSettings(); - ~SyncCallSettings(); - - bool system_defined_value_ = true; - size_t scoped_allow_count_ = 0; -}; - -base::LazyInstance>::DestructorAtExit - g_sync_call_settings = LAZY_INSTANCE_INITIALIZER; - -// static -SyncCallSettings* SyncCallSettings::current() { - SyncCallSettings* result = g_sync_call_settings.Pointer()->Get(); - if (!result) { - result = new SyncCallSettings(); - ANNOTATE_LEAKING_OBJECT_PTR(result); - DCHECK_EQ(result, g_sync_call_settings.Pointer()->Get()); - } - return result; -} - -SyncCallSettings::SyncCallSettings() { - MojoResult result = MojoGetProperty(MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED, - &system_defined_value_); - DCHECK_EQ(MOJO_RESULT_OK, result); - - DCHECK(!g_sync_call_settings.Pointer()->Get()); - g_sync_call_settings.Pointer()->Set(this); -} - -SyncCallSettings::~SyncCallSettings() { - g_sync_call_settings.Pointer()->Set(nullptr); -} - -} // namespace - -// static -void SyncCallRestrictions::AssertSyncCallAllowed() { - if (!SyncCallSettings::current()->allowed()) { - LOG(FATAL) << "Mojo sync calls are not allowed in this process because " - << "they can lead to jank and deadlock. If you must make an " - << "exception, please see " - << "SyncCallRestrictions::ScopedAllowSyncCall and consult " - << "mojo/OWNERS."; - } -} - -// static -void SyncCallRestrictions::IncreaseScopedAllowCount() { - SyncCallSettings::current()->IncreaseScopedAllowCount(); -} - -// static -void SyncCallRestrictions::DecreaseScopedAllowCount() { - SyncCallSettings::current()->DecreaseScopedAllowCount(); -} - -} // namespace mojo - -#endif // ENABLE_SYNC_CALL_RESTRICTIONS diff --git a/mojo/public/cpp/bindings/lib/sync_event_watcher.cc b/mojo/public/cpp/bindings/lib/sync_event_watcher.cc deleted file mode 100644 index b1c97e3..0000000 --- a/mojo/public/cpp/bindings/lib/sync_event_watcher.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/sync_event_watcher.h" - -#include "base/logging.h" - -namespace mojo { - -SyncEventWatcher::SyncEventWatcher(base::WaitableEvent* event, - const base::Closure& callback) - : event_(event), - callback_(callback), - registry_(SyncHandleRegistry::current()), - destroyed_(new base::RefCountedData(false)) {} - -SyncEventWatcher::~SyncEventWatcher() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (registered_) - registry_->UnregisterEvent(event_); - destroyed_->data = true; -} - -void SyncEventWatcher::AllowWokenUpBySyncWatchOnSameThread() { - DCHECK(thread_checker_.CalledOnValidThread()); - IncrementRegisterCount(); -} - -bool SyncEventWatcher::SyncWatch(const bool* should_stop) { - DCHECK(thread_checker_.CalledOnValidThread()); - IncrementRegisterCount(); - if (!registered_) { - DecrementRegisterCount(); - return false; - } - - // This object may be destroyed during the Wait() call. So we have to preserve - // the boolean that Wait uses. - auto destroyed = destroyed_; - const bool* should_stop_array[] = {should_stop, &destroyed->data}; - bool result = registry_->Wait(should_stop_array, 2); - - // This object has been destroyed. - if (destroyed->data) - return false; - - DecrementRegisterCount(); - return result; -} - -void SyncEventWatcher::IncrementRegisterCount() { - register_request_count_++; - if (!registered_) - registered_ = registry_->RegisterEvent(event_, callback_); -} - -void SyncEventWatcher::DecrementRegisterCount() { - DCHECK_GT(register_request_count_, 0u); - register_request_count_--; - if (register_request_count_ == 0 && registered_) { - registry_->UnregisterEvent(event_); - registered_ = false; - } -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc deleted file mode 100644 index fd3df39..0000000 --- a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/sync_handle_registry.h" - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/stl_util.h" -#include "base/threading/thread_local.h" -#include "mojo/public/c/system/core.h" - -namespace mojo { -namespace { - -base::LazyInstance>::Leaky - g_current_sync_handle_watcher = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// static -scoped_refptr SyncHandleRegistry::current() { - scoped_refptr result( - g_current_sync_handle_watcher.Pointer()->Get()); - if (!result) { - result = new SyncHandleRegistry(); - DCHECK_EQ(result.get(), g_current_sync_handle_watcher.Pointer()->Get()); - } - return result; -} - -bool SyncHandleRegistry::RegisterHandle(const Handle& handle, - MojoHandleSignals handle_signals, - const HandleCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (base::ContainsKey(handles_, handle)) - return false; - - MojoResult result = wait_set_.AddHandle(handle, handle_signals); - if (result != MOJO_RESULT_OK) - return false; - - handles_[handle] = callback; - return true; -} - -void SyncHandleRegistry::UnregisterHandle(const Handle& handle) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!base::ContainsKey(handles_, handle)) - return; - - MojoResult result = wait_set_.RemoveHandle(handle); - DCHECK_EQ(MOJO_RESULT_OK, result); - handles_.erase(handle); -} - -bool SyncHandleRegistry::RegisterEvent(base::WaitableEvent* event, - const base::Closure& callback) { - auto result = events_.insert({event, callback}); - DCHECK(result.second); - MojoResult rv = wait_set_.AddEvent(event); - if (rv == MOJO_RESULT_OK) - return true; - DCHECK_EQ(MOJO_RESULT_ALREADY_EXISTS, rv); - return false; -} - -void SyncHandleRegistry::UnregisterEvent(base::WaitableEvent* event) { - auto it = events_.find(event); - DCHECK(it != events_.end()); - events_.erase(it); - MojoResult rv = wait_set_.RemoveEvent(event); - DCHECK_EQ(MOJO_RESULT_OK, rv); -} - -bool SyncHandleRegistry::Wait(const bool* should_stop[], size_t count) { - DCHECK(thread_checker_.CalledOnValidThread()); - - size_t num_ready_handles; - Handle ready_handle; - MojoResult ready_handle_result; - - scoped_refptr preserver(this); - while (true) { - for (size_t i = 0; i < count; ++i) - if (*should_stop[i]) - return true; - - // TODO(yzshen): Theoretically it can reduce sync call re-entrancy if we - // give priority to the handle that is waiting for sync response. - base::WaitableEvent* ready_event = nullptr; - num_ready_handles = 1; - wait_set_.Wait(&ready_event, &num_ready_handles, &ready_handle, - &ready_handle_result); - if (num_ready_handles) { - DCHECK_EQ(1u, num_ready_handles); - const auto iter = handles_.find(ready_handle); - iter->second.Run(ready_handle_result); - } - - if (ready_event) { - const auto iter = events_.find(ready_event); - DCHECK(iter != events_.end()); - iter->second.Run(); - } - }; - - return false; -} - -SyncHandleRegistry::SyncHandleRegistry() { - DCHECK(!g_current_sync_handle_watcher.Pointer()->Get()); - g_current_sync_handle_watcher.Pointer()->Set(this); -} - -SyncHandleRegistry::~SyncHandleRegistry() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // This object may be destructed after the thread local storage slot used by - // |g_current_sync_handle_watcher| is reset during thread shutdown. - // For example, another slot in the thread local storage holds a referrence to - // this object, and that slot is cleaned up after - // |g_current_sync_handle_watcher|. - if (!g_current_sync_handle_watcher.Pointer()->Get()) - return; - - // If this breaks, it is likely that the global variable is bulit into and - // accessed from multiple modules. - DCHECK_EQ(this, g_current_sync_handle_watcher.Pointer()->Get()); - - g_current_sync_handle_watcher.Pointer()->Set(nullptr); -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc b/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc deleted file mode 100644 index f20af56..0000000 --- a/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/public/cpp/bindings/sync_handle_watcher.h" - -#include "base/logging.h" - -namespace mojo { - -SyncHandleWatcher::SyncHandleWatcher( - const Handle& handle, - MojoHandleSignals handle_signals, - const SyncHandleRegistry::HandleCallback& callback) - : handle_(handle), - handle_signals_(handle_signals), - callback_(callback), - registered_(false), - register_request_count_(0), - registry_(SyncHandleRegistry::current()), - destroyed_(new base::RefCountedData(false)) {} - -SyncHandleWatcher::~SyncHandleWatcher() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (registered_) - registry_->UnregisterHandle(handle_); - - destroyed_->data = true; -} - -void SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread() { - DCHECK(thread_checker_.CalledOnValidThread()); - IncrementRegisterCount(); -} - -bool SyncHandleWatcher::SyncWatch(const bool* should_stop) { - DCHECK(thread_checker_.CalledOnValidThread()); - IncrementRegisterCount(); - if (!registered_) { - DecrementRegisterCount(); - return false; - } - - // This object may be destroyed during the Wait() call. So we have to preserve - // the boolean that Wait uses. - auto destroyed = destroyed_; - const bool* should_stop_array[] = {should_stop, &destroyed->data}; - bool result = registry_->Wait(should_stop_array, 2); - - // This object has been destroyed. - if (destroyed->data) - return false; - - DecrementRegisterCount(); - return result; -} - -void SyncHandleWatcher::IncrementRegisterCount() { - register_request_count_++; - if (!registered_) { - registered_ = - registry_->RegisterHandle(handle_, handle_signals_, callback_); - } -} - -void SyncHandleWatcher::DecrementRegisterCount() { - DCHECK_GT(register_request_count_, 0u); - - register_request_count_--; - if (register_request_count_ == 0 && registered_) { - registry_->UnregisterHandle(handle_); - registered_ = false; - } -} - -} // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/template_util.h b/mojo/public/cpp/bindings/lib/template_util.h deleted file mode 100644 index 5151123..0000000 --- a/mojo/public/cpp/bindings/lib/template_util.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_TEMPLATE_UTIL_H_ - -#include - -namespace mojo { -namespace internal { - -template -struct IntegralConstant { - static const T value = v; -}; - -template -const T IntegralConstant::value; - -typedef IntegralConstant TrueType; -typedef IntegralConstant FalseType; - -template -struct IsConst : FalseType {}; -template -struct IsConst : TrueType {}; - -template -struct IsPointer : FalseType {}; -template -struct IsPointer : TrueType {}; - -template -struct EnableIf {}; - -template -struct EnableIf { - typedef T type; -}; - -// Types YesType and NoType are guaranteed such that sizeof(YesType) < -// sizeof(NoType). -typedef char YesType; - -struct NoType { - YesType dummy[2]; -}; - -// A helper template to determine if given type is non-const move-only-type, -// i.e. if a value of the given type should be passed via std::move() in a -// destructive way. -template -struct IsMoveOnlyType { - static const bool value = std::is_constructible::value && - !std::is_constructible::value; -}; - -// This goop is a trick used to implement a template that can be used to -// determine if a given class is the base class of another given class. -template -struct IsSame { - static bool const value = false; -}; -template -struct IsSame { - static bool const value = true; -}; - -template -struct EnsureTypeIsComplete { - // sizeof() cannot be applied to incomplete types, this line will fail - // compilation if T is forward declaration. - using CheckSize = char (*)[sizeof(T)]; -}; - -template -struct IsBaseOf { - private: - static Derived* CreateDerived(); - static char(&Check(Base*))[1]; - static char(&Check(...))[2]; - - EnsureTypeIsComplete check_base_; - EnsureTypeIsComplete check_derived_; - - public: - static bool const value = sizeof Check(CreateDerived()) == 1 && - !IsSame::value; -}; - -template -struct RemovePointer { - typedef T type; -}; -template -struct RemovePointer { - typedef T type; -}; - -template