Merge pull request #1317 from jamesr/roll_pubspec_and_mojo_sdk

Update to Mojo 4e4d51ce28a8edcb32b9c7f555e38e2ae84a825e, update deps
This commit is contained in:
James Robinson 2015-09-23 17:58:54 -07:00
commit 93fe88f148
208 changed files with 2619 additions and 3750 deletions

2
DEPS
View File

@ -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',

View File

@ -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)

View File

@ -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: () {

View File

@ -28,7 +28,8 @@ bool RegisterJNI(JNIEnv* env) {
}
bool Init() {
mojo::embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>(
// TODO(vtl): Use make_unique when C++14 is available.
mojo::embedder::Init(std::unique_ptr<mojo::embedder::PlatformSupport>(
new mojo::embedder::SimplePlatformSupport()));
return true;
}

View File

@ -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.");
}
}
}

View File

@ -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<String> _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);
}
}
}

View File

@ -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<String, String> 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<String, String> 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<String, String> args}) {
return _beginFunction(functionName, categories, traceEventPhaseAsyncBegin,
args: args);
}
void traceInstant(String name, String categories,
{Map<String, String> args}) {
_sendTraceMessage(name, categories, traceEventInstant, 0, args: args);
}
FunctionTrace _beginFunction(String functionName, String categories,
String phase, {Map<String, String> 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<String, String> 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<String, String> args}) {
FunctionTrace ft = beginFunction(functionName, args: args);
dynamic trace(String functionName, String categories, closure(),
{Map<String, String> 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<String, String> 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);
}
}
}
}

View File

@ -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<tracing::TraceProvider> 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<tracing::TraceProvider> 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<std::string>();
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<void(const scoped_refptr<base::RefCountedString>&,
bool)>());
}
void TraceProviderImpl::SendChunk(
const scoped_refptr<base::RefCountedString>& 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();
}

View File

@ -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<tracing::TraceProvider> 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<tracing::TraceProvider> 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<base::RefCountedString>& events_str,
bool has_more_events);
bool tracing_already_started_;
tracing::TraceRecorderPtr recorder_;
StrongBinding<tracing::TraceProvider> binding_;
void DelayedStop();
// Stop the collection of traces if no external connection asked for them yet.
void StopIfForced();
Binding<tracing::TraceProvider> binding_;
bool tracing_forced_;
tracing::TraceRecorderPtr recorder_;
base::WeakPtrFactory<TraceProviderImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(TraceProviderImpl);
};

View File

@ -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<tracing::TraceProvider> request) {
new TraceProviderImpl(request.Pass());
provider_impl_.Bind(request.Pass());
}
} // namespace mojo

View File

@ -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<tracing::TraceProvider> {
void Create(ApplicationConnection* connection,
InterfaceRequest<tracing::TraceProvider> request) override;
TraceProviderImpl provider_impl_;
DISALLOW_COPY_AND_ASSIGN(TracingImpl);
};

View File

@ -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",
]
}

View File

