mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge pull request #1317 from jamesr/roll_pubspec_and_mojo_sdk
Update to Mojo 4e4d51ce28a8edcb32b9c7f555e38e2ae84a825e, update deps
This commit is contained in:
commit
93fe88f148
2
DEPS
2
DEPS
@ -19,7 +19,7 @@
|
||||
|
||||
vars = {
|
||||
'chromium_git': 'https://chromium.googlesource.com',
|
||||
'mojo_sdk_revision': '3ec8c53e9c9e5a8cd3cf251c4ae4754b75172225',
|
||||
'mojo_sdk_revision': '711a0bcfb141b481f51ac1c9c62ec73e9b988615',
|
||||
'mojo_devtools_revision': '49879d78ce4486e10c2214a101d9b2e82794b2f4',
|
||||
'skia_revision': '0d39d37ddcfb3847795639eaef513f1112eba627',
|
||||
'dart_revision': 'cab003366785773ace16b5305ac1f33c228cac54',
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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: () {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
19
mojo/converters/ozone_drm_gpu/BUILD.gn
Normal file
19
mojo/converters/ozone_drm_gpu/BUILD.gn
Normal 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",
|
||||
]
|
||||
}
|
||||
108
mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.cc
Normal file
108
mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.cc
Normal 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
|
||||
@ -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_
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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",
|
||||
]
|
||||
}
|
||||
@ -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.
|
||||
}
|
||||
@ -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"
|
||||
@ -1,4 +0,0 @@
|
||||
name: apptest
|
||||
version: 0.0.1
|
||||
dependencies:
|
||||
test: ^0.12.3+7
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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")
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ dart_pkg("mojo_services") {
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//mojo/public/dart",
|
||||
"//mojo/services",
|
||||
]
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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",
|
||||
]
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
```
|
||||
@ -1,5 +0,0 @@
|
||||
mojom
|
||||
====
|
||||
|
||||
mojom.dart files will appear here after running the generate script (see the
|
||||
top-level documentation for this package).
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
@ -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
|
||||
@ -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();
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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() {}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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() {}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 -------------------------------------------
|
||||
|
||||
@ -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';
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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);
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()|.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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());
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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:
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user