From 5bb2480bcdf1f46482ea6c6ea936e6bf8815fdaf Mon Sep 17 00:00:00 2001 From: James Robinson Date: Wed, 23 Sep 2015 16:28:20 -0700 Subject: [PATCH] Update to Mojo 4e4d51ce28a8edcb32b9c7f555e38e2ae84a825e, update deps This updates to mojo 4e4d51ce28a and mojo sdk 711a0bcfb141b4 and updates the sky package's pubspec.yaml dependency to '>=0.1.0 <0.2.0' to be compatible with the current mojo package. This includes an update to the Mojo Dart generator to produce real classes for enums and the corresponding updates for users of the KeyboardType enum in Sky as well as one scoped_ptr->std::unique_ptr in shell corresponding to a change in the Mojo EDK. When a new version of the sky and sky_services package are pushed this will fix domokit/mojo#440. --- DEPS | 2 +- examples/fitness/lib/measurement.dart | 2 +- examples/fitness/lib/settings.dart | 2 +- mojo/android/javatests/init_library.cc | 3 +- .../mojo/bindings/ValidationTest.java | 23 +- mojo/common/dart/lib/trace_provider_impl.dart | 35 +- mojo/common/dart/lib/tracing_helper.dart | 132 +++- mojo/common/trace_provider_impl.cc | 62 +- mojo/common/trace_provider_impl.h | 30 +- mojo/common/tracing_impl.cc | 17 +- mojo/common/tracing_impl.h | 3 + mojo/converters/ozone_drm_gpu/BUILD.gn | 19 + .../ozone_drm_gpu_type_converters.cc | 108 +++ .../ozone_drm_gpu_type_converters.h | 37 + mojo/dart/BUILD.gn | 2 - mojo/dart/apptest/BUILD.gn | 16 - mojo/dart/apptest/lib/apptest.dart | 67 -- mojo/dart/apptest/pubspec.lock | 131 ---- mojo/dart/apptest/pubspec.yaml | 4 - mojo/dart/dart_snapshotter/main.cc | 5 +- mojo/dart/embedder/BUILD.gn | 78 +-- mojo/dart/embedder/builtin.cc | 3 +- mojo/dart/embedder/builtin.h | 2 +- mojo/dart/embedder/dart_controller.cc | 31 +- .../embedder/io/internet_address_linux.cc | 72 -- .../embedder/io/internet_address_patch.dart | 10 +- ...s_android.cc => internet_address_posix.cc} | 18 +- mojo/dart/embedder/io/mojo_patch.dart | 16 +- mojo/dart/embedder/mojo_dart_state.h | 3 - mojo/dart/mojo_services/BUILD.gn | 1 + mojo/dart/mojo_services/CHANGELOG.md | 10 + mojo/dart/mojo_services/pubspec.yaml | 5 +- mojo/dart/mojom/BUILD.gn | 19 - mojo/dart/mojom/CHANGELOG.md | 51 -- mojo/dart/mojom/README.md | 41 -- mojo/dart/mojom/lib/README.md | 5 - mojo/dart/mojom/lib/generate.dart | 249 ------- mojo/dart/mojom/lib/src/options.dart | 123 ---- mojo/dart/mojom/lib/src/utils.dart | 100 --- mojo/dart/mojom/pubspec.lock | 19 - mojo/dart/mojom/pubspec.yaml | 12 - mojo/dart/mojom/test/generate_test.dart | 390 ----------- mojo/dart/test/bindings_generation_test.dart | 38 +- mojo/dart/test/control_messages_test.dart | 8 +- mojo/dart/test/validation_test.dart | 2 + mojo/data_pipe_utils/data_pipe_file_utils.cc | 26 +- mojo/data_pipe_utils/data_pipe_utils.h | 11 +- mojo/edk/embedder/BUILD.gn | 22 +- mojo/edk/embedder/embedder.cc | 5 +- mojo/edk/embedder/embedder.h | 89 ++- mojo/edk/embedder/embedder_unittest.cc | 65 +- mojo/edk/embedder/master_process_delegate.h | 3 +- mojo/edk/embedder/platform_channel_pair.h | 25 +- .../platform_channel_pair_posix_unittest.cc | 36 +- .../edk/embedder/platform_channel_pair_win.cc | 111 --- .../embedder/platform_channel_utils_posix.h | 38 +- mojo/edk/embedder/platform_handle.cc | 15 - mojo/edk/embedder/platform_handle.h | 25 +- mojo/edk/embedder/platform_handle_utils.h | 7 +- .../edk/embedder/platform_handle_utils_win.cc | 27 - mojo/edk/embedder/platform_handle_vector.h | 10 +- mojo/edk/embedder/platform_shared_buffer.h | 17 +- mojo/edk/embedder/platform_support.h | 21 +- mojo/edk/embedder/process_delegate.h | 3 +- mojo/edk/embedder/process_type.h | 6 +- mojo/edk/embedder/scoped_platform_handle.h | 8 +- .../embedder/simple_platform_shared_buffer.cc | 7 +- .../embedder/simple_platform_shared_buffer.h | 18 +- .../simple_platform_shared_buffer_android.cc | 11 +- .../simple_platform_shared_buffer_posix.cc | 26 +- .../simple_platform_shared_buffer_unittest.cc | 25 +- .../simple_platform_shared_buffer_win.cc | 88 --- mojo/edk/embedder/simple_platform_support.cc | 5 + mojo/edk/embedder/simple_platform_support.h | 5 +- mojo/edk/embedder/slave_process_delegate.h | 3 +- mojo/edk/embedder/test_embedder.cc | 4 +- mojo/edk/embedder/test_embedder.h | 6 +- mojo/edk/js/tests/js_to_cpp_tests.cc | 23 +- mojo/edk/system/BUILD.gn | 10 +- mojo/edk/system/async_waiter.h | 5 +- mojo/edk/system/awakable.h | 17 +- mojo/edk/system/awakable_list.h | 17 +- mojo/edk/system/channel.cc | 30 +- mojo/edk/system/channel.h | 21 +- mojo/edk/system/channel_endpoint.cc | 20 +- mojo/edk/system/channel_endpoint.h | 14 +- mojo/edk/system/channel_endpoint_client.h | 4 +- mojo/edk/system/channel_endpoint_id.h | 36 +- mojo/edk/system/channel_endpoint_unittest.cc | 12 +- mojo/edk/system/channel_manager.h | 7 +- mojo/edk/system/channel_test_base.cc | 12 +- mojo/edk/system/channel_test_base.h | 12 +- mojo/edk/system/channel_unittest.cc | 30 + mojo/edk/system/configuration.h | 9 +- mojo/edk/system/connection_manager.h | 8 +- mojo/edk/system/connection_manager_messages.h | 5 +- mojo/edk/system/core.cc | 12 +- mojo/edk/system/core.h | 4 +- mojo/edk/system/data_pipe.cc | 105 +-- mojo/edk/system/data_pipe.h | 96 +-- .../system/data_pipe_consumer_dispatcher.h | 4 +- mojo/edk/system/data_pipe_impl.cc | 7 +- mojo/edk/system/data_pipe_impl.h | 66 +- mojo/edk/system/data_pipe_impl_unittest.cc | 12 +- .../system/data_pipe_producer_dispatcher.h | 4 +- mojo/edk/system/dispatcher.cc | 4 +- mojo/edk/system/dispatcher.h | 18 +- mojo/edk/system/dispatcher_unittest.cc | 4 +- mojo/edk/system/endpoint_relayer.cc | 12 +- mojo/edk/system/endpoint_relayer.h | 13 +- mojo/edk/system/endpoint_relayer_unittest.cc | 14 +- mojo/edk/system/handle_signals_state.h | 4 +- mojo/edk/system/handle_table.h | 7 +- mojo/edk/system/incoming_endpoint.cc | 2 +- mojo/edk/system/incoming_endpoint.h | 4 +- mojo/edk/system/ipc_support.cc | 8 +- mojo/edk/system/ipc_support.h | 10 +- mojo/edk/system/ipc_support_unittest.cc | 47 +- mojo/edk/system/local_data_pipe_impl.cc | 27 +- mojo/edk/system/local_data_pipe_impl.h | 8 +- .../edk/system/local_message_pipe_endpoint.cc | 6 +- mojo/edk/system/local_message_pipe_endpoint.h | 6 +- mojo/edk/system/mapping_table.cc | 2 +- mojo/edk/system/mapping_table.h | 12 +- mojo/edk/system/master_connection_manager.cc | 30 +- mojo/edk/system/master_connection_manager.h | 15 +- mojo/edk/system/memory.cc | 57 +- mojo/edk/system/memory.h | 34 +- mojo/edk/system/message_in_transit.cc | 12 +- mojo/edk/system/message_in_transit.h | 28 +- mojo/edk/system/message_in_transit_queue.h | 13 +- .../system/message_in_transit_test_utils.cc | 11 +- .../system/message_in_transit_test_utils.h | 5 +- mojo/edk/system/message_pipe.cc | 50 +- mojo/edk/system/message_pipe.h | 21 +- mojo/edk/system/message_pipe_dispatcher.h | 3 +- .../message_pipe_dispatcher_unittest.cc | 8 +- mojo/edk/system/message_pipe_endpoint.h | 7 +- mojo/edk/system/message_pipe_perftest.cc | 3 +- mojo/edk/system/message_pipe_test_utils.cc | 3 +- mojo/edk/system/message_pipe_test_utils.h | 4 +- .../multiprocess_message_pipe_unittest.cc | 40 +- mojo/edk/system/mutex.h | 5 +- mojo/edk/system/options_validation.h | 24 +- mojo/edk/system/platform_handle_dispatcher.h | 4 +- .../platform_handle_dispatcher_unittest.cc | 20 +- .../edk/system/proxy_message_pipe_endpoint.cc | 6 +- mojo/edk/system/proxy_message_pipe_endpoint.h | 6 +- mojo/edk/system/raw_channel.cc | 37 +- mojo/edk/system/raw_channel.h | 110 +-- mojo/edk/system/raw_channel_posix.cc | 62 +- mojo/edk/system/raw_channel_unittest.cc | 86 ++- mojo/edk/system/raw_channel_win.cc | 633 ------------------ .../system/remote_consumer_data_pipe_impl.cc | 39 +- .../system/remote_consumer_data_pipe_impl.h | 22 +- .../system/remote_data_pipe_impl_unittest.cc | 237 ++++++- .../system/remote_message_pipe_unittest.cc | 47 +- .../system/remote_producer_data_pipe_impl.cc | 25 +- .../system/remote_producer_data_pipe_impl.h | 20 +- mojo/edk/system/shared_buffer_dispatcher.cc | 3 +- mojo/edk/system/shared_buffer_dispatcher.h | 6 +- .../shared_buffer_dispatcher_unittest.cc | 8 +- mojo/edk/system/simple_dispatcher.h | 3 +- mojo/edk/system/simple_dispatcher_unittest.cc | 24 +- mojo/edk/system/slave_connection_manager.cc | 13 +- mojo/edk/system/slave_connection_manager.h | 11 +- mojo/edk/system/system_impl_export.h | 29 - .../system/test_channel_endpoint_client.cc | 4 +- .../edk/system/test_channel_endpoint_client.h | 5 +- mojo/edk/system/test_utils.cc | 16 +- mojo/edk/system/test_utils.h | 8 +- mojo/edk/system/transport_data.cc | 13 +- mojo/edk/system/transport_data.h | 13 +- mojo/edk/system/unique_identifier.h | 18 +- mojo/edk/system/unique_identifier_unittest.cc | 6 +- mojo/edk/system/waiter.h | 5 +- mojo/edk/test/BUILD.gn | 10 +- mojo/edk/test/multiprocess_test_helper.cc | 14 +- mojo/edk/test/multiprocess_test_helper.h | 3 +- .../test/multiprocess_test_helper_unittest.cc | 12 +- mojo/edk/test/scoped_test_dir.cc | 27 + mojo/edk/test/scoped_test_dir.h | 33 + mojo/edk/test/test_io_thread.cc | 67 ++ mojo/edk/test/test_io_thread.h | 57 ++ mojo/edk/test/test_support_impl.cc | 19 +- mojo/edk/test/test_utils.h | 9 +- mojo/edk/test/test_utils_posix.cc | 8 +- mojo/edk/test/test_utils_win.cc | 112 ---- mojo/edk/util/BUILD.gn | 20 + mojo/edk/util/make_unique.h | 57 ++ mojo/edk/util/scoped_file.h | 32 + .../services/files/public/interfaces/BUILD.gn | 2 + .../files/public/interfaces/file.mojom | 4 +- .../files/public/interfaces/ioctl.mojom | 17 + .../public/interfaces/ioctl_terminal.mojom | 184 +++++ mojo/services/mojo_services.gni | 17 +- .../public/interfaces/native_viewport.mojom | 1 + .../ozone_drm_gpu/public/interfaces/BUILD.gn | 18 + .../public/interfaces/ozone_drm_gpu.mojom | 54 ++ .../ozone_drm_host/public/interfaces/BUILD.gn | 18 + .../public/interfaces/ozone_drm_host.mojom | 13 + .../interfaces/url_response_disk_cache.mojom | 43 +- .../services/view_manager/public/cpp/BUILD.gn | 2 +- .../sky/lib/src/services/keyboard.dart | 4 +- sky/packages/sky/lib/src/widgets/input.dart | 6 +- sky/packages/sky/pubspec.yaml | 4 +- sky/shell/shell.cc | 4 +- sky/unit/test/widget/input_test.dart | 2 +- 208 files changed, 2619 insertions(+), 3750 deletions(-) create mode 100644 mojo/converters/ozone_drm_gpu/BUILD.gn create mode 100644 mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.cc create mode 100644 mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.h delete mode 100644 mojo/dart/apptest/BUILD.gn delete mode 100644 mojo/dart/apptest/lib/apptest.dart delete mode 100644 mojo/dart/apptest/pubspec.lock delete mode 100644 mojo/dart/apptest/pubspec.yaml delete mode 100644 mojo/dart/embedder/io/internet_address_linux.cc rename mojo/dart/embedder/io/{internet_address_android.cc => internet_address_posix.cc} (82%) delete mode 100644 mojo/dart/mojom/BUILD.gn delete mode 100644 mojo/dart/mojom/CHANGELOG.md delete mode 100644 mojo/dart/mojom/README.md delete mode 100644 mojo/dart/mojom/lib/README.md delete mode 100644 mojo/dart/mojom/lib/generate.dart delete mode 100644 mojo/dart/mojom/lib/src/options.dart delete mode 100644 mojo/dart/mojom/lib/src/utils.dart delete mode 100644 mojo/dart/mojom/pubspec.lock delete mode 100644 mojo/dart/mojom/pubspec.yaml delete mode 100644 mojo/dart/mojom/test/generate_test.dart delete mode 100644 mojo/edk/embedder/platform_channel_pair_win.cc delete mode 100644 mojo/edk/embedder/platform_handle_utils_win.cc delete mode 100644 mojo/edk/embedder/simple_platform_shared_buffer_win.cc delete mode 100644 mojo/edk/system/raw_channel_win.cc delete mode 100644 mojo/edk/system/system_impl_export.h create mode 100644 mojo/edk/test/scoped_test_dir.cc create mode 100644 mojo/edk/test/scoped_test_dir.h create mode 100644 mojo/edk/test/test_io_thread.cc create mode 100644 mojo/edk/test/test_io_thread.h delete mode 100644 mojo/edk/test/test_utils_win.cc create mode 100644 mojo/edk/util/BUILD.gn create mode 100644 mojo/edk/util/make_unique.h create mode 100644 mojo/edk/util/scoped_file.h create mode 100644 mojo/services/files/public/interfaces/ioctl.mojom create mode 100644 mojo/services/files/public/interfaces/ioctl_terminal.mojom create mode 100644 mojo/services/ozone_drm_gpu/public/interfaces/BUILD.gn create mode 100644 mojo/services/ozone_drm_gpu/public/interfaces/ozone_drm_gpu.mojom create mode 100644 mojo/services/ozone_drm_host/public/interfaces/BUILD.gn create mode 100644 mojo/services/ozone_drm_host/public/interfaces/ozone_drm_host.mojom diff --git a/DEPS b/DEPS index bd9035333f4..c4855bb7e27 100644 --- a/DEPS +++ b/DEPS @@ -19,7 +19,7 @@ vars = { 'chromium_git': 'https://chromium.googlesource.com', - 'mojo_sdk_revision': '3ec8c53e9c9e5a8cd3cf251c4ae4754b75172225', + 'mojo_sdk_revision': '711a0bcfb141b481f51ac1c9c62ec73e9b988615', 'mojo_devtools_revision': '49879d78ce4486e10c2214a101d9b2e82794b2f4', 'skia_revision': '0d39d37ddcfb3847795639eaef513f1112eba627', 'dart_revision': 'cab003366785773ace16b5305ac1f33c228cac54', diff --git a/examples/fitness/lib/measurement.dart b/examples/fitness/lib/measurement.dart index 63dcbf8a838..ebea00bc33d 100644 --- a/examples/fitness/lib/measurement.dart +++ b/examples/fitness/lib/measurement.dart @@ -189,7 +189,7 @@ class MeasurementFragment extends StatefulComponent { new Input( key: weightKey, placeholder: 'Enter weight', - keyboardType: KeyboardType_NUMBER, + keyboardType: KeyboardType.NUMBER, onChanged: _handleWeightChanged ), ], alignItems: FlexAlignItems.stretch) diff --git a/examples/fitness/lib/settings.dart b/examples/fitness/lib/settings.dart index 66887b83ba9..584338022eb 100644 --- a/examples/fitness/lib/settings.dart +++ b/examples/fitness/lib/settings.dart @@ -70,7 +70,7 @@ class SettingsFragment extends StatefulComponent { content: new Input( key: weightGoalKey, placeholder: 'Goal weight in lbs', - keyboardType: KeyboardType_NUMBER, + keyboardType: KeyboardType.NUMBER, onChanged: _handleGoalWeightChanged ), onDismiss: () { diff --git a/mojo/android/javatests/init_library.cc b/mojo/android/javatests/init_library.cc index 92d11d99bb3..3cfff9d7504 100644 --- a/mojo/android/javatests/init_library.cc +++ b/mojo/android/javatests/init_library.cc @@ -28,7 +28,8 @@ bool RegisterJNI(JNIEnv* env) { } bool Init() { - mojo::embedder::Init(scoped_ptr( + // TODO(vtl): Use make_unique when C++14 is available. + mojo::embedder::Init(std::unique_ptr( new mojo::embedder::SimplePlatformSupport())); return true; } diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java index 286566de0c9..a99914f4875 100644 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java +++ b/mojo/android/javatests/src/org/chromium/mojo/bindings/ValidationTest.java @@ -112,15 +112,20 @@ public class ValidationTest extends MojoTestCase { 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."); + try { + 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."); + } + } catch (SerializationException e) { + e.printStackTrace(); + fail("Input: " + test.dataFile.getName() + ": Serialization error."); } } } diff --git a/mojo/common/dart/lib/trace_provider_impl.dart b/mojo/common/dart/lib/trace_provider_impl.dart index 13901e09a7f..e1cbbdf0f26 100644 --- a/mojo/common/dart/lib/trace_provider_impl.dart +++ b/mojo/common/dart/lib/trace_provider_impl.dart @@ -4,18 +4,37 @@ import 'dart:async'; -import 'package:mojo/application.dart'; -import 'package:mojo/bindings.dart'; import 'package:mojo/core.dart'; import 'package:mojo_services/tracing/tracing.mojom.dart'; class TraceProviderImpl implements TraceProvider { + // Any messages sent before the tracing service connects to us will be + // recorded and kept until one second after construction of the trace + // provider. If the tracing service connects before that time, we will replay + // the recorded trace events. + // + // This allows the client to record trace events early during initialization + // of the app. + List _message_queue; + bool _enqueuing; + TraceProviderStub _stub; TraceRecorderProxy _recorder; // TODO(rudominer) We currently ignore _categories. String _categories; - TraceProviderImpl.fromEndpoint(MojoMessagePipeEndpoint e) { + TraceProviderImpl() { + _message_queue = []; + _enqueuing = true; + new Future(() { + new Future.delayed(const Duration(seconds: 1), () { + _enqueuing = false; + _message_queue.clear(); + }); + }); + } + + void connect(MojoMessagePipeEndpoint e) { _stub = TraceProviderStub.newFromEndpoint(e); _stub.impl = this; } @@ -25,6 +44,12 @@ class TraceProviderImpl implements TraceProvider { assert(_recorder == null); _recorder = recorder; _categories = categories; + + for (String message in _message_queue) { + _recorder.ptr.record(message); + } + _enqueuing = false; + _message_queue.clear(); } @override @@ -35,12 +60,14 @@ class TraceProviderImpl implements TraceProvider { } bool isActive() { - return _recorder != null; + return _enqueuing || _recorder != null; } void sendTraceMessage(String message) { if (_recorder != null) { _recorder.ptr.record(message); + } else if (_enqueuing) { + _message_queue.add(message); } } } diff --git a/mojo/common/dart/lib/tracing_helper.dart b/mojo/common/dart/lib/tracing_helper.dart index 23c121b4592..44147073daf 100644 --- a/mojo/common/dart/lib/tracing_helper.dart +++ b/mojo/common/dart/lib/tracing_helper.dart @@ -13,64 +13,100 @@ import 'dart:io'; import 'dart:isolate'; import 'package:mojo/application.dart'; -import 'package:mojo/bindings.dart'; import 'package:mojo/core.dart'; import 'package:mojo_services/tracing/tracing.mojom.dart'; +// Phases indicating the nature of the event in the trace log. +// These should be in sync with definitions in +// //base/trace_event/trace_event.h +const traceEventInstant = "I"; +const traceEventPhaseBegin = "B"; +const traceEventPhaseEnd = "E"; +const traceEventPhaseAsyncBegin = "S"; +const traceEventPhaseAsyncEnd = "F"; + // TracingHelper is used by Dart code running in the Mojo shell in order // to perform tracing. class TracingHelper { TraceProviderImpl _impl; - String _tid; - + int _tid; + static TracingHelper _tracing; // Construct an instance of TracingHelper from within your application's // |initialize()| method. |appName| will be used to form a thread identifier // for use in trace messages. If |appName| is longer than 20 characters then // only the last 20 characters of |appName| will be used. - TracingHelper(Application app, String appName) { - // We use only the last 20 characters of appName to form the tid so that - // the 9-digit Isolate hash code we are appending won't get truncated by the - // tracing UI. - if (appName.length > 20) { - appName = appName.substring(appName.length - 20); - } - _tid = "${appName}/${Isolate.current.hashCode.toString()}"; + TracingHelper.fromApplication(Application app, String appName) { + _tid = [appName, Isolate.current].fold(7, + (hash, element) => 31 * hash + element.hashCode); + _impl = new TraceProviderImpl(); ApplicationConnection connection = app.connectToApplication("mojo:tracing"); connection.provideService(TraceProviderName, (e) { - assert(_impl == null); - _impl = new TraceProviderImpl.fromEndpoint(e); + _impl.connect(e); }); + assert(_tracing == null); + _tracing = this; + } + + // Factory to return the singleton instance of the TracingHelper. The isolate + // must have constructed the object using TracingHelper.fromApplication + // atleast once before using this factory. + factory TracingHelper() { + assert(_tracing != null); + return _tracing; } bool isActive() { return (_impl != null) && _impl.isActive(); } - // Invoke this at the beginning of a function whose duration you wish to - // trace. Invoke |end()| on the returned object. - FunctionTrace beginFunction(String functionName, {Map args}) { - assert(functionName != null); - if (isActive()) { - _sendTraceMessage(functionName, "B", args: args); - } else { - functionName = null; - } - return new _FunctionTraceImpl(this, functionName); - } - - void _endFunction(String functionName) { - _sendTraceMessage(functionName, "E"); - } - - void _sendTraceMessage(String name, String phase, + // Invoke this at the beginning of a synchronous function whose + // duration you wish to trace. Invoke |end()| on the returned object. + FunctionTrace begin(String functionName, String categories, {Map args}) { + return _beginFunction(functionName, categories, traceEventPhaseBegin, + args: args); + } + + // Invoke this right before an asynchronous function whose duration + // you wish to trace. Invoke |end()| on the returned object. + FunctionTrace beginAsync(String functionName, String categories, + {Map args}) { + return _beginFunction(functionName, categories, traceEventPhaseAsyncBegin, + args: args); + } + + void traceInstant(String name, String categories, + {Map args}) { + _sendTraceMessage(name, categories, traceEventInstant, 0, args: args); + } + + FunctionTrace _beginFunction(String functionName, String categories, + String phase, {Map args}) { + assert(functionName != null); + final trace = + new _FunctionTraceImpl(this, isActive() ? functionName : null, + categories, phase); + _sendTraceMessage(functionName, categories, phase, trace.hashCode, + args: args); + return trace; + } + + void _endFunction(String functionName, String categories, String phase, + int traceId) { + _sendTraceMessage(functionName, categories, phase, traceId); + } + + void _sendTraceMessage(String name, String categories, String phase, + int traceId, {Map args}) { if (isActive()) { var map = {}; map["name"] = name; + map["cat"] = categories; map["ph"] = phase; map["ts"] = getTimeTicksNow(); map["pid"] = pid; map["tid"] = _tid; + map["id"] = traceId; if (args != null) { map["args"] = args; } @@ -80,16 +116,28 @@ class TracingHelper { // A convenience method that wraps a closure in a begin-end pair of // tracing calls. - dynamic trace(String functionName, closure(), {Map args}) { - FunctionTrace ft = beginFunction(functionName, args: args); + dynamic trace(String functionName, String categories, closure(), + {Map args}) { + FunctionTrace ft = begin(functionName, categories, args: args); final returnValue = closure(); ft.end(); return returnValue; } + + // A convenience method that wraps a closure in a begin-end pair of + // async tracing calls. The return value should either be returned or awaited. + Future traceAsync(String functionName, String categories, Future closure(), + {Map args}) { + FunctionTrace ft = beginAsync(functionName, categories, args: args); + final Future returnValue = closure(); + returnValue.whenComplete(ft.end); + return returnValue; + } } -// A an instance of FunctionTrace is returned from |beginFunction()|. -// Invoke |end()| from every exit point in the function you are tracing. +// An instance of FunctionTrace is returned from |begin()|, |beginAsync()|. +// Invoke |end()| to end the trace from every exit point in the function you are +// tracing. abstract class FunctionTrace { void end(); } @@ -97,13 +145,25 @@ abstract class FunctionTrace { class _FunctionTraceImpl implements FunctionTrace { TracingHelper _tracing; String _functionName; + String _categories; + String _beginPhase; - _FunctionTraceImpl(this._tracing, this._functionName); + _FunctionTraceImpl(this._tracing, this._functionName, this._categories, + this._beginPhase) { + assert(_beginPhase == traceEventPhaseBegin || + _beginPhase == traceEventPhaseAsyncBegin); + } @override void end() { if (_functionName != null) { - _tracing._endFunction(_functionName); + if (_beginPhase == traceEventPhaseBegin) { + _tracing._endFunction(_functionName, _categories, traceEventPhaseEnd, + hashCode); + } else if (_beginPhase == traceEventPhaseAsyncBegin) { + _tracing._endFunction(_functionName, _categories, + traceEventPhaseAsyncEnd, hashCode); + } } } } diff --git a/mojo/common/trace_provider_impl.cc b/mojo/common/trace_provider_impl.cc index cc4fd77e4fc..1e61f62f887 100644 --- a/mojo/common/trace_provider_impl.cc +++ b/mojo/common/trace_provider_impl.cc @@ -4,7 +4,10 @@ #include "mojo/common/trace_provider_impl.h" +#include "base/callback.h" #include "base/logging.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "base/trace_event/trace_config.h" #include "base/trace_event/trace_event.h" #include "mojo/public/cpp/application/application_connection.h" @@ -12,19 +15,25 @@ namespace mojo { -TraceProviderImpl::TraceProviderImpl( - InterfaceRequest request) - : tracing_already_started_(false), binding_(this, request.Pass()) { -} +TraceProviderImpl::TraceProviderImpl() + : binding_(this), tracing_forced_(false), weak_factory_(this) {} -TraceProviderImpl::~TraceProviderImpl() { +TraceProviderImpl::~TraceProviderImpl() {} + +void TraceProviderImpl::Bind(InterfaceRequest request) { + if (!binding_.is_bound()) { + binding_.Bind(request.Pass()); + } else { + LOG(ERROR) << "Cannot accept two connections to TraceProvider."; + } } void TraceProviderImpl::StartTracing(const String& categories, - tracing::TraceRecorderPtr collector) { + tracing::TraceRecorderPtr recorder) { DCHECK(!recorder_.get()); - recorder_ = collector.Pass(); - if (!tracing_already_started_) { + recorder_ = recorder.Pass(); + tracing_forced_ = false; + if (!base::trace_event::TraceLog::GetInstance()->IsEnabled()) { std::string categories_str = categories.To(); base::trace_event::TraceLog::GetInstance()->SetEnabled( base::trace_event::TraceConfig(categories_str, @@ -41,11 +50,46 @@ void TraceProviderImpl::StopTracing() { base::Bind(&TraceProviderImpl::SendChunk, base::Unretained(this))); } +void TraceProviderImpl::ForceEnableTracing() { + base::trace_event::TraceLog::GetInstance()->SetEnabled( + base::trace_event::TraceConfig("*", base::trace_event::RECORD_UNTIL_FULL), + base::trace_event::TraceLog::RECORDING_MODE); + tracing_forced_ = true; + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&TraceProviderImpl::DelayedStop, weak_factory_.GetWeakPtr())); +} + +void TraceProviderImpl::DelayedStop() { + // We use this indirection to account for cases where the Initialize app + // method (within which TraceProviderImpl is created) takes more than one + // second to finish; thus we start the countdown only when the current thread + // is unblocked. + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&TraceProviderImpl::StopIfForced, weak_factory_.GetWeakPtr()), + base::TimeDelta::FromSeconds(1)); +} + +void TraceProviderImpl::StopIfForced() { + if (!tracing_forced_) { + return; + } + base::trace_event::TraceLog::GetInstance()->SetDisabled(); + base::trace_event::TraceLog::GetInstance()->Flush( + base::Callback&, + bool)>()); +} + void TraceProviderImpl::SendChunk( const scoped_refptr& events_str, bool has_more_events) { DCHECK(recorder_); - recorder_->Record(mojo::String(events_str->data())); + // The string will be empty if an error eccured or there were no trace + // events. Empty string is not a valid chunk to record so skip in this case. + if (!events_str->data().empty()) { + recorder_->Record(mojo::String(events_str->data())); + } if (!has_more_events) { recorder_.reset(); } diff --git a/mojo/common/trace_provider_impl.h b/mojo/common/trace_provider_impl.h index 82735a57c8c..8d2124a988d 100644 --- a/mojo/common/trace_provider_impl.h +++ b/mojo/common/trace_provider_impl.h @@ -6,38 +6,42 @@ #define MOJO_COMMON_TRACE_PROVIDER_IMPL_H_ #include "base/memory/ref_counted_memory.h" +#include "base/memory/weak_ptr.h" +#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/services/tracing/public/interfaces/tracing.mojom.h" namespace mojo { class TraceProviderImpl : public tracing::TraceProvider { public: - explicit TraceProviderImpl(InterfaceRequest request); + TraceProviderImpl(); ~TraceProviderImpl() override; - // Set to true if base::trace_event::TraceLog is enabled externally to this - // class. If this is set to true this class will save the collector but not - // enable tracing when it receives a StartTracing message from the tracing - // service. - void set_tracing_already_started(bool tracing_already_started) { - tracing_already_started_ = tracing_already_started; - } + void Bind(InterfaceRequest request); + + // Enable tracing without waiting for an inbound connection. It will stop if + // no TraceRecorder is sent within a set time. + void ForceEnableTracing(); private: // tracing::TraceProvider implementation: void StartTracing(const String& categories, - tracing::TraceRecorderPtr collector) override; + tracing::TraceRecorderPtr recorder) override; void StopTracing() override; void SendChunk(const scoped_refptr& events_str, bool has_more_events); - bool tracing_already_started_; - tracing::TraceRecorderPtr recorder_; - StrongBinding binding_; + void DelayedStop(); + // Stop the collection of traces if no external connection asked for them yet. + void StopIfForced(); + Binding binding_; + bool tracing_forced_; + tracing::TraceRecorderPtr recorder_; + + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(TraceProviderImpl); }; diff --git a/mojo/common/tracing_impl.cc b/mojo/common/tracing_impl.cc index 2a6eac1e92f..a93e3d8b0d6 100644 --- a/mojo/common/tracing_impl.cc +++ b/mojo/common/tracing_impl.cc @@ -5,26 +5,31 @@ #include "mojo/common/tracing_impl.h" #include "base/trace_event/trace_event_impl.h" -#include "mojo/common/trace_provider_impl.h" #include "mojo/public/cpp/application/application_connection.h" #include "mojo/public/cpp/application/application_impl.h" namespace mojo { -TracingImpl::TracingImpl() { -} +TracingImpl::TracingImpl() {} -TracingImpl::~TracingImpl() { -} +TracingImpl::~TracingImpl() {} void TracingImpl::Initialize(ApplicationImpl* app) { ApplicationConnection* connection = app->ConnectToApplication("mojo:tracing"); connection->AddService(this); + +#ifdef NDEBUG + if (app->HasArg("--early-tracing")) { + provider_impl_.ForceEnableTracing(); + } +#else + provider_impl_.ForceEnableTracing(); +#endif } void TracingImpl::Create(ApplicationConnection* connection, InterfaceRequest request) { - new TraceProviderImpl(request.Pass()); + provider_impl_.Bind(request.Pass()); } } // namespace mojo diff --git a/mojo/common/tracing_impl.h b/mojo/common/tracing_impl.h index a996d5c4b28..c798b3e55f9 100644 --- a/mojo/common/tracing_impl.h +++ b/mojo/common/tracing_impl.h @@ -6,6 +6,7 @@ #define MOJO_COMMON_TRACING_IMPL_H_ #include "base/macros.h" +#include "mojo/common/trace_provider_impl.h" #include "mojo/public/cpp/application/interface_factory.h" #include "mojo/services/tracing/public/interfaces/tracing.mojom.h" @@ -27,6 +28,8 @@ class TracingImpl : public InterfaceFactory { void Create(ApplicationConnection* connection, InterfaceRequest request) override; + TraceProviderImpl provider_impl_; + DISALLOW_COPY_AND_ASSIGN(TracingImpl); }; diff --git a/mojo/converters/ozone_drm_gpu/BUILD.gn b/mojo/converters/ozone_drm_gpu/BUILD.gn new file mode 100644 index 00000000000..d7061adf026 --- /dev/null +++ b/mojo/converters/ozone_drm_gpu/BUILD.gn @@ -0,0 +1,19 @@ +# 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. + +source_set("ozone_drm_gpu") { + sources = [ + "ozone_drm_gpu_type_converters.cc", + "ozone_drm_gpu_type_converters.h", + ] + + deps = [ + "//base", + "//ui/ozone:ozone_common_message_types", + "//mojo/converters/geometry", + "//mojo/environment:chromium", + "//mojo/public/c/system", + "//mojo/services/ozone_drm_gpu/public/interfaces", + ] +} diff --git a/mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.cc b/mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.cc new file mode 100644 index 00000000000..4106cc2b0b0 --- /dev/null +++ b/mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.cc @@ -0,0 +1,108 @@ +// 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/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.h" + +#include "mojo/converters/geometry/geometry_type_converters.h" + +namespace mojo { + +// static +ui::DisplayMode_Params +TypeConverter::Convert( + const DisplayModePtr& in) { + auto out = ui::DisplayMode_Params(); + out.size = in->size.To(); + out.is_interlaced = in->is_interlaced; + out.refresh_rate = in->refresh_rate; + return out; +} + +// static +DisplayModePtr TypeConverter::Convert( + const ui::DisplayMode_Params& in) { + auto out = DisplayMode::New(); + out->size = Size::From(in.size); + out->is_interlaced = in.is_interlaced; + out->refresh_rate = in.refresh_rate; + return out.Pass(); +} + +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_NONE) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_NONE), + "Enum value mismatch"); +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_UNKNOWN) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_UNKNOWN), + "Enum value mismatch"); +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_INTERNAL) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_INTERNAL), + "Enum value mismatch"); +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_VGA) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_VGA), + "Enum value mismatch"); +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_HDMI) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_HDMI), + "Enum value mismatch"); +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_DVI) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_DVI), + "Enum value mismatch"); +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_DISPLAYPORT) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_DISPLAYPORT), + "Enum value mismatch"); +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_NETWORK) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_NETWORK), + "Enum value mismatch"); +static_assert(static_cast(ui::DISPLAY_CONNECTION_TYPE_LAST) == + static_cast(mojo::DisplayType::DISPLAY_TYPE_LAST), + "Enum value mismatch"); + +// static +ui::DisplaySnapshot_Params +TypeConverter::Convert( + const DisplaySnapshotPtr& in) { + auto out = ui::DisplaySnapshot_Params(); + out.display_id = in->display_id; + out.origin = in->origin.To(); + out.physical_size = in->physical_size.To(); + out.type = static_cast(in->type); + assert(out.type <= ui::DISPLAY_CONNECTION_TYPE_LAST); + for (size_t i = 0; i < in->modes.size(); ++i) { + out.modes.push_back(in->modes[i].To()); + } + out.has_current_mode = in->has_current_mode; + out.current_mode = in->current_mode.To(); + out.has_native_mode = in->has_native_mode; + out.native_mode = in->native_mode.To(); + out.product_id = in->product_id; + out.string_representation = in->string_representation; + return out; +} + +// static +DisplaySnapshotPtr +TypeConverter::Convert( + const ui::DisplaySnapshot_Params& in) { + auto out = DisplaySnapshot::New(); + out->display_id = in.display_id; + out->origin = Point::From(in.origin); + out->physical_size = Size::From(in.physical_size); + out->type = static_cast(in.type); + assert(out->type <= mojo::DisplayType::DISPLAY_TYPE_LAST); + auto modes = Array::New(in.modes.size()); + for (size_t i = 0; i < in.modes.size(); ++i) { + auto mode = DisplayMode::From(in.modes[i]); + modes[i] = mode.Pass(); + } + out->modes = modes.Pass(); + out->has_current_mode = in.has_current_mode; + out->current_mode = + DisplayMode::From(in.current_mode); + out->has_native_mode = in.has_native_mode; + out->native_mode = DisplayMode::From(in.native_mode); + out->product_id = in.product_id; + out->string_representation = in.string_representation; + return out.Pass(); +} + +} // namespace mojo diff --git a/mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.h b/mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.h new file mode 100644 index 00000000000..3bf0181689e --- /dev/null +++ b/mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.h @@ -0,0 +1,37 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_CONVERTERS_OZONE_DRM_GPU_OZONE_DRM_GPU_TYPE_CONVERTERS_H_ +#define MOJO_CONVERTERS_OZONE_DRM_GPU_OZONE_DRM_GPU_TYPE_CONVERTERS_H_ + +#include "base/memory/scoped_ptr.h" +#include "mojo/services/ozone_drm_gpu/public/interfaces/ozone_drm_gpu.mojom.h" +#include "ui/ozone/common/gpu/ozone_gpu_message_params.h" + +namespace mojo { + +// Types from ozone_drm_gpu.mojom +template <> +struct TypeConverter { + static ui::DisplayMode_Params Convert(const DisplayModePtr& in); +}; + +template <> +struct TypeConverter { + static DisplayModePtr Convert(const ui::DisplayMode_Params& in); +}; + +template <> +struct TypeConverter { + static ui::DisplaySnapshot_Params Convert(const DisplaySnapshotPtr& in); +}; + +template <> +struct TypeConverter { + static DisplaySnapshotPtr Convert(const ui::DisplaySnapshot_Params& in); +}; + +} // namespace mojo + +#endif // MOJO_CONVERTERS_OZONE_DRM_GPU_OZONE_DRM_GPU_TYPE_CONVERTERS_H_ diff --git a/mojo/dart/BUILD.gn b/mojo/dart/BUILD.gn index 88cc7fea62d..402d8cdd50e 100644 --- a/mojo/dart/BUILD.gn +++ b/mojo/dart/BUILD.gn @@ -4,10 +4,8 @@ group("dart") { deps = [ - "//mojo/dart/apptest", "//mojo/dart/dart_snapshotter($host_toolchain)", "//mojo/dart/http_load_test", - "//mojo/dart/mojom", "//mojo/dart/mojo_services", "//mojo/dart/observatory_test", ] diff --git a/mojo/dart/apptest/BUILD.gn b/mojo/dart/apptest/BUILD.gn deleted file mode 100644 index 36e25c4b395..00000000000 --- a/mojo/dart/apptest/BUILD.gn +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/dart/rules.gni") - -dart_pkg("apptest") { - libs = [ "lib/apptest.dart" ] - sources = [ - "pubspec.yaml", - ] - deps = [ - "//mojo/public/dart", - "//third_party/dart-pkg", - ] -} diff --git a/mojo/dart/apptest/lib/apptest.dart b/mojo/dart/apptest/lib/apptest.dart deleted file mode 100644 index 96c76f07a7b..00000000000 --- a/mojo/dart/apptest/lib/apptest.dart +++ /dev/null @@ -1,67 +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. - -library apptest; - -import 'dart:async'; - -import 'package:mojo/application.dart'; -import 'package:mojo/bindings.dart'; -import 'package:mojo/core.dart'; - -// Import and reexport the test package. -import 'package:test/test.dart'; -export 'package:test/test.dart'; - -typedef AppTestFunction(Application app, String url); - -// This class is an application that does nothing but tears down the connections -// between each test. -class _ConnectionToShellApplication extends Application { - final List _testFunctions; - - _ConnectionToShellApplication.fromHandle( - MojoHandle handle, this._testFunctions) - : super.fromHandle(handle); - - // Only run the test suite passed in once we have received an initialize() - // call from the shell. We need to first have a valid connection to the shell - // so that apptests can connect to other applications. - void initialize(List args, String url) { - group('dart_apptests', () { - setUp(testSetUp); - tearDown(testTearDown); - for (var testFunction in _testFunctions) { - testFunction(this, url); - } - }); - // Append a final test to terminate shell connection. - // TODO(johnmccutchan): Remove this once package 'test' supports a global - // tearDown callback. - test('TERMINATE SHELL CONNECTION', () async { - await close(); - assert(MojoHandle.reportLeakedHandles()); - }); - } - - void testSetUp() { - } - - void testTearDown() { - // Reset any connections between tests. - resetConnections(); - } -} - -/// The public interface to apptests. -/// -/// In a dart mojo application, [incomingHandle] is `args[0]`. [testFunctions] -/// is list of [AppTestFunction]. Each function will be passed the application -/// and url. -runAppTests(var incomingHandle, List testFunctions) { - var appHandle = new MojoHandle(incomingHandle); - var application = - new _ConnectionToShellApplication.fromHandle(appHandle, testFunctions); - /// [Application]'s [initialize] will be called. -} diff --git a/mojo/dart/apptest/pubspec.lock b/mojo/dart/apptest/pubspec.lock deleted file mode 100644 index f7f005cb5e0..00000000000 --- a/mojo/dart/apptest/pubspec.lock +++ /dev/null @@ -1,131 +0,0 @@ -# Generated by pub -# See http://pub.dartlang.org/doc/glossary.html#lockfile -packages: - analyzer: - description: analyzer - source: hosted - version: "0.25.2" - args: - description: args - source: hosted - version: "0.13.2" - async: - description: async - source: hosted - version: "1.2.0" - barback: - description: barback - source: hosted - version: "0.15.2+4" - charcode: - description: charcode - source: hosted - version: "1.1.0" - collection: - description: collection - source: hosted - version: "1.1.1" - crypto: - description: crypto - source: hosted - version: "0.9.0" - csslib: - description: csslib - source: hosted - version: "0.12.1" - glob: - description: glob - source: hosted - version: "1.0.5" - html: - description: html - source: hosted - version: "0.12.1+2" - http_multi_server: - description: http_multi_server - source: hosted - version: "1.3.2" - http_parser: - description: http_parser - source: hosted - version: "0.0.2+8" - logging: - description: logging - source: hosted - version: "0.11.1" - matcher: - description: matcher - source: hosted - version: "0.12.0+1" - mime: - description: mime - source: hosted - version: "0.9.3" - package_config: - description: package_config - source: hosted - version: "0.1.1" - path: - description: path - source: hosted - version: "1.3.6" - plugin: - description: plugin - source: hosted - version: "0.1.0" - pool: - description: pool - source: hosted - version: "1.1.0" - pub_semver: - description: pub_semver - source: hosted - version: "1.2.1" - shelf: - description: shelf - source: hosted - version: "0.6.2" - shelf_static: - description: shelf_static - source: hosted - version: "0.2.2" - shelf_web_socket: - description: shelf_web_socket - source: hosted - version: "0.0.1+2" - source_map_stack_trace: - description: source_map_stack_trace - source: hosted - version: "1.0.4" - source_maps: - description: source_maps - source: hosted - version: "0.10.1" - source_span: - description: source_span - source: hosted - version: "1.1.2" - stack_trace: - description: stack_trace - source: hosted - version: "1.3.4" - string_scanner: - description: string_scanner - source: hosted - version: "0.1.3+1" - test: - description: test - source: hosted - version: "0.12.3+7" - utf: - description: utf - source: hosted - version: "0.9.0+2" - watcher: - description: watcher - source: hosted - version: "0.9.7" - yaml: - description: yaml - source: hosted - version: "2.1.3" diff --git a/mojo/dart/apptest/pubspec.yaml b/mojo/dart/apptest/pubspec.yaml deleted file mode 100644 index c7f343a3b61..00000000000 --- a/mojo/dart/apptest/pubspec.yaml +++ /dev/null @@ -1,4 +0,0 @@ -name: apptest -version: 0.0.1 -dependencies: - test: ^0.12.3+7 diff --git a/mojo/dart/dart_snapshotter/main.cc b/mojo/dart/dart_snapshotter/main.cc index 48e5341af14..7fb52567fb6 100644 --- a/mojo/dart/dart_snapshotter/main.cc +++ b/mojo/dart/dart_snapshotter/main.cc @@ -61,8 +61,9 @@ int main(int argc, const char* argv[]) { } // Initialize mojo. - mojo::embedder::Init( - make_scoped_ptr(new mojo::embedder::SimplePlatformSupport())); + // TODO(vtl): Use make_unique when C++14 is available. + mojo::embedder::Init(std::unique_ptr( + new mojo::embedder::SimplePlatformSupport())); InitDartVM(); diff --git a/mojo/dart/embedder/BUILD.gn b/mojo/dart/embedder/BUILD.gn index d21d1ae0bd0..a141cb4f95d 100644 --- a/mojo/dart/embedder/BUILD.gn +++ b/mojo/dart/embedder/BUILD.gn @@ -17,6 +17,7 @@ source_set("dart_controller_no_snapshot") { "dart_controller.cc", "dart_controller.h", "io/internet_address.h", + "io/internet_address_posix.cc", "mojo_dart_state.h", "mojo_io_natives.cc", "mojo_io_natives.h", @@ -26,14 +27,6 @@ source_set("dart_controller_no_snapshot") { "vmservice.h", ] - if (is_linux) { - sources += [ "io/internet_address_linux.cc" ] - } - - if (is_android) { - sources += [ "io/internet_address_android.cc" ] - } - deps = [ ":dart_embedder_packages", ":generate_dart_embedder_patch_resources_cc", @@ -42,7 +35,6 @@ source_set("dart_controller_no_snapshot") { "//base:i18n", "//dart/runtime:libdart", "//dart/runtime/bin:libdart_embedder_noio", - "//third_party/dart-pkg", "//mojo/message_pump", "//mojo/public/c/system", "//mojo/public/cpp/system", @@ -104,30 +96,31 @@ dart_embedder_package("dart_embedder_package_network_service") { action_foreach("dart_embedder_package_sdk") { sources = [ - "//mojo/public/dart/lib/application.dart", - "//mojo/public/dart/lib/bindings.dart", - "//mojo/public/dart/lib/core.dart", - "//mojo/public/dart/lib/src/application.dart", - "//mojo/public/dart/lib/src/application_connection.dart", - "//mojo/public/dart/lib/src/buffer.dart", - "//mojo/public/dart/lib/src/codec.dart", - "//mojo/public/dart/lib/src/control_message.dart", - "//mojo/public/dart/lib/src/data_pipe.dart", - "//mojo/public/dart/lib/src/drain_data.dart", - "//mojo/public/dart/lib/src/event_stream.dart", - "//mojo/public/dart/lib/src/handle.dart", - "//mojo/public/dart/lib/src/message.dart", - "//mojo/public/dart/lib/src/message_pipe.dart", - "//mojo/public/dart/lib/src/proxy.dart", - "//mojo/public/dart/lib/src/struct.dart", - "//mojo/public/dart/lib/src/stub.dart", - "//mojo/public/dart/lib/src/types.dart", - "//mojo/public/dart/lib/src/union.dart", - "//mojo/public/dart/lib/src/utils.dart", - "//mojo/public/dart/sdk_ext/internal.dart", - "//mojo/public/dart/sdk_ext/src/handle_watcher.dart", - "//mojo/public/dart/sdk_ext/src/natives.dart", - "//mojo/public/dart/sdk_ext/src/timer_queue.dart", + "//mojo/public/dart/mojo/lib/application.dart", + "//mojo/public/dart/mojo/lib/bindings.dart", + "//mojo/public/dart/mojo/lib/core.dart", + "//mojo/public/dart/mojo/lib/src/application.dart", + "//mojo/public/dart/mojo/lib/src/application_connection.dart", + "//mojo/public/dart/mojo/lib/src/buffer.dart", + "//mojo/public/dart/mojo/lib/src/codec.dart", + "//mojo/public/dart/mojo/lib/src/control_message.dart", + "//mojo/public/dart/mojo/lib/src/data_pipe.dart", + "//mojo/public/dart/mojo/lib/src/drain_data.dart", + "//mojo/public/dart/mojo/lib/src/enum.dart", + "//mojo/public/dart/mojo/lib/src/event_stream.dart", + "//mojo/public/dart/mojo/lib/src/handle.dart", + "//mojo/public/dart/mojo/lib/src/message.dart", + "//mojo/public/dart/mojo/lib/src/message_pipe.dart", + "//mojo/public/dart/mojo/lib/src/proxy.dart", + "//mojo/public/dart/mojo/lib/src/struct.dart", + "//mojo/public/dart/mojo/lib/src/stub.dart", + "//mojo/public/dart/mojo/lib/src/types.dart", + "//mojo/public/dart/mojo/lib/src/union.dart", + "//mojo/public/dart/mojo/lib/src/utils.dart", + "//mojo/public/dart/mojo/sdk_ext/internal.dart", + "//mojo/public/dart/mojo/sdk_ext/src/handle_watcher.dart", + "//mojo/public/dart/mojo/sdk_ext/src/natives.dart", + "//mojo/public/dart/mojo/sdk_ext/src/timer_queue.dart", ] outputs = [ "$root_gen_dir/dart_embedder_packages/{{source_root_relative_dir}}/{{source_file_part}}", @@ -305,10 +298,10 @@ action("generate_snapshot_bin") { "//dart/runtime/tools/create_snapshot_bin.py", "//mojo/dart/embedder/builtin.dart", "//mojo/dart/embedder/packages.dart", - "//mojo/public/dart/sdk_ext/internal.dart", - "//mojo/public/dart/sdk_ext/src/handle_watcher.dart", - "//mojo/public/dart/sdk_ext/src/natives.dart", - "//mojo/public/dart/sdk_ext/src/timer_queue.dart", + "//mojo/public/dart/mojo/sdk_ext/internal.dart", + "//mojo/public/dart/mojo/sdk_ext/src/handle_watcher.dart", + "//mojo/public/dart/mojo/sdk_ext/src/natives.dart", + "//mojo/public/dart/mojo/sdk_ext/src/timer_queue.dart", ] vm_isolate_snapshot = "$target_gen_dir/vm_isolate_snapshot.bin" isolate_snapshot = "$target_gen_dir/isolate_snapshot.bin" @@ -322,17 +315,16 @@ action("generate_snapshot_bin") { "root_out_dir") script = "//dart/runtime/tools/create_snapshot_bin.py" builtin_path = rebase_path("//mojo/dart/embedder/builtin.dart") - internal_path = rebase_path("//mojo/public/dart/sdk_ext/internal.dart") + internal_path = rebase_path("//mojo/public/dart/mojo/sdk_ext/internal.dart") io_path = rebase_path("//dart/sdk/lib/io/io.dart") embedder_packages_path = rebase_path("//mojo/dart/embedder/packages.dart") embedder_package_application_path = rebase_path( - "$root_gen_dir/dart_embedder_packages/mojo/public/dart/lib/application.dart") + "$root_gen_dir/dart_embedder_packages/mojo/public/dart/mojo/lib/application.dart") embedder_package_bindings_path = rebase_path( - "$root_gen_dir/dart_embedder_packages/mojo/public/dart/lib/bindings.dart") - embedder_package_core_path = - rebase_path( - "$root_gen_dir/dart_embedder_packages/mojo/public/dart/lib/core.dart") + "$root_gen_dir/dart_embedder_packages/mojo/public/dart/mojo/lib/bindings.dart") + embedder_package_core_path = rebase_path( + "$root_gen_dir/dart_embedder_packages/mojo/public/dart/mojo/lib/core.dart") url_mappings_script = rebase_path("//mojo/dart/embedder/tools/dart_embedder_url_mappings.py") diff --git a/mojo/dart/embedder/builtin.cc b/mojo/dart/embedder/builtin.cc index a169e11d57e..94eb71cc7c8 100644 --- a/mojo/dart/embedder/builtin.cc +++ b/mojo/dart/embedder/builtin.cc @@ -135,7 +135,7 @@ Dart_Handle Builtin::GetLibrary(BuiltinLibraryId id) { return library; } -void Builtin::PrepareLibrary(BuiltinLibraryId id) { +Dart_Handle Builtin::PrepareLibrary(BuiltinLibraryId id) { Dart_Handle library = GetLibrary(id); DCHECK(!Dart_IsError(library)); if (builtin_libraries_[id].has_natives_) { @@ -151,6 +151,7 @@ void Builtin::PrepareLibrary(BuiltinLibraryId id) { builtin_libraries_[id].patch_url_, builtin_libraries_[id].patch_resources_); } + return library; } } // namespace dart diff --git a/mojo/dart/embedder/builtin.h b/mojo/dart/embedder/builtin.h index 2d297042cd9..66cd0aa3e85 100644 --- a/mojo/dart/embedder/builtin.h +++ b/mojo/dart/embedder/builtin.h @@ -40,7 +40,7 @@ class Builtin { // 1) Setting the native resolver (if any). // 2) Applying patch files (if any). // NOTE: This should only be called once for a library per isolate. - static void PrepareLibrary(BuiltinLibraryId id); + static Dart_Handle PrepareLibrary(BuiltinLibraryId id); static int64_t GetIntegerValue(Dart_Handle value_obj) { int64_t value = 0; diff --git a/mojo/dart/embedder/dart_controller.cc b/mojo/dart/embedder/dart_controller.cc index ad86db99421..81ca2179407 100644 --- a/mojo/dart/embedder/dart_controller.cc +++ b/mojo/dart/embedder/dart_controller.cc @@ -68,10 +68,12 @@ static Dart_Handle ResolveScriptUri(Dart_Handle builtin_lib, Dart_Handle uri) { dart_args); } -static Dart_Handle PrepareIsolateLibraries(const std::string& package_root, +static Dart_Handle PrepareBuiltinLibraries(const std::string& package_root, const std::string& script_uri) { // First ensure all required libraries are available. - Dart_Handle builtin_lib = Builtin::GetLibrary(Builtin::kBuiltinLibrary); + Dart_Handle builtin_lib = Builtin::PrepareLibrary(Builtin::kBuiltinLibrary); + Builtin::PrepareLibrary(Builtin::kMojoInternalLibrary); + Builtin::PrepareLibrary(Builtin::kDartMojoIoLibrary); Dart_Handle url = Dart_NewStringFromCString(kInternalLibURL); DART_CHECK_VALID(url); Dart_Handle internal_lib = Dart_LookupLibrary(url); @@ -274,6 +276,7 @@ Dart_Isolate DartController::CreateIsolateHelper( callbacks, script_uri, package_root); + CHECK(isolate_snapshot_buffer != nullptr); Dart_Isolate isolate = Dart_CreateIsolate(script_uri.c_str(), "main", isolate_snapshot_buffer, nullptr, isolate_data, error); @@ -317,25 +320,8 @@ Dart_Isolate DartController::CreateIsolateHelper( DART_CHECK_VALID(result); // Toggle checked mode. Dart_IsolateSetStrictCompilation(strict_compilation); - // Setup the native resolvers for the builtin libraries as they are not set - // up when the snapshot is read. - CHECK(isolate_snapshot_buffer != nullptr); - Builtin::PrepareLibrary(Builtin::kBuiltinLibrary); - Builtin::PrepareLibrary(Builtin::kMojoInternalLibrary); - Builtin::PrepareLibrary(Builtin::kDartMojoIoLibrary); - - // TODO(johnmccutchan): Remove? - if (!callbacks.create.is_null()) { - DCHECK(false); - callbacks.create.Run(script_uri.c_str(), - "main", - package_root.c_str(), - isolate_data, - error); - } - // Prepare builtin and its dependent libraries. - result = PrepareIsolateLibraries(package_root, script_uri); + result = PrepareBuiltinLibraries(package_root, script_uri); DART_CHECK_VALID(result); // The VM is creating the service isolate. @@ -436,9 +422,6 @@ void DartController::IsolateShutdownCallback(void* callback_data) { } auto isolate_data = MojoDartState::Cast(callback_data); - if (!isolate_data->callbacks().shutdown.is_null()) { - isolate_data->callbacks().shutdown.Run(callback_data); - } delete isolate_data; } @@ -690,8 +673,6 @@ bool DartController::Initialize( } bool DartController::RunDartScript(const DartControllerConfig& config) { - BlockForServiceIsolate(); - CHECK(service_isolate_running_); const bool strict = strict_compilation_ || config.strict_compilation; Dart_Isolate isolate = CreateIsolateHelper(config.application_data, strict, diff --git a/mojo/dart/embedder/io/internet_address_linux.cc b/mojo/dart/embedder/io/internet_address_linux.cc deleted file mode 100644 index b1440812b08..00000000000 --- a/mojo/dart/embedder/io/internet_address_linux.cc +++ /dev/null @@ -1,72 +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 "mojo/dart/embedder/io/internet_address.h" - -namespace mojo { -namespace dart { - -static void SetupSockAddr(sockaddr_storage* dest, - socklen_t* salen, - const RawAddr& addr, intptr_t addr_length) { - CHECK((addr_length == 4) || (addr_length == 16)); - if (addr_length == 4) { - dest->ss_family = AF_INET; - sockaddr_in* dest4 = reinterpret_cast(dest); - *salen = sizeof(*dest4); - memmove(&(dest4->sin_addr), &addr.bytes[0], addr_length); - } else { - dest->ss_family = AF_INET6; - sockaddr_in6* dest6 = reinterpret_cast(dest); - *salen = sizeof(*dest6); - memmove(&(dest6->sin6_addr), &addr.bytes[0], addr_length); - } -} - -bool InternetAddress::Parse(int type, const char* address, RawAddr* addr) { - memset(addr, 0, IPV6_RAW_ADDR_LENGTH); - int result; - if (type == InternetAddress::TYPE_IPV4) { - struct sockaddr_in in; - result = inet_pton(AF_INET, address, &in.sin_addr); - memmove(addr, &in.sin_addr, IPV4_RAW_ADDR_LENGTH); - } else { - CHECK(type == InternetAddress::TYPE_IPV6); - sockaddr_in6 in6; - result = inet_pton(AF_INET6, address, &in6.sin6_addr); - memmove(addr, &in6.sin6_addr, IPV6_RAW_ADDR_LENGTH); - } - return result == 1; -} - -bool InternetAddress::Reverse(const RawAddr& addr, intptr_t addr_length, - char* host, intptr_t host_len, - intptr_t* error_code, - const char** error_description) { - CHECK(host_len >= NI_MAXHOST); - sockaddr_storage sock_addr; - socklen_t salen; - SetupSockAddr(&sock_addr, &salen, addr, addr_length); - int status = getnameinfo(reinterpret_cast(&sock_addr), - salen, - host, - host_len, - NULL, - 0, - NI_NAMEREQD); - *error_code = status; - if (status != 0) { - CHECK(*error_description == NULL); - *error_description = gai_strerror(status); - return false; - } - return true; -} - -} // namespace dart -} // namespace mojo diff --git a/mojo/dart/embedder/io/internet_address_patch.dart b/mojo/dart/embedder/io/internet_address_patch.dart index 28e2ed7a935..2f910210e42 100644 --- a/mojo/dart/embedder/io/internet_address_patch.dart +++ b/mojo/dart/embedder/io/internet_address_patch.dart @@ -183,16 +183,16 @@ class _InternetAddress implements InternetAddress { static Uint8List _parse(String address) native "InternetAddress_Parse"; } -int _internetAddressTypeToAddressFamily(InternetAddressType type) { +NetAddressFamily _internetAddressTypeToAddressFamily(InternetAddressType type) { if (type == null) { - return NetAddressFamily_UNSPECIFIED; + return NetAddressFamily.UNSPECIFIED; } if (type == InternetAddressType.IP_V4) { - return NetAddressFamily_IPV4; + return NetAddressFamily.IPV4; } else if (type == InternetAddressType.IP_V6) { - return NetAddressFamily_IPV6; + return NetAddressFamily.IPV6; } - return NetAddressFamily_UNSPECIFIED; + return NetAddressFamily.UNSPECIFIED; } class _MojoInternetAddress { diff --git a/mojo/dart/embedder/io/internet_address_android.cc b/mojo/dart/embedder/io/internet_address_posix.cc similarity index 82% rename from mojo/dart/embedder/io/internet_address_android.cc rename to mojo/dart/embedder/io/internet_address_posix.cc index b1440812b08..74b78fedc7c 100644 --- a/mojo/dart/embedder/io/internet_address_android.cc +++ b/mojo/dart/embedder/io/internet_address_posix.cc @@ -13,7 +13,8 @@ namespace dart { static void SetupSockAddr(sockaddr_storage* dest, socklen_t* salen, - const RawAddr& addr, intptr_t addr_length) { + const RawAddr& addr, + intptr_t addr_length) { CHECK((addr_length == 4) || (addr_length == 16)); if (addr_length == 4) { dest->ss_family = AF_INET; @@ -44,21 +45,18 @@ bool InternetAddress::Parse(int type, const char* address, RawAddr* addr) { return result == 1; } -bool InternetAddress::Reverse(const RawAddr& addr, intptr_t addr_length, - char* host, intptr_t host_len, +bool InternetAddress::Reverse(const RawAddr& addr, + intptr_t addr_length, + char* host, + intptr_t host_len, intptr_t* error_code, const char** error_description) { CHECK(host_len >= NI_MAXHOST); sockaddr_storage sock_addr; socklen_t salen; SetupSockAddr(&sock_addr, &salen, addr, addr_length); - int status = getnameinfo(reinterpret_cast(&sock_addr), - salen, - host, - host_len, - NULL, - 0, - NI_NAMEREQD); + int status = getnameinfo(reinterpret_cast(&sock_addr), salen, host, + host_len, NULL, 0, NI_NAMEREQD); *error_code = status; if (status != 0) { CHECK(*error_description == NULL); diff --git a/mojo/dart/embedder/io/mojo_patch.dart b/mojo/dart/embedder/io/mojo_patch.dart index d49c6c4a685..3fc05e519fc 100644 --- a/mojo/dart/embedder/io/mojo_patch.dart +++ b/mojo/dart/embedder/io/mojo_patch.dart @@ -111,9 +111,9 @@ class _NetworkServiceCodec { return null; } var address; - if (netAddress.family == NetAddressFamily_IPV4) { + if (netAddress.family == NetAddressFamily.IPV4) { address = netAddress.ipv4.addr; - } else if (netAddress.family == NetAddressFamily_IPV6) { + } else if (netAddress.family == NetAddressFamily.IPV6) { address = netAddress.ipv6.addr; } else { return null; @@ -127,9 +127,9 @@ class _NetworkServiceCodec { if (netAddress == null) { return null; } - if (netAddress.family == NetAddressFamily_IPV4) { + if (netAddress.family == NetAddressFamily.IPV4) { return netAddress.ipv4.port; - } else if (netAddress.family == NetAddressFamily_IPV6) { + } else if (netAddress.family == NetAddressFamily.IPV6) { return netAddress.ipv6.port; } else { return null; @@ -145,7 +145,7 @@ class _NetworkServiceCodec { var netAddress = new NetAddress(); var rawAddress = internetAddress.rawAddress; if (rawAddress.length == 4) { - netAddress.family = NetAddressFamily_IPV4; + netAddress.family = NetAddressFamily.IPV4; netAddress.ipv4 = new NetAddressIPv4(); netAddress.ipv4.addr = new List.from(rawAddress, growable: false); if (port != null) { @@ -153,7 +153,7 @@ class _NetworkServiceCodec { } } else { assert(rawAddress.length == 16); - netAddress.family = NetAddressFamily_IPV6; + netAddress.family = NetAddressFamily.IPV6; netAddress.ipv6 = new NetAddressIPv6(); netAddress.ipv6.addr = new List.from(rawAddress, growable: false); if (port != null) { @@ -169,7 +169,7 @@ class _NetworkService { /// Return a [NetAddress] for localhost:port. static NetAddress _localhostIpv4([int port = 0]) { var addr = new NetAddress(); - addr.family = NetAddressFamily_IPV4; + addr.family = NetAddressFamily.IPV4; addr.ipv4 = new NetAddressIPv4(); addr.ipv4.addr = [127, 0, 0, 1]; addr.ipv4.port = port; @@ -179,7 +179,7 @@ class _NetworkService { /// Return a [NetAddress] for localhost:port. static NetAddress _localHostIpv6([int port = 0]) { var addr = new NetAddress(); - addr.family = NetAddressFamily_IPV6; + addr.family = NetAddressFamily.IPV6; addr.ipv6 = new NetAddressIPv6(); addr.ipv6.addr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; addr.ipv6.port = port; diff --git a/mojo/dart/embedder/mojo_dart_state.h b/mojo/dart/embedder/mojo_dart_state.h index a0792eec75b..1429c34bab4 100644 --- a/mojo/dart/embedder/mojo_dart_state.h +++ b/mojo/dart/embedder/mojo_dart_state.h @@ -20,9 +20,6 @@ namespace mojo { namespace dart { struct IsolateCallbacks { - base::Callback - create; - base::Callback shutdown; base::Callback exception; }; diff --git a/mojo/dart/mojo_services/BUILD.gn b/mojo/dart/mojo_services/BUILD.gn index bda57f897ca..b0c67fee8c6 100644 --- a/mojo/dart/mojo_services/BUILD.gn +++ b/mojo/dart/mojo_services/BUILD.gn @@ -13,6 +13,7 @@ dart_pkg("mojo_services") { ] deps = [ + "//mojo/public/dart", "//mojo/services", ] } diff --git a/mojo/dart/mojo_services/CHANGELOG.md b/mojo/dart/mojo_services/CHANGELOG.md index 5e4f9d7a624..9b163db0bb6 100644 --- a/mojo/dart/mojo_services/CHANGELOG.md +++ b/mojo/dart/mojo_services/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.1.0 + + - 0 changes: https://github.com/domokit/mojo/compare/86d3dc4...86d3dc4 + + Declare dependency on mojom and mojo 0.1.x + +## 0.0.25 + + - 187 changes: https://github.com/domokit/mojo/compare/e5cc610...3139c74 + ## 0.0.23 ## 0.0.22 diff --git a/mojo/dart/mojo_services/pubspec.yaml b/mojo/dart/mojo_services/pubspec.yaml index 03b8a867b2c..598dd292ba1 100644 --- a/mojo/dart/mojo_services/pubspec.yaml +++ b/mojo/dart/mojo_services/pubspec.yaml @@ -1,7 +1,8 @@ author: Chromium Authors dependencies: - mojo: any + mojo: '>=0.1.0 <0.2.0' + mojom: '>=0.1.0 <0.2.0' description: Generated bindings for mojo services homepage: https://github.com/domokit/mojo name: mojo_services -version: 0.0.23 +version: 0.1.0 diff --git a/mojo/dart/mojom/BUILD.gn b/mojo/dart/mojom/BUILD.gn deleted file mode 100644 index 70ff7da59f4..00000000000 --- a/mojo/dart/mojom/BUILD.gn +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/dart/rules.gni") - -dart_pkg("mojom") { - libs = [ "lib/generate.dart" ] - sources = [ - "CHANGELOG.md", - "README.md", - "lib/src/options.dart", - "lib/src/utils.dart", - "pubspec.yaml", - ] - deps = [ - "//third_party/dart-pkg", - ] -} diff --git a/mojo/dart/mojom/CHANGELOG.md b/mojo/dart/mojom/CHANGELOG.md deleted file mode 100644 index 808a3310b3f..00000000000 --- a/mojo/dart/mojom/CHANGELOG.md +++ /dev/null @@ -1,51 +0,0 @@ -## 0.0.23 - -## 0.0.22 - - - 59 changes: https://github.com/domokit/mojo/compare/c73419d...35de44e - -## 0.0.18 - - - 89 changes: https://github.com/domokit/mojo/compare/0fd4d06...c3119f6 - -## 0.0.17 - - - 18 changes: https://github.com/domokit/mojo/compare/e7433cf...8879bfd - -## 0.0.16 - - - 27 changes: https://github.com/domokit/mojo/compare/e028733...e7433cf - -## 0.0.15 - - - 6 changes: https://github.com/domokit/mojo/compare/4df2d39...e028733 - -## 0.0.14 - - - 138 changes: https://github.com/domokit/mojo/compare/850ac24...cf84c48 - -## 0.0.13 - - - 70 changes: https://github.com/domokit/mojo/compare/889091e...136e0d4 - -## 0.0.12 - - - 29 changes: https://github.com/domokit/mojo/compare/e25e3e2...432ce45 - -## 0.0.11 - - - 12 changes: https://github.com/domokit/mojo/compare/7ba339b...fb1b726 - -## 0.0.10 - - - 23 changes: https://github.com/domokit/mojo/compare/1b7bcee...be9dad7 - -## 0.0.8 - - Update version to match sky package. 0.0.6 and 0.0.7 were skipped. - -## 0.0.5 - - First update after dart dev summit to match mojo and sky packages. - -## 0.0.1 - - Initial placeholder package for generated mojom bindings. - diff --git a/mojo/dart/mojom/README.md b/mojo/dart/mojom/README.md deleted file mode 100644 index eb63e4e0d2a..00000000000 --- a/mojo/dart/mojom/README.md +++ /dev/null @@ -1,41 +0,0 @@ -mojom -==== - -This package is a placeholder for generated mojom bindings. It contains a script -lib/generate.dart. - -This script generates Mojo bindings for a Dart package. Dart packages will be -populated according to the DartPackage annotations in .mojom files. Any .mojom -files that don't have an annotation will have their bindings generated into a -local copy of the 'mojom' package. Annotations specifying the host package will -cause generation into the host package's lib/ directory. For every other -DartPackage annotation, the bindings will be generated into the named package, -either into the global package cache if a package of that name has already been -fetched, or into a local directory created under the current package's packages/ -directory. - -Generated Mojo bindings in other pub packages should be installed into this -package by saying the following after `pub get`: - -``` -$ dart -p packages packages/mojom/generate.dart -``` -If desired, additional directories holding .mojom.dart files can be specified; -their contents will be installed to this package as well: - -``` -$ dart -p packages packages/mojom/generate.dart -a -``` - -Full options: - -``` -$ dart packages/mojom/generate.dart [-p package-root] - [-a additional-dirs] - [-m mojo-sdk] - [-g] # Generate from .mojom files - [-d] # Download from .mojoms files - [-i] # Ignore duplicates - [-v] # verbose - [-f] # Fake (dry) run -``` diff --git a/mojo/dart/mojom/lib/README.md b/mojo/dart/mojom/lib/README.md deleted file mode 100644 index fc326c1f5d4..00000000000 --- a/mojo/dart/mojom/lib/README.md +++ /dev/null @@ -1,5 +0,0 @@ -mojom -==== - -mojom.dart files will appear here after running the generate script (see the -top-level documentation for this package). diff --git a/mojo/dart/mojom/lib/generate.dart b/mojo/dart/mojom/lib/generate.dart deleted file mode 100644 index 5a78ba87fca..00000000000 --- a/mojo/dart/mojom/lib/generate.dart +++ /dev/null @@ -1,249 +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. - -/// This script generates Mojo bindings for a Dart package. See README.md for -/// details. - -library generate; - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:args/args.dart' as args; -import 'package:path/path.dart' as path; - -part 'src/options.dart'; -part 'src/utils.dart'; - -bool errorOnDuplicate; -bool verbose; -bool dryRun; -Map duplicateDetection; - -/// Searches for .mojom.dart files under [mojomDirectory] and copies them to -/// [data.currentPackage]. -copyAction(PackageIterData data, Directory mojomDirectory) async { - await for (var mojom in mojomDirectory.list(recursive: true)) { - if (mojom is! File) continue; - if (!isMojomDart(mojom.path)) continue; - if (verbose) print("Found $mojom"); - - final relative = path.relative(mojom.path, from: mojomDirectory.path); - final dest = path.join(data.currentPackage.path, relative); - final destDirectory = new Directory(path.dirname(dest)); - - if (errorOnDuplicate && duplicateDetection.containsKey(dest)) { - String original = duplicateDetection[dest]; - throw new GenerationError( - 'Conflict: Both ${original} and ${mojom.path} supply ${dest}'); - } - duplicateDetection[dest] = mojom.path; - - if (verbose || dryRun) { - print('Copying $mojom to $dest'); - } - - if (!dryRun) { - final File source = new File(mojom.path); - if (verbose) print("Ensuring $destDirectory exists"); - await destDirectory.create(recursive: true); - source.copy(dest); - } - } -} - -/// Searches for .mojom files under [mojomDirectory], generates .mojom.dart -/// files for them, and copies them to the 'mojom' package. -generateAction(GenerateIterData data, Directory mojomDirectory) async { - final packageRoot = data.currentPackage.parent; - await for (var mojom in mojomDirectory.list(recursive: true)) { - if (mojom is! File) continue; - if (!isMojom(mojom.path)) continue; - if (verbose) print("Found $mojom"); - - final script = path.join( - data.mojoSdk.path, 'tools', 'bindings', 'mojom_bindings_generator.py'); - final sdkInc = path.normalize(path.join(data.mojoSdk.path, '..', '..')); - final outputDir = await data.currentPackage.createTemp(); - final output = outputDir.path; - final arguments = [ - '--use_bundled_pylibs', - '-g', - 'dart', - '-o', - output, - // TODO(zra): Are other include paths needed? - '-I', - sdkInc, - '-I', - mojomDirectory.path, - mojom.path - ]; - - if (verbose || dryRun) { - print('Generating $mojom'); - print('$script ${arguments.join(" ")}'); - } - if (!dryRun) { - final result = await Process.run(script, arguments); - if (result.exitCode != 0) { - throw new GenerationError("$script failed:\n${result.stderr}"); - } - - // Generated .mojom.dart is under $output/dart-pkg/$PACKAGE/lib/$X - // Move $X to $PACKAGE_ROOT/$PACKAGE/$X - final generatedDirName = path.join(output, 'dart-pkg'); - final generatedDir = new Directory(generatedDirName); - await for (var genpack in generatedDir.list()) { - if (genpack is! Directory) continue; - var libDir = new Directory(path.join(genpack.path, 'lib')); - var name = path.relative(genpack.path, from: generatedDirName); - var copyData = new GenerateIterData(data.mojoSdk); - copyData.currentPackage = - new Directory(path.join(packageRoot.path, name)); - await copyAction(copyData, libDir); - } - - await outputDir.delete(recursive: true); - } - } -} - -/// In each package, look for a file named .mojoms. Populate a package's -/// mojom directory with the downloaded mojoms, creating the directory if -/// needed. The .mojoms file should be formatted as follows: -/// ''' -/// root: https://www.example.com/mojoms -/// path/to/some/mojom1.mojom -/// path/to/some/other/mojom2.mojom -/// -/// root: https://www.example-two.com/mojoms -/// path/to/example/two/mojom1.mojom -/// ... -/// -/// Lines beginning with '#' are ignored. -downloadAction(GenerateIterData _, Directory packageDirectory) async { - var mojomsPath = path.join(packageDirectory.path, '.mojoms'); - var mojomsFile = new File(mojomsPath); - if (!await mojomsFile.exists()) return; - if (verbose) print("Found .mojoms file: $mojomsPath"); - - Directory mojomsDir; - var httpClient = new HttpClient(); - int repoCount = 0; - int mojomCount = 0; - String repoRoot; - for (String line in await mojomsFile.readAsLines()) { - line = line.trim(); - if (line.isEmpty || line.startsWith('#')) continue; - - if (line.startsWith('root:')) { - if ((mojomsDir != null) && (mojomCount == 0)) { - throw new DownloadError("root with no mojoms: $repoRoot"); - } - mojomCount = 0; - var rootWords = line.split(" "); - if (rootWords.length != 2) { - throw new DownloadError("Malformed root: $line"); - } - repoRoot = rootWords[1]; - if (verbose) print("Found repo root: $repoRoot"); - if (!repoRoot.startsWith('http://') && !repoRoot.startsWith('https://')) { - throw new DownloadError( - 'Mojom repo "root" should be an http or https URL: $line'); - } - mojomsDir = new Directory(path.join( - packageDirectory.parent.path, 'mojm.repo.$repoCount', 'mojom')); - await mojomsDir.create(recursive: true); - repoCount++; - } else { - if (mojomsDir == null) { - throw new DownloadError('Malformed .mojoms file: $mojomsPath'); - } - String url = "$repoRoot/$line"; - if (verbose) print("Found $url"); - String fileString = await getUrl(httpClient, url); - if (verbose) print("Downloaded $url"); - String filePath = path.join(mojomsDir.path, line); - var file = new File(filePath); - if (!await file.exists()) { - await file.create(recursive: true); - await file.writeAsString(fileString); - if (verbose) print("Wrote $filePath"); - } - mojomCount++; - } - } -} - -/// The "mojom" entry in [packages] is a symbolic link to the mojom package in -/// the global pub cache directory. Because we might need to write package -/// specific .mojom.dart files into the mojom package, we need to make a local -/// copy of it. -copyMojomPackage(Directory packages) async { - var link = new Link(path.join(packages.path, "mojom")); - if (!await link.exists()) { - // If the "mojom" entry in packages is not a symbolic link, then do nothing. - return; - } - - var realpath = await link.resolveSymbolicLinks(); - var realDir = new Directory(realpath); - var mojomDir = new Directory(path.join(packages.path, "mojom")); - - await link.delete(); - await mojomDir.create(); - await for (var file in realDir.list(recursive: true)) { - if (file is File) { - var relative = path.relative(file.path, from: realDir.path); - var destPath = path.join(mojomDir.path, relative); - var destDir = new Directory(path.dirname(destPath)); - await destDir.create(recursive: true); - await file.copy(path.join(mojomDir.path, relative)); - } - } -} - -main(List arguments) async { - var options = await parseArguments(arguments); - duplicateDetection = new Map(); - errorOnDuplicate = options.errorOnDuplicate; - verbose = options.verbose; - dryRun = options.dryRun; - - // mojoms without a DartPackage annotation, and pregenerated mojoms from - // [options.additionalDirs] will go into the mojom package, so we make a local - // copy of it so we don't pollute the global pub cache. - // - // TODO(zra): Fail if a mojom has no DartPackage annotation, and remove the - // need for [options.additionalDirs]. - if (!dryRun) { - await copyMojomPackage(options.packages); - } - - // Download .mojom files. These will be picked up by the generation step - // below. - if (options.download) { - await packageDirIter(options.packages, null, downloadAction); - } - - // Generate mojom files. - if (options.generate) { - await mojomDirIter(options.packages, new GenerateIterData(options.mojoSdk), - generateAction); - } - - // TODO(zra): As mentioned above, this should go away. - // Copy pregenerated files from specified external directories into the - // mojom package. - final data = new GenerateIterData(options.mojoSdk); - data.currentPackage = options.mojomPackage; - for (var mojomDir in options.additionalDirs) { - await copyAction(data, mojomDir); - if (options.generate) { - await generateAction(data, mojomDir); - } - } -} diff --git a/mojo/dart/mojom/lib/src/options.dart b/mojo/dart/mojom/lib/src/options.dart deleted file mode 100644 index 63ff6834170..00000000000 --- a/mojo/dart/mojom/lib/src/options.dart +++ /dev/null @@ -1,123 +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. - -part of generate; - -class GenerateOptions { - final Directory packages; - final Directory mojoSdk; - final Directory mojomPackage; - final List additionalDirs; - final bool download; - final bool generate; - final bool errorOnDuplicate; - final bool verbose; - final bool dryRun; - GenerateOptions(this.packages, this.mojomPackage, this.mojoSdk, - this.additionalDirs, this.download, this.generate, this.errorOnDuplicate, - this.verbose, this.dryRun); -} - -/// Ensures that the directories in [additionalPaths] are absolute and exist, -/// and creates Directories for them, which are returned. -Future> validateAdditionalDirs(Iterable additionalPaths) async { - var additionalDirs = []; - for (var mojomPath in additionalPaths) { - final mojomDir = new Directory(mojomPath); - if (!mojomDir.isAbsolute) { - throw new CommandLineError( - "All --additional-mojom-dir parameters must be absolute paths."); - } - if (!(await mojomDir.exists())) { - throw new CommandLineError( - "The additional mojom directory $mojomDir must exist"); - } - additionalDirs.add(mojomDir); - } - return additionalDirs; -} - -Future parseArguments(List arguments) async { - final parser = new args.ArgParser() - ..addOption('additional-mojom-dir', - abbr: 'a', - allowMultiple: true, - help: 'Absolute path to an additional directory containing mojom.dart' - 'files to put in the mojom package. May be specified multiple times.') - ..addFlag('download', - abbr: 'd', - defaultsTo: false, - help: 'Searches packages for a .mojoms file, and downloads .mojom files' - 'as speficied in that file. Implies -g.') - ..addFlag('fake', - abbr: 'f', - defaultsTo: false, - help: 'Print the operations that would have been run, but' - 'do not run anything.') - ..addFlag('generate', - abbr: 'g', - defaultsTo: false, - help: 'Generate Dart bindings for .mojom files.') - ..addFlag('ignore-duplicates', - abbr: 'i', - defaultsTo: false, - help: 'Ignore generation of a .mojom.dart file into the same location ' - 'as an existing file. By default this is an error') - ..addOption('mojo-sdk', - abbr: 'm', - defaultsTo: Platform.environment['MOJO_SDK'], - help: 'Absolute path to the Mojo SDK, which can also be specified ' - 'with the environment variable MOJO_SDK.') - ..addOption('package-root', - abbr: 'p', - defaultsTo: path.join(Directory.current.path, 'packages'), - help: 'An absolute path to an application\'s package root') - ..addFlag('verbose', abbr: 'v', defaultsTo: false); - final result = parser.parse(arguments); - bool verbose = result['verbose']; - bool dryRun = result['fake']; - bool errorOnDuplicate = !result['ignore-duplicates']; - - final packages = new Directory(result['package-root']); - if (!packages.isAbsolute) { - throw new CommandLineError( - "The --package-root parameter must be an absolute path."); - } - if (verbose) print("packages = $packages"); - if (!(await packages.exists())) { - throw new CommandLineError("The packages directory $packages must exist"); - } - - final mojomPackage = new Directory(path.join(packages.path, 'mojom')); - if (verbose) print("mojom package = $mojomPackage"); - if (!(await mojomPackage.exists())) { - throw new CommandLineError( - "The mojom package directory $mojomPackage must exist"); - } - - final download = result['download']; - final generate = result['generate'] || download; - var mojoSdk = null; - if (generate) { - final mojoSdkPath = result['mojo-sdk']; - if (mojoSdkPath == null) { - throw new CommandLineError( - "The Mojo SDK directory must be specified with the --mojo-sdk flag or" - "the MOJO_SDK environment variable."); - } - mojoSdk = new Directory(mojoSdkPath); - if (verbose) print("Mojo SDK = $mojoSdk"); - if (!(await mojoSdk.exists())) { - throw new CommandLineError( - "The specified Mojo SDK directory $mojoSdk must exist."); - } - } - - final additionalDirs = - await validateAdditionalDirs(result['additional-mojom-dir']); - if (verbose) print("additional_mojom_dirs = $additionalDirs"); - - return new GenerateOptions(packages, mojomPackage, mojoSdk, additionalDirs, - download, generate, errorOnDuplicate, verbose, dryRun); -} diff --git a/mojo/dart/mojom/lib/src/utils.dart b/mojo/dart/mojom/lib/src/utils.dart deleted file mode 100644 index c62c1bab785..00000000000 --- a/mojo/dart/mojom/lib/src/utils.dart +++ /dev/null @@ -1,100 +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. - -part of generate; - -bool isMojomDart(String path) => path.endsWith('.mojom.dart'); -bool isMojom(String path) => path.endsWith('.mojom'); - -/// An Error for problems on the command line. -class CommandLineError extends Error { - final _msg; - CommandLineError(this._msg); - toString() => _msg; -} - -/// An Error for failures of the bindings generation script. -class GenerationError extends Error { - final _msg; - GenerationError(this._msg); - toString() => _msg; -} - -/// An Error for failing to download a .mojom file. -class DownloadError extends Error { - final _msg; - DownloadError(this._msg); - toString() => _msg; -} - -/// The base type of data passed to actions for [mojomDirIter]. -class PackageIterData { - Directory currentPackage; - PackageIterData(this.currentPackage); -} - -/// Data for [mojomDirIter] that includes the path to the Mojo SDK for bindings -/// generation. -class GenerateIterData extends PackageIterData { - final Directory _mojoSdk; - GenerateIterData(this._mojoSdk) : super(null); - Directory get mojoSdk => _mojoSdk; -} - -/// The type of action performed by [mojomDirIter]. -typedef Future MojomAction(PackageIterData data, Directory mojomDirectory); - -packageDirIter( - Directory packages, PackageIterData data, MojomAction action) async { - await for (var package in packages.list()) { - if (package is Directory) { - if (data != null) { - data.currentPackage = package; - } - await action(data, package); - } - } -} - -/// Iterates over mojom directories of Dart packages, taking some action for -/// each. -/// -/// For each 'mojom' subdirectory of each subdirectory in [packages], runs -/// [action] on the subdirectory passing along [data] to [action]. -mojomDirIter( - Directory packages, PackageIterData data, MojomAction action) async { - await packageDirIter(packages, data, (d, p) async { - if (verbose) print("package = $p"); - final mojomDirectory = new Directory(path.join(p.path, 'mojom')); - if (verbose) print("looking for = $mojomDirectory"); - if (await mojomDirectory.exists()) { - await action(d, mojomDirectory); - } else if (verbose) { - print("$mojomDirectory not found"); - } - }); -} - -/// Download file at [url] using [httpClient]. Throw a [DownloadError] if -/// the file is not successfully downloaded. -Future getUrl(HttpClient httpClient, String url) async { - try { - var request = await httpClient.getUrl(Uri.parse(url)); - var response = await request.close(); - if (response.statusCode >= 400) { - var msg = "Failed to download $url\nCode ${response.statusCode}"; - if (response.reasonPhrase != null) { - msg = "$msg: ${response.reasonPhrase}"; - } - throw new DownloadError(msg); - } - var fileString = new StringBuffer(); - await for (String contents in response.transform(UTF8.decoder)) { - fileString.write(contents); - } - return fileString.toString(); - } catch (e) { - throw new DownloadError("$e"); - } -} diff --git a/mojo/dart/mojom/pubspec.lock b/mojo/dart/mojom/pubspec.lock deleted file mode 100644 index d8d42b86859..00000000000 --- a/mojo/dart/mojom/pubspec.lock +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by pub -# See http://pub.dartlang.org/doc/glossary.html#lockfile -packages: - args: - description: args - source: hosted - version: "0.13.0" - path: - description: path - source: hosted - version: "1.3.5" - stack_trace: - description: stack_trace - source: hosted - version: "1.3.3" - unittest: - description: unittest - source: hosted - version: "0.11.6+1" diff --git a/mojo/dart/mojom/pubspec.yaml b/mojo/dart/mojom/pubspec.yaml deleted file mode 100644 index c2d1b5a6472..00000000000 --- a/mojo/dart/mojom/pubspec.yaml +++ /dev/null @@ -1,12 +0,0 @@ -author: Chromium Authors -dependencies: - args: '>=0.13.0 <1.0.0' - path: '>=1.3.5 <2.0.0' -description: Placeholder for mojom bindings. -dev_dependencies: - unittest: '>=0.11.5+4 <0.12.0' -environment: - sdk: '>=1.9.0 <2.0.0' -homepage: https://github.com/domokit/mojo -name: mojom -version: 0.0.23 diff --git a/mojo/dart/mojom/test/generate_test.dart b/mojo/dart/mojom/test/generate_test.dart deleted file mode 100644 index 0ddc862a9ee..00000000000 --- a/mojo/dart/mojom/test/generate_test.dart +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:io'; - -import 'package:mojom/generate.dart' as generate; -import 'package:path/path.dart' as path; -import 'package:unittest/unittest.dart'; - -final mojomContents = ''' -[DartPackage="generated"] -module generated; - -struct Transform { - // Row major order. - array matrix; -}; -'''; - -final dldMojomContents1 = ''' -[DartPackage="downloaded"] -module downloaded; - -struct Downloaded1 { - int32 status; -}; -'''; - -final dldMojomContents2 = ''' -[DartPackage="downloaded"] -module downloaded; - -struct Downloaded2 { - int32 status; -}; -'''; - -main() async { - String mojoSdk; - if (Platform.environment['MOJO_SDK'] != null) { - mojoSdk = Platform.environment['MOJO_SDK']; - } else { - mojoSdk = path.normalize(path.join( - path.dirname(Platform.script.path), '..', '..', '..', 'public')); - } - if (!await new Directory(mojoSdk).exists()) { - fail("Could not find the Mojo SDK"); - } - - final scriptPath = path.dirname(Platform.script.path); - final testPackagePath = path.join(scriptPath, 'test_packages'); - final testMojomPath = path.join(testPackagePath, 'mojom'); - final testMojomLinkPath = path.join(scriptPath, 'mojom_link_target'); - final testMojomLibPath = path.join(testMojomLinkPath, 'lib'); - final fakeGeneratePath = path.join(testMojomLibPath, 'generate.dart'); - - final pregenPath = path.join(testPackagePath, 'pregen'); - final pregenFilePath = - path.join(pregenPath, 'mojom', 'pregen', 'pregen.mojom.dart'); - - final additionalRootPath = path.join(scriptPath, 'additional_dir'); - final additionalPath = - path.join(additionalRootPath, 'additional', 'additional.mojom.dart'); - - final generatedPackagePath = path.join(testPackagePath, 'generated'); - - final downloadedPackagePath = path.join(testPackagePath, 'downloaded'); - final dotMojomsPath = path.join(downloadedPackagePath, '.mojoms'); - - setUp(() async { - await new File(pregenFilePath).create(recursive: true); - await new File(additionalPath).create(recursive: true); - await new File(fakeGeneratePath).create(recursive: true); - await new Link(testMojomPath).create(testMojomLibPath); - - final generatedMojomFile = new File(path.join(testPackagePath, 'generated', - 'mojom', 'generated', 'public', 'interfaces', 'generated.mojom')); - await generatedMojomFile.create(recursive: true); - await generatedMojomFile.writeAsString(mojomContents); - - await new Directory(downloadedPackagePath).create(recursive: true); - }); - - tearDown(() async { - await new Directory(additionalRootPath).delete(recursive: true); - await new Directory(testPackagePath).delete(recursive: true); - await new Directory(testMojomLinkPath).delete(recursive: true); - }); - - group('No Download', () { - test('No-op', () async { - await generate.main(['-p', testPackagePath, '-m', mojoSdk]); - final mojomPackageDir = new Directory(testMojomPath); - final generateFile = new File(path.join(testMojomPath, 'generate.dart')); - expect(await mojomPackageDir.exists(), isTrue); - expect(await generateFile.exists(), isTrue); - }); - - test('Additional', () async { - await generate.main( - ['-p', testPackagePath, '-m', mojoSdk, '-a', additionalRootPath]); - final mojomPackageDir = new Directory(testMojomPath); - final generateFile = new File(path.join(testMojomPath, 'generate.dart')); - final additionalFile = new File( - path.join(testMojomPath, 'additional', 'additional.mojom.dart')); - expect(await mojomPackageDir.exists(), isTrue); - expect(await generateFile.exists(), isTrue); - expect(await additionalFile.exists(), isTrue); - }); - - test('Generated', () async { - await generate.main(['-g', '-p', testPackagePath, '-m', mojoSdk]); - final generatedFile = new File( - path.join(generatedPackagePath, 'generated', 'generated.mojom.dart')); - expect(await generatedFile.exists(), isTrue); - }); - - test('All', () async { - await generate.main([ - '-g', - '-p', - testPackagePath, - '-m', - mojoSdk, - '-a', - additionalRootPath - ]); - - final additionalFile = new File( - path.join(testMojomPath, 'additional', 'additional.mojom.dart')); - expect(await additionalFile.exists(), isTrue); - - final generatedFile = new File( - path.join(generatedPackagePath, 'generated', 'generated.mojom.dart')); - expect(await generatedFile.exists(), isTrue); - }); - }); - - group('Download', () { - var httpServer; - setUp(() async { - httpServer = await HttpServer.bind("localhost", 0); - httpServer.listen((HttpRequest request) { - String path = request.uri.path; - if (path.endsWith('path/to/mojom/download_one.mojom')) { - request.response.write(dldMojomContents1); - } else if (path.endsWith('path/to/mojom/download_two.mojom')) { - request.response.write(dldMojomContents2); - } else { - request.response.statusCode = HttpStatus.NOT_FOUND; - } - request.response.close(); - }); - }); - - tearDown(() async { - await httpServer.close(); - httpServer = null; - }); - - test('simple', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString( - "root: http://localhost:${httpServer.port}\n" - "path/to/mojom/download_one.mojom\n"); - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - final downloadedFile = new File(path.join( - downloadedPackagePath, 'downloaded', 'download_one.mojom.dart')); - expect(await downloadedFile.exists(), isTrue); - await mojomsFile.delete(); - }); - - test('two files', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString( - "root: http://localhost:${httpServer.port}\n" - "path/to/mojom/download_one.mojom\n" - "path/to/mojom/download_two.mojom\n"); - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - final downloaded1File = new File(path.join( - downloadedPackagePath, 'downloaded', 'download_one.mojom.dart')); - expect(await downloaded1File.exists(), isTrue); - final downloaded2File = new File(path.join( - downloadedPackagePath, 'downloaded', 'download_two.mojom.dart')); - expect(await downloaded2File.exists(), isTrue); - await mojomsFile.delete(); - }); - - test('two roots', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString( - "root: http://localhost:${httpServer.port}\n" - "path/to/mojom/download_one.mojom\n" - "root: http://localhost:${httpServer.port}\n" - "path/to/mojom/download_two.mojom\n"); - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - final downloaded1File = new File(path.join( - downloadedPackagePath, 'downloaded', 'download_one.mojom.dart')); - expect(await downloaded1File.exists(), isTrue); - final downloaded2File = new File(path.join( - downloadedPackagePath, 'downloaded', 'download_two.mojom.dart')); - expect(await downloaded2File.exists(), isTrue); - await mojomsFile.delete(); - }); - - test('simple-comment', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString("# Comments are allowed\n" - " root: http://localhost:${httpServer.port}\n\n\n\n" - " # Here too\n" - " path/to/mojom/download_one.mojom\n" - "# And here\n"); - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - final downloadedFile = new File(path.join( - downloadedPackagePath, 'downloaded', 'download_one.mojom.dart')); - expect(await downloadedFile.exists(), isTrue); - await mojomsFile.delete(); - }); - - test('404', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString( - "root: http://localhost:${httpServer.port}\n" - "blah\n"); - var fail = false; - try { - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - } on generate.DownloadError { - fail = true; - } - expect(fail, isTrue); - await mojomsFile.delete(); - }); - }); - - group('Failures', () { - test('Bad Package Root', () async { - final dummyPackageRoot = path.join(scriptPath, 'dummyPackageRoot'); - var fail = false; - try { - await generate.main(['-p', dummyPackageRoot, '-m', mojoSdk]); - } on generate.CommandLineError { - fail = true; - } - expect(fail, isTrue); - }); - - test('Non-absolute PackageRoot', () async { - final dummyPackageRoot = 'dummyPackageRoot'; - var fail = false; - try { - await generate.main(['-p', dummyPackageRoot, '-m', mojoSdk]); - } on generate.CommandLineError { - fail = true; - } - expect(fail, isTrue); - }); - - test('Bad Additional Dir', () async { - final dummyAdditional = path.join(scriptPath, 'dummyAdditional'); - var fail = false; - try { - await generate.main( - ['-a', dummyAdditional, '-p', testPackagePath, '-m', mojoSdk]); - } on generate.CommandLineError { - fail = true; - } - expect(fail, isTrue); - }); - - test('Non-absolute Additional Dir', () async { - final dummyAdditional = 'dummyAdditional'; - var fail = false; - try { - await generate.main( - ['-a', dummyAdditional, '-p', testPackagePath, '-m', mojoSdk]); - } on generate.CommandLineError { - fail = true; - } - expect(fail, isTrue); - }); - - test('No Mojo Package', () async { - final dummyPackageRoot = path.join(scriptPath, 'dummyPackageRoot'); - final dummyPackageDir = new Directory(dummyPackageRoot); - await dummyPackageDir.create(recursive: true); - - var fail = false; - try { - await generate.main(['-p', dummyPackageRoot, '-m', mojoSdk]); - } on generate.CommandLineError { - fail = true; - } - await dummyPackageDir.delete(recursive: true); - expect(fail, isTrue); - }); - - test('Bad Mojo SDK', () async { - final dummySdk = path.join(scriptPath, 'dummySdk'); - var fail = false; - try { - await generate.main(['-g', '-m', dummySdk, '-p', testPackagePath]); - } on generate.CommandLineError { - fail = true; - } - expect(fail, isTrue); - }); - - test('Download No Server', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString("root: http://localhots\n" - "path/to/mojom/download_one.mojom\n"); - var fail = false; - try { - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - } on generate.DownloadError { - fail = true; - } - expect(fail, isTrue); - await mojomsFile.delete(); - }); - - test('.mojoms no root', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString("path/to/mojom/download_one.mojom\n"); - var fail = false; - try { - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - } on generate.DownloadError { - fail = true; - } - expect(fail, isTrue); - await mojomsFile.delete(); - }); - - test('.mojoms blank root', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString("root:\n" - "path/to/mojom/download_one.mojom\n"); - var fail = false; - try { - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - } on generate.DownloadError { - fail = true; - } - expect(fail, isTrue); - await mojomsFile.delete(); - }); - - test('.mojoms root malformed', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString("root: gobledygook\n" - "path/to/mojom/download_one.mojom\n"); - var fail = false; - try { - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - } on generate.DownloadError { - fail = true; - } - expect(fail, isTrue); - await mojomsFile.delete(); - }); - - test('.mojoms root without mojom', () async { - final mojomsFile = new File(dotMojomsPath); - await mojomsFile.create(recursive: true); - await mojomsFile.writeAsString("root: http://localhost\n" - "root: http://localhost\n" - "path/to/mojom/download_one.mojom\n"); - var fail = false; - try { - await generate.main(['-p', testPackagePath, '-m', mojoSdk, '-d', '-g']); - } on generate.DownloadError { - fail = true; - } - expect(fail, isTrue); - await mojomsFile.delete(); - }); - }); -} diff --git a/mojo/dart/test/bindings_generation_test.dart b/mojo/dart/test/bindings_generation_test.dart index d69801225a7..807b2059645 100644 --- a/mojo/dart/test/bindings_generation_test.dart +++ b/mojo/dart/test/bindings_generation_test.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'dart:isolate'; import 'dart:typed_data'; +import 'dart:convert'; import 'package:_testing/expect.dart'; import 'package:mojo/bindings.dart' as bindings; @@ -13,6 +14,7 @@ import 'package:mojom/sample/sample_interfaces.mojom.dart' as sample; import 'package:mojom/mojo/test/test_structs.mojom.dart' as structs; import 'package:mojom/mojo/test/test_unions.mojom.dart' as unions; import 'package:mojom/mojo/test/rect.mojom.dart' as rect; +import 'package:mojom/mojo/test/serialization_test_structs.mojom.dart' as serialization; class ProviderImpl implements sample.Provider { sample.ProviderStub _stub; @@ -30,7 +32,7 @@ class ProviderImpl implements sample.Provider { echoMessagePipeHanlde(core.MojoHandle a, Function responseFactory) => new Future.value(responseFactory(a)); - echoEnum(int a, Function responseFactory) => + echoEnum(sample.Enum a, Function responseFactory) => new Future.value(responseFactory(a)); } @@ -107,9 +109,30 @@ testSerializeArrayValueTypes() { Expect.listEquals(arrayValues.f5, arrayValues2.f5); } +testSerializeToJSON() { + var r = new rect.Rect() + ..x = 1 + ..y = 2 + ..width = 3 + ..height = 4; + + var encodedRect = JSON.encode(r); + var goldenEncoding = "{\"x\":1,\"y\":2,\"width\":3,\"height\":4}"; + Expect.equals(goldenEncoding, encodedRect); +} + +testSerializeHandleToJSON() { + var s = new serialization.Struct2(); + + Expect.throws(() => JSON.encode(s), + (e) => e.cause is bindings.MojoCodecError); +} + testSerializeStructs() { testSerializeNamedRegion(); testSerializeArrayValueTypes(); + testSerializeToJSON(); + testSerializeHandleToJSON(); } testSerializePodUnions() { @@ -227,6 +250,18 @@ testUnions() { testUnionsToString(); } +testSerializeEnum() { + var constants = new structs.ScopedConstants(); + constants.f4 = structs.ScopedConstantsEType.E0; + var message = messageOfStruct(constants); + var constants2 = structs.ScopedConstants.deserialize(message.payload); + Expect.equals(constants.f4.value, constants2.f4.value); +} + +testEnums() { + testSerializeEnum(); +} + void closingProviderIsolate(core.MojoMessagePipeEndpoint endpoint) { var provider = new ProviderImpl(endpoint); provider._stub.close(); @@ -246,6 +281,7 @@ Future runOnClosedTest() { main() async { testSerializeStructs(); testUnions(); + testEnums(); await testCallResponse(); await testAwaitCallResponse(); await runOnClosedTest(); diff --git a/mojo/dart/test/control_messages_test.dart b/mojo/dart/test/control_messages_test.dart index c64f0e30266..e7e3a7c2d91 100644 --- a/mojo/dart/test/control_messages_test.dart +++ b/mojo/dart/test/control_messages_test.dart @@ -21,11 +21,11 @@ class IntegerAccessorImpl implements sample.IntegerAccessor { Future getInteger([Function responseFactory = null]) { - return new Future.value(responseFactory(_value, sample.Enum_VALUE)); + return new Future.value(responseFactory(_value, sample.Enum.VALUE)); } - void setInteger(int data, int type) { - Expect.equals(sample.Enum_VALUE, type); + void setInteger(int data, sample.Enum type) { + Expect.equals(sample.Enum.VALUE.value, type.value); // Update data. _value = data; } @@ -81,7 +81,7 @@ testRequireVersionDisconnect() async { proxy.requireVersion(maxVersion); Expect.equals(maxVersion, proxy.version); // Set integer. - proxy.ptr.setInteger(34, sample.Enum_VALUE); + proxy.ptr.setInteger(34, sample.Enum.VALUE); // Get integer. var response = await proxy.ptr.getInteger(); Expect.equals(34, response.data); diff --git a/mojo/dart/test/validation_test.dart b/mojo/dart/test/validation_test.dart index 20ba8b4bf9d..874ecaa162a 100644 --- a/mojo/dart/test/validation_test.dart +++ b/mojo/dart/test/validation_test.dart @@ -60,6 +60,8 @@ class ConformanceTestInterfaceImpl implements ConformanceTestInterface { if (param2 != null) param2.close(immediate: true); _complete(); } + method14(UnionA param0) => _complete(); + method15(StructH param0) => _complete(); Future close({bool immediate: false}) => _stub.close(immediate: immediate); } diff --git a/mojo/data_pipe_utils/data_pipe_file_utils.cc b/mojo/data_pipe_utils/data_pipe_file_utils.cc index e37c8dfe9ae..08b24a3bf9b 100644 --- a/mojo/data_pipe_utils/data_pipe_file_utils.cc +++ b/mojo/data_pipe_utils/data_pipe_file_utils.cc @@ -315,18 +315,24 @@ size_t CopyToFileHelper(FILE* fp, const void* buffer, uint32_t num_bytes) { } // namespace -bool BlockingCopyToFile(ScopedDataPipeConsumerHandle source, - const base::FilePath& destination) { - TRACE_EVENT1("data_pipe_utils", "BlockingCopyToFile", "dest", - destination.MaybeAsASCII()); - base::ScopedFILE fp(base::OpenFile(destination, "wb")); +base::ScopedFILE BlockingCopyToTempFile(ScopedDataPipeConsumerHandle source) { + base::FilePath path; + base::ScopedFILE fp(CreateAndOpenTemporaryFile(&path)); if (!fp) { - LOG(ERROR) << "OpenFile('" << destination.value() - << "'failed in BlockingCopyToFile"; - return false; + LOG(ERROR) << "CreateAndOpenTemporaryFile failed in" + << "BlockingCopyToTempFile"; + return nullptr; } - return BlockingCopyHelper(source.Pass(), - base::Bind(&CopyToFileHelper, fp.get())); + if (unlink(path.value().c_str())) { + LOG(ERROR) << "Failed to unlink temporary file"; + return nullptr; + } + if (!BlockingCopyHelper(source.Pass(), + base::Bind(&CopyToFileHelper, fp.get()))) { + LOG(ERROR) << "Could not copy source to temporary file"; + return nullptr; + } + return fp; } void CopyToFile(ScopedDataPipeConsumerHandle source, diff --git a/mojo/data_pipe_utils/data_pipe_utils.h b/mojo/data_pipe_utils/data_pipe_utils.h index 289fe12a8ed..48c59d9a79a 100644 --- a/mojo/data_pipe_utils/data_pipe_utils.h +++ b/mojo/data_pipe_utils/data_pipe_utils.h @@ -8,6 +8,7 @@ #include #include "base/callback_forward.h" +#include "base/files/scoped_file.h" #include "base/threading/platform_thread.h" #include "mojo/public/cpp/system/core.h" @@ -42,11 +43,11 @@ bool BlockingCopyToString(ScopedDataPipeConsumerHandle source, bool BlockingCopyFromString(const std::string& source, const ScopedDataPipeProducerHandle& destination); -// Synchronously copies data from source to the destination file returning true -// on success and false on error. In case of an error, |destination| holds the -// data that could be read from the source before the error occured. -bool BlockingCopyToFile(ScopedDataPipeConsumerHandle source, - const base::FilePath& destination); +// Synchronously copies source data to a temporary file, returning a file +// pointer on success and NULL on error. The temporary file is unlinked +// immediately so that it is only accessible by file pointer (and removed once +// closed or the creating process dies). +base::ScopedFILE BlockingCopyToTempFile(ScopedDataPipeConsumerHandle source); } // namespace common } // namespace mojo diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn index b3144f099b0..fccf099837f 100644 --- a/mojo/edk/embedder/BUILD.gn +++ b/mojo/edk/embedder/BUILD.gn @@ -26,10 +26,7 @@ mojo_edk_source_set("embedder") { "test_embedder.h", ] - defines = [ - "MOJO_SYSTEM_IMPL_IMPLEMENTATION", - "MOJO_SYSTEM_IMPLEMENTATION", - ] + defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ] mojo_edk_configs = [ "mojo/edk/system:system_config" ] @@ -45,6 +42,8 @@ mojo_edk_source_set("embedder") { deps = [ "//base", ] + + mojo_edk_deps = [ "mojo/edk/util" ] } mojo_edk_source_set("platform") { @@ -52,20 +51,21 @@ mojo_edk_source_set("platform") { # mojo_system_impl component. visibility = [ ":embedder" ] - mojo_edk_visibility = [ "mojo/edk/system" ] + mojo_edk_visibility = [ + "mojo/edk/system", + "mojo/edk/system:test_utils", + ] sources = [ "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.h", "platform_support.h", @@ -74,13 +74,10 @@ mojo_edk_source_set("platform") { "simple_platform_shared_buffer.h", "simple_platform_shared_buffer_android.cc", "simple_platform_shared_buffer_posix.cc", - "simple_platform_shared_buffer_win.cc", "simple_platform_support.cc", "simple_platform_support.h", ] - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - mojo_edk_configs = [ "mojo/edk/system:system_config" ] mojo_sdk_public_deps = [ "mojo/public/cpp/system" ] @@ -92,6 +89,8 @@ mojo_edk_source_set("platform") { if (is_android) { deps += [ "//third_party/ashmem" ] } + + mojo_edk_deps = [ "mojo/edk/util" ] } mojo_edk_source_set("delegates") { @@ -109,8 +108,6 @@ mojo_edk_source_set("delegates") { "slave_process_delegate.h", ] - defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - mojo_edk_configs = [ "mojo/edk/system:system_config" ] mojo_sdk_public_deps = [ "mojo/public/cpp/system" ] @@ -136,5 +133,6 @@ mojo_edk_source_set("embedder_unittests") { "mojo/edk/test:test_support", "mojo/edk/system", "mojo/edk/system:test_utils", + "mojo/edk/util", ] } diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index 523b368d07e..9ed0f408ad9 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc @@ -9,7 +9,6 @@ #include "base/bind_helpers.h" #include "base/location.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/task_runner.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/master_process_delegate.h" @@ -82,7 +81,7 @@ Configuration* GetConfiguration() { return system::GetMutableConfiguration(); } -void Init(scoped_ptr platform_support) { +void Init(std::unique_ptr platform_support) { DCHECK(platform_support); DCHECK(!internal::g_platform_support); @@ -264,7 +263,7 @@ ScopedMessagePipeHandle CreateChannel( internal::g_ipc_support->channel_manager(); system::ChannelId channel_id = MakeChannelId(); - scoped_ptr channel_info(new ChannelInfo(channel_id)); + std::unique_ptr channel_info(new ChannelInfo(channel_id)); scoped_refptr dispatcher = channel_manager->CreateChannel( channel_id, platform_handle.Pass(), diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h index 2514c7c72de..47aea32dc07 100644 --- a/mojo/edk/embedder/embedder.h +++ b/mojo/edk/embedder/embedder.h @@ -5,17 +5,16 @@ #ifndef MOJO_EDK_EMBEDDER_EMBEDDER_H_ #define MOJO_EDK_EMBEDDER_EMBEDDER_H_ +#include #include #include "base/callback.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/task_runner.h" #include "mojo/edk/embedder/channel_info_forward.h" #include "mojo/edk/embedder/process_type.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/embedder/slave_info.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/message_pipe.h" namespace mojo { @@ -33,11 +32,11 @@ class ProcessDelegate; // Returns the global configuration. In general, you should not need to change // the configuration, but if you do you must do it before calling |Init()|. -MOJO_SYSTEM_IMPL_EXPORT Configuration* GetConfiguration(); +Configuration* GetConfiguration(); // Must be called first, or just after setting configuration parameters, to // initialize the (global, singleton) system. -MOJO_SYSTEM_IMPL_EXPORT void Init(scoped_ptr platform_support); +void Init(std::unique_ptr platform_support); // Basic functions ------------------------------------------------------------- @@ -47,26 +46,24 @@ MOJO_SYSTEM_IMPL_EXPORT void Init(scoped_ptr platform_support); // called exactly once, when |handle| satisfies a signal in |signals| or it // becomes known that it will never do so. |callback| will be executed on an // arbitrary thread, so it must not call any Mojo system or embedder functions. -MOJO_SYSTEM_IMPL_EXPORT MojoResult -AsyncWait(MojoHandle handle, - MojoHandleSignals signals, - const base::Callback& callback); +MojoResult AsyncWait(MojoHandle handle, + MojoHandleSignals signals, + const base::Callback& callback); // Creates a |MojoHandle| that wraps the given |PlatformHandle| (taking // ownership of it). This |MojoHandle| can then, e.g., be passed through message // pipes. Note: This takes ownership (and thus closes) |platform_handle| even on // 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); +MojoResult CreatePlatformHandleWrapper( + ScopedPlatformHandle platform_handle, + MojoHandle* platform_handle_wrapper_handle); // Retrieves the |PlatformHandle| that was wrapped into a |MojoHandle| (using // |CreatePlatformHandleWrapper()| above). Note that the |MojoHandle| must still // be closed separately. -MOJO_SYSTEM_IMPL_EXPORT MojoResult -PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, - ScopedPlatformHandle* platform_handle); +MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, + ScopedPlatformHandle* platform_handle); // Initialialization/shutdown for interprocess communication (IPC) ------------- @@ -90,23 +87,22 @@ PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, // |platform_handle| should be connected to the handle passed to // |ConnectToSlave()| (in the master process). For other processes, // |platform_handle| is ignored (and should not be valid). -MOJO_SYSTEM_IMPL_EXPORT void InitIPCSupport( - ProcessType process_type, - scoped_refptr delegate_thread_task_runner, - ProcessDelegate* process_delegate, - scoped_refptr io_thread_task_runner, - ScopedPlatformHandle platform_handle); +void InitIPCSupport(ProcessType process_type, + scoped_refptr delegate_thread_task_runner, + ProcessDelegate* process_delegate, + scoped_refptr io_thread_task_runner, + ScopedPlatformHandle platform_handle); // Shuts down the subsystem initialized by |InitIPCSupport()|. This must be // called on the I/O thread (given to |InitIPCSupport()|). This completes // synchronously and does not result in a call to the process delegate's // |OnShutdownComplete()|. -MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupportOnIOThread(); +void ShutdownIPCSupportOnIOThread(); // Like |ShutdownIPCSupportOnIOThread()|, but may be called from any thread, // signalling shutdown completion via the process delegate's // |OnShutdownComplete()|. -MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupport(); +void ShutdownIPCSupport(); // Interprocess communication (IPC) functions ---------------------------------- @@ -131,13 +127,13 @@ MOJO_SYSTEM_IMPL_EXPORT void ShutdownIPCSupport(); // |ChannelInfo*| is valid. // // TODO(vtl): The API is a little crazy with respect to the |ChannelInfo*|. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -ConnectToSlave(SlaveInfo slave_info, - ScopedPlatformHandle platform_handle, - const base::Closure& did_connect_to_slave_callback, - scoped_refptr did_connect_to_slave_runner, - std::string* platform_connection_id, - ChannelInfo** channel_info); +ScopedMessagePipeHandle ConnectToSlave( + SlaveInfo slave_info, + ScopedPlatformHandle platform_handle, + const base::Closure& did_connect_to_slave_callback, + scoped_refptr did_connect_to_slave_runner, + std::string* platform_connection_id, + ChannelInfo** channel_info); // Called in a slave process to connect it to the IPC system. (This should only // be called in a process initialized (using |InitIPCSupport()|) with process @@ -150,11 +146,11 @@ ConnectToSlave(SlaveInfo slave_info, // |did_connect_to_master_runner| are analagous to in |ConnectToSlave()|. // // TODO(vtl): The API is a little crazy with respect to the |ChannelInfo*|. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -ConnectToMaster(const std::string& platform_connection_id, - const base::Closure& did_connect_to_master_callback, - scoped_refptr did_connect_to_master_runner, - ChannelInfo** channel_info); +ScopedMessagePipeHandle ConnectToMaster( + const std::string& platform_connection_id, + const base::Closure& did_connect_to_master_callback, + scoped_refptr did_connect_to_master_runner, + ChannelInfo** channel_info); // A "channel" is a connection on top of an OS "pipe", on top of which Mojo // message pipes (etc.) can be multiplexed. It must "live" on some I/O thread. @@ -168,9 +164,8 @@ ConnectToMaster(const std::string& platform_connection_id, // // Both creation functions have a |platform_handle| argument, which should be an // OS-dependent handle to one side of a suitable bidirectional OS "pipe" (e.g., -// a file descriptor to a socket on POSIX, a handle to a named pipe on Windows); -// this "pipe" should be connected and ready for operation (e.g., to be written -// to or read from). +// a file descriptor to a Unix domain socket); this "pipe" should be connected +// and ready for operation (e.g., to be written to or read from). // // Both (synchronously) return a handle to the bootstrap message pipe on the // channel that was (or is to be) created, or |MOJO_HANDLE_INVALID| on error @@ -196,9 +191,9 @@ ConnectToMaster(const std::string& platform_connection_id, // should be a handle to a connected OS "pipe". Eventually (even on failure), // the "out" value |*channel_info| should be passed to |DestoryChannel()| to // tear down the channel. Returns a handle to the bootstrap message pipe. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle -CreateChannelOnIOThread(ScopedPlatformHandle platform_handle, - ChannelInfo** channel_info); +ScopedMessagePipeHandle CreateChannelOnIOThread( + ScopedPlatformHandle platform_handle, + ChannelInfo** channel_info); // Creates a channel asynchronously; may be called from any thread. // |platform_handle| should be a handle to a connected OS "pipe". @@ -210,7 +205,7 @@ CreateChannelOnIOThread(ScopedPlatformHandle platform_handle, // // Note: This should only be used to establish a channel with a process of type // |ProcessType::NONE|. This function may be removed in the future. -MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle CreateChannel( +ScopedMessagePipeHandle CreateChannel( ScopedPlatformHandle platform_handle, const base::Callback& did_create_channel_callback, scoped_refptr did_create_channel_runner); @@ -219,23 +214,21 @@ MOJO_SYSTEM_IMPL_EXPORT ScopedMessagePipeHandle CreateChannel( // |ConnectToSlave()|, |CreateChannel()|, or |CreateChannelOnIOThread()|; must // be called from the channel's I'O thread. Completes synchronously (and posts // no tasks). -MOJO_SYSTEM_IMPL_EXPORT void DestroyChannelOnIOThread( - ChannelInfo* channel_info); +void DestroyChannelOnIOThread(ChannelInfo* channel_info); // Like |DestroyChannelOnIOThread()|, but asynchronous and may be called from // any thread. The callback will be called using |did_destroy_channel_runner| // if that is non-null, or otherwise it will be called on the "channel thread". // The "channel thread" must remain alive and continue to process tasks until // the callback has been executed. -MOJO_SYSTEM_IMPL_EXPORT void DestroyChannel( - ChannelInfo* channel_info, - const base::Closure& did_destroy_channel_callback, - scoped_refptr did_destroy_channel_runner); +void DestroyChannel(ChannelInfo* channel_info, + const base::Closure& did_destroy_channel_callback, + scoped_refptr did_destroy_channel_runner); // Inform the channel that it will soon be destroyed (doing so is optional). // This may be called from any thread, but the caller must ensure that this is // called before |DestroyChannel()|. -MOJO_SYSTEM_IMPL_EXPORT void WillDestroyChannelSoon(ChannelInfo* channel_info); +void WillDestroyChannelSoon(ChannelInfo* channel_info); } // namespace embedder } // namespace mojo diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc index e9735b1aa53..ef231cee117 100644 --- a/mojo/edk/embedder/embedder_unittest.cc +++ b/mojo/edk/embedder/embedder_unittest.cc @@ -6,13 +6,14 @@ #include +#include + #include "base/bind.h" #include "base/command_line.h" #include "base/location.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/synchronization/waitable_event.h" -#include "base/test/test_io_thread.h" #include "base/test/test_timeouts.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/test_embedder.h" @@ -20,6 +21,7 @@ #include "mojo/edk/system/test_utils.h" #include "mojo/edk/test/multiprocess_test_helper.h" #include "mojo/edk/test/scoped_ipc_support.h" +#include "mojo/edk/test/test_io_thread.h" #include "mojo/public/c/system/core.h" #include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/macros.h" @@ -27,6 +29,9 @@ #include "testing/gtest/include/gtest/gtest.h" namespace mojo { + +using test::TestIOThread; + namespace embedder { namespace { @@ -39,6 +44,8 @@ const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | const char kConnectionIdFlag[] = "test-connection-id"; +void DoNothing() {} + class ScopedTestChannel { public: // Creates a channel, which lives on the I/O thread given to @@ -50,7 +57,8 @@ class ScopedTestChannel { explicit ScopedTestChannel(ScopedPlatformHandle platform_handle) : bootstrap_message_pipe_(MOJO_HANDLE_INVALID), event_(true, false), // Manual reset. - channel_info_(nullptr) { + channel_info_(nullptr), + wait_on_shutdown_(true) { bootstrap_message_pipe_ = CreateChannel(platform_handle.Pass(), base::Bind(&ScopedTestChannel::DidCreateChannel, @@ -67,11 +75,15 @@ class ScopedTestChannel { // |WaitForChannelCreationCompletion()| must be called before destruction. CHECK(event_.IsSignaled()); event_.Reset(); - DestroyChannel(channel_info_, - base::Bind(&ScopedTestChannel::DidDestroyChannel, - base::Unretained(this)), - nullptr); - event_.Wait(); + if (wait_on_shutdown_) { + DestroyChannel(channel_info_, + base::Bind(&ScopedTestChannel::DidDestroyChannel, + base::Unretained(this)), + nullptr); + event_.Wait(); + } else { + DestroyChannel(channel_info_, base::Bind(&DoNothing), nullptr); + } } // Waits for channel creation to be completed. @@ -83,6 +95,10 @@ class ScopedTestChannel { // that it's not null. const ChannelInfo* channel_info() const { return channel_info_; } + // Don't wait for the channel shutdown to finish on destruction. Used to + // exercise races. + void NoWaitOnShutdown() { wait_on_shutdown_ = false; } + private: void DidCreateChannel(ChannelInfo* channel_info) { CHECK(channel_info); @@ -107,16 +123,19 @@ class ScopedTestChannel { // Valid after channel creation completion until destruction. ChannelInfo* channel_info_; + // Whether the destructor should wait until the channel is destroyed. + bool wait_on_shutdown_; + MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedTestChannel); }; class EmbedderTest : public testing::Test { public: - EmbedderTest() : test_io_thread_(base::TestIOThread::kAutoStart) {} + EmbedderTest() : test_io_thread_(TestIOThread::kAutoStart) {} ~EmbedderTest() override {} protected: - base::TestIOThread& test_io_thread() { return test_io_thread_; } + TestIOThread& test_io_thread() { return test_io_thread_; } scoped_refptr test_io_task_runner() { return test_io_thread_.task_runner(); } @@ -126,7 +145,7 @@ class EmbedderTest : public testing::Test { void TearDown() override { EXPECT_TRUE(test::Shutdown()); } - base::TestIOThread test_io_thread_; + TestIOThread test_io_thread_; MOJO_DISALLOW_COPY_AND_ASSIGN(EmbedderTest); }; @@ -431,12 +450,34 @@ TEST_F(EmbedderTest, MAYBE_MultiprocessMasterSlave) { base::Bind(&DestroyChannelOnIOThread, base::Unretained(channel_info))); } +TEST_F(EmbedderTest, ChannelShutdownRace_MessagePipeClose) { + const size_t kIterations = 1000; + mojo::test::ScopedIPCSupport ipc_support(test_io_task_runner()); + + for (size_t i = 0; i < kIterations; i++) { + PlatformChannelPair channel_pair; + std::unique_ptr server_channel( + new ScopedTestChannel(channel_pair.PassServerHandle())); + server_channel->WaitForChannelCreationCompletion(); + server_channel->NoWaitOnShutdown(); + + MojoHandle server_mp = server_channel->bootstrap_message_pipe(); + EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); + + // Race between channel shutdown and closing a message pipe. The message + // pipe doesn't have to be the bootstrap pipe. It just has to be bound to + // the channel. + server_channel.reset(); + MojoClose(server_mp); + } +} + MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlave) { ScopedPlatformHandle client_platform_handle = mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); EXPECT_TRUE(client_platform_handle.is_valid()); - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); + TestIOThread test_io_thread(TestIOThread::kAutoStart); test::InitWithSimplePlatformSupport(); { @@ -631,7 +672,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); EXPECT_TRUE(client_platform_handle.is_valid()); - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); + TestIOThread test_io_thread(TestIOThread::kAutoStart); test::InitWithSimplePlatformSupport(); { diff --git a/mojo/edk/embedder/master_process_delegate.h b/mojo/edk/embedder/master_process_delegate.h index 031f3ba7bd2..eb6fa620e03 100644 --- a/mojo/edk/embedder/master_process_delegate.h +++ b/mojo/edk/embedder/master_process_delegate.h @@ -7,7 +7,6 @@ #include "mojo/edk/embedder/process_delegate.h" #include "mojo/edk/embedder/slave_info.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -15,7 +14,7 @@ namespace embedder { // An interface for the master process delegate (which lives in the master // process). -class MOJO_SYSTEM_IMPL_EXPORT MasterProcessDelegate : public ProcessDelegate { +class MasterProcessDelegate : public ProcessDelegate { public: ProcessType GetType() const override; diff --git a/mojo/edk/embedder/platform_channel_pair.h b/mojo/edk/embedder/platform_channel_pair.h index 873df04437b..5f44ef42672 100644 --- a/mojo/edk/embedder/platform_channel_pair.h +++ b/mojo/edk/embedder/platform_channel_pair.h @@ -5,11 +5,8 @@ #ifndef MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ #define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_PAIR_H_ -#include "base/memory/scoped_ptr.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" #include "mojo/public/cpp/system/macros.h" namespace base { @@ -21,26 +18,19 @@ namespace embedder { // 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.) +// suitable (platform-specific) bidirectional "pipe" (e.g., Unix domain socket). +// 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)). +// call |ChildProcessLaunched()|. // // Note: |PlatformChannelPair()|, |PassClientHandleFromParentProcess()| and // |PrepareToPassClientHandleToChildProcess()| have platform-specific @@ -50,7 +40,7 @@ using HandlePassingInformation = base::FileHandleMappingVector; // |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 { +class PlatformChannelPair { public: PlatformChannelPair(); ~PlatformChannelPair(); @@ -70,7 +60,6 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformChannelPair { // 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; diff --git a/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc b/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc index 0b20f4b57b5..5787e532142 100644 --- a/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc +++ b/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc @@ -15,22 +15,18 @@ #include -#include "base/files/scoped_file.h" #include "base/logging.h" #include "build/build_config.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/scoped_test_dir.h" #include "mojo/edk/test/test_utils.h" +#include "mojo/edk/util/scoped_file.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_ANDROID) -#include "base/android/path_utils.h" -#include "base/files/file_path.h" -#endif - namespace mojo { namespace embedder { namespace { @@ -42,22 +38,6 @@ void WaitReadable(PlatformHandle h) { CHECK_EQ(poll(&pfds, 1, -1), 1); } -FILE* NewTmpFile() { -#if defined(OS_ANDROID) - base::FilePath tmpdir; - if (!base::android::GetCacheDirectory(&tmpdir)) - return nullptr; - std::string templ = tmpdir.Append("XXXXXXXX").value(); - int fd = mkstemp(const_cast(templ.c_str())); - if (fd == -1) - return nullptr; - CHECK(unlink(templ.c_str()) == 0); - return fdopen(fd, "w+"); -#else - return tmpfile(); -#endif -} - class PlatformChannelPairPosixTest : public testing::Test { public: PlatformChannelPairPosixTest() {} @@ -147,6 +127,8 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveData) { } TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) { + mojo::test::ScopedTestDir test_dir; + static const char kHello[] = "hello"; PlatformChannelPair channel_pair; @@ -166,7 +148,7 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) { const char c = '0' + (i % 10); ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector); for (size_t j = 1; j <= i; j++) { - base::ScopedFILE fp(NewTmpFile()); + util::ScopedFILE fp(test_dir.CreateFile()); ASSERT_TRUE(fp); ASSERT_EQ(j, fwrite(std::string(j, c).data(), 1, j, fp.get())); platform_handles->push_back( @@ -194,7 +176,7 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) { EXPECT_EQ(i, received_handles.size()); for (size_t j = 0; !received_handles.empty(); j++) { - base::ScopedFILE fp(test::FILEFromPlatformHandle( + util::ScopedFILE fp(test::FILEFromPlatformHandle( ScopedPlatformHandle(received_handles.front()), "rb")); received_handles.pop_front(); ASSERT_TRUE(fp); @@ -208,6 +190,8 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) { } TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) { + mojo::test::ScopedTestDir test_dir; + static const char kHello[] = "hello"; PlatformChannelPair channel_pair; @@ -217,7 +201,7 @@ TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) { const std::string file_contents("hello world"); { - base::ScopedFILE fp(NewTmpFile()); + util::ScopedFILE fp(test_dir.CreateFile()); ASSERT_TRUE(fp); ASSERT_EQ(file_contents.size(), fwrite(file_contents.data(), 1, file_contents.size(), fp.get())); @@ -252,7 +236,7 @@ TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) { EXPECT_TRUE(received_handles[1].is_valid()); { - base::ScopedFILE fp(test::FILEFromPlatformHandle( + util::ScopedFILE fp(test::FILEFromPlatformHandle( ScopedPlatformHandle(received_handles[1]), "rb")); received_handles[1] = PlatformHandle(); ASSERT_TRUE(fp); 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 25306a61468..00000000000 --- a/mojo/edk/embedder/platform_channel_pair_win.cc +++ /dev/null @@ -1,111 +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 embedder { - -namespace { - -std::wstring GeneratePipeName() { - return base::StringPrintf(L"\\\\.\\pipe\\mojo.%u.%u.%I64u", - GetCurrentProcessId(), GetCurrentThreadId(), - base::RandUint64()); -} - -} // namespace - -PlatformChannelPair::PlatformChannelPair() { - std::wstring pipe_name = GeneratePipeName(); - - const 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. - const DWORD kFlags = - SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED; - // Allow the handle to be inherited by child processes. - SECURITY_ATTRIBUTES security_attributes = { - sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; - 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); - - int client_handle_value = 0; - if (client_handle_string.empty() || - !base::StringToInt(client_handle_string, &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); - DCHECK(handle_passing_info); - DCHECK(client_handle_.is_valid()); - - CHECK_GE(base::win::GetVersion(), base::win::VERSION_VISTA); - - handle_passing_info->push_back(client_handle_.get().handle); - - // 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, - base::IntToString(HandleToLong(client_handle_.get().handle))); -} - -} // namespace embedder -} // namespace mojo diff --git a/mojo/edk/embedder/platform_channel_utils_posix.h b/mojo/edk/embedder/platform_channel_utils_posix.h index 3073632e509..429cffa5ed4 100644 --- a/mojo/edk/embedder/platform_channel_utils_posix.h +++ b/mojo/edk/embedder/platform_channel_utils_posix.h @@ -10,9 +10,7 @@ #include -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" struct iovec; // Declared in . @@ -29,10 +27,12 @@ const size_t kPlatformChannelMaxNumHandles = 128; // 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); +ssize_t PlatformChannelWrite(PlatformHandle h, + const void* bytes, + size_t num_bytes); +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 @@ -42,12 +42,11 @@ PlatformChannelWritev(PlatformHandle h, struct iovec* iov, size_t num_iov); // 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); +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()|. @@ -57,18 +56,17 @@ PlatformChannelSendmsgWithHandles(PlatformHandle h, // 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); +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); +ssize_t PlatformChannelRecvmsg(PlatformHandle h, + void* buf, + size_t num_bytes, + std::deque* platform_handles); } // namespace embedder } // namespace mojo diff --git a/mojo/edk/embedder/platform_handle.cc b/mojo/edk/embedder/platform_handle.cc index 04d4f08e37b..570aac9c2e8 100644 --- a/mojo/edk/embedder/platform_handle.cc +++ b/mojo/edk/embedder/platform_handle.cc @@ -4,14 +4,7 @@ #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" @@ -22,17 +15,9 @@ void PlatformHandle::CloseIfNecessary() { if (!is_valid()) return; -#if defined(OS_POSIX) bool success = (close(fd) == 0); DPCHECK(success); fd = -1; -#elif defined(OS_WIN) - bool success = !!CloseHandle(handle); - DPCHECK(success); - handle = INVALID_HANDLE_VALUE; -#else -#error "Platform not yet supported." -#endif } } // namespace embedder diff --git a/mojo/edk/embedder/platform_handle.h b/mojo/edk/embedder/platform_handle.h index 346301a2371..60352947ba6 100644 --- a/mojo/edk/embedder/platform_handle.h +++ b/mojo/edk/embedder/platform_handle.h @@ -5,18 +5,11 @@ #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 -#endif - namespace mojo { namespace embedder { -#if defined(OS_POSIX) -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { +// A |PlatformHandle| is just a file descriptor on POSIX. +struct PlatformHandle { PlatformHandle() : fd(-1) {} explicit PlatformHandle(int fd) : fd(fd) {} @@ -26,20 +19,6 @@ struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { int fd; }; -#elif defined(OS_WIN) -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandle { - PlatformHandle() : handle(INVALID_HANDLE_VALUE) {} - explicit PlatformHandle(HANDLE handle) : handle(handle) {} - - void CloseIfNecessary(); - - bool is_valid() const { return handle != INVALID_HANDLE_VALUE; } - - HANDLE handle; -}; -#else -#error "Platform not yet supported." -#endif } // namespace embedder } // namespace mojo diff --git a/mojo/edk/embedder/platform_handle_utils.h b/mojo/edk/embedder/platform_handle_utils.h index b3d7a79f30a..f00f865af9c 100644 --- a/mojo/edk/embedder/platform_handle_utils.h +++ b/mojo/edk/embedder/platform_handle_utils.h @@ -7,15 +7,13 @@ #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 embedder { // Closes all the |PlatformHandle|s in the given container. template -MOJO_SYSTEM_IMPL_EXPORT inline void CloseAllPlatformHandles( - PlatformHandleContainer* platform_handles) { +inline void CloseAllPlatformHandles(PlatformHandleContainer* platform_handles) { for (typename PlatformHandleContainer::iterator it = platform_handles->begin(); it != platform_handles->end(); ++it) @@ -24,8 +22,7 @@ MOJO_SYSTEM_IMPL_EXPORT inline void CloseAllPlatformHandles( // Duplicates the given |PlatformHandle| (which must be valid). (Returns an // invalid |ScopedPlatformHandle| on failure.) -MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle -DuplicatePlatformHandle(PlatformHandle platform_handle); +ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle); } // namespace embedder } // 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 43d1331dd93..00000000000 --- a/mojo/edk/embedder/platform_handle_utils_win.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/embedder/platform_handle_utils.h" - -#include - -#include "base/logging.h" - -namespace mojo { -namespace embedder { - -ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) { - DCHECK(platform_handle.is_valid()); - - HANDLE new_handle; - 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 embedder -} // namespace mojo diff --git a/mojo/edk/embedder/platform_handle_vector.h b/mojo/edk/embedder/platform_handle_vector.h index 771df4fb9d4..e60eab40a1b 100644 --- a/mojo/edk/embedder/platform_handle_vector.h +++ b/mojo/edk/embedder/platform_handle_vector.h @@ -5,21 +5,21 @@ #ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ #define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_ +#include #include -#include "base/memory/scoped_ptr.h" #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 embedder { +// TODO(vtl): Can we switch to using std::vector instead? using PlatformHandleVector = std::vector; -// A deleter (for use with |scoped_ptr|) which closes all handles and then +// A deleter (for use with |std::unique_ptr|) that closes all handles and then // |delete|s the |PlatformHandleVector|. -struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandleVectorDeleter { +struct PlatformHandleVectorDeleter { void operator()(PlatformHandleVector* platform_handles) const { CloseAllPlatformHandles(platform_handles); delete platform_handles; @@ -27,7 +27,7 @@ struct MOJO_SYSTEM_IMPL_EXPORT PlatformHandleVectorDeleter { }; using ScopedPlatformHandleVectorPtr = - scoped_ptr; + std::unique_ptr; } // namespace embedder } // namespace mojo diff --git a/mojo/edk/embedder/platform_shared_buffer.h b/mojo/edk/embedder/platform_shared_buffer.h index 61b372916ae..331440f45e8 100644 --- a/mojo/edk/embedder/platform_shared_buffer.h +++ b/mojo/edk/embedder/platform_shared_buffer.h @@ -7,10 +7,10 @@ #include +#include + #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -33,7 +33,7 @@ class PlatformSharedBufferMapping; // - Sharing read-only. (This will probably eventually be supported.) // // TODO(vtl): Rectify this with |base::SharedMemory|. -class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer +class PlatformSharedBuffer : public base::RefCountedThreadSafe { public: // Gets the size of shared buffer (in number of bytes). @@ -42,16 +42,17 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer // 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. - virtual scoped_ptr Map(size_t offset, - size_t length) = 0; + virtual std::unique_ptr Map(size_t offset, + size_t length) = 0; // Checks if |offset| and |length| are valid arguments. virtual bool IsValidMap(size_t offset, size_t length) = 0; // Like |Map()|, but doesn't check its arguments (which should have been // preflighted using |IsValidMap()|). - virtual scoped_ptr MapNoCheck(size_t offset, - size_t length) = 0; + virtual std::unique_ptr MapNoCheck( + size_t offset, + size_t length) = 0; // Duplicates the underlying platform handle and passes it to the caller. // TODO(vtl): On POSIX, we'll need two FDs to support sharing read-only. @@ -81,7 +82,7 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer // // Note: This is an entirely separate class (instead of // |PlatformSharedBuffer::Mapping|) so that it can be forward-declared. -class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBufferMapping { +class PlatformSharedBufferMapping { public: // IMPORTANT: Implementations must implement a destructor that unmaps memory. virtual ~PlatformSharedBufferMapping() {} diff --git a/mojo/edk/embedder/platform_support.h b/mojo/edk/embedder/platform_support.h index 02186161082..40b404c74e4 100644 --- a/mojo/edk/embedder/platform_support.h +++ b/mojo/edk/embedder/platform_support.h @@ -8,7 +8,7 @@ #include #include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" +#include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -19,10 +19,27 @@ class PlatformSharedBuffer; // This class is provided by the embedder to implement (typically // platform-dependent) things needed by the Mojo system implementation. // Implementations must be thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT PlatformSupport { +class PlatformSupport { public: virtual ~PlatformSupport() {} + // Gets a "time-ticks" value: + // - The value should be nondecreasing with respect to time/causality. + // - The value should be in microseconds (i.e., if a caller runs + // continuously, getting the value twice, their difference should be + // approximately the real time elapsed between the samples, in + // microseconds). + // - The value should be nonnegative. + // - The behaviour of the value if execution is suspended (i.e., the + // computer "sleeps") is undefined (i.e., this is not a real-time clock), + // except that it must remain monotonic. + // - As observable, monotonicity should hold across threads. + // If multiple |PlatformSupport| implementations/instances are used in a + // single system, all implementations must agree (i.e., respect the above as + // if there were only a single |PlatformSupport|). + virtual MojoTimeTicks GetTimeTicksNow() = 0; + + // Gets cryptographically-secure (pseudo)random bytes. virtual void GetCryptoRandomBytes(void* bytes, size_t num_bytes) = 0; virtual PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) = 0; diff --git a/mojo/edk/embedder/process_delegate.h b/mojo/edk/embedder/process_delegate.h index 5c1406ddda9..189f08e07d2 100644 --- a/mojo/edk/embedder/process_delegate.h +++ b/mojo/edk/embedder/process_delegate.h @@ -6,14 +6,13 @@ #define MOJO_EDK_EMBEDDER_PROCESS_DELEGATE_H_ #include "mojo/edk/embedder/process_type.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { namespace embedder { // An interface for process delegates. -class MOJO_SYSTEM_IMPL_EXPORT ProcessDelegate { +class ProcessDelegate { public: virtual ProcessType GetType() const; diff --git a/mojo/edk/embedder/process_type.h b/mojo/edk/embedder/process_type.h index c18c5f58ce1..4ea439e5fa5 100644 --- a/mojo/edk/embedder/process_type.h +++ b/mojo/edk/embedder/process_type.h @@ -7,8 +7,6 @@ #include -#include "mojo/edk/system/system_impl_export.h" - namespace mojo { namespace embedder { @@ -25,9 +23,7 @@ enum class ProcessType { }; // So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - ProcessType process_type) { +inline std::ostream& operator<<(std::ostream& out, ProcessType process_type) { return out << static_cast(process_type); } diff --git a/mojo/edk/embedder/scoped_platform_handle.h b/mojo/edk/embedder/scoped_platform_handle.h index aec44825667..c886a427b6a 100644 --- a/mojo/edk/embedder/scoped_platform_handle.h +++ b/mojo/edk/embedder/scoped_platform_handle.h @@ -5,16 +5,16 @@ #ifndef MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_ #define MOJO_EDK_EMBEDDER_SCOPED_PLATFORM_HANDLE_H_ -#include "base/move.h" #include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/macros.h" +#include "mojo/public/cpp/system/macros.h" namespace mojo { namespace embedder { -class MOJO_SYSTEM_IMPL_EXPORT ScopedPlatformHandle { - MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(ScopedPlatformHandle) +// Scoper for |PlatformHandle|s, which are just file descriptors. +class ScopedPlatformHandle { + MOJO_MOVE_ONLY_TYPE(ScopedPlatformHandle) public: ScopedPlatformHandle() {} diff --git a/mojo/edk/embedder/simple_platform_shared_buffer.cc b/mojo/edk/embedder/simple_platform_shared_buffer.cc index 866250c9f03..cb4ae3d61d1 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer.cc +++ b/mojo/edk/embedder/simple_platform_shared_buffer.cc @@ -48,7 +48,7 @@ size_t SimplePlatformSharedBuffer::GetNumBytes() const { return num_bytes_; } -scoped_ptr SimplePlatformSharedBuffer::Map( +std::unique_ptr SimplePlatformSharedBuffer::Map( size_t offset, size_t length) { if (!IsValidMap(offset, length)) @@ -69,9 +69,8 @@ bool SimplePlatformSharedBuffer::IsValidMap(size_t offset, size_t length) { return true; } -scoped_ptr SimplePlatformSharedBuffer::MapNoCheck( - size_t offset, - size_t length) { +std::unique_ptr +SimplePlatformSharedBuffer::MapNoCheck(size_t offset, size_t length) { DCHECK(IsValidMap(offset, length)); return MapImpl(offset, length); } diff --git a/mojo/edk/embedder/simple_platform_shared_buffer.h b/mojo/edk/embedder/simple_platform_shared_buffer.h index 66b0c228ab7..199826df521 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer.h +++ b/mojo/edk/embedder/simple_platform_shared_buffer.h @@ -8,15 +8,13 @@ #include #include "mojo/edk/embedder/platform_shared_buffer.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { namespace embedder { // A simple implementation of |PlatformSharedBuffer|. -class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBuffer final - : public PlatformSharedBuffer { +class SimplePlatformSharedBuffer final : public PlatformSharedBuffer { public: // Creates a shared buffer of size |num_bytes| bytes (initially zero-filled). // |num_bytes| must be nonzero. Returns null on failure. @@ -28,11 +26,12 @@ class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBuffer final // |PlatformSharedBuffer| implementation: size_t GetNumBytes() const override; - scoped_ptr Map(size_t offset, - size_t length) override; + std::unique_ptr Map(size_t offset, + size_t length) override; bool IsValidMap(size_t offset, size_t length) override; - scoped_ptr MapNoCheck(size_t offset, - size_t length) override; + std::unique_ptr MapNoCheck( + size_t offset, + size_t length) override; ScopedPlatformHandle DuplicatePlatformHandle() override; ScopedPlatformHandle PassPlatformHandle() override; @@ -51,7 +50,8 @@ class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBuffer final bool InitFromPlatformHandle(ScopedPlatformHandle platform_handle); // The platform-dependent part of |Map()|; doesn't check arguments. - scoped_ptr MapImpl(size_t offset, size_t length); + std::unique_ptr MapImpl(size_t offset, + size_t length); const size_t num_bytes_; @@ -65,7 +65,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBuffer final // An implementation of |PlatformSharedBufferMapping|, produced by // |SimplePlatformSharedBuffer|. -class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBufferMapping +class SimplePlatformSharedBufferMapping final : public PlatformSharedBufferMapping { public: ~SimplePlatformSharedBufferMapping() override; diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_android.cc b/mojo/edk/embedder/simple_platform_shared_buffer_android.cc index 60219f91af9..6ee24e70304 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer_android.cc +++ b/mojo/edk/embedder/simple_platform_shared_buffer_android.cc @@ -10,9 +10,7 @@ #include -#include "base/files/scoped_file.h" #include "base/logging.h" -#include "mojo/edk/embedder/platform_handle.h" #include "third_party/ashmem/ashmem.h" namespace mojo { @@ -28,18 +26,19 @@ bool SimplePlatformSharedBuffer::Init() { return false; } - base::ScopedFD fd(ashmem_create_region(nullptr, num_bytes_)); - if (!fd.is_valid()) { + ScopedPlatformHandle handle( + PlatformHandle(ashmem_create_region(nullptr, num_bytes_))); + if (!handle.is_valid()) { DPLOG(ERROR) << "ashmem_create_region()"; return false; } - if (ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE) < 0) { + if (ashmem_set_prot_region(handle.get().fd, PROT_READ | PROT_WRITE) < 0) { DPLOG(ERROR) << "ashmem_set_prot_region()"; return false; } - handle_.reset(PlatformHandle(fd.release())); + handle_ = handle.Pass(); return true; } diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc b/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc index 4bae02e26d9..ca3f01303d1 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc +++ b/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc @@ -15,12 +15,11 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" -#include "base/files/scoped_file.h" #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/sys_info.h" #include "base/threading/thread_restrictions.h" -#include "mojo/edk/embedder/platform_handle.h" +#include "mojo/edk/util/scoped_file.h" // We assume that |size_t| and |off_t| (type for |ftruncate()|) fits in a // |uint64_t|. @@ -57,7 +56,7 @@ bool SimplePlatformSharedBuffer::Init() { return false; } base::FilePath shared_buffer_file; - base::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir( + util::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir( shared_buffer_dir, &shared_buffer_file)); if (!fp) { LOG(ERROR) << "Failed to create/open temporary file for shared memory"; @@ -71,18 +70,19 @@ bool SimplePlatformSharedBuffer::Init() { } // Note: |dup()| is not interruptible (but |dup2()|/|dup3()| are). - base::ScopedFD fd(dup(fileno(fp.get()))); - if (!fd.is_valid()) { + ScopedPlatformHandle handle(PlatformHandle(dup(fileno(fp.get())))); + if (!handle.is_valid()) { PLOG(ERROR) << "dup"; return false; } - if (HANDLE_EINTR(ftruncate(fd.get(), static_cast(num_bytes_))) != 0) { + if (HANDLE_EINTR( + ftruncate(handle.get().fd, static_cast(num_bytes_))) != 0) { PLOG(ERROR) << "ftruncate"; return false; } - handle_.reset(PlatformHandle(fd.release())); + handle_ = handle.Pass(); return true; } @@ -120,9 +120,8 @@ bool SimplePlatformSharedBuffer::InitFromPlatformHandle( #endif // !defined(OS_ANDROID) -scoped_ptr SimplePlatformSharedBuffer::MapImpl( - size_t offset, - size_t length) { +std::unique_ptr +SimplePlatformSharedBuffer::MapImpl(size_t offset, size_t length) { size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity(); size_t real_offset = offset - offset_rounding; size_t real_length = length + offset_rounding; @@ -143,8 +142,11 @@ scoped_ptr SimplePlatformSharedBuffer::MapImpl( } void* base = static_cast(real_base) + offset_rounding; - return make_scoped_ptr(new SimplePlatformSharedBufferMapping( - base, length, real_base, real_length)); + // Note: We can't use |MakeUnique| here, since it's not a friend of + // |SimplePlatformSharedBufferMapping| (only we are). + return std::unique_ptr( + new SimplePlatformSharedBufferMapping(base, length, real_base, + real_length)); } // SimplePlatformSharedBufferMapping ------------------------------------------- diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc b/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc index cc66c764897..368604fafb8 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc +++ b/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc @@ -7,7 +7,6 @@ #include #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,7 +28,8 @@ TEST(SimplePlatformSharedBufferTest, Basic) { // Map it all, scribble some stuff, and then unmap it. { EXPECT_TRUE(buffer->IsValidMap(0, kNumBytes)); - scoped_ptr mapping(buffer->Map(0, kNumBytes)); + std::unique_ptr mapping( + buffer->Map(0, kNumBytes)); ASSERT_TRUE(mapping); ASSERT_TRUE(mapping->GetBase()); int* stuff = static_cast(mapping->GetBase()); @@ -44,7 +44,7 @@ TEST(SimplePlatformSharedBufferTest, Basic) { { ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes)); // Use |MapNoCheck()| this time. - scoped_ptr mapping1( + std::unique_ptr mapping1( buffer->MapNoCheck(0, kNumBytes)); ASSERT_TRUE(mapping1); ASSERT_TRUE(mapping1->GetBase()); @@ -52,7 +52,7 @@ TEST(SimplePlatformSharedBufferTest, Basic) { for (size_t i = 0; i < kNumInts; i++) EXPECT_EQ(static_cast(i) + kFudge, stuff1[i]) << i; - scoped_ptr mapping2( + std::unique_ptr mapping2( buffer->Map((kNumInts / 2) * sizeof(int), 2 * sizeof(int))); ASSERT_TRUE(mapping2); ASSERT_TRUE(mapping2->GetBase()); @@ -76,7 +76,7 @@ TEST(SimplePlatformSharedBufferTest, Basic) { // it to be. { EXPECT_TRUE(buffer->IsValidMap(sizeof(int), kNumBytes - sizeof(int))); - scoped_ptr mapping( + std::unique_ptr mapping( buffer->Map(sizeof(int), kNumBytes - sizeof(int))); ASSERT_TRUE(mapping); ASSERT_TRUE(mapping->GetBase()); @@ -144,8 +144,8 @@ TEST(SimplePlatformSharedBufferTest, TooBig) { TEST(SimplePlatformSharedBufferTest, MappingsDistinct) { scoped_refptr buffer( SimplePlatformSharedBuffer::Create(100)); - scoped_ptr mapping1(buffer->Map(0, 100)); - scoped_ptr mapping2(buffer->Map(0, 100)); + std::unique_ptr mapping1(buffer->Map(0, 100)); + std::unique_ptr mapping2(buffer->Map(0, 100)); EXPECT_NE(mapping1->GetBase(), mapping2->GetBase()); } @@ -154,7 +154,8 @@ TEST(SimplePlatformSharedBufferTest, BufferZeroInitialized) { for (size_t i = 0; i < MOJO_ARRAYSIZE(kSizes); i++) { scoped_refptr buffer( SimplePlatformSharedBuffer::Create(kSizes[i])); - scoped_ptr mapping(buffer->Map(0, 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. @@ -165,14 +166,14 @@ TEST(SimplePlatformSharedBufferTest, BufferZeroInitialized) { } TEST(SimplePlatformSharedBufferTest, MappingsOutliveBuffer) { - scoped_ptr mapping1; - scoped_ptr mapping2; + std::unique_ptr mapping1; + std::unique_ptr mapping2; { scoped_refptr buffer( SimplePlatformSharedBuffer::Create(100)); - mapping1 = buffer->Map(0, 100).Pass(); - mapping2 = buffer->Map(50, 50).Pass(); + mapping1 = buffer->Map(0, 100); + mapping2 = buffer->Map(50, 50); static_cast(mapping1->GetBase())[50] = 'x'; } diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_win.cc b/mojo/edk/embedder/simple_platform_shared_buffer_win.cc deleted file mode 100644 index 49b82d86cf3..00000000000 --- a/mojo/edk/embedder/simple_platform_shared_buffer_win.cc +++ /dev/null @@ -1,88 +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/simple_platform_shared_buffer.h" - -#include - -#include - -#include "base/logging.h" -#include "base/sys_info.h" -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" - -namespace mojo { -namespace embedder { - -// SimplePlatformSharedBuffer -------------------------------------------------- - -bool SimplePlatformSharedBuffer::Init() { - DCHECK(!handle_.is_valid()); - - // TODO(vtl): Currently, we only support mapping up to 2^32-1 bytes. - if (static_cast(num_bytes_) > - static_cast(std::numeric_limits::max())) { - return false; - } - - // IMPORTANT NOTE: Unnamed objects are NOT SECURABLE. Thus if we ever want to - // share read-only to other processes, we'll have to name our file mapping - // object. - // TODO(vtl): Unlike |base::SharedMemory|, we don't round up the size (to a - // multiple of 64 KB). This may cause problems with NaCl. Cross this bridge - // when we get there. crbug.com/210609 - handle_.reset(PlatformHandle( - CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, - static_cast(num_bytes_), nullptr))); - if (!handle_.is_valid()) { - PLOG(ERROR) << "CreateFileMapping"; - return false; - } - - return true; -} - -bool SimplePlatformSharedBuffer::InitFromPlatformHandle( - ScopedPlatformHandle platform_handle) { - DCHECK(!handle_.is_valid()); - - handle_ = platform_handle.Pass(); - return true; -} - -scoped_ptr SimplePlatformSharedBuffer::MapImpl( - size_t offset, - size_t length) { - size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity(); - size_t real_offset = offset - offset_rounding; - size_t real_length = length + offset_rounding; - - // This should hold (since we checked |num_bytes| versus the maximum value of - // |off_t| on creation, but it never hurts to be paranoid. - DCHECK_LE(static_cast(real_offset), - static_cast(std::numeric_limits::max())); - - void* real_base = - MapViewOfFile(handle_.get().handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, - static_cast(real_offset), real_length); - if (!real_base) { - PLOG(ERROR) << "MapViewOfFile"; - return nullptr; - } - - void* base = static_cast(real_base) + offset_rounding; - return make_scoped_ptr(new SimplePlatformSharedBufferMapping( - base, length, real_base, real_length)); -} - -// SimplePlatformSharedBufferMapping ------------------------------------------- - -void SimplePlatformSharedBufferMapping::Unmap() { - BOOL result = UnmapViewOfFile(real_base_); - PLOG_IF(ERROR, !result) << "UnmapViewOfFile"; -} - -} // namespace embedder -} // namespace mojo diff --git a/mojo/edk/embedder/simple_platform_support.cc b/mojo/edk/embedder/simple_platform_support.cc index 4207120fc7b..f3143239b2a 100644 --- a/mojo/edk/embedder/simple_platform_support.cc +++ b/mojo/edk/embedder/simple_platform_support.cc @@ -5,11 +5,16 @@ #include "mojo/edk/embedder/simple_platform_support.h" #include "base/rand_util.h" +#include "base/time/time.h" #include "mojo/edk/embedder/simple_platform_shared_buffer.h" namespace mojo { namespace embedder { +MojoTimeTicks SimplePlatformSupport::GetTimeTicksNow() { + return base::TimeTicks::Now().ToInternalValue(); +} + void SimplePlatformSupport::GetCryptoRandomBytes(void* bytes, size_t num_bytes) { base::RandBytes(bytes, num_bytes); diff --git a/mojo/edk/embedder/simple_platform_support.h b/mojo/edk/embedder/simple_platform_support.h index f06ae081eb9..19c56a3a65a 100644 --- a/mojo/edk/embedder/simple_platform_support.h +++ b/mojo/edk/embedder/simple_platform_support.h @@ -6,7 +6,6 @@ #define MOJO_EDK_EMBEDDER_SIMPLE_PLATFORM_SUPPORT_H_ #include "mojo/edk/embedder/platform_support.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -17,12 +16,12 @@ namespace embedder { // has no state, and different instances of |SimplePlatformSupport| are mutually // compatible (i.e., you don't need to use a single instance of it everywhere -- // you may simply create one whenever/wherever you need it). -class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSupport final - : public PlatformSupport { +class SimplePlatformSupport final : public PlatformSupport { public: SimplePlatformSupport() {} ~SimplePlatformSupport() override {} + MojoTimeTicks GetTimeTicksNow() override; void GetCryptoRandomBytes(void* bytes, size_t num_bytes) override; PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) override; PlatformSharedBuffer* CreateSharedBufferFromHandle( diff --git a/mojo/edk/embedder/slave_process_delegate.h b/mojo/edk/embedder/slave_process_delegate.h index cef5e0d3932..281c55939fd 100644 --- a/mojo/edk/embedder/slave_process_delegate.h +++ b/mojo/edk/embedder/slave_process_delegate.h @@ -6,7 +6,6 @@ #define MOJO_EDK_EMBEDDER_SLAVE_PROCESS_DELEGATE_H_ #include "mojo/edk/embedder/process_delegate.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -14,7 +13,7 @@ namespace embedder { // An interface for the slave process delegate (which lives in each slave // process). -class MOJO_SYSTEM_IMPL_EXPORT SlaveProcessDelegate : public ProcessDelegate { +class SlaveProcessDelegate : public ProcessDelegate { public: ProcessType GetType() const override; diff --git a/mojo/edk/embedder/test_embedder.cc b/mojo/edk/embedder/test_embedder.cc index d7c0d40df6f..26ceebab2c3 100644 --- a/mojo/edk/embedder/test_embedder.cc +++ b/mojo/edk/embedder/test_embedder.cc @@ -5,13 +5,13 @@ #include "mojo/edk/embedder/test_embedder.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/embedder_internal.h" #include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/edk/system/channel_manager.h" #include "mojo/edk/system/core.h" #include "mojo/edk/system/handle_table.h" +#include "mojo/edk/util/make_unique.h" namespace mojo { @@ -41,7 +41,7 @@ namespace embedder { namespace test { void InitWithSimplePlatformSupport() { - Init(make_scoped_ptr(new SimplePlatformSupport())); + Init(util::MakeUnique()); } bool Shutdown() { diff --git a/mojo/edk/embedder/test_embedder.h b/mojo/edk/embedder/test_embedder.h index 76917ee539e..a4e86e197cf 100644 --- a/mojo/edk/embedder/test_embedder.h +++ b/mojo/edk/embedder/test_embedder.h @@ -5,15 +5,13 @@ #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 embedder { namespace test { // Calls |Init()| with a |SimplePlatformSupport| (use this in tests if, e.g., // you don't care about sandboxing, etc.). -MOJO_SYSTEM_IMPL_EXPORT void InitWithSimplePlatformSupport(); +void InitWithSimplePlatformSupport(); // This shuts down the global, singleton instance. (Note: "Real" embedders are // not expected to ever shut down this instance. This |Shutdown()| function will @@ -23,7 +21,7 @@ MOJO_SYSTEM_IMPL_EXPORT void InitWithSimplePlatformSupport(); // // 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(); +bool Shutdown(); } // namespace test } // namespace embedder diff --git a/mojo/edk/js/tests/js_to_cpp_tests.cc b/mojo/edk/js/tests/js_to_cpp_tests.cc index c012daf10c1..0578afd1d6a 100644 --- a/mojo/edk/js/tests/js_to_cpp_tests.cc +++ b/mojo/edk/js/tests/js_to_cpp_tests.cc @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#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 "gin/array_buffer.h" #include "gin/public/isolate_holder.h" #include "mojo/edk/js/mojo_runner_delegate.h" @@ -24,23 +23,23 @@ namespace js { // Global value updated by some checks to prevent compilers from optimizing // reads out of existence. -uint32 g_waste_accumulator = 0; +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 kExpectedInt8Value = -65; -const int16 kExpectedInt16Value = -16961; -const int32 kExpectedInt32Value = -1145258561; -const int64 kExpectedInt64Value = -77263311946305LL; +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 kExpectedUInt8Value = 65; -const uint16 kExpectedUInt16Value = 16961; -const uint32 kExpectedUInt32Value = 1145258561; -const uint64 kExpectedUInt64Value = 77263311946305LL; +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; diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn index 5367be17a34..9a534450d33 100644 --- a/mojo/edk/system/BUILD.gn +++ b/mojo/edk/system/BUILD.gn @@ -94,7 +94,6 @@ component("system") { "raw_channel.cc", "raw_channel.h", "raw_channel_posix.cc", - "raw_channel_win.cc", "remote_consumer_data_pipe_impl.cc", "remote_consumer_data_pipe_impl.h", "remote_data_pipe_ack.h", @@ -115,10 +114,7 @@ component("system") { "waiter.h", ] - defines = [ - "MOJO_SYSTEM_IMPL_IMPLEMENTATION", - "MOJO_SYSTEM_IMPLEMENTATION", - ] + defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ] all_dependent_configs = [ ":system_config" ] @@ -126,6 +122,7 @@ component("system") { "../embedder", "../embedder:delegates", "../embedder:platform", + "../util", "../../public/c/system", "../../public/cpp/system", ] @@ -163,6 +160,8 @@ mojo_edk_source_set("test_utils") { "//base", "//base/test:test_support", ] + + mojo_edk_deps = [ "mojo/edk/embedder:platform" ] } test("mojo_system_unittests") { @@ -217,6 +216,7 @@ test("mojo_system_unittests") { ":test_utils", "../embedder:embedder_unittests", "../test:test_support", + "../util", "//base", "//base/test:test_support", "//testing/gtest", diff --git a/mojo/edk/system/async_waiter.h b/mojo/edk/system/async_waiter.h index 2c4d7701546..9dece06e5f2 100644 --- a/mojo/edk/system/async_waiter.h +++ b/mojo/edk/system/async_waiter.h @@ -7,7 +7,6 @@ #include "base/callback.h" #include "mojo/edk/system/awakable.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -15,13 +14,13 @@ namespace mojo { namespace system { // An |Awakable| implementation that just calls a given callback object. -class MOJO_SYSTEM_IMPL_EXPORT AsyncWaiter final : public Awakable { +class AsyncWaiter final : public Awakable { public: using AwakeCallback = base::Callback; // |callback| must satisfy the same contract as |Awakable::Awake()|. explicit AsyncWaiter(const AwakeCallback& callback); - virtual ~AsyncWaiter(); + ~AsyncWaiter() override; private: // |Awakable| implementation: diff --git a/mojo/edk/system/awakable.h b/mojo/edk/system/awakable.h index 057d3ebf4f8..c150a78707b 100644 --- a/mojo/edk/system/awakable.h +++ b/mojo/edk/system/awakable.h @@ -7,25 +7,26 @@ #include -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" namespace mojo { namespace system { -// An interface that may be waited on |AwakableList|. -class MOJO_SYSTEM_IMPL_EXPORT Awakable { +// An interface for things that may be awoken. E.g., |Waiter| is an +// implementation that blocks while waiting to be awoken. +class Awakable { public: // |Awake()| must satisfy the following contract: - // * As this is called from any thread, this must be thread-safe. - // * As this is called inside a lock, this must not call anything that takes - // "non-terminal" locks, i.e., those which are always safe to take. - // This should return false if this must not be called again for the same - // reason (e.g., for the same call to |AwakableList::Add()|). + // - It must be thread-safe. + // - Since it is called with a mutex held, it must not call anything that + // takes "non-terminal" locks, i.e., those which are always safe to take. + // - It should return false if it must not be called again for the same + // reason (e.g., for the same call to |AwakableList::Add()|). virtual bool Awake(MojoResult result, uintptr_t context) = 0; protected: Awakable() {} + virtual ~Awakable() {} }; } // namespace system diff --git a/mojo/edk/system/awakable_list.h b/mojo/edk/system/awakable_list.h index a34a4820887..e4d4b244e82 100644 --- a/mojo/edk/system/awakable_list.h +++ b/mojo/edk/system/awakable_list.h @@ -9,7 +9,6 @@ #include -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -19,14 +18,14 @@ namespace system { class Awakable; struct HandleSignalsState; -// |AwakableList| tracks all the |Waiter|s that are waiting on a given -// handle/|Dispatcher|. There should be a |AwakableList| for each handle that -// can be waited on (in any way). In the simple case, the |AwakableList| is -// owned by the |Dispatcher|, whereas in more complex cases it is owned by the -// secondary object (see simple_dispatcher.* and the explanatory comment in -// core.cc). This class is thread-unsafe (all concurrent access must be -// protected by some lock). -class MOJO_SYSTEM_IMPL_EXPORT AwakableList { +// |AwakableList| tracks all the |Awakable|s (usually |Waiter|s) that are +// waiting on a given handle/|Dispatcher|. There should be a |AwakableList| for +// each handle that can be waited on (in any way). In the simple case, the +// |AwakableList| is owned by the |Dispatcher|, whereas in more complex cases it +// is owned by the secondary object (see simple_dispatcher.* and the explanatory +// comment in core.cc). This class is thread-unsafe (all concurrent access must +// be protected by some lock). +class AwakableList { public: AwakableList(); ~AwakableList(); diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc index a95ed3574bf..7cd6f2f96e8 100644 --- a/mojo/edk/system/channel.cc +++ b/mojo/edk/system/channel.cc @@ -5,6 +5,7 @@ #include "mojo/edk/system/channel.h" #include +#include #include "base/bind.h" #include "base/logging.h" @@ -35,14 +36,14 @@ Channel::Channel(embedder::PlatformSupport* platform_support) channel_manager_(nullptr) { } -void Channel::Init(scoped_ptr raw_channel) { +void Channel::Init(std::unique_ptr raw_channel) { DCHECK(creation_thread_checker_.CalledOnValidThread()); DCHECK(raw_channel); // No need to take |mutex_|, since this must be called before this object // becomes thread-safe. DCHECK(!is_running_); - raw_channel_ = raw_channel.Pass(); + raw_channel_ = std::move(raw_channel); raw_channel_->Init(this); is_running_ = true; } @@ -124,7 +125,7 @@ void Channel::SetBootstrapEndpointWithIds( endpoint->AttachAndRun(this, local_id, remote_id); } -bool Channel::WriteMessage(scoped_ptr message) { +bool Channel::WriteMessage(std::unique_ptr message) { MutexLocker locker(&mutex_); if (!is_running_) { // TODO(vtl): I think this is probably not an error condition, but I should @@ -134,7 +135,7 @@ bool Channel::WriteMessage(scoped_ptr message) { } DLOG_IF(WARNING, is_shutting_down_) << "WriteMessage() while shutting down"; - return raw_channel_->WriteMessage(message.Pass()); + return raw_channel_->WriteMessage(std::move(message)); } bool Channel::IsWriteBufferEmpty() { @@ -147,6 +148,13 @@ bool Channel::IsWriteBufferEmpty() { void Channel::DetachEndpoint(ChannelEndpoint* endpoint, ChannelEndpointId local_id, ChannelEndpointId remote_id) { + // Keep a reference to |this| to prevent this |Channel| from being deleted + // while this function is running. Without this, if |Shutdown()| is started + // on the IO thread immediately after |mutex_| is released below and finishes + // before |SendControlMessage()| gets to run, |this| could be deleted while + // this function is still running. + scoped_refptr self(this); + if (!DetachEndpointInternal(endpoint, local_id, remote_id)) return; @@ -289,10 +297,10 @@ void Channel::OnReadMessage( switch (message_view.type()) { case MessageInTransit::Type::ENDPOINT_CLIENT: case MessageInTransit::Type::ENDPOINT: - OnReadMessageForEndpoint(message_view, platform_handles.Pass()); + OnReadMessageForEndpoint(message_view, std::move(platform_handles)); break; case MessageInTransit::Type::CHANNEL: - OnReadMessageForChannel(message_view, platform_handles.Pass()); + OnReadMessageForChannel(message_view, std::move(platform_handles)); break; default: HandleRemoteError( @@ -383,16 +391,16 @@ void Channel::OnReadMessageForEndpoint( return; } - scoped_ptr message(new MessageInTransit(message_view)); + std::unique_ptr message(new MessageInTransit(message_view)); if (message_view.transport_data_buffer_size() > 0) { DCHECK(message_view.transport_data_buffer()); message->SetDispatchers(TransportData::DeserializeDispatchers( message_view.transport_data_buffer(), - message_view.transport_data_buffer_size(), platform_handles.Pass(), + message_view.transport_data_buffer_size(), std::move(platform_handles), this)); } - endpoint->OnReadMessage(message.Pass()); + endpoint->OnReadMessage(std::move(message)); } void Channel::OnReadMessageForChannel( @@ -616,11 +624,11 @@ bool Channel::SendControlMessage(MessageInTransit::Subtype subtype, const void* bytes) { DVLOG(2) << "Sending channel control message: subtype " << subtype << ", local ID " << local_id << ", remote ID " << remote_id; - scoped_ptr message(new MessageInTransit( + std::unique_ptr message(new MessageInTransit( MessageInTransit::Type::CHANNEL, subtype, num_bytes, bytes)); message->set_source_id(local_id); message->set_destination_id(remote_id); - return WriteMessage(message.Pass()); + return WriteMessage(std::move(message)); } } // namespace system diff --git a/mojo/edk/system/channel.h b/mojo/edk/system/channel.h index 6a612ceed6a..4efe2c81c1b 100644 --- a/mojo/edk/system/channel.h +++ b/mojo/edk/system/channel.h @@ -7,9 +7,10 @@ #include -#include "base/containers/hash_tables.h" +#include +#include + #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/threading/thread_checker.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/channel_endpoint.h" @@ -18,7 +19,6 @@ #include "mojo/edk/system/message_in_transit.h" #include "mojo/edk/system/mutex.h" #include "mojo/edk/system/raw_channel.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -49,9 +49,8 @@ class MessageInTransitQueue; // |ChannelEndpointClient| (e.g., |MessagePipe|), |ChannelEndpoint|, |Channel|. // Thus |Channel| may not call into |ChannelEndpoint| with |Channel|'s lock // held. -class MOJO_SYSTEM_IMPL_EXPORT Channel final - : public base::RefCountedThreadSafe, - public RawChannel::Delegate { +class Channel final : public base::RefCountedThreadSafe, + public RawChannel::Delegate { public: // |platform_support| must remain alive until after |Shutdown()| is called. explicit Channel(embedder::PlatformSupport* platform_support); @@ -59,7 +58,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel final // This must be called on the creation thread before any other methods are // called, and before references to this object are given to any other // threads. |raw_channel| should be uninitialized. - void Init(scoped_ptr raw_channel) MOJO_NOT_THREAD_SAFE; + void Init(std::unique_ptr raw_channel) MOJO_NOT_THREAD_SAFE; // Sets the channel manager associated with this channel. This should be set // at most once and only called before |WillShutdownSoon()| (and @@ -99,7 +98,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel final ChannelEndpointId remote_id); // This forwards |message| verbatim to |raw_channel_|. - bool WriteMessage(scoped_ptr message); + bool WriteMessage(std::unique_ptr message); // See |RawChannel::IsWriteBufferEmpty()|. // TODO(vtl): Maybe we shouldn't expose this, and instead have a @@ -247,7 +246,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel final // https://github.com/domokit/mojo/issues/313 mutable Mutex mutex_; - scoped_ptr raw_channel_ MOJO_GUARDED_BY(mutex_); + std::unique_ptr raw_channel_ MOJO_GUARDED_BY(mutex_); bool is_running_ MOJO_GUARDED_BY(mutex_); // Set when |WillShutdownSoon()| is called. bool is_shutting_down_ MOJO_GUARDED_BY(mutex_); @@ -256,7 +255,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel final ChannelManager* channel_manager_ MOJO_GUARDED_BY(mutex_); using IdToEndpointMap = - base::hash_map>; + std::unordered_map>; // Map from local IDs to endpoints. If the endpoint is null, this means that // we're just waiting for the remove ack before removing the entry. IdToEndpointMap local_id_to_endpoint_map_ MOJO_GUARDED_BY(mutex_); @@ -264,7 +263,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel final LocalChannelEndpointIdGenerator local_id_generator_ MOJO_GUARDED_BY(mutex_); using IdToIncomingEndpointMap = - base::hash_map>; + std::unordered_map>; // Map from local IDs to incoming endpoints (i.e., those received inside other // messages, but not yet claimed via |DeserializeEndpoint()|). IdToIncomingEndpointMap incoming_endpoints_ MOJO_GUARDED_BY(mutex_); diff --git a/mojo/edk/system/channel_endpoint.cc b/mojo/edk/system/channel_endpoint.cc index e7e17b4bb3d..73f3c7a9dc0 100644 --- a/mojo/edk/system/channel_endpoint.cc +++ b/mojo/edk/system/channel_endpoint.cc @@ -4,6 +4,8 @@ #include "mojo/edk/system/channel_endpoint.h" +#include + #include "base/logging.h" #include "base/threading/platform_thread.h" #include "mojo/edk/system/channel.h" @@ -26,17 +28,18 @@ ChannelEndpoint::ChannelEndpoint(ChannelEndpointClient* client, channel_message_queue_.Swap(message_queue); } -bool ChannelEndpoint::EnqueueMessage(scoped_ptr message) { +bool ChannelEndpoint::EnqueueMessage( + std::unique_ptr message) { DCHECK(message); MutexLocker locker(&mutex_); switch (state_) { case State::PAUSED: - channel_message_queue_.AddMessage(message.Pass()); + channel_message_queue_.AddMessage(std::move(message)); return true; case State::RUNNING: - return WriteMessageNoLock(message.Pass()); + return WriteMessageNoLock(std::move(message)); case State::DEAD: return false; } @@ -96,9 +99,9 @@ void ChannelEndpoint::AttachAndRun(Channel* channel, } } -void ChannelEndpoint::OnReadMessage(scoped_ptr message) { +void ChannelEndpoint::OnReadMessage(std::unique_ptr message) { if (message->type() == MessageInTransit::Type::ENDPOINT_CLIENT) { - OnReadMessageForClient(message.Pass()); + OnReadMessageForClient(std::move(message)); return; } @@ -148,7 +151,8 @@ ChannelEndpoint::~ChannelEndpoint() { DCHECK(!remote_id_.is_valid()); } -bool ChannelEndpoint::WriteMessageNoLock(scoped_ptr message) { +bool ChannelEndpoint::WriteMessageNoLock( + std::unique_ptr message) { DCHECK(message); mutex_.AssertHeld(); @@ -160,11 +164,11 @@ bool ChannelEndpoint::WriteMessageNoLock(scoped_ptr message) { message->SerializeAndCloseDispatchers(channel_); message->set_source_id(local_id_); message->set_destination_id(remote_id_); - return channel_->WriteMessage(message.Pass()); + return channel_->WriteMessage(std::move(message)); } void ChannelEndpoint::OnReadMessageForClient( - scoped_ptr message) { + std::unique_ptr message) { DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); scoped_refptr client; diff --git a/mojo/edk/system/channel_endpoint.h b/mojo/edk/system/channel_endpoint.h index 3ebe386a685..386ef7ac637 100644 --- a/mojo/edk/system/channel_endpoint.h +++ b/mojo/edk/system/channel_endpoint.h @@ -5,12 +5,12 @@ #ifndef MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_ #define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_ +#include + #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel_endpoint_id.h" #include "mojo/edk/system/message_in_transit_queue.h" #include "mojo/edk/system/mutex.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -108,7 +108,7 @@ class MessageInTransit; // simultaneously, and both sides send "remove" messages). In that // case, it must still remain alive until it receives the "remove // ack" (and it must ack the "remove" message that it received). -class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint final +class ChannelEndpoint final : public base::RefCountedThreadSafe { public: // Constructor for a |ChannelEndpoint| with the given client (specified by @@ -128,7 +128,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint final // Called to enqueue an outbound message. (If |AttachAndRun()| has not yet // been called, the message will be enqueued and sent when |AttachAndRun()| is // called.) - bool EnqueueMessage(scoped_ptr message); + bool EnqueueMessage(std::unique_ptr message); // Called to *replace* current client with a new client (which must differ // from the existing client). This must not be called after @@ -153,7 +153,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint final ChannelEndpointId remote_id); // Called when the |Channel| receives a message for the |ChannelEndpoint|. - void OnReadMessage(scoped_ptr message); + void OnReadMessage(std::unique_ptr message); // Called before the |Channel| gives up its reference to this object. void DetachFromChannel(); @@ -162,11 +162,11 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint final friend class base::RefCountedThreadSafe; ~ChannelEndpoint(); - bool WriteMessageNoLock(scoped_ptr message) + bool WriteMessageNoLock(std::unique_ptr message) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); // Helper for |OnReadMessage()|, handling messages for the client. - void OnReadMessageForClient(scoped_ptr message); + void OnReadMessageForClient(std::unique_ptr message); // Moves |state_| from |RUNNING| to |DEAD|. |channel_| must be non-null, but // this does not call |channel_->DetachEndpoint()|. diff --git a/mojo/edk/system/channel_endpoint_client.h b/mojo/edk/system/channel_endpoint_client.h index 98f6761ce35..d2260f1db76 100644 --- a/mojo/edk/system/channel_endpoint_client.h +++ b/mojo/edk/system/channel_endpoint_client.h @@ -6,8 +6,6 @@ #define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_ #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -31,7 +29,7 @@ class MessageInTransit; // after |ChannelEndpoint::DetachFromClient()| has been called (so the // |ChannelEndpoint| has apparently relinquished its pointer to the // |ChannelEndpointClient|). -class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointClient +class ChannelEndpointClient : public base::RefCountedThreadSafe { public: // Called by |ChannelEndpoint| in response to its |OnReadMessage()|, which is diff --git a/mojo/edk/system/channel_endpoint_id.h b/mojo/edk/system/channel_endpoint_id.h index 3cb2fd11888..cf968c15640 100644 --- a/mojo/edk/system/channel_endpoint_id.h +++ b/mojo/edk/system/channel_endpoint_id.h @@ -8,11 +8,10 @@ #include #include +#include #include -#include "base/containers/hash_tables.h" #include "base/gtest_prod_util.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -35,9 +34,14 @@ FORWARD_DECLARE_TEST(RemoteChannelEndpointIdGeneratorTest, WrapAround); // table, such an ID is a "remotely-allocated local ID". From the standpoint of // the |Channel| allocating such a remote ID (for its peer |Channel|), it's a // "locally-allocated remote ID". -class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointId { +class ChannelEndpointId { public: - ChannelEndpointId() : value_(0) {} + ChannelEndpointId() : value_(0) { + // This wrapper should add no overhead. (Put this here, since |value_| is + // private and we also need the class to be fully defined.) + static_assert(sizeof(ChannelEndpointId) == sizeof(value_), + "ChannelEndpointId has incorrect size"); + } ChannelEndpointId(const ChannelEndpointId& other) : value_(other.value_) {} // Returns the local ID to use for the first message pipe endpoint on a @@ -74,16 +78,10 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointId { // Copying and assignment allowed. }; -// This wrapper should add no overhead. -// TODO(vtl): Rewrite |sizeof(uint32_t)| as |sizeof(ChannelEndpointId::value)| -// once we have sufficient C++11 support. -static_assert(sizeof(ChannelEndpointId) == sizeof(uint32_t), - "ChannelEndpointId has incorrect size"); // So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - const ChannelEndpointId& channel_endpoint_id) { +inline std::ostream& operator<<(std::ostream& out, + const ChannelEndpointId& channel_endpoint_id) { return out << channel_endpoint_id.value(); } @@ -92,7 +90,7 @@ MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( // A generator for "new" local |ChannelEndpointId|s. It does not track // used/existing IDs; that must be done separately. (This class is not // thread-safe.) -class MOJO_SYSTEM_IMPL_EXPORT LocalChannelEndpointIdGenerator { +class LocalChannelEndpointIdGenerator { public: LocalChannelEndpointIdGenerator() : next_(ChannelEndpointId::GetBootstrap()) {} @@ -113,7 +111,7 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalChannelEndpointIdGenerator { // locally allocate remote IDs. (See the comment above |ChannelEndpointId| for // an explanatory note.) It does not track used/existing IDs; that must be done // separately. (This class is not thread-safe.) -class MOJO_SYSTEM_IMPL_EXPORT RemoteChannelEndpointIdGenerator { +class RemoteChannelEndpointIdGenerator { public: RemoteChannelEndpointIdGenerator() : next_(ChannelEndpointId::kRemoteFlag) {} @@ -130,12 +128,10 @@ class MOJO_SYSTEM_IMPL_EXPORT RemoteChannelEndpointIdGenerator { } // namespace system } // namespace mojo -// Define "hash" functions for |ChannelEndpointId|s, so they can be used in hash -// tables. -// TODO(vtl): Once we can use |std::unordered_{map,set}|, update this (and -// remove the base/containers/hash_tables.h include). -namespace BASE_HASH_NAMESPACE { +namespace std { +// Specialization of |std::hash<>| for |ChannelEndpointId|s, so they can be used +// in unordered sets/maps. template <> struct hash { size_t operator()(mojo::system::ChannelEndpointId channel_endpoint_id) const { @@ -143,6 +139,6 @@ struct hash { } }; -} // namespace BASE_HASH_NAMESPACE +} // namespace std #endif // MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_ diff --git a/mojo/edk/system/channel_endpoint_unittest.cc b/mojo/edk/system/channel_endpoint_unittest.cc index e0bf9f15424..6a78307eb6d 100644 --- a/mojo/edk/system/channel_endpoint_unittest.cc +++ b/mojo/edk/system/channel_endpoint_unittest.cc @@ -4,6 +4,9 @@ #include "mojo/edk/system/channel_endpoint.h" +#include +#include + #include "base/synchronization/waitable_event.h" #include "base/test/test_timeouts.h" #include "mojo/edk/system/channel_test_base.h" @@ -64,7 +67,8 @@ TEST_F(ChannelEndpointTest, Basic) { // Make a test message. unsigned message_id = 0x12345678; - scoped_ptr send_message = test::MakeTestMessage(message_id); + std::unique_ptr send_message = + test::MakeTestMessage(message_id); // Check that our test utility works (at least in one direction). test::VerifyTestMessage(send_message.get(), message_id); @@ -72,7 +76,7 @@ TEST_F(ChannelEndpointTest, Basic) { EXPECT_FALSE(read_event.IsSignaled()); // Send it through channel/endpoint 1. - EXPECT_TRUE(endpoint1->EnqueueMessage(send_message.Pass())); + EXPECT_TRUE(endpoint1->EnqueueMessage(std::move(send_message))); // Wait to receive it. EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout())); @@ -80,7 +84,7 @@ TEST_F(ChannelEndpointTest, Basic) { // Check the received message. ASSERT_EQ(1u, client0->NumMessages()); - scoped_ptr read_message = client0->PopMessage(); + std::unique_ptr read_message = client0->PopMessage(); ASSERT_TRUE(read_message); test::VerifyTestMessage(read_message.get(), message_id); } @@ -126,7 +130,7 @@ TEST_F(ChannelEndpointTest, Prequeued) { // Check the received messages. ASSERT_EQ(6u, client0->NumMessages()); for (unsigned message_id = 1; message_id <= 6; message_id++) { - scoped_ptr read_message = client0->PopMessage(); + std::unique_ptr read_message = client0->PopMessage(); ASSERT_TRUE(read_message); test::VerifyTestMessage(read_message.get(), message_id); } diff --git a/mojo/edk/system/channel_manager.h b/mojo/edk/system/channel_manager.h index 1ff958ddd10..dc2ca7e111c 100644 --- a/mojo/edk/system/channel_manager.h +++ b/mojo/edk/system/channel_manager.h @@ -7,8 +7,9 @@ #include +#include + #include "base/callback_forward.h" -#include "base/containers/hash_tables.h" #include "base/memory/ref_counted.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/channel_id.h" @@ -35,7 +36,7 @@ class MessagePipeDispatcher; // This class manages and "owns" |Channel|s (which typically connect to other // processes) for a given process. This class is thread-safe, except as // specifically noted. -class MOJO_SYSTEM_IMPL_EXPORT ChannelManager { +class ChannelManager { public: // |io_thread_task_runner| should be the |TaskRunner| for the I/O thread, on // which this channel manager will create all channels. Connection manager is @@ -151,7 +152,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelManager { mutable Mutex mutex_; using ChannelIdToChannelMap = - base::hash_map>; + std::unordered_map>; ChannelIdToChannelMap channels_ MOJO_GUARDED_BY(mutex_); MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelManager); diff --git a/mojo/edk/system/channel_test_base.cc b/mojo/edk/system/channel_test_base.cc index 15bc607d3dd..df90d3a6d04 100644 --- a/mojo/edk/system/channel_test_base.cc +++ b/mojo/edk/system/channel_test_base.cc @@ -4,6 +4,8 @@ #include "mojo/edk/system/channel_test_base.h" +#include + #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "mojo/edk/embedder/platform_channel_pair.h" @@ -14,8 +16,7 @@ namespace system { namespace test { ChannelTestBase::ChannelTestBase() - : io_thread_(base::TestIOThread::kAutoStart) { -} + : io_thread_(mojo::test::TestIOThread::kAutoStart) {} ChannelTestBase::~ChannelTestBase() { } @@ -36,7 +37,7 @@ void ChannelTestBase::InitChannelOnIOThread(unsigned i) { CHECK(raw_channels_[i]); CHECK(channels_[i]); - channels_[i]->Init(raw_channels_[i].Pass()); + channels_[i]->Init(std::move(raw_channels_[i])); } void ChannelTestBase::CreateAndInitChannelOnIOThread(unsigned i) { @@ -51,6 +52,11 @@ void ChannelTestBase::ShutdownChannelOnIOThread(unsigned i) { channels_[i]->Shutdown(); } +void ChannelTestBase::ShutdownAndReleaseChannelOnIOThread(unsigned i) { + ShutdownChannelOnIOThread(i); + channels_[i] = nullptr; +} + void ChannelTestBase::SetUpOnIOThread() { CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); diff --git a/mojo/edk/system/channel_test_base.h b/mojo/edk/system/channel_test_base.h index a177418b764..b1e81d7ba2d 100644 --- a/mojo/edk/system/channel_test_base.h +++ b/mojo/edk/system/channel_test_base.h @@ -5,13 +5,14 @@ #ifndef MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_ #define MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_ +#include + #include "base/bind.h" #include "base/location.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/test/test_io_thread.h" #include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/edk/system/channel.h" +#include "mojo/edk/test/test_io_thread.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -43,8 +44,9 @@ class ChannelTestBase : public testing::Test { void InitChannelOnIOThread(unsigned i); void CreateAndInitChannelOnIOThread(unsigned i); void ShutdownChannelOnIOThread(unsigned i); + void ShutdownAndReleaseChannelOnIOThread(unsigned i); - base::TestIOThread* io_thread() { return &io_thread_; } + mojo::test::TestIOThread* io_thread() { return &io_thread_; } Channel* channel(unsigned i) { return channels_[i].get(); } scoped_refptr* mutable_channel(unsigned i) { return &channels_[i]; } @@ -52,8 +54,8 @@ class ChannelTestBase : public testing::Test { void SetUpOnIOThread(); embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; - scoped_ptr raw_channels_[2]; + mojo::test::TestIOThread io_thread_; + std::unique_ptr raw_channels_[2]; scoped_refptr channels_[2]; MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelTestBase); diff --git a/mojo/edk/system/channel_unittest.cc b/mojo/edk/system/channel_unittest.cc index 5f2f6eb7211..9f65f63cf01 100644 --- a/mojo/edk/system/channel_unittest.cc +++ b/mojo/edk/system/channel_unittest.cc @@ -17,6 +17,8 @@ namespace { using ChannelTest = test::ChannelTestBase; +void DoNothing() {} + // ChannelTest.InitShutdown ---------------------------------------------------- TEST_F(ChannelTest, InitShutdown) { @@ -114,6 +116,34 @@ TEST_F(ChannelTest, WaitAfterAttachRunAndShutdown) { EXPECT_TRUE(channel(0)->HasOneRef()); } +// ChannelTest.EndpointChannelShutdownRace ------------------------------------- + +TEST_F(ChannelTest, EndpointChannelShutdownRace) { + const size_t kIterations = 1000; + + for (size_t i = 0; i < kIterations; i++) { + // Need a new set of |RawChannel|s on every iteration. + SetUp(); + PostMethodToIOThreadAndWait( + FROM_HERE, &ChannelTest::CreateAndInitChannelOnIOThread, 0); + + scoped_refptr channel_endpoint; + scoped_refptr mp( + MessagePipe::CreateLocalProxy(&channel_endpoint)); + + channel(0)->SetBootstrapEndpoint(channel_endpoint); + + io_thread()->PostTask( + FROM_HERE, base::Bind(&ChannelTest::ShutdownAndReleaseChannelOnIOThread, + base::Unretained(this), 0)); + mp->Close(0); + + // Wait for the IO thread to finish shutting down the channel. + io_thread()->PostTaskAndWait(FROM_HERE, base::Bind(&DoNothing)); + EXPECT_FALSE(channel(0)); + } +} + // TODO(vtl): More. ------------------------------------------------------------ } // namespace diff --git a/mojo/edk/system/configuration.h b/mojo/edk/system/configuration.h index 007277ade94..a923d384900 100644 --- a/mojo/edk/system/configuration.h +++ b/mojo/edk/system/configuration.h @@ -6,22 +6,19 @@ #define MOJO_EDK_SYSTEM_CONFIGURATION_H_ #include "mojo/edk/embedder/configuration.h" -#include "mojo/edk/system/system_impl_export.h" namespace mojo { namespace system { namespace internal { -MOJO_SYSTEM_IMPL_EXPORT extern embedder::Configuration g_configuration; +extern embedder::Configuration g_configuration; } // namespace internal -MOJO_SYSTEM_IMPL_EXPORT inline const embedder::Configuration& -GetConfiguration() { +inline const embedder::Configuration& GetConfiguration() { return internal::g_configuration; } -MOJO_SYSTEM_IMPL_EXPORT inline embedder::Configuration* -GetMutableConfiguration() { +inline embedder::Configuration* GetMutableConfiguration() { return &internal::g_configuration; } diff --git a/mojo/edk/system/connection_manager.h b/mojo/edk/system/connection_manager.h index e0c3a6f7003..7cc0801fd98 100644 --- a/mojo/edk/system/connection_manager.h +++ b/mojo/edk/system/connection_manager.h @@ -9,7 +9,6 @@ #include "mojo/edk/system/connection_identifier.h" #include "mojo/edk/system/process_identifier.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/edk/system/thread_annotations.h" #include "mojo/public/cpp/system/macros.h" @@ -60,7 +59,7 @@ namespace system { // connected to the master by a special dedicated |RawChannel|, on which it does // synchronous IPC (note, however, that the master should never block on any // slave). -class MOJO_SYSTEM_IMPL_EXPORT ConnectionManager { +class ConnectionManager { public: enum class Result { FAILURE = 0, @@ -122,9 +121,8 @@ class MOJO_SYSTEM_IMPL_EXPORT ConnectionManager { }; // So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - ConnectionManager::Result result) { +inline std::ostream& operator<<(std::ostream& out, + ConnectionManager::Result result) { return out << static_cast(result); } diff --git a/mojo/edk/system/connection_manager_messages.h b/mojo/edk/system/connection_manager_messages.h index 4117f953682..3e864949ceb 100644 --- a/mojo/edk/system/connection_manager_messages.h +++ b/mojo/edk/system/connection_manager_messages.h @@ -8,12 +8,13 @@ #include #include "mojo/edk/system/process_identifier.h" -#include "mojo/edk/system/system_impl_export.h" +#include "mojo/public/c/system/macros.h" namespace mojo { namespace system { -struct ConnectionManagerAckSuccessConnectData { +// Align as 8 bytes to force 32/64-bit architectures to match size. +struct MOJO_ALIGNAS(8) ConnectionManagerAckSuccessConnectData { // Set to the process identifier of the process that the receiver of this ack // ack should connect to. ProcessIdentifier peer_process_identifier; diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index fbb6cf1fbf9..450897c7ee4 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc @@ -4,10 +4,11 @@ #include "mojo/edk/system/core.h" +#include +#include #include #include "base/logging.h" -#include "base/time/time.h" #include "mojo/edk/embedder/platform_shared_buffer.h" #include "mojo/edk/embedder/platform_support.h" #include "mojo/edk/system/async_waiter.h" @@ -77,7 +78,6 @@ namespace system { // - Locks at the "INF" level may not have any locks taken while they are // held. -// TODO(vtl): This should take a |scoped_ptr| as a parameter. Core::Core(embedder::PlatformSupport* platform_support) : platform_support_(platform_support) { } @@ -113,7 +113,7 @@ MojoResult Core::AsyncWait(MojoHandle handle, scoped_refptr dispatcher = GetDispatcher(handle); DCHECK(dispatcher); - scoped_ptr waiter = make_scoped_ptr(new AsyncWaiter(callback)); + std::unique_ptr waiter(new AsyncWaiter(callback)); MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr); if (rv == MOJO_RESULT_OK) ignore_result(waiter.release()); @@ -121,7 +121,7 @@ MojoResult Core::AsyncWait(MojoHandle handle, } MojoTimeTicks Core::GetTimeTicksNow() { - return base::TimeTicks::Now().ToInternalValue(); + return platform_support_->GetTimeTicksNow(); } MojoResult Core::Close(MojoHandle handle) { @@ -531,7 +531,7 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle, if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; - scoped_ptr mapping; + std::unique_ptr mapping; MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); if (result != MOJO_RESULT_OK) return result; @@ -540,7 +540,7 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle, void* address = mapping->GetBase(); { MutexLocker locker(&mapping_table_mutex_); - result = mapping_table_.AddMapping(mapping.Pass()); + result = mapping_table_.AddMapping(std::move(mapping)); } if (result != MOJO_RESULT_OK) return result; diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h index 4ed5edeedc3..303f740bd01 100644 --- a/mojo/edk/system/core.h +++ b/mojo/edk/system/core.h @@ -9,12 +9,10 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/handle_table.h" #include "mojo/edk/system/mapping_table.h" #include "mojo/edk/system/memory.h" #include "mojo/edk/system/mutex.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" @@ -34,7 +32,7 @@ struct HandleSignalsState; // |Core| is an object that implements the Mojo system calls. All public methods // are thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT Core { +class Core { public: // --------------------------------------------------------------------------- diff --git a/mojo/edk/system/data_pipe.cc b/mojo/edk/system/data_pipe.cc index c46de2cc1e0..a18c72de7b6 100644 --- a/mojo/edk/system/data_pipe.cc +++ b/mojo/edk/system/data_pipe.cc @@ -8,6 +8,8 @@ #include #include +#include +#include #include "base/logging.h" #include "base/memory/aligned_memory.h" @@ -21,6 +23,7 @@ #include "mojo/edk/system/options_validation.h" #include "mojo/edk/system/remote_consumer_data_pipe_impl.h" #include "mojo/edk/system/remote_producer_data_pipe_impl.h" +#include "mojo/edk/util/make_unique.h" namespace mojo { namespace system { @@ -94,7 +97,7 @@ MojoResult DataPipe::ValidateCreateOptions( DataPipe* DataPipe::CreateLocal( const MojoCreateDataPipeOptions& validated_options) { return new DataPipe(true, true, validated_options, - make_scoped_ptr(new LocalDataPipeImpl())); + util::MakeUnique()); } // static @@ -102,7 +105,7 @@ DataPipe* DataPipe::CreateRemoteProducerFromExisting( const MojoCreateDataPipeOptions& validated_options, MessageInTransitQueue* message_queue, ChannelEndpoint* channel_endpoint) { - scoped_ptr buffer; + std::unique_ptr buffer; size_t buffer_num_bytes = 0; if (!RemoteProducerDataPipeImpl::ProcessMessagesFromIncomingEndpoint( validated_options, message_queue, &buffer, &buffer_num_bytes)) @@ -115,10 +118,10 @@ DataPipe* DataPipe::CreateRemoteProducerFromExisting( // ongoing call to |IncomingEndpoint::OnReadMessage()| return false. This will // make |ChannelEndpoint::OnReadMessage()| retry, until its |ReplaceClient()| // is called. - DataPipe* data_pipe = - new DataPipe(false, true, validated_options, - make_scoped_ptr(new RemoteProducerDataPipeImpl( - channel_endpoint, buffer.Pass(), 0, buffer_num_bytes))); + DataPipe* data_pipe = new DataPipe( + false, true, validated_options, + util::MakeUnique( + channel_endpoint, std::move(buffer), 0, buffer_num_bytes)); if (channel_endpoint) { if (!channel_endpoint->ReplaceClient(data_pipe, 0)) data_pipe->OnDetachFromChannel(0); @@ -147,8 +150,8 @@ DataPipe* DataPipe::CreateRemoteConsumerFromExisting( // is called. DataPipe* data_pipe = new DataPipe(true, false, validated_options, - make_scoped_ptr(new RemoteConsumerDataPipeImpl( - channel_endpoint, consumer_num_bytes))); + util::MakeUnique( + channel_endpoint, consumer_num_bytes, nullptr, 0)); if (channel_endpoint) { if (!channel_endpoint->ReplaceClient(data_pipe, 0)) data_pipe->OnDetachFromChannel(0); @@ -195,7 +198,7 @@ bool DataPipe::ProducerDeserialize(Channel* channel, *data_pipe = new DataPipe( true, false, revalidated_options, - make_scoped_ptr(new RemoteConsumerDataPipeImpl(nullptr, 0))); + util::MakeUnique(nullptr, 0, nullptr, 0)); (*data_pipe)->SetConsumerClosed(); return true; @@ -262,20 +265,20 @@ bool DataPipe::ConsumerDeserialize(Channel* channel, } void DataPipe::ProducerCancelAllAwakables() { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); producer_awakable_list_->CancelAll(); } void DataPipe::ProducerClose() { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); ProducerCloseNoLock(); } MojoResult DataPipe::ProducerWriteData(UserPointer elements, UserPointer num_bytes, bool all_or_none) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); if (producer_in_two_phase_write_no_lock()) @@ -308,7 +311,7 @@ MojoResult DataPipe::ProducerBeginWriteData( UserPointer buffer, UserPointer buffer_num_bytes, bool all_or_none) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); if (producer_in_two_phase_write_no_lock()) @@ -336,7 +339,7 @@ MojoResult DataPipe::ProducerBeginWriteData( } MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); if (!producer_in_two_phase_write_no_lock()) @@ -370,7 +373,7 @@ MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { } HandleSignalsState DataPipe::ProducerGetHandleSignalsState() { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); return impl_->ProducerGetHandleSignalsState(); } @@ -379,7 +382,7 @@ MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable, MojoHandleSignals signals, uint32_t context, HandleSignalsState* signals_state) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); HandleSignalsState producer_state = impl_->ProducerGetHandleSignalsState(); @@ -400,7 +403,7 @@ MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable, void DataPipe::ProducerRemoveAwakable(Awakable* awakable, HandleSignalsState* signals_state) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); producer_awakable_list_->Remove(awakable); if (signals_state) @@ -410,7 +413,7 @@ void DataPipe::ProducerRemoveAwakable(Awakable* awakable, void DataPipe::ProducerStartSerialize(Channel* channel, size_t* max_size, size_t* max_platform_handles) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); impl_->ProducerStartSerialize(channel, max_size, max_platform_handles); } @@ -420,7 +423,7 @@ bool DataPipe::ProducerEndSerialize( void* destination, size_t* actual_size, embedder::PlatformHandleVector* platform_handles) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_producer_no_lock()); // Warning: After |ProducerEndSerialize()|, quite probably |impl_| has // changed. @@ -443,18 +446,18 @@ bool DataPipe::ProducerEndSerialize( } bool DataPipe::ProducerIsBusy() const { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); return producer_in_two_phase_write_no_lock(); } void DataPipe::ConsumerCancelAllAwakables() { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); consumer_awakable_list_->CancelAll(); } void DataPipe::ConsumerClose() { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); ConsumerCloseNoLock(); } @@ -462,7 +465,7 @@ MojoResult DataPipe::ConsumerReadData(UserPointer elements, UserPointer num_bytes, bool all_or_none, bool peek) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); if (consumer_in_two_phase_read_no_lock()) @@ -490,7 +493,7 @@ MojoResult DataPipe::ConsumerReadData(UserPointer elements, MojoResult DataPipe::ConsumerDiscardData(UserPointer num_bytes, bool all_or_none) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); if (consumer_in_two_phase_read_no_lock()) @@ -518,7 +521,7 @@ MojoResult DataPipe::ConsumerDiscardData(UserPointer num_bytes, } MojoResult DataPipe::ConsumerQueryData(UserPointer num_bytes) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); if (consumer_in_two_phase_read_no_lock()) @@ -532,7 +535,7 @@ MojoResult DataPipe::ConsumerBeginReadData( UserPointer buffer, UserPointer buffer_num_bytes, bool all_or_none) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); if (consumer_in_two_phase_read_no_lock()) @@ -554,7 +557,7 @@ MojoResult DataPipe::ConsumerBeginReadData( } MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); if (!consumer_in_two_phase_read_no_lock()) @@ -586,7 +589,7 @@ MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { } HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); return impl_->ConsumerGetHandleSignalsState(); } @@ -595,7 +598,7 @@ MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable, MojoHandleSignals signals, uint32_t context, HandleSignalsState* signals_state) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); HandleSignalsState consumer_state = impl_->ConsumerGetHandleSignalsState(); @@ -616,7 +619,7 @@ MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable, void DataPipe::ConsumerRemoveAwakable(Awakable* awakable, HandleSignalsState* signals_state) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); consumer_awakable_list_->Remove(awakable); if (signals_state) @@ -626,7 +629,7 @@ void DataPipe::ConsumerRemoveAwakable(Awakable* awakable, void DataPipe::ConsumerStartSerialize(Channel* channel, size_t* max_size, size_t* max_platform_handles) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); impl_->ConsumerStartSerialize(channel, max_size, max_platform_handles); } @@ -636,7 +639,7 @@ bool DataPipe::ConsumerEndSerialize( void* destination, size_t* actual_size, embedder::PlatformHandleVector* platform_handles) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(has_local_consumer_no_lock()); // Warning: After |ConsumerEndSerialize()|, quite probably |impl_| has // changed. @@ -658,14 +661,14 @@ bool DataPipe::ConsumerEndSerialize( } bool DataPipe::ConsumerIsBusy() const { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); return consumer_in_two_phase_read_no_lock(); } DataPipe::DataPipe(bool has_local_producer, bool has_local_consumer, const MojoCreateDataPipeOptions& validated_options, - scoped_ptr impl) + std::unique_ptr impl) : validated_options_(validated_options), producer_open_(true), consumer_open_(true), @@ -675,7 +678,7 @@ DataPipe::DataPipe(bool has_local_producer, : nullptr), producer_two_phase_max_num_bytes_written_(0), consumer_two_phase_max_num_bytes_read_(0), - impl_(impl.Pass()) { + impl_(std::move(impl)) { impl_->set_owner(this); #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) @@ -693,34 +696,34 @@ DataPipe::~DataPipe() { DCHECK(!consumer_awakable_list_); } -scoped_ptr DataPipe::ReplaceImplNoLock( - scoped_ptr new_impl) { - lock_.AssertAcquired(); +std::unique_ptr DataPipe::ReplaceImplNoLock( + std::unique_ptr new_impl) { + mutex_.AssertHeld(); DCHECK(new_impl); impl_->set_owner(nullptr); - scoped_ptr rv(impl_.Pass()); - impl_ = new_impl.Pass(); + std::unique_ptr rv(std::move(impl_)); + impl_ = std::move(new_impl); impl_->set_owner(this); - return rv.Pass(); + return rv; } void DataPipe::SetProducerClosedNoLock() { - lock_.AssertAcquired(); + mutex_.AssertHeld(); DCHECK(!has_local_producer_no_lock()); DCHECK(producer_open_); producer_open_ = false; } void DataPipe::SetConsumerClosedNoLock() { - lock_.AssertAcquired(); + mutex_.AssertHeld(); DCHECK(!has_local_consumer_no_lock()); DCHECK(consumer_open_); consumer_open_ = false; } void DataPipe::ProducerCloseNoLock() { - lock_.AssertAcquired(); + mutex_.AssertHeld(); DCHECK(producer_open_); producer_open_ = false; if (has_local_producer_no_lock()) { @@ -736,7 +739,7 @@ void DataPipe::ProducerCloseNoLock() { } void DataPipe::ConsumerCloseNoLock() { - lock_.AssertAcquired(); + mutex_.AssertHeld(); DCHECK(consumer_open_); consumer_open_ = false; if (has_local_consumer_no_lock()) { @@ -752,7 +755,7 @@ void DataPipe::ConsumerCloseNoLock() { } bool DataPipe::OnReadMessage(unsigned port, MessageInTransit* message) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(!has_local_producer_no_lock() || !has_local_consumer_no_lock()); HandleSignalsState old_producer_state = @@ -775,7 +778,7 @@ bool DataPipe::OnReadMessage(unsigned port, MessageInTransit* message) { } void DataPipe::OnDetachFromChannel(unsigned port) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(!has_local_producer_no_lock() || !has_local_consumer_no_lock()); HandleSignalsState old_producer_state = @@ -797,7 +800,7 @@ void DataPipe::OnDetachFromChannel(unsigned port) { void DataPipe::AwakeProducerAwakablesForStateChangeNoLock( const HandleSignalsState& new_producer_state) { - lock_.AssertAcquired(); + mutex_.AssertHeld(); if (!has_local_producer_no_lock()) return; producer_awakable_list_->AwakeForStateChange(new_producer_state); @@ -805,19 +808,19 @@ void DataPipe::AwakeProducerAwakablesForStateChangeNoLock( void DataPipe::AwakeConsumerAwakablesForStateChangeNoLock( const HandleSignalsState& new_consumer_state) { - lock_.AssertAcquired(); + mutex_.AssertHeld(); if (!has_local_consumer_no_lock()) return; consumer_awakable_list_->AwakeForStateChange(new_consumer_state); } void DataPipe::SetProducerClosed() { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); SetProducerClosedNoLock(); } void DataPipe::SetConsumerClosed() { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); SetConsumerClosedNoLock(); } diff --git a/mojo/edk/system/data_pipe.h b/mojo/edk/system/data_pipe.h index 1e0b64ff2ce..c5a1c645225 100644 --- a/mojo/edk/system/data_pipe.h +++ b/mojo/edk/system/data_pipe.h @@ -7,14 +7,15 @@ #include +#include + #include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/system/channel_endpoint_client.h" #include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/memory.h" -#include "mojo/edk/system/system_impl_export.h" +#include "mojo/edk/system/mutex.h" +#include "mojo/edk/system/thread_annotations.h" #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -35,7 +36,7 @@ class MessageInTransitQueue; // Its subclasses implement the three cases: local producer and consumer, local // producer and remote consumer, and remote producer and local consumer. This // class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT DataPipe final : public ChannelEndpointClient { +class DataPipe final : public ChannelEndpointClient { public: // The default options for |MojoCreateDataPipe()|. (Real uses should obtain // this via |ValidateCreateOptions()| with a null |in_options|; this is @@ -164,14 +165,16 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe final : public ChannelEndpointClient { // serializing data pipe dispatchers (i.e., in |ProducerEndSerialize()| and // |ConsumerEndSerialize()|). Returns the old value of |impl_| (in case the // caller needs to manage its lifetime). - scoped_ptr ReplaceImplNoLock(scoped_ptr new_impl); - void SetProducerClosedNoLock(); - void SetConsumerClosedNoLock(); + std::unique_ptr ReplaceImplNoLock( + std::unique_ptr new_impl) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void SetProducerClosedNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void SetConsumerClosedNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void ProducerCloseNoLock(); - void ConsumerCloseNoLock(); + void ProducerCloseNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void ConsumerCloseNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - // Thread-safe and fast (they don't take the lock): + // Thread-safe and fast (they don't take |mutex_|): const MojoCreateDataPipeOptions& validated_options() const { return validated_options_; } @@ -182,38 +185,43 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe final : public ChannelEndpointClient { return validated_options_.capacity_num_bytes; } - // Must be called under lock. - bool producer_open_no_lock() const { - lock_.AssertAcquired(); + // Must be called under |mutex_|. + bool producer_open_no_lock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); return producer_open_; } - bool consumer_open_no_lock() const { - lock_.AssertAcquired(); + bool consumer_open_no_lock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); return consumer_open_; } - uint32_t producer_two_phase_max_num_bytes_written_no_lock() const { - lock_.AssertAcquired(); + uint32_t producer_two_phase_max_num_bytes_written_no_lock() const + MOJO_SHARED_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); return producer_two_phase_max_num_bytes_written_; } - uint32_t consumer_two_phase_max_num_bytes_read_no_lock() const { - lock_.AssertAcquired(); + uint32_t consumer_two_phase_max_num_bytes_read_no_lock() const + MOJO_SHARED_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); return consumer_two_phase_max_num_bytes_read_; } - void set_producer_two_phase_max_num_bytes_written_no_lock( - uint32_t num_bytes) { - lock_.AssertAcquired(); + void set_producer_two_phase_max_num_bytes_written_no_lock(uint32_t num_bytes) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); producer_two_phase_max_num_bytes_written_ = num_bytes; } - void set_consumer_two_phase_max_num_bytes_read_no_lock(uint32_t num_bytes) { - lock_.AssertAcquired(); + void set_consumer_two_phase_max_num_bytes_read_no_lock(uint32_t num_bytes) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); consumer_two_phase_max_num_bytes_read_ = num_bytes; } - bool producer_in_two_phase_write_no_lock() const { - lock_.AssertAcquired(); + bool producer_in_two_phase_write_no_lock() const + MOJO_SHARED_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); return producer_two_phase_max_num_bytes_written_ > 0; } - bool consumer_in_two_phase_read_no_lock() const { - lock_.AssertAcquired(); + bool consumer_in_two_phase_read_no_lock() const + MOJO_SHARED_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); return consumer_two_phase_max_num_bytes_read_ > 0; } @@ -229,7 +237,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe final : public ChannelEndpointClient { DataPipe(bool has_local_producer, bool has_local_consumer, const MojoCreateDataPipeOptions& validated_options, - scoped_ptr impl); + std::unique_ptr impl); ~DataPipe() override; // |ChannelEndpointClient| implementation: @@ -237,36 +245,38 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe final : public ChannelEndpointClient { void OnDetachFromChannel(unsigned port) override; void AwakeProducerAwakablesForStateChangeNoLock( - const HandleSignalsState& new_producer_state); + const HandleSignalsState& new_producer_state) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); void AwakeConsumerAwakablesForStateChangeNoLock( - const HandleSignalsState& new_consumer_state); + const HandleSignalsState& new_consumer_state) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); void SetProducerClosed(); void SetConsumerClosed(); - bool has_local_producer_no_lock() const { - lock_.AssertAcquired(); + bool has_local_producer_no_lock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); return !!producer_awakable_list_; } - bool has_local_consumer_no_lock() const { - lock_.AssertAcquired(); + bool has_local_consumer_no_lock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_) { + mutex_.AssertHeld(); return !!consumer_awakable_list_; } MSVC_SUPPRESS_WARNING(4324) const MojoCreateDataPipeOptions validated_options_; - mutable base::Lock lock_; // Protects the following members. + mutable Mutex mutex_; // *Known* state of producer or consumer. - bool producer_open_; - bool consumer_open_; + bool producer_open_ MOJO_GUARDED_BY(mutex_); + bool consumer_open_ MOJO_GUARDED_BY(mutex_); // Non-null only if the producer or consumer, respectively, is local. - scoped_ptr producer_awakable_list_; - scoped_ptr consumer_awakable_list_; + std::unique_ptr producer_awakable_list_ MOJO_GUARDED_BY(mutex_); + std::unique_ptr consumer_awakable_list_ MOJO_GUARDED_BY(mutex_); // These are nonzero if and only if a two-phase write/read is in progress. - uint32_t producer_two_phase_max_num_bytes_written_; - uint32_t consumer_two_phase_max_num_bytes_read_; - scoped_ptr impl_; + uint32_t producer_two_phase_max_num_bytes_written_ MOJO_GUARDED_BY(mutex_); + uint32_t consumer_two_phase_max_num_bytes_read_ MOJO_GUARDED_BY(mutex_); + std::unique_ptr impl_ MOJO_GUARDED_BY(mutex_); MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipe); }; diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.h b/mojo/edk/system/data_pipe_consumer_dispatcher.h index 29df228efc0..8a541a84ab9 100644 --- a/mojo/edk/system/data_pipe_consumer_dispatcher.h +++ b/mojo/edk/system/data_pipe_consumer_dispatcher.h @@ -7,7 +7,6 @@ #include "base/memory/ref_counted.h" #include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -18,8 +17,7 @@ class DataPipe; // 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 { +class DataPipeConsumerDispatcher final : public Dispatcher { public: static scoped_refptr Create() { return make_scoped_refptr(new DataPipeConsumerDispatcher()); diff --git a/mojo/edk/system/data_pipe_impl.cc b/mojo/edk/system/data_pipe_impl.cc index 6c19297c6de..91ddb02af82 100644 --- a/mojo/edk/system/data_pipe_impl.cc +++ b/mojo/edk/system/data_pipe_impl.cc @@ -5,9 +5,10 @@ #include "mojo/edk/system/data_pipe_impl.h" #include +#include +#include #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/message_in_transit.h" #include "mojo/edk/system/message_in_transit_queue.h" @@ -34,11 +35,11 @@ void DataPipeImpl::ConvertDataToMessages(const char* buffer, std::min(max_message_num_bytes, current_contiguous_num_bytes); // Note: |message_num_bytes| fits in a |uint32_t| since the capacity does. - scoped_ptr message(new MessageInTransit( + std::unique_ptr message(new MessageInTransit( MessageInTransit::Type::ENDPOINT_CLIENT, MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, static_cast(message_num_bytes), buffer + *start_index)); - message_queue->AddMessage(message.Pass()); + message_queue->AddMessage(std::move(message)); DCHECK_LE(message_num_bytes, *current_num_bytes); *start_index += message_num_bytes; diff --git a/mojo/edk/system/data_pipe_impl.h b/mojo/edk/system/data_pipe_impl.h index 4dac32dee50..eff67353894 100644 --- a/mojo/edk/system/data_pipe_impl.h +++ b/mojo/edk/system/data_pipe_impl.h @@ -7,11 +7,13 @@ #include +#include + #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/system/data_pipe.h" #include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/memory.h" -#include "mojo/edk/system/system_impl_export.h" +#include "mojo/edk/system/thread_annotations.h" #include "mojo/public/c/system/data_pipe.h" #include "mojo/public/c/system/macros.h" #include "mojo/public/c/system/types.h" @@ -25,8 +27,29 @@ class MessageInTransit; // Base class/interface for classes that "implement" |DataPipe| for various // situations (local versus remote). The methods, other than the constructor, // |set_owner()|, and the destructor, are always protected by |DataPipe|'s -// |lock_|. -class MOJO_SYSTEM_IMPL_EXPORT DataPipeImpl { +// |mutex_|. +// +// Methods that access |owner_| are marked |MOJO_NO_THREAD_SAFETY_ANALYSIS| for +// the reason described below. +// +// Ideally, they'd be marked as requiring |owner_->mutex_|, but then we'd have +// trouble with the |DataPipe| methods that call |DataPipeImpl| methods (via +// |DataPipe|'s |impl_| member): we cannot tell the compiler that |impl_->owner_ +// == this| in |DataPipe| methods, so that taking |mutex_| is equivalent to +// taking |impl_->owner_->mutex_|. +// +// Since |DataPipeImpl| methods are only called by |DataPipe| methods (which are +// required to hold |mutex_| since |impl_| marked as being guarded by it) and by +// |DataPipeImpl| and subclasses' methods (which are all transitively under +// |mutex_|, having originated from a call from |DataPipe|), we choose to turn +// off thread-safety analysis for our methods, which are trivial (they just +// thunk to |owner_|), rather than turn off thread-safety analysis for +// |DataPipe|'s methods, which aren't. + +// Note that subclasses do not have access to the owning |DataPipe| (except as a +// |ChannelEndpointClient|), so that their methods should never need +// |MOJO_NO_THREAD_SAFETY_ANALYSIS| annotations. +class DataPipeImpl { public: virtual ~DataPipeImpl() {} @@ -98,31 +121,50 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeImpl { size_t* current_num_bytes, MessageInTransitQueue* message_queue); - DataPipe* owner() const { return owner_; } + std::unique_ptr ReplaceImpl( + std::unique_ptr new_impl) MOJO_NO_THREAD_SAFETY_ANALYSIS { + return owner_->ReplaceImplNoLock(std::move(new_impl)); + } + void SetProducerClosed() MOJO_NO_THREAD_SAFETY_ANALYSIS { + owner_->SetProducerClosedNoLock(); + } + void SetConsumerClosed() MOJO_NO_THREAD_SAFETY_ANALYSIS { + owner_->SetConsumerClosedNoLock(); + } + + ChannelEndpointClient* channel_endpoint_client() const { return owner_; } const MojoCreateDataPipeOptions& validated_options() const { return owner_->validated_options(); } size_t element_num_bytes() const { return owner_->element_num_bytes(); } size_t capacity_num_bytes() const { return owner_->capacity_num_bytes(); } - bool producer_open() const { return owner_->producer_open_no_lock(); } - bool consumer_open() const { return owner_->consumer_open_no_lock(); } - uint32_t producer_two_phase_max_num_bytes_written() const { + bool producer_open() const MOJO_NO_THREAD_SAFETY_ANALYSIS { + return owner_->producer_open_no_lock(); + } + bool consumer_open() const MOJO_NO_THREAD_SAFETY_ANALYSIS { + return owner_->consumer_open_no_lock(); + } + uint32_t producer_two_phase_max_num_bytes_written() const + MOJO_NO_THREAD_SAFETY_ANALYSIS { return owner_->producer_two_phase_max_num_bytes_written_no_lock(); } - uint32_t consumer_two_phase_max_num_bytes_read() const { + uint32_t consumer_two_phase_max_num_bytes_read() const + MOJO_NO_THREAD_SAFETY_ANALYSIS { return owner_->consumer_two_phase_max_num_bytes_read_no_lock(); } - void set_producer_two_phase_max_num_bytes_written(uint32_t num_bytes) { + void set_producer_two_phase_max_num_bytes_written(uint32_t num_bytes) + MOJO_NO_THREAD_SAFETY_ANALYSIS { owner_->set_producer_two_phase_max_num_bytes_written_no_lock(num_bytes); } - void set_consumer_two_phase_max_num_bytes_read(uint32_t num_bytes) { + void set_consumer_two_phase_max_num_bytes_read(uint32_t num_bytes) + MOJO_NO_THREAD_SAFETY_ANALYSIS { owner_->set_consumer_two_phase_max_num_bytes_read_no_lock(num_bytes); } - bool producer_in_two_phase_write() const { + bool producer_in_two_phase_write() const MOJO_NO_THREAD_SAFETY_ANALYSIS { return owner_->producer_in_two_phase_write_no_lock(); } - bool consumer_in_two_phase_read() const { + bool consumer_in_two_phase_read() const MOJO_NO_THREAD_SAFETY_ANALYSIS { return owner_->consumer_in_two_phase_read_no_lock(); } diff --git a/mojo/edk/system/data_pipe_impl_unittest.cc b/mojo/edk/system/data_pipe_impl_unittest.cc index 0bc7506dbe6..3b19c5b8f77 100644 --- a/mojo/edk/system/data_pipe_impl_unittest.cc +++ b/mojo/edk/system/data_pipe_impl_unittest.cc @@ -9,12 +9,12 @@ #include +#include + #include "base/bind.h" #include "base/location.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" -#include "base/test/test_io_thread.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/edk/system/channel.h" @@ -27,6 +27,7 @@ #include "mojo/edk/system/raw_channel.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/system/waiter.h" +#include "mojo/edk/test/test_io_thread.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -180,7 +181,7 @@ class DataPipeImplTest : public testing::Test { DataPipe* dpp() { return helper_->DataPipeForProducer(); } DataPipe* dpc() { return helper_->DataPipeForConsumer(); } - scoped_ptr helper_; + std::unique_ptr helper_; MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipeImplTest); }; @@ -222,7 +223,8 @@ class LocalDataPipeImplTestHelper : public DataPipeImplTestHelper { // Base class for |Remote{Producer,Consumer}DataPipeImplTestHelper|. class RemoteDataPipeImplTestHelper : public DataPipeImplTestHelper { public: - RemoteDataPipeImplTestHelper() : io_thread_(base::TestIOThread::kAutoStart) {} + RemoteDataPipeImplTestHelper() + : io_thread_(mojo::test::TestIOThread::kAutoStart) {} ~RemoteDataPipeImplTestHelper() override {} void SetUp() override { @@ -343,7 +345,7 @@ class RemoteDataPipeImplTestHelper : public DataPipeImplTestHelper { } embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; + mojo::test::TestIOThread io_thread_; scoped_refptr channels_[2]; scoped_refptr message_pipes_[2]; diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.h b/mojo/edk/system/data_pipe_producer_dispatcher.h index 7ce51566001..53fa291da53 100644 --- a/mojo/edk/system/data_pipe_producer_dispatcher.h +++ b/mojo/edk/system/data_pipe_producer_dispatcher.h @@ -7,7 +7,6 @@ #include "base/memory/ref_counted.h" #include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -18,8 +17,7 @@ class DataPipe; // 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 { +class DataPipeProducerDispatcher final : public Dispatcher { public: static scoped_refptr Create() { return make_scoped_refptr(new DataPipeProducerDispatcher()); diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc index ad362fe5eac..e0ef182c6ac 100644 --- a/mojo/edk/system/dispatcher.cc +++ b/mojo/edk/system/dispatcher.cc @@ -208,7 +208,7 @@ MojoResult Dispatcher::MapBuffer( uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr* mapping) { + std::unique_ptr* mapping) { MutexLocker locker(&mutex_); if (is_closed_) return MOJO_RESULT_INVALID_ARGUMENT; @@ -360,7 +360,7 @@ MojoResult Dispatcher::MapBufferImplNoLock( uint64_t /*offset*/, uint64_t /*num_bytes*/, MojoMapBufferFlags /*flags*/, - scoped_ptr* /*mapping*/) { + std::unique_ptr* /*mapping*/) { mutex_.AssertHeld(); DCHECK(!is_closed_); // By default, not supported. Only needed for buffer dispatchers. diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h index 98b39f43a3f..4b0c558a248 100644 --- a/mojo/edk/system/dispatcher.h +++ b/mojo/edk/system/dispatcher.h @@ -8,16 +8,15 @@ #include #include +#include #include #include #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/memory.h" #include "mojo/edk/system/mutex.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" @@ -47,8 +46,7 @@ using DispatcherVector = std::vector>; namespace test { // Test helper. We need to declare it here so we can friend it. -MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport -DispatcherTryStartTransport(Dispatcher* dispatcher); +DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher); } // namespace test @@ -57,8 +55,7 @@ DispatcherTryStartTransport(Dispatcher* dispatcher); // object is thread-safe, with its state being protected by a single mutex // |mutex_|, which is also made available to implementation subclasses (via the // |mutex()| method). -class MOJO_SYSTEM_IMPL_EXPORT Dispatcher - : public base::RefCountedThreadSafe { +class Dispatcher : public base::RefCountedThreadSafe { public: enum class Type { UNKNOWN = 0, @@ -121,7 +118,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr* mapping); + std::unique_ptr* mapping); // Gets the current handle signals state. (The default implementation simply // returns a default-constructed |HandleSignalsState|, i.e., no signals @@ -272,7 +269,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr* mapping) + std::unique_ptr* mapping) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_); @@ -390,7 +387,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher // // Note: This class is deliberately "thin" -- no more expensive than a // |Dispatcher*|. -class MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport { +class DispatcherTransport { public: DispatcherTransport() : dispatcher_(nullptr) {} @@ -423,8 +420,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport { }; // So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out, - Dispatcher::Type type) { +inline std::ostream& operator<<(std::ostream& out, Dispatcher::Type type) { return out << static_cast(type); } diff --git a/mojo/edk/system/dispatcher_unittest.cc b/mojo/edk/system/dispatcher_unittest.cc index c6431ffea7b..1f95c514df0 100644 --- a/mojo/edk/system/dispatcher_unittest.cc +++ b/mojo/edk/system/dispatcher_unittest.cc @@ -4,6 +4,8 @@ #include "mojo/edk/system/dispatcher.h" +#include + #include "base/memory/ref_counted.h" #include "base/memory/scoped_vector.h" #include "base/synchronization/waitable_event.h" @@ -204,7 +206,7 @@ class ThreadSafetyStressThread : public base::SimpleThread { break; } case MAP_BUFFER: { - scoped_ptr unused; + std::unique_ptr unused; EXPECT_EQ( MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE, &unused)); diff --git a/mojo/edk/system/endpoint_relayer.cc b/mojo/edk/system/endpoint_relayer.cc index 9655f9cfb9f..5634db0cab2 100644 --- a/mojo/edk/system/endpoint_relayer.cc +++ b/mojo/edk/system/endpoint_relayer.cc @@ -4,6 +4,8 @@ #include "mojo/edk/system/endpoint_relayer.h" +#include + #include "base/logging.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/message_in_transit.h" @@ -30,9 +32,9 @@ void EndpointRelayer::Init(ChannelEndpoint* endpoint0, endpoints_[1] = endpoint1; } -void EndpointRelayer::SetFilter(scoped_ptr filter) { +void EndpointRelayer::SetFilter(std::unique_ptr filter) { MutexLocker locker(&mutex_); - filter_ = filter.Pass(); + filter_ = std::move(filter); } bool EndpointRelayer::OnReadMessage(unsigned port, MessageInTransit* message) { @@ -53,8 +55,10 @@ bool EndpointRelayer::OnReadMessage(unsigned port, MessageInTransit* message) { } // Otherwise, consume it even if the peer port is closed. - if (endpoints_[peer_port]) - endpoints_[peer_port]->EnqueueMessage(make_scoped_ptr(message)); + if (endpoints_[peer_port]) { + endpoints_[peer_port]->EnqueueMessage( + std::unique_ptr(message)); + } return true; } diff --git a/mojo/edk/system/endpoint_relayer.h b/mojo/edk/system/endpoint_relayer.h index cfeda2405ea..d30816790ab 100644 --- a/mojo/edk/system/endpoint_relayer.h +++ b/mojo/edk/system/endpoint_relayer.h @@ -5,11 +5,11 @@ #ifndef MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_ #define MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_ +#include + #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel_endpoint_client.h" #include "mojo/edk/system/mutex.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -19,8 +19,7 @@ class ChannelEndpoint; // This is a simple |ChannelEndpointClient| that just relays messages between // two |ChannelEndpoint|s (without the overhead of |MessagePipe|). -class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer final - : public ChannelEndpointClient { +class EndpointRelayer final : public ChannelEndpointClient { public: // A class that can inspect and optionally handle messages of type // |Type::ENDPOINT_CLIENT| received from either |ChannelEndpoint|. @@ -30,7 +29,7 @@ class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer final // // Destructors may not call methods of the |EndpointRelayer| (nor of the // |ChannelEndpoint|s). - class MOJO_SYSTEM_IMPL_EXPORT Filter { + class Filter { public: virtual ~Filter() {} @@ -73,7 +72,7 @@ class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer final // Sets (or resets) the filter, which can (optionally) handle/filter // |Type::ENDPOINT_CLIENT| messages (see |Filter| above). - void SetFilter(scoped_ptr filter); + void SetFilter(std::unique_ptr filter); // |ChannelEndpointClient| methods: bool OnReadMessage(unsigned port, MessageInTransit* message) override; @@ -84,7 +83,7 @@ class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer final Mutex mutex_; scoped_refptr endpoints_[2] MOJO_GUARDED_BY(mutex_); - scoped_ptr filter_ MOJO_GUARDED_BY(mutex_); + std::unique_ptr filter_ MOJO_GUARDED_BY(mutex_); MOJO_DISALLOW_COPY_AND_ASSIGN(EndpointRelayer); }; diff --git a/mojo/edk/system/endpoint_relayer_unittest.cc b/mojo/edk/system/endpoint_relayer_unittest.cc index 8cc9b23d8e3..276bfeeb2ec 100644 --- a/mojo/edk/system/endpoint_relayer_unittest.cc +++ b/mojo/edk/system/endpoint_relayer_unittest.cc @@ -12,6 +12,7 @@ #include "mojo/edk/system/message_in_transit_queue.h" #include "mojo/edk/system/message_in_transit_test_utils.h" #include "mojo/edk/system/test_channel_endpoint_client.h" +#include "mojo/edk/util/make_unique.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -98,7 +99,7 @@ TEST_F(EndpointRelayerTest, Basic) { client1b()->SetReadEvent(nullptr); ASSERT_EQ(1u, client1b()->NumMessages()); - scoped_ptr read_message = client1b()->PopMessage(); + std::unique_ptr read_message = client1b()->PopMessage(); ASSERT_TRUE(read_message); test::VerifyTestMessage(read_message.get(), 12345); @@ -136,7 +137,7 @@ TEST_F(EndpointRelayerTest, MultipleMessages) { // Check the received messages. ASSERT_EQ(5u, client1b()->NumMessages()); for (unsigned message_id = 1; message_id <= 5; message_id++) { - scoped_ptr read_message = client1b()->PopMessage(); + std::unique_ptr read_message = client1b()->PopMessage(); ASSERT_TRUE(read_message); test::VerifyTestMessage(read_message.get(), message_id); } @@ -169,7 +170,8 @@ class TestFilter : public EndpointRelayer::Filter { unsigned id = 0; if (test::IsTestMessage(message, &id) && id >= 1000) { - filtered_messages_->AddMessage(make_scoped_ptr(message)); + filtered_messages_->AddMessage( + std::unique_ptr(message)); return true; } @@ -184,7 +186,7 @@ class TestFilter : public EndpointRelayer::Filter { TEST_F(EndpointRelayerTest, Filter) { MessageInTransitQueue filtered_messages; - relayer()->SetFilter(make_scoped_ptr(new TestFilter(&filtered_messages))); + relayer()->SetFilter(util::MakeUnique(&filtered_messages)); EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1))); EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(2))); @@ -206,7 +208,7 @@ TEST_F(EndpointRelayerTest, Filter) { // Check the received messages: We should get "1"-"5". ASSERT_EQ(5u, client1b()->NumMessages()); for (unsigned message_id = 1; message_id <= 5; message_id++) { - scoped_ptr read_message = client1b()->PopMessage(); + std::unique_ptr read_message = client1b()->PopMessage(); ASSERT_TRUE(read_message); test::VerifyTestMessage(read_message.get(), message_id); } @@ -218,7 +220,7 @@ TEST_F(EndpointRelayerTest, Filter) { // the latter must have also been "received"/filtered. ASSERT_EQ(3u, filtered_messages.Size()); for (unsigned message_id = 1001; message_id <= 1003; message_id++) { - scoped_ptr message = filtered_messages.GetMessage(); + std::unique_ptr message = filtered_messages.GetMessage(); ASSERT_TRUE(message); test::VerifyTestMessage(message.get(), message_id); } diff --git a/mojo/edk/system/handle_signals_state.h b/mojo/edk/system/handle_signals_state.h index 78a3d65529e..8d3fb04f950 100644 --- a/mojo/edk/system/handle_signals_state.h +++ b/mojo/edk/system/handle_signals_state.h @@ -5,7 +5,6 @@ #ifndef MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ #define MOJO_EDK_SYSTEM_HANDLE_SIGNALS_STATE_H_ -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" namespace mojo { @@ -13,8 +12,7 @@ namespace system { // Just "add" some constructors and methods to the C struct // |MojoHandleSignalsState| (for convenience). This should add no overhead. -struct MOJO_SYSTEM_IMPL_EXPORT HandleSignalsState final - : public MojoHandleSignalsState { +struct HandleSignalsState final : public MojoHandleSignalsState { HandleSignalsState() { satisfied_signals = MOJO_HANDLE_SIGNAL_NONE; satisfiable_signals = MOJO_HANDLE_SIGNAL_NONE; diff --git a/mojo/edk/system/handle_table.h b/mojo/edk/system/handle_table.h index 83c7208924b..b67a583e227 100644 --- a/mojo/edk/system/handle_table.h +++ b/mojo/edk/system/handle_table.h @@ -5,12 +5,11 @@ #ifndef MOJO_EDK_SYSTEM_HANDLE_TABLE_H_ #define MOJO_EDK_SYSTEM_HANDLE_TABLE_H_ +#include #include #include -#include "base/containers/hash_tables.h" #include "base/memory/ref_counted.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -37,7 +36,7 @@ bool ShutdownCheckNoLeaks(Core*); // to make several changes -- "atomically" or in rapid successsion, in which // case the extra locking/unlocking would be unnecessary overhead). -class MOJO_SYSTEM_IMPL_EXPORT HandleTable { +class HandleTable { public: HandleTable(); ~HandleTable(); @@ -126,7 +125,7 @@ class MOJO_SYSTEM_IMPL_EXPORT HandleTable { scoped_refptr dispatcher; bool busy; }; - using HandleToEntryMap = base::hash_map; + using HandleToEntryMap = std::unordered_map; // Adds the given dispatcher to the handle table, not doing any size checks. MojoHandle AddDispatcherNoSizeCheck( diff --git a/mojo/edk/system/incoming_endpoint.cc b/mojo/edk/system/incoming_endpoint.cc index eaa1825a9f4..d92cf499920 100644 --- a/mojo/edk/system/incoming_endpoint.cc +++ b/mojo/edk/system/incoming_endpoint.cc @@ -67,7 +67,7 @@ bool IncomingEndpoint::OnReadMessage(unsigned /*port*/, if (!endpoint_) return false; - message_queue_.AddMessage(make_scoped_ptr(message)); + message_queue_.AddMessage(std::unique_ptr(message)); return true; } diff --git a/mojo/edk/system/incoming_endpoint.h b/mojo/edk/system/incoming_endpoint.h index bf0acf34dfe..efb85a4a4a2 100644 --- a/mojo/edk/system/incoming_endpoint.h +++ b/mojo/edk/system/incoming_endpoint.h @@ -11,7 +11,6 @@ #include "mojo/edk/system/channel_endpoint_client.h" #include "mojo/edk/system/message_in_transit_queue.h" #include "mojo/edk/system/mutex.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" struct MojoCreateDataPipeOptions; @@ -26,8 +25,7 @@ class MessagePipe; // This is a simple |ChannelEndpointClient| that only receives messages. It's // used for endpoints that are "received" by |Channel|, but not yet turned into // |MessagePipe|s or |DataPipe|s. -class MOJO_SYSTEM_IMPL_EXPORT IncomingEndpoint final - : public ChannelEndpointClient { +class IncomingEndpoint final : public ChannelEndpointClient { public: IncomingEndpoint(); diff --git a/mojo/edk/system/ipc_support.cc b/mojo/edk/system/ipc_support.cc index 1c4b232c1d3..af142818f21 100644 --- a/mojo/edk/system/ipc_support.cc +++ b/mojo/edk/system/ipc_support.cc @@ -4,6 +4,8 @@ #include "mojo/edk/system/ipc_support.h" +#include + #include "base/logging.h" #include "mojo/edk/embedder/master_process_delegate.h" #include "mojo/edk/embedder/slave_process_delegate.h" @@ -96,8 +98,7 @@ scoped_refptr IPCSupport::ConnectToSlave( DCHECK(channel_id); // We rely on |ChannelId| and |ProcessIdentifier| being identical types. - // TODO(vtl): Use std::is_same instead when we are allowed to (C++11 library). - static_assert(sizeof(ChannelId) == sizeof(ProcessIdentifier), + static_assert(std::is_same::value, "ChannelId and ProcessIdentifier types don't match"); embedder::ScopedPlatformHandle platform_connection_handle = @@ -115,8 +116,7 @@ scoped_refptr IPCSupport::ConnectToMaster( ChannelId* channel_id) { DCHECK(channel_id); - // TODO(vtl): Use std::is_same instead when we are allowed to (C++11 library). - static_assert(sizeof(ChannelId) == sizeof(ProcessIdentifier), + static_assert(std::is_same::value, "ChannelId and ProcessIdentifier types don't match"); embedder::ScopedPlatformHandle platform_connection_handle = ConnectToMasterInternal(connection_id); diff --git a/mojo/edk/system/ipc_support.h b/mojo/edk/system/ipc_support.h index 33441fbc66e..3cb948a75cc 100644 --- a/mojo/edk/system/ipc_support.h +++ b/mojo/edk/system/ipc_support.h @@ -5,10 +5,11 @@ #ifndef MOJO_EDK_SYSTEM_IPC_SUPPORT_H_ #define MOJO_EDK_SYSTEM_IPC_SUPPORT_H_ +#include + #include "base/callback_forward.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/task_runner.h" #include "mojo/edk/embedder/process_type.h" #include "mojo/edk/embedder/scoped_platform_handle.h" @@ -16,7 +17,6 @@ #include "mojo/edk/system/channel_id.h" #include "mojo/edk/system/connection_identifier.h" #include "mojo/edk/system/process_identifier.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -53,7 +53,7 @@ void MultiprocessMasterSlaveInternalTestChildTest(); // // Except for |ShutdownOnIOThread()|, this class is thread-safe. (No methods may // be called during/after |ShutdownOnIOThread()|.) -class MOJO_SYSTEM_IMPL_EXPORT IPCSupport { +class IPCSupport { public: // Constructor: initializes for the given |process_type|; |process_delegate| // must match the process type. |platform_handle| is only used for slave @@ -169,8 +169,8 @@ class MOJO_SYSTEM_IMPL_EXPORT IPCSupport { embedder::ProcessDelegate* process_delegate_; scoped_refptr io_thread_task_runner_; - scoped_ptr connection_manager_; - scoped_ptr channel_manager_; + std::unique_ptr connection_manager_; + std::unique_ptr channel_manager_; MOJO_DISALLOW_COPY_AND_ASSIGN(IPCSupport); }; diff --git a/mojo/edk/system/ipc_support_unittest.cc b/mojo/edk/system/ipc_support_unittest.cc index 695c4ecb829..cb45eb3a7a0 100644 --- a/mojo/edk/system/ipc_support_unittest.cc +++ b/mojo/edk/system/ipc_support_unittest.cc @@ -4,6 +4,7 @@ #include "mojo/edk/system/ipc_support.h" +#include #include #include @@ -11,9 +12,7 @@ #include "base/command_line.h" #include "base/location.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/waitable_event.h" -#include "base/test/test_io_thread.h" #include "base/test/test_timeouts.h" #include "mojo/edk/embedder/master_process_delegate.h" #include "mojo/edk/embedder/platform_channel_pair.h" @@ -28,11 +27,15 @@ #include "mojo/edk/system/test_utils.h" #include "mojo/edk/system/waiter.h" #include "mojo/edk/test/multiprocess_test_helper.h" +#include "mojo/edk/test/test_io_thread.h" #include "mojo/edk/test/test_utils.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { + +using test::TestIOThread; + namespace system { namespace { @@ -158,7 +161,7 @@ class TestSlaveProcessDelegate : public embedder::SlaveProcessDelegate { // Represents the master's side of its connection to a slave. class TestSlaveConnection { public: - TestSlaveConnection(base::TestIOThread* test_io_thread, + TestSlaveConnection(TestIOThread* test_io_thread, IPCSupport* master_ipc_support) : test_io_thread_(test_io_thread), master_ipc_support_(master_ipc_support), @@ -206,7 +209,7 @@ class TestSlaveConnection { const ConnectionIdentifier& connection_id() const { return connection_id_; } private: - base::TestIOThread* const test_io_thread_; + TestIOThread* const test_io_thread_; IPCSupport* const master_ipc_support_; const ConnectionIdentifier connection_id_; // The master's message pipe dispatcher. @@ -224,7 +227,7 @@ class TestSlave { public: // Note: Before destruction, |ShutdownIPCSupport()| must be called. TestSlave(embedder::PlatformSupport* platform_support, - base::TestIOThread* test_io_thread, + TestIOThread* test_io_thread, embedder::ScopedPlatformHandle platform_handle) : test_io_thread_(test_io_thread), slave_ipc_support_(platform_support, @@ -274,7 +277,7 @@ class TestSlave { } private: - base::TestIOThread* const test_io_thread_; + TestIOThread* const test_io_thread_; TestSlaveProcessDelegate slave_process_delegate_; IPCSupport slave_ipc_support_; base::WaitableEvent event_; @@ -286,7 +289,7 @@ class TestSlave { class TestSlaveSetup { public: TestSlaveSetup(embedder::SimplePlatformSupport* platform_support, - base::TestIOThread* test_io_thread, + TestIOThread* test_io_thread, TestMasterProcessDelegate* master_process_delegate, IPCSupport* master_ipc_support) : platform_support_(platform_support), @@ -352,14 +355,14 @@ class TestSlaveSetup { private: embedder::SimplePlatformSupport* const platform_support_; - base::TestIOThread* const test_io_thread_; + TestIOThread* const test_io_thread_; TestMasterProcessDelegate* const master_process_delegate_; IPCSupport* const master_ipc_support_; - scoped_ptr slave_connection_; + std::unique_ptr slave_connection_; scoped_refptr master_mp_; - scoped_ptr slave_; + std::unique_ptr slave_; scoped_refptr slave_mp_; MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveSetup); @@ -369,7 +372,7 @@ class IPCSupportTest : public testing::Test { public: // Note: Run master process delegate methods on the I/O thread. IPCSupportTest() - : test_io_thread_(base::TestIOThread::kAutoStart), + : test_io_thread_(TestIOThread::kAutoStart), master_ipc_support_(&platform_support_, embedder::ProcessType::MASTER, test_io_thread_.task_runner(), @@ -378,8 +381,8 @@ class IPCSupportTest : public testing::Test { embedder::ScopedPlatformHandle()) {} ~IPCSupportTest() override {} - scoped_ptr SetupSlave() { - scoped_ptr s( + std::unique_ptr SetupSlave() { + std::unique_ptr s( new TestSlaveSetup(&platform_support_, &test_io_thread_, &master_process_delegate_, &master_ipc_support_)); s->Init(); @@ -395,7 +398,7 @@ class IPCSupportTest : public testing::Test { embedder::SimplePlatformSupport& platform_support() { return platform_support_; } - base::TestIOThread& test_io_thread() { return test_io_thread_; } + TestIOThread& test_io_thread() { return test_io_thread_; } TestMasterProcessDelegate& master_process_delegate() { return master_process_delegate_; } @@ -403,7 +406,7 @@ class IPCSupportTest : public testing::Test { private: embedder::SimplePlatformSupport platform_support_; - base::TestIOThread test_io_thread_; + TestIOThread test_io_thread_; // All tests require a master. TestMasterProcessDelegate master_process_delegate_; @@ -428,7 +431,7 @@ MessagePipeDispatcherPair CreateMessagePipe() { } TEST_F(IPCSupportTest, MasterSlave) { - scoped_ptr s(SetupSlave()); + std::unique_ptr s(SetupSlave()); s->TestConnection(); @@ -456,8 +459,8 @@ TEST_F(IPCSupportTest, MasterSlave) { // TODO(vtl): In this scenario, we can't test the intermediary (the master) // going away. TEST_F(IPCSupportTest, ConnectTwoSlaves) { - scoped_ptr s1(SetupSlave()); - scoped_ptr s2(SetupSlave()); + std::unique_ptr s1(SetupSlave()); + std::unique_ptr s2(SetupSlave()); s1->TestConnection(); s2->TestConnection(); @@ -494,8 +497,8 @@ TEST_F(IPCSupportTest, ConnectTwoSlaves) { // Like |ConnectTwoSlaves|, but does it twice, to test reusing a connection. TEST_F(IPCSupportTest, ConnectTwoSlavesTwice) { - scoped_ptr s1(SetupSlave()); - scoped_ptr s2(SetupSlave()); + std::unique_ptr s1(SetupSlave()); + std::unique_ptr s2(SetupSlave()); s1->TestConnection(); s2->TestConnection(); @@ -544,7 +547,7 @@ TEST_F(IPCSupportTest, ConnectTwoSlavesTwice) { // Creates a message pipe in the slave, which sends both ends (in separate // messages) to the master. TEST_F(IPCSupportTest, SlavePassBackToMaster) { - scoped_ptr s(SetupSlave()); + std::unique_ptr s(SetupSlave()); s->TestConnection(); @@ -683,7 +686,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlaveInternal) { ASSERT_TRUE(client_platform_handle.is_valid()); embedder::SimplePlatformSupport platform_support; - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); + TestIOThread test_io_thread(TestIOThread::kAutoStart); TestSlaveProcessDelegate slave_process_delegate; // Note: Run process delegate methods on the I/O thread. IPCSupport ipc_support(&platform_support, embedder::ProcessType::SLAVE, diff --git a/mojo/edk/system/local_data_pipe_impl.cc b/mojo/edk/system/local_data_pipe_impl.cc index 321b22e9ee2..3d2e9e5f09d 100644 --- a/mojo/edk/system/local_data_pipe_impl.cc +++ b/mojo/edk/system/local_data_pipe_impl.cc @@ -13,9 +13,9 @@ #include #include +#include #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/data_pipe.h" @@ -23,6 +23,7 @@ #include "mojo/edk/system/message_in_transit_queue.h" #include "mojo/edk/system/remote_consumer_data_pipe_impl.h" #include "mojo/edk/system/remote_producer_data_pipe_impl.h" +#include "mojo/edk/util/make_unique.h" namespace mojo { namespace system { @@ -189,12 +190,13 @@ bool LocalDataPipeImpl::ProducerEndSerialize( // Note: We don't use |port|. scoped_refptr channel_endpoint = channel->SerializeEndpointWithLocalPeer(destination_for_endpoint, nullptr, - owner(), 0); + channel_endpoint_client(), 0); // Note: Keep |*this| alive until the end of this method, to make things // slightly easier on ourselves. - scoped_ptr self(owner()->ReplaceImplNoLock(make_scoped_ptr( - new RemoteProducerDataPipeImpl(channel_endpoint.get(), buffer_.Pass(), - start_index_, current_num_bytes_)))); + std::unique_ptr self( + ReplaceImpl(util::MakeUnique( + channel_endpoint.get(), std::move(buffer_), start_index_, + current_num_bytes_))); *actual_size = sizeof(SerializedDataPipeProducerDispatcher) + channel->GetSerializedEndpointSize(); @@ -357,11 +359,10 @@ bool LocalDataPipeImpl::ConsumerEndSerialize( MessageInTransitQueue message_queue; ConvertDataToMessages(buffer_.get(), &start_index_, ¤t_num_bytes_, &message_queue); - start_index_ = 0; - current_num_bytes_ = 0; if (!producer_open()) { // Case 1: The producer is closed. + DestroyBuffer(); channel->SerializeEndpointWithClosedPeer(destination_for_endpoint, &message_queue); *actual_size = sizeof(SerializedDataPipeConsumerDispatcher) + @@ -375,11 +376,15 @@ bool LocalDataPipeImpl::ConsumerEndSerialize( // Note: We don't use |port|. scoped_refptr channel_endpoint = channel->SerializeEndpointWithLocalPeer(destination_for_endpoint, - &message_queue, owner(), 0); + &message_queue, + channel_endpoint_client(), 0); // Note: Keep |*this| alive until the end of this method, to make things // slightly easier on ourselves. - scoped_ptr self(owner()->ReplaceImplNoLock(make_scoped_ptr( - new RemoteConsumerDataPipeImpl(channel_endpoint.get(), old_num_bytes)))); + std::unique_ptr self( + ReplaceImpl(util::MakeUnique( + channel_endpoint.get(), old_num_bytes, std::move(buffer_), + start_index_))); + DestroyBuffer(); *actual_size = sizeof(SerializedDataPipeConsumerDispatcher) + channel->GetSerializedEndpointSize(); @@ -413,6 +418,8 @@ void LocalDataPipeImpl::DestroyBuffer() { memset(buffer_.get(), 0xcd, capacity_num_bytes()); #endif buffer_.reset(); + start_index_ = 0; + current_num_bytes_ = 0; } size_t LocalDataPipeImpl::GetMaxNumBytesToWrite() { diff --git a/mojo/edk/system/local_data_pipe_impl.h b/mojo/edk/system/local_data_pipe_impl.h index 07b4c1e8654..46a353d7252 100644 --- a/mojo/edk/system/local_data_pipe_impl.h +++ b/mojo/edk/system/local_data_pipe_impl.h @@ -5,10 +5,10 @@ #ifndef MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_IMPL_H_ #define MOJO_EDK_SYSTEM_LOCAL_DATA_PIPE_IMPL_H_ +#include + #include "base/memory/aligned_memory.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/data_pipe_impl.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -19,7 +19,7 @@ class MessageInTransitQueue; // |LocalDataPipeImpl| is a subclass that "implements" |DataPipe| for data pipes // whose producer and consumer are both local. See |DataPipeImpl| for more // details. -class MOJO_SYSTEM_IMPL_EXPORT LocalDataPipeImpl final : public DataPipeImpl { +class LocalDataPipeImpl final : public DataPipeImpl { public: LocalDataPipeImpl(); ~LocalDataPipeImpl() override; @@ -82,7 +82,7 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalDataPipeImpl final : public DataPipeImpl { // no greater than |current_num_bytes_|. void MarkDataAsConsumed(size_t num_bytes); - scoped_ptr buffer_; + std::unique_ptr buffer_; // Circular buffer. size_t start_index_; size_t current_num_bytes_; diff --git a/mojo/edk/system/local_message_pipe_endpoint.cc b/mojo/edk/system/local_message_pipe_endpoint.cc index 1800aa48db7..43d11e1258a 100644 --- a/mojo/edk/system/local_message_pipe_endpoint.cc +++ b/mojo/edk/system/local_message_pipe_endpoint.cc @@ -6,6 +6,8 @@ #include +#include + #include "base/logging.h" #include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/message_in_transit.h" @@ -44,12 +46,12 @@ bool LocalMessagePipeEndpoint::OnPeerClose() { } void LocalMessagePipeEndpoint::EnqueueMessage( - scoped_ptr message) { + std::unique_ptr message) { DCHECK(is_open_); DCHECK(is_peer_open_); bool was_empty = message_queue_.IsEmpty(); - message_queue_.AddMessage(message.Pass()); + message_queue_.AddMessage(std::move(message)); if (was_empty) awakable_list_.AwakeForStateChange(GetHandleSignalsState()); } diff --git a/mojo/edk/system/local_message_pipe_endpoint.h b/mojo/edk/system/local_message_pipe_endpoint.h index 0f06847a473..ac90b68d4e4 100644 --- a/mojo/edk/system/local_message_pipe_endpoint.h +++ b/mojo/edk/system/local_message_pipe_endpoint.h @@ -9,14 +9,12 @@ #include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/message_in_transit_queue.h" #include "mojo/edk/system/message_pipe_endpoint.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { namespace system { -class MOJO_SYSTEM_IMPL_EXPORT LocalMessagePipeEndpoint final - : public MessagePipeEndpoint { +class LocalMessagePipeEndpoint final : public MessagePipeEndpoint { public: // If |message_queue| is non-null, its contents will be taken as the queue of // (already-received) messages. @@ -27,7 +25,7 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalMessagePipeEndpoint final // |MessagePipeEndpoint| implementation: Type GetType() const override; bool OnPeerClose() override; - void EnqueueMessage(scoped_ptr message) override; + void EnqueueMessage(std::unique_ptr message) override; // There's a dispatcher for |LocalMessagePipeEndpoint|s, so we have to // implement/override these: diff --git a/mojo/edk/system/mapping_table.cc b/mojo/edk/system/mapping_table.cc index 693e8d79590..d69d8fa6160 100644 --- a/mojo/edk/system/mapping_table.cc +++ b/mojo/edk/system/mapping_table.cc @@ -20,7 +20,7 @@ MappingTable::~MappingTable() { } MojoResult MappingTable::AddMapping( - scoped_ptr mapping) { + std::unique_ptr mapping) { DCHECK(mapping); if (address_to_mapping_map_.size() >= diff --git a/mojo/edk/system/mapping_table.h b/mojo/edk/system/mapping_table.h index 5af16557c24..c1f53402996 100644 --- a/mojo/edk/system/mapping_table.h +++ b/mojo/edk/system/mapping_table.h @@ -7,11 +7,10 @@ #include +#include +#include #include -#include "base/containers/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -35,7 +34,7 @@ bool ShutdownCheckNoLeaks(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 { +class MappingTable { public: MappingTable(); ~MappingTable(); @@ -43,14 +42,15 @@ class MOJO_SYSTEM_IMPL_EXPORT MappingTable { // Tries to add a mapping. (Takes ownership of the mapping in all cases; on // failure, it will be destroyed.) MojoResult AddMapping( - scoped_ptr mapping); + std::unique_ptr mapping); MojoResult RemoveMapping(uintptr_t address); private: friend bool internal::ShutdownCheckNoLeaks(Core*); + // TODO(vtl): Should the value type be |std::unique_ptr|? using AddressToMappingMap = - base::hash_map; + std::unordered_map; AddressToMappingMap address_to_mapping_map_; MOJO_DISALLOW_COPY_AND_ASSIGN(MappingTable); diff --git a/mojo/edk/system/master_connection_manager.cc b/mojo/edk/system/master_connection_manager.cc index 92572122c4d..dd8da3a0abd 100644 --- a/mojo/edk/system/master_connection_manager.cc +++ b/mojo/edk/system/master_connection_manager.cc @@ -4,6 +4,10 @@ #include "mojo/edk/system/master_connection_manager.h" +#include +#include +#include + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/location.h" @@ -18,6 +22,7 @@ #include "mojo/edk/system/message_in_transit.h" #include "mojo/edk/system/raw_channel.h" #include "mojo/edk/system/transport_data.h" +#include "mojo/edk/util/make_unique.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -61,8 +66,7 @@ MessageInTransit::Subtype ConnectionManagerResultToMessageInTransitSubtype( // |MasterConnectionManager::Helper| is not thread-safe, and must only be used // on its |owner_|'s private thread. -class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager::Helper final - : public RawChannel::Delegate { +class MasterConnectionManager::Helper final : public RawChannel::Delegate { public: Helper(MasterConnectionManager* owner, ProcessIdentifier process_identifier, @@ -88,7 +92,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager::Helper final MasterConnectionManager* const owner_; const ProcessIdentifier process_identifier_; embedder::SlaveInfo const slave_info_; - scoped_ptr raw_channel_; + std::unique_ptr raw_channel_; MOJO_DISALLOW_COPY_AND_ASSIGN(Helper); }; @@ -181,7 +185,7 @@ void MasterConnectionManager::Helper::OnReadMessage( return; } - scoped_ptr response(new MessageInTransit( + std::unique_ptr response(new MessageInTransit( MessageInTransit::Type::CONNECTION_MANAGER_ACK, ConnectionManagerResultToMessageInTransitSubtype(result), num_bytes, bytes)); @@ -193,14 +197,14 @@ void MasterConnectionManager::Helper::OnReadMessage( embedder::ScopedPlatformHandleVectorPtr platform_handles( new embedder::PlatformHandleVector()); platform_handles->push_back(platform_handle.release()); - response->SetTransportData(make_scoped_ptr( - new TransportData(platform_handles.Pass(), - raw_channel_->GetSerializedPlatformHandleSize()))); + response->SetTransportData(util::MakeUnique( + std::move(platform_handles), + raw_channel_->GetSerializedPlatformHandleSize())); } else { DCHECK(!platform_handle.is_valid()); } - if (!raw_channel_->WriteMessage(response.Pass())) { + if (!raw_channel_->WriteMessage(std::move(response))) { LOG(ERROR) << "WriteMessage failed"; FatalError(); // WARNING: This destroys us. return; @@ -221,7 +225,7 @@ void MasterConnectionManager::Helper::FatalError() { // MasterConnectionManager::PendingConnectInfo --------------------------------- -struct MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager::PendingConnectInfo { +struct MasterConnectionManager::PendingConnectInfo { // States: // - This is created upon a first "allow connect" (with |first| set // immediately). We then wait for a second "allow connect". @@ -308,7 +312,7 @@ class MasterConnectionManager::ProcessConnections { } private: - base::hash_map + std::unordered_map process_connections_; // "Owns" any valid platform handles. MOJO_DISALLOW_COPY_AND_ASSIGN(ProcessConnections); @@ -554,7 +558,7 @@ ConnectionManager::Result MasterConnectionManager::ConnectImpl( // The remaining cases all result in |it| being removed from // |pending_connects_| and deleting |info|. pending_connects_.erase(it); - scoped_ptr info_deleter(info); + std::unique_ptr info_deleter(info); // |remaining_connectee| should be the same as |process_identifier|. ProcessIdentifier remaining_connectee; @@ -672,8 +676,8 @@ void MasterConnectionManager::AddSlaveOnPrivateThread( DCHECK(event); AssertOnPrivateThread(); - scoped_ptr helper(new Helper(this, slave_process_identifier, - slave_info, platform_handle.Pass())); + std::unique_ptr helper(new Helper( + this, slave_process_identifier, slave_info, platform_handle.Pass())); helper->Init(); DCHECK(helpers_.find(slave_process_identifier) == helpers_.end()); diff --git a/mojo/edk/system/master_connection_manager.h b/mojo/edk/system/master_connection_manager.h index ee702a88919..97fb8ee561a 100644 --- a/mojo/edk/system/master_connection_manager.h +++ b/mojo/edk/system/master_connection_manager.h @@ -7,13 +7,13 @@ #include -#include "base/containers/hash_tables.h" +#include + #include "base/memory/ref_counted.h" #include "base/threading/thread.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/connection_manager.h" #include "mojo/edk/system/mutex.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace base { @@ -36,8 +36,7 @@ namespace system { // its internal, private thread), with condition that |Init()| be called before // anything else and |Shutdown()| be called before destruction (and no other // public methods may be called during/after |Shutdown()|). -class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager final - : public ConnectionManager { +class MasterConnectionManager final : public ConnectionManager { public: // Note: None of the public methods may be called from |private_thread_|. @@ -143,7 +142,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager final base::Thread private_thread_; // The following members are only accessed on |private_thread_|: - base::hash_map helpers_; // Owns its values. + std::unordered_map helpers_; // Owns its values. // Note: |mutex_| is not needed in the constructor, |Init()|, // |Shutdown()|/|ShutdownOnPrivateThread()|, or the destructor @@ -156,8 +155,8 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager final // |AllowConnect()| but both have not yet called |Connect()| (or // |CancelConnect()|). struct PendingConnectInfo; - base::hash_map pending_connects_ - MOJO_GUARDED_BY(mutex_); // Owns its values. + std::unordered_map + pending_connects_ MOJO_GUARDED_BY(mutex_); // Owns its values. // A |ProcessConnections| stores information about connections "from" a given // (fixed, implied) process "to" other processes. A connection may be not @@ -166,7 +165,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager final // "from" side must still be given a platform handle). class ProcessConnections; // This is a map from "from" processes to its |ProcessConnections| (above). - base::hash_map connections_ + std::unordered_map connections_ MOJO_GUARDED_BY(mutex_); // Owns its values. MOJO_DISALLOW_COPY_AND_ASSIGN(MasterConnectionManager); diff --git a/mojo/edk/system/memory.cc b/mojo/edk/system/memory.cc index 0e3d9a9cb70..7073e3cd6f3 100644 --- a/mojo/edk/system/memory.cc +++ b/mojo/edk/system/memory.cc @@ -7,7 +7,6 @@ #include #include "base/logging.h" -#include "build/build_config.h" namespace mojo { namespace system { @@ -18,42 +17,28 @@ bool IsAligned(const void* pointer) { return reinterpret_cast(pointer) % alignment == 0; } -// MSVS (2010, 2013) sometimes (on the stack) aligns, e.g., |int64_t|s (for -// which |__alignof(int64_t)| is 8) to 4-byte boundaries. http://goo.gl/Y2n56T -#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) -template <> -bool IsAligned<8>(const void* pointer) { - return reinterpret_cast(pointer) % 4 == 0; -} -#endif - template -void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer) { +void CheckUserPointer(const void* pointer) { CHECK(pointer && IsAligned(pointer)); } // Explicitly instantiate the sizes we need. Add instantiations as needed. -template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<1, 1>(const void*); -template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<4, 4>(const void*); -template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 4>(const void*); -template void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer<8, 8>(const void*); +template void CheckUserPointer<1, 1>(const void*); +template void CheckUserPointer<4, 4>(const void*); +template void CheckUserPointer<8, 4>(const void*); +template void CheckUserPointer<8, 8>(const void*); template -void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount(const void* pointer, size_t count) { +void CheckUserPointerWithCount(const void* pointer, size_t count) { CHECK_LE(count, std::numeric_limits::max() / size); CHECK(count == 0 || (pointer && IsAligned(pointer))); } // Explicitly instantiate the sizes we need. Add instantiations as needed. -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount<1, 1>(const void*, size_t); -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount<4, 4>(const void*, size_t); -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount<8, 4>(const void*, size_t); -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount<8, 8>(const void*, size_t); +template void CheckUserPointerWithCount<1, 1>(const void*, size_t); +template void CheckUserPointerWithCount<4, 4>(const void*, size_t); +template void CheckUserPointerWithCount<8, 4>(const void*, size_t); +template void CheckUserPointerWithCount<8, 8>(const void*, size_t); template void CheckUserPointerWithSize(const void* pointer, size_t size) { @@ -64,25 +49,9 @@ void CheckUserPointerWithSize(const void* pointer, size_t size) { } // Explicitly instantiate the sizes we need. Add instantiations as needed. -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize<1>(const void*, size_t); -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize<4>(const void*, size_t); -// Whereas the other |Check...()| functions are usually used with integral typs -// or arrays of integral types, this one is used with Options structs for which -// alignment has been explicitly been specified (using |MOJO_ALIGNAS()|), which -// MSVS *does* respect. -#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) -template <> -void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize<8>(const void* pointer, size_t size) { - CHECK(size == 0 || - (!!pointer && reinterpret_cast(pointer) % 8 == 0)); -} -#else -template void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize<8>(const void*, size_t); -#endif +template void CheckUserPointerWithSize<1>(const void*, size_t); +template void CheckUserPointerWithSize<4>(const void*, size_t); +template void CheckUserPointerWithSize<8>(const void*, size_t); } // namespace internal } // namespace system diff --git a/mojo/edk/system/memory.h b/mojo/edk/system/memory.h index 31d67cc94d8..427dbb3becc 100644 --- a/mojo/edk/system/memory.h +++ b/mojo/edk/system/memory.h @@ -9,8 +9,9 @@ #include #include // For |memcpy()|. -#include "base/memory/scoped_ptr.h" -#include "mojo/edk/system/system_impl_export.h" +#include +#include + #include "mojo/public/c/system/macros.h" #include "mojo/public/cpp/system/macros.h" @@ -19,17 +20,6 @@ namespace system { namespace internal { -// Removes |const| from |T| (available as |remove_const::type|): -// TODO(vtl): Remove these once we have the C++11 |remove_const|. -template -struct remove_const { - using type = T; -}; -template -struct remove_const { - using type = T; -}; - // Yields |(const) char| if |T| is |(const) void|, else |T|: template struct VoidToChar { @@ -47,19 +37,17 @@ struct VoidToChar { // Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to // a buffer of the given size and alignment (both in bytes). template -void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer); +void CheckUserPointer(const void* pointer); // Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to // a buffer of |count| elements of the given size and alignment (both in bytes). template -void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithCount(const void* pointer, size_t count); +void CheckUserPointerWithCount(const void* pointer, size_t count); // Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to // a buffer of the given size and alignment (both in bytes). template -void MOJO_SYSTEM_IMPL_EXPORT -CheckUserPointerWithSize(const void* pointer, size_t size); +void CheckUserPointerWithSize(const void* pointer, size_t size); } // namespace internal @@ -156,7 +144,7 @@ class UserPointer { // void|) from the location pointed to by this user pointer. Use this when // you'd do something like |memcpy(destination, user_pointer, count * // sizeof(Type)|. - void GetArray(typename internal::remove_const::type* destination, + void GetArray(typename std::remove_cv::type* destination, size_t count) const { CheckArray(count); memcpy(destination, pointer_, count * sizeof(NonVoidType)); @@ -269,7 +257,7 @@ inline UserPointer MakeUserPointer(Type* pointer) { template class UserPointerReader { private: - using TypeNoConst = typename internal::remove_const::type; + using TypeNoConst = typename std::remove_const::type; public: // Note: If |count| is zero, |GetPointer()| will always return null. @@ -305,7 +293,7 @@ class UserPointerReader { memcpy(buffer_.get(), user_pointer, count * sizeof(Type)); } - scoped_ptr buffer_; + std::unique_ptr buffer_; MOJO_DISALLOW_COPY_AND_ASSIGN(UserPointerReader); }; @@ -334,7 +322,7 @@ class UserPointerWriter { private: UserPointer user_pointer_; size_t count_; - scoped_ptr buffer_; + std::unique_ptr buffer_; MOJO_DISALLOW_COPY_AND_ASSIGN(UserPointerWriter); }; @@ -366,7 +354,7 @@ class UserPointerReaderWriter { private: UserPointer user_pointer_; size_t count_; - scoped_ptr buffer_; + std::unique_ptr buffer_; MOJO_DISALLOW_COPY_AND_ASSIGN(UserPointerReaderWriter); }; diff --git a/mojo/edk/system/message_in_transit.cc b/mojo/edk/system/message_in_transit.cc index 7ac54e1afdf..771c155cba4 100644 --- a/mojo/edk/system/message_in_transit.cc +++ b/mojo/edk/system/message_in_transit.cc @@ -6,7 +6,7 @@ #include -#include +#include #include "base/logging.h" #include "mojo/edk/system/configuration.h" @@ -144,12 +144,12 @@ bool MessageInTransit::GetNextMessageSize(const void* buffer, } void MessageInTransit::SetDispatchers( - scoped_ptr dispatchers) { + std::unique_ptr dispatchers) { DCHECK(dispatchers); DCHECK(!dispatchers_); DCHECK(!transport_data_); - dispatchers_ = dispatchers.Pass(); + dispatchers_ = std::move(dispatchers); #ifndef NDEBUG for (size_t i = 0; i < dispatchers_->size(); i++) DCHECK(!(*dispatchers_)[i] || (*dispatchers_)[i]->HasOneRef()); @@ -157,12 +157,12 @@ void MessageInTransit::SetDispatchers( } void MessageInTransit::SetTransportData( - scoped_ptr transport_data) { + std::unique_ptr transport_data) { DCHECK(transport_data); DCHECK(!transport_data_); DCHECK(!dispatchers_); - transport_data_ = transport_data.Pass(); + transport_data_ = std::move(transport_data); UpdateTotalSize(); } @@ -173,7 +173,7 @@ void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) { if (!dispatchers_ || !dispatchers_->size()) return; - transport_data_.reset(new TransportData(dispatchers_.Pass(), channel)); + transport_data_.reset(new TransportData(std::move(dispatchers_), channel)); // Update the sizes in the message header. UpdateTotalSize(); diff --git a/mojo/edk/system/message_in_transit.h b/mojo/edk/system/message_in_transit.h index 2edc7762a63..d77a416fb82 100644 --- a/mojo/edk/system/message_in_transit.h +++ b/mojo/edk/system/message_in_transit.h @@ -8,15 +8,14 @@ #include #include +#include #include #include #include "base/memory/aligned_memory.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel_endpoint_id.h" #include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/memory.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -42,7 +41,7 @@ class TransportData; // // See |TransportData| for a description of the (serialized) transport data // buffer. -class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { +class MessageInTransit { public: enum class Type : uint16_t { // Messages that are forwarded to endpoint clients. @@ -102,7 +101,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { public: // This represents a view of serialized message data in a raw buffer. - class MOJO_SYSTEM_IMPL_EXPORT View { + class View { public: // Constructs a view from the given buffer of the given size. (The size must // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer @@ -188,11 +187,11 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { // not be referenced from anywhere else (in particular, not from the handle // table), i.e., each dispatcher must have a reference count of 1. This // message must not already have dispatchers. - void SetDispatchers(scoped_ptr dispatchers); + void SetDispatchers(std::unique_ptr dispatchers); // Sets the |TransportData| for this message. This should only be done when // there are no dispatchers and no existing |TransportData|. - void SetTransportData(scoped_ptr transport_data); + void SetTransportData(std::unique_ptr transport_data); // Serializes any dispatchers to the secondary buffer. This message must not // already have a secondary buffer (so this must only be called once). The @@ -276,30 +275,29 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit { void UpdateTotalSize(); const size_t main_buffer_size_; - const scoped_ptr main_buffer_; // Never null. + // Never null. + const std::unique_ptr main_buffer_; - scoped_ptr transport_data_; // May be null. + std::unique_ptr transport_data_; // May be null. // Any dispatchers that may be attached to this message. These dispatchers // should be "owned" by this message, i.e., have a ref count of exactly 1. (We // allow a dispatcher entry to be null, in case it couldn't be duplicated for // some reason.) - scoped_ptr dispatchers_; + std::unique_ptr dispatchers_; MOJO_DISALLOW_COPY_AND_ASSIGN(MessageInTransit); }; // So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - MessageInTransit::Type type) { +inline std::ostream& operator<<(std::ostream& out, + MessageInTransit::Type type) { return out << static_cast(type); } // So logging macros and |DCHECK_EQ()|, etc. work. -MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<( - std::ostream& out, - MessageInTransit::Subtype subtype) { +inline std::ostream& operator<<(std::ostream& out, + MessageInTransit::Subtype subtype) { return out << static_cast(subtype); } diff --git a/mojo/edk/system/message_in_transit_queue.h b/mojo/edk/system/message_in_transit_queue.h index f7464bd6272..d746ee825bc 100644 --- a/mojo/edk/system/message_in_transit_queue.h +++ b/mojo/edk/system/message_in_transit_queue.h @@ -6,10 +6,9 @@ #define MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_QUEUE_H_ #include +#include -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/message_in_transit.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -17,7 +16,7 @@ namespace system { // A simple queue for |MessageInTransit|s (that owns its messages). // This class is not thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT MessageInTransitQueue { +class MessageInTransitQueue { public: MessageInTransitQueue(); ~MessageInTransitQueue(); @@ -25,14 +24,14 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransitQueue { bool IsEmpty() const { return queue_.empty(); } size_t Size() const { return queue_.size(); } - void AddMessage(scoped_ptr message) { + void AddMessage(std::unique_ptr message) { queue_.push_back(message.release()); } - scoped_ptr GetMessage() { + std::unique_ptr GetMessage() { MessageInTransit* rv = queue_.front(); queue_.pop_front(); - return make_scoped_ptr(rv); + return std::unique_ptr(rv); } const MessageInTransit* PeekMessage() const { return queue_.front(); } @@ -50,7 +49,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransitQueue { private: // TODO(vtl): When C++11 is available, switch this to a deque of - // |scoped_ptr|/|unique_ptr|s. + // |unique_ptr|s. std::deque queue_; MOJO_DISALLOW_COPY_AND_ASSIGN(MessageInTransitQueue); diff --git a/mojo/edk/system/message_in_transit_test_utils.cc b/mojo/edk/system/message_in_transit_test_utils.cc index 0d7cc2425fd..7578c2bd103 100644 --- a/mojo/edk/system/message_in_transit_test_utils.cc +++ b/mojo/edk/system/message_in_transit_test_utils.cc @@ -4,17 +4,18 @@ #include "mojo/edk/system/message_in_transit_test_utils.h" +#include "mojo/edk/util/make_unique.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { namespace system { namespace test { -scoped_ptr MakeTestMessage(unsigned id) { - return make_scoped_ptr( - new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - static_cast(sizeof(id)), &id)); +std::unique_ptr MakeTestMessage(unsigned id) { + return util::MakeUnique( + MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, + static_cast(sizeof(id)), &id); } void VerifyTestMessage(const MessageInTransit* message, unsigned id) { diff --git a/mojo/edk/system/message_in_transit_test_utils.h b/mojo/edk/system/message_in_transit_test_utils.h index 283783871ff..ce971bb193a 100644 --- a/mojo/edk/system/message_in_transit_test_utils.h +++ b/mojo/edk/system/message_in_transit_test_utils.h @@ -5,7 +5,8 @@ #ifndef MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_TEST_UTILS_H_ #define MOJO_EDK_SYSTEM_MESSAGE_IN_TRANSIT_TEST_UTILS_H_ -#include "base/memory/scoped_ptr.h" +#include + #include "mojo/edk/system/message_in_transit.h" namespace mojo { @@ -17,7 +18,7 @@ namespace test { // |MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA|, and contain data // associated with |id| (so that test messages with different |id|s are // distinguishable). -scoped_ptr MakeTestMessage(unsigned id); +std::unique_ptr MakeTestMessage(unsigned id); // Verifies a test message: ASSERTs that |message| is non-null, and EXPECTs that // it looks like a message created using |MakeTestMessage(id)| (see above). diff --git a/mojo/edk/system/message_pipe.cc b/mojo/edk/system/message_pipe.cc index b17344c2091..c89e24056bd 100644 --- a/mojo/edk/system/message_pipe.cc +++ b/mojo/edk/system/message_pipe.cc @@ -4,6 +4,9 @@ #include "mojo/edk/system/message_pipe.h" +#include +#include + #include "base/logging.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/channel_endpoint.h" @@ -14,12 +17,13 @@ #include "mojo/edk/system/message_pipe_dispatcher.h" #include "mojo/edk/system/message_pipe_endpoint.h" #include "mojo/edk/system/proxy_message_pipe_endpoint.h" +#include "mojo/edk/util/make_unique.h" namespace mojo { namespace system { // static -MessagePipe* MessagePipe::CreateLocalLocal() { +MessagePipe* MessagePipe::CreateLocalLocal() MOJO_NO_THREAD_SAFETY_ANALYSIS { MessagePipe* message_pipe = new MessagePipe(); message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint()); message_pipe->endpoints_[1].reset(new LocalMessagePipeEndpoint()); @@ -28,7 +32,8 @@ MessagePipe* MessagePipe::CreateLocalLocal() { // static MessagePipe* MessagePipe::CreateLocalProxy( - scoped_refptr* channel_endpoint) { + scoped_refptr* channel_endpoint) + MOJO_NO_THREAD_SAFETY_ANALYSIS { DCHECK(!*channel_endpoint); // Not technically wrong, but unlikely. MessagePipe* message_pipe = new MessagePipe(); message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint()); @@ -41,7 +46,7 @@ MessagePipe* MessagePipe::CreateLocalProxy( // static MessagePipe* MessagePipe::CreateLocalProxyFromExisting( MessageInTransitQueue* message_queue, - ChannelEndpoint* channel_endpoint) { + ChannelEndpoint* channel_endpoint) MOJO_NO_THREAD_SAFETY_ANALYSIS { DCHECK(message_queue); MessagePipe* message_pipe = new MessagePipe(); message_pipe->endpoints_[0].reset( @@ -64,7 +69,8 @@ MessagePipe* MessagePipe::CreateLocalProxyFromExisting( // static MessagePipe* MessagePipe::CreateProxyLocal( - scoped_refptr* channel_endpoint) { + scoped_refptr* channel_endpoint) + MOJO_NO_THREAD_SAFETY_ANALYSIS { DCHECK(!*channel_endpoint); // Not technically wrong, but unlikely. MessagePipe* message_pipe = new MessagePipe(); *channel_endpoint = new ChannelEndpoint(message_pipe, 0); @@ -106,7 +112,7 @@ bool MessagePipe::Deserialize(Channel* channel, MessagePipeEndpoint::Type MessagePipe::GetType(unsigned port) { DCHECK(port == 0 || port == 1); - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(endpoints_[port]); return endpoints_[port]->GetType(); @@ -115,7 +121,7 @@ MessagePipeEndpoint::Type MessagePipe::GetType(unsigned port) { void MessagePipe::CancelAllAwakables(unsigned port) { DCHECK(port == 0 || port == 1); - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(endpoints_[port]); endpoints_[port]->CancelAllAwakables(); } @@ -125,7 +131,7 @@ void MessagePipe::Close(unsigned port) { unsigned peer_port = GetPeerPort(port); - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); // The endpoint's |OnPeerClose()| may have been called first and returned // false, which would have resulted in its destruction. if (!endpoints_[port]) @@ -148,12 +154,12 @@ MojoResult MessagePipe::WriteMessage( MojoWriteMessageFlags flags) { DCHECK(port == 0 || port == 1); - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); return EnqueueMessageNoLock( GetPeerPort(port), - make_scoped_ptr(new MessageInTransit( + util::MakeUnique( MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, num_bytes, bytes)), + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, num_bytes, bytes), transports); } @@ -165,7 +171,7 @@ MojoResult MessagePipe::ReadMessage(unsigned port, MojoReadMessageFlags flags) { DCHECK(port == 0 || port == 1); - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(endpoints_[port]); return endpoints_[port]->ReadMessage(bytes, num_bytes, dispatchers, @@ -175,7 +181,7 @@ MojoResult MessagePipe::ReadMessage(unsigned port, HandleSignalsState MessagePipe::GetHandleSignalsState(unsigned port) const { DCHECK(port == 0 || port == 1); - base::AutoLock locker(const_cast(lock_)); + MutexLocker locker(&mutex_); DCHECK(endpoints_[port]); return endpoints_[port]->GetHandleSignalsState(); @@ -188,7 +194,7 @@ MojoResult MessagePipe::AddAwakable(unsigned port, HandleSignalsState* signals_state) { DCHECK(port == 0 || port == 1); - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(endpoints_[port]); return endpoints_[port]->AddAwakable(awakable, signals, context, @@ -200,7 +206,7 @@ void MessagePipe::RemoveAwakable(unsigned port, HandleSignalsState* signals_state) { DCHECK(port == 0 || port == 1); - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(endpoints_[port]); endpoints_[port]->RemoveAwakable(awakable, signals_state); @@ -222,7 +228,7 @@ bool MessagePipe::EndSerialize( embedder::PlatformHandleVector* /*platform_handles*/) { DCHECK(port == 0 || port == 1); - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); DCHECK(endpoints_[port]); // The port being serialized must be local. @@ -274,7 +280,7 @@ bool MessagePipe::EndSerialize( } bool MessagePipe::OnReadMessage(unsigned port, MessageInTransit* message) { - base::AutoLock locker(lock_); + MutexLocker locker(&mutex_); if (!endpoints_[port]) { // This will happen only on the rare occasion that the call to @@ -289,8 +295,8 @@ bool MessagePipe::OnReadMessage(unsigned port, MessageInTransit* message) { // |ProxyMessagePipeEndpoint| |port| receives a message (from the |Channel|). // We need to pass this message on to its peer port (typically a // |LocalMessagePipeEndpoint|). - MojoResult result = EnqueueMessageNoLock(GetPeerPort(port), - make_scoped_ptr(message), nullptr); + MojoResult result = EnqueueMessageNoLock( + GetPeerPort(port), std::unique_ptr(message), nullptr); DLOG_IF(WARNING, result != MOJO_RESULT_OK) << "EnqueueMessageNoLock() failed (result = " << result << ")"; return true; @@ -313,7 +319,7 @@ MessagePipe::~MessagePipe() { MojoResult MessagePipe::EnqueueMessageNoLock( unsigned port, - scoped_ptr message, + std::unique_ptr message, std::vector* transports) { DCHECK(port == 0 || port == 1); DCHECK(message); @@ -332,7 +338,7 @@ MojoResult MessagePipe::EnqueueMessageNoLock( } // The endpoint's |EnqueueMessage()| may not report failure. - endpoints_[port]->EnqueueMessage(message.Pass()); + endpoints_[port]->EnqueueMessage(std::move(message)); return MOJO_RESULT_OK; } @@ -365,7 +371,7 @@ MojoResult MessagePipe::AttachTransportsNoLock( // Clone the dispatchers and attach them to the message. (This must be done as // a separate loop, since we want to leave the dispatchers alone on failure.) - scoped_ptr dispatchers(new DispatcherVector()); + std::unique_ptr dispatchers(new DispatcherVector()); dispatchers->reserve(transports->size()); for (size_t i = 0; i < transports->size(); i++) { if ((*transports)[i].is_valid()) { @@ -376,7 +382,7 @@ MojoResult MessagePipe::AttachTransportsNoLock( dispatchers->push_back(nullptr); } } - message->SetDispatchers(dispatchers.Pass()); + message->SetDispatchers(std::move(dispatchers)); return MOJO_RESULT_OK; } diff --git a/mojo/edk/system/message_pipe.h b/mojo/edk/system/message_pipe.h index 8a843885f24..9508addc36e 100644 --- a/mojo/edk/system/message_pipe.h +++ b/mojo/edk/system/message_pipe.h @@ -8,11 +8,10 @@ #include #include +#include #include #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/system/channel_endpoint_client.h" #include "mojo/edk/system/dispatcher.h" @@ -20,7 +19,7 @@ #include "mojo/edk/system/memory.h" #include "mojo/edk/system/message_in_transit.h" #include "mojo/edk/system/message_pipe_endpoint.h" -#include "mojo/edk/system/system_impl_export.h" +#include "mojo/edk/system/mutex.h" #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -36,7 +35,7 @@ class MessageInTransitQueue; // |MessagePipe| is the secondary object implementing a message pipe (see the // explanatory comment in core.cc). It is typically owned by the dispatcher(s) // corresponding to the local endpoints. This class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT MessagePipe final : public ChannelEndpointClient { +class MessagePipe final : public ChannelEndpointClient { public: // Creates a |MessagePipe| with two new |LocalMessagePipeEndpoint|s. static MessagePipe* CreateLocalLocal(); @@ -127,17 +126,19 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipe final : public ChannelEndpointClient { // |transports| may be non-null only if it's nonempty and |message| has no // dispatchers attached. Must be called with |lock_| held. MojoResult EnqueueMessageNoLock(unsigned port, - scoped_ptr message, - std::vector* transports); + std::unique_ptr message, + std::vector* transports) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - // Helper for |EnqueueMessageNoLock()|. Must be called with |lock_| held. + // Helper for |EnqueueMessageNoLock()|. MojoResult AttachTransportsNoLock( unsigned port, MessageInTransit* message, - std::vector* transports); + std::vector* transports) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - base::Lock lock_; // Protects the following members. - scoped_ptr endpoints_[2]; + mutable Mutex mutex_; + std::unique_ptr endpoints_[2] MOJO_GUARDED_BY(mutex_); MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipe); }; diff --git a/mojo/edk/system/message_pipe_dispatcher.h b/mojo/edk/system/message_pipe_dispatcher.h index 23bb1ed590e..0d2a2737ed0 100644 --- a/mojo/edk/system/message_pipe_dispatcher.h +++ b/mojo/edk/system/message_pipe_dispatcher.h @@ -8,7 +8,6 @@ #include "base/memory/ref_counted.h" #include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/memory.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -20,7 +19,7 @@ class MessagePipeDispatcherTransport; // This is the |Dispatcher| implementation for message pipes (created by the // Mojo primitive |MojoCreateMessagePipe()|). This class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT MessagePipeDispatcher final : public Dispatcher { +class MessagePipeDispatcher final : public Dispatcher { public: // The default options to use for |MojoCreateMessagePipe()|. (Real uses // should obtain this via |ValidateCreateOptions()| with a null |in_options|; diff --git a/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/mojo/edk/system/message_pipe_dispatcher_unittest.cc index aebc439b679..a0eca42cade 100644 --- a/mojo/edk/system/message_pipe_dispatcher_unittest.cc +++ b/mojo/edk/system/message_pipe_dispatcher_unittest.cc @@ -338,13 +338,7 @@ TEST(MessagePipeDispatcherTest, BasicClosed) { } } -#if defined(OS_WIN) -// http://crbug.com/396386 -#define MAYBE_BasicThreaded DISABLED_BasicThreaded -#else -#define MAYBE_BasicThreaded BasicThreaded -#endif -TEST(MessagePipeDispatcherTest, MAYBE_BasicThreaded) { +TEST(MessagePipeDispatcherTest, BasicThreaded) { test::Stopwatch stopwatch; int32_t buffer[1]; const uint32_t kBufferSize = static_cast(sizeof(buffer)); diff --git a/mojo/edk/system/message_pipe_endpoint.h b/mojo/edk/system/message_pipe_endpoint.h index 73d9a920a89..c488ca3a43f 100644 --- a/mojo/edk/system/message_pipe_endpoint.h +++ b/mojo/edk/system/message_pipe_endpoint.h @@ -7,14 +7,13 @@ #include +#include #include #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/memory.h" #include "mojo/edk/system/message_in_transit.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/message_pipe.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -33,7 +32,7 @@ class Awakable; // |MessagePipeEndpoint| also implements the functionality required by the // dispatcher, e.g., to read messages and to wait. Implementations of this class // are not thread-safe; instances are protected by |MesssagePipe|'s lock. -class MOJO_SYSTEM_IMPL_EXPORT MessagePipeEndpoint { +class MessagePipeEndpoint { public: virtual ~MessagePipeEndpoint() {} @@ -47,7 +46,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipeEndpoint { // a) Dispatchers have been vetted and cloned/attached to the message. // b) At this point, we cannot report failure (if, e.g., a channel is torn // down at this point, we should silently swallow the message). - virtual void EnqueueMessage(scoped_ptr message) = 0; + virtual void EnqueueMessage(std::unique_ptr message) = 0; virtual void Close() = 0; // Implementations must override these if they represent a local endpoint, diff --git a/mojo/edk/system/message_pipe_perftest.cc b/mojo/edk/system/message_pipe_perftest.cc index 562acbd9f8a..6772b2eed50 100644 --- a/mojo/edk/system/message_pipe_perftest.cc +++ b/mojo/edk/system/message_pipe_perftest.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -84,7 +85,7 @@ class MultiprocessMessagePipePerfTest size_t message_size_; std::string payload_; std::string read_buffer_; - scoped_ptr perf_logger_; + std::unique_ptr perf_logger_; }; // For each message received, sends a reply message with the same contents diff --git a/mojo/edk/system/message_pipe_test_utils.cc b/mojo/edk/system/message_pipe_test_utils.cc index efbae959380..8591c5afd0c 100644 --- a/mojo/edk/system/message_pipe_test_utils.cc +++ b/mojo/edk/system/message_pipe_test_utils.cc @@ -35,8 +35,7 @@ MojoResult WaitIfNecessary(scoped_refptr mp, ChannelThread::ChannelThread(embedder::PlatformSupport* platform_support) : platform_support_(platform_support), - test_io_thread_(base::TestIOThread::kManualStart) { -} + test_io_thread_(mojo::test::TestIOThread::kManualStart) {} ChannelThread::~ChannelThread() { Stop(); diff --git a/mojo/edk/system/message_pipe_test_utils.h b/mojo/edk/system/message_pipe_test_utils.h index 3e8e0050a2a..317d66d3a01 100644 --- a/mojo/edk/system/message_pipe_test_utils.h +++ b/mojo/edk/system/message_pipe_test_utils.h @@ -5,11 +5,11 @@ #ifndef MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_ #define MOJO_EDK_SYSTEM_MESSAGE_PIPE_TEST_UTILS_H_ -#include "base/test/test_io_thread.h" #include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/test/multiprocess_test_helper.h" +#include "mojo/edk/test/test_io_thread.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -40,7 +40,7 @@ class ChannelThread { void ShutdownChannelOnIOThread(); embedder::PlatformSupport* const platform_support_; - base::TestIOThread test_io_thread_; + mojo::test::TestIOThread test_io_thread_; scoped_refptr channel_; MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelThread); diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc index 4f28bc5e9a4..f708b5ea3c9 100644 --- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc @@ -6,14 +6,11 @@ #include #include +#include #include #include #include "base/bind.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/location.h" #include "base/logging.h" #include "build/build_config.h" // TODO(vtl): Remove this. @@ -27,7 +24,9 @@ #include "mojo/edk/system/raw_channel.h" #include "mojo/edk/system/shared_buffer_dispatcher.h" #include "mojo/edk/system/test_utils.h" +#include "mojo/edk/test/scoped_test_dir.h" #include "mojo/edk/test/test_utils.h" +#include "mojo/edk/util/scoped_file.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { @@ -94,13 +93,13 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) { return rv; } -// Sends "hello" to child, and expects "hellohello" back. #if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. #define MAYBE_Basic DISABLED_Basic #else #define MAYBE_Basic Basic -#endif // defined(OS_ANDROID) +#endif +// Sends "hello" to child, and expects "hellohello" back. TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { helper()->StartChild("EchoEcho"); @@ -139,14 +138,14 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { EXPECT_EQ(1 % 100, helper()->WaitForChildShutdown()); } -// Sends a bunch of messages to the child. Expects them "repeated" back. Waits -// for the child to close its end before quitting. #if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. #define MAYBE_QueueMessages DISABLED_QueueMessages #else #define MAYBE_QueueMessages QueueMessages -#endif // defined(OS_ANDROID) +#endif +// Sends a bunch of messages to the child. Expects them "repeated" back. Waits +// for the child to close its end before quitting. TEST_F(MultiprocessMessagePipeTest, DISABLED_QueueMessages) { helper()->StartChild("EchoEcho"); @@ -245,7 +244,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { static_cast(dispatchers[0].get())); // Make a mapping. - scoped_ptr mapping; + std::unique_ptr mapping; CHECK_EQ(dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping), MOJO_RESULT_OK); CHECK(mapping); @@ -295,12 +294,11 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { return 0; } -#if defined(OS_POSIX) && !defined(OS_ANDROID) -#define MAYBE_SharedBufferPassing SharedBufferPassing -#else -// Not yet implemented (on Windows). +#if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. #define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing +#else +#define MAYBE_SharedBufferPassing SharedBufferPassing #endif TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { helper()->StartChild("CheckSharedBuffer"); @@ -318,7 +316,7 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { ASSERT_TRUE(dispatcher); // Make a mapping. - scoped_ptr mapping; + std::unique_ptr mapping; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); ASSERT_TRUE(mapping); @@ -431,7 +429,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { CHECK(h.is_valid()); dispatcher->Close(); - base::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h.Pass(), "r")); + util::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h.Pass(), "r")); CHECK(fp); std::string fread_buffer(100, '\0'); size_t bytes_read = @@ -448,8 +446,7 @@ class MultiprocessMessagePipeTestWithPipeCount public testing::WithParamInterface {}; TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + mojo::test::ScopedTestDir test_dir; helper()->StartChild("CheckPlatformHandleFile"); @@ -462,9 +459,7 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { size_t pipe_count = GetParam(); for (size_t i = 0; i < pipe_count; ++i) { - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); + util::ScopedFILE fp(test_dir.CreateFile()); const std::string world("world"); CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size()); fflush(fp.get()); @@ -506,9 +501,8 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { EXPECT_EQ(0, helper()->WaitForChildShutdown()); } -// Not yet implemented (on Windows). // Android multi-process tests are not executing the new process. This is flaky. -#if defined(OS_POSIX) && !defined(OS_ANDROID) +#if !defined(OS_ANDROID) INSTANTIATE_TEST_CASE_P(PipeCount, MultiprocessMessagePipeTestWithPipeCount, testing::Values(1u, 128u, 140u)); diff --git a/mojo/edk/system/mutex.h b/mojo/edk/system/mutex.h index acb410aafef..859f6a31a63 100644 --- a/mojo/edk/system/mutex.h +++ b/mojo/edk/system/mutex.h @@ -14,7 +14,6 @@ #include "base/synchronization/lock_impl.h" #include "base/threading/platform_thread.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/edk/system/thread_annotations.h" #include "mojo/public/cpp/system/macros.h" @@ -23,7 +22,7 @@ namespace system { // Mutex ----------------------------------------------------------------------- -class MOJO_SYSTEM_IMPL_EXPORT MOJO_LOCKABLE Mutex { +class MOJO_LOCKABLE Mutex { public: #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) Mutex() : lock_() {} @@ -73,7 +72,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MOJO_LOCKABLE Mutex { // MutexLocker ----------------------------------------------------------------- -class MOJO_SYSTEM_IMPL_EXPORT MOJO_SCOPED_LOCKABLE MutexLocker { +class MOJO_SCOPED_LOCKABLE MutexLocker { public: explicit MutexLocker(Mutex* mutex) MOJO_EXCLUSIVE_LOCK_FUNCTION(mutex) : mutex_(mutex) { diff --git a/mojo/edk/system/options_validation.h b/mojo/edk/system/options_validation.h index 6a0dae450b8..35d81f9884c 100644 --- a/mojo/edk/system/options_validation.h +++ b/mojo/edk/system/options_validation.h @@ -15,10 +15,10 @@ #include #include +#include #include "base/logging.h" #include "mojo/edk/system/memory.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -28,6 +28,11 @@ namespace system { template class UserOptionsReader { public: + static_assert(offsetof(Options, struct_size) == 0, + "struct_size not first member of Options"); + static_assert(std::is_same::value, + "Options::struct_size not a uint32_t"); + // Constructor from a |UserPointer| (which it checks -- this // constructor has side effects!). // Note: We initialize |options_reader_| without checking, since we do a check @@ -35,14 +40,7 @@ class UserOptionsReader { explicit UserOptionsReader(UserPointer options) : options_reader_(UserPointer::Reader::NoCheck(), options.template ReinterpretCast(), - GetSizeForReader(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?) - } + GetSizeForReader(options)) {} bool is_valid() const { return !!options_reader_.GetPointer(); } @@ -90,11 +88,11 @@ class UserOptionsReader { // (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. +// TODO(vtl): Can we pull out the type |Options| from |reader| instead of +// requiring a parameter? (E.g., we could give |UserOptionsReader| a type alias +// for |Options|. Or maybe there's a clever way to use |decltype|.) #define OPTIONS_STRUCT_HAS_MEMBER(Options, member, reader) \ - reader.HasMember(offsetof(Options, member), sizeof(reader.options().member)) + reader.HasMember(offsetof(Options, member), sizeof(Options::member)) } // namespace system } // namespace mojo diff --git a/mojo/edk/system/platform_handle_dispatcher.h b/mojo/edk/system/platform_handle_dispatcher.h index 8e8cf6904d9..86d63e59889 100644 --- a/mojo/edk/system/platform_handle_dispatcher.h +++ b/mojo/edk/system/platform_handle_dispatcher.h @@ -7,7 +7,6 @@ #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/simple_dispatcher.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -15,8 +14,7 @@ namespace system { // A dispatcher that simply wraps/transports a |PlatformHandle| (only for use by // the embedder). -class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher final - : public SimpleDispatcher { +class PlatformHandleDispatcher final : public SimpleDispatcher { public: static scoped_refptr Create( embedder::ScopedPlatformHandle platform_handle) { diff --git a/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/mojo/edk/system/platform_handle_dispatcher_unittest.cc index 55887a79704..ecc4d3e5cd7 100644 --- a/mojo/edk/system/platform_handle_dispatcher_unittest.cc +++ b/mojo/edk/system/platform_handle_dispatcher_unittest.cc @@ -6,12 +6,10 @@ #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/test/scoped_test_dir.h" #include "mojo/edk/test/test_utils.h" +#include "mojo/edk/util/scoped_file.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { @@ -19,14 +17,11 @@ namespace system { namespace { TEST(PlatformHandleDispatcherTest, Basic) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + mojo::test::ScopedTestDir test_dir; static const char kHelloWorld[] = "hello world"; - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); + util::ScopedFILE fp(test_dir.CreateFile()); ASSERT_TRUE(fp); EXPECT_EQ(sizeof(kHelloWorld), fwrite(kHelloWorld, 1, sizeof(kHelloWorld), fp.get())); @@ -62,14 +57,11 @@ TEST(PlatformHandleDispatcherTest, Basic) { } TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + mojo::test::ScopedTestDir test_dir; static const char kFooBar[] = "foo bar"; - base::FilePath unused; - base::ScopedFILE fp( - CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); + util::ScopedFILE fp(test_dir.CreateFile()); EXPECT_EQ(sizeof(kFooBar), fwrite(kFooBar, 1, sizeof(kFooBar), fp.get())); scoped_refptr dispatcher = diff --git a/mojo/edk/system/proxy_message_pipe_endpoint.cc b/mojo/edk/system/proxy_message_pipe_endpoint.cc index ce96f248e47..951fb29e085 100644 --- a/mojo/edk/system/proxy_message_pipe_endpoint.cc +++ b/mojo/edk/system/proxy_message_pipe_endpoint.cc @@ -6,6 +6,8 @@ #include +#include + #include "base/logging.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/local_message_pipe_endpoint.h" @@ -44,9 +46,9 @@ bool ProxyMessagePipeEndpoint::OnPeerClose() { // -- it may have been written to and closed immediately, before we were ready. // This case is handled in |Run()| (which will call us). void ProxyMessagePipeEndpoint::EnqueueMessage( - scoped_ptr message) { + std::unique_ptr message) { DCHECK(channel_endpoint_); - bool ok = channel_endpoint_->EnqueueMessage(message.Pass()); + bool ok = channel_endpoint_->EnqueueMessage(std::move(message)); LOG_IF(WARNING, !ok) << "Failed to write enqueue message to channel"; } diff --git a/mojo/edk/system/proxy_message_pipe_endpoint.h b/mojo/edk/system/proxy_message_pipe_endpoint.h index 385379bcca2..b11093e43d8 100644 --- a/mojo/edk/system/proxy_message_pipe_endpoint.h +++ b/mojo/edk/system/proxy_message_pipe_endpoint.h @@ -8,7 +8,6 @@ #include "base/memory/ref_counted.h" #include "mojo/edk/system/message_in_transit.h" #include "mojo/edk/system/message_pipe_endpoint.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -27,8 +26,7 @@ class MessagePipe; // remote consists of a |LocalMessagePipeEndpoint| and a // |ProxyMessagePipeEndpoint|, with only the local endpoint being accessible via // a |MessagePipeDispatcher|. -class MOJO_SYSTEM_IMPL_EXPORT ProxyMessagePipeEndpoint final - : public MessagePipeEndpoint { +class ProxyMessagePipeEndpoint final : public MessagePipeEndpoint { public: explicit ProxyMessagePipeEndpoint(ChannelEndpoint* channel_endpoint); ~ProxyMessagePipeEndpoint() override; @@ -44,7 +42,7 @@ class MOJO_SYSTEM_IMPL_EXPORT ProxyMessagePipeEndpoint final // |MessagePipeEndpoint| implementation: Type GetType() const override; bool OnPeerClose() override; - void EnqueueMessage(scoped_ptr message) override; + void EnqueueMessage(std::unique_ptr message) override; void Close() override; private: diff --git a/mojo/edk/system/raw_channel.cc b/mojo/edk/system/raw_channel.cc index ac9f3ffc32a..9c1aa247bd2 100644 --- a/mojo/edk/system/raw_channel.cc +++ b/mojo/edk/system/raw_channel.cc @@ -7,6 +7,7 @@ #include #include +#include #include "base/bind.h" #include "base/location.h" @@ -163,7 +164,7 @@ RawChannel::~RawChannel() { DCHECK(!read_buffer_); DCHECK(!write_buffer_); - // No need to take the |write_lock_| here -- if there are still weak pointers + // No need to take |write_mutex_| here -- if there are still weak pointers // outstanding, then we're hosed anyway (since we wouldn't be able to // invalidate them cleanly, since we might not be on the I/O thread). DCHECK(!weak_ptr_factory_.HasWeakPtrs()); @@ -203,7 +204,7 @@ void RawChannel::Init(Delegate* delegate) { void RawChannel::Shutdown() { DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); - base::AutoLock locker(write_lock_); + MutexLocker locker(&write_mutex_); LOG_IF(WARNING, !write_buffer_->message_queue_.IsEmpty()) << "Shutting down RawChannel with write buffer nonempty"; @@ -217,23 +218,23 @@ void RawChannel::Shutdown() { write_stopped_ = true; weak_ptr_factory_.InvalidateWeakPtrs(); - OnShutdownNoLock(read_buffer_.Pass(), write_buffer_.Pass()); + OnShutdownNoLock(std::move(read_buffer_), std::move(write_buffer_)); } // Reminder: This must be thread-safe. -bool RawChannel::WriteMessage(scoped_ptr message) { +bool RawChannel::WriteMessage(std::unique_ptr message) { DCHECK(message); - base::AutoLock locker(write_lock_); + MutexLocker locker(&write_mutex_); if (write_stopped_) return false; if (!write_buffer_->message_queue_.IsEmpty()) { - EnqueueMessageNoLock(message.Pass()); + EnqueueMessageNoLock(std::move(message)); return true; } - EnqueueMessageNoLock(message.Pass()); + EnqueueMessageNoLock(std::move(message)); DCHECK_EQ(write_buffer_->data_offset_, 0u); size_t platform_handles_written = 0; @@ -258,7 +259,7 @@ bool RawChannel::WriteMessage(scoped_ptr message) { // Reminder: This must be thread-safe. bool RawChannel::IsWriteBufferEmpty() { - base::AutoLock locker(write_lock_); + MutexLocker locker(&write_mutex_); return write_buffer_->message_queue_.IsEmpty(); } @@ -332,9 +333,8 @@ void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { &platform_handle_table); if (num_platform_handles > 0) { - platform_handles = - GetReadPlatformHandles(num_platform_handles, - platform_handle_table).Pass(); + platform_handles = GetReadPlatformHandles(num_platform_handles, + platform_handle_table); if (!platform_handles) { LOG(ERROR) << "Invalid number of platform handles received"; CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); @@ -353,7 +353,7 @@ void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { DCHECK(!set_on_shutdown_); set_on_shutdown_ = &shutdown_called; DCHECK(delegate_); - delegate_->OnReadMessage(message_view, platform_handles.Pass()); + delegate_->OnReadMessage(message_view, std::move(platform_handles)); if (shutdown_called) return; set_on_shutdown_ = nullptr; @@ -412,7 +412,7 @@ void RawChannel::OnWriteCompleted(IOResult io_result, bool did_fail = false; { - base::AutoLock locker(write_lock_); + MutexLocker locker(&write_mutex_); DCHECK_EQ(write_stopped_, write_buffer_->message_queue_.IsEmpty()); if (write_stopped_) { @@ -430,9 +430,10 @@ void RawChannel::OnWriteCompleted(IOResult io_result, } } -void RawChannel::EnqueueMessageNoLock(scoped_ptr message) { - write_lock_.AssertAcquired(); - write_buffer_->message_queue_.AddMessage(message.Pass()); +void RawChannel::EnqueueMessageNoLock( + std::unique_ptr message) { + write_mutex_.AssertHeld(); + write_buffer_->message_queue_.AddMessage(std::move(message)); } bool RawChannel::OnReadMessageForRawChannel( @@ -463,7 +464,7 @@ RawChannel::Delegate::Error RawChannel::ReadIOResultToError( void RawChannel::CallOnError(Delegate::Error error) { DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); - // TODO(vtl): Add a "write_lock_.AssertNotAcquired()"? + // TODO(vtl): Add a "write_mutex_.AssertNotHeld()"? if (delegate_) { delegate_->OnError(error); return; // |this| may have been destroyed in |OnError()|. @@ -473,7 +474,7 @@ void RawChannel::CallOnError(Delegate::Error error) { bool RawChannel::OnWriteCompletedNoLock(IOResult io_result, size_t platform_handles_written, size_t bytes_written) { - write_lock_.AssertAcquired(); + write_mutex_.AssertHeld(); DCHECK(!write_stopped_); DCHECK(!write_buffer_->message_queue_.IsEmpty()); diff --git a/mojo/edk/system/raw_channel.h b/mojo/edk/system/raw_channel.h index cbcc1b3fc63..6a783955514 100644 --- a/mojo/edk/system/raw_channel.h +++ b/mojo/edk/system/raw_channel.h @@ -5,16 +5,16 @@ #ifndef MOJO_EDK_SYSTEM_RAW_CHANNEL_H_ #define MOJO_EDK_SYSTEM_RAW_CHANNEL_H_ +#include #include -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/synchronization/lock.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/message_in_transit.h" #include "mojo/edk/system/message_in_transit_queue.h" -#include "mojo/edk/system/system_impl_export.h" +#include "mojo/edk/system/mutex.h" +#include "mojo/edk/system/thread_annotations.h" #include "mojo/public/cpp/system/macros.h" namespace base { @@ -36,10 +36,10 @@ namespace system { // OS-specific implementation subclasses are to be instantiated using the // |Create()| static factory method. // -// With the exception of |WriteMessage()|, this class is thread-unsafe (and in -// general its methods should only be used on the I/O thread, i.e., the thread -// on which |Init()| is called). -class MOJO_SYSTEM_IMPL_EXPORT RawChannel { +// With the exception of |WriteMessage()| and |IsWriteBufferEmpty()|, this class +// is thread-unsafe (and in general its methods should only be used on the I/O +// thread, i.e., the thread on which |Init()| is called). +class RawChannel { public: // This object may be destroyed on any thread (if |Init()| was called, after // |Shutdown()| was called). @@ -47,7 +47,7 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { // The |Delegate| is only accessed on the same thread as the message loop // (passed in on creation). - class MOJO_SYSTEM_IMPL_EXPORT Delegate { + class Delegate { public: enum Error { // Failed read due to raw channel shutdown (e.g., on the other side). @@ -84,22 +84,23 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { // Static factory method. |handle| should be a handle to a // (platform-appropriate) bidirectional communication channel (e.g., a socket // on POSIX, a named pipe on Windows). - static scoped_ptr Create(embedder::ScopedPlatformHandle handle); + static std::unique_ptr Create( + embedder::ScopedPlatformHandle handle); // This must be called (on an I/O thread) before this object is used. Does // *not* take ownership of |delegate|. Both the I/O thread and |delegate| must // remain alive until |Shutdown()| is called (unless this fails); |delegate| // will no longer be used after |Shutdown()|. - void Init(Delegate* delegate); + void Init(Delegate* delegate) MOJO_NOT_THREAD_SAFE; // This must be called (on the I/O thread) before this object is destroyed. - void Shutdown(); + void Shutdown() MOJO_NOT_THREAD_SAFE; // Writes the given message (or schedules it to be written). |message| must // have no |Dispatcher|s still attached (i.e., // |SerializeAndCloseDispatchers()| should have been called). This method is // thread-safe and may be called from any thread. Returns true on success. - bool WriteMessage(scoped_ptr message); + bool WriteMessage(std::unique_ptr message); // Returns true if the write buffer is empty (i.e., all messages written using // |WriteMessage()| have actually been sent. @@ -125,7 +126,7 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { IO_PENDING }; - class MOJO_SYSTEM_IMPL_EXPORT ReadBuffer { + class ReadBuffer { public: ReadBuffer(); ~ReadBuffer(); @@ -145,7 +146,7 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { MOJO_DISALLOW_COPY_AND_ASSIGN(ReadBuffer); }; - class MOJO_SYSTEM_IMPL_EXPORT WriteBuffer { + class WriteBuffer { public: struct Buffer { const char* addr; @@ -199,31 +200,32 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { RawChannel(); - // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. This object may be destroyed by this call. - void OnReadCompleted(IOResult io_result, size_t bytes_read); - // |result| must not be |IO_PENDING|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. This object may be destroyed by this call. + // |result| must not be |IO_PENDING|. Must be called on the I/O thread. This + // object may be destroyed by this call. + void OnReadCompleted(IOResult io_result, size_t bytes_read) + MOJO_LOCKS_EXCLUDED(write_mutex_); + // |result| must not be |IO_PENDING|. Must be called on the I/O thread. This + // object may be destroyed by this call. void OnWriteCompleted(IOResult io_result, size_t platform_handles_written, - size_t bytes_written); + size_t bytes_written) MOJO_LOCKS_EXCLUDED(write_mutex_); base::MessageLoopForIO* message_loop_for_io() { return message_loop_for_io_; } - base::Lock& write_lock() { return write_lock_; } + Mutex& write_mutex() MOJO_LOCK_RETURNED(write_mutex_) { return write_mutex_; } // Should only be called on the I/O thread. ReadBuffer* read_buffer() { return read_buffer_.get(); } - // Only called under |write_lock_|. - WriteBuffer* write_buffer_no_lock() { - write_lock_.AssertAcquired(); + WriteBuffer* write_buffer_no_lock() + MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_) { return write_buffer_.get(); } // Adds |message| to the write message queue. Implementation subclasses may // override this to add any additional "control" messages needed. This is - // called (on any thread) with |write_lock_| held. - virtual void EnqueueMessageNoLock(scoped_ptr message); + // called (on any thread). + virtual void EnqueueMessageNoLock(std::unique_ptr message) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_); // Handles any control messages targeted to the |RawChannel| (or // implementation subclass). Implementation subclasses may override this to @@ -239,34 +241,34 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { // - the area indicated by |GetBuffer()| will stay valid until read completion // (but please also see the comments for |OnShutdownNoLock()|); // - a second read is not started if there is a pending read; - // - the method is called on the I/O thread WITHOUT |write_lock_| held. + // - the method is called on the I/O thread. // // The implementing subclass must guarantee that: // - |bytes_read| is untouched unless |Read()| returns |IO_SUCCEEDED|; // - if the method returns |IO_PENDING|, |OnReadCompleted()| will be called on // the I/O thread to report the result, unless |Shutdown()| is called. - virtual IOResult Read(size_t* bytes_read) = 0; + virtual IOResult Read(size_t* bytes_read) + MOJO_LOCKS_EXCLUDED(write_mutex_) = 0; // Similar to |Read()|, except that the implementing subclass must also // guarantee that the method doesn't succeed synchronously, i.e., it only // returns |IO_FAILED_...| or |IO_PENDING|. - virtual IOResult ScheduleRead() = 0; + virtual IOResult ScheduleRead() MOJO_LOCKS_EXCLUDED(write_mutex_) = 0; // Called by |OnReadCompleted()| to get the platform handles associated with // the given platform handle table (from a message). This should only be // called when |num_platform_handles| is nonzero. Returns null if the // |num_platform_handles| handles are not available. Only called on the I/O - // thread (without |write_lock_| held). + // thread. virtual embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( size_t num_platform_handles, - const void* platform_handle_table) = 0; + const void* platform_handle_table) MOJO_LOCKS_EXCLUDED(write_mutex_) = 0; // Writes contents in |write_buffer_no_lock()|. // This class guarantees that: // - the |PlatformHandle|s given by |GetPlatformHandlesToSend()| and the // buffer(s) given by |GetBuffers()| will remain valid until write // completion (see also the comments for |OnShutdownNoLock()|); - // - a second write is not started if there is a pending write; - // - the method is called under |write_lock_|. + // - a second write is not started if there is a pending write. // // The implementing subclass must guarantee that: // - |platform_handles_written| and |bytes_written| are untouched unless @@ -274,37 +276,39 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { // - if the method returns |IO_PENDING|, |OnWriteCompleted()| will be called // on the I/O thread to report the result, unless |Shutdown()| is called. virtual IOResult WriteNoLock(size_t* platform_handles_written, - size_t* bytes_written) = 0; + size_t* bytes_written) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_) = 0; // Similar to |WriteNoLock()|, except that the implementing subclass must also // guarantee that the method doesn't succeed synchronously, i.e., it only // returns |IO_FAILED_...| or |IO_PENDING|. virtual IOResult ScheduleWriteNoLock() = 0; - // Must be called on the I/O thread WITHOUT |write_lock_| held. - virtual void OnInit() = 0; + // Must be called on the I/O thread. + virtual void OnInit() MOJO_LOCKS_EXCLUDED(write_mutex_) = 0; // On shutdown, passes the ownership of the buffers to subclasses, which may // want to preserve them if there are pending read/writes. After this is // called, |OnReadCompleted()| must no longer be called. Must be called on the - // I/O thread under |write_lock_|. - virtual void OnShutdownNoLock(scoped_ptr read_buffer, - scoped_ptr write_buffer) = 0; + // I/O thread. + virtual void OnShutdownNoLock(std::unique_ptr read_buffer, + std::unique_ptr write_buffer) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_) = 0; private: // Converts an |IO_FAILED_...| for a read to a |Delegate::Error|. static Delegate::Error ReadIOResultToError(IOResult io_result); - // Calls |delegate_->OnError(error)|. Must be called on the I/O thread WITHOUT - // |write_lock_| held. This object may be destroyed by this call. - void CallOnError(Delegate::Error error); + // Calls |delegate_->OnError(error)|. Must be called on the I/O thread. This + // object may be destroyed by this call. + void CallOnError(Delegate::Error error) MOJO_LOCKS_EXCLUDED(write_mutex_); // If |io_result| is |IO_SUCCESS|, updates the write buffer and schedules a // write operation to run later if there is more to write. If |io_result| is // failure or any other error occurs, cancels pending writes and returns - // false. Must be called under |write_lock_| and only if |write_stopped_| is - // false. + // false. May only be called if |write_stopped_| is false. bool OnWriteCompletedNoLock(IOResult io_result, size_t platform_handles_written, - size_t bytes_written); + size_t bytes_written) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex_); // Set in |Init()| and never changed (hence usable on any thread without // locking): @@ -313,16 +317,16 @@ class MOJO_SYSTEM_IMPL_EXPORT RawChannel { // Only used on the I/O thread: Delegate* delegate_; bool* set_on_shutdown_; - scoped_ptr read_buffer_; + std::unique_ptr read_buffer_; - base::Lock write_lock_; // Protects the following members. - bool write_stopped_; - scoped_ptr write_buffer_; + Mutex write_mutex_; // Protects the following members. + bool write_stopped_ MOJO_GUARDED_BY(write_mutex_); + std::unique_ptr write_buffer_ MOJO_GUARDED_BY(write_mutex_); - // This is used for posting tasks from write threads to the I/O thread. It - // must only be accessed under |write_lock_|. The weak pointers it produces - // are only used/invalidated on the I/O thread. - base::WeakPtrFactory weak_ptr_factory_; + // This is used for posting tasks from write threads to the I/O thread. The + // weak pointers it produces are only used/invalidated on the I/O thread. + base::WeakPtrFactory weak_ptr_factory_ + MOJO_GUARDED_BY(write_mutex_); MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannel); }; diff --git a/mojo/edk/system/raw_channel_posix.cc b/mojo/edk/system/raw_channel_posix.cc index 47862a709f6..d740516e7d5 100644 --- a/mojo/edk/system/raw_channel_posix.cc +++ b/mojo/edk/system/raw_channel_posix.cc @@ -10,18 +10,19 @@ #include #include +#include +#include #include "base/bind.h" #include "base/location.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" -#include "base/synchronization/lock.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/system/transport_data.h" +#include "mojo/edk/util/make_unique.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -42,7 +43,8 @@ class RawChannelPosix final : public RawChannel, // |RawChannel| protected methods: // Actually override this so that we can send multiple messages with (only) // FDs if necessary. - void EnqueueMessageNoLock(scoped_ptr message) override; + void EnqueueMessageNoLock(std::unique_ptr message) override + MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex()); // Override this to handle those extra FD-only messages. bool OnReadMessageForRawChannel( const MessageInTransit::View& message_view) override; @@ -55,8 +57,8 @@ class RawChannelPosix final : public RawChannel, size_t* bytes_written) override; IOResult ScheduleWriteNoLock() override; void OnInit() override; - void OnShutdownNoLock(scoped_ptr read_buffer, - scoped_ptr write_buffer) override; + void OnShutdownNoLock(std::unique_ptr read_buffer, + std::unique_ptr write_buffer) override; // |base::MessageLoopForIO::Watcher| implementation: void OnFileCanReadWithoutBlocking(int fd) override; @@ -71,21 +73,19 @@ class RawChannelPosix final : public RawChannel, embedder::ScopedPlatformHandle fd_; // The following members are only used on the I/O thread: - scoped_ptr read_watcher_; - scoped_ptr write_watcher_; + std::unique_ptr read_watcher_; + std::unique_ptr write_watcher_; bool pending_read_; std::deque read_platform_handles_; - // The following members are used on multiple threads and protected by - // |write_lock()|: - bool pending_write_; + bool pending_write_ MOJO_GUARDED_BY(write_mutex()); - // This is used for posting tasks from write threads to the I/O thread. It - // must only be accessed under |write_lock_|. The weak pointers it produces - // are only used/invalidated on the I/O thread. - base::WeakPtrFactory weak_ptr_factory_; + // This is used for posting tasks from write threads to the I/O thread. The + // weak pointers it produces are only used/invalidated on the I/O thread. + base::WeakPtrFactory weak_ptr_factory_ + MOJO_GUARDED_BY(write_mutex()); MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelPosix); }; @@ -102,7 +102,7 @@ RawChannelPosix::~RawChannelPosix() { DCHECK(!pending_read_); DCHECK(!pending_write_); - // No need to take the |write_lock()| here -- if there are still weak pointers + // No need to take |write_mutex()| here -- if there are still weak pointers // outstanding, then we're hosed anyway (since we wouldn't be able to // invalidate them cleanly, since we might not be on the I/O thread). DCHECK(!weak_ptr_factory_.HasWeakPtrs()); @@ -120,7 +120,7 @@ size_t RawChannelPosix::GetSerializedPlatformHandleSize() const { } void RawChannelPosix::EnqueueMessageNoLock( - scoped_ptr message) { + std::unique_ptr message) { if (message->transport_data()) { embedder::PlatformHandleVector* const platform_handles = message->transport_data()->platform_handles(); @@ -133,7 +133,7 @@ void RawChannelPosix::EnqueueMessageNoLock( for (; platform_handles->size() - i > embedder::kPlatformChannelMaxNumHandles; i += embedder::kPlatformChannelMaxNumHandles) { - scoped_ptr fd_message(new MessageInTransit( + std::unique_ptr fd_message(new MessageInTransit( MessageInTransit::Type::RAW_CHANNEL, MessageInTransit::Subtype::RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES, 0, nullptr)); @@ -142,9 +142,9 @@ void RawChannelPosix::EnqueueMessageNoLock( platform_handles->begin() + i, platform_handles->begin() + i + embedder::kPlatformChannelMaxNumHandles)); - fd_message->SetTransportData(make_scoped_ptr( - new TransportData(fds.Pass(), GetSerializedPlatformHandleSize()))); - RawChannel::EnqueueMessageNoLock(fd_message.Pass()); + fd_message->SetTransportData(util::MakeUnique( + std::move(fds), GetSerializedPlatformHandleSize())); + RawChannel::EnqueueMessageNoLock(std::move(fd_message)); } // Remove the handles that we "moved" into the other messages. @@ -153,7 +153,7 @@ void RawChannelPosix::EnqueueMessageNoLock( } } - RawChannel::EnqueueMessageNoLock(message.Pass()); + RawChannel::EnqueueMessageNoLock(std::move(message)); } bool RawChannelPosix::OnReadMessageForRawChannel( @@ -209,13 +209,13 @@ embedder::ScopedPlatformHandleVectorPtr RawChannelPosix::GetReadPlatformHandles( read_platform_handles_.erase( read_platform_handles_.begin(), read_platform_handles_.begin() + num_platform_handles); - return rv.Pass(); + return rv; } RawChannel::IOResult RawChannelPosix::WriteNoLock( size_t* platform_handles_written, size_t* bytes_written) { - write_lock().AssertAcquired(); + write_mutex().AssertHeld(); DCHECK(!pending_write_); @@ -288,7 +288,7 @@ RawChannel::IOResult RawChannelPosix::WriteNoLock( } RawChannel::IOResult RawChannelPosix::ScheduleWriteNoLock() { - write_lock().AssertAcquired(); + write_mutex().AssertHeld(); DCHECK(!pending_write_); @@ -329,10 +329,10 @@ void RawChannelPosix::OnInit() { } void RawChannelPosix::OnShutdownNoLock( - scoped_ptr /*read_buffer*/, - scoped_ptr /*write_buffer*/) { + std::unique_ptr /*read_buffer*/, + std::unique_ptr /*write_buffer*/) { DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - write_lock().AssertAcquired(); + write_mutex().AssertHeld(); read_watcher_.reset(); // This will stop watching (if necessary). write_watcher_.reset(); // This will stop watching (if necessary). @@ -385,7 +385,7 @@ void RawChannelPosix::OnFileCanWriteWithoutBlocking(int fd) { size_t platform_handles_written = 0; size_t bytes_written = 0; { - base::AutoLock locker(write_lock()); + MutexLocker locker(&write_mutex()); DCHECK(pending_write_); @@ -454,7 +454,7 @@ void RawChannelPosix::WaitToWrite() { fd_.get().fd, false, base::MessageLoopForIO::WATCH_WRITE, write_watcher_.get(), this)) { { - base::AutoLock locker(write_lock()); + MutexLocker locker(&write_mutex()); DCHECK(pending_write_); pending_write_ = false; @@ -470,9 +470,9 @@ void RawChannelPosix::WaitToWrite() { // Static factory method declared in raw_channel.h. // static -scoped_ptr RawChannel::Create( +std::unique_ptr RawChannel::Create( embedder::ScopedPlatformHandle handle) { - return make_scoped_ptr(new RawChannelPosix(handle.Pass())); + return util::MakeUnique(handle.Pass()); } } // namespace system diff --git a/mojo/edk/system/raw_channel_unittest.cc b/mojo/edk/system/raw_channel_unittest.cc index 2fa3f7b3f05..0d6f2c32267 100644 --- a/mojo/edk/system/raw_channel_unittest.cc +++ b/mojo/edk/system/raw_channel_unittest.cc @@ -7,21 +7,16 @@ #include #include +#include +#include #include #include "base/bind.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/location.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/synchronization/waitable_event.h" -#include "base/test/test_io_thread.h" #include "base/threading/simple_thread.h" -#include "build/build_config.h" // TODO(vtl): Remove this. #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/platform_handle.h" #include "mojo/edk/embedder/scoped_platform_handle.h" @@ -29,7 +24,11 @@ #include "mojo/edk/system/mutex.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/system/transport_data.h" +#include "mojo/edk/test/scoped_test_dir.h" +#include "mojo/edk/test/test_io_thread.h" #include "mojo/edk/test/test_utils.h" +#include "mojo/edk/util/make_unique.h" +#include "mojo/edk/util/scoped_file.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -37,14 +36,14 @@ namespace mojo { namespace system { namespace { -scoped_ptr MakeTestMessage(uint32_t num_bytes) { +std::unique_ptr MakeTestMessage(uint32_t num_bytes) { std::vector bytes(num_bytes, 0); for (size_t i = 0; i < num_bytes; i++) bytes[i] = static_cast(i + num_bytes); - return make_scoped_ptr( - new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - num_bytes, bytes.empty() ? nullptr : &bytes[0])); + return util::MakeUnique( + MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, num_bytes, + bytes.empty() ? nullptr : &bytes[0]); } bool CheckMessageData(const void* bytes, uint32_t num_bytes) { @@ -62,7 +61,7 @@ void InitOnIOThread(RawChannel* raw_channel, RawChannel::Delegate* delegate) { bool WriteTestMessageToHandle(const embedder::PlatformHandle& handle, uint32_t num_bytes) { - scoped_ptr message(MakeTestMessage(num_bytes)); + std::unique_ptr message(MakeTestMessage(num_bytes)); size_t write_size = 0; mojo::test::BlockingWrite(handle, message->main_buffer(), @@ -74,7 +73,7 @@ bool WriteTestMessageToHandle(const embedder::PlatformHandle& handle, class RawChannelTest : public testing::Test { public: - RawChannelTest() : io_thread_(base::TestIOThread::kManualStart) {} + RawChannelTest() : io_thread_(mojo::test::TestIOThread::kManualStart) {} ~RawChannelTest() override {} void SetUp() override { @@ -91,12 +90,12 @@ class RawChannelTest : public testing::Test { } protected: - base::TestIOThread* io_thread() { return &io_thread_; } + mojo::test::TestIOThread* io_thread() { return &io_thread_; } embedder::ScopedPlatformHandle handles[2]; private: - base::TestIOThread io_thread_; + mojo::test::TestIOThread io_thread_; MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelTest); }; @@ -193,7 +192,7 @@ class TestMessageReaderAndChecker { // Tests writing (and verifies reading using our own custom reader). TEST_F(RawChannelTest, WriteMessage) { WriteOnlyRawChannelDelegate delegate; - scoped_ptr rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc(RawChannel::Create(handles[0].Pass())); TestMessageReaderAndChecker checker(handles[1].get()); io_thread()->PostTaskAndWait( FROM_HERE, @@ -279,7 +278,7 @@ class ReadCheckerRawChannelDelegate : public RawChannel::Delegate { // Tests reading (writing using our own custom writer). TEST_F(RawChannelTest, OnReadMessage) { ReadCheckerRawChannelDelegate delegate; - scoped_ptr rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc(RawChannel::Create(handles[0].Pass())); io_thread()->PostTaskAndWait( FROM_HERE, base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); @@ -376,14 +375,14 @@ TEST_F(RawChannelTest, WriteMessageAndOnReadMessage) { static const size_t kNumWriteMessagesPerThread = 4000; WriteOnlyRawChannelDelegate writer_delegate; - scoped_ptr writer_rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr writer_rc(RawChannel::Create(handles[0].Pass())); io_thread()->PostTaskAndWait(FROM_HERE, base::Bind(&InitOnIOThread, writer_rc.get(), base::Unretained(&writer_delegate))); ReadCountdownRawChannelDelegate reader_delegate(kNumWriterThreads * kNumWriteMessagesPerThread); - scoped_ptr reader_rc(RawChannel::Create(handles[1].Pass())); + std::unique_ptr reader_rc(RawChannel::Create(handles[1].Pass())); io_thread()->PostTaskAndWait(FROM_HERE, base::Bind(&InitOnIOThread, reader_rc.get(), base::Unretained(&reader_delegate))); @@ -473,7 +472,7 @@ class ErrorRecordingRawChannelDelegate // Tests (fatal) errors. TEST_F(RawChannelTest, OnError) { ErrorRecordingRawChannelDelegate delegate(0, true, true); - scoped_ptr rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc(RawChannel::Create(handles[0].Pass())); io_thread()->PostTaskAndWait( FROM_HERE, base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); @@ -516,7 +515,7 @@ TEST_F(RawChannelTest, ReadUnaffectedByWriteError) { // Only start up reading here. The system buffer should still contain the // messages that were written. ErrorRecordingRawChannelDelegate delegate(kMessageCount, true, true); - scoped_ptr rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc(RawChannel::Create(handles[0].Pass())); io_thread()->PostTaskAndWait( FROM_HERE, base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); @@ -542,7 +541,7 @@ TEST_F(RawChannelTest, ReadUnaffectedByWriteError) { // correctly. TEST_F(RawChannelTest, WriteMessageAfterShutdown) { WriteOnlyRawChannelDelegate delegate; - scoped_ptr rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc(RawChannel::Create(handles[0].Pass())); io_thread()->PostTaskAndWait( FROM_HERE, base::Bind(&InitOnIOThread, rc.get(), base::Unretained(&delegate))); @@ -602,7 +601,7 @@ TEST_F(RawChannelTest, ShutdownOnReadMessage) { for (size_t count = 0; count < 5; count++) EXPECT_TRUE(WriteTestMessageToHandle(handles[1].get(), 10)); - scoped_ptr rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc(RawChannel::Create(handles[0].Pass())); ShutdownOnReadMessageRawChannelDelegate delegate(rc.get(), false); io_thread()->PostTaskAndWait( FROM_HERE, @@ -674,7 +673,7 @@ class ShutdownOnErrorRawChannelDelegate : public RawChannel::Delegate { }; TEST_F(RawChannelTest, ShutdownOnErrorRead) { - scoped_ptr rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc(RawChannel::Create(handles[0].Pass())); ShutdownOnErrorRawChannelDelegate delegate( rc.get(), false, RawChannel::Delegate::ERROR_READ_SHUTDOWN); io_thread()->PostTaskAndWait( @@ -703,7 +702,7 @@ TEST_F(RawChannelTest, ShutdownAndDestroyOnErrorRead) { } TEST_F(RawChannelTest, ShutdownOnErrorWrite) { - scoped_ptr rc(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc(RawChannel::Create(handles[0].Pass())); ShutdownOnErrorRawChannelDelegate delegate(rc.get(), false, RawChannel::Delegate::ERROR_WRITE); io_thread()->PostTaskAndWait( @@ -763,7 +762,7 @@ class ReadPlatformHandlesCheckerRawChannelDelegate { char buffer[100] = {}; - base::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h1.Pass(), "rb")); + util::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h1.Pass(), "rb")); EXPECT_TRUE(fp); rewind(fp.get()); EXPECT_EQ(1u, fread(buffer, 1, sizeof(buffer), fp.get())); @@ -772,7 +771,7 @@ class ReadPlatformHandlesCheckerRawChannelDelegate { char buffer[100] = {}; - base::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h2.Pass(), "rb")); + util::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h2.Pass(), "rb")); EXPECT_TRUE(fp); rewind(fp.get()); EXPECT_EQ(1u, fread(buffer, 1, sizeof(buffer), fp.get())); @@ -794,34 +793,24 @@ class ReadPlatformHandlesCheckerRawChannelDelegate MOJO_DISALLOW_COPY_AND_ASSIGN(ReadPlatformHandlesCheckerRawChannelDelegate); }; -#if defined(OS_POSIX) -#define MAYBE_ReadWritePlatformHandles ReadWritePlatformHandles -#else -// Not yet implemented (on Windows). -#define MAYBE_ReadWritePlatformHandles DISABLED_ReadWritePlatformHandles -#endif -TEST_F(RawChannelTest, MAYBE_ReadWritePlatformHandles) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); +TEST_F(RawChannelTest, ReadWritePlatformHandles) { + mojo::test::ScopedTestDir test_dir; WriteOnlyRawChannelDelegate write_delegate; - scoped_ptr rc_write(RawChannel::Create(handles[0].Pass())); + std::unique_ptr rc_write(RawChannel::Create(handles[0].Pass())); io_thread()->PostTaskAndWait(FROM_HERE, base::Bind(&InitOnIOThread, rc_write.get(), base::Unretained(&write_delegate))); ReadPlatformHandlesCheckerRawChannelDelegate read_delegate; - scoped_ptr rc_read(RawChannel::Create(handles[1].Pass())); + std::unique_ptr rc_read(RawChannel::Create(handles[1].Pass())); io_thread()->PostTaskAndWait(FROM_HERE, base::Bind(&InitOnIOThread, rc_read.get(), base::Unretained(&read_delegate))); - base::FilePath unused; - base::ScopedFILE fp1( - base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); + util::ScopedFILE fp1(test_dir.CreateFile()); EXPECT_EQ(1u, fwrite("1", 1, 1, fp1.get())); - base::ScopedFILE fp2( - base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); + util::ScopedFILE fp2(test_dir.CreateFile()); EXPECT_EQ(1u, fwrite("2", 1, 1, fp2.get())); { @@ -833,13 +822,14 @@ TEST_F(RawChannelTest, MAYBE_ReadWritePlatformHandles) { platform_handles->push_back( mojo::test::PlatformHandleFromFILE(fp2.Pass()).release()); - scoped_ptr message( + std::unique_ptr message( new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, sizeof(kHello), kHello)); - message->SetTransportData(make_scoped_ptr(new TransportData( - platform_handles.Pass(), rc_write->GetSerializedPlatformHandleSize()))); - EXPECT_TRUE(rc_write->WriteMessage(message.Pass())); + message->SetTransportData(util::MakeUnique( + std::move(platform_handles), + rc_write->GetSerializedPlatformHandleSize())); + EXPECT_TRUE(rc_write->WriteMessage(std::move(message))); } read_delegate.Wait(); diff --git a/mojo/edk/system/raw_channel_win.cc b/mojo/edk/system/raw_channel_win.cc deleted file mode 100644 index 10a9bff7baa..00000000000 --- a/mojo/edk/system/raw_channel_win.cc +++ /dev/null @@ -1,633 +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/raw_channel.h" - -#include - -#include "base/bind.h" -#include "base/lazy_instance.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/process/process.h" -#include "base/synchronization/lock.h" -#include "base/win/windows_version.h" -#include "mojo/edk/embedder/platform_handle.h" -#include "mojo/public/cpp/system/macros.h" - -namespace mojo { -namespace system { - -namespace { - -class VistaOrHigherFunctions { - public: - VistaOrHigherFunctions(); - - bool is_vista_or_higher() const { return is_vista_or_higher_; } - - BOOL SetFileCompletionNotificationModes(HANDLE handle, UCHAR flags) { - return set_file_completion_notification_modes_(handle, flags); - } - - BOOL CancelIoEx(HANDLE handle, LPOVERLAPPED overlapped) { - return cancel_io_ex_(handle, overlapped); - } - - private: - using SetFileCompletionNotificationModesFunc = BOOL(WINAPI*)(HANDLE, UCHAR); - using CancelIoExFunc = BOOL(WINAPI*)(HANDLE, LPOVERLAPPED); - - bool is_vista_or_higher_; - SetFileCompletionNotificationModesFunc - set_file_completion_notification_modes_; - CancelIoExFunc cancel_io_ex_; -}; - -VistaOrHigherFunctions::VistaOrHigherFunctions() - : is_vista_or_higher_(base::win::GetVersion() >= base::win::VERSION_VISTA), - set_file_completion_notification_modes_(nullptr), - cancel_io_ex_(nullptr) { - if (!is_vista_or_higher_) - return; - - HMODULE module = GetModuleHandleW(L"kernel32.dll"); - set_file_completion_notification_modes_ = - reinterpret_cast( - GetProcAddress(module, "SetFileCompletionNotificationModes")); - DCHECK(set_file_completion_notification_modes_); - - cancel_io_ex_ = - reinterpret_cast(GetProcAddress(module, "CancelIoEx")); - DCHECK(cancel_io_ex_); -} - -base::LazyInstance g_vista_or_higher_functions = - LAZY_INSTANCE_INITIALIZER; - -class RawChannelWin final : public RawChannel { - public: - RawChannelWin(embedder::ScopedPlatformHandle handle); - ~RawChannelWin() override; - - // |RawChannel| public methods: - size_t GetSerializedPlatformHandleSize() const override; - - private: - // RawChannelIOHandler receives OS notifications for I/O completion. It must - // be created on the I/O thread. - // - // It manages its own destruction. Destruction happens on the I/O thread when - // all the following conditions are satisfied: - // - |DetachFromOwnerNoLock()| has been called; - // - there is no pending read; - // - there is no pending write. - class RawChannelIOHandler : public base::MessageLoopForIO::IOHandler { - public: - RawChannelIOHandler(RawChannelWin* owner, - embedder::ScopedPlatformHandle handle); - - HANDLE handle() const { return handle_.get().handle; } - - // The following methods are only called by the owner on the I/O thread. - bool pending_read() const; - base::MessageLoopForIO::IOContext* read_context(); - // Instructs the object to wait for an |OnIOCompleted()| notification. - void OnPendingReadStarted(); - - // The following methods are only called by the owner under - // |owner_->write_lock()|. - bool pending_write_no_lock() const; - base::MessageLoopForIO::IOContext* write_context_no_lock(); - // Instructs the object to wait for an |OnIOCompleted()| notification. - void OnPendingWriteStartedNoLock(size_t platform_handles_written); - - // |base::MessageLoopForIO::IOHandler| implementation: - // Must be called on the I/O thread. It could be called before or after - // detached from the owner. - void OnIOCompleted(base::MessageLoopForIO::IOContext* context, - DWORD bytes_transferred, - DWORD error) override; - - // Must be called on the I/O thread under |owner_->write_lock()|. - // After this call, the owner must not make any further calls on this - // object, and therefore the object is used on the I/O thread exclusively - // (if it stays alive). - void DetachFromOwnerNoLock(scoped_ptr read_buffer, - scoped_ptr write_buffer); - - private: - ~RawChannelIOHandler() override; - - // Returns true if |owner_| has been reset and there is not pending read or - // write. - // Must be called on the I/O thread. - bool ShouldSelfDestruct() const; - - // Must be called on the I/O thread. It may be called before or after - // detaching from the owner. - void OnReadCompleted(DWORD bytes_read, DWORD error); - // Must be called on the I/O thread. It may be called before or after - // detaching from the owner. - void OnWriteCompleted(DWORD bytes_written, DWORD error); - - embedder::ScopedPlatformHandle handle_; - - // |owner_| is reset on the I/O thread under |owner_->write_lock()|. - // Therefore, it may be used on any thread under lock; or on the I/O thread - // without locking. - RawChannelWin* owner_; - - // The following members must be used on the I/O thread. - scoped_ptr preserved_read_buffer_after_detach_; - scoped_ptr preserved_write_buffer_after_detach_; - bool suppress_self_destruct_; - - bool pending_read_; - base::MessageLoopForIO::IOContext read_context_; - - // The following members must be used under |owner_->write_lock()| while the - // object is still attached to the owner, and only on the I/O thread - // afterwards. - bool pending_write_; - size_t platform_handles_written_; - base::MessageLoopForIO::IOContext write_context_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler); - }; - - // |RawChannel| private methods: - IOResult Read(size_t* bytes_read) override; - IOResult ScheduleRead() override; - embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( - size_t num_platform_handles, - const void* platform_handle_table) override; - IOResult WriteNoLock(size_t* platform_handles_written, - size_t* bytes_written) override; - IOResult ScheduleWriteNoLock() override; - void OnInit() override; - void OnShutdownNoLock(scoped_ptr read_buffer, - scoped_ptr write_buffer) override; - - // Passed to |io_handler_| during initialization. - embedder::ScopedPlatformHandle handle_; - - RawChannelIOHandler* io_handler_; - - const bool skip_completion_port_on_success_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelWin); -}; - -RawChannelWin::RawChannelIOHandler::RawChannelIOHandler( - RawChannelWin* owner, - embedder::ScopedPlatformHandle handle) - : handle_(handle.Pass()), - owner_(owner), - suppress_self_destruct_(false), - pending_read_(false), - pending_write_(false), - platform_handles_written_(0) { - memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); - read_context_.handler = this; - memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); - write_context_.handler = this; - - owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); -} - -RawChannelWin::RawChannelIOHandler::~RawChannelIOHandler() { - DCHECK(ShouldSelfDestruct()); -} - -bool RawChannelWin::RawChannelIOHandler::pending_read() const { - DCHECK(owner_); - DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); - return pending_read_; -} - -base::MessageLoopForIO::IOContext* -RawChannelWin::RawChannelIOHandler::read_context() { - DCHECK(owner_); - DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); - return &read_context_; -} - -void RawChannelWin::RawChannelIOHandler::OnPendingReadStarted() { - DCHECK(owner_); - DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); - DCHECK(!pending_read_); - pending_read_ = true; -} - -bool RawChannelWin::RawChannelIOHandler::pending_write_no_lock() const { - DCHECK(owner_); - owner_->write_lock().AssertAcquired(); - return pending_write_; -} - -base::MessageLoopForIO::IOContext* -RawChannelWin::RawChannelIOHandler::write_context_no_lock() { - DCHECK(owner_); - owner_->write_lock().AssertAcquired(); - return &write_context_; -} - -void RawChannelWin::RawChannelIOHandler::OnPendingWriteStartedNoLock( - size_t platform_handles_written) { - DCHECK(owner_); - owner_->write_lock().AssertAcquired(); - DCHECK(!pending_write_); - pending_write_ = true; - platform_handles_written_ = platform_handles_written; -} - -void RawChannelWin::RawChannelIOHandler::OnIOCompleted( - base::MessageLoopForIO::IOContext* context, - DWORD bytes_transferred, - DWORD error) { - DCHECK(!owner_ || - base::MessageLoop::current() == owner_->message_loop_for_io()); - - // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they - // result in a call to |Shutdown()|). - bool old_suppress_self_destruct = suppress_self_destruct_; - suppress_self_destruct_ = true; - - if (context == &read_context_) - OnReadCompleted(bytes_transferred, error); - else if (context == &write_context_) - OnWriteCompleted(bytes_transferred, error); - else - NOTREACHED(); - - // Maybe allow self-destruction again. - suppress_self_destruct_ = old_suppress_self_destruct; - - if (ShouldSelfDestruct()) - delete this; -} - -void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( - scoped_ptr read_buffer, - scoped_ptr write_buffer) { - DCHECK(owner_); - DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); - owner_->write_lock().AssertAcquired(); - - // If read/write is pending, we have to retain the corresponding buffer. - if (pending_read_) - preserved_read_buffer_after_detach_ = read_buffer.Pass(); - if (pending_write_) - preserved_write_buffer_after_detach_ = write_buffer.Pass(); - - owner_ = nullptr; - if (ShouldSelfDestruct()) - delete this; -} - -bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { - if (owner_ || suppress_self_destruct_) - return false; - - // Note: Detached, hence no lock needed for |pending_write_|. - return !pending_read_ && !pending_write_; -} - -void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, - DWORD error) { - DCHECK(!owner_ || - base::MessageLoop::current() == owner_->message_loop_for_io()); - DCHECK(suppress_self_destruct_); - - CHECK(pending_read_); - pending_read_ = false; - if (!owner_) - return; - - // Note: |OnReadCompleted()| may detach us from |owner_|. - if (error == ERROR_SUCCESS) { - DCHECK_GT(bytes_read, 0u); - owner_->OnReadCompleted(IO_SUCCEEDED, bytes_read); - } else if (error == ERROR_BROKEN_PIPE) { - DCHECK_EQ(bytes_read, 0u); - owner_->OnReadCompleted(IO_FAILED_SHUTDOWN, 0); - } else { - DCHECK_EQ(bytes_read, 0u); - LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error); - owner_->OnReadCompleted(IO_FAILED_UNKNOWN, 0); - } -} - -void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, - DWORD error) { - DCHECK(!owner_ || - base::MessageLoop::current() == owner_->message_loop_for_io()); - DCHECK(suppress_self_destruct_); - - if (!owner_) { - // No lock needed. - CHECK(pending_write_); - pending_write_ = false; - return; - } - - { - base::AutoLock locker(owner_->write_lock()); - CHECK(pending_write_); - pending_write_ = false; - } - - // Note: |OnWriteCompleted()| may detach us from |owner_|. - if (error == ERROR_SUCCESS) { - // Reset |platform_handles_written_| before calling |OnWriteCompleted()| - // since that function may call back to this class and set it again. - size_t local_platform_handles_written_ = platform_handles_written_; - platform_handles_written_ = 0; - owner_->OnWriteCompleted(IO_SUCCEEDED, local_platform_handles_written_, - bytes_written); - } else if (error == ERROR_BROKEN_PIPE) { - owner_->OnWriteCompleted(IO_FAILED_SHUTDOWN, 0, 0); - } else { - LOG(WARNING) << "WriteFile: " << logging::SystemErrorCodeToString(error); - owner_->OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0); - } -} - -RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle) - : handle_(handle.Pass()), - io_handler_(nullptr), - skip_completion_port_on_success_( - g_vista_or_higher_functions.Get().is_vista_or_higher()) { - DCHECK(handle_.is_valid()); -} - -RawChannelWin::~RawChannelWin() { - DCHECK(!io_handler_); -} - -size_t RawChannelWin::GetSerializedPlatformHandleSize() const { - return sizeof(DWORD) + sizeof(HANDLE); -} - -RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - DCHECK(io_handler_); - DCHECK(!io_handler_->pending_read()); - - char* buffer = nullptr; - size_t bytes_to_read = 0; - read_buffer()->GetBuffer(&buffer, &bytes_to_read); - - BOOL result = - ReadFile(io_handler_->handle(), buffer, static_cast(bytes_to_read), - nullptr, &io_handler_->read_context()->overlapped); - if (!result) { - DWORD error = GetLastError(); - if (error == ERROR_BROKEN_PIPE) - return IO_FAILED_SHUTDOWN; - if (error != ERROR_IO_PENDING) { - LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error); - return IO_FAILED_UNKNOWN; - } - } - - if (result && skip_completion_port_on_success_) { - DWORD bytes_read_dword = 0; - BOOL get_size_result = GetOverlappedResult( - io_handler_->handle(), &io_handler_->read_context()->overlapped, - &bytes_read_dword, FALSE); - DPCHECK(get_size_result); - *bytes_read = bytes_read_dword; - return IO_SUCCEEDED; - } - - // If the read is pending or the read has succeeded but we don't skip - // completion port on success, instruct |io_handler_| to wait for the - // completion packet. - // - // TODO(yzshen): It seems there isn't document saying that all error cases - // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion - // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| - // will crash so we will learn about it. - - io_handler_->OnPendingReadStarted(); - return IO_PENDING; -} - -RawChannel::IOResult RawChannelWin::ScheduleRead() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - DCHECK(io_handler_); - DCHECK(!io_handler_->pending_read()); - - size_t bytes_read = 0; - IOResult io_result = Read(&bytes_read); - if (io_result == IO_SUCCEEDED) { - DCHECK(skip_completion_port_on_success_); - - // We have finished reading successfully. Queue a notification manually. - io_handler_->OnPendingReadStarted(); - // |io_handler_| won't go away before the task is run, so it is safe to use - // |base::Unretained()|. - message_loop_for_io()->PostTask( - FROM_HERE, base::Bind(&RawChannelIOHandler::OnIOCompleted, - base::Unretained(io_handler_), - base::Unretained(io_handler_->read_context()), - static_cast(bytes_read), ERROR_SUCCESS)); - return IO_PENDING; - } - - return io_result; -} - -embedder::ScopedPlatformHandleVectorPtr RawChannelWin::GetReadPlatformHandles( - size_t num_platform_handles, - const void* platform_handle_table) { - // TODO(jam): this code will have to be updated once it's used in a sandbox - // and the receiving process doesn't have duplicate permission for the - // receiver. Once there's a broker and we have a connection to it (possibly - // through ConnectionManager), then we can make a sync IPC to it here to get a - // token for this handle, and it will duplicate the handle to is process. Then - // we pass the token to the receiver, which will then make a sync call to the - // broker to get a duplicated handle. This will also allow us to avoid leaks - // of the handle if the receiver dies, since the broker can notice that. - DCHECK_GT(num_platform_handles, 0u); - embedder::ScopedPlatformHandleVectorPtr rv( - new embedder::PlatformHandleVector()); - - const char* serialization_data = - static_cast(platform_handle_table); - for (size_t i = 0; i < num_platform_handles; i++) { - DWORD pid = *reinterpret_cast(serialization_data); - serialization_data += sizeof(DWORD); - HANDLE source_handle = *reinterpret_cast(serialization_data); - serialization_data += sizeof(HANDLE); - base::Process sender = - base::Process::OpenWithAccess(pid, PROCESS_DUP_HANDLE); - DCHECK(sender.IsValid()); - HANDLE target_handle = NULL; - BOOL dup_result = - DuplicateHandle(sender.Handle(), source_handle, - base::GetCurrentProcessHandle(), &target_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); - DCHECK(dup_result); - rv->push_back(embedder::PlatformHandle(target_handle)); - } - return rv.Pass(); -} - -RawChannel::IOResult RawChannelWin::WriteNoLock( - size_t* platform_handles_written, - size_t* bytes_written) { - write_lock().AssertAcquired(); - - DCHECK(io_handler_); - DCHECK(!io_handler_->pending_write_no_lock()); - - size_t num_platform_handles = 0; - if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { - // Since we're not sure which process might ultimately deserialize this - // message, we can't duplicate the handle now. Instead, write the process ID - // and handle now and let the receiver duplicate it. - embedder::PlatformHandle* platform_handles; - void* serialization_data_temp; - write_buffer_no_lock()->GetPlatformHandlesToSend( - &num_platform_handles, &platform_handles, &serialization_data_temp); - char* serialization_data = static_cast(serialization_data_temp); - DCHECK_GT(num_platform_handles, 0u); - DCHECK(platform_handles); - - DWORD current_process_id = base::GetCurrentProcId(); - for (size_t i = 0; i < num_platform_handles; i++) { - *reinterpret_cast(serialization_data) = current_process_id; - serialization_data += sizeof(DWORD); - *reinterpret_cast(serialization_data) = - platform_handles[i].handle; - serialization_data += sizeof(HANDLE); - platform_handles[i] = embedder::PlatformHandle(); - } - } - - std::vector buffers; - write_buffer_no_lock()->GetBuffers(&buffers); - DCHECK(!buffers.empty()); - - // TODO(yzshen): Handle multi-segment writes more efficiently. - DWORD bytes_written_dword = 0; - BOOL result = - WriteFile(io_handler_->handle(), buffers[0].addr, - static_cast(buffers[0].size), &bytes_written_dword, - &io_handler_->write_context_no_lock()->overlapped); - if (!result) { - DWORD error = GetLastError(); - if (error == ERROR_BROKEN_PIPE) - return IO_FAILED_SHUTDOWN; - if (error != ERROR_IO_PENDING) { - LOG(WARNING) << "WriteFile: " << logging::SystemErrorCodeToString(error); - return IO_FAILED_UNKNOWN; - } - } - - if (result && skip_completion_port_on_success_) { - *platform_handles_written = num_platform_handles; - *bytes_written = bytes_written_dword; - return IO_SUCCEEDED; - } - - // If the write is pending or the write has succeeded but we don't skip - // completion port on success, instruct |io_handler_| to wait for the - // completion packet. - // - // TODO(yzshen): it seems there isn't document saying that all error cases - // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion - // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| - // will crash so we will learn about it. - - io_handler_->OnPendingWriteStartedNoLock(num_platform_handles); - return IO_PENDING; -} - -RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() { - write_lock().AssertAcquired(); - - DCHECK(io_handler_); - DCHECK(!io_handler_->pending_write_no_lock()); - - size_t platform_handles_written = 0; - size_t bytes_written = 0; - IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written); - if (io_result == IO_SUCCEEDED) { - DCHECK(skip_completion_port_on_success_); - - // We have finished writing successfully. Queue a notification manually. - io_handler_->OnPendingWriteStartedNoLock(platform_handles_written); - // |io_handler_| won't go away before that task is run, so it is safe to use - // |base::Unretained()|. - message_loop_for_io()->PostTask( - FROM_HERE, - base::Bind(&RawChannelIOHandler::OnIOCompleted, - base::Unretained(io_handler_), - base::Unretained(io_handler_->write_context_no_lock()), - static_cast(bytes_written), ERROR_SUCCESS)); - return IO_PENDING; - } - - return io_result; -} - -void RawChannelWin::OnInit() { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - - DCHECK(handle_.is_valid()); - if (skip_completion_port_on_success_) { - // I don't know how this can fail (unless |handle_| is bad, in which case - // it's a bug in our code). - CHECK(g_vista_or_higher_functions.Get().SetFileCompletionNotificationModes( - handle_.get().handle, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)); - } - - DCHECK(!io_handler_); - io_handler_ = new RawChannelIOHandler(this, handle_.Pass()); -} - -void RawChannelWin::OnShutdownNoLock(scoped_ptr read_buffer, - scoped_ptr write_buffer) { - DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); - DCHECK(io_handler_); - - write_lock().AssertAcquired(); - - if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) { - // |io_handler_| will be alive until pending read/write (if any) completes. - // Call |CancelIoEx()| or |CancelIo()| so that resources can be freed up as - // soon as possible. - // Note: |CancelIo()| only cancels read/write requests started from this - // thread. - if (g_vista_or_higher_functions.Get().is_vista_or_higher()) { - g_vista_or_higher_functions.Get().CancelIoEx(io_handler_->handle(), - nullptr); - } else { - CancelIo(io_handler_->handle()); - } - } - - io_handler_->DetachFromOwnerNoLock(read_buffer.Pass(), write_buffer.Pass()); - io_handler_ = nullptr; -} - -} // namespace - -// ----------------------------------------------------------------------------- - -// Static factory method declared in raw_channel.h. -// static -scoped_ptr RawChannel::Create( - embedder::ScopedPlatformHandle handle) { - return make_scoped_ptr(new RawChannelWin(handle.Pass())); -} - -} // namespace system -} // namespace mojo diff --git a/mojo/edk/system/remote_consumer_data_pipe_impl.cc b/mojo/edk/system/remote_consumer_data_pipe_impl.cc index 8e2162021fb..ce0c24033df 100644 --- a/mojo/edk/system/remote_consumer_data_pipe_impl.cc +++ b/mojo/edk/system/remote_consumer_data_pipe_impl.cc @@ -7,9 +7,10 @@ #include #include +#include +#include #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/configuration.h" @@ -68,10 +69,14 @@ bool ValidateIncomingMessage(size_t element_num_bytes, RemoteConsumerDataPipeImpl::RemoteConsumerDataPipeImpl( ChannelEndpoint* channel_endpoint, - size_t consumer_num_bytes) + size_t consumer_num_bytes, + std::unique_ptr buffer, + size_t start_index) : channel_endpoint_(channel_endpoint), - consumer_num_bytes_(consumer_num_bytes) { - // Note: |buffer_| is lazily allocated. + consumer_num_bytes_(consumer_num_bytes), + buffer_(std::move(buffer)), + start_index_(start_index) { + // Note: |buffer_| may be null (in which case it'll be lazily allocated). } RemoteConsumerDataPipeImpl::~RemoteConsumerDataPipeImpl() { @@ -96,7 +101,7 @@ bool RemoteConsumerDataPipeImpl::ProcessMessagesFromIncomingEndpoint( if (messages) { while (!messages->IsEmpty()) { - scoped_ptr message(messages->GetMessage()); + std::unique_ptr message(messages->GetMessage()); if (!ValidateIncomingMessage(element_num_bytes, capacity_num_bytes, *consumer_num_bytes, message.get())) { messages->Clear(); @@ -148,11 +153,11 @@ MojoResult RemoteConsumerDataPipeImpl::ProducerWriteData( while (offset < num_bytes_to_write) { size_t message_num_bytes = std::min(max_message_num_bytes, num_bytes_to_write - offset); - scoped_ptr message(new MessageInTransit( + std::unique_ptr message(new MessageInTransit( MessageInTransit::Type::ENDPOINT_CLIENT, MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, static_cast(message_num_bytes), elements.At(offset))); - if (!channel_endpoint_->EnqueueMessage(message.Pass())) { + if (!channel_endpoint_->EnqueueMessage(std::move(message))) { Disconnect(); break; } @@ -192,6 +197,7 @@ MojoResult RemoteConsumerDataPipeImpl::ProducerBeginWriteData( return MOJO_RESULT_SHOULD_WAIT; EnsureBuffer(); + start_index_ = 0; // We always have the full buffer. buffer.Put(buffer_.get()); buffer_num_bytes.Put(static_cast(max_num_bytes_to_write)); set_producer_two_phase_max_num_bytes_written( @@ -201,12 +207,12 @@ MojoResult RemoteConsumerDataPipeImpl::ProducerBeginWriteData( MojoResult RemoteConsumerDataPipeImpl::ProducerEndWriteData( uint32_t num_bytes_written) { + DCHECK(buffer_); DCHECK_LE(num_bytes_written, producer_two_phase_max_num_bytes_written()); DCHECK_EQ(num_bytes_written % element_num_bytes(), 0u); DCHECK_LE(num_bytes_written, capacity_num_bytes() - consumer_num_bytes_); if (!consumer_open()) { - DCHECK(buffer_); set_producer_two_phase_max_num_bytes_written(0); DestroyBuffer(); return MOJO_RESULT_OK; @@ -227,11 +233,12 @@ MojoResult RemoteConsumerDataPipeImpl::ProducerEndWriteData( while (offset < num_bytes_written) { size_t message_num_bytes = std::min(max_message_num_bytes, num_bytes_written - offset); - scoped_ptr message(new MessageInTransit( - MessageInTransit::Type::ENDPOINT_CLIENT, - MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, - static_cast(message_num_bytes), buffer_.get() + offset)); - if (!channel_endpoint_->EnqueueMessage(message.Pass())) { + std::unique_ptr message( + new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT, + MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA, + static_cast(message_num_bytes), + buffer_.get() + start_index_ + offset)); + if (!channel_endpoint_->EnqueueMessage(std::move(message))) { set_producer_two_phase_max_num_bytes_written(0); Disconnect(); return MOJO_RESULT_OK; @@ -299,7 +306,7 @@ bool RemoteConsumerDataPipeImpl::ProducerEndSerialize( channel_endpoint.swap(channel_endpoint_); channel->SerializeEndpointWithRemotePeer(destination_for_endpoint, nullptr, channel_endpoint); - owner()->SetConsumerClosedNoLock(); + SetConsumerClosed(); *actual_size = sizeof(SerializedDataPipeProducerDispatcher) + channel->GetSerializedEndpointSize(); @@ -373,7 +380,7 @@ bool RemoteConsumerDataPipeImpl::OnReadMessage(unsigned /*port*/, MessageInTransit* message) { // Always take ownership of the message. (This means that we should always // return true.) - scoped_ptr msg(message); + std::unique_ptr msg(message); if (!ValidateIncomingMessage(element_num_bytes(), capacity_num_bytes(), consumer_num_bytes_, msg.get())) { @@ -419,7 +426,7 @@ void RemoteConsumerDataPipeImpl::DestroyBuffer() { void RemoteConsumerDataPipeImpl::Disconnect() { DCHECK(consumer_open()); DCHECK(channel_endpoint_); - owner()->SetConsumerClosedNoLock(); + SetConsumerClosed(); channel_endpoint_->DetachFromClient(); channel_endpoint_ = nullptr; if (!producer_in_two_phase_write()) diff --git a/mojo/edk/system/remote_consumer_data_pipe_impl.h b/mojo/edk/system/remote_consumer_data_pipe_impl.h index dbd1f7b61b2..1bcd989e90d 100644 --- a/mojo/edk/system/remote_consumer_data_pipe_impl.h +++ b/mojo/edk/system/remote_consumer_data_pipe_impl.h @@ -5,12 +5,12 @@ #ifndef MOJO_EDK_SYSTEM_REMOTE_CONSUMER_DATA_PIPE_IMPL_H_ #define MOJO_EDK_SYSTEM_REMOTE_CONSUMER_DATA_PIPE_IMPL_H_ +#include + #include "base/memory/aligned_memory.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/data_pipe_impl.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -19,11 +19,16 @@ namespace system { // |RemoteConsumerDataPipeImpl| is a subclass that "implements" |DataPipe| for // data pipes whose producer is local and whose consumer is remote. See // |DataPipeImpl| for more details. -class MOJO_SYSTEM_IMPL_EXPORT RemoteConsumerDataPipeImpl final - : public DataPipeImpl { +class RemoteConsumerDataPipeImpl final : public DataPipeImpl { public: - RemoteConsumerDataPipeImpl(ChannelEndpoint* channel_endpoint, - size_t consumer_num_bytes); + // |buffer| is only required if |producer_two_phase_max_num_bytes_written()| + // is nonzero (i.e., if we're in the middle of a two-phase write when the + // consumer handle is transferred); |start_index| is ignored if it is zero. + RemoteConsumerDataPipeImpl( + ChannelEndpoint* channel_endpoint, + size_t consumer_num_bytes, + std::unique_ptr buffer, + size_t start_index); ~RemoteConsumerDataPipeImpl() override; // Processes messages that were received and queued by an |IncomingEndpoint|. @@ -97,7 +102,10 @@ class MOJO_SYSTEM_IMPL_EXPORT RemoteConsumerDataPipeImpl final size_t consumer_num_bytes_; // Used for two-phase writes. - scoped_ptr buffer_; + std::unique_ptr buffer_; + // This is nearly always zero, except when the two-phase write started on a + // |LocalDataPipeImpl|. + size_t start_index_; MOJO_DISALLOW_COPY_AND_ASSIGN(RemoteConsumerDataPipeImpl); }; diff --git a/mojo/edk/system/remote_data_pipe_impl_unittest.cc b/mojo/edk/system/remote_data_pipe_impl_unittest.cc index e6a3179511c..bb03b075444 100644 --- a/mojo/edk/system/remote_data_pipe_impl_unittest.cc +++ b/mojo/edk/system/remote_data_pipe_impl_unittest.cc @@ -11,7 +11,6 @@ #include "base/location.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" -#include "base/test/test_io_thread.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/edk/system/channel.h" @@ -24,6 +23,7 @@ #include "mojo/edk/system/raw_channel.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/system/waiter.h" +#include "mojo/edk/test/test_io_thread.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -37,7 +37,7 @@ const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | class RemoteDataPipeImplTest : public testing::Test { public: - RemoteDataPipeImplTest() : io_thread_(base::TestIOThread::kAutoStart) {} + RemoteDataPipeImplTest() : io_thread_(mojo::test::TestIOThread::kAutoStart) {} ~RemoteDataPipeImplTest() override {} void SetUp() override { @@ -111,7 +111,7 @@ class RemoteDataPipeImplTest : public testing::Test { } embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; + mojo::test::TestIOThread io_thread_; scoped_refptr channels_[2]; scoped_refptr message_pipes_[2]; @@ -157,8 +157,6 @@ TEST_F(RemoteDataPipeImplTest, Sanity) { EXPECT_STREQ(kHello, read_buffer); } -// TODO(vtl): This test doesn't have an obvious analogue in -// |LocalDataPipeImplTest|. TEST_F(RemoteDataPipeImplTest, SendConsumerWithClosedProducer) { char read_buffer[100] = {}; uint32_t read_buffer_size = static_cast(sizeof(read_buffer)); @@ -277,6 +275,235 @@ TEST_F(RemoteDataPipeImplTest, SendConsumerWithClosedProducer) { consumer->Close(); } +TEST_F(RemoteDataPipeImplTest, SendConsumerDuringTwoPhaseWrite) { + char read_buffer[100] = {}; + uint32_t read_buffer_size = static_cast(sizeof(read_buffer)); + DispatcherVector read_dispatchers; + uint32_t read_num_dispatchers = 10; // Maximum to get. + Waiter waiter; + HandleSignalsState hss; + uint32_t context = 0; + + scoped_refptr dp(CreateLocal(sizeof(int32_t), 1000)); + // This is the consumer dispatcher we'll send. + scoped_refptr consumer = + DataPipeConsumerDispatcher::Create(); + consumer->Init(dp); + + uint32_t num_bytes = static_cast(10u * sizeof(int32_t)); + void* write_ptr = nullptr; + EXPECT_EQ(MOJO_RESULT_OK, + dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), + MakeUserPointer(&num_bytes), false)); + ASSERT_GE(num_bytes, 1u * sizeof(int32_t)); + + // Write the consumer to MP 0 (port 0). Wait and receive on MP 1 (port 0). + // (Add the waiter first, to avoid any handling the case where it's already + // readable.) + waiter.Init(); + ASSERT_EQ(MOJO_RESULT_OK, + message_pipe(1)->AddAwakable( + 0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + { + DispatcherTransport transport( + test::DispatcherTryStartTransport(consumer.get())); + EXPECT_TRUE(transport.is_valid()); + + std::vector transports; + transports.push_back(transport); + EXPECT_EQ(MOJO_RESULT_OK, message_pipe(0)->WriteMessage( + 0, NullUserPointer(), 0, &transports, + MOJO_WRITE_MESSAGE_FLAG_NONE)); + transport.End(); + + // |consumer| should have been closed. This is |DCHECK()|ed when it is + // destroyed. + EXPECT_TRUE(consumer->HasOneRef()); + consumer = nullptr; + } + EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); + EXPECT_EQ(123u, context); + hss = HandleSignalsState(); + message_pipe(1)->RemoveAwakable(0, &waiter, &hss); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + hss.satisfied_signals); + EXPECT_EQ(kAllSignals, hss.satisfiable_signals); + EXPECT_EQ(MOJO_RESULT_OK, + message_pipe(1)->ReadMessage( + 0, UserPointer(read_buffer), + MakeUserPointer(&read_buffer_size), &read_dispatchers, + &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(0u, static_cast(read_buffer_size)); + EXPECT_EQ(1u, read_dispatchers.size()); + EXPECT_EQ(1u, read_num_dispatchers); + ASSERT_TRUE(read_dispatchers[0]); + EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); + + EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, + read_dispatchers[0]->GetType()); + consumer = + static_cast(read_dispatchers[0].get()); + read_dispatchers.clear(); + + // Now actually write the data, complete the two-phase write, and close the + // producer. + *static_cast(write_ptr) = 123456; + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData( + static_cast(1u * sizeof(int32_t)))); + dp->ProducerClose(); + + // Wait for the consumer to be readable. + waiter.Init(); + hss = HandleSignalsState(); + MojoResult result = + consumer->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, &hss); + if (result == MOJO_RESULT_OK) { + context = 0; + EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); + EXPECT_EQ(456u, context); + consumer->RemoveAwakable(&waiter, &hss); + } else { + ASSERT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); + } + // We don't know if the fact that the producer has been closed is known yet. + EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); + EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); + + // Read one element. + int32_t elements[10] = {-1, -1}; + num_bytes = static_cast(1u * sizeof(elements[0])); + EXPECT_EQ(MOJO_RESULT_OK, consumer->ReadData(UserPointer(elements), + MakeUserPointer(&num_bytes), + MOJO_READ_DATA_FLAG_NONE)); + EXPECT_EQ(1u * sizeof(elements[0]), num_bytes); + EXPECT_EQ(123456, elements[0]); + EXPECT_EQ(-1, elements[1]); + + consumer->Close(); +} + +// Like |SendConsumerDuringTwoPhaseWrite|, but transfers the consumer during the +// second two-phase write (to try to test that the offset in circular buffer is +// properly preserved). +TEST_F(RemoteDataPipeImplTest, SendConsumerDuringSecondTwoPhaseWrite) { + char read_buffer[100] = {}; + uint32_t read_buffer_size = static_cast(sizeof(read_buffer)); + DispatcherVector read_dispatchers; + uint32_t read_num_dispatchers = 10; // Maximum to get. + Waiter waiter; + HandleSignalsState hss; + uint32_t context = 0; + + scoped_refptr dp(CreateLocal(sizeof(int32_t), 1000)); + // This is the consumer dispatcher we'll send. + scoped_refptr consumer = + DataPipeConsumerDispatcher::Create(); + consumer->Init(dp); + + uint32_t num_bytes = static_cast(10u * sizeof(int32_t)); + void* write_ptr = nullptr; + EXPECT_EQ(MOJO_RESULT_OK, + dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), + MakeUserPointer(&num_bytes), false)); + ASSERT_GE(num_bytes, 1u * sizeof(int32_t)); + *static_cast(write_ptr) = 123456; + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData( + static_cast(1u * sizeof(int32_t)))); + + num_bytes = static_cast(10u * sizeof(int32_t)); + write_ptr = nullptr; + EXPECT_EQ(MOJO_RESULT_OK, + dp->ProducerBeginWriteData(MakeUserPointer(&write_ptr), + MakeUserPointer(&num_bytes), false)); + ASSERT_GE(num_bytes, 1u * sizeof(int32_t)); + + // Write the consumer to MP 0 (port 0). Wait and receive on MP 1 (port 0). + // (Add the waiter first, to avoid any handling the case where it's already + // readable.) + waiter.Init(); + ASSERT_EQ(MOJO_RESULT_OK, + message_pipe(1)->AddAwakable( + 0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + { + DispatcherTransport transport( + test::DispatcherTryStartTransport(consumer.get())); + EXPECT_TRUE(transport.is_valid()); + + std::vector transports; + transports.push_back(transport); + EXPECT_EQ(MOJO_RESULT_OK, message_pipe(0)->WriteMessage( + 0, NullUserPointer(), 0, &transports, + MOJO_WRITE_MESSAGE_FLAG_NONE)); + transport.End(); + + // |consumer| should have been closed. This is |DCHECK()|ed when it is + // destroyed. + EXPECT_TRUE(consumer->HasOneRef()); + consumer = nullptr; + } + EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); + EXPECT_EQ(123u, context); + hss = HandleSignalsState(); + message_pipe(1)->RemoveAwakable(0, &waiter, &hss); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + hss.satisfied_signals); + EXPECT_EQ(kAllSignals, hss.satisfiable_signals); + EXPECT_EQ(MOJO_RESULT_OK, + message_pipe(1)->ReadMessage( + 0, UserPointer(read_buffer), + MakeUserPointer(&read_buffer_size), &read_dispatchers, + &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(0u, static_cast(read_buffer_size)); + EXPECT_EQ(1u, read_dispatchers.size()); + EXPECT_EQ(1u, read_num_dispatchers); + ASSERT_TRUE(read_dispatchers[0]); + EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); + + EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, + read_dispatchers[0]->GetType()); + consumer = + static_cast(read_dispatchers[0].get()); + read_dispatchers.clear(); + + // Now actually write the data, complete the two-phase write, and close the + // producer. + *static_cast(write_ptr) = 789012; + EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData( + static_cast(1u * sizeof(int32_t)))); + dp->ProducerClose(); + + // Wait for the consumer to know that the producer is closed. + waiter.Init(); + hss = HandleSignalsState(); + MojoResult result = + consumer->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 456, &hss); + if (result == MOJO_RESULT_OK) { + context = 0; + EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context)); + EXPECT_EQ(456u, context); + consumer->RemoveAwakable(&waiter, &hss); + } else { + ASSERT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); + } + 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); + + // Read some elements. + int32_t elements[10] = {}; + num_bytes = static_cast(sizeof(elements)); + EXPECT_EQ(MOJO_RESULT_OK, consumer->ReadData(UserPointer(elements), + MakeUserPointer(&num_bytes), + MOJO_READ_DATA_FLAG_NONE)); + EXPECT_EQ(2u * sizeof(elements[0]), num_bytes); + EXPECT_EQ(123456, elements[0]); + EXPECT_EQ(789012, elements[1]); + EXPECT_EQ(0, elements[2]); + + consumer->Close(); +} + } // namespace } // namespace system } // namespace mojo diff --git a/mojo/edk/system/remote_message_pipe_unittest.cc b/mojo/edk/system/remote_message_pipe_unittest.cc index b222895469b..530d6c5c902 100644 --- a/mojo/edk/system/remote_message_pipe_unittest.cc +++ b/mojo/edk/system/remote_message_pipe_unittest.cc @@ -6,18 +6,13 @@ #include #include +#include #include #include "base/bind.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/location.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" -#include "base/test/test_io_thread.h" -#include "build/build_config.h" // TODO(vtl): Remove this. #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/platform_shared_buffer.h" #include "mojo/edk/embedder/scoped_platform_handle.h" @@ -33,7 +28,10 @@ #include "mojo/edk/system/shared_buffer_dispatcher.h" #include "mojo/edk/system/test_utils.h" #include "mojo/edk/system/waiter.h" +#include "mojo/edk/test/scoped_test_dir.h" +#include "mojo/edk/test/test_io_thread.h" #include "mojo/edk/test/test_utils.h" +#include "mojo/edk/util/scoped_file.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -47,7 +45,7 @@ const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | class RemoteMessagePipeTest : public testing::Test { public: - RemoteMessagePipeTest() : io_thread_(base::TestIOThread::kAutoStart) {} + RemoteMessagePipeTest() : io_thread_(mojo::test::TestIOThread::kAutoStart) {} ~RemoteMessagePipeTest() override {} void SetUp() override { @@ -93,7 +91,7 @@ class RemoteMessagePipeTest : public testing::Test { } embedder::PlatformSupport* platform_support() { return &platform_support_; } - base::TestIOThread* io_thread() { return &io_thread_; } + mojo::test::TestIOThread* io_thread() { return &io_thread_; } // Warning: It's up to the caller to ensure that the returned channel // is/remains valid. Channel* channels(size_t i) { return channels_[i].get(); } @@ -160,7 +158,7 @@ class RemoteMessagePipeTest : public testing::Test { } embedder::SimplePlatformSupport platform_support_; - base::TestIOThread io_thread_; + mojo::test::TestIOThread io_thread_; embedder::ScopedPlatformHandle platform_handles_[2]; scoped_refptr channels_[2]; @@ -338,7 +336,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) { &max_platform_handle_count); EXPECT_GT(max_endpoint_info_size, 0u); ASSERT_EQ(0u, max_platform_handle_count); - scoped_ptr endpoint_info(new char[max_endpoint_info_size]); + std::unique_ptr endpoint_info(new char[max_endpoint_info_size]); size_t endpoint_info_size; mp2->EndSerialize(1, channels(0), endpoint_info.get(), &endpoint_info_size, nullptr); @@ -363,7 +361,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) { EXPECT_EQ(kAllSignals, hss.satisfiable_signals); EXPECT_EQ(endpoint_info_size, channels(1)->GetSerializedEndpointSize()); - scoped_ptr received_endpoint_info(new char[endpoint_info_size]); + std::unique_ptr received_endpoint_info(new char[endpoint_info_size]); buffer_size = static_cast(endpoint_info_size); EXPECT_EQ(MOJO_RESULT_OK, mp1->ReadMessage(1, UserPointer(received_endpoint_info.get()), @@ -893,13 +891,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) { EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); } -#if defined(OS_POSIX) -#define MAYBE_SharedBufferPassing SharedBufferPassing -#else -// Not yet implemented (on Windows). -#define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing -#endif -TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { +TEST_F(RemoteMessagePipeTest, SharedBufferPassing) { static const char kHello[] = "hello"; Waiter waiter; HandleSignalsState hss; @@ -920,7 +912,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { ASSERT_TRUE(dispatcher); // Make a mapping. - scoped_ptr mapping0; + std::unique_ptr mapping0; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping0)); ASSERT_TRUE(mapping0); @@ -987,7 +979,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { dispatcher = static_cast(read_dispatchers[0].get()); // Make another mapping. - scoped_ptr mapping1; + std::unique_ptr mapping1; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); ASSERT_TRUE(mapping1); @@ -1017,15 +1009,8 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { EXPECT_EQ('x', static_cast(mapping1->GetBase())[1]); } -#if defined(OS_POSIX) -#define MAYBE_PlatformHandlePassing PlatformHandlePassing -#else -// Not yet implemented (on Windows). -#define MAYBE_PlatformHandlePassing DISABLED_PlatformHandlePassing -#endif -TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); +TEST_F(RemoteMessagePipeTest, PlatformHandlePassing) { + mojo::test::ScopedTestDir test_dir; static const char kHello[] = "hello"; static const char kWorld[] = "world"; @@ -1039,9 +1024,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) { scoped_refptr mp1(MessagePipe::CreateProxyLocal(&ep1)); BootstrapChannelEndpoints(ep0, ep1); - base::FilePath unused; - base::ScopedFILE fp( - base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); + util::ScopedFILE fp(test_dir.CreateFile()); EXPECT_EQ(sizeof(kHello), fwrite(kHello, 1, sizeof(kHello), fp.get())); // We'll try to pass this dispatcher, which will cause a |PlatformHandle| to // be passed. diff --git a/mojo/edk/system/remote_producer_data_pipe_impl.cc b/mojo/edk/system/remote_producer_data_pipe_impl.cc index 833c505bf90..847949f386c 100644 --- a/mojo/edk/system/remote_producer_data_pipe_impl.cc +++ b/mojo/edk/system/remote_producer_data_pipe_impl.cc @@ -7,9 +7,10 @@ #include #include +#include +#include #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/configuration.h" @@ -68,11 +69,11 @@ RemoteProducerDataPipeImpl::RemoteProducerDataPipeImpl( RemoteProducerDataPipeImpl::RemoteProducerDataPipeImpl( ChannelEndpoint* channel_endpoint, - scoped_ptr buffer, + std::unique_ptr buffer, size_t start_index, size_t current_num_bytes) : channel_endpoint_(channel_endpoint), - buffer_(buffer.Pass()), + buffer_(std::move(buffer)), start_index_(start_index), current_num_bytes_(current_num_bytes) { DCHECK(buffer_ || !current_num_bytes); @@ -82,21 +83,21 @@ RemoteProducerDataPipeImpl::RemoteProducerDataPipeImpl( bool RemoteProducerDataPipeImpl::ProcessMessagesFromIncomingEndpoint( const MojoCreateDataPipeOptions& validated_options, MessageInTransitQueue* messages, - scoped_ptr* buffer, + std::unique_ptr* buffer, size_t* buffer_num_bytes) { DCHECK(!*buffer); // Not wrong, but unlikely. const size_t element_num_bytes = validated_options.element_num_bytes; const size_t capacity_num_bytes = validated_options.capacity_num_bytes; - scoped_ptr new_buffer(static_cast( + std::unique_ptr new_buffer(static_cast( base::AlignedAlloc(capacity_num_bytes, GetConfiguration().data_pipe_buffer_alignment_bytes))); size_t current_num_bytes = 0; if (messages) { while (!messages->IsEmpty()) { - scoped_ptr message(messages->GetMessage()); + std::unique_ptr message(messages->GetMessage()); if (!ValidateIncomingMessage(element_num_bytes, capacity_num_bytes, current_num_bytes, message.get())) { messages->Clear(); @@ -109,7 +110,7 @@ bool RemoteProducerDataPipeImpl::ProcessMessagesFromIncomingEndpoint( } } - *buffer = new_buffer.Pass(); + *buffer = std::move(new_buffer); *buffer_num_bytes = current_num_bytes; return true; } @@ -339,7 +340,7 @@ bool RemoteProducerDataPipeImpl::ConsumerEndSerialize( channel_endpoint.swap(channel_endpoint_); channel->SerializeEndpointWithRemotePeer(destination_for_endpoint, &message_queue, channel_endpoint); - owner()->SetProducerClosedNoLock(); + SetProducerClosed(); *actual_size = sizeof(SerializedDataPipeConsumerDispatcher) + channel->GetSerializedEndpointSize(); @@ -360,7 +361,7 @@ bool RemoteProducerDataPipeImpl::OnReadMessage(unsigned /*port*/, // Otherwise, we take ownership of the message. (This means that we should // always return true below.) - scoped_ptr msg(message); + std::unique_ptr msg(message); if (!ValidateIncomingMessage(element_num_bytes(), capacity_num_bytes(), current_num_bytes_, msg.get())) { @@ -449,18 +450,18 @@ void RemoteProducerDataPipeImpl::MarkDataAsConsumed(size_t num_bytes) { RemoteDataPipeAck ack_data = {}; ack_data.num_bytes_consumed = static_cast(num_bytes); - scoped_ptr message(new MessageInTransit( + std::unique_ptr message(new MessageInTransit( MessageInTransit::Type::ENDPOINT_CLIENT, MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA_PIPE_ACK, static_cast(sizeof(ack_data)), &ack_data)); - if (!channel_endpoint_->EnqueueMessage(message.Pass())) + if (!channel_endpoint_->EnqueueMessage(std::move(message))) Disconnect(); } void RemoteProducerDataPipeImpl::Disconnect() { DCHECK(producer_open()); DCHECK(channel_endpoint_); - owner()->SetProducerClosedNoLock(); + SetProducerClosed(); channel_endpoint_->DetachFromClient(); channel_endpoint_ = nullptr; // If the consumer is still open and we still have data, we have to keep the diff --git a/mojo/edk/system/remote_producer_data_pipe_impl.h b/mojo/edk/system/remote_producer_data_pipe_impl.h index 49a1a343999..617cf9d5b15 100644 --- a/mojo/edk/system/remote_producer_data_pipe_impl.h +++ b/mojo/edk/system/remote_producer_data_pipe_impl.h @@ -5,12 +5,12 @@ #ifndef MOJO_EDK_SYSTEM_REMOTE_PRODUCER_DATA_PIPE_IMPL_H_ #define MOJO_EDK_SYSTEM_REMOTE_PRODUCER_DATA_PIPE_IMPL_H_ +#include + #include "base/memory/aligned_memory.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/data_pipe_impl.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -21,14 +21,14 @@ class MessageInTransitQueue; // |RemoteProducerDataPipeImpl| is a subclass that "implements" |DataPipe| for // data pipes whose producer is remote and whose consumer is local. See // |DataPipeImpl| for more details. -class MOJO_SYSTEM_IMPL_EXPORT RemoteProducerDataPipeImpl final - : public DataPipeImpl { +class RemoteProducerDataPipeImpl final : public DataPipeImpl { public: explicit RemoteProducerDataPipeImpl(ChannelEndpoint* channel_endpoint); - RemoteProducerDataPipeImpl(ChannelEndpoint* channel_endpoint, - scoped_ptr buffer, - size_t start_index, - size_t current_num_bytes); + RemoteProducerDataPipeImpl( + ChannelEndpoint* channel_endpoint, + std::unique_ptr buffer, + size_t start_index, + size_t current_num_bytes); ~RemoteProducerDataPipeImpl() override; // Processes messages that were received and queued by an |IncomingEndpoint|. @@ -38,7 +38,7 @@ class MOJO_SYSTEM_IMPL_EXPORT RemoteProducerDataPipeImpl final static bool ProcessMessagesFromIncomingEndpoint( const MojoCreateDataPipeOptions& validated_options, MessageInTransitQueue* messages, - scoped_ptr* buffer, + std::unique_ptr* buffer, size_t* buffer_num_bytes); private: @@ -107,7 +107,7 @@ class MOJO_SYSTEM_IMPL_EXPORT RemoteProducerDataPipeImpl final // Should be valid if and only if |producer_open()| returns true. scoped_refptr channel_endpoint_; - scoped_ptr buffer_; + std::unique_ptr buffer_; // Circular buffer. size_t start_index_; size_t current_num_bytes_; diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc index caf8e0b64bf..d049626329c 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.cc +++ b/mojo/edk/system/shared_buffer_dispatcher.cc @@ -7,7 +7,6 @@ #include #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/embedder/platform_support.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/configuration.h" @@ -208,7 +207,7 @@ MojoResult SharedBufferDispatcher::MapBufferImplNoLock( uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr* mapping) { + std::unique_ptr* mapping) { mutex().AssertHeld(); DCHECK(shared_buffer_); diff --git a/mojo/edk/system/shared_buffer_dispatcher.h b/mojo/edk/system/shared_buffer_dispatcher.h index 1222e030c18..9032fa01663 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.h +++ b/mojo/edk/system/shared_buffer_dispatcher.h @@ -8,7 +8,6 @@ #include "mojo/edk/embedder/platform_shared_buffer.h" #include "mojo/edk/system/memory.h" #include "mojo/edk/system/simple_dispatcher.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -22,8 +21,7 @@ namespace system { // TODO(vtl): We derive from SimpleDispatcher, even though we don't currently // have anything that's waitable. I want to add a "transferrable" wait flag // (which would entail overriding |GetHandleSignalsStateImplNoLock()|, etc.). -class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final - : public SimpleDispatcher { +class SharedBufferDispatcher final : public SimpleDispatcher { public: // The default options to use for |MojoCreateSharedBuffer()|. (Real uses // should obtain this via |ValidateCreateOptions()| with a null |in_options|; @@ -90,7 +88,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final uint64_t offset, uint64_t num_bytes, MojoMapBufferFlags flags, - scoped_ptr* mapping) override; + std::unique_ptr* mapping) override; void StartSerializeImplNoLock(Channel* channel, size_t* max_size, size_t* max_platform_handles) override diff --git a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc index 35c9d2e41a2..35bc16ad8a4 100644 --- a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc +++ b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc @@ -122,7 +122,7 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType()); // Make a couple of mappings. - scoped_ptr mapping1; + std::unique_ptr mapping1; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); ASSERT_TRUE(mapping1); @@ -131,7 +131,7 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { // Write something. static_cast(mapping1->GetBase())[50] = 'x'; - scoped_ptr mapping2; + std::unique_ptr mapping2; EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); ASSERT_TRUE(mapping2); @@ -155,7 +155,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { 100, &dispatcher1)); // Map and write something. - scoped_ptr mapping; + 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'; @@ -258,7 +258,7 @@ TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) { SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher)); - scoped_ptr mapping; + std::unique_ptr mapping; EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); EXPECT_FALSE(mapping); diff --git a/mojo/edk/system/simple_dispatcher.h b/mojo/edk/system/simple_dispatcher.h index a8284358bf7..8a8e83ec8f1 100644 --- a/mojo/edk/system/simple_dispatcher.h +++ b/mojo/edk/system/simple_dispatcher.h @@ -9,7 +9,6 @@ #include "mojo/edk/system/awakable_list.h" #include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -19,7 +18,7 @@ namespace system { // correspondence between handles and dispatchers (see the explanatory comment // in core.cc). This class implements the standard waiter-signalling mechanism // in that case. -class MOJO_SYSTEM_IMPL_EXPORT SimpleDispatcher : public Dispatcher { +class SimpleDispatcher : public Dispatcher { protected: SimpleDispatcher(); ~SimpleDispatcher() override; diff --git a/mojo/edk/system/simple_dispatcher_unittest.cc b/mojo/edk/system/simple_dispatcher_unittest.cc index 9e1bd7bb423..3c918578dea 100644 --- a/mojo/edk/system/simple_dispatcher_unittest.cc +++ b/mojo/edk/system/simple_dispatcher_unittest.cc @@ -82,13 +82,7 @@ class MockSimpleDispatcher final : public SimpleDispatcher { MOJO_DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher); }; -#if defined(OS_WIN) -// http://crbug.com/396404 -#define MAYBE_Basic DISABLED_Basic -#else -#define MAYBE_Basic Basic -#endif -TEST(SimpleDispatcherTest, MAYBE_Basic) { +TEST(SimpleDispatcherTest, Basic) { test::Stopwatch stopwatch; scoped_refptr d(new MockSimpleDispatcher()); @@ -321,13 +315,7 @@ TEST(SimpleDispatcherTest, BasicClosed) { // Don't need to remove waiters from closed dispatchers. } -#if defined(OS_WIN) -// http://crbug.com/396393 -#define MAYBE_BasicThreaded DISABLED_BasicThreaded -#else -#define MAYBE_BasicThreaded BasicThreaded -#endif -TEST(SimpleDispatcherTest, MAYBE_BasicThreaded) { +TEST(SimpleDispatcherTest, BasicThreaded) { test::Stopwatch stopwatch; bool did_wait; MojoResult result; @@ -448,13 +436,7 @@ TEST(SimpleDispatcherTest, MAYBE_BasicThreaded) { hss.satisfiable_signals); } -#if defined(OS_WIN) -// http://crbug.com/387124 -#define MAYBE_MultipleWaiters DISABLED_MultipleWaiters -#else -#define MAYBE_MultipleWaiters MultipleWaiters -#endif -TEST(SimpleDispatcherTest, MAYBE_MultipleWaiters) { +TEST(SimpleDispatcherTest, MultipleWaiters) { static const uint32_t kNumWaiters = 20; bool did_wait[kNumWaiters]; diff --git a/mojo/edk/system/slave_connection_manager.cc b/mojo/edk/system/slave_connection_manager.cc index 1d9d590008c..58b164d1fe1 100644 --- a/mojo/edk/system/slave_connection_manager.cc +++ b/mojo/edk/system/slave_connection_manager.cc @@ -11,6 +11,7 @@ #include "base/message_loop/message_loop.h" #include "mojo/edk/system/connection_manager_messages.h" #include "mojo/edk/system/message_in_transit.h" +#include "mojo/edk/util/make_unique.h" namespace mojo { namespace system { @@ -160,10 +161,10 @@ void SlaveConnectionManager::AllowConnectOnPrivateThread( DVLOG(1) << "Sending AllowConnect: connection ID " << connection_id.ToString(); - if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( + if (!raw_channel_->WriteMessage(util::MakeUnique( MessageInTransit::Type::CONNECTION_MANAGER, MessageInTransit::Subtype::CONNECTION_MANAGER_ALLOW_CONNECT, - sizeof(connection_id), &connection_id)))) { + sizeof(connection_id), &connection_id))) { // Don't tear things down; possibly we'll still read some messages. *result = Result::FAILURE; event_.Signal(); @@ -185,10 +186,10 @@ void SlaveConnectionManager::CancelConnectOnPrivateThread( DVLOG(1) << "Sending CancelConnect: connection ID " << connection_id.ToString(); - if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( + if (!raw_channel_->WriteMessage(util::MakeUnique( MessageInTransit::Type::CONNECTION_MANAGER, MessageInTransit::Subtype::CONNECTION_MANAGER_CANCEL_CONNECT, - sizeof(connection_id), &connection_id)))) { + sizeof(connection_id), &connection_id))) { // Don't tear things down; possibly we'll still read some messages. *result = Result::FAILURE; event_.Signal(); @@ -212,10 +213,10 @@ void SlaveConnectionManager::ConnectOnPrivateThread( DCHECK_EQ(awaiting_ack_type_, NOT_AWAITING_ACK); DVLOG(1) << "Sending Connect: connection ID " << connection_id.ToString(); - if (!raw_channel_->WriteMessage(make_scoped_ptr(new MessageInTransit( + if (!raw_channel_->WriteMessage(util::MakeUnique( MessageInTransit::Type::CONNECTION_MANAGER, MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT, - sizeof(connection_id), &connection_id)))) { + sizeof(connection_id), &connection_id))) { // Don't tear things down; possibly we'll still read some messages. *result = Result::FAILURE; platform_handle->reset(); diff --git a/mojo/edk/system/slave_connection_manager.h b/mojo/edk/system/slave_connection_manager.h index 664c8dd80f6..4edf1355350 100644 --- a/mojo/edk/system/slave_connection_manager.h +++ b/mojo/edk/system/slave_connection_manager.h @@ -5,8 +5,9 @@ #ifndef MOJO_EDK_SYSTEM_SLAVE_CONNECTION_MANAGER_H_ #define MOJO_EDK_SYSTEM_SLAVE_CONNECTION_MANAGER_H_ +#include + #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "mojo/edk/embedder/scoped_platform_handle.h" @@ -14,7 +15,6 @@ #include "mojo/edk/system/connection_manager.h" #include "mojo/edk/system/mutex.h" #include "mojo/edk/system/raw_channel.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace base { @@ -35,9 +35,8 @@ namespace system { // its internal, private thread), with condition that |Init()| be called before // anything else and |Shutdown()| be called before destruction (and no other // public methods may be called during/after |Shutdown()|). -class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager final - : public ConnectionManager, - public RawChannel::Delegate { +class SlaveConnectionManager final : public ConnectionManager, + public RawChannel::Delegate { public: // Note: None of the public methods may be called from |private_thread_|. @@ -106,7 +105,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager final base::Thread private_thread_; // Only accessed on |private_thread_|: - scoped_ptr raw_channel_; + std::unique_ptr raw_channel_; enum AwaitingAckType { NOT_AWAITING_ACK, AWAITING_ACCEPT_CONNECT_ACK, diff --git a/mojo/edk/system/system_impl_export.h b/mojo/edk/system/system_impl_export.h deleted file mode 100644 index 5bbf0057b0d..00000000000 --- 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_channel_endpoint_client.cc b/mojo/edk/system/test_channel_endpoint_client.cc index b3e69b11c8d..3b88be80a99 100644 --- a/mojo/edk/system/test_channel_endpoint_client.cc +++ b/mojo/edk/system/test_channel_endpoint_client.cc @@ -34,7 +34,7 @@ size_t TestChannelEndpointClient::NumMessages() const { return messages_.Size(); } -scoped_ptr TestChannelEndpointClient::PopMessage() { +std::unique_ptr TestChannelEndpointClient::PopMessage() { MutexLocker locker(&mutex_); if (messages_.IsEmpty()) return nullptr; @@ -52,7 +52,7 @@ bool TestChannelEndpointClient::OnReadMessage(unsigned port, EXPECT_EQ(port_, port); EXPECT_TRUE(endpoint_); - messages_.AddMessage(make_scoped_ptr(message)); + messages_.AddMessage(std::unique_ptr(message)); if (read_event_) read_event_->Signal(); diff --git a/mojo/edk/system/test_channel_endpoint_client.h b/mojo/edk/system/test_channel_endpoint_client.h index bb812f01956..831fbc7167b 100644 --- a/mojo/edk/system/test_channel_endpoint_client.h +++ b/mojo/edk/system/test_channel_endpoint_client.h @@ -5,8 +5,9 @@ #ifndef MOJO_EDK_SYSTEM_TEST_CHANNEL_ENDPOINT_CLIENT_H_ #define MOJO_EDK_SYSTEM_TEST_CHANNEL_ENDPOINT_CLIENT_H_ +#include + #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/channel_endpoint_client.h" #include "mojo/edk/system/message_in_transit_queue.h" @@ -36,7 +37,7 @@ class TestChannelEndpointClient final : public ChannelEndpointClient { // Gets/removes a message that was received (|NumMessages()| must be // non-zero), in FIFO order. - scoped_ptr PopMessage(); + std::unique_ptr PopMessage(); // Sets an event to signal when we receive a message. (|read_event| must live // until this object is destroyed or the read event is reset to null.) diff --git a/mojo/edk/system/test_utils.cc b/mojo/edk/system/test_utils.cc index 823bcf4ea3d..e25adc9a067 100644 --- a/mojo/edk/system/test_utils.cc +++ b/mojo/edk/system/test_utils.cc @@ -23,15 +23,11 @@ MojoDeadline DeadlineFromMilliseconds(unsigned milliseconds) { } 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) +// etc.). Based on this, set it to (usually be) 30 ms on Android and 20 ms +// elsewhere. (We'd like this to be as small as possible, without making things +// flaky) +#if defined(OS_ANDROID) return (TinyDeadline() * 3) / 10; #else return (TinyDeadline() * 2) / 10; @@ -79,11 +75,11 @@ Stopwatch::~Stopwatch() { } void Stopwatch::Start() { - start_time_ = base::TimeTicks::Now(); + start_time_ = platform_support_.GetTimeTicksNow(); } MojoDeadline Stopwatch::Elapsed() { - int64_t result = (base::TimeTicks::Now() - start_time_).InMicroseconds(); + int64_t result = platform_support_.GetTimeTicksNow() - start_time_; // |DCHECK_GE|, not |CHECK_GE|, since this may be performance-important. DCHECK_GE(result, 0); return static_cast(result); diff --git a/mojo/edk/system/test_utils.h b/mojo/edk/system/test_utils.h index 59f9dd53bbf..8d424cc9e90 100644 --- a/mojo/edk/system/test_utils.h +++ b/mojo/edk/system/test_utils.h @@ -5,7 +5,7 @@ #ifndef MOJO_EDK_SYSTEM_TEST_UTILS_H_ #define MOJO_EDK_SYSTEM_TEST_UTILS_H_ -#include "base/time/time.h" +#include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -55,7 +55,11 @@ class Stopwatch { MojoDeadline Elapsed(); private: - base::TimeTicks start_time_; + // TODO(vtl): We need this for |GetTimeTicksNow()|. Maybe we should have a + // singleton for tests instead? Or maybe it should be injected? + embedder::SimplePlatformSupport platform_support_; + + MojoTimeTicks start_time_; MOJO_DISALLOW_COPY_AND_ASSIGN(Stopwatch); }; diff --git a/mojo/edk/system/transport_data.cc b/mojo/edk/system/transport_data.cc index 8d9b229b08a..805d24c4e0e 100644 --- a/mojo/edk/system/transport_data.cc +++ b/mojo/edk/system/transport_data.cc @@ -6,6 +6,8 @@ #include +#include + #include "base/logging.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/configuration.h" @@ -60,7 +62,7 @@ struct TransportData::PrivateStructForCompileAsserts { "alignment"); }; -TransportData::TransportData(scoped_ptr dispatchers, +TransportData::TransportData(std::unique_ptr dispatchers, Channel* channel) : buffer_size_() { DCHECK(dispatchers); @@ -194,7 +196,7 @@ TransportData::TransportData(scoped_ptr dispatchers, TransportData::TransportData( embedder::ScopedPlatformHandleVectorPtr platform_handles, size_t serialized_platform_handle_size) - : buffer_size_(), platform_handles_(platform_handles.Pass()) { + : buffer_size_(), platform_handles_(std::move(platform_handles)) { buffer_size_ = MessageInTransit::RoundUpMessageAlignment( sizeof(Header) + platform_handles_->size() * serialized_platform_handle_size); @@ -306,7 +308,7 @@ void TransportData::GetPlatformHandleTable(const void* transport_data_buffer, } // static -scoped_ptr TransportData::DeserializeDispatchers( +std::unique_ptr TransportData::DeserializeDispatchers( const void* buffer, size_t buffer_size, embedder::ScopedPlatformHandleVectorPtr platform_handles, @@ -317,7 +319,8 @@ scoped_ptr TransportData::DeserializeDispatchers( const Header* header = static_cast(buffer); const size_t num_handles = header->num_handles; - scoped_ptr dispatchers(new DispatcherVector(num_handles)); + std::unique_ptr dispatchers( + new DispatcherVector(num_handles)); const HandleTableEntry* handle_table = reinterpret_cast( @@ -335,7 +338,7 @@ scoped_ptr TransportData::DeserializeDispatchers( channel, handle_table[i].type, source, size, platform_handles.get()); } - return dispatchers.Pass(); + return dispatchers; } } // namespace system diff --git a/mojo/edk/system/transport_data.h b/mojo/edk/system/transport_data.h index 20bb80fe3c3..fb4ba6bdde2 100644 --- a/mojo/edk/system/transport_data.h +++ b/mojo/edk/system/transport_data.h @@ -7,15 +7,13 @@ #include +#include #include #include "base/memory/aligned_memory.h" -#include "base/memory/scoped_ptr.h" -#include "build/build_config.h" #include "mojo/edk/embedder/platform_handle.h" #include "mojo/edk/embedder/platform_handle_vector.h" #include "mojo/edk/system/dispatcher.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -73,7 +71,7 @@ class Channel; // the application the data payload and these handles. // // TODO(vtl): Everything above involving |PlatformHandle|s. -class MOJO_SYSTEM_IMPL_EXPORT TransportData { +class TransportData { public: // The maximum size of a single serialized dispatcher. This must be a multiple // of |kMessageAlignment|. @@ -89,7 +87,8 @@ class MOJO_SYSTEM_IMPL_EXPORT TransportData { // The maximum total number of platform handles that may be attached. static size_t GetMaxPlatformHandles(); - TransportData(scoped_ptr dispatchers, Channel* channel); + TransportData(std::unique_ptr dispatchers, + Channel* channel); // This is used for users of |MessageInTransit|/|TransportData|/|RawChannel| // that want to simply transport data and platform handles, and not @@ -140,7 +139,7 @@ class MOJO_SYSTEM_IMPL_EXPORT TransportData { // Deserializes dispatchers from the given (serialized) transport data buffer // (typically from a |MessageInTransit::View|) and vector of platform handles. // |buffer| should be non-null and |buffer_size| should be nonzero. - static scoped_ptr DeserializeDispatchers( + static std::unique_ptr DeserializeDispatchers( const void* buffer, size_t buffer_size, embedder::ScopedPlatformHandleVectorPtr platform_handles, @@ -174,7 +173,7 @@ class MOJO_SYSTEM_IMPL_EXPORT TransportData { } size_t buffer_size_; - scoped_ptr buffer_; // Never null. + std::unique_ptr buffer_; // Never null. // Any platform-specific handles attached to this message (for inter-process // transport). The vector (if any) owns the handles that it contains (and is diff --git a/mojo/edk/system/unique_identifier.h b/mojo/edk/system/unique_identifier.h index 52ca57d7089..613a56fcb14 100644 --- a/mojo/edk/system/unique_identifier.h +++ b/mojo/edk/system/unique_identifier.h @@ -8,10 +8,10 @@ #include #include +#include #include -#include "base/containers/hash_tables.h" -#include "mojo/edk/system/system_impl_export.h" +#include "base/containers/hash_tables.h" // For |base::HashInts64()|. #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -22,13 +22,13 @@ class UniqueIdentifier; } // namespace system } // namespace mojo -namespace BASE_HASH_NAMESPACE { +namespace std { // Declare this before |UniqueIdentifier|, so that it can be friended. template <> struct hash; -} // BASE_HASH_NAMESPACE +} // namespace std namespace mojo { @@ -42,7 +42,7 @@ namespace system { // |UniqueIdentifier| is a POD class whose value is used to uniquely identify // things. -class MOJO_SYSTEM_IMPL_EXPORT UniqueIdentifier { +class UniqueIdentifier { public: // This generates a new identifier. Uniqueness is "guaranteed" (i.e., // probabilistically) for identifiers. @@ -70,7 +70,7 @@ class MOJO_SYSTEM_IMPL_EXPORT UniqueIdentifier { } private: - friend BASE_HASH_NAMESPACE::hash; + friend std::hash; explicit UniqueIdentifier() {} @@ -87,8 +87,10 @@ static_assert(MOJO_ALIGNOF(UniqueIdentifier) == 1, } // namespace system } // namespace mojo -namespace BASE_HASH_NAMESPACE { +namespace std { +// Specialization of |std::hash<>| for |UniqueIdentifier|s, so they can be used +// in unordered sets/maps. template <> struct hash { size_t operator()(mojo::system::UniqueIdentifier unique_identifier) const { @@ -99,6 +101,6 @@ struct hash { } }; -} // BASE_HASH_NAMESPACE +} // namespace std #endif // MOJO_EDK_SYSTEM_UNIQUE_IDENTIFIER_H_ diff --git a/mojo/edk/system/unique_identifier_unittest.cc b/mojo/edk/system/unique_identifier_unittest.cc index 1914af293c3..cd879b18e9a 100644 --- a/mojo/edk/system/unique_identifier_unittest.cc +++ b/mojo/edk/system/unique_identifier_unittest.cc @@ -6,8 +6,8 @@ #include #include +#include -#include "base/containers/hash_tables.h" #include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -140,8 +140,8 @@ TEST_F(UniqueIdentifierTest, StdSet) { EXPECT_TRUE(s.empty()); } -TEST_F(UniqueIdentifierTest, HashSet) { - base::hash_set s; +TEST_F(UniqueIdentifierTest, UnorderedSet) { + std::unordered_set s; EXPECT_TRUE(s.empty()); UniqueIdentifier id1 = UniqueIdentifier::Generate(platform_support()); diff --git a/mojo/edk/system/waiter.h b/mojo/edk/system/waiter.h index 945acbabd43..d676789f291 100644 --- a/mojo/edk/system/waiter.h +++ b/mojo/edk/system/waiter.h @@ -10,7 +10,6 @@ #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" #include "mojo/edk/system/awakable.h" -#include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" #include "mojo/public/cpp/system/macros.h" @@ -21,10 +20,10 @@ namespace system { // under other locks, in particular, |Dispatcher::lock_|s, so |Waiter| methods // must never call out to other objects (in particular, |Dispatcher|s). This // class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT Waiter final : public Awakable { +class Waiter final : public Awakable { public: Waiter(); - ~Waiter(); + ~Waiter() override; // A |Waiter| can be used multiple times; |Init()| should be called before // each time it's used. diff --git a/mojo/edk/test/BUILD.gn b/mojo/edk/test/BUILD.gn index 834d837ac2a..cbe6e26a8fa 100644 --- a/mojo/edk/test/BUILD.gn +++ b/mojo/edk/test/BUILD.gn @@ -13,9 +13,12 @@ mojo_edk_source_set("test_support") { "multiprocess_test_helper.h", "scoped_ipc_support.cc", "scoped_ipc_support.h", + "scoped_test_dir.cc", + "scoped_test_dir.h", + "test_io_thread.cc", + "test_io_thread.h", "test_utils.h", "test_utils_posix.cc", - "test_utils_win.cc", ] deps = [ @@ -24,7 +27,10 @@ mojo_edk_source_set("test_support") { "//testing/gtest", ] - mojo_edk_deps = [ "mojo/edk/system" ] + mojo_edk_deps = [ + "mojo/edk/system", + "mojo/edk/util", + ] mojo_sdk_public_deps = [ "mojo/public/cpp/system" ] } diff --git a/mojo/edk/test/multiprocess_test_helper.cc b/mojo/edk/test/multiprocess_test_helper.cc index c107a02da2a..81fbdcc1749 100644 --- a/mojo/edk/test/multiprocess_test_helper.cc +++ b/mojo/edk/test/multiprocess_test_helper.cc @@ -6,16 +6,13 @@ #include "base/command_line.h" #include "base/logging.h" -#include "base/process/kill.h" -#include "base/process/process_handle.h" -#include "build/build_config.h" #include "mojo/edk/embedder/platform_channel_pair.h" namespace mojo { namespace test { -MultiprocessTestHelper::MultiprocessTestHelper() { - platform_channel_pair_.reset(new embedder::PlatformChannelPair()); +MultiprocessTestHelper::MultiprocessTestHelper() + : platform_channel_pair_(new embedder::PlatformChannelPair()) { server_platform_handle = platform_channel_pair_->PassServerHandle(); } @@ -54,14 +51,7 @@ void MultiprocessTestHelper::StartChildWithExtraSwitch( } base::LaunchOptions options; -#if defined(OS_POSIX) options.fds_to_remap = &handle_passing_info; -#elif defined(OS_WIN) - options.start_hidden = true; - options.handles_to_inherit = &handle_passing_info; -#else -#error "Not supported yet." -#endif test_child_ = base::SpawnMultiProcessTestChild(test_child_main, command_line, options); diff --git a/mojo/edk/test/multiprocess_test_helper.h b/mojo/edk/test/multiprocess_test_helper.h index fb00510f18b..2d02796b4b0 100644 --- a/mojo/edk/test/multiprocess_test_helper.h +++ b/mojo/edk/test/multiprocess_test_helper.h @@ -5,6 +5,7 @@ #ifndef MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_ #define MOJO_EDK_TEST_MULTIPROCESS_TEST_HELPER_H_ +#include #include #include "base/process/process.h" @@ -61,7 +62,7 @@ class MultiprocessTestHelper { static embedder::ScopedPlatformHandle client_platform_handle; private: - scoped_ptr platform_channel_pair_; + std::unique_ptr platform_channel_pair_; // Valid after |StartChild()| and before |WaitForChildShutdown()|. base::Process test_child_; diff --git a/mojo/edk/test/multiprocess_test_helper_unittest.cc b/mojo/edk/test/multiprocess_test_helper_unittest.cc index 4fe170c3609..2780a69d731 100644 --- a/mojo/edk/test/multiprocess_test_helper_unittest.cc +++ b/mojo/edk/test/multiprocess_test_helper_unittest.cc @@ -4,28 +4,20 @@ #include "mojo/edk/test/multiprocess_test_helper.h" +#include + #include "base/logging.h" #include "build/build_config.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_POSIX) -#include -#endif - namespace mojo { namespace test { namespace { bool IsNonBlocking(const embedder::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.fd, F_GETFL) & O_NONBLOCK; -#endif } bool WriteByte(const embedder::PlatformHandle& handle, char c) { diff --git a/mojo/edk/test/scoped_test_dir.cc b/mojo/edk/test/scoped_test_dir.cc new file mode 100644 index 00000000000..5bd768b352a --- /dev/null +++ b/mojo/edk/test/scoped_test_dir.cc @@ -0,0 +1,27 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/test/scoped_test_dir.h" + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" + +namespace mojo { +namespace test { + +ScopedTestDir::ScopedTestDir() { + CHECK(temp_dir_.CreateUniqueTempDir()); +} + +ScopedTestDir::~ScopedTestDir() {} + +util::ScopedFILE ScopedTestDir::CreateFile() { + base::FilePath unused; + return util::ScopedFILE( + base::CreateAndOpenTemporaryFileInDir(temp_dir_.path(), &unused)); +} + +} // namespace test +} // namespace mojo diff --git a/mojo/edk/test/scoped_test_dir.h b/mojo/edk/test/scoped_test_dir.h new file mode 100644 index 00000000000..4db372ff3e4 --- /dev/null +++ b/mojo/edk/test/scoped_test_dir.h @@ -0,0 +1,33 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_TEST_SCOPED_TEST_DIR_H_ +#define MOJO_EDK_TEST_SCOPED_TEST_DIR_H_ + +#include "base/files/scoped_temp_dir.h" +#include "mojo/edk/util/scoped_file.h" +#include "mojo/public/cpp/system/macros.h" + +namespace mojo { +namespace test { + +// Creates/destroyes a temporary directory for test purposes. (Unlike +// |base::ScopedTempDir|, this automatically creates the temporary directory.) +class ScopedTestDir { + public: + ScopedTestDir(); + ~ScopedTestDir(); + + util::ScopedFILE CreateFile(); + + private: + base::ScopedTempDir temp_dir_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedTestDir); +}; + +} // namespace test +} // namespace mojo + +#endif // MOJO_EDK_TEST_SCOPED_TEST_DIR_H_ diff --git a/mojo/edk/test/test_io_thread.cc b/mojo/edk/test/test_io_thread.cc new file mode 100644 index 00000000000..b5b9042cf66 --- /dev/null +++ b/mojo/edk/test/test_io_thread.cc @@ -0,0 +1,67 @@ +// 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/test_io_thread.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/synchronization/waitable_event.h" + +namespace mojo { +namespace test { + +namespace { + +void PostTaskAndWaitHelper(base::WaitableEvent* event, + const base::Closure& task) { + task.Run(); + event->Signal(); +} + +} // namespace + +TestIOThread::TestIOThread(Mode mode) + : io_thread_("test_io_thread"), io_thread_started_(false) { + switch (mode) { + case kAutoStart: + Start(); + return; + case kManualStart: + return; + } + CHECK(false) << "Invalid mode"; +} + +TestIOThread::~TestIOThread() { + Stop(); +} + +void TestIOThread::Start() { + CHECK(!io_thread_started_); + io_thread_started_ = true; + CHECK(io_thread_.StartWithOptions( + base::Thread::Options(base::MessageLoop::TYPE_IO, 0))); +} + +void TestIOThread::Stop() { + // Note: It's okay to call |Stop()| even if the thread isn't running. + io_thread_.Stop(); + io_thread_started_ = false; +} + +void TestIOThread::PostTask(const tracked_objects::Location& from_here, + const base::Closure& task) { + task_runner()->PostTask(from_here, task); +} + +void TestIOThread::PostTaskAndWait(const tracked_objects::Location& from_here, + const base::Closure& task) { + base::WaitableEvent event(false, false); + task_runner()->PostTask(from_here, + base::Bind(&PostTaskAndWaitHelper, &event, task)); + event.Wait(); +} + +} // namespace test +} // namespace mojo diff --git a/mojo/edk/test/test_io_thread.h b/mojo/edk/test/test_io_thread.h new file mode 100644 index 00000000000..78b0b015f9f --- /dev/null +++ b/mojo/edk/test/test_io_thread.h @@ -0,0 +1,57 @@ +// 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_TEST_IO_THREAD_H_ +#define MOJO_EDK_TEST_TEST_IO_THREAD_H_ + +#include "base/callback_forward.h" +#include "base/memory/ref_counted.h" +#include "base/task_runner.h" +#include "base/threading/thread.h" +#include "mojo/public/cpp/system/macros.h" + +namespace mojo { +namespace test { + +// Class to help create/run threads with I/O |MessageLoop|s in tests. +class TestIOThread { + public: + enum Mode { kAutoStart, kManualStart }; + explicit TestIOThread(Mode mode); + // Stops the I/O thread if necessary. + ~TestIOThread(); + + // |Start()|/|Stop()| should only be called from the main (creation) thread. + // After |Stop()|, |Start()| may be called again to start a new I/O thread. + // |Stop()| may be called even when the I/O thread is not started. + void Start(); + void Stop(); + + // Post |task| to the IO thread. + void PostTask(const tracked_objects::Location& from_here, + const base::Closure& task); + // Posts |task| to the IO-thread with an WaitableEvent associated blocks on + // it until the posted |task| is executed, then returns. + void PostTaskAndWait(const tracked_objects::Location& from_here, + const base::Closure& task); + + base::MessageLoopForIO* message_loop() { + return static_cast(io_thread_.message_loop()); + } + + scoped_refptr task_runner() { + return message_loop()->task_runner(); + } + + private: + base::Thread io_thread_; + bool io_thread_started_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(TestIOThread); +}; + +} // namespace test +} // namespace mojo + +#endif // MOJO_EDK_TEST_TEST_IO_THREAD_H_ diff --git a/mojo/edk/test/test_support_impl.cc b/mojo/edk/test/test_support_impl.cc index 34b32cee543..4bf11bde0ce 100644 --- a/mojo/edk/test/test_support_impl.cc +++ b/mojo/edk/test/test_support_impl.cc @@ -14,9 +14,6 @@ #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 { @@ -24,19 +21,11 @@ namespace test { namespace { base::FilePath ResolveSourceRootRelativePath(const char* relative_path) { + // TODO(vtl): Have someone inject the source root instead. base::FilePath path; if (!PathService::Get(base::DIR_SOURCE_ROOT, &path)) return base::FilePath(); - - std::vector components; - base::SplitString(relative_path, '/', &components); - - for (size_t i = 0; i < components.size(); ++i) { - if (!components[i].empty()) - path = path.AppendASCII(components[i]); - } - - return path; + return path.Append(base::FilePath::FromUTF8Unsafe(relative_path)); } } // namespace @@ -53,7 +42,7 @@ void TestSupportImpl::LogPerfResult(const char* test_name, const char* units) { DCHECK(test_name); if (sub_test_name) { - std::string name = base::StringPrintf("%s/%s", test_name, sub_test_name); + std::string name = std::string(test_name) + "/" + sub_test_name; base::LogPerfResult(name.c_str(), value, units); } else { base::LogPerfResult(test_name, value, units); @@ -75,7 +64,7 @@ char** TestSupportImpl::EnumerateSourceRootRelativeDirectory( // |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()); + rv[i] = strdup(names[i].c_str()); return rv; } diff --git a/mojo/edk/test/test_utils.h b/mojo/edk/test/test_utils.h index 9c21a1a29ed..72f92578b1a 100644 --- a/mojo/edk/test/test_utils.h +++ b/mojo/edk/test/test_utils.h @@ -6,13 +6,10 @@ #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" +#include "mojo/edk/util/scoped_file.h" namespace mojo { namespace test { @@ -41,10 +38,10 @@ bool NonBlockingRead(const embedder::PlatformHandle& handle, size_t* bytes_read); // Gets a (scoped) |PlatformHandle| from the given (scoped) |FILE|. -embedder::ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp); +embedder::ScopedPlatformHandle PlatformHandleFromFILE(util::ScopedFILE fp); // Gets a (scoped) |FILE| from a (scoped) |PlatformHandle|. -base::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h, +util::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h, const char* mode); } // namespace test diff --git a/mojo/edk/test/test_utils_posix.cc b/mojo/edk/test/test_utils_posix.cc index 182aa337edc..70c1bdee27c 100644 --- a/mojo/edk/test/test_utils_posix.cc +++ b/mojo/edk/test/test_utils_posix.cc @@ -5,8 +5,10 @@ #include "mojo/edk/test/test_utils.h" #include +#include #include +#include "base/logging.h" #include "base/posix/eintr_wrapper.h" namespace mojo { @@ -72,17 +74,17 @@ bool NonBlockingRead(const embedder::PlatformHandle& handle, return true; } -embedder::ScopedPlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) { +embedder::ScopedPlatformHandle PlatformHandleFromFILE(util::ScopedFILE fp) { CHECK(fp); int rv = dup(fileno(fp.get())); PCHECK(rv != -1) << "dup"; return embedder::ScopedPlatformHandle(embedder::PlatformHandle(rv)); } -base::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h, +util::ScopedFILE FILEFromPlatformHandle(embedder::ScopedPlatformHandle h, const char* mode) { CHECK(h.is_valid()); - base::ScopedFILE rv(fdopen(h.release().fd, mode)); + util::ScopedFILE rv(fdopen(h.release().fd, mode)); PCHECK(rv) << "fdopen"; return rv.Pass(); } diff --git a/mojo/edk/test/test_utils_win.cc b/mojo/edk/test/test_utils_win.cc deleted file mode 100644 index c74f009989a..00000000000 --- a/mojo/edk/test/test_utils_win.cc +++ /dev/null @@ -1,112 +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 - -namespace mojo { -namespace test { - -bool BlockingWrite(const embedder::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 embedder::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 embedder::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; -} - -embedder::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 embedder::ScopedPlatformHandle(embedder::PlatformHandle(rv)); -} - -base::ScopedFILE FILEFromPlatformHandle(embedder::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.Pass(); -} - -} // namespace test -} // namespace mojo diff --git a/mojo/edk/util/BUILD.gn b/mojo/edk/util/BUILD.gn new file mode 100644 index 00000000000..380255d8a34 --- /dev/null +++ b/mojo/edk/util/BUILD.gn @@ -0,0 +1,20 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../mojo_edk.gni") + +mojo_edk_source_set("util") { + sources = [ + "make_unique.h", + "scoped_file.h", + ] + + defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ] + + mojo_edk_configs = [ "mojo/edk/system:system_config" ] + + deps = [ + "//base", + ] +} diff --git a/mojo/edk/util/make_unique.h b/mojo/edk/util/make_unique.h new file mode 100644 index 00000000000..37df9cd9efa --- /dev/null +++ b/mojo/edk/util/make_unique.h @@ -0,0 +1,57 @@ +// 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. + +// This is almost the source from N3656 ("make_unique (Revision 1)"; +// https://isocpp.org/files/papers/N3656.txt) almost verbatim, so that we have a +// "make_unique" to use until we can use C++14. The following changes have been +// made: +// - It's called |MakeUnique| instead of |make_unique|. +// - It's in the |mojo::util| namespace instead of |std|; this also +// necessitates adding some |std::|s. +// - It's been formatted. + +#ifndef MOJO_EDK_UTIL_MAKE_UNIQUE_H_ +#define MOJO_EDK_UTIL_MAKE_UNIQUE_H_ + +#include +#include +#include +#include + +namespace mojo { +namespace util { + +template +struct _Unique_if { + typedef std::unique_ptr _Single_object; +}; + +template +struct _Unique_if { + typedef std::unique_ptr _Unknown_bound; +}; + +template +struct _Unique_if { + typedef void _Known_bound; +}; + +template +typename _Unique_if::_Single_object MakeUnique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +template +typename _Unique_if::_Unknown_bound MakeUnique(size_t n) { + typedef typename std::remove_extent::type U; + return std::unique_ptr(new U[n]()); +} + +template +typename _Unique_if::_Known_bound MakeUnique(Args&&...) = delete; + +} // namespace util +} // namespace mojo + +#endif // MOJO_EDK_UTIL_MAKE_UNIQUE_H_ diff --git a/mojo/edk/util/scoped_file.h b/mojo/edk/util/scoped_file.h new file mode 100644 index 00000000000..7aeb868f975 --- /dev/null +++ b/mojo/edk/util/scoped_file.h @@ -0,0 +1,32 @@ +// 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_UTIL_SCOPED_FILE_H_ +#define MOJO_EDK_UTIL_SCOPED_FILE_H_ + +#include + +#include "base/memory/scoped_ptr.h" + +namespace mojo { +namespace util { +namespace internal { + +// Functor for |ScopedFILE| (below). +struct ScopedFILECloser { + inline void operator()(FILE* x) const { + if (x) + fclose(x); + } +}; + +} // namespace internal + +// Automatically closes |FILE*|s. +using ScopedFILE = scoped_ptr; + +} // namespace util +} // namespace mojo + +#endif // MOJO_EDK_UTIL_SCOPED_FILE_H_ diff --git a/mojo/services/files/public/interfaces/BUILD.gn b/mojo/services/files/public/interfaces/BUILD.gn index 04d041bcf90..d7451417592 100644 --- a/mojo/services/files/public/interfaces/BUILD.gn +++ b/mojo/services/files/public/interfaces/BUILD.gn @@ -10,6 +10,8 @@ mojom("interfaces") { "directory.mojom", "file.mojom", "files.mojom", + "ioctl.mojom", + "ioctl_terminal.mojom", "types.mojom", ] diff --git a/mojo/services/files/public/interfaces/file.mojom b/mojo/services/files/public/interfaces/file.mojom index 83ca8d3b985..3cb358a2789 100644 --- a/mojo/services/files/public/interfaces/file.mojom +++ b/mojo/services/files/public/interfaces/file.mojom @@ -82,8 +82,8 @@ interface File { AsBuffer() => (Error error, handle? buffer); // Special-file-specific control function, for device "files". |in| and |out| - // are dependent on |request|. - // TODO(vtl): Make a master list of request values somewhere. + // are dependent on |request|. See ioctl.mojom for the master list of request + // values. Ioctl(uint32 request, array? in_values) => (Error error, array? out_values); diff --git a/mojo/services/files/public/interfaces/ioctl.mojom b/mojo/services/files/public/interfaces/ioctl.mojom new file mode 100644 index 00000000000..99f255566fd --- /dev/null +++ b/mojo/services/files/public/interfaces/ioctl.mojom @@ -0,0 +1,17 @@ +// 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. + +// Master list of values for |request| in |mojo.files.File|'s |Ioctl()|. + +[DartPackage="mojo_services"] +module mojo.files; + +// Invalid ioctl request. The response should be error |UNIMPLEMENTED|. +const uint32 kIoctlInvalid = 0; + +// Terminal-related ioctl request (i.e., for terminal/terminal-like "files"). +// Unlike Linux, we have a single top-level request for terminal-related ioctls +// (using |in_values| to specify the request further. See ioctl_terminal.mojom +// for details. +const uint32 kIoctlTerminal = 1; diff --git a/mojo/services/files/public/interfaces/ioctl_terminal.mojom b/mojo/services/files/public/interfaces/ioctl_terminal.mojom new file mode 100644 index 00000000000..1996875add3 --- /dev/null +++ b/mojo/services/files/public/interfaces/ioctl_terminal.mojom @@ -0,0 +1,184 @@ +// 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. + +// Defines constants, etc. to be used with the |kIoctlTerminal| ioctl. +// +// TODO(vtl): Add constants for indices? + +[DartPackage="mojo_services"] +module mojo.files; + +// For: +// Ioctl(kIoctlTerminal, array? in_values) +// => (Error error, array? out_values); +// +// A file that is *not* terminal-like should always respond with error +// |UNIMPLEMENTED| (|out_values| is then undefined). The following applies to +// files that *are* terminal-like. +// +// If |in_values| is null or empty, the response should be |OK| (|out_values| is +// undefined). Thus |Ioctl(kIoctlTerminal, null)| can be used as a test for "is +// a terminal". +// +// Otherwise, |in_values[0]| should be one of "subrequest" values described +// below. (Subrequest values unknown to the implementation should be responded +// to with error |UNIMPLEMENTED|.) +// +// Unless otherwise specified, nothing in |in_values| is required. Unless +// otherwise specified, the presence of extra values beyond those specified (if +// any) should result in error |INVALID_ARGUMENT|. In contrast, extra values in +// |out_values| beyond those specified should be ignored. + +// Invalid subrequest. The response should error |UNIMPLEMENTED|. +const uint32 kIoctlTerminalInvalid = 0; + +// Get terminal ("termios") settings subrequest. On |OK|: +// * |out_values[0]| is "iflag" (input mode flags); +// * |out_values[1]| is "oflag" (output mode flags); +// * |out_values[2]| is "cflag" (control mode flags); +// * |out_values[3]| is "lflag" (local mode flags); +// * |out_values[4]| is "ispeed" (input speed; 0 if unavailable); +// * |out_values[5]| is "ospeed" (output speed; 1 if unavailable); +// * |out_values[6..]| are "cc" (control/special characters -- there may be +// any number of these). +// Constants for the flags, etc. are defined further below. +const uint32 kIoctlTerminalGetSettings = 1; + +// Set terminal ("termios") settings subrequest. |in_values[1..6]| should be +// like |out_values[0..5]| for |kIoctlTerminalGetSettings|, and |in_values[7..]| +// should be like |out_values[6..]| (any missing "cc" values are left +// untouched and unknown/extra "cc" values are ignored). +const uint32 kIoctlTerminalSetSettings = 2; + +// Get terminal "window" size subrequest. |out_values[0..1]| should be the +// number of rows and columns, respectively. This may also result in error +// |UNAVAILABLE| (and no |out_values|), if the size is not available for +// whatever reason. +// TODO(vtl): This is unlike the Linux/POSIX ioctl, I think, which will just use +// a previous/default value. +const uint32 kIoctlTerminalGetWindowSize = 3; + +// Set terminal "window" size subrequest. |in_values[1..2]| should be the +// requested number of rows and and columns, respectively. If the error is |OK| +// or |OUT_OF_RANGE|, |out_values[0..1]| should be the actual set number of rows +// and columns (if |OK| these should be the same as the requested values; on +// other errors, |out_values| is undefined). +const uint32 kIoctlTerminalSetWindowSize = 4; + +// Constants for "termios" fields ---------------------------------------------- + +// Number of base/nonoptional fields: +const uint32 kIoctlTerminalTermiosBaseFieldCount = 6; + +// Indices for the base fields: +const uint32 kIoctlTerminalTermiosIFlagIndex = 0; +const uint32 kIoctlTerminalTermiosOFlagIndex = 1; +const uint32 kIoctlTerminalTermiosCFlagIndex = 2; +const uint32 kIoctlTerminalTermiosLFlagIndex = 3; +const uint32 kIoctlTerminalTermiosISpeedIndex = 4; +const uint32 kIoctlTerminalTermiosOSpeedIndex = 5; + +// Current number of "cc" fields: +const uint32 kIoctlTerminalTermiosCtrlCharCount = 17; + +// "cc" field indices: +// Note: Not all of these may be available. +const uint32 kIoctlTerminalTermiosCtrlCharVINTRIndex = 17; +const uint32 kIoctlTerminalTermiosCtrlCharVQUITIndex = 18; +const uint32 kIoctlTerminalTermiosCtrlCharVERASEIndex = 19; +const uint32 kIoctlTerminalTermiosCtrlCharVKILLIndex = 20; +const uint32 kIoctlTerminalTermiosCtrlCharVEOFIndex = 21; +const uint32 kIoctlTerminalTermiosCtrlCharVTIMEIndex = 22; +const uint32 kIoctlTerminalTermiosCtrlCharVMINIndex = 23; +const uint32 kIoctlTerminalTermiosCtrlCharVSWTCIndex = 24; +const uint32 kIoctlTerminalTermiosCtrlCharVSTARTIndex = 25; +const uint32 kIoctlTerminalTermiosCtrlCharVSTOPIndex = 26; +const uint32 kIoctlTerminalTermiosCtrlCharVSUSPIndex = 27; +const uint32 kIoctlTerminalTermiosCtrlCharVEOLIndex = 28; +const uint32 kIoctlTerminalTermiosCtrlCharVREPRINTIndex = 29; +const uint32 kIoctlTerminalTermiosCtrlCharVDISCARDIndex = 30; +const uint32 kIoctlTerminalTermiosCtrlCharVWERASEIndex = 31; +const uint32 kIoctlTerminalTermiosCtrlCharVLNEXTIndex = 32; +const uint32 kIoctlTerminalTermiosCtrlCharVEOL2Index = 33; + +// "iflag" flag values: +const uint32 kIoctlTerminalTermiosIFlagIGNBRK = 0x0001; +const uint32 kIoctlTerminalTermiosIFlagBRKINT = 0x0002; +const uint32 kIoctlTerminalTermiosIFlagIGNPAR = 0x0004; +const uint32 kIoctlTerminalTermiosIFlagPARMRK = 0x0008; +const uint32 kIoctlTerminalTermiosIFlagINPCK = 0x0010; +const uint32 kIoctlTerminalTermiosIFlagISTRIP = 0x0020; +const uint32 kIoctlTerminalTermiosIFlagINLCR = 0x0040; +const uint32 kIoctlTerminalTermiosIFlagIGNCR = 0x0080; +const uint32 kIoctlTerminalTermiosIFlagICRNL = 0x0100; +const uint32 kIoctlTerminalTermiosIFlagIUCLC = 0x0200; +const uint32 kIoctlTerminalTermiosIFlagIXON = 0x0400; +const uint32 kIoctlTerminalTermiosIFlagIXANY = 0x0800; +const uint32 kIoctlTerminalTermiosIFlagIXOFF = 0x1000; +const uint32 kIoctlTerminalTermiosIFlagIMAXBEL = 0x2000; +const uint32 kIoctlTerminalTermiosIFlagIUTF8 = 0x4000; + +// "oflag" flag values: +const uint32 kIoctlTerminalTermiosOFlagOPOST = 0x0001; +const uint32 kIoctlTerminalTermiosOFlagOLCUC = 0x0002; +const uint32 kIoctlTerminalTermiosOFlagONLCR = 0x0004; +const uint32 kIoctlTerminalTermiosOFlagOCRNL = 0x0008; +const uint32 kIoctlTerminalTermiosOFlagONOCR = 0x0010; +const uint32 kIoctlTerminalTermiosOFlagONLRET = 0x0020; +const uint32 kIoctlTerminalTermiosOFlagOFILL = 0x0040; +const uint32 kIoctlTerminalTermiosOFlagOFDEL = 0x0080; + +const uint32 kIoctlTerminalTermiosOFlagNLDLY = 0x0100; // Mask. +const uint32 kIoctlTerminalTermiosOFlagNL0 = 0x0000; +const uint32 kIoctlTerminalTermiosOFlagNL1 = 0x0100; + +const uint32 kIoctlTerminalTermiosOFlagCRDLY = 0x0600; // Mask. +const uint32 kIoctlTerminalTermiosOFlagCR0 = 0x0000; +const uint32 kIoctlTerminalTermiosOFlagCR1 = 0x0200; +const uint32 kIoctlTerminalTermiosOFlagCR2 = 0x0400; +const uint32 kIoctlTerminalTermiosOFlagCR3 = 0x0600; + +const uint32 kIoctlTerminalTermiosOFlagTABDLY = 0x1800; // Mask. +const uint32 kIoctlTerminalTermiosOFlagTAB0 = 0x0000; +const uint32 kIoctlTerminalTermiosOFlagTAB1 = 0x0800; +const uint32 kIoctlTerminalTermiosOFlagTAB2 = 0x1000; +const uint32 kIoctlTerminalTermiosOFlagTAB3 = 0x1800; + +const uint32 kIoctlTerminalTermiosOFlagBSDLY = 0x2000; // Mask. +const uint32 kIoctlTerminalTermiosOFlagBS0 = 0x0000; +const uint32 kIoctlTerminalTermiosOFlagBS1 = 0x2000; + +const uint32 kIoctlTerminalTermiosOFlagVTDLY = 0x4000; // Mask. +const uint32 kIoctlTerminalTermiosOFlagVT0 = 0x0000; +const uint32 kIoctlTerminalTermiosOFlagVT1 = 0x4000; + +const uint32 kIoctlTerminalTermiosOFlagFFDLY = 0x8000; // Mask. +const uint32 kIoctlTerminalTermiosOFlagFF0 = 0x0000; +const uint32 kIoctlTerminalTermiosOFlagFF1 = 0x8000; + +// "cflag" flag values: +// Note: We don't have "CBAUD" in our "cflag". +const uint32 kIoctlTerminalTermiosCFlagCSIZE = 0x0003; // Mask. +const uint32 kIoctlTerminalTermiosCFlagCS5 = 0x0000; +const uint32 kIoctlTerminalTermiosCFlagCS6 = 0x0001; +const uint32 kIoctlTerminalTermiosCFlagCS7 = 0x0002; +const uint32 kIoctlTerminalTermiosCFlagCS8 = 0x0003; + +const uint32 kIoctlTerminalTermiosCFlagCSTOPB = 0x0004; +const uint32 kIoctlTerminalTermiosCFlagCREAD = 0x0008; +const uint32 kIoctlTerminalTermiosCFlagPARENB = 0x0010; +const uint32 kIoctlTerminalTermiosCFlagPARODD = 0x0020; +const uint32 kIoctlTerminalTermiosCFlagHUPCL = 0x0040; +const uint32 kIoctlTerminalTermiosCFlagCLOCAL = 0x0080; + +// "lflag" flag values: +const uint32 kIoctlTerminalTermiosLFlagISIG = 0x0001; +const uint32 kIoctlTerminalTermiosLFlagICANON = 0x0002; +const uint32 kIoctlTerminalTermiosLFlagXCASE = 0x0004; +const uint32 kIoctlTerminalTermiosLFlagECHO = 0x0008; +const uint32 kIoctlTerminalTermiosLFlagECHOE = 0x0010; +const uint32 kIoctlTerminalTermiosLFlagECHOK = 0x0020; +const uint32 kIoctlTerminalTermiosLFlagECHONL = 0x0040; +const uint32 kIoctlTerminalTermiosLFlagNOFLSH = 0x0080; +const uint32 kIoctlTerminalTermiosLFlagTOSTOP = 0x0100; diff --git a/mojo/services/mojo_services.gni b/mojo/services/mojo_services.gni index 74c09815a6b..eb6d5d74d6c 100644 --- a/mojo/services/mojo_services.gni +++ b/mojo/services/mojo_services.gni @@ -2,6 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +# This list is used to populate the Dart mojo_services package. It must be +# updated to contain the public interfaces under //mojo/services. If you add a +# new directory, X, containing public interfaces, then you must add +# //mojo/services/X/public/interfaces to this list. + mojo_services = [ "//mojo/services/accessibility/public/interfaces", "//mojo/services/asset_bundle/public/interfaces", @@ -13,20 +18,28 @@ mojo_services = [ "//mojo/services/device_info/public/interfaces", "//mojo/services/files/public/interfaces", "//mojo/services/geometry/public/interfaces", + "//mojo/services/gpu/public/interfaces", "//mojo/services/http_server/public/interfaces", + "//mojo/services/icu_data/public/interfaces", "//mojo/services/input_events/public/interfaces", + "//mojo/services/keyboard/public/interfaces", "//mojo/services/location/public/interfaces", "//mojo/services/native_viewport/public/interfaces", "//mojo/services/navigation/public/interfaces", "//mojo/services/network/public/interfaces", - "//mojo/services/notifications/public/interfaces", "//mojo/services/nfc/public/interfaces", + "//mojo/services/notifications/public/interfaces", + "//mojo/services/ozone_drm_gpu/public/interfaces", + "//mojo/services/ozone_drm_host/public/interfaces", + "//mojo/services/prediction/public/interfaces", "//mojo/services/sensors/public/interfaces", "//mojo/services/service_registry/public/interfaces", - "//mojo/services/speech_recognizer/public/interfaces", "//mojo/services/sharing/public/interfaces", + "//mojo/services/speech_recognizer/public/interfaces", "//mojo/services/surfaces/public/interfaces", "//mojo/services/terminal/public/interfaces", + "//mojo/services/tracing/public/interfaces", + "//mojo/services/url_response_disk_cache/public/interfaces", "//mojo/services/vanadium/security/public/interfaces", "//mojo/services/view_manager/public/interfaces", "//mojo/services/window_manager/public/interfaces", diff --git a/mojo/services/native_viewport/public/interfaces/native_viewport.mojom b/mojo/services/native_viewport/public/interfaces/native_viewport.mojom index ab1506e6f92..40036c65eb7 100644 --- a/mojo/services/native_viewport/public/interfaces/native_viewport.mojom +++ b/mojo/services/native_viewport/public/interfaces/native_viewport.mojom @@ -26,6 +26,7 @@ struct SurfaceConfiguration { interface NativeViewport { // TODO(sky): having a create function is awkward. Should there be a factory // to create the NativeViewport that takes the size? + // When the viewport is created it is initially shown. Create(Size size, SurfaceConfiguration? requested_configuration) => (ViewportMetrics metrics); Show(); diff --git a/mojo/services/ozone_drm_gpu/public/interfaces/BUILD.gn b/mojo/services/ozone_drm_gpu/public/interfaces/BUILD.gn new file mode 100644 index 00000000000..f4ad43fe4c1 --- /dev/null +++ b/mojo/services/ozone_drm_gpu/public/interfaces/BUILD.gn @@ -0,0 +1,18 @@ +# 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/module_args/mojo.gni") +import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "ozone_drm_gpu.mojom", + ] + + import_dirs = [ get_path_info("../../../", "abspath") ] + + public_deps = [ + "../../../geometry/public/interfaces", + ] +} diff --git a/mojo/services/ozone_drm_gpu/public/interfaces/ozone_drm_gpu.mojom b/mojo/services/ozone_drm_gpu/public/interfaces/ozone_drm_gpu.mojom new file mode 100644 index 00000000000..ccc6941a043 --- /dev/null +++ b/mojo/services/ozone_drm_gpu/public/interfaces/ozone_drm_gpu.mojom @@ -0,0 +1,54 @@ +// 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. + +module mojo; + +import "geometry/public/interfaces/geometry.mojom"; + +enum DisplayType { + NONE = 0, + UNKNOWN = 1, + INTERNAL = 2, + VGA = 4, + HDMI = 8, + DVI = 16, + DISPLAYPORT = 32, + NETWORK = 64, + LAST = NETWORK +}; + +struct DisplayMode { + Size size; + bool is_interlaced; + float refresh_rate; +}; + +struct DisplaySnapshot { + // The internal display identifier. + int64 display_id; + Point origin; + Size physical_size; + DisplayType type; + bool has_current_mode; + bool has_native_mode; + array modes; + // The mode currently active on this display. + // TODO(cstout): can this be just an index into the modes array? + DisplayMode current_mode; + // The display's native mode. + // TODO(cstout): can this be just an index into the modes array? + DisplayMode native_mode; + // The identifier for the model of the display. + int64 product_id; + string string_representation; +}; + +interface OzoneDrmGpu { + AddGraphicsDevice(string file_path, int32 file_descriptor); + CreateWindow(int64 widget); + WindowBoundsChanged(int64 widget, Rect bounds); + + RefreshNativeDisplays(); + ConfigureNativeDisplay(int64 id, DisplayMode mode, Point originhost); +}; diff --git a/mojo/services/ozone_drm_host/public/interfaces/BUILD.gn b/mojo/services/ozone_drm_host/public/interfaces/BUILD.gn new file mode 100644 index 00000000000..0b7c3da919c --- /dev/null +++ b/mojo/services/ozone_drm_host/public/interfaces/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/module_args/mojo.gni") +import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "ozone_drm_host.mojom", + ] + + import_dirs = [ get_path_info("../../../", "abspath") ] + + public_deps = [ + "../../../ozone_drm_gpu/public/interfaces", + ] +} diff --git a/mojo/services/ozone_drm_host/public/interfaces/ozone_drm_host.mojom b/mojo/services/ozone_drm_host/public/interfaces/ozone_drm_host.mojom new file mode 100644 index 00000000000..261bedf256d --- /dev/null +++ b/mojo/services/ozone_drm_host/public/interfaces/ozone_drm_host.mojom @@ -0,0 +1,13 @@ +// 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. + +module mojo; + +import "geometry/public/interfaces/geometry.mojom"; +import "ozone_drm_gpu/public/interfaces/ozone_drm_gpu.mojom"; + +interface OzoneDrmHost { + UpdateNativeDisplays(array displays); + DisplayConfigured(int64 id, bool result); +}; diff --git a/mojo/services/url_response_disk_cache/public/interfaces/url_response_disk_cache.mojom b/mojo/services/url_response_disk_cache/public/interfaces/url_response_disk_cache.mojom index d6868b4b5cf..a6c7a2227bf 100644 --- a/mojo/services/url_response_disk_cache/public/interfaces/url_response_disk_cache.mojom +++ b/mojo/services/url_response_disk_cache/public/interfaces/url_response_disk_cache.mojom @@ -17,20 +17,37 @@ import "mojo/public/interfaces/network/url_response.mojom"; // with http servers that do not support ETags. interface URLResponseDiskCache { - // Given a URLResponse, returns a pair of paths. |file_path| is a file - // containing the body of the response. |cache_dir_path| is a directory that - // the applicaton can use to store content. This service guarantee that - // |cache_dir_path| will be emptied when |file_path| content changes. For - // example, a content handler that is backed by a VM that compiles files - // could have the VM use this directory to cache the compiled files. - GetFile(mojo.URLResponse response) => + // Given an URL, returns a tuple. If the |url| is not in the cache, all the + // response parameters are null. Otherwise |response| is the cached response + // stripped of the body, |file_path| is a file containing the body of the + // response and |cache_dir_path| is a directory that the applicaton can use + // to store content. This service guarantee that |cache_dir_path| will be + // emptied when |file_path| content changes. For example, a content handler + // that is backed by a VM that compiles files could have the VM use this + // directory to cache the compiled files. + Get(string url) => (mojo.URLResponse? response, + array? file_path, + array? cache_dir_path); + + // Update the cache with the given response. + Update(mojo.URLResponse response); + + // Given a URLResponse, updates the cache and returns a pair of paths. + // |file_path| is a file containing the body of the response. + // |cache_dir_path| is a directory that the applicaton can use to store + // content. This service guarantee that |cache_dir_path| will be emptied + // when |file_path| content changes. For example, a content handler that is + // backed by a VM that compiles files could have the VM use this directory + // to cache the compiled files. + UpdateAndGet(mojo.URLResponse response) => (array? file_path, array? cache_dir_path); - // Given a URLResponse that is expected to have a zipped body, returns a - // pair of paths. |extracted_dir_path| is a directory containing the unzipped - // body of the response. |cache_dir_path| is a directory that the applicaton - // can use to store content. This service guarantee that |cache_dir_path| - // will be emptied when |extracted_dir_path| content changes. - GetExtractedContent(mojo.URLResponse response) => + // Given a URLResponse that is expected to have a zipped body, updates the + // cache and returns a pair of paths. |extracted_dir_path| is a directory + // containing the unzipped body of the response. |cache_dir_path| is a + // directory that the applicaton can use to store content. This service + // guarantee that |cache_dir_path| will be emptied when |extracted_dir_path| + // content changes. + UpdateAndGetExtracted(mojo.URLResponse response) => (array? extracted_dir_path, array? cache_dir_path); }; diff --git a/mojo/services/view_manager/public/cpp/BUILD.gn b/mojo/services/view_manager/public/cpp/BUILD.gn index 36d0feb3d49..a278cceb28d 100644 --- a/mojo/services/view_manager/public/cpp/BUILD.gn +++ b/mojo/services/view_manager/public/cpp/BUILD.gn @@ -44,7 +44,7 @@ mojo_sdk_source_set("cpp") { mojo_sdk_deps = [ "mojo/public/cpp/application", - "mojo/public/cpp/bindings", + "mojo/public/cpp/bindings:bindings", "mojo/public/cpp/system", "mojo/public/interfaces/application", ] diff --git a/sky/packages/sky/lib/src/services/keyboard.dart b/sky/packages/sky/lib/src/services/keyboard.dart index 49d2ebe47b6..d5bcd97014d 100644 --- a/sky/packages/sky/lib/src/services/keyboard.dart +++ b/sky/packages/sky/lib/src/services/keyboard.dart @@ -31,7 +31,7 @@ class Keyboard { KeyboardHandle _currentHandle; - KeyboardHandle show(KeyboardClientStub stub, int keyboardType) { + KeyboardHandle show(KeyboardClientStub stub, KeyboardType keyboardType) { assert(stub != null); if (_currentHandle != null) { if (_currentHandle.stub == stub) @@ -46,7 +46,7 @@ class Keyboard { class KeyboardHandle { - KeyboardHandle._show(Keyboard keyboard, this.stub, int keyboardType) : _keyboard = keyboard { + KeyboardHandle._show(Keyboard keyboard, this.stub, KeyboardType keyboardType) : _keyboard = keyboard { _keyboard.service.show(stub, keyboardType); _attached = true; } diff --git a/sky/packages/sky/lib/src/widgets/input.dart b/sky/packages/sky/lib/src/widgets/input.dart index 69399c37063..67d4581d1a9 100644 --- a/sky/packages/sky/lib/src/widgets/input.dart +++ b/sky/packages/sky/lib/src/widgets/input.dart @@ -10,7 +10,7 @@ import 'package:sky/src/widgets/focus.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/theme.dart'; -export 'package:sky/services.dart' show KeyboardType_TEXT, KeyboardType_NUMBER, KeyboardType_PHONE, KeyboardType_DATETIME; +export 'package:sky/services.dart' show KeyboardType; typedef void StringValueChanged(String value); @@ -25,10 +25,10 @@ class Input extends StatefulComponent { String initialValue: '', this.placeholder, this.onChanged, - this.keyboardType : KeyboardType_TEXT + this.keyboardType : KeyboardType.TEXT }): _value = initialValue, super(key: key); - int keyboardType; + KeyboardType keyboardType; String placeholder; StringValueChanged onChanged; diff --git a/sky/packages/sky/pubspec.yaml b/sky/packages/sky/pubspec.yaml index 0437b63f55b..3ae5e5fbb3f 100644 --- a/sky/packages/sky/pubspec.yaml +++ b/sky/packages/sky/pubspec.yaml @@ -6,8 +6,8 @@ homepage: http://flutter.io dependencies: cassowary: ^0.1.7 material_design_icons: ^0.0.3 - mojo_services: 0.0.23 - mojo: 0.0.23 + mojo_services: '>=0.1.0 <0.2.0' + mojo: '>=0.1.0 <0.2.0' newton: ^0.1.3 sky_engine: ^0.0.25 sky_services: ^0.0.25 diff --git a/sky/shell/shell.cc b/sky/shell/shell.cc index 78e496074c5..c72fd15caac 100644 --- a/sky/shell/shell.cc +++ b/sky/shell/shell.cc @@ -4,6 +4,8 @@ #include "sky/shell/shell.h" +#include + #include "base/bind.h" #include "base/i18n/icu_util.h" #include "base/lazy_instance.h" @@ -52,7 +54,7 @@ base::LazyInstance g_discardable; Shell::Shell(scoped_ptr service_provider_context) : service_provider_context_(service_provider_context.Pass()) { DCHECK(!g_shell); - mojo::embedder::Init(scoped_ptr( + mojo::embedder::Init(std::unique_ptr( new mojo::embedder::SimplePlatformSupport())); base::Thread::Options options; diff --git a/sky/unit/test/widget/input_test.dart b/sky/unit/test/widget/input_test.dart index e0379a916bb..14aa708dace 100644 --- a/sky/unit/test/widget/input_test.dart +++ b/sky/unit/test/widget/input_test.dart @@ -11,7 +11,7 @@ import '../services/mock_services.dart'; class MockKeyboard implements KeyboardService { KeyboardClient client; - void show(KeyboardClientStub client, int type) { + void show(KeyboardClientStub client, KeyboardType type) { this.client = client.impl; }