@ -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<ui::DisplayMode_Params, DisplayModePtr>::Convert(
const DisplayModePtr& in) {
auto out = ui::DisplayMode_Params();
out.size = in->size.To<gfx::Size>();
out.is_interlaced = in->is_interlaced;
out.refresh_rate = in->refresh_rate;
return out;
}
// static
DisplayModePtr TypeConverter<DisplayModePtr, ui::DisplayMode_Params>::Convert(
const ui::DisplayMode_Params& in) {
auto out = DisplayMode::New();
out->size = Size::From<gfx::Size>(in.size);
out->is_interlaced = in.is_interlaced;
out->refresh_rate = in.refresh_rate;
return out.Pass();
}
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NONE) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_NONE),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_UNKNOWN) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_UNKNOWN),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_INTERNAL) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_INTERNAL),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_VGA) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_VGA),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_HDMI) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_HDMI),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_DVI) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_DVI),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_DISPLAYPORT) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_DISPLAYPORT),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NETWORK) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_NETWORK),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_LAST) ==
static_cast<int>(mojo::DisplayType::DISPLAY_TYPE_LAST),
"Enum value mismatch");
// static
ui::DisplaySnapshot_Params
TypeConverter<ui::DisplaySnapshot_Params, DisplaySnapshotPtr>::Convert(
const DisplaySnapshotPtr& in) {
auto out = ui::DisplaySnapshot_Params();
out.display_id = in->display_id;
out.origin = in->origin.To<gfx::Point>();
out.physical_size = in->physical_size.To<gfx::Size>();
out.type = static_cast<ui::DisplayConnectionType>(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<ui::DisplayMode_Params>());
}
out.has_current_mode = in->has_current_mode;
out.current_mode = in->current_mode.To<ui::DisplayMode_Params>();
out.has_native_mode = in->has_native_mode;
out.native_mode = in->native_mode.To<ui::DisplayMode_Params>();
out.product_id = in->product_id;
out.string_representation = in->string_representation;
return out;
}
// static
DisplaySnapshotPtr
TypeConverter<DisplaySnapshotPtr, ui::DisplaySnapshot_Params>::Convert(
const ui::DisplaySnapshot_Params& in) {
auto out = DisplaySnapshot::New();
out->display_id = in.display_id;
out->origin = Point::From<gfx::Point>(in.origin);
out->physical_size = Size::From<gfx::Size>(in.physical_size);
out->type = static_cast<mojo::DisplayType>(in.type);
assert(out->type <= mojo::DisplayType::DISPLAY_TYPE_LAST);
auto modes = Array<DisplayModePtr>::New(in.modes.size());
for (size_t i = 0; i < in.modes.size(); ++i) {
auto mode = DisplayMode::From<ui::DisplayMode_Params>(in.modes[i]);
modes[i] = mode.Pass();
}
out->modes = modes.Pass();
out->has_current_mode = in.has_current_mode;
out->current_mode =
DisplayMode::From<ui::DisplayMode_Params>(in.current_mode);
out->has_native_mode = in.has_native_mode;
out->native_mode = DisplayMode::From<ui::DisplayMode_Params>(in.native_mode);
out->product_id = in.product_id;
out->string_representation = in.string_representation;
return out.Pass();
}
} // namespace mojo

View File

@ -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<ui::DisplayMode_Params, DisplayModePtr> {
static ui::DisplayMode_Params Convert(const DisplayModePtr& in);
};
template <>
struct TypeConverter<DisplayModePtr, ui::DisplayMode_Params> {
static DisplayModePtr Convert(const ui::DisplayMode_Params& in);
};
template <>
struct TypeConverter<ui::DisplaySnapshot_Params, DisplaySnapshotPtr> {
static ui::DisplaySnapshot_Params Convert(const DisplaySnapshotPtr& in);
};
template <>
struct TypeConverter<DisplaySnapshotPtr, ui::DisplaySnapshot_Params> {
static DisplaySnapshotPtr Convert(const ui::DisplaySnapshot_Params& in);
};
} // namespace mojo
#endif // MOJO_CONVERTERS_OZONE_DRM_GPU_OZONE_DRM_GPU_TYPE_CONVERTERS_H_

View File

@ -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",
]

View File

@ -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",
]
}

View File

@ -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<AppTestFunction> _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<String> 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<AppTestFunction> testFunctions) {
var appHandle = new MojoHandle(incomingHandle);
var application =
new _ConnectionToShellApplication.fromHandle(appHandle, testFunctions);
/// [Application]'s [initialize] will be called.
}

View File

@ -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"

View File

@ -1,4 +0,0 @@
name: apptest
version: 0.0.1
dependencies:
test: ^0.12.3+7

View File

@ -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<mojo::embedder::PlatformSupport>(
new mojo::embedder::SimplePlatformSupport()));
InitDartVM();

View File

@ -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")

View File

@ -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

View File

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

View File

@ -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,

View File

