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; }