@ -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 <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#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<sockaddr_in*>(dest);
*salen = sizeof(*dest4);
memmove(&(dest4->sin_addr), &addr.bytes[0], addr_length);
} else {
dest->ss_family = AF_INET6;
sockaddr_in6* dest6 = reinterpret_cast<sockaddr_in6*>(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<sockaddr*>(&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

View File

@ -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 {

View File

@ -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<sockaddr*>(&sock_addr),
salen,
host,
host_len,
NULL,
0,
NI_NAMEREQD);
int status = getnameinfo(reinterpret_cast<sockaddr*>(&sock_addr), salen, host,
host_len, NULL, 0, NI_NAMEREQD);
*error_code = status;
if (status != 0) {
CHECK(*error_description == NULL);

View File

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

View File

@ -20,9 +20,6 @@ namespace mojo {
namespace dart {
struct IsolateCallbacks {
base::Callback<Dart_Isolate(const char*,const char*,const char*,void*,char**)>
create;
base::Callback<void(void*)> shutdown;
base::Callback<void(Dart_Handle)> exception;
};

View File

@ -13,6 +13,7 @@ dart_pkg("mojo_services") {
]
deps = [
"//mojo/public/dart",
"//mojo/services",
]
}

View File

@ -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

View File

@ -1,7 +1,8 @@
author: Chromium Authors <mojo-dev@googlegroups.com>
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

View File

@ -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",
]
}

View File

@ -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.

View File

@ -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 </path/to/mojom/dir>
```
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
```

View File

@ -1,5 +0,0 @@
mojom
====
mojom.dart files will appear here after running the generate script (see the
top-level documentation for this package).

View File

@ -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<String, String> 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<String> arguments) async {
var options = await parseArguments(arguments);
duplicateDetection = new Map<String, String>();
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);
}
}
}

View File

@ -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<Directory> 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<List<Directory>> 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<GenerateOptions> parseArguments(List<String> 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);
}

View File

@ -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<String> 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");
}
}

View File

@ -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"

View File

@ -1,12 +0,0 @@
author: Chromium Authors <mojo-dev@googlegroups.com>
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

View File

@ -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<float, 16> 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();
});
});
}

View File

@ -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<bool> runOnClosedTest() {
main() async {
testSerializeStructs();
testUnions();
testEnums();
await testCallResponse();
await testAwaitCallResponse();
await runOnClosedTest();

View File

@ -21,11 +21,11 @@ class IntegerAccessorImpl implements sample.IntegerAccessor {
Future<sample.IntegerAccessorGetIntegerResponseParams>
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);

View File

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

View File

@ -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,

View File

@ -8,6 +8,7 @@
#include <string>
#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

View File

@ -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",
]
}

View File

@ -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<PlatformSupport> platform_support) {
void Init(std::unique_ptr<PlatformSupport> 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<ChannelInfo> channel_info(new ChannelInfo(channel_id));
std::unique_ptr<ChannelInfo> channel_info(new ChannelInfo(channel_id));
scoped_refptr<system::MessagePipeDispatcher> dispatcher =
channel_manager->CreateChannel(
channel_id, platform_handle.Pass(),

View File

@ -5,17 +5,16 @@
#ifndef MOJO_EDK_EMBEDDER_EMBEDDER_H_
#define MOJO_EDK_EMBEDDER_EMBEDDER_H_
#include <memory>
#include <string>
#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<PlatformSupport> platform_support);
void Init(std::unique_ptr<PlatformSupport> platform_support);
// Basic functions -------------------------------------------------------------
@ -47,26 +46,24 @@ MOJO_SYSTEM_IMPL_EXPORT void Init(scoped_ptr<PlatformSupport> 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<void(MojoResult)>& callback);
MojoResult AsyncWait(MojoHandle handle,
MojoHandleSignals signals,
const base::Callback<void(MojoResult)>& callback);
// Creates a |MojoHandle| that wraps the given |PlatformHandle| (taking
// ownership of it). This |MojoHandle| can then, e.g., be passed through message
// pipes. Note: This takes ownership (and thus closes) |platform_handle| even on
// failure, which is different from what you'd expect from a Mojo API, but it
// makes for a more convenient embedder API.
MOJO_SYSTEM_IMPL_EXPORT MojoResult
CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle,
MojoHandle* platform_handle_wrapper_handle);
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<base::TaskRunner> delegate_thread_task_runner,
ProcessDelegate* process_delegate,
scoped_refptr<base::TaskRunner> io_thread_task_runner,
ScopedPlatformHandle platform_handle);
void InitIPCSupport(ProcessType process_type,
scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
ProcessDelegate* process_delegate,
scoped_refptr<base::TaskRunner> io_thread_task_runner,
ScopedPlatformHandle platform_handle);
// 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<base::TaskRunner> 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<base::TaskRunner> 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<base::TaskRunner> 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<base::TaskRunner> 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<void(ChannelInfo*)>& did_create_channel_callback,
scoped_refptr<base::TaskRunner> 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<base::TaskRunner> did_destroy_channel_runner);
void DestroyChannel(ChannelInfo* channel_info,
const base::Closure& did_destroy_channel_callback,
scoped_refptr<base::TaskRunner> 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

View File

@ -6,13 +6,14 @@
#include <string.h>
#include <memory>
#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<base::TaskRunner> 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<ScopedTestChannel> 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();
{

View File

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

View File

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

View File

@ -15,22 +15,18 @@
#include <deque>
#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<char*>(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);

View File

@ -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 <windows.h>
#include <string>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "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

View File

@ -10,9 +10,7 @@
#include <deque>
#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 <sys/uio.h>.
@ -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<PlatformHandle>* platform_handles);
ssize_t PlatformChannelRecvmsg(PlatformHandle h,
void* buf,
size_t num_bytes,
std::deque<PlatformHandle>* platform_handles);
} // namespace embedder
} // namespace mojo

View File

@ -4,14 +4,7 @@
#include "mojo/edk/embedder/platform_handle.h"
#include "build/build_config.h"
#if defined(OS_POSIX)
#include <unistd.h>
#elif defined(OS_WIN)
#include <windows.h>
#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

View File

@ -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 <windows.h>
#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

View File

@ -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 <typename PlatformHandleContainer>
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

View File

@ -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 <windows.h>
#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

View File

@ -5,21 +5,21 @@
#ifndef MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_
#define MOJO_EDK_EMBEDDER_PLATFORM_HANDLE_VECTOR_H_
#include <memory>
#include <vector>
#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<ScopedPlatformHandle> instead?
using PlatformHandleVector = std::vector<PlatformHandle>;
// 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<PlatformHandleVector, PlatformHandleVectorDeleter>;
std::unique_ptr<PlatformHandleVector, PlatformHandleVectorDeleter>;
} // namespace embedder
} // namespace mojo

View File

@ -7,10 +7,10 @@
#include <stddef.h>
#include <memory>
#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<PlatformSharedBuffer> {
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<PlatformSharedBufferMapping> Map(size_t offset,
size_t length) = 0;
virtual std::unique_ptr<PlatformSharedBufferMapping> 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<PlatformSharedBufferMapping> MapNoCheck(size_t offset,
size_t length) = 0;
virtual std::unique_ptr<PlatformSharedBufferMapping> 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() {}

View File

@ -8,7 +8,7 @@
#include <stddef.h>
#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;

View File

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

View File

@ -7,8 +7,6 @@
#include <ostream>
#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<int>(process_type);
}

View File

@ -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() {}

View File

@ -48,7 +48,7 @@ size_t SimplePlatformSharedBuffer::GetNumBytes() const {
return num_bytes_;
}
scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::Map(
std::unique_ptr<PlatformSharedBufferMapping> 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<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapNoCheck(
size_t offset,
size_t length) {
std::unique_ptr<PlatformSharedBufferMapping>
SimplePlatformSharedBuffer::MapNoCheck(size_t offset, size_t length) {
DCHECK(IsValidMap(offset, length));
return MapImpl(offset, length);
}

View File

@ -8,15 +8,13 @@
#include <stddef.h>
#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<PlatformSharedBufferMapping> Map(size_t offset,
size_t length) override;
std::unique_ptr<PlatformSharedBufferMapping> Map(size_t offset,
size_t length) override;
bool IsValidMap(size_t offset, size_t length) override;
scoped_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset,
size_t length) override;
std::unique_ptr<PlatformSharedBufferMapping> 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<PlatformSharedBufferMapping> MapImpl(size_t offset, size_t length);
std::unique_ptr<PlatformSharedBufferMapping> 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;

View File

@ -10,9 +10,7 @@
#include <limits>
#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;
}

View File

@ -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<off_t>(num_bytes_))) != 0) {
if (HANDLE_EINTR(
ftruncate(handle.get().fd, static_cast<off_t>(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<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapImpl(
size_t offset,
size_t length) {
std::unique_ptr<PlatformSharedBufferMapping>
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<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapImpl(
}
void* base = static_cast<char*>(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<SimplePlatformSharedBufferMapping>(
new SimplePlatformSharedBufferMapping(base, length, real_base,
real_length));
}
// SimplePlatformSharedBufferMapping -------------------------------------------

View File

@ -7,7 +7,6 @@
#include <limits>
#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<PlatformSharedBufferMapping> mapping(buffer->Map(0, kNumBytes));
std::unique_ptr<PlatformSharedBufferMapping> mapping(
buffer->Map(0, kNumBytes));
ASSERT_TRUE(mapping);
ASSERT_TRUE(mapping->GetBase());
int* stuff = static_cast<int*>(mapping->GetBase());
@ -44,7 +44,7 @@ TEST(SimplePlatformSharedBufferTest, Basic) {
{
ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes));
// Use |MapNoCheck()| this time.
scoped_ptr<PlatformSharedBufferMapping> mapping1(
std::unique_ptr<PlatformSharedBufferMapping> 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<int>(i) + kFudge, stuff1[i]) << i;
scoped_ptr<PlatformSharedBufferMapping> mapping2(
std::unique_ptr<PlatformSharedBufferMapping> 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<PlatformSharedBufferMapping> mapping(
std::unique_ptr<PlatformSharedBufferMapping> 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<SimplePlatformSharedBuffer> buffer(
SimplePlatformSharedBuffer::Create(100));
scoped_ptr<PlatformSharedBufferMapping> mapping1(buffer->Map(0, 100));
scoped_ptr<PlatformSharedBufferMapping> mapping2(buffer->Map(0, 100));
std::unique_ptr<PlatformSharedBufferMapping> mapping1(buffer->Map(0, 100));
std::unique_ptr<PlatformSharedBufferMapping> 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<SimplePlatformSharedBuffer> buffer(
SimplePlatformSharedBuffer::Create(kSizes[i]));
scoped_ptr<PlatformSharedBufferMapping> mapping(buffer->Map(0, kSizes[i]));
std::unique_ptr<PlatformSharedBufferMapping> 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<PlatformSharedBufferMapping> mapping1;
scoped_ptr<PlatformSharedBufferMapping> mapping2;
std::unique_ptr<PlatformSharedBufferMapping> mapping1;
std::unique_ptr<PlatformSharedBufferMapping> mapping2;
{
scoped_refptr<SimplePlatformSharedBuffer> 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<char*>(mapping1->GetBase())[50] = 'x';
}

View File

@ -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 <windows.h>
#include <limits>
#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<uint64_t>(num_bytes_) >
static_cast<uint64_t>(std::numeric_limits<DWORD>::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<DWORD>(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<PlatformSharedBufferMapping> 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<uint64_t>(real_offset),
static_cast<uint64_t>(std::numeric_limits<DWORD>::max()));
void* real_base =
MapViewOfFile(handle_.get().handle, FILE_MAP_READ | FILE_MAP_WRITE, 0,
static_cast<DWORD>(real_offset), real_length);
if (!real_base) {
PLOG(ERROR) << "MapViewOfFile";
return nullptr;
}
void* base = static_cast<char*>(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

View File

@ -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);

View File

@ -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(

View File

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

View File

@ -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<SimplePlatformSupport>());
}
bool Shutdown() {

View File

@ -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

View File

@ -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 <stdint.h>
#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;

View File

@ -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",

View File

@ -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<void(MojoResult)>;
// |callback| must satisfy the same contract as |Awakable::Awake()|.
explicit AsyncWaiter(const AwakeCallback& callback);
virtual ~AsyncWaiter();
~AsyncWaiter() override;
private:
// |Awakable| implementation:

View File

@ -7,25 +7,26 @@
#include <stdint.h>
#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

View File

@ -9,7 +9,6 @@
#include <vector>
#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();

View File

@ -5,6 +5,7 @@
#include "mojo/edk/system/channel.h"
#include <algorithm>
#include <utility>
#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<RawChannel> raw_channel) {
void Channel::Init(std::unique_ptr<RawChannel> 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<MessageInTransit> message) {
bool Channel::WriteMessage(std::unique_ptr<MessageInTransit> 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<MessageInTransit> 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<Channel> 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<MessageInTransit> message(new MessageInTransit(message_view));
std::unique_ptr<MessageInTransit> 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<MessageInTransit> message(new MessageInTransit(
std::unique_ptr<MessageInTransit> 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

View File

@ -7,9 +7,10 @@
#include <stdint.h>
#include "base/containers/hash_tables.h"
#include <memory>
#include <unordered_map>
#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<Channel>,
public RawChannel::Delegate {
class Channel final : public base::RefCountedThreadSafe<Channel>,
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<RawChannel> raw_channel) MOJO_NOT_THREAD_SAFE;
void Init(std::unique_ptr<RawChannel> 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<MessageInTransit> message);
bool WriteMessage(std::unique_ptr<MessageInTransit> 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<RawChannel> raw_channel_ MOJO_GUARDED_BY(mutex_);
std::unique_ptr<RawChannel> 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<ChannelEndpointId, scoped_refptr<ChannelEndpoint>>;
std::unordered_map<ChannelEndpointId, scoped_refptr<ChannelEndpoint>>;
// 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<ChannelEndpointId, scoped_refptr<IncomingEndpoint>>;
std::unordered_map<ChannelEndpointId, scoped_refptr<IncomingEndpoint>>;
// 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_);

View File

@ -4,6 +4,8 @@
#include "mojo/edk/system/channel_endpoint.h"
#include <utility>
#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<MessageInTransit> message) {
bool ChannelEndpoint::EnqueueMessage(
std::unique_ptr<MessageInTransit> 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<MessageInTransit> message) {
void ChannelEndpoint::OnReadMessage(std::unique_ptr<MessageInTransit> 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<MessageInTransit> message) {
bool ChannelEndpoint::WriteMessageNoLock(
std::unique_ptr<MessageInTransit> message) {
DCHECK(message);
mutex_.AssertHeld();
@ -160,11 +164,11 @@ bool ChannelEndpoint::WriteMessageNoLock(scoped_ptr<MessageInTransit> 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<MessageInTransit> message) {
std::unique_ptr<MessageInTransit> message) {
DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT);
scoped_refptr<ChannelEndpointClient> client;

View File

@ -5,12 +5,12 @@
#ifndef MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_
#define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_H_
#include <memory>
#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<ChannelEndpoint> {
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<MessageInTransit> message);
bool EnqueueMessage(std::unique_ptr<MessageInTransit> 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<MessageInTransit> message);
void OnReadMessage(std::unique_ptr<MessageInTransit> 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>;
~ChannelEndpoint();
bool WriteMessageNoLock(scoped_ptr<MessageInTransit> message)
bool WriteMessageNoLock(std::unique_ptr<MessageInTransit> message)
MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Helper for |OnReadMessage()|, handling messages for the client.
void OnReadMessageForClient(scoped_ptr<MessageInTransit> message);
void OnReadMessageForClient(std::unique_ptr<MessageInTransit> message);
// Moves |state_| from |RUNNING| to |DEAD|. |channel_| must be non-null, but
// this does not call |channel_->DetachEndpoint()|.

View File

@ -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<ChannelEndpointClient> {
public:
// Called by |ChannelEndpoint| in response to its |OnReadMessage()|, which is

View File

@ -8,11 +8,10 @@
#include <stddef.h>
#include <stdint.h>
#include <functional>
#include <ostream>
#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<mojo::system::ChannelEndpointId> {
size_t operator()(mojo::system::ChannelEndpointId channel_endpoint_id) const {
@ -143,6 +139,6 @@ struct hash<mojo::system::ChannelEndpointId> {
}
};
} // namespace BASE_HASH_NAMESPACE
} // namespace std
#endif // MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_ID_H_

View File

@ -4,6 +4,9 @@
#include "mojo/edk/system/channel_endpoint.h"
#include <memory>
#include <utility>
#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<MessageInTransit> send_message = test::MakeTestMessage(message_id);
std::unique_ptr<MessageInTransit> 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<MessageInTransit> read_message = client0->PopMessage();
std::unique_ptr<MessageInTransit> 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<MessageInTransit> read_message = client0->PopMessage();
std::unique_ptr<MessageInTransit> read_message = client0->PopMessage();
ASSERT_TRUE(read_message);
test::VerifyTestMessage(read_message.get(), message_id);
}

View File

@ -7,8 +7,9 @@
#include <stdint.h>
#include <unordered_map>
#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<ChannelId, scoped_refptr<Channel>>;
std::unordered_map<ChannelId, scoped_refptr<Channel>>;
ChannelIdToChannelMap channels_ MOJO_GUARDED_BY(mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelManager);

View File

@ -4,6 +4,8 @@
#include "mojo/edk/system/channel_test_base.h"
#include <utility>
#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());

View File

@ -5,13 +5,14 @@
#ifndef MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_
#define MOJO_EDK_SYSTEM_CHANNEL_TEST_BASE_H_
#include <memory>
#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<Channel>* 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<RawChannel> raw_channels_[2];
mojo::test::TestIOThread io_thread_;
std::unique_ptr<RawChannel> raw_channels_[2];
scoped_refptr<Channel> channels_[2];
MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelTestBase);

View File

@ -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<ChannelEndpoint> channel_endpoint;
scoped_refptr<MessagePipe> 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

View File

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

View File

@ -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<int>(result);
}

View File

@ -8,12 +8,13 @@
#include <string.h>
#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;

View File

@ -4,10 +4,11 @@
#include "mojo/edk/system/core.h"
#include <memory>
#include <utility>
#include <vector>
#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<PlatformSupport>| 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> dispatcher = GetDispatcher(handle);
DCHECK(dispatcher);
scoped_ptr<AsyncWaiter> waiter = make_scoped_ptr(new AsyncWaiter(callback));
std::unique_ptr<AsyncWaiter> 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<embedder::PlatformSharedBufferMapping> mapping;
std::unique_ptr<embedder::PlatformSharedBufferMapping> 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;

View File

@ -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:
// ---------------------------------------------------------------------------

View File

@ -8,6 +8,8 @@
#include <algorithm>
#include <limits>
#include <memory>
#include <utility>
#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<LocalDataPipeImpl>());
}
// static
@ -102,7 +105,7 @@ DataPipe* DataPipe::CreateRemoteProducerFromExisting(
const MojoCreateDataPipeOptions& validated_options,
MessageInTransitQueue* message_queue,
ChannelEndpoint* channel_endpoint) {
scoped_ptr<char, base::AlignedFreeDeleter> buffer;
std::unique_ptr<char, base::AlignedFreeDeleter> 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<RemoteProducerDataPipeImpl>(
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<RemoteConsumerDataPipeImpl>(
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<RemoteConsumerDataPipeImpl>(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<const void> elements,
UserPointer<uint32_t> 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<void*> buffer,
UserPointer<uint32_t> 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<void> elements,
UserPointer<uint32_t> 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<void> elements,
MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> 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<uint32_t> num_bytes,
}
MojoResult DataPipe::ConsumerQueryData(UserPointer<uint32_t> 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<const void*> buffer,
UserPointer<uint32_t> 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<DataPipeImpl> impl)
std::unique_ptr<DataPipeImpl> 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<DataPipeImpl> DataPipe::ReplaceImplNoLock(
scoped_ptr<DataPipeImpl> new_impl) {
lock_.AssertAcquired();
std::unique_ptr<DataPipeImpl> DataPipe::ReplaceImplNoLock(
std::unique_ptr<DataPipeImpl> new_impl) {
mutex_.AssertHeld();
DCHECK(new_impl);
impl_->set_owner(nullptr);
scoped_ptr<DataPipeImpl> rv(impl_.Pass());
impl_ = new_impl.Pass();
std::unique_ptr<DataPipeImpl> 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();
}

View File

@ -7,14 +7,15 @@
#include <stdint.h>
#include <memory>
#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<DataPipeImpl> ReplaceImplNoLock(scoped_ptr<DataPipeImpl> new_impl);
void SetProducerClosedNoLock();
void SetConsumerClosedNoLock();
std::unique_ptr<DataPipeImpl> ReplaceImplNoLock(
std::unique_ptr<DataPipeImpl> 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<DataPipeImpl> impl);
std::unique_ptr<DataPipeImpl> 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<AwakableList> producer_awakable_list_;
scoped_ptr<AwakableList> consumer_awakable_list_;
std::unique_ptr<AwakableList> producer_awakable_list_ MOJO_GUARDED_BY(mutex_);
std::unique_ptr<AwakableList> 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<DataPipeImpl> 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<DataPipeImpl> impl_ MOJO_GUARDED_BY(mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipe);
};

Some files were not shown because too many files have changed in this diff Show More