0

third_party/mojo: Remove python/go/dart bindings.

This patch also removes some unused tools for downloading prebuilt or
dart stuff.

BUG=None
R=jam@chromium.org, rockot@chromium.org

Review URL: https://codereview.chromium.org/1348903003 .

Cr-Commit-Position: refs/heads/master@{#350015}
This commit is contained in:
yzshen
2015-09-21 14:10:37 -07:00
parent 18949d2a87
commit f9493daff3
134 changed files with 6 additions and 16865 deletions
BUILD.gn
third_party/mojo
mojom_bindings_generator.gypimojom_bindings_generator_explicit.gypimojom_bindings_generator_variables.gypi
src
mojo
public
.gitignoreBUILD.gnVERSION
dart
go
platform
native_cgo
python
tools

@ -717,24 +717,11 @@ group("gn_mojo_targets") {
# TODO(GYP): Figure out if any of these should be in gn_all
# and figure out how cross-platform they are
deps = [
"//chrome/browser/ui/webui/omnibox:mojo_bindings_python",
"//content/public/common:mojo_bindings_python",
"//content/common:mojo_bindings_python",
"//content/test:web_ui_test_mojo_bindings_python",
"//device/battery:mojo_bindings_python",
"//device/vibration:mojo_bindings_python",
"//ipc/mojo:ipc_mojo_perftests",
"//ipc/mojo:client_channel_python",
"//media/mojo/interfaces:interfaces_python",
"//media/mojo/services:cdm_service",
"//media/mojo:tests",
"//mojo:tests",
"//net/interfaces:interfaces_python",
"//third_party/mojo/src/mojo/edk/js/test:js_integration_tests",
"//third_party/mojo/src/mojo/edk/js/tests:js_to_cpp_bindings_python",
"//third_party/mojo/src/mojo/public/python:packaged_application",
"//third_party/mojo/src/mojo/public/python:packaged_bindings",
"//third_party/mojo_services/src/accessibility/public/interfaces:interfaces_python",
]
}
}

@ -46,7 +46,6 @@
'<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom.cc',
'<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom.h',
'<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom.js',
'<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT)_mojom.py',
'<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom-internal.h',
],
'action': [
@ -57,7 +56,6 @@
'<@(mojom_import_args)',
'-o', '<(SHARED_INTERMEDIATE_DIR)',
'--java_output_directory=<(java_out_dir)',
'--dart_mojo_root=//third_party/mojo/src',
],
'message': 'Generating Mojo bindings from <(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).mojom',
'process_outputs_as_sources': 1,

@ -64,7 +64,6 @@
'<@(mojom_import_args)',
'-o', '<(SHARED_INTERMEDIATE_DIR)',
'--java_output_directory=<(java_out_dir)',
'--dart_mojo_root=//third_party/mojo/src',
],
'message': 'Generating Mojo bindings from <@(mojom_files)',
}

@ -43,12 +43,9 @@
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/js_templates/struct_definition.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/js_templates/union_definition.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/js_templates/validation_macros.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/python_templates/module_macros.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/python_templates/module.py.tmpl',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_java_generator.py',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_js_generator.py',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_python_generator.py',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/__init__.py',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/error.py',
'<(DEPTH)/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/__init__.py',

@ -1,2 +1 @@
*.pyc
/tools/prebuilt/

@ -20,10 +20,6 @@ group("public") {
deps += [ "cpp/application:standalone" ]
}
if (is_linux) {
deps += [ "python" ]
}
if (is_android) {
deps += [
"java:system",

@ -1 +0,0 @@
cbf8d2ee9b7d07c7751d8d861f3b7e2bd9829b05

@ -1,3 +0,0 @@
analyzer:
exclude:
- 'sdk_ext/**'

@ -1,3 +0,0 @@
.packages
packages/
pubspec.lock

@ -1,71 +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_sdk.gni")
import("rules.gni")
dart_mojo_sdk_entrypoints = [
"lib/application.dart",
"lib/bindings.dart",
"lib/core.dart",
]
dart_mojo_sdk_sources = [
"lib/src/application_connection.dart",
"lib/src/application.dart",
"lib/src/buffer.dart",
"lib/src/codec.dart",
"lib/src/control_message.dart",
"lib/src/data_pipe.dart",
"lib/src/drain_data.dart",
"lib/src/event_stream.dart",
"lib/src/handle.dart",
"lib/src/message.dart",
"lib/src/message_pipe.dart",
"lib/src/proxy.dart",
"lib/src/struct.dart",
"lib/src/stub.dart",
"lib/src/types.dart",
"lib/src/union.dart",
"lib/src/utils.dart",
]
dartzip_package("dart_dartzip") {
sources = dart_mojo_sdk_entrypoints + dart_mojo_sdk_sources + [
"pubspec.yaml",
"CHANGELOG.md",
"README.md",
]
uses_pub = true
package_name_override = "mojo"
deps = [
"../interfaces/application",
"../interfaces/bindings",
"../interfaces/network",
]
}
dart_pkg("dart_pkg") {
libs = dart_mojo_sdk_entrypoints
sources = dart_mojo_sdk_sources + [
"lib/_sdkext",
"pubspec.yaml",
"CHANGELOG.md",
"README.md",
]
sdk_ext_directory = "sdk_ext"
# List of mojom targets that the mojo pkg exports
deps = [
"../interfaces",
]
}
group("dart") {
deps = [
":dart_dartzip",
":dart_pkg",
]
}

@ -1,48 +0,0 @@
## 0.0.22
- 58 changes: https://github.com/domokit/mojo/compare/e172885...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
- 197 changes: https://github.com/domokit/mojo/compare/bdbb0c7...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.7 was skipped.
## 0.0.6
- Fix interface name capitalization bug in Dart bindings
- Add support for interface control messages (queryVersion, requireVersion)

@ -1,126 +0,0 @@
Dart Mojo Applications
====
## Mojo Application API
*TODO(zra)*
## Application Packaging
All Dart sources for a Mojo application are collected in a specially formatted
zip file, which is understood by Dart's content handler in the Mojo shell.
This section describes what the various parts of that package are, and how they
all make it to the right place.
### GN Template
Dart Mojo applications are built with the GN template
'dartzip_packaged_application' defined in `//mojo/public/dart/rules.gni`.
Here is an example:
```
dartzip_packaged_application("foo") {
output_name = "dart_foo"
uses_pub = true
sources = [
"main.dart",
"foo.dart",
]
deps = [
"//mojo/public/dart",
"//mojo/services/network/public/interfaces",
]
}
```
There are several parts:
* `output_name` is the name of the resulting .mojo file if it should be
different from the name of the target. (In this case we get dart_foo.mojo
instead of foo.mojo.)
* `uses_pub` should be true when the application depends on Dart packages pulled
down from pub. The application should have `pubspec.yaml` and `pubspec.lock`
files adjacent to `main.dart`. More on this below.
* `sources` is the list of Dart sources for the application. Each application
**must** contain a `main.dart` file. `main.dart` must be the library entry
point, and must contain the `main()` function.
* `deps` has the usual meaning. In the example above,
`//mojo/services/network/public/interfaces` indicates that the "foo"
application uses the Dart bindings generated for the network service.
### pub packages
Dart Mojo applications may use packages from the pub package repository at
pub.dartlang.org.
The "foo" example above has `uses_pub` set to true. Suppose its `pubspec.yaml`
is as follows:
```
name: foo
version: 0.0.1
description: Foo
dependencies:
crypto: ">=0.9.0 <0.10.0"
```
The script `//mojo/public/tools/git/dart_pub_get.py` should be run before build
time, e.g. as a "runhooks" action during `gclient sync`. The script traverses
a directory tree looking for `pubspec.yaml` files. On finding one, in the
containing directory, it runs `pub get`. This creates a "packages/" directory
in the source tree adjacent to the `pubspec.yaml` file containing the downloaded
Dart packages. `pub get` also creates a `pubspec.lock` file that locks down
pub packages to specific versions. This `pubspec.lock` file must be checked in
in order to have hermetic builds.
During the build, The `dartzip_packaged_application` rule looks for a
"packages/" directory, and copies its contents into the zip file.
### Generated bindings
The script `//mojo/public/tools/bindings/generators/mojom_dart_generator.py`
and the templates under `//mojo/public/tools/bindings/generators/dart_templates`
govern how `.mojom` files are compiled into Dart code.
Consider the `network_error.mojom` file from the network services used by our
"foo" example:
```
module mojo;
struct NetworkError {
int32 code;
string? description;
};
```
This contents of this file are in the `mojo` module. The Dart source generated
for this file will end up under, e.g.
`//out/Debug/gen/dart-gen/mojom/mojo/network_error.mojom.dart`, along with the
other Dart sources generated for `.mojom` files in the `mojo` module.
### Resulting layout
They layout for our "foo" example will be the following:
```
//main.dart
//foo.dart
//crypto/... # Dart's crypto pub package.
//mojo/public/dart/... # Mojo SDK Dart libraries.
//mojom/mojo/... # Generated bindings in the mojo module.
```
Where `//mojo/public/dart` contains Dart's Mojo bindings, `//crypto` contains
the `crypto` pub package, and `//mojom/mojo` contains the generated bindings in
the mojom module for the network service.
Mojo's Dart content handler sets the package root for a Dart application to be
the root directory of the unpacked zip file. Therefore, Dart sources in this
application can use the following imports:
```dart
import 'package:crypto/crypto.dart';
import 'package:mojo/public/dart/application.dart';
import 'package:mojom/mojo/network_error.mojom.dart';
```

@ -1,3 +0,0 @@
{
"dart:mojo.internal": "../sdk_ext/internal.dart"
}

@ -1,16 +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.
library application;
import 'dart:async';
import 'package:mojo/bindings.dart' as bindings;
import 'package:mojo/core.dart' as core;
import 'package:mojo/mojo/application.mojom.dart' as application_mojom;
import 'package:mojo/mojo/service_provider.mojom.dart';
import 'package:mojo/mojo/shell.mojom.dart' as shell_mojom;
part 'src/application.dart';
part 'src/application_connection.dart';

@ -1,20 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library bindings;
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:mojo/core.dart' as core;
import 'package:mojo/mojo/interface_control_messages.mojom.dart' as icm;
part 'src/control_message.dart';
part 'src/codec.dart';
part 'src/message.dart';
part 'src/proxy.dart';
part 'src/struct.dart';
part 'src/stub.dart';
part 'src/union.dart';

@ -1,20 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library core;
import 'dart:async';
import 'dart:collection';
import 'dart:isolate';
import 'dart:mojo.internal';
import 'dart:typed_data';
part 'src/buffer.dart';
part 'src/data_pipe.dart';
part 'src/drain_data.dart';
part 'src/event_stream.dart';
part 'src/handle.dart';
part 'src/message_pipe.dart';
part 'src/types.dart';
part 'src/utils.dart';

@ -1,133 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of application;
class _ApplicationImpl implements application_mojom.Application {
application_mojom.ApplicationStub _stub;
shell_mojom.ShellProxy shell;
Application _application;
_ApplicationImpl(
Application application, core.MojoMessagePipeEndpoint endpoint) {
_application = application;
_stub = new application_mojom.ApplicationStub.fromEndpoint(endpoint, this);
_stub.onError = close;
}
_ApplicationImpl.fromHandle(Application application, core.MojoHandle handle) {
_application = application;
_stub = new application_mojom.ApplicationStub.fromHandle(handle, this);
_stub.onError = close;
}
set onError(core.ErrorHandler f) {
_stub.onError = f;
}
void initialize(
bindings.ProxyBase shellProxy, List<String> args, String url) {
assert(shell == null);
shell = shellProxy;
_application.initialize(args, url);
}
@override
void acceptConnection(String requestorUrl, ServiceProviderStub services,
bindings.ProxyBase exposedServices, String resolvedUrl) => _application
._acceptConnection(requestorUrl, services, exposedServices, resolvedUrl);
@override
void requestQuit() => _application._requestQuitAndClose();
Future close({bool immediate: false}) {
if (shell != null) {
shell.close(immediate: immediate);
}
return _stub.close(immediate: immediate);
}
}
// TODO(zra): Better documentation and examples.
// To implement, do the following:
// - Optionally override initialize() to process command-line args.
// - Optionally override acceptConnection() if services are to be provided.
// - Optionally override close() to clean up application resources.
abstract class Application {
_ApplicationImpl _applicationImpl;
List<ApplicationConnection> _applicationConnections;
Function onError;
Application(core.MojoMessagePipeEndpoint endpoint) {
_applicationConnections = [];
_applicationImpl = new _ApplicationImpl(this, endpoint);
_applicationImpl.onError = _errorHandler;
}
Application.fromHandle(core.MojoHandle appHandle) {
_applicationConnections = [];
_applicationImpl = new _ApplicationImpl.fromHandle(this, appHandle);
_applicationImpl.onError = _errorHandler;
}
void initialize(List<String> args, String url) {}
// TODO(skydart): This is a temporary fix to allow sky application to consume
// mojo services. Do not use for any other purpose.
void initializeFromShellProxy(
shell_mojom.ShellProxy shellProxy, List<String> args, String url) =>
_applicationImpl.initialize(shellProxy, args, url);
// Returns a connection to the app at |url|.
ApplicationConnection connectToApplication(String url) {
var proxy = new ServiceProviderProxy.unbound();
var stub = new ServiceProviderStub.unbound();
_applicationImpl.shell.ptr.connectToApplication(url, proxy, stub);
var connection = new ApplicationConnection(stub, proxy);
_applicationConnections.add(connection);
return connection;
}
void connectToService(String url, bindings.ProxyBase proxy) {
connectToApplication(url).requestService(proxy);
}
void requestQuit() {}
void _requestQuitAndClose() {
requestQuit();
close();
}
void _errorHandler() {
close().then((_) {
if (onError != null) onError();
});
}
Future close({bool immediate: false}) {
assert(_applicationImpl != null);
_applicationConnections.forEach((c) => c.close(immediate: immediate));
_applicationConnections.clear();
return _applicationImpl.close(immediate: immediate);
}
// This method closes all the application connections. Used during apptesting.
void resetConnections() {
assert(_applicationImpl != null);
_applicationConnections.forEach((c) => c.close());
_applicationConnections.clear();
}
void _acceptConnection(String requestorUrl, ServiceProviderStub services,
ServiceProviderProxy exposedServices, String resolvedUrl) {
var connection = new ApplicationConnection(services, exposedServices);
_applicationConnections.add(connection);
acceptConnection(requestorUrl, resolvedUrl, connection);
}
// Override this method to provide services on |connection|.
void acceptConnection(String requestorUrl, String resolvedUrl,
ApplicationConnection connection) {}
}

@ -1,121 +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.
part of application;
typedef Object ServiceFactory(core.MojoMessagePipeEndpoint endpoint);
typedef void FallbackServiceFactory(
String interfaceName, core.MojoMessagePipeEndpoint endpoint);
class LocalServiceProvider implements ServiceProvider {
final ApplicationConnection connection;
ServiceProviderStub _stub;
LocalServiceProvider(this.connection, this._stub) {
assert(_stub.isOpen);
_stub.impl = this;
}
set onError(Function f) {
_stub.onError = f;
}
Future close({bool immediate: false}) => _stub.close(immediate: immediate);
void connectToService(
String interfaceName, core.MojoMessagePipeEndpoint pipe) {
if (connection._nameToServiceFactory.containsKey(interfaceName)) {
connection._nameToServiceFactory[interfaceName](pipe);
return;
}
if (connection.fallbackServiceFactory != null) {
connection.fallbackServiceFactory(interfaceName, pipe);
return;
}
// The specified interface isn't provided. Close the pipe so the
// remote endpoint sees that we don't support this interface.
pipe.close();
}
}
// Encapsulates a pair of ServiceProviders that enable services (interface
// implementations) to be provided to a remote application as well as exposing
// services provided by a remote application. ApplicationConnection
// objects are returned by the Application ConnectToApplication() method
// and they're passed to the Application AcceptConnection() method.
//
// To request a service from the remote application:
// var proxy = applicationConnection.requestService(ViewManagerClientName);
//
// To provide a service to the remote application, specify a function that
// returns a service. For example:
// applicationConnection.provideService(ViewManagerClientName, (pipe) =>
// new ViewManagerClientImpl(pipe));
//
// To handle requests for any interface, set fallbackServiceFactory to a
// function that takes ownership of the incoming message pipe endpoint. If the
// fallbackServiceFactory function doesn't bind the pipe, it should close it.
//
// The fallbackServiceFactory is only used if a service wasn't specified
// with provideService().
class ApplicationConnection {
ServiceProviderProxy remoteServiceProvider;
LocalServiceProvider _localServiceProvider;
final _nameToServiceFactory = new Map<String, ServiceFactory>();
FallbackServiceFactory _fallbackServiceFactory;
core.ErrorHandler onError;
ApplicationConnection(ServiceProviderStub stub, this.remoteServiceProvider) {
if (stub != null) {
_localServiceProvider = new LocalServiceProvider(this, stub);
_localServiceProvider.onError = _errorHandler;
}
}
FallbackServiceFactory get fallbackServiceFactory => _fallbackServiceFactory;
set fallbackServiceFactory(FallbackServiceFactory f) {
assert(_localServiceProvider != null);
_fallbackServiceFactory = f;
}
bindings.ProxyBase requestService(bindings.ProxyBase proxy) {
assert(!proxy.impl.isBound &&
(remoteServiceProvider != null) &&
remoteServiceProvider.impl.isBound);
var pipe = new core.MojoMessagePipe();
proxy.impl.bind(pipe.endpoints[0]);
remoteServiceProvider.ptr.connectToService(proxy.name, pipe.endpoints[1]);
return proxy;
}
void provideService(String interfaceName, ServiceFactory factory) {
assert(_localServiceProvider != null);
_nameToServiceFactory[interfaceName] = factory;
}
void _errorHandler() {
close().then((_) {
if (onError != null) onError();
});
}
Future close({bool immediate: false}) {
var rspCloseFuture;
var lspCloseFuture;
if (remoteServiceProvider != null) {
rspCloseFuture = remoteServiceProvider.close();
remoteServiceProvider = null;
} else {
rspCloseFuture = new Future.value(null);
}
if (_localServiceProvider != null) {
lspCloseFuture = _localServiceProvider.close(immediate: immediate);
_localServiceProvider = null;
} else {
lspCloseFuture = new Future.value(null);
}
return rspCloseFuture.then((_) => lspCloseFuture);
}
}

@ -1,85 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of core;
class MojoSharedBuffer {
static const int CREATE_FLAG_NONE = 0;
static const int DUPLICATE_FLAG_NONE = 0;
static const int MAP_FLAG_NONE = 0;
MojoHandle handle;
MojoResult status;
ByteData mapping;
MojoSharedBuffer(this.handle,
[this.status = MojoResult.OK, this.mapping = null]);
factory MojoSharedBuffer.create(int numBytes, [int flags = 0]) {
List result = MojoSharedBufferNatives.Create(numBytes, flags);
if (result == null) {
return null;
}
assert((result is List) && (result.length == 2));
var r = new MojoResult(result[0]);
if (!r.isOk) {
return null;
}
MojoSharedBuffer buf =
new MojoSharedBuffer(new MojoHandle(result[1]), r, null);
return buf;
}
factory MojoSharedBuffer.duplicate(MojoSharedBuffer msb, [int flags = 0]) {
List result = MojoSharedBufferNatives.Duplicate(msb.handle.h, flags);
if (result == null) {
return null;
}
assert((result is List) && (result.length == 2));
var r = new MojoResult(result[0]);
if (!r.isOk) {
return null;
}
MojoSharedBuffer dupe =
new MojoSharedBuffer(new MojoHandle(result[1]), r, null);
return dupe;
}
MojoResult close() {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return status;
}
MojoResult r = handle.close();
status = r;
mapping = null;
return status;
}
MojoResult map(int offset, int numBytes, [int flags = 0]) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return status;
}
List result =
MojoSharedBufferNatives.Map(this, handle.h, offset, numBytes, flags);
if (result == null) {
status = MojoResult.INVALID_ARGUMENT;
return status;
}
assert((result is List) && (result.length == 2));
status = new MojoResult(result[0]);
mapping = result[1];
return status;
}
MojoResult unmap() {
int r = MojoSharedBufferNatives.Unmap(mapping);
status = new MojoResult(r);
mapping = null;
return status;
}
}

@ -1,877 +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.
part of bindings;
int align(int size) => size + (kAlignment - (size % kAlignment)) % kAlignment;
const int kAlignment = 8;
const int kSerializedHandleSize = 4;
const int kSerializedInterfaceSize = 8; // 4-byte handle + 4-byte version
const int kPointerSize = 8;
const int kUnionSize = 16;
const StructDataHeader kMapStructHeader = const StructDataHeader(24, 0);
const int kUnspecifiedArrayLength = -1;
const int kNothingNullable = 0;
const int kArrayNullable = (1 << 0);
const int kElementNullable = (1 << 1);
bool isArrayNullable(int nullability) => (nullability & kArrayNullable) > 0;
bool isElementNullable(int nullability) => (nullability & kElementNullable) > 0;
class StructDataHeader {
static const int kHeaderSize = 8;
static const int kSizeOffset = 0;
static const int kVersionOffset = 4;
final int size;
final int version;
const StructDataHeader(this.size, this.version);
String toString() => "StructDataHeader($size, $version)";
}
class ArrayDataHeader {
static const int kHeaderSize = 8;
static const int kSizeOffset = 0;
static const int kNumElementsOffset = 4;
final int size;
final int numElements;
const ArrayDataHeader(this.size, this.numElements);
String toString() => "ArrayDataHeader($size, $numElements)";
}
class MojoCodecError {
final String message;
MojoCodecError(this.message);
String toString() => message;
}
class _EncoderBuffer {
ByteData buffer;
List<core.MojoHandle> handles;
int extent;
static const int kInitialBufferSize = 1024;
_EncoderBuffer([int size = -1])
: buffer = new ByteData(size > 0 ? size : kInitialBufferSize),
handles = [],
extent = 0;
void _grow(int newSize) {
Uint8List newBuffer = new Uint8List(newSize);
newBuffer.setRange(0, buffer.lengthInBytes, buffer.buffer.asUint8List());
buffer = newBuffer.buffer.asByteData();
}
void claimMemory(int claimSize) {
extent += claimSize;
if (extent > buffer.lengthInBytes) {
int newSize = buffer.lengthInBytes + claimSize;
newSize += newSize ~/ 2;
_grow(newSize);
}
}
ByteData get trimmed => new ByteData.view(buffer.buffer, 0, extent);
}
class Encoder {
_EncoderBuffer _buffer;
int _base;
Encoder([int size = -1])
: _buffer = new _EncoderBuffer(size),
_base = 0;
Encoder._fromBuffer(_EncoderBuffer buffer)
: _buffer = buffer,
_base = buffer.extent;
Encoder getStructEncoderAtOffset(StructDataHeader dataHeader) {
var result = new Encoder._fromBuffer(_buffer);
result.encodeStructDataHeader(dataHeader);
return result;
}
Encoder getArrayEncoderAtOffset(ArrayDataHeader dataHeader) {
var result = new Encoder._fromBuffer(_buffer);
result.encodeArrayDataHeader(dataHeader);
return result;
}
Message get message => new Message(_buffer.trimmed, _buffer.handles);
void encodeStructDataHeader(StructDataHeader dataHeader) {
_buffer.claimMemory(align(dataHeader.size));
encodeUint32(dataHeader.size, StructDataHeader.kSizeOffset);
encodeUint32(dataHeader.version, StructDataHeader.kVersionOffset);
}
void encodeArrayDataHeader(ArrayDataHeader dataHeader) {
_buffer.claimMemory(align(dataHeader.size));
encodeUint32(dataHeader.size, ArrayDataHeader.kSizeOffset);
encodeUint32(dataHeader.numElements, ArrayDataHeader.kNumElementsOffset);
}
static const String kErrorUnsigned =
'Passing negative value to unsigned encoder';
void encodeBool(bool value, int offset, int bit) {
if (value) {
int encodedValue = _buffer.buffer.getUint8(_base + offset);
encodedValue |= (1 << bit);
_buffer.buffer.setUint8(_base + offset, encodedValue);
}
}
void encodeInt8(int value, int offset) =>
_buffer.buffer.setInt8(_base + offset, value);
void encodeUint8(int value, int offset) {
if (value < 0) {
throw new MojoCodecError('$kErrorUnsigned: $value');
}
_buffer.buffer.setUint8(_base + offset, value);
}
void encodeInt16(int value, int offset) =>
_buffer.buffer.setInt16(_base + offset, value, Endianness.LITTLE_ENDIAN);
void encodeUint16(int value, int offset) {
if (value < 0) {
throw new MojoCodecError('$kErrorUnsigned: $value');
}
_buffer.buffer.setUint16(_base + offset, value, Endianness.LITTLE_ENDIAN);
}
void encodeInt32(int value, int offset) =>
_buffer.buffer.setInt32(_base + offset, value, Endianness.LITTLE_ENDIAN);
void encodeUint32(int value, int offset) {
if (value < 0) {
throw new MojoCodecError('$kErrorUnsigned: $value');
}
_buffer.buffer.setUint32(_base + offset, value, Endianness.LITTLE_ENDIAN);
}
void encodeInt64(int value, int offset) =>
_buffer.buffer.setInt64(_base + offset, value, Endianness.LITTLE_ENDIAN);
void encodeUint64(int value, int offset) {
if (value < 0) {
throw new MojoCodecError('$kErrorUnsigned: $value');
}
_buffer.buffer.setUint64(_base + offset, value, Endianness.LITTLE_ENDIAN);
}
void encodeFloat(double value, int offset) => _buffer.buffer.setFloat32(
_base + offset, value, Endianness.LITTLE_ENDIAN);
void encodeDouble(double value, int offset) => _buffer.buffer.setFloat64(
_base + offset, value, Endianness.LITTLE_ENDIAN);
void encodeHandle(core.MojoHandle value, int offset, bool nullable) {
if ((value == null) || !value.isValid) {
encodeInvalideHandle(offset, nullable);
} else {
encodeUint32(_buffer.handles.length, offset);
_buffer.handles.add(value.pass());
}
}
void encodeMessagePipeHandle(
core.MojoMessagePipeEndpoint value, int offset, bool nullable) =>
encodeHandle(value != null ? value.handle : null, offset, nullable);
void encodeConsumerHandle(
core.MojoDataPipeConsumer value, int offset, bool nullable) =>
encodeHandle(value != null ? value.handle : null, offset, nullable);
void encodeProducerHandle(
core.MojoDataPipeProducer value, int offset, bool nullable) =>
encodeHandle(value != null ? value.handle : null, offset, nullable);
void encodeSharedBufferHandle(
core.MojoSharedBuffer value, int offset, bool nullable) =>
encodeHandle(value != null ? value.handle : null, offset, nullable);
void encodeInterface(
core.MojoEventStreamListener interface, int offset, bool nullable) {
if (interface == null) {
encodeInvalideHandle(offset, nullable);
// Set the version field to 0.
encodeUint32(0, offset + kSerializedHandleSize);
return;
}
if (interface is Stub) {
assert(!interface.isBound);
var pipe = new core.MojoMessagePipe();
interface.bind(pipe.endpoints[0]);
interface.listen();
encodeMessagePipeHandle(pipe.endpoints[1], offset, nullable);
// Set the version to the version in the stub.
encodeUint32(interface.version, offset + kSerializedHandleSize);
} else if (interface is Proxy) {
assert(interface.isBound);
if (!interface.isOpen) {
// Make sure that we are listening so that state for the proxy is
// cleaned up when the message is sent and the handle is closed.
interface.listen();
}
encodeMessagePipeHandle(interface.endpoint, offset, nullable);
// Set the version to the current version of the proxy.
encodeUint32(interface.version, offset + kSerializedHandleSize);
} else {
throw new MojoCodecError(
'Trying to encode an unknown MojoEventStreamListener');
}
}
void encodeInterfaceRequest(ProxyBase client, int offset, bool nullable) {
if (client == null) {
encodeInvalideHandle(offset, nullable);
return;
}
var pipe = new core.MojoMessagePipe();
client.impl.bind(pipe.endpoints[0]);
client.impl.listen();
encodeMessagePipeHandle(pipe.endpoints[1], offset, nullable);
}
void encodeNullPointer(int offset, bool nullable) {
if (!nullable) {
throw new MojoCodecError(
'Trying to encode a null pointer for a non-nullable type');
}
_buffer.buffer.setUint64(_base + offset, 0, Endianness.LITTLE_ENDIAN);
}
void encodeInvalideHandle(int offset, bool nullable) {
if (!nullable) {
throw new MojoCodecError(
'Trying to encode a null pointer for a non-nullable type');
}
_buffer.buffer.setInt32(_base + offset, -1, Endianness.LITTLE_ENDIAN);
}
void encodePointerToNextUnclaimed(int offset) =>
encodeUint64(_buffer.extent - (_base + offset), offset);
void encodeStruct(Struct value, int offset, bool nullable) {
if (value == null) {
encodeNullPointer(offset, nullable);
return;
}
encodePointerToNextUnclaimed(offset);
value.encode(this);
}
void encodeUnion(Union value, int offset, bool nullable) {
if (value == null) {
if (!nullable) {
throw new MojoCodecError(
'Trying to encode a non-nullable null union.');
}
encodeUint64(0, offset);
encodeUint64(0, offset + 8);
return;
}
value.encode(this, offset);
}
void encodeNestedUnion(Union value, int offset, bool nullable) {
_buffer.claimMemory(align(kUnionSize));
encodePointerToNextUnclaimed(offset);
var encoder = new Encoder._fromBuffer(_buffer);
encoder.encodeUnion(value, 0, nullable);
}
Encoder encodePointerArray(int length, int offset, int expectedLength) =>
encoderForArray(kPointerSize, length, offset, expectedLength);
Encoder encodeUnionArray(int length, int offset, int expectedLength) =>
encoderForArray(kUnionSize, length, offset, expectedLength);
Encoder encoderForArray(
int elementSize, int length, int offset, int expectedLength) {
if ((expectedLength != kUnspecifiedArrayLength) &&
(expectedLength != length)) {
throw new MojoCodecError(
'Trying to encode a fixed array of incorrect length');
}
return encoderForArrayByTotalSize(length * elementSize, length, offset);
}
Encoder encoderForArrayByTotalSize(int size, int length, int offset) {
encodePointerToNextUnclaimed(offset);
return getArrayEncoderAtOffset(
new ArrayDataHeader(ArrayDataHeader.kHeaderSize + size, length));
}
void encodeBoolArray(
List<bool> value, int offset, int nullability, int expectedLength) {
if (value == null) {
encodeNullPointer(offset, isArrayNullable(nullability));
return;
}
if ((expectedLength != kUnspecifiedArrayLength) &&
(expectedLength != value.length)) {
throw new MojoCodecError(
'Trying to encode a fixed array of incorrect size.');
}
var bytes = new Uint8List((value.length + 7) ~/ kAlignment);
for (int i = 0; i < bytes.length; ++i) {
for (int j = 0; j < kAlignment; ++j) {
int boolIndex = kAlignment * i + j;
if ((boolIndex < value.length) && value[boolIndex]) {
bytes[i] |= (1 << j);
}
}
}
var encoder =
encoderForArrayByTotalSize(bytes.length, value.length, offset);
encoder.appendUint8Array(bytes);
}
void encodeArray(Function arrayAppend, int elementBytes, List<int> value,
int offset, int nullability, int expectedLength) {
if (value == null) {
encodeNullPointer(offset, isArrayNullable(nullability));
return;
}
var encoder =
encoderForArray(elementBytes, value.length, offset, expectedLength);
arrayAppend(encoder, value);
}
void encodeInt8Array(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendInt8Array(v), 1, value, offset, nullability,
expectedLength);
void encodeUint8Array(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendUint8Array(v), 1, value, offset,
nullability, expectedLength);
void encodeInt16Array(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendInt16Array(v), 2, value, offset,
nullability, expectedLength);
void encodeUint16Array(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendUint16Array(v), 2, value, offset,
nullability, expectedLength);
void encodeInt32Array(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendInt32Array(v), 4, value, offset,
nullability, expectedLength);
void encodeUint32Array(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendUint32Array(v), 4, value, offset,
nullability, expectedLength);
void encodeInt64Array(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendInt64Array(v), 8, value, offset,
nullability, expectedLength);
void encodeUint64Array(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendUint64Array(v), 8, value, offset,
nullability, expectedLength);
void encodeFloatArray(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendFloatArray(v), 4, value, offset,
nullability, expectedLength);
void encodeDoubleArray(
List<int> value, int offset, int nullability, int expectedLength) =>
encodeArray((e, v) => e.appendDoubleArray(v), 8, value, offset,
nullability, expectedLength);
void _handleArrayEncodeHelper(Function elementEncoder, List value, int offset,
int elementSize, int nullability, int expectedLength) {
if (value == null) {
encodeNullPointer(offset, isArrayNullable(nullability));
return;
}
var encoder =
encoderForArray(elementSize, value.length, offset, expectedLength);
for (int i = 0; i < value.length; ++i) {
int elementOffset = ArrayDataHeader.kHeaderSize + elementSize * i;
elementEncoder(
encoder, value[i], elementOffset, isElementNullable(nullability));
}
}
void encodeHandleArray(List<core.MojoHandle> value, int offset,
int nullability, int expectedLength) => _handleArrayEncodeHelper(
(e, v, o, n) => e.encodeHandle(v, o, n), value, offset,
kSerializedHandleSize, nullability, expectedLength);
void encodeMessagePipeHandleArray(List<core.MojoMessagePipeEndpoint> value,
int offset, int nullability, int expectedLength) =>
_handleArrayEncodeHelper(
(e, v, o, n) => e.encodeMessagePipeHandle(v, o, n), value, offset,
kSerializedHandleSize, nullability, expectedLength);
void encodeConsumerHandleArray(List<core.MojoDataPipeConsumer> value,
int offset, int nullability, int expectedLength) =>
_handleArrayEncodeHelper((e, v, o, n) => e.encodeConsumerHandle(v, o, n),
value, offset, kSerializedHandleSize, nullability, expectedLength);
void encodeProducerHandleArray(List<core.MojoDataPipeProducer> value,
int offset, int nullability, int expectedLength) =>
_handleArrayEncodeHelper((e, v, o, n) => e.encodeProducerHandle(v, o, n),
value, offset, kSerializedHandleSize, nullability, expectedLength);
void encodeSharedBufferHandleArray(List<core.MojoSharedBuffer> value,
int offset, int nullability, int expectedLength) =>
_handleArrayEncodeHelper(
(e, v, o, n) => e.encodeSharedBufferHandle(v, o, n), value, offset,
kSerializedHandleSize, nullability, expectedLength);
void encodeInterfaceRequestArray(
List<Proxy> value, int offset, int nullability, int expectedLength) =>
_handleArrayEncodeHelper(
(e, v, o, n) => e.encodeInterfaceRequest(v, o, n), value, offset,
kSerializedHandleSize, nullability, expectedLength);
void encodeInterfaceArray(
List<Stub> value, int offset, int nullability, int expectedLength) =>
_handleArrayEncodeHelper((e, v, o, n) => e.encodeInterface(v, o, n),
value, offset, kSerializedInterfaceSize, nullability, expectedLength);
static Uint8List _utf8OfString(String s) =>
(new Uint8List.fromList((const Utf8Encoder()).convert(s)));
void encodeString(String value, int offset, bool nullable) {
if (value == null) {
encodeNullPointer(offset, nullable);
return;
}
int nullability = nullable ? kArrayNullable : kNothingNullable;
encodeUint8Array(
_utf8OfString(value), offset, nullability, kUnspecifiedArrayLength);
}
void appendBytes(Uint8List value) {
_buffer.buffer.buffer
.asUint8List()
.setRange(_base + ArrayDataHeader.kHeaderSize,
_base + ArrayDataHeader.kHeaderSize + value.lengthInBytes, value);
}
void appendInt8Array(List<int> value) =>
appendBytes(new Uint8List.view(new Int8List.fromList(value).buffer));
void appendUint8Array(List<int> value) =>
appendBytes(new Uint8List.fromList(value));
void appendInt16Array(List<int> value) =>
appendBytes(new Uint8List.view(new Int16List.fromList(value).buffer));
void appendUint16Array(List<int> value) =>
appendBytes(new Uint8List.view(new Uint16List.fromList(value).buffer));
void appendInt32Array(List<int> value) =>
appendBytes(new Uint8List.view(new Int32List.fromList(value).buffer));
void appendUint32Array(List<int> value) =>
appendBytes(new Uint8List.view(new Uint32List.fromList(value).buffer));
void appendInt64Array(List<int> value) =>
appendBytes(new Uint8List.view(new Int64List.fromList(value).buffer));
void appendUint64Array(List<int> value) =>
appendBytes(new Uint8List.view(new Uint64List.fromList(value).buffer));
void appendFloatArray(List<double> value) =>
appendBytes(new Uint8List.view(new Float32List.fromList(value).buffer));
void appendDoubleArray(List<double> value) =>
appendBytes(new Uint8List.view(new Float64List.fromList(value).buffer));
Encoder encoderForMap(int offset) {
encodePointerToNextUnclaimed(offset);
return getStructEncoderAtOffset(kMapStructHeader);
}
}
class _Validator {
final int _maxMemory;
final int _numberOfHandles;
int _minNextClaimedHandle = 0;
int _minNextMemory = 0;
List<int> _skippedIndices = [];
_Validator(this._maxMemory, this._numberOfHandles);
void claimHandle(int handle) {
if (handle < _minNextClaimedHandle) {
throw new MojoCodecError('Trying to access handle out of order.');
}
if (handle >= _numberOfHandles) {
throw new MojoCodecError('Trying to access non present handle.');
}
for (int i = _minNextClaimedHandle; i < handle; i++) {
_skippedIndices.add(i);
}
_minNextClaimedHandle = handle + 1;
}
void claimMemory(int start, int end) {
if ((start % kAlignment) != 0) {
throw new MojoCodecError('Incorrect starting alignment: $start.');
}
if (start < _minNextMemory) {
throw new MojoCodecError('Trying to access memory out of order.');
}
if (end < start) {
throw new MojoCodecError('Incorrect memory range.');
}
if (end > _maxMemory) {
throw new MojoCodecError('Trying to access out of range memory.');
}
_minNextMemory = align(end);
}
}
class Decoder {
_Validator _validator;
Message _message;
int _base = 0;
Decoder(this._message, [this._base = 0, this._validator = null]) {
if (_validator == null) {
_validator = new _Validator(
_message.buffer.lengthInBytes, _message.handles.length);
}
}
Decoder getDecoderAtPosition(int offset) =>
new Decoder(_message, offset, _validator);
factory Decoder.atOffset(Decoder d, int offset, _Validator validator) =>
new Decoder(d._message, offset, validator);
ByteData get _buffer => _message.buffer;
List<core.MojoHandle> get _handles => _message.handles;
List<core.MojoHandle> get excessHandles => new List.from(_message.handles
.getRange(_validator._minNextClaimedHandle, _message.handles.length))
..addAll(_validator._skippedIndices.map((i) => _message.handles[i]));
int decodeInt8(int offset) => _buffer.getInt8(_base + offset);
int decodeUint8(int offset) => _buffer.getUint8(_base + offset);
int decodeInt16(int offset) =>
_buffer.getInt16(_base + offset, Endianness.LITTLE_ENDIAN);
int decodeUint16(int offset) =>
_buffer.getUint16(_base + offset, Endianness.LITTLE_ENDIAN);
int decodeInt32(int offset) =>
_buffer.getInt32(_base + offset, Endianness.LITTLE_ENDIAN);
int decodeUint32(int offset) =>
_buffer.getUint32(_base + offset, Endianness.LITTLE_ENDIAN);
int decodeInt64(int offset) =>
_buffer.getInt64(_base + offset, Endianness.LITTLE_ENDIAN);
int decodeUint64(int offset) =>
_buffer.getUint64(_base + offset, Endianness.LITTLE_ENDIAN);
double decodeFloat(int offset) =>
_buffer.getFloat32(_base + offset, Endianness.LITTLE_ENDIAN);
double decodeDouble(int offset) =>
_buffer.getFloat64(_base + offset, Endianness.LITTLE_ENDIAN);
bool decodeBool(int offset, int bit) =>
(decodeUint8(offset) & (1 << bit)) != 0;
core.MojoHandle decodeHandle(int offset, bool nullable) {
int index = decodeInt32(offset);
if (index == -1) {
if (!nullable) {
throw new MojoCodecError(
'Trying to decode an invalid handle from a non-nullable type.');
}
return new core.MojoHandle.invalid();
}
_validator.claimHandle(index);
return _handles[index];
}
core.MojoMessagePipeEndpoint decodeMessagePipeHandle(
int offset, bool nullable) =>
new core.MojoMessagePipeEndpoint(decodeHandle(offset, nullable));
core.MojoDataPipeConsumer decodeConsumerHandle(int offset, bool nullable) =>
new core.MojoDataPipeConsumer(decodeHandle(offset, nullable));
core.MojoDataPipeProducer decodeProducerHandle(int offset, bool nullable) =>
new core.MojoDataPipeProducer(decodeHandle(offset, nullable));
core.MojoSharedBuffer decodeSharedBufferHandle(int offset, bool nullable) =>
new core.MojoSharedBuffer(decodeHandle(offset, nullable));
ProxyBase decodeServiceInterface(
int offset, bool nullable, Function clientFactory) {
var endpoint = decodeMessagePipeHandle(offset, nullable);
var version = decodeUint32(offset + kSerializedHandleSize);
if (!endpoint.handle.isValid) {
return null;
}
ProxyBase client = clientFactory(endpoint);
client.impl._version = version;
return client;
}
Stub decodeInterfaceRequest(
int offset, bool nullable, Function interfaceFactory) {
var endpoint = decodeMessagePipeHandle(offset, nullable);
return endpoint.handle.isValid ? interfaceFactory(endpoint) : null;
}
Decoder decodePointer(int offset, bool nullable) {
int basePosition = _base + offset;
int pointerOffset = decodeUint64(offset);
if (pointerOffset == 0) {
if (!nullable) {
throw new MojoCodecError(
'Trying to decode a null pointer for a non-nullable type');
}
return null;
}
int newPosition = (basePosition + pointerOffset);
return new Decoder.atOffset(this, newPosition, _validator);
}
StructDataHeader decodeStructDataHeader() {
_validator.claimMemory(_base, _base + StructDataHeader.kHeaderSize);
int size = decodeUint32(StructDataHeader.kSizeOffset);
int version = decodeUint32(StructDataHeader.kVersionOffset);
if (size < 0) {
throw new MojoCodecError('Negative size.');
}
if (version < 0) {
throw new MojoCodecError('Negative version number.');
}
_validator.claimMemory(_base + StructDataHeader.kHeaderSize, _base + size);
return new StructDataHeader(size, version);
}
ArrayDataHeader decodeArrayDataHeader() {
_validator.claimMemory(_base, _base + ArrayDataHeader.kHeaderSize);
int size = decodeUint32(ArrayDataHeader.kSizeOffset);
int numElements = decodeUint32(ArrayDataHeader.kNumElementsOffset);
if (size < 0) {
throw new MojoCodecError('Negative size.');
}
if (numElements < 0) {
throw new MojoCodecError('Negative number of elements.');
}
_validator.claimMemory(_base + ArrayDataHeader.kHeaderSize, _base + size);
return new ArrayDataHeader(size, numElements);
}
// Decode arrays.
ArrayDataHeader decodeDataHeaderForBoolArray(int expectedLength) {
var header = decodeArrayDataHeader();
var arrayByteCount =
ArrayDataHeader.kHeaderSize + (header.numElements + 7) ~/ 8;
if (header.size < arrayByteCount) {
throw new MojoCodecError('Array header is incorrect');
}
if ((expectedLength != kUnspecifiedArrayLength) &&
(header.numElements != expectedLength)) {
throw new MojoCodecError(
'Incorrect array length. Expected $expectedLength, but got '
'${header.numElements}.');
}
return header;
}
List<bool> decodeBoolArray(int offset, int nullability, int expectedLength) {
Decoder d = decodePointer(offset, isArrayNullable(nullability));
if (d == null) {
return null;
}
var header = d.decodeDataHeaderForBoolArray(expectedLength);
var bytes = new Uint8List.view(d._buffer.buffer,
d._buffer.offsetInBytes + d._base + ArrayDataHeader.kHeaderSize,
(header.numElements + 7) ~/ kAlignment);
var result = new List<bool>(header.numElements);
for (int i = 0; i < bytes.lengthInBytes; ++i) {
for (int j = 0; j < kAlignment; ++j) {
int boolIndex = i * kAlignment + j;
if (boolIndex < result.length) {
result[boolIndex] = (bytes[i] & (1 << j)) != 0;
}
}
}
return result;
}
ArrayDataHeader decodeDataHeaderForArray(
int elementSize, int expectedLength) {
var header = decodeArrayDataHeader();
var arrayByteCount =
ArrayDataHeader.kHeaderSize + header.numElements * elementSize;
if (header.size < arrayByteCount) {
throw new MojoCodecError(
'Array header is incorrect: $header, elementSize = $elementSize');
}
if ((expectedLength != kUnspecifiedArrayLength) &&
(header.numElements != expectedLength)) {
throw new MojoCodecError(
'Incorrect array length. Expected $expectedLength, but got '
'${header.numElements}');
}
return header;
}
ArrayDataHeader decodeDataHeaderForPointerArray(int expectedLength) =>
decodeDataHeaderForArray(kPointerSize, expectedLength);
ArrayDataHeader decodeDataHeaderForUnionArray(int expectedLength) =>
decodeDataHeaderForArray(kUnionSize, expectedLength);
List decodeArray(Function arrayViewer, int elementSize, int offset,
int nullability, int expectedLength) {
Decoder d = decodePointer(offset, isArrayNullable(nullability));
if (d == null) {
return null;
}
var header = d.decodeDataHeaderForArray(elementSize, expectedLength);
return arrayViewer(d._buffer.buffer,
d._buffer.offsetInBytes + d._base + ArrayDataHeader.kHeaderSize,
header.numElements);
}
List<int> decodeInt8Array(int offset, int nullability, int expectedLength) =>
decodeArray((b, s, l) => new Int8List.view(b, s, l), 1, offset,
nullability, expectedLength);
List<int> decodeUint8Array(int offset, int nullability, int expectedLength) =>
decodeArray((b, s, l) => new Uint8List.view(b, s, l), 1, offset,
nullability, expectedLength);
List<int> decodeInt16Array(int offset, int nullability, int expectedLength) =>
decodeArray((b, s, l) => new Int16List.view(b, s, l), 2, offset,
nullability, expectedLength);
List<int> decodeUint16Array(
int offset, int nullability, int expectedLength) => decodeArray(
(b, s, l) => new Uint16List.view(b, s, l), 2, offset, nullability,
expectedLength);
List<int> decodeInt32Array(int offset, int nullability, int expectedLength) =>
decodeArray((b, s, l) => new Int32List.view(b, s, l), 4, offset,
nullability, expectedLength);
List<int> decodeUint32Array(
int offset, int nullability, int expectedLength) => decodeArray(
(b, s, l) => new Uint32List.view(b, s, l), 4, offset, nullability,
expectedLength);
List<int> decodeInt64Array(int offset, int nullability, int expectedLength) =>
decodeArray((b, s, l) => new Int64List.view(b, s, l), 8, offset,
nullability, expectedLength);
List<int> decodeUint64Array(
int offset, int nullability, int expectedLength) => decodeArray(
(b, s, l) => new Uint64List.view(b, s, l), 8, offset, nullability,
expectedLength);
List<double> decodeFloatArray(
int offset, int nullability, int expectedLength) => decodeArray(
(b, s, l) => new Float32List.view(b, s, l), 4, offset, nullability,
expectedLength);
List<double> decodeDoubleArray(
int offset, int nullability, int expectedLength) => decodeArray(
(b, s, l) => new Float64List.view(b, s, l), 8, offset, nullability,
expectedLength);
List _handleArrayDecodeHelper(Function elementDecoder, int offset,
int elementSize, int nullability, int expectedLength) {
Decoder d = decodePointer(offset, isArrayNullable(nullability));
if (d == null) {
return null;
}
var header = d.decodeDataHeaderForArray(elementSize, expectedLength);
var result = new List(header.numElements);
for (int i = 0; i < result.length; ++i) {
result[i] = elementDecoder(d,
ArrayDataHeader.kHeaderSize + elementSize * i,
isElementNullable(nullability));
}
return result;
}
List<core.MojoHandle> decodeHandleArray(
int offset, int nullability, int expectedLength) =>
_handleArrayDecodeHelper((d, o, n) => d.decodeHandle(o, n), offset,
kSerializedHandleSize, nullability, expectedLength);
List<core.MojoDataPipeConsumer> decodeConsumerHandleArray(
int offset, int nullability, int expectedLength) =>
_handleArrayDecodeHelper((d, o, n) => d.decodeConsumerHandle(o, n),
offset, kSerializedHandleSize, nullability, expectedLength);
List<core.MojoDataPipeProducer> decodeProducerHandleArray(
int offset, int nullability, int expectedLength) =>
_handleArrayDecodeHelper((d, o, n) => d.decodeProducerHandle(o, n),
offset, kSerializedHandleSize, nullability, expectedLength);
List<core.MojoMessagePipeEndpoint> decodeMessagePipeHandleArray(
int offset, int nullability, int expectedLength) =>
_handleArrayDecodeHelper((d, o, n) => d.decodeMessagePipeHandle(o, n),
offset, kSerializedHandleSize, nullability, expectedLength);
List<core.MojoSharedBuffer> decodeSharedBufferHandleArray(
int offset, int nullability, int expectedLength) =>
_handleArrayDecodeHelper((d, o, n) => d.decodeSharedBufferHandle(o, n),
offset, kSerializedHandleSize, nullability, expectedLength);
List<Stub> decodeInterfaceRequestArray(int offset, int nullability,
int expectedLength, Function interfaceFactory) =>
_handleArrayDecodeHelper(
(d, o, n) => d.decodeInterfaceRequest(o, n, interfaceFactory), offset,
kSerializedHandleSize, nullability, expectedLength);
List<Proxy> decodeServiceInterfaceArray(int offset, int nullability,
int expectedLength, Function clientFactory) => _handleArrayDecodeHelper(
(d, o, n) => d.decodeServiceInterface(o, n, clientFactory), offset,
kSerializedInterfaceSize, nullability, expectedLength);
static String _stringOfUtf8(Uint8List bytes) =>
(const Utf8Decoder()).convert(bytes.toList());
String decodeString(int offset, bool nullable) {
int nullability = nullable ? kArrayNullable : 0;
var bytes = decodeUint8Array(offset, nullability, kUnspecifiedArrayLength);
if (bytes == null) {
return null;
}
return _stringOfUtf8(bytes);
}
StructDataHeader decodeDataHeaderForMap() {
var header = decodeStructDataHeader();
if (header.size != kMapStructHeader.size) {
throw new MojoCodecError(
'Incorrect header for map. The size is incorrect.');
}
if (header.version != kMapStructHeader.version) {
throw new MojoCodecError(
'Incorrect header for map. The version is incorrect.');
}
return header;
}
}

@ -1,60 +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 bindings;
// Handles InterfaceControlMessages for a stub.
class ControlMessageHandler {
static bool isControlMessage(ServiceMessage message) =>
_isRun(message) || _isRunOrClose(message);
static bool _isRun(ServiceMessage message) =>
(message.header.type == icm.kRunMessageId);
static bool _isRunOrClose(ServiceMessage message) =>
(message.header.type == icm.kRunOrClosePipeMessageId);
static Future<Message> handleMessage(Stub stub,
int interface_version,
ServiceMessage message) {
assert(isControlMessage(message));
if (_isRun(message)) {
return _handleRun(stub, interface_version, message);
} else {
assert(_isRunOrClose(message));
return _handleRunOrClose(stub, interface_version, message);
}
}
static Future<Message> _handleRun(Stub stub,
int interface_version,
ServiceMessage message) {
// Construct RunMessage response.
var response = new icm.RunResponseMessageParams();
response.reserved0 = 16;
response.reserved1 = 0;
response.queryVersionResult = new icm.QueryVersionResult();
response.queryVersionResult.version = interface_version;
// Return response.
return new Future.value(
stub.buildResponseWithId(response,
icm.kRunMessageId,
message.header.requestId,
MessageHeader.kMessageIsResponse));
}
static Future _handleRunOrClose(Stub stub,
int interface_version,
ServiceMessage message) {
// Deserialize message.
var params = icm.RunOrClosePipeMessageParams.deserialize(message.payload);
// Grab required version.
var requiredVersion = params.requireVersion.version;
if (interface_version < requiredVersion) {
// Stub does not implement required version. Close the pipe immediately.
stub.close(immediate: true);
}
return null;
}
}

@ -1,167 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of core;
class MojoDataPipeProducer {
static const int FLAG_NONE = 0;
static const int FLAG_ALL_OR_NONE = 1 << 0;
MojoHandle handle;
MojoResult status;
final int elementBytes;
MojoDataPipeProducer(this.handle,
[this.status = MojoResult.OK, this.elementBytes = 1]);
int write(ByteData data, [int numBytes = -1, int flags = 0]) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return 0;
}
int data_numBytes = (numBytes == -1) ? data.lengthInBytes : numBytes;
List result =
MojoDataPipeNatives.MojoWriteData(handle.h, data, data_numBytes, flags);
if (result == null) {
status = MojoResult.INVALID_ARGUMENT;
return 0;
}
assert((result is List) && (result.length == 2));
status = new MojoResult(result[0]);
return result[1];
}
ByteData beginWrite(int bufferBytes, [int flags = 0]) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return null;
}
List result =
MojoDataPipeNatives.MojoBeginWriteData(handle.h, bufferBytes, flags);
if (result == null) {
status = MojoResult.INVALID_ARGUMENT;
return null;
}
assert((result is List) && (result.length == 2));
status = new MojoResult(result[0]);
return result[1];
}
MojoResult endWrite(int bytesWritten) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return status;
}
int result = MojoDataPipeNatives.MojoEndWriteData(handle.h, bytesWritten);
status = new MojoResult(result);
return status;
}
String toString() => "MojoDataPipeProducer(handle: $handle, status: $status)";
}
class MojoDataPipeConsumer {
static const int FLAG_NONE = 0;
static const int FLAG_ALL_OR_NONE = 1 << 0;
static const int FLAG_DISCARD = 1 << 1;
static const int FLAG_QUERY = 1 << 2;
static const int FLAG_PEEK = 1 << 3;
MojoHandle handle;
MojoResult status;
final int elementBytes;
MojoDataPipeConsumer(this.handle,
[this.status = MojoResult.OK, this.elementBytes = 1]);
int read(ByteData data, [int numBytes = -1, int flags = 0]) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return 0;
}
int data_numBytes = (numBytes == -1) ? data.lengthInBytes : numBytes;
List result =
MojoDataPipeNatives.MojoReadData(handle.h, data, data_numBytes, flags);
if (result == null) {
status = MojoResult.INVALID_ARGUMENT;
return 0;
}
assert((result is List) && (result.length == 2));
status = new MojoResult(result[0]);
return result[1];
}
ByteData beginRead([int bufferBytes = 0, int flags = 0]) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return null;
}
List result =
MojoDataPipeNatives.MojoBeginReadData(handle.h, bufferBytes, flags);
if (result == null) {
status = MojoResult.INVALID_ARGUMENT;
return null;
}
assert((result is List) && (result.length == 2));
status = new MojoResult(result[0]);
return result[1];
}
MojoResult endRead(int bytesRead) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return status;
}
int result = MojoDataPipeNatives.MojoEndReadData(handle.h, bytesRead);
status = new MojoResult(result);
return status;
}
int query() => read(null, 0, FLAG_QUERY);
String toString() => "MojoDataPipeConsumer("
"handle: $handle, status: $status, available: ${query()})";
}
class MojoDataPipe {
static const int FLAG_NONE = 0;
static const int DEFAULT_ELEMENT_SIZE = 1;
static const int DEFAULT_CAPACITY = 0;
MojoDataPipeProducer producer;
MojoDataPipeConsumer consumer;
MojoResult status;
MojoDataPipe._internal() {
producer = null;
consumer = null;
status = MojoResult.OK;
}
factory MojoDataPipe([int elementBytes = DEFAULT_ELEMENT_SIZE,
int capacityBytes = DEFAULT_CAPACITY, int flags = FLAG_NONE]) {
List result = MojoDataPipeNatives.MojoCreateDataPipe(
elementBytes, capacityBytes, flags);
if (result == null) {
return null;
}
assert((result is List) && (result.length == 3));
MojoHandle producerHandle = new MojoHandle(result[1]);
MojoHandle consumerHandle = new MojoHandle(result[2]);
MojoDataPipe pipe = new MojoDataPipe._internal();
pipe.producer = new MojoDataPipeProducer(
producerHandle, new MojoResult(result[0]), elementBytes);
pipe.consumer = new MojoDataPipeConsumer(
consumerHandle, new MojoResult(result[0]), elementBytes);
pipe.status = new MojoResult(result[0]);
return pipe;
}
}

@ -1,72 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of core;
class DataPipeDrainer {
MojoDataPipeConsumer _consumer;
MojoEventStream _eventStream;
List<ByteData> _dataList;
int _dataSize;
DataPipeDrainer(this._consumer) {
_eventStream = new MojoEventStream(_consumer.handle);
_dataList = new List();
_dataSize = 0;
}
ByteData _copy(ByteData byteData) =>
new ByteData.view(
new Uint8List.fromList(byteData.buffer.asUint8List()).buffer);
MojoResult _doRead() {
ByteData thisRead = _consumer.beginRead();
if (thisRead == null) {
throw 'Data pipe beginRead failed: ${_consumer.status}';
}
_dataList.add(_copy(thisRead));
_dataSize += thisRead.lengthInBytes;
return _consumer.endRead(thisRead.lengthInBytes);
}
ByteData _concatData() {
var data = new ByteData(_dataSize);
int end = 0;
for (var chunk in _dataList) {
data.buffer.asUint8List().setRange(
end, end + chunk.lengthInBytes, chunk.buffer.asUint8List());
end += chunk.lengthInBytes;
}
return data;
}
Future<ByteData> drain() {
var completer = new Completer();
_eventStream.listen((List<int> event) {
var mojoSignals = new MojoHandleSignals(event[1]);
if (mojoSignals.isReadable) {
var result = _doRead();
if (!result.isOk) {
_eventStream.close();
_eventStream = null;
completer.complete(_concatData());
} else {
_eventStream.enableReadEvents();
}
} else if (mojoSignals.isPeerClosed) {
_eventStream.close();
_eventStream = null;
completer.complete(_concatData());
} else {
throw 'Unexpected handle event: $mojoSignals';
}
});
return completer.future;
}
static Future<ByteData> drainHandle(MojoDataPipeConsumer consumer) {
var drainer = new DataPipeDrainer(consumer);
return drainer.drain();
}
}

@ -1,249 +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.
part of core;
class MojoEventStream extends Stream<List<int>> {
// The underlying Mojo handle.
MojoHandle _handle;
// Providing our own stream controller allows us to take custom actions when
// listeners pause/resume/etc. their StreamSubscription.
StreamController _controller;
// The send port that we give to the handle watcher to notify us of handle
// events.
SendPort _sendPort;
// The receive port on which we listen and receive events from the handle
// watcher.
ReceivePort _receivePort;
// The signals on this handle that we're interested in.
MojoHandleSignals _signals;
// Whether listen has been called.
bool _isListening;
MojoEventStream(MojoHandle handle,
[MojoHandleSignals signals = MojoHandleSignals.PEER_CLOSED_READABLE])
: _handle = handle,
_signals = signals,
_isListening = false {
MojoResult result = MojoHandle.register(this);
if (!result.isOk) {
throw "Failed to register the MojoHandle: $result.";
}
}
Future close({bool immediate: false}) {
if (_handle != null) {
if (_isListening) {
return _handleWatcherClose(immediate: immediate);
} else {
_localClose();
}
}
return new Future.value(null);
}
StreamSubscription<List<int>> listen(void onData(List event),
{Function onError, void onDone(), bool cancelOnError}) {
if (_isListening) {
throw "Listen has already been called: $_handle.";
}
_receivePort = new ReceivePort();
_sendPort = _receivePort.sendPort;
_controller = new StreamController(
sync: true,
onListen: _onSubscriptionStateChange,
onCancel: _onSubscriptionStateChange,
onPause: _onPauseStateChange,
onResume: _onPauseStateChange);
_controller.addStream(_receivePort).whenComplete(_controller.close);
if (_signals != MojoHandleSignals.NONE) {
var res = new MojoResult(
MojoHandleWatcher.add(_handle.h, _sendPort, _signals.value));
if (!res.isOk) {
throw "MojoHandleWatcher add failed: $res";
}
}
_isListening = true;
return _controller.stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
}
void enableSignals(MojoHandleSignals signals) {
_signals = signals;
if (_isListening) {
var res = new MojoResult(
MojoHandleWatcher.add(_handle.h, _sendPort, signals.value));
if (!res.isOk) {
throw "MojoHandleWatcher add failed: $res";
}
}
}
void enableReadEvents() =>
enableSignals(MojoHandleSignals.PEER_CLOSED_READABLE);
void enableWriteEvents() => enableSignals(MojoHandleSignals.WRITABLE);
void enableAllEvents() => enableSignals(MojoHandleSignals.READWRITE);
Future _handleWatcherClose({bool immediate: false}) {
assert(_handle != null);
assert(MojoHandle._removeUnclosedHandle(_handle));
return MojoHandleWatcher.close(_handle.h, wait: !immediate).then((r) {
if (_receivePort != null) {
_receivePort.close();
_receivePort = null;
}
return new MojoResult(r);
});
}
void _localClose() {
assert(_handle != null);
_handle.close();
_handle = null;
if (_receivePort != null) {
_receivePort.close();
_receivePort = null;
}
}
void _onSubscriptionStateChange() {
if (!_controller.hasListener) {
// No one is listening, close it immediately.
close(immediate: true);
}
}
void _onPauseStateChange() {
if (_controller.isPaused) {
var res = new MojoResult(MojoHandleWatcher.remove(_handle.h));
if (!res.isOk) {
throw "MojoHandleWatcher add failed: $res";
}
} else {
var res = new MojoResult(
MojoHandleWatcher.add(_handle.h, _sendPort, _signals.value));
if (!res.isOk) {
throw "MojoHandleWatcher add failed: $res";
}
}
}
bool get readyRead => _handle.readyRead;
bool get readyWrite => _handle.readyWrite;
String toString() => "$_handle";
}
typedef void ErrorHandler();
class MojoEventStreamListener {
MojoMessagePipeEndpoint _endpoint;
MojoEventStream _eventStream;
bool _isOpen = false;
bool _isInHandler = false;
StreamSubscription subscription;
ErrorHandler onError;
MojoEventStreamListener.fromEndpoint(MojoMessagePipeEndpoint endpoint)
: _endpoint = endpoint,
_eventStream = new MojoEventStream(endpoint.handle),
_isOpen = false {
listen();
}
MojoEventStreamListener.fromHandle(MojoHandle handle) {
_endpoint = new MojoMessagePipeEndpoint(handle);
_eventStream = new MojoEventStream(handle);
_isOpen = false;
listen();
}
MojoEventStreamListener.unbound()
: _endpoint = null,
_eventStream = null,
_isOpen = false;
void bind(MojoMessagePipeEndpoint endpoint) {
assert(!isBound);
_endpoint = endpoint;
_eventStream = new MojoEventStream(endpoint.handle);
_isOpen = false;
}
void bindFromHandle(MojoHandle handle) {
assert(!isBound);
_endpoint = new MojoMessagePipeEndpoint(handle);
_eventStream = new MojoEventStream(handle);
_isOpen = false;
}
StreamSubscription<List<int>> listen() {
assert(isBound && (subscription == null));
_isOpen = true;
subscription = _eventStream.listen((List<int> event) {
if (!_isOpen) {
// The actual close of the underlying stream happens asynchronously
// after the call to close. However, we start to ignore incoming events
// immediately.
return;
}
var signalsWatched = new MojoHandleSignals(event[0]);
var signalsReceived = new MojoHandleSignals(event[1]);
_isInHandler = true;
if (signalsReceived.isReadable) {
assert(_eventStream.readyRead);
handleRead();
}
if (signalsReceived.isWritable) {
assert(_eventStream.readyWrite);
handleWrite();
}
if (!signalsReceived.isPeerClosed) {
_eventStream.enableSignals(signalsWatched);
}
_isInHandler = false;
if (signalsReceived.isPeerClosed) {
// immediate is true here because there is no need to wait to close
// until outstanding messages are sent. The other side is gone.
close(immediate: true).then((_) {
if (onError != null) {
onError();
}
});
}
}, onDone: close);
return subscription;
}
Future close({bool immediate: false}) {
var result;
_isOpen = false;
_endpoint = null;
subscription = null;
if (_eventStream != null) {
result = _eventStream.close(immediate: immediate).then((_) {
_eventStream = null;
});
}
return result != null ? result : new Future.value(null);
}
void handleRead() {}
void handleWrite() {}
MojoMessagePipeEndpoint get endpoint => _endpoint;
bool get isOpen => _isOpen;
bool get isInHandler => _isInHandler;
bool get isBound => _endpoint != null;
String toString() => "MojoEventStreamListener("
"isOpen: $isOpen, isBound: $isBound, endpoint: $_endpoint)";
}

@ -1,144 +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.
part of core;
class _HandleCreationRecord {
final MojoHandle handle;
final StackTrace stack;
String description;
_HandleCreationRecord(this.handle, this.stack, {this.description});
}
class MojoHandle {
static const int INVALID = 0;
static const int DEADLINE_INDEFINITE = -1;
int _h;
int get h => _h;
MojoHandle(this._h, {String description}) {
assert(_addUnclosedHandle(this, description: description));
}
MojoHandle._internal(this._h);
MojoHandle.invalid() : this._internal(INVALID);
MojoResult close() {
assert(_removeUnclosedHandle(this));
int result = MojoHandleNatives.close(_h);
_h = INVALID;
return new MojoResult(result);
}
MojoHandle pass() {
assert(_removeUnclosedHandle(this));
return this;
}
MojoWaitResult wait(int signals, int deadline) {
List result = MojoHandleNatives.wait(h, signals, deadline);
var state = result[1] != null
? new MojoHandleSignalsState(result[1][0], result[1][1])
: null;
return new MojoWaitResult(new MojoResult(result[0]), state);
}
bool _ready(MojoHandleSignals signal) {
MojoWaitResult mwr = wait(signal.value, 0);
switch (mwr.result) {
case MojoResult.OK:
return true;
case MojoResult.DEADLINE_EXCEEDED:
case MojoResult.CANCELLED:
case MojoResult.INVALID_ARGUMENT:
case MojoResult.FAILED_PRECONDITION:
return false;
default:
// Should be unreachable.
throw "Unexpected result $mwr for wait on $h";
}
}
void _set(int value) {
_h = value;
}
bool get readyRead => _ready(MojoHandleSignals.PEER_CLOSED_READABLE);
bool get readyWrite => _ready(MojoHandleSignals.WRITABLE);
bool get isValid => (_h != INVALID);
String toString() {
if (!isValid) {
return "MojoHandle(INVALID)";
}
var mwr = wait(MojoHandleSignals.kAll, 0);
return "MojoHandle(h: $h, status: $mwr)";
}
bool operator ==(MojoHandle other) {
return _h == other._h;
}
static MojoWaitManyResult waitMany(
List<int> handles, List<int> signals, int deadline) {
List result = MojoHandleNatives.waitMany(handles, signals, deadline);
List states = result[2] != null
? result[2].map((l) => new MojoHandleSignalsState(l[0], l[1])).toList()
: null;
return new MojoWaitManyResult(new MojoResult(result[0]), result[1], states);
}
static MojoResult register(MojoEventStream eventStream) {
return new MojoResult(
MojoHandleNatives.register(eventStream, eventStream._handle.h));
}
static HashMap<int, _HandleCreationRecord> _unclosedHandles = new HashMap();
// _addUnclosedHandle(), _removeUnclosedHandle(), and dumpLeakedHandles()
// should only be used inside of assert() statements.
static bool _addUnclosedHandle(MojoHandle handle, {String description}) {
var stack;
try {
assert(false);
} catch (_, s) {
stack = s;
}
var handleCreate = new _HandleCreationRecord(
handle, stack, description: description);
_unclosedHandles[handle.h] = handleCreate;
return true;
}
static bool _setHandleLeakDescription(MojoHandle handle, String description) {
if (_unclosedHandles.containsKey(handle.h)) {
_unclosedHandles[handle.h].description = description;
}
return true;
}
static bool _removeUnclosedHandle(MojoHandle handle) {
_unclosedHandles.remove(handle._h);
return true;
}
static bool reportLeakedHandles() {
var noleaks = true;
for (var handle in MojoHandle._unclosedHandles.keys) {
var handleCreation = MojoHandle._unclosedHandles[handle];
if (handleCreation != null) {
print("HANDLE LEAK: handle: $handle");
if (handleCreation.description != null) {
print("HANDLE LEAK: message: ${handleCreation.description}");
}
print("HANDLE LEAK: stack at creation:\n${handleCreation.stack}");
noleaks = false;
}
}
return noleaks;
}
}

@ -1,127 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of bindings;
class MessageHeader {
static const int kSimpleMessageSize = 16;
static const int kSimpleMessageVersion = 0;
static const int kMessageWithRequestIdSize = 24;
static const int kMessageWithRequestIdVersion = 1;
static const int kMessageTypeOffset = StructDataHeader.kHeaderSize;
static const int kMessageFlagsOffset = kMessageTypeOffset + 4;
static const int kMessageRequestIdOffset = kMessageFlagsOffset + 4;
static const int kMessageExpectsResponse = 1 << 0;
static const int kMessageIsResponse = 1 << 1;
StructDataHeader _header;
int type;
int flags;
int requestId;
static bool mustHaveRequestId(int flags) =>
(flags & (kMessageExpectsResponse | kMessageIsResponse)) != 0;
MessageHeader(this.type)
: _header = new StructDataHeader(
kSimpleMessageSize, kSimpleMessageVersion),
flags = 0,
requestId = 0;
MessageHeader.withRequestId(this.type, this.flags, this.requestId)
: _header = new StructDataHeader(
kMessageWithRequestIdSize, kMessageWithRequestIdVersion);
MessageHeader.fromMessage(Message message) {
var decoder = new Decoder(message);
_header = decoder.decodeStructDataHeader();
if (_header.size < kSimpleMessageSize) {
throw new MojoCodecError('Incorrect message size. Got: ${_header.size} '
'wanted $kSimpleMessageSize');
}
type = decoder.decodeUint32(kMessageTypeOffset);
flags = decoder.decodeUint32(kMessageFlagsOffset);
if (mustHaveRequestId(flags)) {
if (_header.size < kMessageWithRequestIdSize) {
throw new MojoCodecError('Incorrect message size. Got: ${_header.size} '
'wanted $kMessageWithRequestIdSize');
}
requestId = decoder.decodeUint64(kMessageRequestIdOffset);
} else {
requestId = 0;
}
}
int get size => _header.size;
bool get hasRequestId => mustHaveRequestId(flags);
void encode(Encoder encoder) {
encoder.encodeStructDataHeader(_header);
encoder.encodeUint32(type, kMessageTypeOffset);
encoder.encodeUint32(flags, kMessageFlagsOffset);
if (hasRequestId) {
encoder.encodeUint64(requestId, kMessageRequestIdOffset);
}
}
String toString() => "MessageHeader($_header, $type, $flags, $requestId)";
bool validateHeaderFlags(expectedFlags) =>
(flags & (kMessageExpectsResponse | kMessageIsResponse)) == expectedFlags;
bool validateHeader(int expectedType, int expectedFlags) =>
(type == expectedType) && validateHeaderFlags(expectedFlags);
static void _validateDataHeader(StructDataHeader dataHeader) {
if (dataHeader.version < kSimpleMessageVersion) {
throw 'Incorrect version, expecting at least '
'$kSimpleMessageVersion, but got: ${dataHeader.version}.';
}
if (dataHeader.size < kSimpleMessageSize) {
throw 'Incorrect message size, expecting at least $kSimpleMessageSize, '
'but got: ${dataHeader.size}';
}
if ((dataHeader.version == kSimpleMessageVersion) &&
(dataHeader.size != kSimpleMessageSize)) {
throw 'Incorrect message size for a message of version '
'$kSimpleMessageVersion, expecting $kSimpleMessageSize, '
'but got ${dataHeader.size}';
}
if ((dataHeader.version == kMessageWithRequestIdVersion) &&
(dataHeader.size != kMessageWithRequestIdSize)) {
throw 'Incorrect message size for a message of version '
'$kMessageWithRequestIdVersion, expecting '
'$kMessageWithRequestIdSize, but got ${dataHeader.size}';
}
}
}
class Message {
final ByteData buffer;
final List<core.MojoHandle> handles;
Message(this.buffer, this.handles);
String toString() =>
"Message(numBytes=${buffer.lengthInBytes}, numHandles=${handles.length})";
}
class ServiceMessage extends Message {
final MessageHeader header;
Message _payload;
ServiceMessage(Message message, this.header)
: super(message.buffer, message.handles);
ServiceMessage.fromMessage(Message message)
: this(message, new MessageHeader.fromMessage(message));
Message get payload {
if (_payload == null) {
var truncatedBuffer = new ByteData.view(buffer.buffer, header.size);
_payload = new Message(truncatedBuffer, handles);
}
return _payload;
}
String toString() => "ServiceMessage($header, $_payload)";
}

@ -1,153 +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.
part of core;
class MojoMessagePipeReadResult {
final MojoResult status;
final int bytesRead;
final int handlesRead;
MojoMessagePipeReadResult(this.status, this.bytesRead, this.handlesRead);
MojoMessagePipeReadResult.fromList(List<int> resultList)
: this(new MojoResult(resultList[0]), resultList[1], resultList[2]);
String toString() {
return "MojoMessagePipeReadResult("
"status: $status, bytesRead: $bytesRead, handlesRead: $handlesRead)";
}
}
class MojoMessagePipeEndpoint {
static const int WRITE_FLAG_NONE = 0;
static const int READ_FLAG_NONE = 0;
static const int READ_FLAG_MAY_DISCARD = 1 << 0;
MojoHandle handle;
MojoResult status;
MojoMessagePipeEndpoint(this.handle);
MojoResult write(ByteData data,
[int numBytes = -1, List<MojoHandle> handles = null, int flags = 0]) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return status;
}
int dataLengthInBytes = (data == null) ? 0 : data.lengthInBytes;
// If numBytes has the default value, use the full length of the data.
int dataNumBytes = (numBytes == -1) ? dataLengthInBytes : numBytes;
if (dataNumBytes > dataLengthInBytes) {
status = MojoResult.INVALID_ARGUMENT;
return status;
}
// handles may be null, otherwise convert to ints.
List<int> mojoHandles =
(handles != null) ? handles.map((h) => h.h).toList() : null;
// Do the call.
int result = MojoMessagePipeNatives.MojoWriteMessage(
handle.h, data, dataNumBytes, mojoHandles, flags);
status = new MojoResult(result);
return status;
}
MojoMessagePipeReadResult read(ByteData data,
[int numBytes = -1, List<MojoHandle> handles = null, int flags = 0]) {
if (handle == null) {
status = MojoResult.INVALID_ARGUMENT;
return null;
}
// If numBytes has the default value, use the full length of the data.
int dataNumBytes;
if (data == null) {
dataNumBytes = 0;
} else {
dataNumBytes = (numBytes == -1) ? data.lengthInBytes : numBytes;
if (dataNumBytes > data.lengthInBytes) {
status = MojoResult.INVALID_ARGUMENT;
return null;
}
}
// handles may be null, otherwise make an int list for the handles.
List<int> mojoHandles;
if (handles == null) {
mojoHandles = null;
} else {
mojoHandles = new List<int>(handles.length);
}
// Do the call.
List result = MojoMessagePipeNatives.MojoReadMessage(
handle.h, data, dataNumBytes, mojoHandles, flags);
if (result == null) {
status = MojoResult.INVALID_ARGUMENT;
return null;
}
assert((result is List) && (result.length == 3));
var readResult = new MojoMessagePipeReadResult.fromList(result);
// Copy out the handles that were read.
if (handles != null) {
for (var i = 0; i < readResult.handlesRead; i++) {
handles[i] = new MojoHandle(mojoHandles[i]);
}
}
status = readResult.status;
return readResult;
}
MojoMessagePipeReadResult query() => read(null);
bool setDescription(String description) {
assert(MojoHandle._setHandleLeakDescription(handle, description));
return true;
}
void close() {
handle.close();
handle = null;
}
String toString() =>
"MojoMessagePipeEndpoint(handle: $handle, status: $status)";
}
class MojoMessagePipe {
static const int FLAG_NONE = 0;
List<MojoMessagePipeEndpoint> endpoints;
MojoResult status;
MojoMessagePipe._() {
endpoints = null;
status = MojoResult.OK;
}
factory MojoMessagePipe([int flags = FLAG_NONE]) {
List result = MojoMessagePipeNatives.MojoCreateMessagePipe(flags);
if (result == null) {
return null;
}
assert((result is List) && (result.length == 3));
MojoHandle end1 = new MojoHandle(result[1]);
MojoHandle end2 = new MojoHandle(result[2]);
MojoMessagePipe pipe = new MojoMessagePipe._();
pipe.endpoints = new List(2);
pipe.endpoints[0] = new MojoMessagePipeEndpoint(end1);
pipe.endpoints[1] = new MojoMessagePipeEndpoint(end2);
pipe.status = new MojoResult(result[0]);
return pipe;
}
}

@ -1,170 +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.
part of bindings;
class ProxyCloseException {
final String message;
ProxyCloseException(this.message);
String toString() => message;
}
abstract class Proxy extends core.MojoEventStreamListener {
Map<int, Completer> _completerMap;
int _nextId = 0;
int _version = 0;
/// Version of this interface that the remote side supports. Updated when a
/// call to [queryVersion] or [requireVersion] is made.
int get version => _version;
Proxy.fromEndpoint(core.MojoMessagePipeEndpoint endpoint)
: _completerMap = {},
super.fromEndpoint(endpoint);
Proxy.fromHandle(core.MojoHandle handle)
: _completerMap = {},
super.fromHandle(handle);
Proxy.unbound()
: _completerMap = {},
super.unbound();
void handleResponse(ServiceMessage reader);
void handleRead() {
// Query how many bytes are available.
var result = endpoint.query();
assert(result.status.isOk || result.status.isResourceExhausted);
// Read the data.
var bytes = new ByteData(result.bytesRead);
var handles = new List<core.MojoHandle>(result.handlesRead);
result = endpoint.read(bytes, result.bytesRead, handles);
assert(result.status.isOk || result.status.isResourceExhausted);
var message = new ServiceMessage.fromMessage(new Message(bytes, handles));
if (ControlMessageHandler.isControlMessage(message)) {
_handleControlMessageResponse(message);
return;
}
handleResponse(message);
}
void handleWrite() {
throw 'Unexpected write signal in proxy.';
}
@override
Future close({bool immediate: false}) {
for (var completer in _completerMap.values) {
completer.completeError(new ProxyCloseException('Proxy closed'));
}
_completerMap.clear();
return super.close(immediate: immediate);
}
void sendMessage(Struct message, int name) {
if (!isOpen) {
listen();
}
var header = new MessageHeader(name);
var serviceMessage = message.serializeWithHeader(header);
endpoint.write(serviceMessage.buffer,
serviceMessage.buffer.lengthInBytes, serviceMessage.handles);
if (!endpoint.status.isOk) {
throw "message pipe write failed - ${endpoint.status}";
}
}
Future sendMessageWithRequestId(Struct message, int name, int id, int flags) {
if (!isOpen) {
listen();
}
if (id == -1) {
id = _nextId++;
}
var header = new MessageHeader.withRequestId(name, flags, id);
var serviceMessage = message.serializeWithHeader(header);
endpoint.write(serviceMessage.buffer,
serviceMessage.buffer.lengthInBytes, serviceMessage.handles);
if (!endpoint.status.isOk) {
throw "message pipe write failed - ${endpoint.status}";
}
var completer = new Completer();
_completerMap[id] = completer;
return completer.future;
}
// Need a getter for this for access in subclasses.
Map<int, Completer> get completerMap => _completerMap;
String toString() {
var superString = super.toString();
return "Proxy(${superString})";
}
/// Queries the max version that the remote side supports.
/// Updates [version].
Future<int> queryVersion() async {
var params = new icm.RunMessageParams();
params.reserved0 = 16;
params.reserved1 = 0;
params.queryVersion = new icm.QueryVersion();
var response = await
sendMessageWithRequestId(params,
icm.kRunMessageId,
-1,
MessageHeader.kMessageExpectsResponse);
_version = response.queryVersionResult.version;
return _version;
}
/// If the remote side doesn't support the [requiredVersion], it will close
/// its end of the message pipe asynchronously. This does nothing if it's
/// already known that the remote side supports [requiredVersion].
/// Updates [version].
void requireVersion(int requiredVersion) {
if (requiredVersion <= _version) {
// Already supported.
return;
}
// If the remote end doesn't close the pipe, we know that it supports
// required version.
_version = requiredVersion;
var params = new icm.RunOrClosePipeMessageParams();
params.reserved0 = 16;
params.reserved1 = 0;
params.requireVersion = new icm.RequireVersion();
params.requireVersion.version = requiredVersion;
// TODO(johnmccutchan): We've set _version above but if this sendMessage
// throws an exception we may not have sent the RunOrClose message. Should
// we reset _version in that case?
sendMessage(params, icm.kRunOrClosePipeMessageId);
}
_handleControlMessageResponse(ServiceMessage message) {
// We only expect to see Run messages.
assert(message.header.type == icm.kRunMessageId);
var response = icm.RunResponseMessageParams.deserialize(message.payload);
if (!message.header.hasRequestId) {
throw 'Expected a message with a valid request Id.';
}
Completer c = completerMap[message.header.requestId];
if (c == null) {
throw 'Message had unknown request Id: ${message.header.requestId}';
}
completerMap.remove(message.header.requestId);
assert(!c.isCompleted);
c.complete(response);
}
}
// Generated Proxy classes implement this interface.
abstract class ProxyBase {
final Proxy impl = null;
final String name = null;
}

@ -1,26 +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.
part of bindings;
abstract class Struct {
final int encodedSize;
Struct(this.encodedSize);
void encode(Encoder encoder);
Message serialize() {
var encoder = new Encoder(encodedSize);
encode(encoder);
return encoder.message;
}
ServiceMessage serializeWithHeader(MessageHeader header) {
var encoder = new Encoder(encodedSize + header.size);
header.encode(encoder);
encode(encoder);
return new ServiceMessage(encoder.message, header);
}
}

@ -1,130 +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.
part of bindings;
abstract class Stub extends core.MojoEventStreamListener {
int _outstandingResponseFutures = 0;
bool _isClosing = false;
Completer _closeCompleter;
Stub.fromEndpoint(core.MojoMessagePipeEndpoint endpoint)
: super.fromEndpoint(endpoint);
Stub.fromHandle(core.MojoHandle handle) : super.fromHandle(handle);
Stub.unbound() : super.unbound();
Future<Message> handleMessage(ServiceMessage message);
void handleRead() {
// Query how many bytes are available.
var result = endpoint.query();
assert(result.status.isOk || result.status.isResourceExhausted);
if (result.bytesRead == 0) {
throw new MojoCodecError('Unexpected empty message.');
}
// Read the data and view as a message.
var bytes = new ByteData(result.bytesRead);
var handles = new List<core.MojoHandle>(result.handlesRead);
result = endpoint.read(bytes, result.bytesRead, handles);
assert(result.status.isOk || result.status.isResourceExhausted);
// Prepare the response.
var message;
var responseFuture;
try {
message = new ServiceMessage.fromMessage(new Message(bytes, handles));
responseFuture = _isClosing ? null : handleMessage(message);
} catch (e, s) {
handles.forEach((h) => h.close());
rethrow;
}
// If there's a response, send it.
if (responseFuture != null) {
_outstandingResponseFutures++;
responseFuture.then((response) {
_outstandingResponseFutures--;
if (isOpen) {
endpoint.write(
response.buffer, response.buffer.lengthInBytes, response.handles);
// FailedPrecondition is only used to indicate that the other end of
// the pipe has been closed. We can ignore the close here and wait for
// the PeerClosed signal on the event stream.
assert(endpoint.status.isOk || endpoint.status.isFailedPrecondition);
if (_isClosing && (_outstandingResponseFutures == 0)) {
// This was the final response future for which we needed to send
// a response. It is safe to close.
super.close().then((_) {
if (_isClosing) {
_isClosing = false;
_closeCompleter.complete(null);
_closeCompleter = null;
}
});
}
}
});
} else if (_isClosing && (_outstandingResponseFutures == 0)) {
// We are closing, there is no response to send for this message, and
// there are no outstanding response futures. Do the close now.
super.close().then((_) {
if (_isClosing) {
_isClosing = false;
_closeCompleter.complete(null);
_closeCompleter = null;
}
});
}
}
void handleWrite() {
throw 'Unexpected write signal in client.';
}
// NB: |immediate| should only be true when calling close() while handling an
// exception thrown from handleRead(), e.g. when we receive a malformed
// message, or when we have received the PEER_CLOSED event.
@override
Future close({bool immediate: false}) {
if (isOpen &&
!immediate &&
(isInHandler || (_outstandingResponseFutures > 0))) {
// Either close() is being called from within handleRead() or
// handleWrite(), or close() is being called while there are outstanding
// response futures. Defer the actual close until all response futures
// have been resolved.
_isClosing = true;
_closeCompleter = new Completer();
return _closeCompleter.future;
} else {
return super.close(immediate: immediate).then((_) {
if (_isClosing) {
_isClosing = false;
_closeCompleter.complete(null);
_closeCompleter = null;
}
});
}
}
Message buildResponse(Struct response, int name) {
var header = new MessageHeader(name);
return response.serializeWithHeader(header);
}
Message buildResponseWithId(Struct response, int name, int id, int flags) {
var header = new MessageHeader.withRequestId(name, flags, id);
return response.serializeWithHeader(header);
}
String toString() {
var superString = super.toString();
return "Stub(${superString})";
}
int get version;
}

@ -1,260 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of core;
class MojoResult {
static const int kOk = 0;
static const int kCancelled = 1;
static const int kUnknown = 2;
static const int kInvalidArgument = 3;
static const int kDeadlineExceeded = 4;
static const int kNotFound = 5;
static const int kAlreadyExists = 6;
static const int kPermissionDenied = 7;
static const int kResourceExhausted = 8;
static const int kFailedPrecondition = 9;
static const int kAborted = 10;
static const int kOutOfRange = 11;
static const int kUnimplemented = 12;
static const int kInternal = 13;
static const int kUnavailable = 14;
static const int kDataLoss = 15;
static const int kBusy = 16;
static const int kShouldWait = 17;
static const OK = const MojoResult._(kOk);
static const CANCELLED = const MojoResult._(kCancelled);
static const UNKNOWN = const MojoResult._(kUnknown);
static const INVALID_ARGUMENT = const MojoResult._(kInvalidArgument);
static const DEADLINE_EXCEEDED = const MojoResult._(kDeadlineExceeded);
static const NOT_FOUND = const MojoResult._(kNotFound);
static const ALREADY_EXISTS = const MojoResult._(kAlreadyExists);
static const PERMISSION_DENIED = const MojoResult._(kPermissionDenied);
static const RESOURCE_EXHAUSTED = const MojoResult._(kResourceExhausted);
static const FAILED_PRECONDITION = const MojoResult._(kFailedPrecondition);
static const ABORTED = const MojoResult._(kAborted);
static const OUT_OF_RANGE = const MojoResult._(kOutOfRange);
static const UNIMPLEMENTED = const MojoResult._(kUnimplemented);
static const INTERNAL = const MojoResult._(kInternal);
static const UNAVAILABLE = const MojoResult._(kUnavailable);
static const DATA_LOSS = const MojoResult._(kDataLoss);
static const BUSY = const MojoResult._(kBusy);
static const SHOULD_WAIT = const MojoResult._(kShouldWait);
final int value;
const MojoResult._(this.value);
factory MojoResult(int value) {
switch (value) {
case kOk:
return OK;
case kCancelled:
return CANCELLED;
case kUnknown:
return UNKNOWN;
case kInvalidArgument:
return INVALID_ARGUMENT;
case kDeadlineExceeded:
return DEADLINE_EXCEEDED;
case kNotFound:
return NOT_FOUND;
case kAlreadyExists:
return ALREADY_EXISTS;
case kPermissionDenied:
return PERMISSION_DENIED;
case kResourceExhausted:
return RESOURCE_EXHAUSTED;
case kFailedPrecondition:
return FAILED_PRECONDITION;
case kAborted:
return ABORTED;
case kOutOfRange:
return OUT_OF_RANGE;
case kUnimplemented:
return UNIMPLEMENTED;
case kInternal:
return INTERNAL;
case kUnavailable:
return UNAVAILABLE;
case kDataLoss:
return DATA_LOSS;
case kBusy:
return BUSY;
case kShouldWait:
return SHOULD_WAIT;
default:
throw 'Invalid Mojo result';
}
}
bool get isOk => (this == OK);
bool get isCancelled => (this == CANCELLED);
bool get isUnknown => (this == UNKNOWN);
bool get isInvalidArgument => (this == INVALID_ARGUMENT);
bool get isDeadlineExceeded => (this == DEADLINE_EXCEEDED);
bool get isNotFound => (this == NOT_FOUND);
bool get isAlreadExists => (this == ALREADY_EXISTS);
bool get isPermissionDenied => (this == PERMISSION_DENIED);
bool get isResourceExhausted => (this == RESOURCE_EXHAUSTED);
bool get isFailedPrecondition => (this == FAILED_PRECONDITION);
bool get isAborted => (this == ABORTED);
bool get isOutOfRange => (this == OUT_OF_RANGE);
bool get isUnimplemented => (this == UNIMPLEMENTED);
bool get isInternal => (this == INTERNAL);
bool get isUnavailable => (this == UNAVAILABLE);
bool get isDataLoss => (this == DATA_LOSS);
bool get isBusy => (this == BUSY);
bool get isShouldWait => (this == SHOULD_WAIT);
String toString() {
switch (value) {
case kOk:
return "OK";
case kCancelled:
return "CANCELLED";
case kUnknown:
return "UNKNOWN";
case kInvalidArgument:
return "INVALID_ARGUMENT";
case kDeadlineExceeded:
return "DEADLINE_EXCEEDED";
case kNotFound:
return "NOT_FOUND";
case kAlreadyExists:
return "ALREADY_EXISTS";
case kPermissionDenied:
return "PERMISSION_DENIED";
case kResourceExhausted:
return "RESOURCE_EXHAUSTED";
case kFailedPrecondition:
return "FAILED_PRECONDITION";
case kAborted:
return "ABORTED";
case kOutOfRange:
return "OUT_OF_RANGE";
case kUnimplemented:
return "UNIMPLEMENTED";
case kInternal:
return "INTERNAL";
case kUnavailable:
return "UNAVAILABLE";
case kDataLoss:
return "DATA_LOSS";
case kBusy:
return "BUSY";
case kShouldWait:
return "SHOULD_WAIT";
default:
return "<invalid result>";
}
}
}
class MojoHandleSignals {
static const int kNone = 0;
static const int kReadable = 1 << 0;
static const int kWritable = 1 << 1;
static const int kPeerClosed = 1 << 2;
static const int kReadWrite = kReadable | kWritable;
static const int kAll = kReadable | kWritable | kPeerClosed;
static const int kBitfieldSize = 3;
static const NONE = const MojoHandleSignals._(kNone);
static const READABLE = const MojoHandleSignals._(kReadable);
static const WRITABLE = const MojoHandleSignals._(kWritable);
static const PEER_CLOSED = const MojoHandleSignals._(kPeerClosed);
static const PEER_CLOSED_READABLE =
const MojoHandleSignals._(kPeerClosed | kReadable);
static const READWRITE = const MojoHandleSignals._(kReadWrite);
static const PEER_CLOSED_WRITABLE =
const MojoHandleSignals._(kPeerClosed | kWritable);
static const ALL = const MojoHandleSignals._(kAll);
final int value;
const MojoHandleSignals._(this.value);
factory MojoHandleSignals(int value) {
switch (value) {
case kNone:
return NONE;
case kReadable:
return READABLE;
case kWritable:
return WRITABLE;
case kPeerClosed:
return PEER_CLOSED;
case kReadWrite:
return READWRITE;
case kPeerClosed | kReadable:
return PEER_CLOSED_READABLE;
case kPeerClosed | kWritable:
return PEER_CLOSED_WRITABLE;
case kAll:
return ALL;
default:
throw 'Invalid handle signal: $value';
}
}
bool get isNone => (this == NONE);
bool get isReadable => (value & kReadable) == kReadable;
bool get isWritable => (value & kWritable) == kWritable;
bool get isPeerClosed => (value & kPeerClosed) == kPeerClosed;
bool get isReadWrite => (value & kReadWrite) == kReadWrite;
bool get isAll => (this == ALL);
bool get isValid => (value & kAll) == value;
MojoHandleSignals operator +(MojoHandleSignals other) {
return new MojoHandleSignals(value | other.value);
}
MojoHandleSignals operator -(MojoHandleSignals other) {
return new MojoHandleSignals(value & ~other.value);
}
String toString() {
if (isNone) {
return "(None)";
}
if (!isValid) {
return "(INVALID)";
}
List<String> signals = [];
if (isReadable) signals.add("Readable");
if (isWritable) signals.add("Writable");
if (isPeerClosed) signals.add("PeerClosed");
return "(" + signals.join(", ") + ")";
}
}
class MojoHandleSignalsState {
MojoHandleSignalsState(this.satisfied_signals, this.satisfiable_signals);
final int satisfied_signals;
final int satisfiable_signals;
String toString() => (new MojoHandleSignals(satisfied_signals)).toString();
}
class MojoWaitResult {
MojoWaitResult(this.result, this.state);
final MojoResult result;
MojoHandleSignalsState state;
String toString() => "MojoWaitResult(result: $result, state: $state)";
}
class MojoWaitManyResult {
MojoWaitManyResult(this.result, this.index, this.states);
final MojoResult result;
final int index;
List<MojoHandleSignalsState> states;
bool get isIndexValid => (this.index != null);
bool get areSignalStatesValid => (this.states != null);
String toString() =>
"MojoWaitManyResult(" "result: $result, idx: $index, state: ${states[index]})";
}

@ -1,24 +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 bindings;
abstract class Union {
void encode(Encoder encoder, int offset);
}
class UnionError {
}
class UnsetUnionTagError extends UnionError {
final curTag;
final requestedTag;
UnsetUnionTagError(this.curTag, this.requestedTag);
String toString() {
return "Tried to read unset union member: {{requestedTag}} "
"current member: {{curTag}}.";
}
}

@ -1,15 +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 core;
// Returns the time, in microseconds, since some undefined point in the past.
// The values are only meaningful relative to other values that were obtained
// from the same device without an intervening system restart. Such values are
// guaranteed to be monotonically non-decreasing with the passage of real time.
// Although the units are microseconds, the resolution of the clock may vary
// and is typically in the range of ~1-15 ms.
int getTimeTicksNow() {
return MojoCoreNatives.getTimeTicksNow();
}

@ -1,5 +0,0 @@
author: Chromium Authors <mojo-dev@googlegroups.com>
description: Dart files to support executing inside Mojo.
homepage: https://github.com/domokit/mojo
name: mojo
version: 0.0.22

@ -1,614 +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 file has rules for making Dart packages and Dart-based Mojo applications.
#
# Entrypoint rules are:
# - dart_pkg
# - dartzip_package
# - dartzip_packaged_application
import("../mojo.gni")
import("//build/module_args/mojo.gni")
import("//build/module_args/dart.gni")
template("dartx") {
bundle_prefix = target_name
bundle = "$target_gen_dir/${bundle_prefix}.dartx"
snapshot = "$target_gen_dir/${bundle_prefix}_snapshot.bin"
if (mojo_use_prebuilt_dart_snapshotter) {
dart_snapshotter_path =
rebase_path("mojo/public/tools:copy_dart_snapshotter", ".", mojo_root)
dart_snapshotter_rule = "$dart_snapshotter_path($host_toolchain)"
} else {
dart_snapshotter_rule = dart_snapshotter_bin
}
dart_snapshotter_dir =
get_label_info("$dart_snapshotter_rule", "root_out_dir")
dart_snapshotter = "$dart_snapshotter_dir/dart_snapshotter"
action("gen_${bundle_prefix}_snapshot") {
main_dart = invoker.main_dart
inputs = [
dart_snapshotter,
main_dart,
]
outputs = [
snapshot,
]
if (defined(invoker.sources)) {
inputs += invoker.sources
}
script =
rebase_path("mojo/public/tools/dart_snapshotter.py", ".", mojo_sdk_root)
args = [
rebase_path(dart_snapshotter),
rebase_path(main_dart),
"--package-root",
rebase_path("$root_gen_dir/dart-pkg/packages"),
"--snapshot",
rebase_path(snapshot),
]
deps = [
dart_snapshotter_rule,
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
}
action("gen_${bundle_prefix}_bundle") {
sources = [
rebase_path("mojo/public/tools/dartx.py", ".", mojo_sdk_root),
snapshot,
]
outputs = [
bundle,
]
script = rebase_path("mojo/public/tools/dartx.py", ".", mojo_sdk_root)
args = [
"--snapshot",
rebase_path(snapshot),
"--output",
rebase_path(bundle),
]
deps = [
":gen_${bundle_prefix}_snapshot",
]
}
group(target_name) {
deps = [
":gen_${bundle_prefix}_bundle",
]
}
}
template("dartx_application") {
dartx_name = "${target_name}_dartx"
dartx(dartx_name) {
main_dart = invoker.main_dart
if (defined(invoker.sources)) {
sources = invoker.sources
}
if (defined(invoker.deps)) {
deps = invoker.deps
}
}
if (defined(invoker.output_name)) {
mojo_output = "$root_out_dir/" + invoker.output_name + ".mojo"
} else {
mojo_output = "$root_out_dir/" + target_name + ".mojo"
}
action(target_name) {
script = rebase_path("mojo/public/tools/prepend.py", ".", mojo_sdk_root)
input = "$target_gen_dir/${dartx_name}.dartx"
inputs = [
input,
]
output = mojo_output
outputs = [
output,
]
deps = [
":$dartx_name",
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
line = "#!mojo mojo:dart_content_handler"
if (is_debug || (defined(invoker.strict) && invoker.strict == true)) {
line = "#!mojo mojo:dart_content_handler?strict=true"
}
rebase_input = rebase_path(input, root_build_dir)
rebase_output = rebase_path(output, root_build_dir)
args = [
"--input=$rebase_input",
"--output=$rebase_output",
"--line=$line",
]
}
}
template("dart_pkg_helper") {
assert(defined(invoker.package_name))
package_name = invoker.package_name
pkg_directory = rebase_path("$root_gen_dir/dart-pkg")
package_root = rebase_path("$root_gen_dir/dart-pkg/packages")
stamp_file = "$root_gen_dir/dart-pkg/${package_name}.stamp"
assert(defined(invoker.sources) || defined(invoker.apps) ||
defined(invoker.libs) || defined(invoker.pkg_dir))
action(target_name) {
deps = []
if (defined(invoker.deps)) {
deps += invoker.deps
}
datadeps = []
if (defined(invoker.datadeps)) {
datadeps += invoker.datadeps
}
list_mojoms_script =
rebase_path("mojo/public/tools/dart_list_mojoms.py", ".", mojo_sdk_root)
mojom_sources = []
foreach(d, deps) {
root_prefix = rebase_path(".", "", mojo_sdk_root)
source_directory = rebase_path(get_label_info(d, "dir"))
mojom_sources += exec_script(list_mojoms_script,
[
source_directory,
root_prefix,
],
"list lines")
}
sdk_ext_directory = []
if (defined(invoker.sdk_ext_directory)) {
sdk_ext_directory += [ invoker.sdk_ext_directory ]
}
sdk_ext_files = []
if (defined(invoker.sdk_ext_files)) {
sdk_ext_files += invoker.sdk_ext_files
}
sdk_ext_mappings = []
if (defined(invoker.sdk_ext_mappings)) {
sdk_ext_mappings += invoker.sdk_ext_mappings
}
script = rebase_path("mojo/public/tools/dart_pkg.py", ".", mojo_sdk_root)
entrypoints = []
if (defined(invoker.apps)) {
entrypoints += invoker.apps
}
if (defined(invoker.libs)) {
entrypoints += invoker.libs
}
sources = entrypoints
if (defined(invoker.sources)) {
sources += invoker.sources
} else if (defined(invoker.pkg_dir)) {
list_script = rebase_path("build/ls.py", ".", mojo_sdk_root)
sources += exec_script(list_script,
[
"--target-directory",
rebase_path(invoker.pkg_dir),
],
"list lines")
}
# We have to use foreach to set up outputs instead of rebase_path because
# GN doesn't like assignments to outputs that aren't obviously under
# $root_gen_dir somewhere.
outputs = []
foreach(s, sources) {
outputs += [ "$root_gen_dir/dart-pkg/${package_name}/$s" ]
}
outputs += [ stamp_file ]
inputs = [
list_mojoms_script,
script,
] + rebase_path(sources)
args = [
"--package-name",
package_name,
"--dart-sdk",
rebase_path(dart_sdk_root),
"--gen-directory",
rebase_path("$root_gen_dir/dart-gen"),
"--pkg-directory",
pkg_directory,
"--package-root",
package_root,
"--stamp-file",
rebase_path(stamp_file),
"--package-sources",
] + rebase_path(sources) + [ "--package-entrypoints" ] +
rebase_path(entrypoints) + [ "--mojom-sources" ] +
rebase_path(mojom_sources, "", mojo_sdk_root) +
[ "--sdk-ext-directories" ] + rebase_path(sdk_ext_directory) +
[ "--sdk-ext-files" ] + rebase_path(sdk_ext_files) +
[ "--sdk-ext-mappings" ] + sdk_ext_mappings
}
}
# This is the entrypoint for organizing Dart code for Mojo.
#
# For each file in |apps|, it makes a .mojo Mojo application using the dartx
# format as well as an assemblage of the app under $root_gen_dir/part-pkg for
# use in local development.
#
# For each file in |libs|, it invokes the Dart analyzer. All other sources go in
# |sources|. This should at least contain a 'pubspec.yaml' file. If no |apps|
# are defined, this rule makes the library package available to applications.
# The name of the package is taken from the 'pubspec.yaml' file. Even if a
# package will not be uploaded to pub, an attempt should be made not to conflict
# with the names of existing pub packages, for example by using the prefix
# 'mojo_dart_'.
#
# sources
# List of non-app and non-lib sources to include in the package. This
# should at least contain the pubspec.yaml for the package.
#
# apps (optional)
# List of Mojo application entrypoints containing a main() function.
# Each of these entrypoints will result in a .mojo Mojo application.
# See |output_name| for how this application is named.
#
# libs (optional)
# List of package entrypoints to pass to the analyzer. If none are
# defined, the analyzer is not run.
#
# strict (optional)
# If |apps| are specified, |strict| can be set to true to
# instruct the content handler to run the apps in Dart VM's strict
# compilation mode (with assertions and type-checks, etc.).
#
# app_name_override (optional)
# When |apps| are specified, this is the prefix to use for the
# name of the assembled .mojo file. The target name is used by default.
# For each entrypoint, the result is |output_name|_|entrypoint|.mojo. If
# the entrypoint is main.dart, the result is simply |output_name|.mojo.
#
# deps (optional)
# List of other dart_pkg targets for Dart packages imported by this
# dart_pkg, as well as the mojom targets needed by this dart_pkg.
#
# pkg_dir (optional)
# Directory containing the package sources. This overrides sources and
# entrypoints. The analyzer will not be run.
#
# datadeps (optional)
#
# sdk_ext_directory (optional)
# Directory containing sdk-ext .dart sources.
#
# sdk_ext_files (optional)
# List of sources to include in sdk-ext.
#
# sdk_ext_mappings (optional)
# Mappings for dart libraries that are part of of sdk_ext.
template("dart_pkg") {
if (defined(invoker.pkg_dir)) {
pubspec_yaml_path = rebase_path("pubspec.yaml", "", invoker.pkg_dir)
} else {
pubspec_yaml_path = rebase_path("pubspec.yaml")
}
dart_package_name_script =
rebase_path("mojo/public/tools/dart_package_name.py", ".", mojo_sdk_root)
dart_package_name = exec_script(dart_package_name_script,
[
"--pubspec",
pubspec_yaml_path,
],
"trim string",
[ pubspec_yaml_path ])
dart_pkg_target_name = "${target_name}_pkg_helper"
dart_pkg_helper(dart_pkg_target_name) {
package_name = dart_package_name
if (defined(invoker.sources)) {
sources = invoker.sources
}
if (defined(invoker.apps)) {
apps = invoker.apps
}
if (defined(invoker.libs)) {
libs = invoker.libs
}
if (defined(invoker.pkg_dir)) {
pkg_dir = invoker.pkg_dir
}
if (defined(invoker.deps)) {
deps = invoker.deps
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
if (defined(invoker.sdk_ext_directory)) {
sdk_ext_directory = invoker.sdk_ext_directory
}
if (defined(invoker.sdk_ext_files)) {
sdk_ext_files = invoker.sdk_ext_files
}
if (defined(invoker.sdk_ext_mappings)) {
sdk_ext_mappings = invoker.sdk_ext_mappings
}
}
if (defined(invoker.apps)) {
pkg_name = target_name
if (defined(invoker.app_name_override)) {
pkg_name = invoker.app_name_override
}
pkg_helper_output_dir = "$root_gen_dir/dart-pkg/${dart_package_name}"
foreach(entrypoint, invoker.apps) {
entrypoint_name = get_path_info(entrypoint, "name")
dartx_target_name = "${pkg_name}_${entrypoint_name}"
dartx_output_name = dartx_target_name
if (entrypoint_name == "main") {
dartx_output_name = pkg_name
}
dartx_application(dartx_target_name) {
output_name = dartx_output_name
main_dart = rebase_path(entrypoint, "", pkg_helper_output_dir)
sources = rebase_path(invoker.sources, "", pkg_helper_output_dir)
deps = [
":$dart_pkg_target_name",
]
deps += invoker.deps
if (defined(invoker.strict)) {
strict = invoker.strict
}
}
}
}
group(target_name) {
deps = [
":$dart_pkg_target_name",
]
if (defined(invoker.apps)) {
pkg_name = target_name
if (defined(invoker.app_name_override)) {
pkg_name = invoker.app_name_override
}
foreach(entrypoint, invoker.apps) {
entrypoint_name = get_path_info(entrypoint, "name")
dartx_target_name = "${pkg_name}_${entrypoint_name}"
deps += [ ":$dartx_target_name" ]
}
}
}
}
# Creates a dartzip package.
template("dartzip_package") {
package_target_name = "$target_name"
package_output = "$target_out_dir/$target_name.dartzip"
if (defined(invoker.uses_pub) && invoker.uses_pub) {
# Repackage all dependencies pulled in via "pub get" in a dartzip file.
action("${package_target_name}_repackage") {
target_dir = get_label_info(":$target_name", "dir")
script = rebase_path("mojo/public/tools/gn/zip.py", ".", mojo_sdk_root)
package_name = "$package_target_name"
if (defined(invoker.package_name_override)) {
package_name = invoker.package_name_override
}
# Get a list of the files in packages/ as inputs.
list_packages_contents_script =
rebase_path("mojo/public/tools/dart_list_packages_contents.py",
".",
mojo_sdk_root)
rebase_target_dir = rebase_path(target_dir, root_build_dir)
inputs = exec_script(list_packages_contents_script,
[
"--target-directory",
rebase_target_dir,
"--package-name",
package_name,
],
"list lines",
[ target_dir + "/pubspec.lock" ])
# Zip up all the pulled-in files relative to their location in the
# packages dir.
output = "$target_out_dir/$target_name.dartzip"
outputs = [
output,
]
rebase_base_dir = rebase_target_dir
rebase_inputs = rebase_path(inputs, root_build_dir)
rebase_output = rebase_path(output, root_build_dir)
args = [
"--base-dir=$rebase_base_dir",
"--inputs=$rebase_inputs",
"--output=$rebase_output",
]
}
}
action("${package_target_name}_package") {
script =
rebase_path("mojo/public/tools/dart_package.py", ".", mojo_sdk_root)
inputs = invoker.sources
deps = []
zip_inputs = []
if (defined(invoker.uses_pub) && invoker.uses_pub) {
deps += [ ":${package_target_name}_repackage" ]
}
if (defined(invoker.deps)) {
deps += invoker.deps
foreach(d, deps) {
dep_name = get_label_info(d, "name")
dep_target_out_dir = get_label_info(d, "target_out_dir")
zip_inputs += [ "$dep_target_out_dir/$dep_name.dartzip" ]
}
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
output = package_output
outputs = [
output,
]
rebase_base_dir =
rebase_path(get_label_info(":$package_target_name", "dir"),
root_build_dir)
if (defined(invoker.base_dir)) {
rebase_base_dir = invoker.base_dir
}
rebase_inputs = rebase_path(inputs, root_build_dir)
rebase_zip_inputs = rebase_path(zip_inputs, root_build_dir)
rebase_output = rebase_path(output, root_build_dir)
args = [
"--base-dir=$rebase_base_dir",
"--inputs=$rebase_inputs",
"--zip-inputs=$rebase_zip_inputs",
"--output=$rebase_output",
]
}
action(target_name) {
script =
rebase_path("mojo/public/tools/dart_analyze.py", ".", mojo_sdk_root)
sources = [
package_output,
]
args = [
"--dart-sdk",
rebase_path(dart_sdk_root),
"--dartzip-file",
rebase_path(package_output),
"--stamp-file",
rebase_path("$target_gen_dir/${package_target_name}_analyze.stamp"),
"--no-hints",
]
public_deps = [
":${package_target_name}_package",
]
if (defined(invoker.deps)) {
deps = invoker.deps
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
outputs = [
"$target_gen_dir/${package_target_name}_analyze.stamp",
]
}
}
# Use this template to generate a .mojo dart application. One of the source
# files should be named main.dart and contain a main function as the
# entry point. Dependencies of dart_packaged_application targets should be
# either mojom targets (and specified using the mojom_deps variable) or
# dartzip_package targets.
template("dartzip_packaged_application") {
package_name = "${target_name}_package"
package_output = "$target_out_dir/$package_name.dartzip"
if (defined(invoker.output_name)) {
mojo_output = "$root_out_dir/" + invoker.output_name + ".mojo"
} else {
mojo_output = "$root_out_dir/" + target_name + ".mojo"
}
dartzip_package(package_name) {
sources = invoker.sources
if (defined(invoker.deps)) {
deps = invoker.deps
}
if (defined(invoker.uses_pub)) {
uses_pub = invoker.uses_pub
}
if (defined(invoker.mojom_deps)) {
mojom_deps = invoker.mojom_deps
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
}
action(target_name) {
script = rebase_path("mojo/public/tools/prepend.py", ".", mojo_sdk_root)
input = package_output
inputs = [
input,
]
output = mojo_output
outputs = [
output,
]
deps = [
":$package_name",
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
if (defined(invoker.mojom_deps)) {
deps += invoker.mojom_deps
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
line = "#!mojo mojo:dart_content_handler"
if (is_debug || (defined(invoker.strict) && invoker.strict == true)) {
line = "#!mojo mojo:dart_content_handler?strict=true"
}
rebase_input = rebase_path(input, root_build_dir)
rebase_output = rebase_path(output, root_build_dir)
args = [
"--input=$rebase_input",
"--output=$rebase_output",
"--line=$line",
]
}
}

@ -1,14 +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 internal;
import 'dart:async';
import 'dart:collection';
import 'dart:isolate';
import 'dart:typed_data';
part 'src/handle_watcher.dart';
part 'src/natives.dart';
part 'src/timer_queue.dart';

@ -1,353 +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.
part of internal;
// The MojoHandleWatcher sends a stream of events to application isolates that
// register Mojo handles with it. Application isolates make the following calls:
//
// add(handle, port, signals) - Instructs the MojoHandleWatcher isolate to add
// 'handle' to the set of handles it watches, and to notify the calling
// isolate only for the events specified by 'signals' using the send port
// 'port'
//
// remove(handle) - Instructs the MojoHandleWatcher isolate to remove 'handle'
// from the set of handles it watches. This allows the application isolate
// to, e.g., pause the stream of events.
//
// close(handle) - Notifies the HandleWatcherIsolate that a handle it is
// watching should be removed from its set and closed.
class MojoHandleWatcher {
// Control commands.
static const int ADD = 0;
static const int REMOVE = 1;
static const int CLOSE = 2;
static const int TIMER = 3;
static const int SHUTDOWN = 4;
static const int kMojoHandleInvalid = 0;
static const int kDeadlineIndefinite = -1;
static const int kMojoResultOk = 0;
static const int kMojoResultDeadlineExceeded = 4;
static const int kMojoResultFailedPrecondition = 9;
static const int kMojoSignalsReadable = (1 << 0);
static const int kMojoSignalsWritable = (1 << 1);
static const int kMojoSignalsPeerClosed = (1 << 2);
static const int kMojoSignalsAll =
kMojoSignalsReadable | kMojoSignalsWritable | kMojoSignalsPeerClosed;
static int _encodeCommand(int cmd, [int signals = 0]) =>
(cmd << 3) | (signals & kMojoSignalsAll);
static int _decodeCommand(int cmd) {
assert(kMojoSignalsAll < 1 << 3);
return cmd >> 3;
}
static int _decodeSignals(int cmd) {
return cmd & kMojoSignalsAll;
}
// The Mojo handle over which control messages are sent.
int _controlHandle;
// Whether the handle watcher should shut down.
bool _shutdown;
// The list of handles being watched.
List<int> _handles;
int _handleCount;
// A port for each handle on which to send events back to the isolate that
// owns the handle.
List<SendPort> _ports;
// The signals that we care about for each handle.
List<int> _signals;
// A mapping from Mojo handles to their indices in _handles.
Map<int, int> _handleIndices;
// Priority queue of timers registered with the watcher.
TimerQueue _timerQueue;
MojoHandleWatcher(this._controlHandle)
: _shutdown = false,
_handles = new List<int>(),
_ports = new List<SendPort>(),
_signals = new List<int>(),
_handleIndices = new Map<int, int>(),
_handleCount = 1,
_timerQueue = new TimerQueue() {
// Setup control handle.
_handles.add(_controlHandle);
_ports.add(null); // There is no port for the control handle.
_signals.add(kMojoSignalsReadable);
_handleIndices[_controlHandle] = 0;
}
static void _handleWatcherIsolate(int consumerHandle) {
MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle);
while (!watcher._shutdown) {
int deadline = watcher._processTimerDeadlines();
// mwmr[0]: result, mwmr[1]: index, mwmr[2]: list of signal states.
List mwmr = MojoHandleNatives.waitMany(
watcher._handles, watcher._signals, deadline);
if ((mwmr[0] == kMojoResultOk) && (mwmr[1] == 0)) {
watcher._handleControlMessage();
} else if ((mwmr[0] == kMojoResultOk) && (mwmr[1] > 0)) {
int handle = watcher._handles[mwmr[1]];
// Route event.
watcher._routeEvent(mwmr[2][mwmr[1]][0], mwmr[1]);
// Remove the handle from the list.
watcher._removeHandle(handle);
} else if (mwmr[0] != kMojoResultDeadlineExceeded) {
// Some handle was closed, but not by us.
// Find it and close it on our side.
watcher._pruneClosedHandles(mwmr[2]);
}
}
}
void _routeEvent(int satisfiedSignals, int idx) {
_ports[idx].send([_signals[idx], satisfiedSignals & _signals[idx]]);
}
void _handleControlMessage() {
List result = MojoHandleWatcherNatives.recvControlData(_controlHandle);
// result[0] = mojo handle if any, or a timer deadline in milliseconds.
// result[1] = SendPort if any.
// result[2] = command << 2 | WRITABLE | READABLE
var signals = _decodeSignals(result[2]);
int command = _decodeCommand(result[2]);
switch (command) {
case ADD:
_addHandle(result[0], result[1], signals);
break;
case REMOVE:
_removeHandle(result[0]);
break;
case CLOSE:
_close(result[0], result[1]);
break;
case TIMER:
_timer(result[1], result[0]);
break;
case SHUTDOWN:
_shutdownHandleWatcher(result[1]);
break;
default:
throw "Invalid Command: $command";
break;
}
}
void _addHandle(int mojoHandle, SendPort port, int signals) {
int idx = _handleIndices[mojoHandle];
if (idx == null) {
_handles.add(mojoHandle);
_ports.add(port);
_signals.add(signals);
_handleIndices[mojoHandle] = _handleCount;
_handleCount++;
} else {
assert(_ports[idx] == port);
assert(_handles[idx] == mojoHandle);
_signals[idx] |= signals;
}
}
void _removeHandle(int mojoHandle) {
int idx = _handleIndices[mojoHandle];
if (idx == null) {
throw "Remove on a non-existent handle: idx = $idx.";
}
if (idx == 0) {
throw "The control handle (idx = 0) cannot be removed.";
}
// We don't use List.removeAt so that we know how to fix-up _handleIndices.
if (idx == _handleCount - 1) {
int handle = _handles[idx];
_handleIndices[handle] = null;
_handles.removeLast();
_signals.removeLast();
_ports.removeLast();
_handleCount--;
} else {
int last = _handleCount - 1;
_handleIndices[_handles[idx]] = null;
_handles[idx] = _handles[last];
_signals[idx] = _signals[last];
_ports[idx] = _ports[last];
_handles.removeLast();
_signals.removeLast();
_ports.removeLast();
_handleIndices[_handles[idx]] = idx;
_handleCount--;
}
}
void _close(int mojoHandle, SendPort port, {bool pruning: false}) {
assert(!pruning || (port == null));
int idx = _handleIndices[mojoHandle];
if (idx == null) {
// An app isolate may request that the handle watcher close a handle that
// has already been pruned. This happens when the app isolate has not yet
// received the PEER_CLOSED event. The app isolate will not close the
// handle, so we must do so here.
MojoHandleNatives.close(mojoHandle);
if (port != null) port.send(null); // Notify that close is done.
return;
}
if (idx == 0) {
throw "The control handle (idx = 0) cannot be closed.";
}
MojoHandleNatives.close(_handles[idx]);
if (port != null) port.send(null); // Notify that close is done.
if (pruning) {
// If this handle is being pruned, notify the application isolate
// by sending MojoHandleSignals.PEER_CLOSED.
_ports[idx].send([_signals[idx], kMojoSignalsPeerClosed]);
}
_removeHandle(mojoHandle);
}
// Returns the next timer deadline in units of microseconds from 'now'.
int _processTimerDeadlines() {
int now = (new DateTime.now()).millisecondsSinceEpoch;
while (_timerQueue.hasTimer && (now >= _timerQueue.currentTimeout)) {
_timerQueue.currentPort.send(null);
_timerQueue.removeCurrent();
now = (new DateTime.now()).millisecondsSinceEpoch;
}
return _timerQueue.hasTimer
? (_timerQueue.currentTimeout - now) * 1000
: kDeadlineIndefinite;
}
void _timer(SendPort port, int deadline) {
_timerQueue.updateTimer(port, deadline);
}
void _pruneClosedHandles(List<List<int>> states) {
List<int> closed = new List();
for (var i = 0; i < _handles.length; i++) {
if (states != null) {
int signals = states[i][0];
if ((signals & kMojoSignalsPeerClosed) != 0) {
closed.add(_handles[i]);
}
} else {
List mwr = MojoHandleNatives.wait(_handles[i], kMojoSignalsAll, 0);
if ((mwr[0] != kMojoResultOk) &&
(mwr[0] != kMojoResultDeadlineExceeded)) {
closed.add(_handles[i]);
}
}
}
for (var h in closed) {
_close(h, null, pruning: true);
}
// '_close' updated the '_handles' array, so at this point the '_handles'
// array and the caller's 'states' array are mismatched.
}
void _shutdownHandleWatcher(SendPort shutdownSendPort) {
_shutdown = true;
MojoHandleNatives.close(_controlHandle);
shutdownSendPort.send(null);
}
static int _sendControlData(int rawHandle, SendPort port, int data) {
int controlHandle = MojoHandleWatcherNatives.getControlHandle();
if (controlHandle == kMojoHandleInvalid) {
return kMojoResultFailedPrecondition;
}
var result = MojoHandleWatcherNatives.sendControlData(
controlHandle, rawHandle, port, data);
return result;
}
// Starts up the MojoHandleWatcher isolate. Should be called only once
// per VM process.
static Future<Isolate> _start() {
// Make a control message pipe,
List pipeEndpoints = MojoMessagePipeNatives.MojoCreateMessagePipe(0);
assert(pipeEndpoints != null);
assert((pipeEndpoints is List) && (pipeEndpoints.length == 3));
assert(pipeEndpoints[0] == kMojoResultOk);
int consumerHandle = pipeEndpoints[1];
int producerHandle = pipeEndpoints[2];
// Call setControlHandle with the other end.
assert(producerHandle != kMojoHandleInvalid);
MojoHandleWatcherNatives.setControlHandle(producerHandle);
// Spawn the handle watcher isolate with the MojoHandleWatcher,
return Isolate.spawn(_handleWatcherIsolate, consumerHandle);
}
// Causes the MojoHandleWatcher isolate to exit. Should be called only
// once per VM process.
static void _stop() {
// Create a port for notification that the handle watcher has shutdown.
var shutdownReceivePort = new ReceivePort();
var shutdownSendPort = shutdownReceivePort.sendPort;
// Send the shutdown command.
_sendControlData(
kMojoHandleInvalid, shutdownSendPort, _encodeCommand(SHUTDOWN));
// Close the control handle.
int controlHandle = MojoHandleWatcherNatives.getControlHandle();
MojoHandleNatives.close(controlHandle);
// Invalidate the control handle.
MojoHandleWatcherNatives.setControlHandle(kMojoHandleInvalid);
// Wait for the handle watcher isolate to exit.
shutdownReceivePort.first.then((_) {
shutdownReceivePort.close();
});
}
// If wait is true, returns a future that resolves only after the handle
// has actually been closed by the handle watcher. Otherwise, returns a
// future that resolves immediately.
static Future<int> close(int mojoHandle, {bool wait: false}) {
//assert(MojoHandle._removeUnclosedHandle(mojoHandle));
if (!wait) {
return new Future.value(
_sendControlData(mojoHandle, null, _encodeCommand(CLOSE)));
}
int result;
var completer = new Completer();
var rawPort = new RawReceivePort((_) {
completer.complete(result);
});
result =
_sendControlData(mojoHandle, rawPort.sendPort, _encodeCommand(CLOSE));
return completer.future.then((r) {
rawPort.close();
return r;
});
}
static int add(int mojoHandle, SendPort port, int signals) {
return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals));
}
static int remove(int mojoHandle) {
return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE));
}
static int timer(Object ignored, SendPort port, int deadline) {
// The deadline will be unwrapped before sending to the handle watcher.
return _sendControlData(deadline, port, _encodeCommand(TIMER));
}
}

@ -1,74 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of internal;
class MojoCoreNatives {
static int getTimeTicksNow() native "Mojo_GetTimeTicksNow";
}
class MojoHandleNatives {
static int register(
Object eventStream, int handle) native "MojoHandle_Register";
static int close(int handle) native "MojoHandle_Close";
static List wait(
int handle, int signals, int deadline) native "MojoHandle_Wait";
static List waitMany(List<int> handles, List<int> signals,
int deadline) native "MojoHandle_WaitMany";
}
class MojoHandleWatcherNatives {
static int sendControlData(int controlHandle, int mojoHandle, SendPort port,
int data) native "MojoHandleWatcher_SendControlData";
static List recvControlData(
int controlHandle) native "MojoHandleWatcher_RecvControlData";
static int setControlHandle(
int controlHandle) native "MojoHandleWatcher_SetControlHandle";
static int getControlHandle() native "MojoHandleWatcher_GetControlHandle";
}
class MojoMessagePipeNatives {
static List MojoCreateMessagePipe(int flags) native "MojoMessagePipe_Create";
static int MojoWriteMessage(int handle, ByteData data, int numBytes,
List<int> handles, int flags) native "MojoMessagePipe_Write";
static List MojoReadMessage(int handle, ByteData data, int numBytes,
List<int> handles, int flags) native "MojoMessagePipe_Read";
}
class MojoDataPipeNatives {
static List MojoCreateDataPipe(int elementBytes, int capacityBytes,
int flags) native "MojoDataPipe_Create";
static List MojoWriteData(int handle, ByteData data, int numBytes,
int flags) native "MojoDataPipe_WriteData";
static List MojoBeginWriteData(int handle, int bufferBytes,
int flags) native "MojoDataPipe_BeginWriteData";
static int MojoEndWriteData(
int handle, int bytesWritten) native "MojoDataPipe_EndWriteData";
static List MojoReadData(int handle, ByteData data, int numBytes,
int flags) native "MojoDataPipe_ReadData";
static List MojoBeginReadData(int handle, int bufferBytes,
int flags) native "MojoDataPipe_BeginReadData";
static int MojoEndReadData(
int handle, int bytesRead) native "MojoDataPipe_EndReadData";
}
class MojoSharedBufferNatives {
static List Create(int numBytes, int flags) native "MojoSharedBuffer_Create";
static List Duplicate(
int bufferHandle, int flags) native "MojoSharedBuffer_Duplicate";
static List Map(Object buffer, int bufferHandle, int offset, int numBytes,
int flags) native "MojoSharedBuffer_Map";
static int Unmap(ByteData buffer) native "MojoSharedBuffer_Unmap";
}

@ -1,53 +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.
part of internal;
class Timeout implements Comparable<Timeout> {
int deadline; // milliseconds since the Unix epoch.
SendPort port;
Timeout(this.port, this.deadline);
int compareTo(Timeout other) => deadline - other.deadline;
}
class TimerQueue {
SplayTreeSet _set;
Timeout _nextTimer;
TimerQueue() : _set = new SplayTreeSet();
void updateTimer(SendPort port, int deadline) {
var removedTimeout = null;
_set.removeWhere((timeout) {
if (timeout.port == port) {
removedTimeout = timeout;
return true;
}
return false;
});
if ((removedTimeout == null) && (deadline >= 0)) {
_set.add(new Timeout(port, deadline));
} else {
if (deadline > 0) {
removedTimeout.deadline = deadline;
_set.add(removedTimeout);
}
}
if (_set.isNotEmpty) {
_nextTimer = _set.first;
} else {
_nextTimer = null;
}
}
void removeCurrent() => updateTimer(currentPort, -1);
bool get hasTimer => _nextTimer != null;
int get currentTimeout => _nextTimer.deadline;
SendPort get currentPort => _nextTimer.port;
}

@ -1,176 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package application
import (
"log"
"sync"
"mojo/public/go/bindings"
"mojo/public/go/system"
"mojo/public/interfaces/application/application"
sp "mojo/public/interfaces/application/service_provider"
"mojo/public/interfaces/application/shell"
)
// Delegate is an interface that your mojo application should implement.
// All methods are called from the same goroutine to make sure that order of
// calls matches the order of messages sent to underlying message pipe.
type Delegate interface {
// Initialize is called exactly once before any other method.
Initialize(ctx Context)
// AcceptConnection is called when another application attempts to open
// a connection to this application. Close the connection if you no
// longer need it.
AcceptConnection(connection *Connection)
// Quit is called to request the application shut itself down
// gracefully.
Quit()
}
// Context is an interface to information about mojo application environment.
type Context interface {
// URL returns the URL the application was found at, after all mappings,
// resolution, and redirects.
URL() string
// Args returns a list of initial configuration arguments, passed by the
// Shell.
Args() []string
// ConnectToApplication requests a new connection to an application. You
// should pass a list of services you want to provide to the requested
// application.
ConnectToApplication(remoteURL string, providedServices ...ServiceFactory) *OutgoingConnection
// Close closes the main run loop for this application.
Close()
}
// ApplicationImpl is an utility class for communicating with the Shell, and
// providing Services to clients.
type ApplicationImpl struct {
shell *shell.Shell_Proxy
args []string
url string
// Pointer to the stub that runs this instance of ApplicationImpl.
runner *bindings.Stub
quitOnce sync.Once
delegate Delegate
// Protects connections, that can be modified concurrently because of
// ConnectToApplication calls.
mu sync.Mutex
connections []*Connection
}
// Run binds your mojo application to provided message pipe handle and runs it
// until the application is terminated.
func Run(delegate Delegate, applicationRequest system.MojoHandle) {
messagePipe := system.GetCore().AcquireNativeHandle(applicationRequest).ToMessagePipeHandle()
appRequest := application.Application_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
impl := &ApplicationImpl{
delegate: delegate,
}
stub := application.NewApplicationStub(appRequest, impl, bindings.GetAsyncWaiter())
impl.runner = stub
for {
if err := stub.ServeRequest(); err != nil {
connectionError, ok := err.(*bindings.ConnectionError)
if !ok || !connectionError.Closed() {
log.Println(err)
}
impl.RequestQuit()
break
}
}
}
// Mojo application implementation.
func (impl *ApplicationImpl) Initialize(shellPointer shell.Shell_Pointer, args *[]string, url string) error {
impl.shell = shell.NewShellProxy(shellPointer, bindings.GetAsyncWaiter())
if args != nil {
impl.args = *args
}
impl.url = url
impl.delegate.Initialize(impl)
return nil
}
// Mojo application implementation.
func (impl *ApplicationImpl) AcceptConnection(requestorURL string, services *sp.ServiceProvider_Request, exposedServices *sp.ServiceProvider_Pointer, resolvedURL string) error {
connection := newConnection(requestorURL, services, exposedServices, resolvedURL)
impl.delegate.AcceptConnection(connection)
impl.addConnection(connection)
return nil
}
// Mojo application implementation.
func (impl *ApplicationImpl) RequestQuit() error {
impl.quitOnce.Do(func() {
impl.delegate.Quit()
impl.mu.Lock()
for _, c := range impl.connections {
c.Close()
}
impl.mu.Unlock()
impl.shell.Close_Proxy()
impl.runner.Close()
})
return nil
}
// Context implementaion.
func (impl *ApplicationImpl) URL() string {
return impl.url
}
// Context implementaion.
func (impl *ApplicationImpl) Args() []string {
return impl.args
}
// Context implementaion.
func (impl *ApplicationImpl) ConnectToApplication(remoteURL string, providedServices ...ServiceFactory) *OutgoingConnection {
servicesRequest, servicesPointer := sp.CreateMessagePipeForServiceProvider()
exposedServicesRequest, exposedServicesPointer := sp.CreateMessagePipeForServiceProvider()
if err := impl.shell.ConnectToApplication(remoteURL, &servicesRequest, &exposedServicesPointer); err != nil {
log.Printf("can't connect to %v: %v", remoteURL, err)
// In case of error message pipes sent through Shell are closed and
// the connection will work as if the remote application closed
// both ServiceProvider's pipes.
}
connection := newConnection(impl.url, &exposedServicesRequest, &servicesPointer, remoteURL)
impl.addConnection(connection)
return connection.ProvideServices(providedServices...)
}
func (impl *ApplicationImpl) Close() {
impl.RequestQuit()
}
// addConnection appends connections slice by a provided connection, removing
// connections that have been closed.
func (impl *ApplicationImpl) addConnection(c *Connection) {
impl.mu.Lock()
i := 0
for i < len(impl.connections) {
if impl.connections[i].isClosed {
last := len(impl.connections) - 1
impl.connections[i] = impl.connections[last]
impl.connections[last] = nil
impl.connections = impl.connections[:last]
} else {
i++
}
}
if !c.isClosed {
impl.connections = append(impl.connections, c)
}
impl.mu.Unlock()
}

@ -1,176 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package application
import (
"log"
"mojo/public/go/bindings"
"mojo/public/go/system"
sp "mojo/public/interfaces/application/service_provider"
)
type connectionInfo struct {
requestorURL string
connectionURL string
}
// RequestorURL returns the URL of application that established the connection.
func (c *connectionInfo) RequestorURL() string {
return c.requestorURL
}
// ConnectionURL returns the URL that was used by the source application to
// establish a connection to the destination application.
func (c *connectionInfo) ConnectionURL() string {
return c.connectionURL
}
// ServiceRequest is an interface request for a specified mojo service.
type ServiceRequest interface {
// Name returns the name of requested mojo service.
Name() string
// PassMessagePipe passes ownership of the underlying message pipe
// handle to the newly created handle object, invalidating the
// underlying handle object in the process.
PassMessagePipe() system.MessagePipeHandle
}
// ServiceFactory provides implementation of a mojo service.
type ServiceFactory interface {
// Name returns the name of provided mojo service.
Name() string
// Create binds an implementation of mojo service to the provided
// message pipe and runs it.
Create(pipe system.MessagePipeHandle)
}
// Connection represents a connection to another application. An instance of
// this struct is passed to Delegate's AcceptConnection() function each time a
// connection is made to this application.
type Connection struct {
connectionInfo
// Request for local services. Is valid until ProvideServices is called.
servicesRequest *sp.ServiceProvider_Request
// Indicates that ProvideServices function was already called.
servicesProvided bool
localServices *bindings.Stub
outgoingConnection *OutgoingConnection
isClosed bool
}
func newConnection(requestorURL string, services *sp.ServiceProvider_Request, exposedServices *sp.ServiceProvider_Pointer, resolvedURL string) *Connection {
info := connectionInfo{
requestorURL,
resolvedURL,
}
var remoteServices *sp.ServiceProvider_Proxy
if exposedServices != nil {
remoteServices = sp.NewServiceProviderProxy(*exposedServices, bindings.GetAsyncWaiter())
}
return &Connection{
connectionInfo: info,
servicesRequest: services,
outgoingConnection: &OutgoingConnection{
info,
remoteServices,
},
}
}
// ProvideServices starts a service provider on a separate goroutine that
// provides given services to the remote application. Returns a pointer to
// outgoing connection that can be used to connect to services provided by
// remote application.
// Panics if called more than once.
func (c *Connection) ProvideServices(services ...ServiceFactory) *OutgoingConnection {
if c.servicesProvided {
panic("ProvideServices can be called only once")
}
c.servicesProvided = true
if c.servicesRequest == nil {
return c.outgoingConnection
}
if len(services) == 0 {
c.servicesRequest.PassMessagePipe().Close()
return c.outgoingConnection
}
provider := &serviceProviderImpl{
make(map[string]ServiceFactory),
}
for _, service := range services {
provider.AddService(service)
}
c.localServices = sp.NewServiceProviderStub(*c.servicesRequest, provider, bindings.GetAsyncWaiter())
go func() {
for {
if err := c.localServices.ServeRequest(); err != nil {
connectionError, ok := err.(*bindings.ConnectionError)
if !ok || !connectionError.Closed() {
log.Println(err)
}
break
}
}
}()
return c.outgoingConnection
}
// Close closes both incoming and outgoing parts of the connection.
func (c *Connection) Close() {
if c.servicesRequest != nil {
c.servicesRequest.Close()
}
if c.localServices != nil {
c.localServices.Close()
}
if c.outgoingConnection.remoteServices != nil {
c.outgoingConnection.remoteServices.Close_Proxy()
}
c.isClosed = true
}
// OutgoingConnection represents outgoing part of connection to another
// application. In order to close it close the |Connection| object that returned
// this |OutgoingConnection|.
type OutgoingConnection struct {
connectionInfo
remoteServices *sp.ServiceProvider_Proxy
}
// ConnectToService asks remote application to provide a service through the
// message pipe endpoint supplied by the caller.
func (c *OutgoingConnection) ConnectToService(request ServiceRequest) {
pipe := request.PassMessagePipe()
if c.remoteServices == nil {
pipe.Close()
return
}
c.remoteServices.ConnectToService(request.Name(), pipe)
}
// serviceProviderImpl is an implementation of mojo ServiceProvider interface.
type serviceProviderImpl struct {
factories map[string]ServiceFactory
}
// Mojo ServiceProvider implementation.
func (sp *serviceProviderImpl) ConnectToService(name string, messagePipe system.MessagePipeHandle) error {
factory, ok := sp.factories[name]
if !ok {
messagePipe.Close()
return nil
}
factory.Create(messagePipe)
return nil
}
func (sp *serviceProviderImpl) AddService(factory ServiceFactory) {
sp.factories[factory.Name()] = factory
}

@ -1,282 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
"mojo/public/go/system"
)
var defaultWaiter *asyncWaiterImpl
var once sync.Once
// GetAsyncWaiter returns a default implementation of |AsyncWaiter| interface.
func GetAsyncWaiter() AsyncWaiter {
once.Do(func() {
defaultWaiter = newAsyncWaiter()
})
return defaultWaiter
}
// AsyncWaitId is an id returned by |AsyncWait()| used to cancel it.
type AsyncWaitId uint64
// WaitResponse is a struct sent to a channel waiting for |AsyncWait()| to
// finish. It contains the same information as if |Wait()| was called on a
// handle.
type WaitResponse struct {
Result system.MojoResult
State system.MojoHandleSignalsState
}
// AsyncWaiter defines an interface for asynchronously waiting (and cancelling
// asynchronous waits) on a handle.
type AsyncWaiter interface {
// AsyncWait asynchronously waits on a given handle until a signal
// indicated by |signals| is satisfied or it becomes known that no
// signal indicated by |signals| will ever be satisified. The wait
// response will be sent to |responseChan|.
//
// |handle| must not be closed or transferred until the wait response
// is received from |responseChan|.
AsyncWait(handle system.Handle, signals system.MojoHandleSignals, responseChan chan<- WaitResponse) AsyncWaitId
// CancelWait cancels an outstanding async wait (specified by |id|)
// initiated by |AsyncWait()|. A response with Mojo result
// |MOJO_RESULT_ABORTED| is sent to the corresponding |responseChan|.
CancelWait(id AsyncWaitId)
}
// waitRequest is a struct sent to asyncWaiterWorker to add another handle to
// the list of waiting handles.
type waitRequest struct {
handle system.Handle
signals system.MojoHandleSignals
// Used for |CancelWait()| calls. The worker should issue IDs so that
// you can't cancel the wait until the worker received the wait request.
idChan chan<- AsyncWaitId
// A channel end to send wait results.
responseChan chan<- WaitResponse
}
// asyncWaiterWorker does the actual work, in its own goroutine. It calls
// |WaitMany()| on all provided handles. New handles a added via |waitChan|
// and removed via |cancelChan| messages. To wake the worker asyncWaiterImpl
// sends mojo messages to a dedicated message pipe, the other end of which has
// index 0 in all slices of the worker.
type asyncWaiterWorker struct {
// |handles| and |signals| are used to make |WaitMany()| calls directly.
// All these arrays should be operated simultaneously; i-th element
// of each refers to i-th handle.
handles []system.Handle
signals []system.MojoHandleSignals
asyncWaitIds []AsyncWaitId
responses []chan<- WaitResponse
// Flag shared between waiterImpl and worker that is 1 iff the worker is
// already notified by waiterImpl. The worker sets it to 0 as soon as
// |WaitMany()| succeeds.
isNotified *int32
waitChan <-chan waitRequest // should have a non-empty buffer
cancelChan <-chan AsyncWaitId // should have a non-empty buffer
ids uint64 // is incremented each |AsyncWait()| call
}
// removeHandle removes handle at provided index without sending response by
// swapping all information associated with index-th handle with the last one
// and removing the last one.
func (w *asyncWaiterWorker) removeHandle(index int) {
l := len(w.handles) - 1
// Swap with the last and remove last.
w.handles[index] = w.handles[l]
w.handles = w.handles[0:l]
w.signals[index] = w.signals[l]
w.signals = w.signals[0:l]
w.asyncWaitIds[index] = w.asyncWaitIds[l]
w.asyncWaitIds = w.asyncWaitIds[0:l]
w.responses[index] = w.responses[l]
w.responses = w.responses[0:l]
}
// sendWaitResponseAndRemove send response to corresponding channel and removes
// index-th waiting handle.
func (w *asyncWaiterWorker) sendWaitResponseAndRemove(index int, result system.MojoResult, state system.MojoHandleSignalsState) {
w.responses[index] <- WaitResponse{
result,
state,
}
w.removeHandle(index)
}
// respondToSatisfiedWaits responds to all wait requests that have at least
// one satisfied signal and removes them.
func (w *asyncWaiterWorker) respondToSatisfiedWaits(states []system.MojoHandleSignalsState) {
// Don't touch handle at index 0 as it is the waking handle.
for i := 1; i < len(states); {
if (states[i].SatisfiedSignals & w.signals[i]) != 0 {
// Respond and swap i-th with last and remove last.
w.sendWaitResponseAndRemove(i, system.MOJO_RESULT_OK, states[i])
// Swap i-th with last and remove last.
states[i] = states[len(states)-1]
states = states[:len(states)-1]
} else {
i++
}
}
}
// processIncomingRequests processes all queued async wait or cancel requests
// sent by asyncWaiterImpl.
func (w *asyncWaiterWorker) processIncomingRequests() {
for {
select {
case request := <-w.waitChan:
w.handles = append(w.handles, request.handle)
w.signals = append(w.signals, request.signals)
w.responses = append(w.responses, request.responseChan)
w.ids++
id := AsyncWaitId(w.ids)
w.asyncWaitIds = append(w.asyncWaitIds, id)
request.idChan <- id
case AsyncWaitId := <-w.cancelChan:
// Zero index is reserved for the waking message pipe handle.
index := 0
for i := 1; i < len(w.asyncWaitIds); i++ {
if w.asyncWaitIds[i] == AsyncWaitId {
index = i
break
}
}
// Do nothing if the id was not found as wait response may be
// already sent if the async wait was successful.
if index > 0 {
w.sendWaitResponseAndRemove(index, system.MOJO_RESULT_ABORTED, system.MojoHandleSignalsState{})
}
default:
return
}
}
}
// runLoop run loop of the asyncWaiterWorker. Blocks on |WaitMany()|. If the
// wait is interrupted by waking handle (index 0) then it means that the worker
// was woken by waiterImpl, so the worker processes incoming requests from
// waiterImpl; otherwise responses to corresponding wait request.
func (w *asyncWaiterWorker) runLoop() {
for {
result, index, states := system.GetCore().WaitMany(w.handles, w.signals, system.MOJO_DEADLINE_INDEFINITE)
// Set flag to 0, so that the next incoming request to
// waiterImpl would explicitly wake worker by sending a message
// to waking message pipe.
atomic.StoreInt32(w.isNotified, 0)
if index == -1 {
panic(fmt.Sprintf("error waiting on handles: %v", result))
break
}
// Zero index means that the worker was signaled by asyncWaiterImpl.
if index == 0 {
if result != system.MOJO_RESULT_OK {
panic(fmt.Sprintf("error waiting on waking handle: %v", result))
}
w.handles[0].(system.MessagePipeHandle).ReadMessage(system.MOJO_READ_MESSAGE_FLAG_NONE)
w.processIncomingRequests()
} else if result != system.MOJO_RESULT_OK {
w.sendWaitResponseAndRemove(index, result, system.MojoHandleSignalsState{})
} else {
w.respondToSatisfiedWaits(states)
}
}
}
// asyncWaiterImpl is an implementation of |AsyncWaiter| interface.
// Runs a worker in a separate goroutine and comunicates with it by sending a
// message to |wakingHandle| to wake worker from |WaitMany()| call and
// sending request via |waitChan| and |cancelChan|.
type asyncWaiterImpl struct {
wakingHandle system.MessagePipeHandle
// Flag shared between waiterImpl and worker that is 1 iff the worker is
// already notified by waiterImpl. The worker sets it to 0 as soon as
// |WaitMany()| succeeds.
isWorkerNotified *int32
waitChan chan<- waitRequest // should have a non-empty buffer
cancelChan chan<- AsyncWaitId // should have a non-empty buffer
}
func finalizeWorker(worker *asyncWaiterWorker) {
// Close waking handle on worker side.
worker.handles[0].Close()
}
func finalizeAsyncWaiter(waiter *asyncWaiterImpl) {
waiter.wakingHandle.Close()
}
// newAsyncWaiter creates an asyncWaiterImpl and starts its worker goroutine.
func newAsyncWaiter() *asyncWaiterImpl {
result, h0, h1 := system.GetCore().CreateMessagePipe(nil)
if result != system.MOJO_RESULT_OK {
panic(fmt.Sprintf("can't create message pipe %v", result))
}
waitChan := make(chan waitRequest, 10)
cancelChan := make(chan AsyncWaitId, 10)
isNotified := new(int32)
worker := &asyncWaiterWorker{
[]system.Handle{h1},
[]system.MojoHandleSignals{system.MOJO_HANDLE_SIGNAL_READABLE},
[]AsyncWaitId{0},
[]chan<- WaitResponse{make(chan WaitResponse)},
isNotified,
waitChan,
cancelChan,
0,
}
runtime.SetFinalizer(worker, finalizeWorker)
go worker.runLoop()
waiter := &asyncWaiterImpl{
wakingHandle: h0,
isWorkerNotified: isNotified,
waitChan: waitChan,
cancelChan: cancelChan,
}
runtime.SetFinalizer(waiter, finalizeAsyncWaiter)
return waiter
}
// wakeWorker wakes the worker from |WaitMany()| call. This should be called
// after sending a message to |waitChan| or |cancelChan| to avoid deadlock.
func (w *asyncWaiterImpl) wakeWorker() {
if atomic.CompareAndSwapInt32(w.isWorkerNotified, 0, 1) {
result := w.wakingHandle.WriteMessage([]byte{0}, nil, system.MOJO_WRITE_MESSAGE_FLAG_NONE)
if result != system.MOJO_RESULT_OK {
panic("can't write to a message pipe")
}
}
}
func (w *asyncWaiterImpl) AsyncWait(handle system.Handle, signals system.MojoHandleSignals, responseChan chan<- WaitResponse) AsyncWaitId {
idChan := make(chan AsyncWaitId, 1)
w.waitChan <- waitRequest{
handle,
signals,
idChan,
responseChan,
}
w.wakeWorker()
return <-idChan
}
func (w *asyncWaiterImpl) CancelWait(id AsyncWaitId) {
w.cancelChan <- id
w.wakeWorker()
}

@ -1,113 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"fmt"
"sync"
"mojo/public/go/system"
)
var errConnectionClosed = &ConnectionError{system.MOJO_RESULT_FAILED_PRECONDITION}
// ConnectionError represents a error caused by an operation on a message pipe.
type ConnectionError struct {
Result system.MojoResult
}
func (e *ConnectionError) Error() string {
return fmt.Sprintf("message pipe error: %v", e.Result)
}
// Closed returnes true iff the error was caused by an operation on a closed
// message pipe.
func (e *ConnectionError) Closed() bool {
return e.Result == system.MOJO_RESULT_FAILED_PRECONDITION
}
// Connector owns a message pipe handle. It can read and write messages
// from the message pipe waiting on it if necessary. The operation are
// thread-safe.
type Connector struct {
mu sync.RWMutex // protects pipe handle
pipe system.MessagePipeHandle
done chan struct{}
waitMutex sync.Mutex
waiter AsyncWaiter
waitChan chan WaitResponse
}
// NewStubConnector returns a new |Connector| instance that sends and
// receives messages from a provided message pipe handle.
func NewConnector(pipe system.MessagePipeHandle, waiter AsyncWaiter) *Connector {
return &Connector{
pipe: pipe,
waiter: waiter,
done: make(chan struct{}),
waitChan: make(chan WaitResponse, 1),
}
}
// ReadMessage reads a message from message pipe waiting on it if necessary.
func (c *Connector) ReadMessage() (*Message, error) {
// Make sure that only one goroutine at a time waits a the handle.
// We use separate lock so that we can send messages to the message pipe
// while waiting on the pipe.
//
// It is better to acquire this lock first so that a potential queue of
// readers will wait while closing the message pipe in case of Close()
// call.
c.waitMutex.Lock()
defer c.waitMutex.Unlock()
// Use read lock to use pipe handle without modifying it.
c.mu.RLock()
defer c.mu.RUnlock()
if !c.pipe.IsValid() {
return nil, errConnectionClosed
}
// Check if we already have a message.
result, bytes, handles := c.pipe.ReadMessage(system.MOJO_READ_MESSAGE_FLAG_NONE)
if result == system.MOJO_RESULT_SHOULD_WAIT {
waitId := c.waiter.AsyncWait(c.pipe, system.MOJO_HANDLE_SIGNAL_READABLE, c.waitChan)
select {
case <-c.waitChan:
result, bytes, handles = c.pipe.ReadMessage(system.MOJO_READ_MESSAGE_FLAG_NONE)
if result != system.MOJO_RESULT_OK {
return nil, &ConnectionError{result}
}
case <-c.done:
c.waiter.CancelWait(waitId)
return nil, errConnectionClosed
}
} else if result != system.MOJO_RESULT_OK {
return nil, &ConnectionError{result}
}
return ParseMessage(bytes, handles)
}
// WriteMessage writes a message to the message pipe.
func (c *Connector) WriteMessage(message *Message) error {
// Use read lock to use pipe handle without modifying it.
c.mu.RLock()
defer c.mu.RUnlock()
if !c.pipe.IsValid() {
return errConnectionClosed
}
return WriteMessage(c.pipe, message)
}
// Close closes the message pipe aborting wait on the message pipe.
// Panics if you try to close the |Connector| more than once.
func (c *Connector) Close() {
// Stop waiting to acquire the lock.
close(c.done)
// Use write lock to modify the pipe handle.
c.mu.Lock()
c.pipe.Close()
c.mu.Unlock()
}

@ -1,429 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"encoding/binary"
"fmt"
"math"
"mojo/public/go/system"
)
// Decoder is a helper to decode mojo complex elements from mojo archive format.
type Decoder struct {
// Buffer containing data to decode.
buf []byte
// Index of the first unclaimed byte in buf.
end int
// Array containing handles to decode.
handles []system.UntypedHandle
// The first unclaimed handle index.
nextHandle int
// A stack of encoding states matching current one-level value stack
// of the decoding data structure.
stateStack []encodingState
}
// NewDecoder returns a decoder that will decode structured data from provided
// byte array and with handles.
func NewDecoder(bytes []byte, handles []system.UntypedHandle) *Decoder {
return &Decoder{buf: bytes, handles: handles}
}
// claimData claims a block of |size| bytes for a one-level value.
func (d *Decoder) claimData(size int) error {
if d.end+size > len(d.buf) {
return &ValidationError{IllegalMemoryRange, "data buffer is too small"}
}
d.end += size
return nil
}
func (d *Decoder) claimHandle(index int) (system.UntypedHandle, error) {
if index >= len(d.handles) {
return nil, &ValidationError{IllegalHandle, "trying to access non present handle"}
}
if index < d.nextHandle {
return nil, &ValidationError{IllegalHandle, "trying to access handle out of order"}
}
d.nextHandle = index + 1
return d.handles[index], nil
}
func (d *Decoder) popState() {
if len(d.stateStack) != 0 {
d.stateStack = d.stateStack[:len(d.stateStack)-1]
}
}
func (d *Decoder) pushState(header DataHeader, checkElements bool) error {
oldEnd := d.end
if err := d.claimData(int(header.Size - dataHeaderSize)); err != nil {
return err
}
elements := uint32(0)
if checkElements {
elements = header.ElementsOrVersion
}
d.stateStack = append(d.stateStack, encodingState{
offset: oldEnd,
limit: d.end,
elements: elements,
checkElements: checkElements,
})
return nil
}
// state returns state of the top-level value.
func (d *Decoder) state() *encodingState {
if len(d.stateStack) == 0 {
return nil
}
return &d.stateStack[len(d.stateStack)-1]
}
// StartArray starts decoding an array and reads its data header,
// returning number of elements declared in data header.
// Note: it doesn't read a pointer to the encoded array.
// Call |Finish()| after reading all array elements.
func (d *Decoder) StartArray(elementBitSize uint32) (uint32, error) {
header, err := d.readDataHeader()
if err != nil {
return 0, err
}
minSize := bytesForBits(uint64(header.ElementsOrVersion) * uint64(elementBitSize))
if got, want := int(header.Size), dataHeaderSize+minSize; got < want {
return 0, &ValidationError{UnexpectedArrayHeader,
fmt.Sprintf("data header size(%d) should be at least %d", got, want),
}
}
if err := d.pushState(header, true); err != nil {
return 0, err
}
return header.ElementsOrVersion, nil
}
// StartMap starts decoding a map and reads its data header.
// Note: it doesn't read a pointer to the encoded map.
// Call |Finish()| after reading keys array and values array.
func (d *Decoder) StartMap() error {
header, err := d.readDataHeader()
if err != nil {
return err
}
if header != mapHeader {
return &ValidationError{UnexpectedStructHeader,
fmt.Sprintf("invalid map header: %v", header),
}
}
if err := d.pushState(header, false); err != nil {
return err
}
return nil
}
// StartStruct starts decoding a struct and reads its data header.
// Returns the read data header. The caller should check if it is valid.
// Note: it doesn't read a pointer to the encoded struct.
// Call |Finish()| after reading all fields.
func (d *Decoder) StartStruct() (DataHeader, error) {
header, err := d.readDataHeader()
if err != nil {
return DataHeader{}, err
}
if header.Size < dataHeaderSize {
return DataHeader{}, &ValidationError{UnexpectedStructHeader,
fmt.Sprintf("data header size(%d) should be at least %d", header.Size, dataHeaderSize),
}
}
if err := d.pushState(header, false); err != nil {
return DataHeader{}, err
}
return header, nil
}
// StartNestedUnion starts decoding a union.
// Note: it doesn't read a pointer to the encoded struct or the union header.
// Call |Finish()| after reading the header and data.
func (d *Decoder) StartNestedUnion() error {
// We have to trick pushState into claiming 16 bytes.
header := DataHeader{uint32(24), uint32(0)}
if err := d.pushState(header, false); err != nil {
return err
}
return nil
}
// ReadUnionHeader reads the union header and returns the union's size and tag.
func (d *Decoder) ReadUnionHeader() (uint32, uint32, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil {
return 0, 0, err
}
d.state().alignOffsetToBytes()
d.state().offset = align(d.state().offset, 8)
size := binary.LittleEndian.Uint32(d.buf[d.state().offset:])
tag := binary.LittleEndian.Uint32(d.buf[d.state().offset+4:])
d.state().offset += 8
if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil {
return 0, 0, err
}
return size, tag, nil
}
// FinishReadingUnionValue should be called after the union value has been read
// in order to indicate to move the decoder past the union value field.
func (d *Decoder) FinishReadingUnionValue() {
d.state().offset = align(d.state().offset, 8)
d.state().alignOffsetToBytes()
}
// SkipNullUnionValue skips the union's null value.
func (d *Decoder) SkipNullUnionValue() {
d.state().offset += 8
d.state().elementsProcessed += 1
}
func (d *Decoder) readDataHeader() (DataHeader, error) {
if err := d.claimData(dataHeaderSize); err != nil {
return DataHeader{}, err
}
oldEnd := d.end - dataHeaderSize
header := DataHeader{
Size: binary.LittleEndian.Uint32(d.buf[oldEnd:]),
ElementsOrVersion: binary.LittleEndian.Uint32(d.buf[oldEnd+4:]),
}
return header, nil
}
// Finish indicates the decoder that you have finished reading elements of
// a one-level value.
func (d *Decoder) Finish() error {
if d.state() == nil {
return fmt.Errorf("state stack is empty")
}
if d.state().checkElements && d.state().elementsProcessed != d.state().elements {
return fmt.Errorf("unexpected number of elements read: defined in header %d, but read %d", d.state().elements, d.state().elementsProcessed)
}
d.popState()
return nil
}
// ReadBool reads a bool value.
func (d *Decoder) ReadBool() (bool, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 1); err != nil {
return false, err
}
value := ((d.buf[d.state().offset] >> d.state().bitOffset) & 1) == 1
d.state().skipBits(1)
d.state().elementsProcessed++
return value, nil
}
// ReadInt8 reads an int8 value.
func (d *Decoder) ReadInt8() (int8, error) {
value, err := d.ReadUint8()
return int8(value), err
}
// ReadUint8 reads an uint8 value.
func (d *Decoder) ReadUint8() (uint8, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 8); err != nil {
return 0, err
}
d.state().alignOffsetToBytes()
value := d.buf[d.state().offset]
d.state().skipBytes(1)
d.state().elementsProcessed++
return value, nil
}
// ReadInt16 reads an int16 value.
func (d *Decoder) ReadInt16() (int16, error) {
value, err := d.ReadUint16()
return int16(value), err
}
// ReadUint16 reads an uint16 value.
func (d *Decoder) ReadUint16() (uint16, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 16); err != nil {
return 0, err
}
d.state().alignOffsetToBytes()
d.state().offset = align(d.state().offset, 2)
value := binary.LittleEndian.Uint16(d.buf[d.state().offset:])
d.state().skipBytes(2)
d.state().elementsProcessed++
return value, nil
}
// ReadInt32 reads an int32 value.
func (d *Decoder) ReadInt32() (int32, error) {
value, err := d.ReadUint32()
return int32(value), err
}
// ReadUint32 reads an uint32 value.
func (d *Decoder) ReadUint32() (uint32, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 32); err != nil {
return 0, err
}
d.state().alignOffsetToBytes()
d.state().offset = align(d.state().offset, 4)
value := binary.LittleEndian.Uint32(d.buf[d.state().offset:])
d.state().skipBytes(4)
d.state().elementsProcessed++
return value, nil
}
// ReadInt64 reads an int64 value.
func (d *Decoder) ReadInt64() (int64, error) {
value, err := d.ReadUint64()
return int64(value), err
}
// ReadUint64 reads an uint64 value.
func (d *Decoder) ReadUint64() (uint64, error) {
if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil {
return 0, err
}
d.state().alignOffsetToBytes()
d.state().offset = align(d.state().offset, 8)
value := binary.LittleEndian.Uint64(d.buf[d.state().offset:])
d.state().skipBytes(8)
d.state().elementsProcessed++
return value, nil
}
// ReadFloat32 reads a float32 value.
func (d *Decoder) ReadFloat32() (float32, error) {
bits, err := d.ReadUint32()
return math.Float32frombits(bits), err
}
// ReadFloat64 reads a float64 value.
func (d *Decoder) ReadFloat64() (float64, error) {
bits, err := d.ReadUint64()
return math.Float64frombits(bits), err
}
// ReadString reads a string value. It doesn't read a pointer to the encoded
// string.
func (d *Decoder) ReadString() (string, error) {
length, err := d.StartArray(8)
if err != nil {
return "", err
}
var bytes []byte
for i := uint32(0); i < length; i++ {
b, err := d.ReadUint8()
if err != nil {
return "", err
}
bytes = append(bytes, b)
}
if err := d.Finish(); err != nil {
return "", err
}
return string(bytes), nil
}
// ReadPointer reads a pointer and reassigns first unclaimed byte index if the
// pointer is not null.
func (d *Decoder) ReadPointer() (uint64, error) {
pointer, err := d.ReadUint64()
if err != nil {
return pointer, err
}
if pointer == 0 {
return pointer, nil
}
newEnd := uint64(d.state().offset-8) + pointer
if pointer >= uint64(len(d.buf)) || newEnd >= uint64(len(d.buf)) {
return 0, &ValidationError{IllegalPointer, "trying to access out of range memory"}
}
if newEnd < uint64(d.end) {
return 0, &ValidationError{IllegalMemoryRange, "trying to access memory out of order"}
}
if newEnd%8 != 0 {
return 0, &ValidationError{MisalignedObject,
fmt.Sprintf("incorrect pointer data alignment: %d", newEnd),
}
}
d.claimData(int(newEnd) - d.end)
return pointer, nil
}
// ReadUntypedHandle reads an untyped handle.
func (d *Decoder) ReadUntypedHandle() (system.UntypedHandle, error) {
handleIndex, err := d.ReadUint32()
if err != nil {
return nil, err
}
if handleIndex == ^uint32(0) {
return &InvalidHandle{}, nil
}
return d.claimHandle(int(handleIndex))
}
// ReadHandle reads a handle.
func (d *Decoder) ReadHandle() (system.Handle, error) {
return d.ReadUntypedHandle()
}
// ReadMessagePipeHandle reads a message pipe handle.
func (d *Decoder) ReadMessagePipeHandle() (system.MessagePipeHandle, error) {
if handle, err := d.ReadUntypedHandle(); err != nil {
return nil, err
} else {
return handle.ToMessagePipeHandle(), nil
}
}
// ReadConsumerHandle reads a data pipe consumer handle.
func (d *Decoder) ReadConsumerHandle() (system.ConsumerHandle, error) {
if handle, err := d.ReadUntypedHandle(); err != nil {
return nil, err
} else {
return handle.ToConsumerHandle(), nil
}
}
// ReadProducerHandle reads a data pipe producer handle.
func (d *Decoder) ReadProducerHandle() (system.ProducerHandle, error) {
if handle, err := d.ReadUntypedHandle(); err != nil {
return nil, err
} else {
return handle.ToProducerHandle(), nil
}
}
// ReadSharedBufferHandle reads a shared buffer handle.
func (d *Decoder) ReadSharedBufferHandle() (system.SharedBufferHandle, error) {
if handle, err := d.ReadUntypedHandle(); err != nil {
return nil, err
} else {
return handle.ToSharedBufferHandle(), nil
}
}
// ReadInterface reads an encoded interface and returns the message pipe handle.
// The version field is ignored for now.
func (d *Decoder) ReadInterface() (system.MessagePipeHandle, error) {
handle, err := d.ReadMessagePipeHandle()
if err != nil {
return nil, err
}
d.state().elementsProcessed--
if _, err := d.ReadUint32(); err != nil {
return nil, err
}
return handle, nil
}

@ -1,385 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"encoding/binary"
"fmt"
"math"
"mojo/public/go/system"
)
// encodingState has information required to encode/decode a one-level value.
type encodingState struct {
// Index of the first unprocessed byte.
offset int
// Index of the first unprocessed bit of buffer[offset] byte.
bitOffset uint32
// Index of the first byte after the claimed buffer block for the current
// one-level value.
limit int
// Number of elements declared in the data header for the current one-level
// value.
elements uint32
// Number of elements already encoded/decoded of the current one-level
// value.
elementsProcessed uint32
// Whether the number of elements processed should be checked.
checkElements bool
}
func (s *encodingState) alignOffsetToBytes() {
if s.bitOffset > 0 {
s.offset++
s.bitOffset = 0
}
}
func (s *encodingState) skipBits(count uint32) {
s.bitOffset += count
s.offset += int(s.bitOffset >> 3) // equal to s.bitOffset / 8
s.bitOffset &= 7 // equal to s.bitOffset % 8
}
func (s *encodingState) skipBytes(count int) {
s.bitOffset = 0
s.offset += count
}
// Encoder is a helper to encode mojo complex elements into mojo archive format.
type Encoder struct {
// Buffer containing encoded data.
buf []byte
// Index of the first unclaimed byte in buf.
end int
// Array containing encoded handles.
handles []system.UntypedHandle
// A stack of encoder states matching current one-level value stack
// of the encoding data structure.
stateStack []encodingState
}
func ensureElementBitSizeAndCapacity(state *encodingState, bitSize uint32) error {
if state == nil {
return fmt.Errorf("empty state stack")
}
if state.checkElements && state.elementsProcessed >= state.elements {
return fmt.Errorf("can't process more than elements defined in header(%d)", state.elements)
}
byteSize := bytesForBits(uint64(state.bitOffset + bitSize))
if align(state.offset+byteSize, byteSize) > state.limit {
return fmt.Errorf("buffer size limit exceeded")
}
return nil
}
// claimData claims a block of |size| bytes for a one-level value, resizing
// buffer if needed.
func (e *Encoder) claimData(size int) {
e.end += size
if e.end < len(e.buf) {
return
}
newLen := e.end
if l := 2 * len(e.buf); newLen < l {
newLen = l
}
tmp := make([]byte, newLen)
copy(tmp, e.buf)
e.buf = tmp
}
func (e *Encoder) popState() {
if len(e.stateStack) != 0 {
e.stateStack = e.stateStack[:len(e.stateStack)-1]
}
}
func (e *Encoder) pushState(header DataHeader, checkElements bool) {
oldEnd := e.end
e.claimData(align(int(header.Size), defaultAlignment))
elements := uint32(0)
if checkElements {
elements = header.ElementsOrVersion
}
e.stateStack = append(e.stateStack, encodingState{
offset: oldEnd,
limit: e.end,
elements: elements,
checkElements: checkElements,
})
}
// state returns encoder state of the top-level value.
func (e *Encoder) state() *encodingState {
if len(e.stateStack) == 0 {
return nil
}
return &e.stateStack[len(e.stateStack)-1]
}
// NewEncoder returns a new instance of encoder.
func NewEncoder() *Encoder {
return &Encoder{}
}
// StartArray starts encoding an array and writes its data header.
// Note: it doesn't write a pointer to the encoded array.
// Call |Finish()| after writing all array elements.
func (e *Encoder) StartArray(length, elementBitSize uint32) {
dataSize := dataHeaderSize + bytesForBits(uint64(length)*uint64(elementBitSize))
header := DataHeader{uint32(dataSize), length}
e.pushState(header, true)
e.writeDataHeader(header)
}
// StartMap starts encoding a map and writes its data header.
// Note: it doesn't write a pointer to the encoded map.
// Call |Finish()| after writing keys array and values array.
func (e *Encoder) StartMap() {
e.pushState(mapHeader, false)
e.writeDataHeader(mapHeader)
}
// StartStruct starts encoding a struct and writes its data header.
// Note: it doesn't write a pointer to the encoded struct.
// Call |Finish()| after writing all fields.
func (e *Encoder) StartStruct(size, version uint32) {
dataSize := dataHeaderSize + int(size)
header := DataHeader{uint32(dataSize), version}
e.pushState(header, false)
e.writeDataHeader(header)
}
// StartNestedUnion starts encoding a nested union.
// Note: it doesn't write a pointer or a union header.
// Call |Finish()| after writing all fields.
func (e *Encoder) StartNestedUnion() {
header := DataHeader{uint32(16), uint32(0)}
e.pushState(header, false)
}
func (e *Encoder) writeDataHeader(header DataHeader) {
binary.LittleEndian.PutUint32(e.buf[e.state().offset:], header.Size)
binary.LittleEndian.PutUint32(e.buf[e.state().offset+4:], header.ElementsOrVersion)
e.state().offset += 8
}
// WriteUnionHeader writes a union header for a non-null union.
// (See. WriteNullUnion)
func (e *Encoder) WriteUnionHeader(tag uint32) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil {
return err
}
e.state().alignOffsetToBytes()
e.state().offset = align(e.state().offset, 8)
binary.LittleEndian.PutUint32(e.buf[e.state().offset:], 16)
binary.LittleEndian.PutUint32(e.buf[e.state().offset+4:], tag)
e.state().offset += 8
if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil {
return err
}
return nil
}
// FinishWritingUnionValue should call after the union value has been read in
// order to indicate to move the encoder past the union value field.
func (e *Encoder) FinishWritingUnionValue() {
e.state().offset = align(e.state().offset, 8)
e.state().alignOffsetToBytes()
}
// Finish indicates the encoder that you have finished writing elements of
// a one-level value.
func (e *Encoder) Finish() error {
if e.state() == nil {
return fmt.Errorf("state stack is empty")
}
if e.state().checkElements && e.state().elementsProcessed != e.state().elements {
return fmt.Errorf("unexpected number of elements written: defined in header %d, but written %d", e.state().elements, e.state().elementsProcessed)
}
e.popState()
return nil
}
// Data returns an encoded message with attached handles.
// Call this method after finishing encoding of a value.
func (e *Encoder) Data() ([]byte, []system.UntypedHandle, error) {
if len(e.stateStack) != 0 {
return nil, nil, fmt.Errorf("can't return data when encoder has non-empty state stack")
}
return e.buf[:e.end], e.handles, nil
}
// WriteBool writes a bool value.
func (e *Encoder) WriteBool(value bool) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 1); err != nil {
return err
}
if value {
e.buf[e.state().offset] |= 1 << e.state().bitOffset
}
e.state().skipBits(1)
e.state().elementsProcessed++
return nil
}
// WriteBool writes an int8 value.
func (e *Encoder) WriteInt8(value int8) error {
return e.WriteUint8(uint8(value))
}
// WriteUint8 writes an uint8 value.
func (e *Encoder) WriteUint8(value uint8) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 8); err != nil {
return err
}
e.state().alignOffsetToBytes()
e.buf[e.state().offset] = value
e.state().skipBytes(1)
e.state().elementsProcessed++
return nil
}
// WriteInt16 writes an int16 value.
func (e *Encoder) WriteInt16(value int16) error {
return e.WriteUint16(uint16(value))
}
// WriteUint16 writes an uint16 value.
func (e *Encoder) WriteUint16(value uint16) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 16); err != nil {
return err
}
e.state().alignOffsetToBytes()
e.state().offset = align(e.state().offset, 2)
binary.LittleEndian.PutUint16(e.buf[e.state().offset:], value)
e.state().skipBytes(2)
e.state().elementsProcessed++
return nil
}
// WriteInt32 writes an int32 value.
func (e *Encoder) WriteInt32(value int32) error {
return e.WriteUint32(uint32(value))
}
// WriteUint32 writes an uint32 value.
func (e *Encoder) WriteUint32(value uint32) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 32); err != nil {
return err
}
e.state().alignOffsetToBytes()
e.state().offset = align(e.state().offset, 4)
binary.LittleEndian.PutUint32(e.buf[e.state().offset:], value)
e.state().skipBytes(4)
e.state().elementsProcessed++
return nil
}
// WriteInt64 writes an int64 value.
func (e *Encoder) WriteInt64(value int64) error {
return e.WriteUint64(uint64(value))
}
// WriteUint64 writes an uint64 value.
func (e *Encoder) WriteUint64(value uint64) error {
if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil {
return err
}
e.state().alignOffsetToBytes()
e.state().offset = align(e.state().offset, 8)
binary.LittleEndian.PutUint64(e.buf[e.state().offset:], value)
e.state().skipBytes(8)
e.state().elementsProcessed++
return nil
}
// WriteFloat32 writes a float32 value.
func (e *Encoder) WriteFloat32(value float32) error {
return e.WriteUint32(math.Float32bits(value))
}
// WriteFloat64 writes a float64 value.
func (e *Encoder) WriteFloat64(value float64) error {
return e.WriteUint64(math.Float64bits(value))
}
// WriteNullUnion writes a null union.
func (e *Encoder) WriteNullUnion() error {
if err := e.WriteUint64(0); err != nil {
return err
}
e.state().elementsProcessed--
return e.WriteUint64(0)
}
// WriteNullPointer writes a null pointer.
func (e *Encoder) WriteNullPointer() error {
return e.WriteUint64(0)
}
// WriteString writes a string value. It doesn't write a pointer to the encoded
// string.
func (e *Encoder) WriteString(value string) error {
bytes := []byte(value)
e.StartArray(uint32(len(bytes)), 8)
for _, b := range bytes {
if err := e.WriteUint8(b); err != nil {
return err
}
}
return e.Finish()
}
// WritePointer writes a pointer to first unclaimed byte index.
func (e *Encoder) WritePointer() error {
e.state().alignOffsetToBytes()
e.state().offset = align(e.state().offset, 8)
return e.WriteUint64(uint64(e.end - e.state().offset))
}
// WriteInvalidHandle an invalid handle.
func (e *Encoder) WriteInvalidHandle() error {
return e.WriteInt32(-1)
}
// WriteHandle writes a handle and invalidates the passed handle object.
func (e *Encoder) WriteHandle(handle system.Handle) error {
if !handle.IsValid() {
return fmt.Errorf("can't write an invalid handle")
}
UntypedHandle := handle.ToUntypedHandle()
e.handles = append(e.handles, UntypedHandle)
return e.WriteUint32(uint32(len(e.handles) - 1))
}
// WriteInvalidInterface writes an invalid interface.
func (e *Encoder) WriteInvalidInterface() error {
if err := e.WriteInvalidHandle(); err != nil {
return err
}
e.state().elementsProcessed--
return e.WriteUint32(0)
}
// WriteInterface writes an interface and invalidates the passed handle object.
func (e *Encoder) WriteInterface(handle system.Handle) error {
if err := e.WriteHandle(handle); err != nil {
return err
}
e.state().elementsProcessed--
// Set the version field to 0 for now.
return e.WriteUint32(0)
}

@ -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.
package bindings
import (
"fmt"
"mojo/public/go/system"
)
// MessagePipeHandleOwner owns a message pipe handle, it can only pass it
// invalidating itself or close it.
type MessagePipeHandleOwner struct {
handle system.MessagePipeHandle
}
// PassMessagePipe passes ownership of the underlying message pipe handle to
// the newly created handle object, invalidating the underlying handle object
// in the process.
func (o *MessagePipeHandleOwner) PassMessagePipe() system.MessagePipeHandle {
if o.handle == nil {
return &InvalidHandle{}
}
return o.handle.ToUntypedHandle().ToMessagePipeHandle()
}
// Close closes the underlying handle.
func (o *MessagePipeHandleOwner) Close() {
if o.handle != nil {
o.handle.Close()
}
}
// NewMessagePipeHandleOwner creates |MessagePipeHandleOwner| that owns the
// provided message pipe handle.
func NewMessagePipeHandleOwner(handle system.MessagePipeHandle) MessagePipeHandleOwner {
return MessagePipeHandleOwner{handle}
}
// InterfaceRequest represents a request from a remote client for an
// implementation of mojo interface over a specified message pipe. The
// implementor of the interface should remove the message pipe by calling
// PassMessagePipe() and attach it to the implementation.
type InterfaceRequest struct {
MessagePipeHandleOwner
}
// InterfacePointer owns a message pipe handle with an implementation of mojo
// interface attached to the other end of the message pipe. The client of the
// interface should remove the message pipe by calling PassMessagePipe() and
// attach it to the proxy.
type InterfacePointer struct {
MessagePipeHandleOwner
}
// CreateMessagePipeForInterface creates a message pipe with interface request
// on one end and interface pointer on the other end. The interface request
// should be attached to appropriate mojo interface implementation and
// the interface pointer should be attached to mojo interface proxy.
func CreateMessagePipeForMojoInterface() (InterfaceRequest, InterfacePointer) {
r, h0, h1 := system.GetCore().CreateMessagePipe(nil)
if r != system.MOJO_RESULT_OK {
panic(fmt.Sprintf("can't create a message pipe: %v", r))
}
return InterfaceRequest{MessagePipeHandleOwner{h0}}, InterfacePointer{MessagePipeHandleOwner{h1}}
}

@ -1,97 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"mojo/public/go/system"
)
// InvalidHandle is a handle that will always be invalid.
type InvalidHandle struct {
}
func (h *InvalidHandle) Close() system.MojoResult {
return system.MOJO_RESULT_INVALID_ARGUMENT
}
func (h *InvalidHandle) IsValid() bool {
return false
}
func (h *InvalidHandle) NativeHandle() system.MojoHandle {
return system.MOJO_HANDLE_INVALID
}
func (h *InvalidHandle) ReleaseNativeHandle() system.MojoHandle {
return system.MOJO_HANDLE_INVALID
}
func (h *InvalidHandle) ToUntypedHandle() system.UntypedHandle {
return h
}
func (h *InvalidHandle) Wait(signals system.MojoHandleSignals, deadline system.MojoDeadline) (system.MojoResult, system.MojoHandleSignalsState) {
return system.MOJO_RESULT_INVALID_ARGUMENT, system.MojoHandleSignalsState{}
}
func (h *InvalidHandle) ToConsumerHandle() system.ConsumerHandle {
return h
}
func (h *InvalidHandle) ToProducerHandle() system.ProducerHandle {
return h
}
func (h *InvalidHandle) ToMessagePipeHandle() system.MessagePipeHandle {
return h
}
func (h *InvalidHandle) ToSharedBufferHandle() system.SharedBufferHandle {
return h
}
func (h *InvalidHandle) ReadData(flags system.MojoReadDataFlags) (system.MojoResult, []byte) {
return system.MOJO_RESULT_INVALID_ARGUMENT, nil
}
func (h *InvalidHandle) BeginReadData(numBytes int, flags system.MojoReadDataFlags) (system.MojoResult, []byte) {
return system.MOJO_RESULT_INVALID_ARGUMENT, nil
}
func (h *InvalidHandle) EndReadData(numBytesRead int) system.MojoResult {
return system.MOJO_RESULT_INVALID_ARGUMENT
}
func (h *InvalidHandle) WriteData(data []byte, flags system.MojoWriteDataFlags) (system.MojoResult, int) {
return system.MOJO_RESULT_INVALID_ARGUMENT, 0
}
func (h *InvalidHandle) BeginWriteData(numBytes int, flags system.MojoWriteDataFlags) (system.MojoResult, []byte) {
return system.MOJO_RESULT_INVALID_ARGUMENT, nil
}
func (h *InvalidHandle) EndWriteData(numBytesWritten int) system.MojoResult {
return system.MOJO_RESULT_INVALID_ARGUMENT
}
func (h *InvalidHandle) ReadMessage(flags system.MojoReadMessageFlags) (system.MojoResult, []byte, []system.UntypedHandle) {
return system.MOJO_RESULT_INVALID_ARGUMENT, nil, nil
}
func (h *InvalidHandle) WriteMessage(bytes []byte, handles []system.UntypedHandle, flags system.MojoWriteMessageFlags) system.MojoResult {
return system.MOJO_RESULT_INVALID_ARGUMENT
}
func (h *InvalidHandle) DuplicateBufferHandle(opts *system.DuplicateBufferHandleOptions) (system.MojoResult, system.SharedBufferHandle) {
return system.MOJO_RESULT_INVALID_ARGUMENT, nil
}
func (h *InvalidHandle) MapBuffer(offset uint64, numBytes int, flags system.MojoMapBufferFlags) (system.MojoResult, []byte) {
return system.MOJO_RESULT_INVALID_ARGUMENT, nil
}
func (h *InvalidHandle) UnmapBuffer(buffer []byte) system.MojoResult {
return system.MOJO_RESULT_INVALID_ARGUMENT
}

@ -1,205 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"fmt"
"mojo/public/go/system"
)
const (
// Flag for a header of a simple message.
MessageNoFlag = 0
// Flag for a header of a message that expected a response.
MessageExpectsResponseFlag = 1 << 0
// Flag for a header of a message that is a response.
MessageIsResponseFlag = 1 << 1
dataHeaderSize = 8
defaultAlignment = 8
pointerBitSize = 64
)
var mapHeader DataHeader
func init() {
mapHeader = DataHeader{24, 0}
}
const (
DifferentSizedArraysInMap = "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP"
IllegalHandle = "VALIDATION_ERROR_ILLEGAL_HANDLE"
IllegalMemoryRange = "VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE"
IllegalPointer = "VALIDATION_ERROR_ILLEGAL_POINTER"
MessageHeaderInvalidFlags = "VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS"
MessageHeaderMissingRequestId = "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID"
MessageHeaderUnknownMethod = "VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD"
MisalignedObject = "VALIDATION_ERROR_MISALIGNED_OBJECT"
UnexpectedArrayHeader = "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER"
UnexpectedInvalidHandle = "VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE"
UnexpectedNullPointer = "VALIDATION_ERROR_UNEXPECTED_NULL_POINTER"
UnexpectedNullUnion = "VALIDATION_ERROR_UNEXPECTED_NULL_UNION"
UnexpectedStructHeader = "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER"
)
// ValidationError is an error that can happen during message validation.
type ValidationError struct {
ErrorCode string
Message string
}
func (e *ValidationError) Error() string {
return e.Message
}
// Payload is an interface implemented by a mojo struct that can encode/decode
// itself into mojo archive format.
type Payload interface {
Encode(encoder *Encoder) error
Decode(decoder *Decoder) error
}
// DataHeader is a header for a mojo complex element.
type DataHeader struct {
Size uint32
ElementsOrVersion uint32
}
// MessageHeader is a header information for a message.
type MessageHeader struct {
Type uint32
Flags uint32
RequestId uint64
}
func (h *MessageHeader) Encode(encoder *Encoder) error {
encoder.StartStruct(h.dataSize(), h.version())
if err := encoder.WriteUint32(h.Type); err != nil {
return err
}
if err := encoder.WriteUint32(h.Flags); err != nil {
return err
}
if h.Flags != MessageNoFlag {
if err := encoder.WriteUint64(h.RequestId); err != nil {
return err
}
}
return encoder.Finish()
}
func (h *MessageHeader) Decode(decoder *Decoder) error {
header, err := decoder.StartStruct()
if err != nil {
return err
}
version := header.ElementsOrVersion
if version > 1 {
return &ValidationError{UnexpectedStructHeader,
fmt.Sprintf("invalid message header: it should be of version 0 or 1, but has %d", version),
}
}
expectedSize := uint32(dataHeaderSize + 2*4)
if version == 1 {
expectedSize += 8
}
if expectedSize != header.Size {
return &ValidationError{UnexpectedStructHeader,
fmt.Sprintf("unexpected struct header size: expected %d, but got %d", expectedSize, header.Size),
}
}
if h.Type, err = decoder.ReadUint32(); err != nil {
return err
}
if h.Flags, err = decoder.ReadUint32(); err != nil {
return err
}
if version == 1 {
if h.Flags != MessageExpectsResponseFlag && h.Flags != MessageIsResponseFlag {
return &ValidationError{MessageHeaderInvalidFlags,
fmt.Sprintf("message header flags(%v) should be MessageExpectsResponseFlag or MessageIsResponseFlag", h.Flags),
}
}
if h.RequestId, err = decoder.ReadUint64(); err != nil {
return err
}
} else {
if h.Flags != MessageNoFlag {
return &ValidationError{MessageHeaderMissingRequestId, "missing request ID in message header"}
}
}
return decoder.Finish()
}
func (h *MessageHeader) dataSize() uint32 {
var size uint32
size = 2 * 4
if h.Flags != MessageNoFlag {
size += 8
}
return size
}
func (h *MessageHeader) version() uint32 {
if h.Flags != MessageNoFlag {
return 1
} else {
return 0
}
}
// Message is a a raw message to be sent/received from a message pipe handle
// which contains a message header.
type Message struct {
Header MessageHeader
Bytes []byte
Handles []system.UntypedHandle
Payload []byte
}
func newMessage(header MessageHeader, bytes []byte, handles []system.UntypedHandle) *Message {
return &Message{header, bytes, handles, bytes[header.dataSize()+dataHeaderSize:]}
}
// DecodePayload decodes the provided payload from the message.
func (m *Message) DecodePayload(payload Payload) error {
decoder := NewDecoder(m.Payload, m.Handles)
if err := payload.Decode(decoder); err != nil {
return err
}
return nil
}
// EncodeMessage returns a message with provided header that has provided
// payload encoded in mojo archive format.
func EncodeMessage(header MessageHeader, payload Payload) (*Message, error) {
encoder := NewEncoder()
if err := header.Encode(encoder); err != nil {
return nil, err
}
if err := payload.Encode(encoder); err != nil {
return nil, err
}
if bytes, handles, err := encoder.Data(); err != nil {
return nil, err
} else {
return newMessage(header, bytes, handles), nil
}
}
// ParseMessage parses message header from byte buffer with attached handles
// and returnes parsed message.
func ParseMessage(bytes []byte, handles []system.UntypedHandle) (*Message, error) {
decoder := NewDecoder(bytes, []system.UntypedHandle{})
var header MessageHeader
if err := header.Decode(decoder); err != nil {
return nil, err
}
return newMessage(header, bytes, handles), nil
}

@ -1,228 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"fmt"
"sync"
"mojo/public/go/system"
)
// MessageReadResult contains information returned after reading and parsing
// a message: a non-nil error of a valid message.
type MessageReadResult struct {
Message *Message
Error error
}
// routeRequest is a request sent from Router to routerWorker.
type routeRequest struct {
// The outgoing message with non-zero request id.
message *Message
// The channel to send respond for the message.
responseChan chan<- MessageReadResult
}
// routerWorker sends messages that require a response and and routes responses
// to appropriate receivers. The work is done on a separate go routine.
type routerWorker struct {
// The message pipe handle to send requests and receive responses.
handle system.MessagePipeHandle
// Map from request id to response channel.
responders map[uint64]chan<- MessageReadResult
// The channel of incoming requests that require responses.
requestChan <-chan routeRequest
// The channel that indicates that the worker should terminate.
done <-chan struct{}
// Implementation of async waiter.
waiter AsyncWaiter
waitChan chan WaitResponse
waitId AsyncWaitId
}
// readOutstandingMessages reads and dispatches available messages in the
// message pipe until the messages is empty or there are no waiting responders.
// If the worker is currently waiting on the message pipe, returns immediately
// without an error.
func (w *routerWorker) readAndDispatchOutstandingMessages() error {
if w.waitId != 0 {
// Still waiting for a new message in the message pipe.
return nil
}
for len(w.responders) > 0 {
result, bytes, handles := w.handle.ReadMessage(system.MOJO_READ_MESSAGE_FLAG_NONE)
if result == system.MOJO_RESULT_SHOULD_WAIT {
w.waitId = w.waiter.AsyncWait(w.handle, system.MOJO_HANDLE_SIGNAL_READABLE, w.waitChan)
return nil
}
if result != system.MOJO_RESULT_OK {
return &ConnectionError{result}
}
message, err := ParseMessage(bytes, handles)
if err != nil {
return err
}
id := message.Header.RequestId
w.responders[id] <- MessageReadResult{message, nil}
delete(w.responders, id)
}
return nil
}
func (w *routerWorker) cancelIfWaiting() {
if w.waitId != 0 {
w.waiter.CancelWait(w.waitId)
w.waitId = 0
}
}
// runLoop is the main run loop of the worker. It processes incoming requests
// from Router and waits on a message pipe for new messages.
// Returns an error describing the cause of stopping.
func (w *routerWorker) runLoop() error {
for {
select {
case waitResponse := <-w.waitChan:
w.waitId = 0
if waitResponse.Result != system.MOJO_RESULT_OK {
return &ConnectionError{waitResponse.Result}
}
case request := <-w.requestChan:
if err := WriteMessage(w.handle, request.message); err != nil {
return err
}
if request.responseChan != nil {
w.responders[request.message.Header.RequestId] = request.responseChan
}
case <-w.done:
return errConnectionClosed
}
// Returns immediately without an error if still waiting for
// a new message.
if err := w.readAndDispatchOutstandingMessages(); err != nil {
return err
}
}
}
// Router sends messages to a message pipe and routes responses back to senders
// of messages with non-zero request ids. The caller should issue unique request
// ids for each message given to the router.
type Router struct {
// Mutex protecting requestChan from new requests in case the router is
// closed and the handle.
mu sync.Mutex
// The message pipe handle to send requests and receive responses.
handle system.MessagePipeHandle
// Channel to communicate with worker.
requestChan chan<- routeRequest
// Makes sure that the done channel is closed once.
closeOnce sync.Once
// Channel to stop the worker.
done chan<- struct{}
}
// NewRouter returns a new Router instance that sends and receives messages
// from a provided message pipe handle.
func NewRouter(handle system.MessagePipeHandle, waiter AsyncWaiter) *Router {
requestChan := make(chan routeRequest, 10)
doneChan := make(chan struct{})
router := &Router{
handle: handle,
requestChan: requestChan,
done: doneChan,
}
router.runWorker(&routerWorker{
handle,
make(map[uint64]chan<- MessageReadResult),
requestChan,
doneChan,
waiter,
make(chan WaitResponse, 1),
0,
})
return router
}
// Close closes the router and the underlying message pipe. All new incoming
// requests are returned with an error.
func (r *Router) Close() {
r.closeOnce.Do(func() {
close(r.done)
})
}
// Accept sends a message to the message pipe. The message should have a
// zero request id in header.
func (r *Router) Accept(message *Message) error {
if message.Header.RequestId != 0 {
return fmt.Errorf("message header should have a zero request ID")
}
r.mu.Lock()
defer r.mu.Unlock()
if !r.handle.IsValid() {
return errConnectionClosed
}
r.requestChan <- routeRequest{message, nil}
return nil
}
func (r *Router) runWorker(worker *routerWorker) {
// Run worker on a separate go routine.
go func() {
// Get the reason why the worker stopped. The error means that
// either the router is closed or there was an error reading
// or writing to a message pipe. In both cases it will be
// the reason why we can't process any more requests.
err := worker.runLoop()
worker.cancelIfWaiting()
// Respond to all pending requests.
for _, responseChan := range worker.responders {
responseChan <- MessageReadResult{nil, err}
}
// Respond to incoming requests until we make sure that all
// new requests return with an error before sending request
// to responseChan.
go func() {
for responder := range worker.requestChan {
responder.responseChan <- MessageReadResult{nil, err}
}
}()
r.mu.Lock()
r.handle.Close()
// If we acquire the lock then no other go routine is waiting
// to write to responseChan. All go routines that acquire the
// lock after us will return before sending to responseChan as
// the underlying handle is invalid (already closed).
// We can safely close the requestChan.
close(r.requestChan)
r.mu.Unlock()
}()
}
// AcceptWithResponse sends a message to the message pipe and returns a channel
// that will stream the result of reading corresponding response. The message
// should have a non-zero request id in header. It is responsibility of the
// caller to issue unique request ids for all given messages.
func (r *Router) AcceptWithResponse(message *Message) <-chan MessageReadResult {
responseChan := make(chan MessageReadResult, 1)
if message.Header.RequestId == 0 {
responseChan <- MessageReadResult{nil, fmt.Errorf("message header should have a request ID")}
return responseChan
}
r.mu.Lock()
defer r.mu.Unlock()
// Return an error before sending a request to requestChan if the router
// is closed so that we can safely close responseChan once we close the
// router.
if !r.handle.IsValid() {
responseChan <- MessageReadResult{nil, errConnectionClosed}
return responseChan
}
r.requestChan <- routeRequest{message, responseChan}
return responseChan
}

@ -1,63 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"sync"
)
// MessageReceiver can receive |Message| objects.
type MessageReceiver interface {
// Accept receives a |Message|. Returns a error if the message was not
// handled.
Accept(message *Message) error
}
// Stub is a base implementation of Stub. Stubs receives messages from message
// pipe, deserialize the payload and call the appropriate method in the
// implementation. If the method returns result, the stub serializes the
// response and sends it back.
type Stub struct {
// Makes sure that connector is closed only once.
closeOnce sync.Once
connector *Connector
receiver MessageReceiver
}
// NewStub returns a new Stub instance using provided |Connector| to send and
// receive messages. Incoming messages are handled by the provided |receiver|.
func NewStub(connector *Connector, receiver MessageReceiver) *Stub {
return &Stub{
connector: connector,
receiver: receiver,
}
}
// ServeRequest synchronously serves one request from the message pipe: the
// |Stub| waits on its underlying message pipe for a message and handles it.
// Can be called from multiple goroutines. Each calling goroutine will receive
// a different message or an error. Closes itself in case of error.
func (s *Stub) ServeRequest() error {
message, err := s.connector.ReadMessage()
if err != nil {
s.Close()
return err
}
err = s.receiver.Accept(message)
if err != nil {
s.Close()
}
return err
}
// Close immediately closes the |Stub| and its underlying message pipe. If the
// |Stub| is waiting on its message pipe handle the wait process is interrupted.
// All goroutines trying to serve will start returning errors as the underlying
// message pipe becomes invalid.
func (s *Stub) Close() {
s.closeOnce.Do(func() {
s.connector.Close()
})
}

@ -1,59 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package bindings
import (
"sync/atomic"
"mojo/public/go/system"
)
func align(size, alignment int) int {
return ((size - 1) | (alignment - 1)) + 1
}
// bytesForBits returns minimum number of bytes required to store provided
// number of bits.
func bytesForBits(bits uint64) int {
return int((bits + 7) / 8)
}
// WriteMessage writes a message to a message pipe.
func WriteMessage(handle system.MessagePipeHandle, message *Message) error {
result := handle.WriteMessage(message.Bytes, message.Handles, system.MOJO_WRITE_MESSAGE_FLAG_NONE)
if result != system.MOJO_RESULT_OK {
return &ConnectionError{result}
}
return nil
}
// StringPointer converts provided string to *string.
func StringPointer(s string) *string {
return &s
}
// Counter is a simple thread-safe lock-free counter that can issue unique
// numbers starting from 1 to callers.
type Counter interface {
// Count returns next unused value, each value is returned only once.
Count() uint64
}
// NewCounter return a new counter that returns numbers starting from 1.
func NewCounter() Counter {
return &counterImpl{}
}
// counterImpl implements Counter interface.
// This implementation uses atomic operations on an uint64, it should be always
// allocated separatelly to be 8-aligned in order to work correctly on ARM.
// See http://golang.org/pkg/sync/atomic/#pkg-note-BUG.
type counterImpl struct {
last uint64
}
func (c *counterImpl) Count() uint64 {
return atomic.AddUint64(&c.last, 1)
}

@ -1,147 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
import (
"runtime"
"sync"
)
// core is an instance of the Mojo system APIs implementation.
var core coreImpl
// Core is an interface giving access to the base operations.
// See |src/mojo/public/c/system/core.h| for the underlying api.
type Core interface {
// AcquireNativeHandle acquires a handle from the native side. The handle
// will be owned by the returned object and must not be closed outside of
// it.
AcquireNativeHandle(handle MojoHandle) UntypedHandle
// GetTimeTicksNow returns a monotonically increasing platform dependent
// tick count representing "right now". Resolution depends on the system
// configuration.
GetTimeTicksNow() MojoTimeTicks
// WaitMany behaves as if Wait were called on each handle/signal pair
// simultaneously and completing when the first Wait would complete.
// Notes about return values:
// |index| can be -1 if the error returned was not caused by a
// particular handle. For example, the error MOJO_RESULT_DEADLINE_EXCEEDED
// is not related to a particular handle.
// |states| can be nil if the signal array could not be returned. This can
// happen with errors such as MOJO_RESULT_INVALID_ARGUMENT.
WaitMany(handles []Handle, signals []MojoHandleSignals, deadline MojoDeadline) (result MojoResult, index int, states []MojoHandleSignalsState)
// CreateDataPipe creates a data pipe which is a unidirectional
// communication channel for unframed data. On success, returns a
// handle to the producer and consumer of the data pipe.
CreateDataPipe(opts *DataPipeOptions) (MojoResult, ProducerHandle, ConsumerHandle)
// CreateMessagePipe creates a message pipe which is a bidirectional
// communication channel for framed data (i.e., messages). Messages
// can contain plain data and/or Mojo handles. On success, it returns
// handles to the two endpoints of the message pipe.
CreateMessagePipe(opts *MessagePipeOptions) (MojoResult, MessagePipeHandle, MessagePipeHandle)
// CreateSharedBuffer creates a buffer of size numBytes that can be
// shared between applications. One must call MapBuffer to access
// the buffer.
CreateSharedBuffer(opts *SharedBufferOptions, numBytes uint64) (MojoResult, SharedBufferHandle)
}
// coreImpl is an implementation of the Mojo system APIs.
type coreImpl struct {
// Protects from making parallel non-blocking mojo cgo calls.
mu sync.Mutex
}
// GetCore returns singleton instance of the Mojo system APIs implementation.
//
// The implementation uses cgo to call native mojo APIs implementation. Each cgo
// call uses a separate thread for execution. To limit the number of used
// threads all non-blocking system calls (i.e. all system calls except |Wait|
// and |WaitMany|) on this implementation and on handles returned by this
// implementation are protected by a mutex so that if you make two parallel
// system calls one will wait for another to finish before executing.
// However, |Wait| and |WaitMany| are not protected by a mutex and each parallel
// call will use a separate thread. To reduce number of threads used for |Wait|
// calls prefer to use |WaitMany|.
func GetCore() Core {
return &core
}
func (impl *coreImpl) AcquireNativeHandle(mojoHandle MojoHandle) UntypedHandle {
handle := &untypedHandleImpl{baseHandle{impl, mojoHandle}}
runtime.SetFinalizer(handle, finalizeHandle)
return handle
}
func (impl *coreImpl) GetTimeTicksNow() MojoTimeTicks {
impl.mu.Lock()
r := sysImpl.GetTimeTicksNow()
impl.mu.Unlock()
return MojoTimeTicks(r)
}
func (impl *coreImpl) WaitMany(handles []Handle, signals []MojoHandleSignals, deadline MojoDeadline) (MojoResult, int, []MojoHandleSignalsState) {
if len(handles) == 0 {
r, _, _, _ := sysImpl.WaitMany(nil, nil, uint64(deadline))
return MojoResult(r), -1, nil
}
rawHandles := make([]uint32, len(handles))
rawSignals := make([]uint32, len(signals))
for i := 0; i < len(handles); i++ {
rawHandles[i] = uint32(handles[i].NativeHandle())
rawSignals[i] = uint32(signals[i])
}
r, index, rawSatisfiedSignals, rawSatisfiableSignals := sysImpl.WaitMany(rawHandles, rawSignals, uint64(deadline))
if MojoResult(r) == MOJO_RESULT_INVALID_ARGUMENT || MojoResult(r) == MOJO_RESULT_RESOURCE_EXHAUSTED {
return MojoResult(r), index, nil
}
signalsStates := make([]MojoHandleSignalsState, len(handles))
for i := 0; i < len(handles); i++ {
signalsStates[i].SatisfiedSignals = MojoHandleSignals(rawSatisfiedSignals[i])
signalsStates[i].SatisfiableSignals = MojoHandleSignals(rawSatisfiableSignals[i])
}
return MojoResult(r), index, signalsStates
}
func (impl *coreImpl) CreateDataPipe(opts *DataPipeOptions) (MojoResult, ProducerHandle, ConsumerHandle) {
var r uint32
var p, c uint32
impl.mu.Lock()
if opts == nil {
r, p, c = sysImpl.CreateDataPipeWithDefaultOptions()
} else {
r, p, c = sysImpl.CreateDataPipe(uint32(opts.Flags), uint32(opts.ElemSize), uint32(opts.Capacity))
}
impl.mu.Unlock()
return MojoResult(r), impl.AcquireNativeHandle(MojoHandle(p)).ToProducerHandle(), impl.AcquireNativeHandle(MojoHandle(c)).ToConsumerHandle()
}
func (impl *coreImpl) CreateMessagePipe(opts *MessagePipeOptions) (MojoResult, MessagePipeHandle, MessagePipeHandle) {
var flags uint32
if opts != nil {
flags = uint32(opts.Flags)
}
impl.mu.Lock()
r, handle0, handle1 := sysImpl.CreateMessagePipe(flags)
impl.mu.Unlock()
return MojoResult(r), impl.AcquireNativeHandle(MojoHandle(handle0)).ToMessagePipeHandle(), impl.AcquireNativeHandle(MojoHandle(handle1)).ToMessagePipeHandle()
}
func (impl *coreImpl) CreateSharedBuffer(opts *SharedBufferOptions, numBytes uint64) (MojoResult, SharedBufferHandle) {
var flags uint32
if opts != nil {
flags = uint32(opts.Flags)
}
impl.mu.Lock()
r, handle := sysImpl.CreateSharedBuffer(flags, numBytes)
impl.mu.Unlock()
return MojoResult(r), impl.AcquireNativeHandle(MojoHandle(handle)).ToSharedBufferHandle()
}

@ -1,131 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
// ConsumerHandle is a handle for the consumer part of a data pipe.
type ConsumerHandle interface {
Handle
// ReadData reads data from the data pipe consumer handle with the
// given flags. On success, returns the data that was read.
ReadData(flags MojoReadDataFlags) (MojoResult, []byte)
// BeginReadData begins a two-phase read from the data pipe consumer.
// On success, returns a slice from which the caller can read up to its
// length bytes of data. If flags has |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
// set, then the slice length will be at least as large as |numBytes|,
// which must also be a multiple of the element size (otherwise the
// caller must check the length of the slice).
//
// During a two-phase read, this handle is *not* readable. E.g., read
// from this handle will return |MOJO_RESULT_BUSY|.
//
// Once the caller has finished reading data from the slice, it should
// call |EndReadData()| to specify the amount read and to complete the
// two-phase read.
BeginReadData(numBytes int, flags MojoReadDataFlags) (MojoResult, []byte)
// EndReadData ends a two-phase read from the data pipe consumer that
// was begun by a call to |BeginReadData()| on the same handle.
// |numBytesRead| should indicate the amount of data actually read; it
// must be less than or equal to the length of the slice returned by
// |BeginReadData()| and must be a multiple of the element size.
//
// On failure, the two-phase read (if any) is ended (so the handle may
// become readable again) but no data is "removed" from the data pipe.
EndReadData(numBytesRead int) MojoResult
}
// ProducerHandle is a handle for the producer part of a data pipe.
type ProducerHandle interface {
Handle
// WriteData writes data to the data pipe producer handle with the
// given flags. On success, returns the number of bytes that were
// actually written.
WriteData(data []byte, flags MojoWriteDataFlags) (MojoResult, int)
// BeginWriteData begins a two-phase write to the data pipe producer.
// On success, returns a slice to which the caller can write. If flags
// has |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, then the slice length will
// be at least as large as |numBytes|, which must also be a multiple of
// the element size (otherwise the caller must check the length of the
// slice).
//
// During a two-phase write, this handle is *not* writable. E.g., write
// to this handle will return |MOJO_RESULT_BUSY|.
//
// Once the caller has finished writing data to the buffer, it should
// call |EndWriteData()| to specify the amount written and to complete
// the two-phase write.
BeginWriteData(numBytes int, flags MojoWriteDataFlags) (MojoResult, []byte)
// EndWriteData ends a two-phase write to the data pipe producer that
// was begun by a call to |BeginWriteData()| on the same handle.
// |numBytesWritten| should indicate the amount of data actually
// written; it must be less than or equal to the length of the slice
// returned by |BeginWriteData()| and must be a multiple of the element
// size. The slice returned from |BeginWriteData()| must have been
// filled with exactly |numBytesWritten| bytes of data.
//
// On failure, the two-phase write (if any) is ended (so the handle may
// become writable again, if there's space available) but no data
// written to the slice is "put into" the data pipe.
EndWriteData(numBytesWritten int) MojoResult
}
type dataPipeConsumer struct {
// baseHandle should always be the first component of this struct,
// see |finalizeHandle()| for more details.
baseHandle
}
func (h *dataPipeConsumer) ReadData(flags MojoReadDataFlags) (MojoResult, []byte) {
h.core.mu.Lock()
r, buf := sysImpl.ReadData(uint32(h.mojoHandle), uint32(flags))
h.core.mu.Unlock()
return MojoResult(r), buf
}
func (h *dataPipeConsumer) BeginReadData(numBytes int, flags MojoReadDataFlags) (MojoResult, []byte) {
h.core.mu.Lock()
r, buf := sysImpl.BeginReadData(uint32(h.mojoHandle), uint32(numBytes), uint32(flags))
h.core.mu.Unlock()
return MojoResult(r), buf
}
func (h *dataPipeConsumer) EndReadData(numBytesRead int) MojoResult {
h.core.mu.Lock()
r := sysImpl.EndReadData(uint32(h.mojoHandle), uint32(numBytesRead))
h.core.mu.Unlock()
return MojoResult(r)
}
type dataPipeProducer struct {
// baseHandle should always be the first component of this struct,
// see |finalizeHandle()| for more details.
baseHandle
}
func (h *dataPipeProducer) WriteData(data []byte, flags MojoWriteDataFlags) (MojoResult, int) {
h.core.mu.Lock()
r, bytesWritten := sysImpl.WriteData(uint32(h.mojoHandle), data, uint32(flags))
h.core.mu.Unlock()
return MojoResult(r), int(bytesWritten)
}
func (h *dataPipeProducer) BeginWriteData(numBytes int, flags MojoWriteDataFlags) (MojoResult, []byte) {
h.core.mu.Lock()
r, buf := sysImpl.BeginWriteData(uint32(h.mojoHandle), uint32(numBytes), uint32(flags))
h.core.mu.Unlock()
return MojoResult(r), buf
}
func (h *dataPipeProducer) EndWriteData(numBytesWritten int) MojoResult {
h.core.mu.Lock()
r := sysImpl.EndWriteData(uint32(h.mojoHandle), uint32(numBytesWritten))
h.core.mu.Unlock()
return MojoResult(r)
}

@ -1,169 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
import (
"log"
"runtime"
)
// Handle is a generic handle for mojo objects.
type Handle interface {
// Close closes the given handle.
Close() MojoResult
// IsValid returns whether the handle is valid. A handle is valid until it
// has been explicitly closed or sent through a message pipe.
IsValid() bool
// NativeHandle returns the native handle backed by this handle.
//
// Note: try to avoid using this method as you lose ownership tracking.
NativeHandle() MojoHandle
// ReleaseNativeHandle releases the native handle backed by this handle.
// The caller owns the handle and must close it.
ReleaseNativeHandle() MojoHandle
// ToUntypedHandle converts this handle into an UntypedHandle, invalidating
// this handle.
ToUntypedHandle() UntypedHandle
// Wait waits on the handle until a signal indicated by signals is satisfied
// or it becomes known that no signal indicated by signals will ever be
// satisified or until deadline has passed.
Wait(signals MojoHandleSignals, deadline MojoDeadline) (MojoResult, MojoHandleSignalsState)
}
// UntypedHandle is a a mojo handle of unknown type. This handle can be typed by
// using one of its methods, which will return a handle of the requested type
// and invalidate this object. No validation is made when the conversion
// operation is called.
type UntypedHandle interface {
Handle
// ToConsumerHandle returns the underlying handle as a ConsumerHandle
// and invalidates this UntypedHandle representation.
ToConsumerHandle() ConsumerHandle
// ToProducerHandle returns the underlying handle as a ProducerHandle
// and invalidates this UntypedHandle representation.
ToProducerHandle() ProducerHandle
// ToMessagePipeHandle returns the underlying handle as a MessagePipeHandle
// and invalidates this UntypedHandle representation.
ToMessagePipeHandle() MessagePipeHandle
// ToSharedBufferHandle returns the underlying handle as a
// SharedBufferHandle and invalidates this UntypedHandle representation.
ToSharedBufferHandle() SharedBufferHandle
}
// finalizeHandle closes handles that becomes unreachable in runtime.
// We want to make sure that every mojo handle is closed, so we set this
// finalizer function on every handle object we create. If a handle object
// becomes invalidated (because the handle was closed or the underlying mojo
// handle has been passed to another handle object), we remove the finalizer.
//
// The finalizing mechanism works tricky: runtime.SetFinalizer can be called on
// an object allocated by calling new or by taking the address of a composite
// literal, so we can't set a finalizer on an embedded struct if the embedded
// struct has a non-zero offset related to the outmost struct.
//
// Type structure of handles is the following: there is a struct baseHandle,
// which serves as a "base class" for all the typed handles (i.e. sharedBuffer,
// untypedHandleImpl, dataPipeProducer, dataPipeConsumer and messagePipe). We
// express it by struct embedding. When we operate with handles, we create typed
// handles and set finalizers on them, while to invalidate a handle and remove
// finalizer we call methods on the embedded baseHandle struct. So in order for
// finalizers to work correct we need to make sure that baseHandle is the first
// component of typed handles.
func finalizeHandle(h Handle) {
log.Println("Handle was not closed.")
h.Close()
}
type baseHandle struct {
core *coreImpl
mojoHandle MojoHandle
}
func (h *baseHandle) invalidate() {
h.mojoHandle = MOJO_HANDLE_INVALID
runtime.SetFinalizer(h, nil)
}
func (h *baseHandle) Close() MojoResult {
mojoHandle := h.mojoHandle
h.invalidate()
h.core.mu.Lock()
r := sysImpl.Close(uint32(mojoHandle))
h.core.mu.Unlock()
return MojoResult(r)
}
func (h *baseHandle) IsValid() bool {
return h.mojoHandle != MOJO_HANDLE_INVALID
}
func (h *baseHandle) NativeHandle() MojoHandle {
return h.mojoHandle
}
func (h *baseHandle) ReleaseNativeHandle() MojoHandle {
mojoHandle := h.mojoHandle
h.invalidate()
return mojoHandle
}
func (h *baseHandle) ToUntypedHandle() UntypedHandle {
handle := &untypedHandleImpl{*h}
runtime.SetFinalizer(handle, finalizeHandle)
h.invalidate()
return handle
}
func (h *baseHandle) Wait(signals MojoHandleSignals, deadline MojoDeadline) (MojoResult, MojoHandleSignalsState) {
r, satisfiedSignals, satisfiableSignals := sysImpl.Wait(uint32(h.mojoHandle), uint32(signals), uint64(deadline))
state := MojoHandleSignalsState{
SatisfiedSignals: MojoHandleSignals(satisfiedSignals),
SatisfiableSignals: MojoHandleSignals(satisfiableSignals),
}
return MojoResult(r), state
}
type untypedHandleImpl struct {
// baseHandle should always be the first component of this struct,
// see |finalizeHandle()| for more details.
baseHandle
}
func (h *untypedHandleImpl) ToConsumerHandle() ConsumerHandle {
handle := &dataPipeConsumer{h.baseHandle}
runtime.SetFinalizer(handle, finalizeHandle)
h.invalidate()
return handle
}
func (h *untypedHandleImpl) ToProducerHandle() ProducerHandle {
handle := &dataPipeProducer{h.baseHandle}
runtime.SetFinalizer(handle, finalizeHandle)
h.invalidate()
return handle
}
func (h *untypedHandleImpl) ToMessagePipeHandle() MessagePipeHandle {
handle := &messagePipe{h.baseHandle}
runtime.SetFinalizer(handle, finalizeHandle)
h.invalidate()
return handle
}
func (h *untypedHandleImpl) ToSharedBufferHandle() SharedBufferHandle {
handle := &sharedBuffer{h.baseHandle}
runtime.SetFinalizer(handle, finalizeHandle)
h.invalidate()
return handle
}

@ -1,59 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
// MessagePipeHandle is a handle for a bidirectional communication channel for
// framed data (i.e., messages). Messages can contain plain data and/or Mojo
// handles.
type MessagePipeHandle interface {
Handle
// ReadMessage reads a message from the message pipe endpoint with the
// specified flags. Returns the message data and attached handles that were
// received in the "next" message.
ReadMessage(flags MojoReadMessageFlags) (MojoResult, []byte, []UntypedHandle)
// WriteMessage writes message data and optional attached handles to
// the message pipe endpoint given by handle. On success the attached
// handles will no longer be valid (i.e.: the receiver will receive
// equivalent but logically different handles).
WriteMessage(bytes []byte, handles []UntypedHandle, flags MojoWriteMessageFlags) MojoResult
}
type messagePipe struct {
// baseHandle should always be the first component of this struct,
// see |finalizeHandle()| for more details.
baseHandle
}
func (h *messagePipe) ReadMessage(flags MojoReadMessageFlags) (MojoResult, []byte, []UntypedHandle) {
h.core.mu.Lock()
r, buf, rawHandles := sysImpl.ReadMessage(uint32(h.mojoHandle), uint32(flags))
h.core.mu.Unlock()
if r != 0 {
return MojoResult(r), nil, nil
}
handles := make([]UntypedHandle, len(rawHandles))
for i := 0; i < len(handles); i++ {
handles[i] = h.core.AcquireNativeHandle(MojoHandle(rawHandles[i]))
}
return MojoResult(r), buf, handles
}
func (h *messagePipe) WriteMessage(bytes []byte, handles []UntypedHandle, flags MojoWriteMessageFlags) MojoResult {
var rawHandles []uint32
if len(handles) != 0 {
rawHandles = make([]uint32, len(handles))
for i := 0; i < len(handles); i++ {
rawHandles[i] = uint32(handles[i].ReleaseNativeHandle())
}
}
h.core.mu.Lock()
r := sysImpl.WriteMessage(uint32(h.mojoHandle), bytes, rawHandles, uint32(flags))
h.core.mu.Unlock()
return MojoResult(r)
}

@ -1,127 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
import "math"
// Go equivalent definitions of the various system types defined in Mojo.
// mojo/public/c/system/types.h
// mojo/public/c/system/data_pipe.h
// mojo/public/c/system/message_pipe.h
//
type MojoTimeTicks int64
type MojoHandle uint32
type MojoResult uint32
type MojoDeadline uint64
type MojoHandleSignals uint32
type MojoWriteMessageFlags uint32
type MojoReadMessageFlags uint32
type MojoWriteDataFlags uint32
type MojoReadDataFlags uint32
type MojoCreateDataPipeOptionsFlags uint32
type MojoCreateMessagePipeOptionsFlags uint32
type MojoCreateSharedBufferOptionsFlags uint32
type MojoDuplicateBufferHandleOptionsFlags uint32
type MojoMapBufferFlags uint32
const (
MOJO_DEADLINE_INDEFINITE MojoDeadline = math.MaxUint64
MOJO_HANDLE_INVALID MojoHandle = 0
MOJO_RESULT_OK MojoResult = 0
MOJO_RESULT_CANCELLED MojoResult = 1
MOJO_RESULT_UNKNOWN MojoResult = 2
MOJO_RESULT_INVALID_ARGUMENT MojoResult = 3
MOJO_RESULT_DEADLINE_EXCEEDED MojoResult = 4
MOJO_RESULT_NOT_FOUND MojoResult = 5
MOJO_RESULT_ALREADY_EXISTS MojoResult = 6
MOJO_RESULT_PERMISSION_DENIED MojoResult = 7
MOJO_RESULT_RESOURCE_EXHAUSTED MojoResult = 8
MOJO_RESULT_FAILED_PRECONDITION MojoResult = 9
MOJO_RESULT_ABORTED MojoResult = 10
MOJO_RESULT_OUT_OF_RANGE MojoResult = 11
MOJO_RESULT_UNIMPLEMENTED MojoResult = 12
MOJO_RESULT_INTERNAL MojoResult = 13
MOJO_RESULT_UNAVAILABLE MojoResult = 14
MOJO_RESULT_DATA_LOSS MojoResult = 15
MOJO_RESULT_BUSY MojoResult = 16
MOJO_RESULT_SHOULD_WAIT MojoResult = 17
MOJO_HANDLE_SIGNAL_NONE MojoHandleSignals = 0
MOJO_HANDLE_SIGNAL_READABLE MojoHandleSignals = 1 << 0
MOJO_HANDLE_SIGNAL_WRITABLE MojoHandleSignals = 1 << 1
MOJO_HANDLE_SIGNAL_PEER_CLOSED MojoHandleSignals = 1 << 2
MOJO_WRITE_MESSAGE_FLAG_NONE MojoWriteMessageFlags = 0
MOJO_READ_MESSAGE_FLAG_NONE MojoReadMessageFlags = 0
MOJO_READ_MESSAGE_FLAG_MAY_DISCARD MojoReadMessageFlags = 1 << 0
MOJO_READ_DATA_FLAG_NONE MojoReadDataFlags = 0
MOJO_READ_DATA_FLAG_ALL_OR_NONE MojoReadDataFlags = 1 << 0
MOJO_READ_DATA_FLAG_DISCARD MojoReadDataFlags = 1 << 1
MOJO_READ_DATA_FLAG_QUERY MojoReadDataFlags = 1 << 2
MOJO_READ_DATA_FLAG_PEEK MojoReadDataFlags = 1 << 3
MOJO_WRITE_DATA_FLAG_NONE MojoWriteDataFlags = 0
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE MojoWriteDataFlags = 1 << 0
MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE MojoCreateDataPipeOptionsFlags = 0
MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE MojoCreateMessagePipeOptionsFlags = 0
MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE MojoCreateSharedBufferOptionsFlags = 0
MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE MojoDuplicateBufferHandleOptionsFlags = 0
MOJO_MAP_BUFFER_FLAG_NONE MojoMapBufferFlags = 0
)
// IsReadable returns true iff the |MOJO_HANDLE_SIGNAL_READABLE| bit is set.
func (m MojoHandleSignals) IsReadable() bool {
return (m & MOJO_HANDLE_SIGNAL_READABLE) != 0
}
// IsWritable returns true iff the |MOJO_HANDLE_SIGNAL_WRITABLE| bit is set.
func (m MojoHandleSignals) IsWritable() bool {
return (m & MOJO_HANDLE_SIGNAL_WRITABLE) != 0
}
// IsClosed returns true iff the |MOJO_HANDLE_SIGNAL_PEER_CLOSED| bit is set.
func (m MojoHandleSignals) IsClosed() bool {
return (m & MOJO_HANDLE_SIGNAL_PEER_CLOSED) != 0
}
// MojoHandleSignalsState is a struct returned by wait functions to indicate
// the signaling state of handles.
type MojoHandleSignalsState struct {
// Signals that were satisfied at some time before the call returned.
SatisfiedSignals MojoHandleSignals
// Signals that are possible to satisfy. For example, if the return value
// was |MOJO_RESULT_FAILED_PRECONDITION|, you can use this field to
// determine which, if any, of the signals can still be satisfied.
SatisfiableSignals MojoHandleSignals
}
// DataPipeOptions is used to specify creation parameters for a data pipe.
type DataPipeOptions struct {
Flags MojoCreateDataPipeOptionsFlags
// The size of an element in bytes. All transactions and buffers will
// be an integral number of elements.
ElemSize uint32
// The capacity of the data pipe in bytes. Must be a multiple of elemSize.
Capacity uint32
}
// MessagePipeOptions is used to specify creation parameters for a message pipe.
type MessagePipeOptions struct {
Flags MojoCreateMessagePipeOptionsFlags
}
// SharedBufferOptions is used to specify creation parameters for a
// shared buffer.
type SharedBufferOptions struct {
Flags MojoCreateSharedBufferOptionsFlags
}
// DuplicateBufferHandleOptions is used to specify parameters in
// duplicating access to a shared buffer.
type DuplicateBufferHandleOptions struct {
Flags MojoDuplicateBufferHandleOptionsFlags
}

@ -1,75 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
import (
"reflect"
"unsafe"
)
// SharedBufferHandle is a handle for a buffer that can be shared between
// applications.
type SharedBufferHandle interface {
Handle
// DuplicateBufferHandle duplicates the handle to a buffer.
DuplicateBufferHandle(opts *DuplicateBufferHandleOptions) (MojoResult, SharedBufferHandle)
// MapBuffer maps the requested part of the shared buffer given by handle
// into memory with specified flags. On success, it returns slice that
// points to the requested shared buffer.
MapBuffer(offset uint64, numBytes int, flags MojoMapBufferFlags) (MojoResult, []byte)
// UnmapBuffer unmaps a buffer that was returned by MapBuffer.
UnmapBuffer(buffer []byte) MojoResult
}
type sharedBuffer struct {
// baseHandle should always be the first component of this struct,
// see |finalizeHandle()| for more details.
baseHandle
}
func (h *sharedBuffer) DuplicateBufferHandle(opts *DuplicateBufferHandleOptions) (MojoResult, SharedBufferHandle) {
var flags uint32
if opts != nil {
flags = uint32(opts.Flags)
}
h.core.mu.Lock()
r, dup := sysImpl.DuplicateBufferHandle(uint32(h.mojoHandle), flags)
h.core.mu.Unlock()
return MojoResult(r), core.AcquireNativeHandle(MojoHandle(dup)).ToSharedBufferHandle()
}
func (h *sharedBuffer) MapBuffer(offset uint64, numBytes int, flags MojoMapBufferFlags) (MojoResult, []byte) {
h.core.mu.Lock()
r, buf := sysImpl.MapBuffer(uint32(h.mojoHandle), offset, uint64(numBytes), uint32(flags))
h.core.mu.Unlock()
if r != 0 {
return MojoResult(r), nil
}
return MojoResult(r), buf
}
func (h *sharedBuffer) UnmapBuffer(buffer []byte) MojoResult {
h.core.mu.Lock()
r := sysImpl.UnmapBuffer(buffer)
h.core.mu.Unlock()
return MojoResult(r)
}
func newUnsafeSlice(ptr unsafe.Pointer, length int) unsafe.Pointer {
header := &reflect.SliceHeader{
Data: uintptr(ptr),
Len: length,
Cap: length,
}
return unsafe.Pointer(header)
}
func unsafeByteSlice(ptr unsafe.Pointer, length int) []byte {
return *(*[]byte)(newUnsafeSlice(ptr, length))
}

@ -1,46 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
// This interface wraps the "raw" mojo system entry points. This has no
// dependencies on other types in this package so it can be implemented
// by code that doesn't depend on this package.
type MojoSystem interface {
// Shared buffer
CreateSharedBuffer(flags uint32, numBytes uint64) (result uint32, handle uint32)
DuplicateBufferHandle(handle uint32, flags uint32) (result uint32, dupHandle uint32)
// After a successful MapBuffer call, the caller must pass the same slice value to UnmapBuffer to release
// the underlying memory segment.
MapBuffer(handle uint32, offset, numBytes uint64, flags uint32) (result uint32, buf []byte)
UnmapBuffer(buf []byte) (result uint32)
// Data pipe
CreateDataPipe(flags, elementNumBytes, capacityNumBytes uint32) (result uint32, producerHandle, consumerHandle uint32)
CreateDataPipeWithDefaultOptions() (result uint32, producerHandle, consumerHandle uint32)
WriteData(producerHandle uint32, buf []byte, flags uint32) (result uint32, bytesWritten uint32)
BeginWriteData(producerHandle uint32, numBytes uint32, flags uint32) (result uint32, buf []byte)
EndWriteData(producerHandle uint32, numBytesWritten uint32) (result uint32)
ReadData(consumerHandle, flags uint32) (result uint32, buf []byte)
BeginReadData(consumerHandle uint32, numBytes uint32, flags uint32) (result uint32, buf []byte)
EndReadData(consumerHandle uint32, numBytesRead uint32) (result uint32)
// Time
GetTimeTicksNow() (timestamp uint64)
// Close a handle
Close(handle uint32) (result uint32)
// Waiting
Wait(handle uint32, signals uint32, deadline uint64) (result uint32, satisfiedSignals, satisfiableSignals uint32)
WaitMany(handles []uint32, signals []uint32, deadline uint64) (result uint32, index int, satisfiedSignals, satisfiableSignals []uint32)
// Message pipe
CreateMessagePipe(flags uint32) (result uint32, handle0, handle1 uint32)
WriteMessage(handle uint32, bytes []byte, handles []uint32, flags uint32) (result uint32)
ReadMessage(handle uint32, flags uint32) (result uint32, buf []byte, handles []uint32)
}
var sysImpl MojoSystem

@ -1,12 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
import "mojo/public/platform/native_cgo"
// Linux uses the CGo based system implementation.
func init() {
sysImpl = &native_cgo.CGoSystem{}
}

@ -1,12 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
import "mojo/public/platform/native_cgo"
// Linux uses the CGo based system implementation.
func init() {
sysImpl = &native_cgo.CGoSystem{}
}

@ -1,12 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package system
import "runtime/nacl"
// NaCl uses the runtime's Mojo IRT based system implementation.
func init() {
sysImpl = &nacl.MojoNaClSystem{}
}

@ -1,258 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package native_cgo
//#include "mojo/public/c/system/core.h"
// // These functions are used to 8-byte align C structs.
// MojoResult CreateSharedBuffer(struct MojoCreateSharedBufferOptions* options,
// uint64_t num_bytes, MojoHandle* handle) {
// struct MojoCreateSharedBufferOptions aligned_options;
// if (options != NULL) {
// aligned_options = *options;
// return MojoCreateSharedBuffer(&aligned_options, num_bytes, handle);
// } else {
// return MojoCreateSharedBuffer(NULL, num_bytes, handle);
// }
// }
//
// MojoResult DuplicateBufferHandle(MojoHandle handle,
// struct MojoDuplicateBufferHandleOptions* options, MojoHandle* duplicate) {
// struct MojoDuplicateBufferHandleOptions aligned_options;
// if (options != NULL) {
// aligned_options = *options;
// return MojoDuplicateBufferHandle(handle, &aligned_options, duplicate);
// } else {
// return MojoDuplicateBufferHandle(handle, NULL, duplicate);
// }
// }
//
// MojoResult CreateDataPipe(struct MojoCreateDataPipeOptions* options,
// MojoHandle* producer, MojoHandle* consumer) {
// struct MojoCreateDataPipeOptions aligned_options;
// if (options != NULL) {
// aligned_options = *options;
// return MojoCreateDataPipe(&aligned_options, producer, consumer);
// } else {
// return MojoCreateDataPipe(NULL, producer, consumer);
// }
// }
//
// MojoResult CreateMessagePipe(struct MojoCreateMessagePipeOptions* options,
// MojoHandle* handle0, MojoHandle* handle1) {
// struct MojoCreateMessagePipeOptions aligned_options = *options;
// if (options != NULL) {
// aligned_options = *options;
// return MojoCreateMessagePipe(&aligned_options, handle0, handle1);
// } else {
// return MojoCreateMessagePipe(NULL, handle0, handle1);
// }
// }
//
import "C"
import (
"reflect"
"unsafe"
)
// CGoSystem provides an implementation of the system.System interface based on CGO
type CGoSystem struct{}
func (c *CGoSystem) CreateSharedBuffer(flags uint32, numBytes uint64) (uint32, uint32) {
var opts *C.struct_MojoCreateSharedBufferOptions
opts = &C.struct_MojoCreateSharedBufferOptions{
C.uint32_t(unsafe.Sizeof(*opts)),
C.MojoCreateSharedBufferOptionsFlags(flags),
}
var cHandle C.MojoHandle
r := C.CreateSharedBuffer(opts, C.uint64_t(numBytes), &cHandle)
return uint32(r), uint32(cHandle)
}
func (c *CGoSystem) DuplicateBufferHandle(handle uint32, flags uint32) (uint32, uint32) {
var opts *C.struct_MojoDuplicateBufferHandleOptions
opts = &C.struct_MojoDuplicateBufferHandleOptions{
C.uint32_t(unsafe.Sizeof(*opts)),
C.MojoDuplicateBufferHandleOptionsFlags(flags),
}
var cDuplicateHandle C.MojoHandle
r := C.DuplicateBufferHandle(C.MojoHandle(handle), opts, &cDuplicateHandle)
return uint32(r), uint32(cDuplicateHandle)
}
func (c *CGoSystem) MapBuffer(handle uint32, offset, numBytes uint64, flags uint32) (result uint32, buf []byte) {
var bufPtr unsafe.Pointer
r := C.MojoMapBuffer(C.MojoHandle(handle), C.uint64_t(offset), C.uint64_t(numBytes), &bufPtr, C.MojoMapBufferFlags(flags))
if r != C.MOJO_RESULT_OK {
return uint32(r), nil
}
return uint32(r), unsafeByteSlice(bufPtr, int(numBytes))
}
func (c *CGoSystem) UnmapBuffer(buf []byte) (result uint32) {
return uint32(C.MojoUnmapBuffer(unsafe.Pointer(&buf[0])))
}
func createDataPipeWithCOptions(opts *C.struct_MojoCreateDataPipeOptions) (result uint32, producerHandle, consumerHandle uint32) {
var cProducerHandle, cConsumerHandle C.MojoHandle
r := C.CreateDataPipe(opts, &cProducerHandle, &cConsumerHandle)
return uint32(r), uint32(cProducerHandle), uint32(cConsumerHandle)
}
func (c *CGoSystem) CreateDataPipe(flags, elementNumBytes, capacityNumBytes uint32) (result uint32, producerHandle, consumerHandle uint32) {
var opts *C.struct_MojoCreateDataPipeOptions
opts = &C.struct_MojoCreateDataPipeOptions{
C.uint32_t(unsafe.Sizeof(*opts)),
C.MojoCreateDataPipeOptionsFlags(flags),
C.uint32_t(elementNumBytes),
C.uint32_t(capacityNumBytes),
}
return createDataPipeWithCOptions(opts)
}
func (c *CGoSystem) CreateDataPipeWithDefaultOptions() (result uint32, producerHandle, consumerHandle uint32) {
// A nil options pointer in the C interface means use the default values.
return createDataPipeWithCOptions(nil)
}
func (c *CGoSystem) WriteData(producerHandle uint32, buf []byte, flags uint32) (result uint32, bytesWritten uint32) {
numBytes := C.uint32_t(len(buf))
r := C.MojoWriteData(C.MojoHandle(producerHandle), unsafe.Pointer(&buf[0]), &numBytes, C.MojoWriteDataFlags(flags))
return uint32(r), uint32(numBytes)
}
func (c *CGoSystem) BeginWriteData(producerHandle uint32, numBytes uint32, flags uint32) (result uint32, buf []byte) {
var buffer unsafe.Pointer
bufferNumBytes := C.uint32_t(numBytes)
r := C.MojoBeginWriteData(C.MojoHandle(producerHandle), &buffer, &bufferNumBytes, C.MojoWriteDataFlags(flags))
if r != C.MOJO_RESULT_OK {
return uint32(r), nil
}
return uint32(r), unsafeByteSlice(buffer, int(bufferNumBytes))
}
func (c *CGoSystem) EndWriteData(producerHandle uint32, numBytesWritten uint32) (result uint32) {
return uint32(C.MojoEndWriteData(C.MojoHandle(producerHandle), C.uint32_t(numBytesWritten)))
}
func (c *CGoSystem) ReadData(consumerHandle uint32, flags uint32) (result uint32, buf []byte) {
var numBytes C.uint32_t
if r := C.MojoReadData(C.MojoHandle(consumerHandle), nil, &numBytes, C.MOJO_READ_DATA_FLAG_QUERY); r != C.MOJO_RESULT_OK {
return uint32(r), nil
}
buf = make([]byte, int(numBytes))
r := C.MojoReadData(C.MojoHandle(consumerHandle), unsafe.Pointer(&buf[0]), &numBytes, C.MojoReadDataFlags(flags))
buf = buf[0:int(numBytes)]
return uint32(r), buf
}
func (c *CGoSystem) BeginReadData(consumerHandle uint32, numBytes uint32, flags uint32) (result uint32, buf []byte) {
var buffer unsafe.Pointer
bufferNumBytes := C.uint32_t(numBytes)
r := C.MojoBeginReadData(C.MojoHandle(consumerHandle), &buffer, &bufferNumBytes, C.MojoReadDataFlags(flags))
if r != C.MOJO_RESULT_OK {
return uint32(r), nil
}
return uint32(r), unsafeByteSlice(buffer, int(bufferNumBytes))
}
func (c *CGoSystem) EndReadData(consumerHandle uint32, numBytesRead uint32) (result uint32) {
return uint32(C.MojoEndReadData(C.MojoHandle(consumerHandle), C.uint32_t(numBytesRead)))
}
func (c *CGoSystem) GetTimeTicksNow() (timestamp uint64) {
return uint64(C.MojoGetTimeTicksNow())
}
func (c *CGoSystem) Close(handle uint32) (result uint32) {
return uint32(C.MojoClose(C.MojoHandle(handle)))
}
func (c *CGoSystem) Wait(handle uint32, signals uint32, deadline uint64) (result uint32, satisfiedSignals, satisfiableSignals uint32) {
var cState C.struct_MojoHandleSignalsState
r := C.MojoWait(C.MojoHandle(handle), C.MojoHandleSignals(signals), C.MojoDeadline(deadline), &cState)
return uint32(r), uint32(cState.satisfied_signals), uint32(cState.satisfiable_signals)
}
func (c *CGoSystem) WaitMany(handles []uint32, signals []uint32, deadline uint64) (uint32, int, []uint32, []uint32) {
if len(handles) == 0 {
r := C.MojoWaitMany(nil, nil, 0, C.MojoDeadline(deadline), nil, nil)
return uint32(r), -1, nil, nil
}
if len(handles) != len(signals) {
panic("number of handles and signals must match")
}
index := ^C.uint32_t(0) // -1
cHandles := (*C.MojoHandle)(unsafe.Pointer(&handles[0]))
cSignals := (*C.MojoHandleSignals)(unsafe.Pointer(&signals[0]))
cStates := make([]C.struct_MojoHandleSignalsState, len(handles))
r := C.MojoWaitMany(cHandles, cSignals, C.uint32_t(len(handles)), C.MojoDeadline(deadline), &index, &cStates[0])
var satisfied, satisfiable []uint32
if r != C.MOJO_RESULT_INVALID_ARGUMENT && r != C.MOJO_RESULT_RESOURCE_EXHAUSTED {
satisfied = make([]uint32, len(handles))
satisfiable = make([]uint32, len(handles))
for i := 0; i < len(handles); i++ {
satisfied[i] = uint32(cStates[i].satisfied_signals)
satisfiable[i] = uint32(cStates[i].satisfiable_signals)
}
}
return uint32(r), int(int32(index)), satisfied, satisfiable
}
func (c *CGoSystem) CreateMessagePipe(flags uint32) (uint32, uint32, uint32) {
var handle0, handle1 C.MojoHandle
var opts *C.struct_MojoCreateMessagePipeOptions
opts = &C.struct_MojoCreateMessagePipeOptions{
C.uint32_t(unsafe.Sizeof(*opts)),
C.MojoCreateMessagePipeOptionsFlags(flags),
}
r := C.CreateMessagePipe(opts, &handle0, &handle1)
return uint32(r), uint32(handle0), uint32(handle1)
}
func (c *CGoSystem) WriteMessage(handle uint32, bytes []byte, handles []uint32, flags uint32) (result uint32) {
var bytesPtr unsafe.Pointer
if len(bytes) != 0 {
bytesPtr = unsafe.Pointer(&bytes[0])
}
var handlesPtr *C.MojoHandle
if len(handles) != 0 {
handlesPtr = (*C.MojoHandle)(unsafe.Pointer(&handles[0]))
}
return uint32(C.MojoWriteMessage(C.MojoHandle(handle), bytesPtr, C.uint32_t(len(bytes)), handlesPtr, C.uint32_t(len(handles)), C.MojoWriteMessageFlags(flags)))
}
func (c *CGoSystem) ReadMessage(handle uint32, flags uint32) (result uint32, buf []byte, handles []uint32) {
var numBytes, numHandles C.uint32_t
cHandle := C.MojoHandle(handle)
cFlags := C.MojoReadMessageFlags(flags)
if r := C.MojoReadMessage(cHandle, nil, &numBytes, nil, &numHandles, cFlags); r != C.MOJO_RESULT_RESOURCE_EXHAUSTED {
return uint32(r), nil, nil
}
var bufPtr unsafe.Pointer
if numBytes != 0 {
buf = make([]byte, int(numBytes))
bufPtr = unsafe.Pointer(&buf[0])
}
var handlesPtr *C.MojoHandle
if numHandles != 0 {
handles = make([]uint32, int(numHandles))
handlesPtr = (*C.MojoHandle)(unsafe.Pointer(&handles[0]))
}
r := C.MojoReadMessage(cHandle, bufPtr, &numBytes, handlesPtr, &numHandles, cFlags)
return uint32(r), buf, handles
}
func newUnsafeSlice(ptr unsafe.Pointer, length int) unsafe.Pointer {
header := &reflect.SliceHeader{
Data: uintptr(ptr),
Len: length,
Cap: length,
}
return unsafe.Pointer(header)
}
func unsafeByteSlice(ptr unsafe.Pointer, length int) []byte {
return *(*[]byte)(newUnsafeSlice(ptr, length))
}

@ -1,151 +0,0 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("../mojo_sdk.gni")
import("//third_party/cython/rules.gni")
import("rules.gni")
group("python") {
deps = [
":bindings",
":mojo_system",
":mojo_system_impl",
]
}
# GYP version: mojo.gyp:mojo_python_system
python_binary_module("mojo_system") {
configs = [ "../build/config:mojo_sdk" ]
deps = [
":system_embedded",
]
}
python_binary_source_set("system_embedded") {
cython_sources = [
"c_async_waiter.pxd",
"c_core.pxd",
"c_export.pxd",
"c_thunks.pxd",
"mojo_system.pyx",
]
configs = [ "../build/config:mojo_sdk" ]
deps = [
"../c/system",
"../cpp/bindings:callback",
"../cpp/system",
"../cpp/utility",
"../platform/native:system",
]
}
python_binary_module("mojo_system_impl") {
cython_sources = [
"c_environment.pxd",
"c_export.pxd",
"c_thunks.pxd",
"mojo_system_impl.pyx",
]
sources = [
"src/python_system_helper.cc",
"src/python_system_helper.h",
]
configs = [ "../build/config:mojo_sdk" ]
deps = [
":python_common",
"../c/environment",
"../c/system",
"../cpp/bindings:callback",
"../cpp/environment:standalone",
"../cpp/system",
"../cpp/utility",
"../platform/native:system",
]
}
python_binary_source_set("python_common") {
sources = [
"src/common.cc",
"src/common.h",
]
configs = [ "../build/config:mojo_sdk" ]
deps = [
"../c/environment:environment",
"../cpp/bindings:callback",
"../cpp/environment:environment",
"../cpp/system:system",
"../cpp/utility",
]
}
python_package("packaged_application") {
sources = [
"mojo_application/__init__.py",
"mojo_application/application_delegate.py",
"mojo_application/application_impl.py",
"mojo_application/application_runner.py",
"mojo_application/service_provider_impl.py",
]
}
action("import_interface_bindings") {
visibility = [ ":bindings" ]
script = rebase_path("mojo/public/tools/gn/unzip.py", ".", mojo_root)
timestamp = "$target_gen_dir/${target_name}.outputstamp"
mojom_deps = [ "../interfaces/bindings:bindings_python" ]
inputs = []
foreach(d, mojom_deps) {
dep_name = get_label_info(d, "name")
dep_target_out_dir = get_label_info(d, "target_out_dir")
inputs += [ "$dep_target_out_dir/$dep_name.pyzip" ]
}
outputs = [
timestamp,
]
rebase_inputs = rebase_path(inputs, root_build_dir)
rabase_output = rebase_path("$root_out_dir/python", root_build_dir)
rebase_timestamp = rebase_path(timestamp, root_build_dir)
args = [
"--inputs=${rebase_inputs}",
"--output=${rabase_output}",
"--timestamp=${rebase_timestamp}",
]
deps = mojom_deps
}
copy("bindings") {
sources = [
"mojo_bindings/__init__.py",
"mojo_bindings/descriptor.py",
"mojo_bindings/interface_reflection.py",
"mojo_bindings/messaging.py",
"mojo_bindings/promise.py",
"mojo_bindings/reflection.py",
"mojo_bindings/serialization.py",
]
outputs = [
"$root_out_dir/python/mojo_bindings/{{source_file_part}}",
]
deps = [
":import_interface_bindings",
":mojo_system",
]
}
python_package("packaged_bindings") {
sources = [
"mojo_bindings/__init__.py",
"mojo_bindings/descriptor.py",
"mojo_bindings/interface_reflection.py",
"mojo_bindings/messaging.py",
"mojo_bindings/promise.py",
"mojo_bindings/reflection.py",
"mojo_bindings/serialization.py",
]
deps = [
"../interfaces/bindings:bindings_python",
]
}

@ -1,28 +0,0 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# distutils: language = c++
from libc.stdint cimport intptr_t, uint32_t, uint64_t
cdef extern from "mojo/public/c/system/core.h" nogil:
ctypedef uint32_t MojoHandle
ctypedef uint64_t MojoDeadline
ctypedef uint32_t MojoHandleSignals
cdef extern from "mojo/public/c/environment/async_waiter.h" nogil:
ctypedef intptr_t MojoAsyncWaitID
cdef extern from "mojo/public/python/src/common.h" \
namespace "mojo::python" nogil:
cdef cppclass PythonAsyncWaiter "mojo::python::PythonAsyncWaiter":
PythonAsyncWaiter()
MojoAsyncWaitID AsyncWait(MojoHandle,
MojoHandleSignals,
MojoDeadline,
object)
void CancelWait(MojoAsyncWaitID)

@ -1,200 +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.
# distutils: language = c++
from cpython.buffer cimport PyBUF_CONTIG
from cpython.buffer cimport PyBUF_CONTIG_RO
from cpython.buffer cimport Py_buffer
from cpython.buffer cimport PyBuffer_FillInfo
from cpython.buffer cimport PyBuffer_Release
from cpython.buffer cimport PyObject_GetBuffer
from cpython.mem cimport PyMem_Malloc, PyMem_Free
from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t, uintptr_t
cdef extern from "mojo/public/c/system/core.h" nogil:
# types.h
ctypedef int64_t MojoTimeTicks
ctypedef uint32_t MojoHandle
const MojoHandle MOJO_HANDLE_INVALID
ctypedef int32_t MojoResult
const MojoResult MOJO_RESULT_OK
const MojoResult MOJO_RESULT_CANCELLED
const MojoResult MOJO_RESULT_UNKNOWN
const MojoResult MOJO_RESULT_INVALID_ARGUMENT
const MojoResult MOJO_RESULT_DEADLINE_EXCEEDED
const MojoResult MOJO_RESULT_NOT_FOUND
const MojoResult MOJO_RESULT_ALREADY_EXISTS
const MojoResult MOJO_RESULT_PERMISSION_DENIED
const MojoResult MOJO_RESULT_RESOURCE_EXHAUSTED
const MojoResult MOJO_RESULT_FAILED_PRECONDITION
const MojoResult MOJO_RESULT_ABORTED
const MojoResult MOJO_RESULT_OUT_OF_RANGE
const MojoResult MOJO_RESULT_UNIMPLEMENTED
const MojoResult MOJO_RESULT_INTERNAL
const MojoResult MOJO_RESULT_UNAVAILABLE
const MojoResult MOJO_RESULT_DATA_LOSS
const MojoResult MOJO_RESULT_BUSY
const MojoResult MOJO_RESULT_SHOULD_WAIT
ctypedef uint64_t MojoDeadline
const MojoDeadline MOJO_DEADLINE_INDEFINITE
ctypedef uint32_t MojoHandleSignals
const MojoHandleSignals MOJO_HANDLE_SIGNAL_NONE
const MojoHandleSignals MOJO_HANDLE_SIGNAL_READABLE
const MojoHandleSignals MOJO_HANDLE_SIGNAL_WRITABLE
const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_CLOSED
cdef struct MojoHandleSignalsState:
MojoHandleSignals satisfied_signals
MojoHandleSignals satisfiable_signals
# functions.h
MojoTimeTicks MojoGetTimeTicksNow()
MojoResult MojoClose(MojoHandle handle)
MojoResult MojoWait "MojoWait"(MojoHandle handle,
MojoHandleSignals signals,
MojoDeadline deadline,
MojoHandleSignalsState* signals_state)
MojoResult MojoWaitMany "MojoWaitMany"(const MojoHandle* handles,
const MojoHandleSignals* signals,
uint32_t num_handles,
MojoDeadline deadline,
uint32_t* result_index,
MojoHandleSignalsState* signals_states)
# message_pipe.h
ctypedef uint32_t MojoCreateMessagePipeOptionsFlags
const MojoCreateMessagePipeOptionsFlags MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE
ctypedef uint32_t MojoWriteMessageFlags
const MojoWriteMessageFlags MOJO_WRITE_MESSAGE_FLAG_NONE
ctypedef uint32_t MojoReadMessageFlags
const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_NONE
const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_MAY_DISCARD
cdef struct MojoCreateMessagePipeOptions:
uint32_t struct_size
MojoCreateMessagePipeOptionsFlags flags
MojoResult MojoCreateMessagePipe(
const MojoCreateMessagePipeOptions* options,
MojoHandle* message_pipe_handle0,
MojoHandle* message_pipe_handle1)
MojoResult MojoWriteMessage(
MojoHandle message_pipe_handle,
const void* bytes,
uint32_t num_bytes,
const MojoHandle* handles,
uint32_t num_handles,
MojoWriteMessageFlags flags)
MojoResult MojoReadMessage(
MojoHandle message_pipe_handle,
void* bytes,
uint32_t* num_bytes,
MojoHandle* handles,
uint32_t* num_handles,
MojoReadMessageFlags flags)
# data_pipe.h
ctypedef uint32_t MojoCreateDataPipeOptionsFlags
const MojoCreateDataPipeOptionsFlags MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE
cdef struct MojoCreateDataPipeOptions:
uint32_t struct_size
MojoCreateDataPipeOptionsFlags flags
uint32_t element_num_bytes
uint32_t capacity_num_bytes
ctypedef uint32_t MojoWriteDataFlags
const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_NONE
const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
ctypedef uint32_t MojoReadDataFlags
const MojoReadDataFlags MOJO_READ_DATA_FLAG_NONE
const MojoReadDataFlags MOJO_READ_DATA_FLAG_ALL_OR_NONE
const MojoReadDataFlags MOJO_READ_DATA_FLAG_DISCARD
const MojoReadDataFlags MOJO_READ_DATA_FLAG_QUERY
const MojoReadDataFlags MOJO_READ_DATA_FLAG_PEEK
MojoResult MojoCreateDataPipe(
const MojoCreateDataPipeOptions* options,
MojoHandle* data_pipe_producer_handle,
MojoHandle* data_pipe_consumer_handle)
MojoResult MojoWriteData(
MojoHandle data_pipe_producer_handle,
const void* elements,
uint32_t* num_bytes,
MojoWriteDataFlags flags)
MojoResult MojoBeginWriteData(
MojoHandle data_pipe_producer_handle,
void** buffer,
uint32_t* buffer_num_bytes,
MojoWriteDataFlags flags)
MojoResult MojoEndWriteData(
MojoHandle data_pipe_producer_handle,
uint32_t num_bytes_written)
MojoResult MojoReadData(
MojoHandle data_pipe_consumer_handle,
void* elements,
uint32_t* num_bytes,
MojoReadDataFlags flags)
MojoResult MojoBeginReadData(
MojoHandle data_pipe_consumer_handle,
const void** buffer,
uint32_t* buffer_num_bytes,
MojoReadDataFlags flags)
MojoResult MojoEndReadData(
MojoHandle data_pipe_consumer_handle,
uint32_t num_bytes_read)
# buffer.h
ctypedef uint32_t MojoCreateSharedBufferOptionsFlags
const MojoCreateSharedBufferOptionsFlags MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE
cdef struct MojoCreateSharedBufferOptions:
uint32_t struct_size
MojoCreateSharedBufferOptionsFlags flags
ctypedef uint32_t MojoDuplicateBufferHandleOptionsFlags
const MojoDuplicateBufferHandleOptionsFlags MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE
cdef struct MojoDuplicateBufferHandleOptions:
uint32_t struct_size
MojoDuplicateBufferHandleOptionsFlags flags
ctypedef uint32_t MojoMapBufferFlags
const MojoMapBufferFlags MOJO_MAP_BUFFER_FLAG_NONE
MojoResult MojoCreateSharedBuffer(
const MojoCreateSharedBufferOptions* options,
uint64_t num_bytes,
MojoHandle* shared_buffer_handle)
MojoResult MojoDuplicateBufferHandle(
MojoHandle buffer_handle,
const MojoDuplicateBufferHandleOptions* options,
MojoHandle* new_buffer_handle)
MojoResult MojoMapBuffer(MojoHandle buffer_handle,
uint64_t offset,
uint64_t num_bytes,
void** buffer,
MojoMapBufferFlags flags)
MojoResult MojoUnmapBuffer(void* buffer)

@ -1,35 +0,0 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# distutils: language = c++
from libc.stdint cimport int64_t, intptr_t, uint32_t, uint64_t
cimport c_async_waiter
cdef extern from "mojo/public/cpp/bindings/callback.h" nogil:
cdef cppclass CClosure "mojo::Callback<void()>":
CClosure()
cdef extern from "mojo/public/python/src/python_system_helper.h" \
namespace "mojo::python" nogil:
cdef CClosure BuildClosure(object)
cdef c_async_waiter.PythonAsyncWaiter* NewAsyncWaiter()
cdef extern from "mojo/public/cpp/utility/run_loop.h" nogil:
cdef cppclass CRunLoop "mojo::RunLoop":
CRunLoop()
void Run() except *
void RunUntilIdle() except *
void Quit()
void PostDelayedTask(CClosure&, int64_t)
cdef CRunLoop CRunLoopCurrent "mojo::RunLoop::current"()
cdef extern from "mojo/public/cpp/environment/environment.h" nogil:
cdef cppclass CEnvironment "mojo::Environment":
CEnvironment()

@ -1,11 +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.
# distutils: language = c++
# If the definition below is not present, cython-compiled modules do not expose
# an init method as they should.
cdef extern from "third_party/cython/python_export.h":
pass

@ -1,12 +0,0 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# distutils: language = c++
cdef extern from "mojo/public/platform/native/system_thunks.h" nogil:
cdef struct MojoSystemThunks:
pass
cdef extern size_t MojoSetSystemThunks(const MojoSystemThunks* system_thunks)

@ -1,3 +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.

@ -1,30 +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.
"""Interface for the delegate of ApplicationImpl."""
import mojo_application.application_impl
import mojo_application.service_provider_impl
import shell_mojom
import mojo_system
# pylint: disable=unused-argument
class ApplicationDelegate:
def Initialize(self, shell, application):
"""
Called from ApplicationImpl's Initialize() method.
"""
pass
def OnAcceptConnection(self,
requestor_url,
resolved_url,
service_provider,
exposed_services):
"""
Called from ApplicationImpl's OnAcceptConnection() method. Returns a bool
indicating whether this connection should be accepted.
"""
return False

@ -1,57 +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.
"""Python implementation of the Application interface."""
import application_mojom
import service_provider_mojom
import shell_mojom
from mojo_application.service_provider_impl import ServiceProviderImpl
import mojo_system
class ApplicationImpl(application_mojom.Application):
def __init__(self, delegate, app_request_handle):
self.shell = None
self.url = None
self.args = None
self._delegate = delegate
self._providers = []
application_mojom.Application.manager.Bind(self, app_request_handle)
def Initialize(self, shell, url, args):
self.shell = shell
self.url = url
self.args = args
self._delegate.Initialize(shell, self)
def AcceptConnection(self, requestor_url, services, exposed_services,
resolved_url):
service_provider = ServiceProviderImpl(services)
if self._delegate.OnAcceptConnection(requestor_url, resolved_url,
service_provider, exposed_services):
# We keep a reference to ServiceProviderImpl to ensure neither it nor
# |services| gets garbage collected.
services.Bind(service_provider)
self._providers.append(service_provider)
def removeServiceProvider():
self._providers.remove(service_provider)
service_provider.manager.AddOnErrorCallback(removeServiceProvider)
def ConnectToService(self, application_url, service_class):
"""
Helper method to connect to a service. |application_url| is the URL of the
application to be connected to, and |service_class| is the class of the
service to be connected to. Returns a proxy to the service.
"""
application_proxy, request = (
service_provider_mojom.ServiceProvider.manager.NewRequest())
self.shell.ConnectToApplication(application_url, request, None)
service_proxy, request = service_class.manager.NewRequest()
application_proxy.ConnectToService(service_class.manager.name,
request.PassMessagePipe())
return service_proxy

@ -1,17 +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.
"""Helper for running Mojo applications in Python."""
from mojo_application.application_impl import ApplicationImpl
import mojo_system
def RunMojoApplication(application_delegate, app_request_handle):
loop = mojo_system.RunLoop()
application = ApplicationImpl(application_delegate, app_request_handle)
application.manager.AddOnErrorCallback(loop.Quit)
loop.Run()

@ -1,24 +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.
"""Python implementation of the ServiceProvider interface."""
import logging
import service_provider_mojom
class ServiceProviderImpl(service_provider_mojom.ServiceProvider):
def __init__(self, provider):
self._provider = provider
self._name_to_service_connector = {}
def AddService(self, service_class):
self._name_to_service_connector[service_class.manager.name] = service_class
def ConnectToService(self, interface_name, pipe):
if interface_name in self._name_to_service_connector:
service = self._name_to_service_connector[interface_name]
service.manager.Bind(service(), pipe)
else:
logging.error("Unable to find service " + interface_name)

@ -1,3 +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.

@ -1,809 +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.
"""
The descriptors used to define generated elements of the mojo python bindings.
"""
import array
import itertools
import struct
import mojo_bindings.reflection as reflection
import mojo_bindings.serialization as serialization
# pylint: disable=E0611,F0401
import mojo_system
class Type(object):
"""Describes the type of a struct field or a method parameter,"""
def Convert(self, value): # pylint: disable=R0201
"""
Convert the given value into its canonical representation, raising an
exception if the value cannot be converted.
"""
return value
def GetDefaultValue(self, value):
"""
Returns the default value for this type associated with the given value.
This method must be able to correcly handle value being None.
"""
return self.Convert(value)
def IsUnion(self):
"""
Returns true if the type is a union. This is necessary to be able to
identify a union when descriptor.py cannot be imported.
"""
return False
class SerializableType(Type):
"""Describe a type that can be serialized by itself."""
def __init__(self, typecode):
Type.__init__(self)
self.typecode = typecode
self.byte_size = struct.calcsize('<%s' % self.GetTypeCode())
def GetTypeCode(self):
"""
Returns the type code (as defined by the struct module) used to encode
this type.
"""
return self.typecode
def GetByteSize(self):
"""
Returns the size of the encoding of this type.
"""
return self.byte_size
def GetAlignment(self):
"""
Returns the alignment required by the encoding of this type. By default it
is set to the byte size of the biggest packed value.
"""
return max([struct.calcsize('<%s' % c) for c in self.GetTypeCode()])
def Serialize(self, value, data_offset, data, handle_offset):
"""
Serialize a value of this type.
Args:
value: the value to serialize.
data_offset: the offset to the end of the data bytearray. Used to encode
pointers.
data: the bytearray to append additional data to.
handle_offset: the offset to use to encode handles.
Returns a a tuple where the first element is the value to encode, and the
second is the array of handles to add to the message.
"""
raise NotImplementedError()
def Deserialize(self, value, context):
"""
Deserialize a value of this type.
Args:
value: the base value for this type. This is always a numeric type, and
corresponds to the first element in the tuple returned by
Serialize.
data: the bytearray to retrieve additional data from.
handles: the array of handles contained in the message to deserialize.
Returns the deserialized value.
"""
raise NotImplementedError()
class BooleanType(Type):
"""Type object for booleans"""
def Convert(self, value):
return bool(value)
class NumericType(SerializableType):
"""Base Type object for all numeric types"""
def GetDefaultValue(self, value):
if value is None:
return self.Convert(0)
return self.Convert(value)
def Serialize(self, value, data_offset, data, handle_offset):
return (value, [])
def Deserialize(self, value, context):
return value
class IntegerType(NumericType):
"""Type object for integer types."""
def __init__(self, typecode):
NumericType.__init__(self, typecode)
size = 8 * self.byte_size
signed = typecode.islower()
if signed:
self._min_value = -(1 << (size - 1))
self._max_value = (1 << (size - 1)) - 1
else:
self._min_value = 0
self._max_value = (1 << size) - 1
def Convert(self, value):
if value is None:
raise TypeError('None is not an integer.')
if not isinstance(value, (int, long)):
raise TypeError('%r is not an integer type' % value)
if value < self._min_value or value > self._max_value:
raise OverflowError('%r is not in the range [%d, %d]' %
(value, self._min_value, self._max_value))
return value
class FloatType(NumericType):
"""Type object for floating point number types."""
def Convert(self, value):
if value is None:
raise TypeError('None is not an floating point number.')
if not isinstance(value, (int, long, float)):
raise TypeError('%r is not a numeric type' % value)
return float(value)
class UnionType(SerializableType):
"""Base Type object for union."""
def __init__(self, union_type_getter, nullable=False):
SerializableType.__init__(self, 'IIQ')
self.nullable = nullable
self._union_type_getter = union_type_getter
self._union_type = None
def IsUnion(self):
return True
@property
def union_type(self):
if not self._union_type:
self._union_type = self._union_type_getter()
return self._union_type
def Serialize(self, value, data_offset, data, handle_offset):
if not value:
if not self.nullable:
raise serialization.SerializationException(
'Trying to serialize null for non nullable type.')
return ((0, 0, 0), [])
((size, tag, entry, new_data), new_handles) = (
value.SerializeInline(handle_offset))
if len(new_data) > 0:
data.extend(new_data)
entry = data_offset - 8
return ((size, tag, entry), new_handles)
def Deserialize(self, value, context):
result = self.union_type.Deserialize(context)
if not result and not self.nullable:
raise serialization.DeserializationException(
'Trying to deserialize null for non nullable type.')
return result
class PointerType(SerializableType):
"""Base Type object for pointers."""
def __init__(self, nullable=False):
SerializableType.__init__(self, 'Q')
self.nullable = nullable
def Serialize(self, value, data_offset, data, handle_offset):
if value is None and not self.nullable:
raise serialization.SerializationException(
'Trying to serialize null for non nullable type.')
if value is None:
return (0, [])
return self.SerializePointer(value, data_offset, data, handle_offset)
def Deserialize(self, value, context):
if value == 0:
if not self.nullable:
raise serialization.DeserializationException(
'Trying to deserialize null for non nullable type.')
return None
if value % 8 != 0:
raise serialization.DeserializationException(
'Pointer alignment is incorrect.')
sub_context = context.GetSubContext(value)
if len(sub_context.data) < serialization.HEADER_STRUCT.size:
raise serialization.DeserializationException(
'Available data too short to contain header.')
(size, nb_elements) = serialization.HEADER_STRUCT.unpack_from(
sub_context.data)
if len(sub_context.data) < size or size < serialization.HEADER_STRUCT.size:
raise serialization.DeserializationException('Header size is incorrect.')
sub_context.ClaimMemory(0, size)
return self.DeserializePointer(size, nb_elements, sub_context)
def SerializePointer(self, value, data_offset, data, handle_offset):
"""Serialize the not null value."""
raise NotImplementedError()
def DeserializePointer(self, size, nb_elements, context):
raise NotImplementedError()
class StringType(PointerType):
"""
Type object for strings.
Strings are represented as unicode, and the conversion is done using the
default encoding if a string instance is used.
"""
def __init__(self, nullable=False):
PointerType.__init__(self, nullable)
self._array_type = NativeArrayType('B', nullable)
def Convert(self, value):
if value is None or isinstance(value, unicode):
return value
if isinstance(value, str):
return unicode(value)
raise TypeError('%r is not a string' % value)
def SerializePointer(self, value, data_offset, data, handle_offset):
string_array = array.array('b')
string_array.fromstring(value.encode('utf8'))
return self._array_type.SerializeArray(
string_array, data_offset, data, handle_offset)
def DeserializePointer(self, size, nb_elements, context):
string_array = self._array_type.DeserializeArray(size, nb_elements, context)
return unicode(string_array.tostring(), 'utf8')
class BaseHandleType(SerializableType):
"""Type object for handles."""
def __init__(self, nullable=False, type_code='i'):
SerializableType.__init__(self, type_code)
self.nullable = nullable
def Serialize(self, value, data_offset, data, handle_offset):
handle = self.ToHandle(value)
if not handle.IsValid() and not self.nullable:
raise serialization.SerializationException(
'Trying to serialize null for non nullable type.')
if not handle.IsValid():
return (-1, [])
return (handle_offset, [handle])
def Deserialize(self, value, context):
if value == -1:
if not self.nullable:
raise serialization.DeserializationException(
'Trying to deserialize null for non nullable type.')
return self.FromHandle(mojo_system.Handle())
return self.FromHandle(context.ClaimHandle(value))
def FromHandle(self, handle):
raise NotImplementedError()
def ToHandle(self, value):
raise NotImplementedError()
class HandleType(BaseHandleType):
"""Type object for handles."""
def Convert(self, value):
if value is None:
return mojo_system.Handle()
if not isinstance(value, mojo_system.Handle):
raise TypeError('%r is not a handle' % value)
return value
def FromHandle(self, handle):
return handle
def ToHandle(self, value):
return value
class InterfaceRequestType(BaseHandleType):
"""Type object for interface requests."""
def Convert(self, value):
if value is None:
return reflection.InterfaceRequest(mojo_system.Handle())
if not isinstance(value, reflection.InterfaceRequest):
raise TypeError('%r is not an interface request' % value)
return value
def FromHandle(self, handle):
return reflection.InterfaceRequest(handle)
def ToHandle(self, value):
return value.PassMessagePipe()
class InterfaceType(BaseHandleType):
"""Type object for interfaces."""
def __init__(self, interface_getter, nullable=False):
# handle (4 bytes) + version (4 bytes)
BaseHandleType.__init__(self, nullable, 'iI')
self._interface_getter = interface_getter
self._interface = None
def Convert(self, value):
if value is None or isinstance(value, self.interface):
return value
raise TypeError('%r is not an instance of ' % self.interface)
@property
def interface(self):
if not self._interface:
self._interface = self._interface_getter()
return self._interface
def Serialize(self, value, data_offset, data, handle_offset):
(encoded_handle, handles) = super(InterfaceType, self).Serialize(
value, data_offset, data, handle_offset)
if encoded_handle == -1:
version = 0
else:
version = self.interface.manager.version
if value and isinstance(value, reflection.InterfaceProxy):
version = value.manager.version
return ((encoded_handle, version), handles)
def Deserialize(self, value, context):
proxy = super(InterfaceType, self).Deserialize(value[0], context)
if proxy:
proxy.manager.version = value[1]
return proxy
def FromHandle(self, handle):
if handle.IsValid():
return self.interface.manager.Proxy(handle)
return None
def ToHandle(self, value):
if not value:
return mojo_system.Handle()
if isinstance(value, reflection.InterfaceProxy):
return value.manager.PassMessagePipe()
pipe = mojo_system.MessagePipe()
self.interface.manager.Bind(value, pipe.handle0)
return pipe.handle1
class BaseArrayType(PointerType):
"""Abstract Type object for arrays."""
def __init__(self, nullable=False, length=0):
PointerType.__init__(self, nullable)
self.length = length
def SerializePointer(self, value, data_offset, data, handle_offset):
if self.length != 0 and len(value) != self.length:
raise serialization.SerializationException('Incorrect array size')
return self.SerializeArray(value, data_offset, data, handle_offset)
def SerializeArray(self, value, data_offset, data, handle_offset):
"""Serialize the not null array."""
raise NotImplementedError()
def DeserializePointer(self, size, nb_elements, context):
if self.length != 0 and nb_elements != self.length:
raise serialization.DeserializationException('Incorrect array size')
if (size <
serialization.HEADER_STRUCT.size + self.SizeForLength(nb_elements)):
raise serialization.DeserializationException('Incorrect array size')
return self.DeserializeArray(size, nb_elements, context)
def DeserializeArray(self, size, nb_elements, context):
raise NotImplementedError()
def SizeForLength(self, nb_elements):
raise NotImplementedError()
class BooleanArrayType(BaseArrayType):
def __init__(self, nullable=False, length=0):
BaseArrayType.__init__(self, nullable, length)
self._array_type = NativeArrayType('B', nullable)
def Convert(self, value):
if value is None:
return value
return [TYPE_BOOL.Convert(x) for x in value]
def SerializeArray(self, value, data_offset, data, handle_offset):
groups = [value[i:i+8] for i in range(0, len(value), 8)]
converted = array.array('B', [_ConvertBooleansToByte(x) for x in groups])
return _SerializeNativeArray(converted, data_offset, data, len(value))
def DeserializeArray(self, size, nb_elements, context):
converted = self._array_type.DeserializeArray(size, nb_elements, context)
elements = list(itertools.islice(
itertools.chain.from_iterable(
[_ConvertByteToBooleans(x, 8) for x in converted]),
0,
nb_elements))
return elements
def SizeForLength(self, nb_elements):
return (nb_elements + 7) // 8
class GenericArrayType(BaseArrayType):
"""Type object for arrays of pointers."""
def __init__(self, sub_type, nullable=False, length=0):
BaseArrayType.__init__(self, nullable, length)
assert isinstance(sub_type, SerializableType)
self.sub_type = sub_type
def Convert(self, value):
if value is None:
return value
return [self.sub_type.Convert(x) for x in value]
def SerializeArray(self, value, data_offset, data, handle_offset):
size = (serialization.HEADER_STRUCT.size +
self.sub_type.GetByteSize() * len(value))
data_end = len(data)
position = len(data) + serialization.HEADER_STRUCT.size
data.extend(bytearray(size +
serialization.NeededPaddingForAlignment(size)))
returned_handles = []
to_pack = []
for item in value:
(new_data, new_handles) = self.sub_type.Serialize(
item,
len(data) - position,
data,
handle_offset + len(returned_handles))
to_pack.extend(serialization.Flatten(new_data))
returned_handles.extend(new_handles)
position = position + self.sub_type.GetByteSize()
serialization.HEADER_STRUCT.pack_into(data, data_end, size, len(value))
# TODO(azani): Refactor so we don't have to create big formatting strings.
struct.pack_into(('%s' % self.sub_type.GetTypeCode()) * len(value),
data,
data_end + serialization.HEADER_STRUCT.size,
*to_pack)
return (data_offset, returned_handles)
def DeserializeArray(self, size, nb_elements, context):
# TODO(azani): Refactor so the format string isn't so big.
values = struct.unpack_from(
nb_elements * self.sub_type.GetTypeCode(),
buffer(context.data, serialization.HEADER_STRUCT.size))
values_per_element = len(self.sub_type.GetTypeCode())
assert nb_elements * values_per_element == len(values)
result = []
sub_context = context.GetSubContext(serialization.HEADER_STRUCT.size)
for index in xrange(nb_elements):
if values_per_element == 1:
value = values[index]
else:
value = tuple(values[index * values_per_element :
(index + 1) * values_per_element])
result.append(self.sub_type.Deserialize(
value,
sub_context))
sub_context = sub_context.GetSubContext(self.sub_type.GetByteSize())
return result
def SizeForLength(self, nb_elements):
return nb_elements * self.sub_type.GetByteSize();
class NativeArrayType(BaseArrayType):
"""Type object for arrays of native types."""
def __init__(self, typecode, nullable=False, length=0):
BaseArrayType.__init__(self, nullable, length)
self.array_typecode = typecode
self.element_size = struct.calcsize('<%s' % self.array_typecode)
def Convert(self, value):
if value is None:
return value
if (isinstance(value, array.array) and
value.array_typecode == self.array_typecode):
return value
return array.array(self.array_typecode, value)
def SerializeArray(self, value, data_offset, data, handle_offset):
return _SerializeNativeArray(value, data_offset, data, len(value))
def DeserializeArray(self, size, nb_elements, context):
result = array.array(self.array_typecode)
result.fromstring(buffer(context.data,
serialization.HEADER_STRUCT.size,
size - serialization.HEADER_STRUCT.size))
return result
def SizeForLength(self, nb_elements):
return nb_elements * self.element_size
class StructType(PointerType):
"""Type object for structs."""
def __init__(self, struct_type_getter, nullable=False):
PointerType.__init__(self)
self._struct_type_getter = struct_type_getter
self._struct_type = None
self.nullable = nullable
@property
def struct_type(self):
if not self._struct_type:
self._struct_type = self._struct_type_getter()
return self._struct_type
def Convert(self, value):
if value is None or isinstance(value, self.struct_type):
return value
raise TypeError('%r is not an instance of %r' % (value, self.struct_type))
def GetDefaultValue(self, value):
if value:
return self.struct_type()
return None
def SerializePointer(self, value, data_offset, data, handle_offset):
(new_data, new_handles) = value.Serialize(handle_offset)
data.extend(new_data)
return (data_offset, new_handles)
def DeserializePointer(self, size, nb_elements, context):
return self.struct_type.Deserialize(context)
class MapType(SerializableType):
"""Type objects for maps."""
def __init__(self, key_type, value_type, nullable=False):
self._key_type = key_type
self._value_type = value_type
dictionary = {
'__metaclass__': reflection.MojoStructType,
'__module__': __name__,
'DESCRIPTOR': {
'fields': [
SingleFieldGroup('keys', MapType._GetArrayType(key_type), 0, 0),
SingleFieldGroup('values', MapType._GetArrayType(value_type), 1, 0),
],
}
}
self.struct = reflection.MojoStructType('MapStruct', (object,), dictionary)
self.struct_type = StructType(lambda: self.struct, nullable)
SerializableType.__init__(self, self.struct_type.typecode)
def Convert(self, value):
if value is None:
return value
if isinstance(value, dict):
return dict([(self._key_type.Convert(x), self._value_type.Convert(y)) for
x, y in value.iteritems()])
raise TypeError('%r is not a dictionary.')
def Serialize(self, value, data_offset, data, handle_offset):
s = None
if value:
keys, values = [], []
for key, value in value.iteritems():
keys.append(key)
values.append(value)
s = self.struct(keys=keys, values=values)
return self.struct_type.Serialize(s, data_offset, data, handle_offset)
def Deserialize(self, value, context):
s = self.struct_type.Deserialize(value, context)
if s:
if len(s.keys) != len(s.values):
raise serialization.DeserializationException(
'keys and values do not have the same length.')
return dict(zip(s.keys, s.values))
return None
@staticmethod
def _GetArrayType(t):
if t == TYPE_BOOL:
return BooleanArrayType()
else:
return GenericArrayType(t)
TYPE_BOOL = BooleanType()
TYPE_INT8 = IntegerType('b')
TYPE_INT16 = IntegerType('h')
TYPE_INT32 = IntegerType('i')
TYPE_INT64 = IntegerType('q')
TYPE_UINT8 = IntegerType('B')
TYPE_UINT16 = IntegerType('H')
TYPE_UINT32 = IntegerType('I')
TYPE_UINT64 = IntegerType('Q')
TYPE_FLOAT = FloatType('f')
TYPE_DOUBLE = FloatType('d')
TYPE_STRING = StringType()
TYPE_NULLABLE_STRING = StringType(True)
TYPE_HANDLE = HandleType()
TYPE_NULLABLE_HANDLE = HandleType(True)
TYPE_INTERFACE_REQUEST = InterfaceRequestType()
TYPE_NULLABLE_INTERFACE_REQUEST = InterfaceRequestType(True)
class FieldDescriptor(object):
"""Describes a field in a generated struct."""
def __init__(self, name, field_type, index, version, default_value=None):
self.name = name
self.field_type = field_type
self.version = version
self.index = index
self._default_value = default_value
def GetDefaultValue(self):
return self.field_type.GetDefaultValue(self._default_value)
class FieldGroup(object):
"""
Describe a list of field in the generated struct that must be
serialized/deserialized together.
"""
def __init__(self, descriptors):
self.descriptors = descriptors
def GetDescriptors(self):
return self.descriptors
def GetTypeCode(self):
raise NotImplementedError()
def GetByteSize(self):
raise NotImplementedError()
def GetAlignment(self):
raise NotImplementedError()
def GetMinVersion(self):
raise NotImplementedError()
def GetMaxVersion(self):
raise NotImplementedError()
def Serialize(self, obj, data_offset, data, handle_offset):
raise NotImplementedError()
def Deserialize(self, value, context):
raise NotImplementedError()
def Filter(self, version):
raise NotImplementedError()
class SingleFieldGroup(FieldGroup, FieldDescriptor):
"""A FieldGroup that contains a single FieldDescriptor."""
def __init__(self, name, field_type, index, version, default_value=None):
FieldDescriptor.__init__(
self, name, field_type, index, version, default_value)
FieldGroup.__init__(self, [self])
def GetTypeCode(self):
return self.field_type.GetTypeCode()
def GetByteSize(self):
return self.field_type.GetByteSize()
def GetAlignment(self):
return self.field_type.GetAlignment()
def GetMinVersion(self):
return self.version
def GetMaxVersion(self):
return self.version
def Serialize(self, obj, data_offset, data, handle_offset):
value = getattr(obj, self.name)
return self.field_type.Serialize(value, data_offset, data, handle_offset)
def Deserialize(self, value, context):
entity = self.field_type.Deserialize(value, context)
return { self.name: entity }
def Filter(self, version):
return self
class BooleanGroup(FieldGroup):
"""A FieldGroup to pack booleans."""
def __init__(self, descriptors):
FieldGroup.__init__(self, descriptors)
self.min_version = min([descriptor.version for descriptor in descriptors])
self.max_version = max([descriptor.version for descriptor in descriptors])
def GetTypeCode(self):
return 'B'
def GetByteSize(self):
return 1
def GetAlignment(self):
return 1
def GetMinVersion(self):
return self.min_version
def GetMaxVersion(self):
return self.max_version
def Serialize(self, obj, data_offset, data, handle_offset):
value = _ConvertBooleansToByte(
[getattr(obj, field.name) for field in self.GetDescriptors()])
return (value, [])
def Deserialize(self, value, context):
values = itertools.izip_longest([x.name for x in self.descriptors],
_ConvertByteToBooleans(value),
fillvalue=False)
return dict(values)
def Filter(self, version):
return BooleanGroup(
filter(lambda d: d.version <= version, self.descriptors))
def _SerializeNativeArray(value, data_offset, data, length):
data_size = len(data)
data.extend(bytearray(serialization.HEADER_STRUCT.size))
data.extend(buffer(value))
data_length = len(data) - data_size
data.extend(bytearray(serialization.NeededPaddingForAlignment(data_length)))
serialization.HEADER_STRUCT.pack_into(data, data_size, data_length, length)
return (data_offset, [])
def _ConvertBooleansToByte(booleans):
"""Pack a list of booleans into an integer."""
return reduce(lambda x, y: x * 2 + y, reversed(booleans), 0)
def _ConvertByteToBooleans(value, min_size=0):
"""Unpack an integer into a list of booleans."""
res = []
while value:
res.append(bool(value&1))
value = value / 2
res.extend([False] * (min_size - len(res)))
return res

@ -1,466 +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.
"""
The metaclasses used by the mojo python bindings for interfaces.
It is splitted from mojo_bindings.reflection because it uses some generated code
that would create a cyclic dependency.
"""
import logging
import sys
# pylint: disable=F0401
import interface_control_messages_mojom
import mojo_bindings.messaging as messaging
import mojo_bindings.promise as promise
import mojo_bindings.reflection as reflection
import mojo_bindings.serialization as serialization
import mojo_system
class MojoInterfaceType(type):
"""Meta class for interfaces.
Usage:
class MyInterface(object):
__metaclass__ = MojoInterfaceType
DESCRIPTOR = {
'fully_qualified_name': 'service::MyInterface'
'version': 3,
'methods': [
{
'name': 'FireAndForget',
'ordinal': 0,
'parameters': [
SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
]
},
{
'name': 'Ping',
'ordinal': 1,
'parameters': [
SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
],
'responses': [
SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
],
},
],
}
"""
def __new__(mcs, name, bases, dictionary):
# If one of the base class is already an interface type, do not edit the
# class.
for base in bases:
if isinstance(base, mcs):
return type.__new__(mcs, name, bases, dictionary)
descriptor = dictionary.pop('DESCRIPTOR', {})
methods = [_MethodDescriptor(x) for x in descriptor.get('methods', [])]
for method in methods:
dictionary[method.name] = _NotImplemented
fully_qualified_name = descriptor['fully_qualified_name']
interface_manager = InterfaceManager(
fully_qualified_name, descriptor['version'], methods)
dictionary.update({
'manager': None,
'_interface_manager': interface_manager,
})
interface_class = type.__new__(mcs, name, bases, dictionary)
interface_manager.interface_class = interface_class
return interface_class
@property
def manager(cls):
return cls._interface_manager
# Prevent adding new attributes, or mutating constants.
def __setattr__(cls, key, value):
raise AttributeError('can\'t set attribute')
# Prevent deleting constants.
def __delattr__(cls, key):
raise AttributeError('can\'t delete attribute')
class InterfaceManager(object):
"""
Manager for an interface class. The manager contains the operation that allows
to bind an implementation to a pipe, or to generate a proxy for an interface
over a pipe.
"""
def __init__(self, name, version, methods):
self.name = name
self.version = version
self.methods = methods
self.interface_class = None
self._proxy_class = None
self._stub_class = None
def Proxy(self, handle, version=0):
router = messaging.Router(handle)
error_handler = _ProxyErrorHandler()
router.SetErrorHandler(error_handler)
router.Start()
return self._InternalProxy(router, error_handler, version)
# pylint: disable=W0212
def Bind(self, impl, handle):
router = messaging.Router(handle)
router.SetIncomingMessageReceiver(self._Stub(impl))
error_handler = _ProxyErrorHandler()
router.SetErrorHandler(error_handler)
# Retain the router, until an error happen.
retainer = _Retainer(router)
def Cleanup(_):
retainer.release()
error_handler.AddCallback(Cleanup)
# Give an instance manager to the implementation to allow it to close
# the connection.
impl.manager = InstanceManager(self, router, error_handler)
router.Start()
def NewRequest(self):
pipe = mojo_system.MessagePipe()
return (self.Proxy(pipe.handle0), reflection.InterfaceRequest(pipe.handle1))
def _InternalProxy(self, router, error_handler, version):
if error_handler is None:
error_handler = _ProxyErrorHandler()
if not self._proxy_class:
dictionary = {
'__module__': __name__,
'__init__': _ProxyInit,
}
for method in self.methods:
dictionary[method.name] = _ProxyMethodCall(method)
self._proxy_class = type(
'%sProxy' % self.name,
(self.interface_class, reflection.InterfaceProxy),
dictionary)
proxy = self._proxy_class(router, error_handler)
# Give an instance manager to the proxy to allow to close the connection.
proxy.manager = ProxyInstanceManager(
self, proxy, router, error_handler, version)
return proxy
def _Stub(self, impl):
if not self._stub_class:
accept_method = _StubAccept(self.methods)
dictionary = {
'__module__': __name__,
'__init__': _StubInit,
'Accept': accept_method,
'AcceptWithResponder': accept_method,
}
self._stub_class = type('%sStub' % self.name,
(messaging.MessageReceiverWithResponder,),
dictionary)
return self._stub_class(impl)
class InstanceManager(object):
"""
Manager for the implementation of an interface or a proxy. The manager allows
to control the connection over the pipe.
"""
def __init__(self, interface_manager, router, error_handler):
self.interface_manager = interface_manager
self._router = router
self._error_handler = error_handler
assert self._error_handler is not None
def Close(self):
self._error_handler.OnClose()
self._router.Close()
def PassMessagePipe(self):
self._error_handler.OnClose()
return self._router.PassMessagePipe()
def AddOnErrorCallback(self, callback):
self._error_handler.AddCallback(lambda _: callback(), False)
class ProxyInstanceManager(InstanceManager):
"""
Manager for the implementation of a proxy. The manager allows to control the
connection over the pipe.
"""
def __init__(self, interface_manager, proxy, router, error_handler, version):
super(ProxyInstanceManager, self).__init__(
interface_manager, router, error_handler)
self.proxy = proxy
self.version = version
self._run_method = _ProxyMethodCall(_BaseMethodDescriptor(
'Run',
interface_control_messages_mojom.RUN_MESSAGE_ID,
interface_control_messages_mojom.RunMessageParams,
interface_control_messages_mojom.RunResponseMessageParams))
self._run_or_close_pipe_method = _ProxyMethodCall(_BaseMethodDescriptor(
'RunOrClosePipe',
interface_control_messages_mojom.RUN_OR_CLOSE_PIPE_MESSAGE_ID,
interface_control_messages_mojom.RunOrClosePipeMessageParams,
None))
def QueryVersion(self):
params = interface_control_messages_mojom.RunMessageParams()
params.reserved0 = 16
params.reserved1 = 0
params.query_version = (
interface_control_messages_mojom.QueryVersion())
def ToVersion(r):
self.version = r.query_version_result.version
return self.version
return self._run_method(self.proxy, **params.AsDict()).Then(ToVersion)
def RequireVersion(self, version):
if self.version >= version:
return
self.version = version
params = interface_control_messages_mojom.RunOrClosePipeMessageParams()
params.reserved0 = 16
params.reserved1 = 0
params.require_version = interface_control_messages_mojom.RequireVersion()
params.require_version.version = version
return self._run_or_close_pipe_method(self.proxy, **params.AsDict())
class _BaseMethodDescriptor(object):
def __init__(self, name, ordinal, parameters_struct, response_struct):
self.name = name
self.ordinal = ordinal
self.parameters_struct = parameters_struct
self.response_struct = response_struct
class _MethodDescriptor(_BaseMethodDescriptor):
def __init__(self, descriptor):
name = descriptor['name']
super(_MethodDescriptor, self).__init__(
name,
descriptor['ordinal'],
_ConstructParameterStruct(
descriptor['parameters'], name, "Parameters"),
_ConstructParameterStruct(
descriptor.get('responses'), name, "Responses"))
def _ConstructParameterStruct(descriptor, name, suffix):
if descriptor is None:
return None
parameter_dictionary = {
'__metaclass__': reflection.MojoStructType,
'__module__': __name__,
'DESCRIPTOR': descriptor,
}
return reflection.MojoStructType(
'%s%s' % (name, suffix),
(object,),
parameter_dictionary)
class _ProxyErrorHandler(messaging.ConnectionErrorHandler):
def __init__(self):
messaging.ConnectionErrorHandler.__init__(self)
self._callbacks = dict()
def OnError(self, result):
if self._callbacks is None:
return
exception = messaging.MessagingException('Mojo error: %d' % result)
for (callback, _) in self._callbacks.iteritems():
callback(exception)
self._callbacks = None
def OnClose(self):
if self._callbacks is None:
return
exception = messaging.MessagingException('Router has been closed.')
for (callback, call_on_close) in self._callbacks.iteritems():
if call_on_close:
callback(exception)
self._callbacks = None
def AddCallback(self, callback, call_on_close=True):
if self._callbacks is not None:
self._callbacks[callback] = call_on_close
def RemoveCallback(self, callback):
if self._callbacks:
del self._callbacks[callback]
class _Retainer(object):
# Set to force instances to be retained.
_RETAINED = set()
def __init__(self, retained):
self._retained = retained
_Retainer._RETAINED.add(self)
def release(self):
self._retained = None
_Retainer._RETAINED.remove(self)
def _ProxyInit(self, router, error_handler):
self._router = router
self._error_handler = error_handler
# pylint: disable=W0212
def _ProxyMethodCall(method):
flags = messaging.NO_FLAG
if method.response_struct:
flags = messaging.MESSAGE_EXPECTS_RESPONSE_FLAG
def _Call(self, *args, **kwargs):
def GenerationMethod(resolve, reject):
message = _GetMessage(method, flags, None, *args, **kwargs)
if method.response_struct:
def Accept(message):
try:
assert message.header.message_type == method.ordinal
payload = message.payload
response = method.response_struct.Deserialize(
serialization.RootDeserializationContext(payload.data,
payload.handles))
as_dict = response.AsDict()
if len(as_dict) == 1:
value = as_dict.values()[0]
if not isinstance(value, dict):
response = value
resolve(response)
return True
except Exception as e:
# Adding traceback similarly to python 3.0 (pep-3134)
e.__traceback__ = sys.exc_info()[2]
reject(e)
return False
finally:
self._error_handler.RemoveCallback(reject)
self._error_handler.AddCallback(reject)
if not self._router.AcceptWithResponder(
message, messaging.ForwardingMessageReceiver(Accept)):
self._error_handler.RemoveCallback(reject)
reject(messaging.MessagingException("Unable to send message."))
else:
if (self._router.Accept(message)):
resolve(None)
else:
reject(messaging.MessagingException("Unable to send message."))
return promise.Promise(GenerationMethod)
return _Call
def _GetMessageWithStruct(struct, ordinal, flags, request_id):
header = messaging.MessageHeader(
ordinal, flags, 0 if request_id is None else request_id)
data = header.Serialize()
(payload, handles) = struct.Serialize()
data.extend(payload)
return messaging.Message(data, handles, header)
def _GetMessage(method, flags, request_id, *args, **kwargs):
if flags == messaging.MESSAGE_IS_RESPONSE_FLAG:
struct = method.response_struct(*args, **kwargs)
else:
struct = method.parameters_struct(*args, **kwargs)
return _GetMessageWithStruct(struct, method.ordinal, flags, request_id)
def _StubInit(self, impl):
self.impl = impl
def _StubAccept(methods):
methods_by_ordinal = dict((m.ordinal, m) for m in methods)
def Accept(self, message, responder=None):
try:
header = message.header
assert header.expects_response == bool(responder)
if header.message_type == interface_control_messages_mojom.RUN_MESSAGE_ID:
return _RunMessage(self.impl.manager, message, responder)
if (header.message_type ==
interface_control_messages_mojom.RUN_OR_CLOSE_PIPE_MESSAGE_ID):
return _RunMessageOrClosePipe(self.impl.manager, message)
assert header.message_type in methods_by_ordinal
method = methods_by_ordinal[header.message_type]
payload = message.payload
parameters = method.parameters_struct.Deserialize(
serialization.RootDeserializationContext(
payload.data, payload.handles)).AsDict()
response = getattr(self.impl, method.name)(**parameters)
if header.expects_response:
@promise.async
def SendResponse(response):
if isinstance(response, dict):
response_message = _GetMessage(method,
messaging.MESSAGE_IS_RESPONSE_FLAG,
header.request_id,
**response)
else:
response_message = _GetMessage(method,
messaging.MESSAGE_IS_RESPONSE_FLAG,
header.request_id,
response)
return responder.Accept(response_message)
p = SendResponse(response)
if self.impl.manager:
# Close the connection in case of error.
p.Catch(lambda _: self.impl.manager.Close())
return True
# pylint: disable=W0702
except:
# Close the connection in case of error.
logging.warning(
'Error occured in accept method. Connection will be closed.')
logging.debug("Exception", exc_info=True)
if self.impl.manager:
self.impl.manager.Close()
return False
return Accept
def _RunMessage(manager, message, responder):
response = interface_control_messages_mojom.RunResponseMessageParams()
response.reserved0 = 16
response.reserved1 = 0
response.query_version_result = (
interface_control_messages_mojom.QueryVersionResult())
response.query_version_result.version = manager.interface_manager.version
response_message = _GetMessageWithStruct(
response,
interface_control_messages_mojom.RUN_MESSAGE_ID,
messaging.MESSAGE_IS_RESPONSE_FLAG,
message.header.request_id)
return responder.Accept(response_message)
def _RunMessageOrClosePipe(manager, message):
payload = message.payload
query = (
interface_control_messages_mojom.RunOrClosePipeMessageParams.Deserialize(
serialization.RootDeserializationContext(payload.data,
payload.handles)))
return query.require_version.version <= manager.interface_manager.version
def _NotImplemented(*_1, **_2):
raise NotImplementedError()

@ -1,409 +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.
"""Utility classes to handle sending and receiving messages."""
import struct
import sys
import weakref
import mojo_bindings.serialization as serialization
# pylint: disable=E0611,F0401
import mojo_system as system
# The flag values for a message header.
NO_FLAG = 0
MESSAGE_EXPECTS_RESPONSE_FLAG = 1 << 0
MESSAGE_IS_RESPONSE_FLAG = 1 << 1
class MessagingException(Exception):
def __init__(self, *args, **kwargs):
Exception.__init__(self, *args, **kwargs)
self.__traceback__ = sys.exc_info()[2]
class MessageHeader(object):
"""The header of a mojo message."""
_SIMPLE_MESSAGE_VERSION = 0
_SIMPLE_MESSAGE_STRUCT = struct.Struct("<IIII")
_REQUEST_ID_STRUCT = struct.Struct("<Q")
_REQUEST_ID_OFFSET = _SIMPLE_MESSAGE_STRUCT.size
_MESSAGE_WITH_REQUEST_ID_VERSION = 1
_MESSAGE_WITH_REQUEST_ID_SIZE = (
_SIMPLE_MESSAGE_STRUCT.size + _REQUEST_ID_STRUCT.size)
def __init__(self, message_type, flags, request_id=0, data=None):
self._message_type = message_type
self._flags = flags
self._request_id = request_id
self._data = data
@classmethod
def Deserialize(cls, data):
buf = buffer(data)
if len(data) < cls._SIMPLE_MESSAGE_STRUCT.size:
raise serialization.DeserializationException('Header is too short.')
(size, version, message_type, flags) = (
cls._SIMPLE_MESSAGE_STRUCT.unpack_from(buf))
if (version < cls._SIMPLE_MESSAGE_VERSION):
raise serialization.DeserializationException('Incorrect version.')
request_id = 0
if _HasRequestId(flags):
if version < cls._MESSAGE_WITH_REQUEST_ID_VERSION:
raise serialization.DeserializationException('Incorrect version.')
if (size < cls._MESSAGE_WITH_REQUEST_ID_SIZE or
len(data) < cls._MESSAGE_WITH_REQUEST_ID_SIZE):
raise serialization.DeserializationException('Header is too short.')
(request_id, ) = cls._REQUEST_ID_STRUCT.unpack_from(
buf, cls._REQUEST_ID_OFFSET)
return MessageHeader(message_type, flags, request_id, data)
@property
def message_type(self):
return self._message_type
# pylint: disable=E0202
@property
def request_id(self):
assert self.has_request_id
return self._request_id
# pylint: disable=E0202
@request_id.setter
def request_id(self, request_id):
assert self.has_request_id
self._request_id = request_id
self._REQUEST_ID_STRUCT.pack_into(self._data, self._REQUEST_ID_OFFSET,
request_id)
@property
def has_request_id(self):
return _HasRequestId(self._flags)
@property
def expects_response(self):
return self._HasFlag(MESSAGE_EXPECTS_RESPONSE_FLAG)
@property
def is_response(self):
return self._HasFlag(MESSAGE_IS_RESPONSE_FLAG)
@property
def size(self):
if self.has_request_id:
return self._MESSAGE_WITH_REQUEST_ID_SIZE
return self._SIMPLE_MESSAGE_STRUCT.size
def Serialize(self):
if not self._data:
self._data = bytearray(self.size)
version = self._SIMPLE_MESSAGE_VERSION
size = self._SIMPLE_MESSAGE_STRUCT.size
if self.has_request_id:
version = self._MESSAGE_WITH_REQUEST_ID_VERSION
size = self._MESSAGE_WITH_REQUEST_ID_SIZE
self._SIMPLE_MESSAGE_STRUCT.pack_into(self._data, 0, size, version,
self._message_type, self._flags)
if self.has_request_id:
self._REQUEST_ID_STRUCT.pack_into(self._data, self._REQUEST_ID_OFFSET,
self._request_id)
return self._data
def _HasFlag(self, flag):
return self._flags & flag != 0
class Message(object):
"""A message for a message pipe. This contains data and handles."""
def __init__(self, data=None, handles=None, header=None):
self.data = data
self.handles = handles
self._header = header
self._payload = None
@property
def header(self):
if self._header is None:
self._header = MessageHeader.Deserialize(self.data)
return self._header
@property
def payload(self):
if self._payload is None:
self._payload = Message(self.data[self.header.size:], self.handles)
return self._payload
def SetRequestId(self, request_id):
header = self.header
header.request_id = request_id
(data, _) = header.Serialize()
self.data[:header.Size] = data[:header.Size]
class MessageReceiver(object):
"""A class which implements this interface can receive Message objects."""
def Accept(self, message):
"""
Receive a Message. The MessageReceiver is allowed to mutate the message.
Args:
message: the received message.
Returns:
True if the message has been handled, False otherwise.
"""
raise NotImplementedError()
class MessageReceiverWithResponder(MessageReceiver):
"""
A MessageReceiver that can also handle the response message generated from the
given message.
"""
def AcceptWithResponder(self, message, responder):
"""
A variant on Accept that registers a MessageReceiver (known as the
responder) to handle the response message generated from the given message.
The responder's Accept method may be called as part of the call to
AcceptWithResponder, or some time after its return.
Args:
message: the received message.
responder: the responder that will receive the response.
Returns:
True if the message has been handled, False otherwise.
"""
raise NotImplementedError()
class ConnectionErrorHandler(object):
"""
A ConnectionErrorHandler is notified of an error happening while using the
bindings over message pipes.
"""
def OnError(self, result):
raise NotImplementedError()
class Connector(MessageReceiver):
"""
A Connector owns a message pipe and will send any received messages to the
registered MessageReceiver. It also acts as a MessageReceiver and will send
any message through the handle.
The method Start must be called before the Connector will start listening to
incoming messages.
"""
def __init__(self, handle):
MessageReceiver.__init__(self)
self._handle = handle
self._cancellable = None
self._incoming_message_receiver = None
self._error_handler = None
def __del__(self):
if self._cancellable:
self._cancellable()
def SetIncomingMessageReceiver(self, message_receiver):
"""
Set the MessageReceiver that will receive message from the owned message
pipe.
"""
self._incoming_message_receiver = message_receiver
def SetErrorHandler(self, error_handler):
"""
Set the ConnectionErrorHandler that will be notified of errors on the owned
message pipe.
"""
self._error_handler = error_handler
def Start(self):
assert not self._cancellable
self._RegisterAsyncWaiterForRead()
def Accept(self, message):
result = self._handle.WriteMessage(message.data, message.handles)
return result == system.RESULT_OK
def Close(self):
if self._cancellable:
self._cancellable()
self._cancellable = None
self._handle.Close()
def PassMessagePipe(self):
if self._cancellable:
self._cancellable()
self._cancellable = None
result = self._handle
self._handle = system.Handle()
return result
def _OnAsyncWaiterResult(self, result):
self._cancellable = None
if result == system.RESULT_OK:
self._ReadOutstandingMessages()
else:
self._OnError(result)
def _OnError(self, result):
assert not self._cancellable
if self._error_handler:
self._error_handler.OnError(result)
self._handle.Close()
def _RegisterAsyncWaiterForRead(self) :
assert not self._cancellable
self._cancellable = self._handle.AsyncWait(
system.HANDLE_SIGNAL_READABLE,
system.DEADLINE_INDEFINITE,
_WeakCallback(self._OnAsyncWaiterResult))
def _ReadOutstandingMessages(self):
result = None
dispatched = True
while dispatched:
result, dispatched = _ReadAndDispatchMessage(
self._handle, self._incoming_message_receiver)
if result == system.RESULT_SHOULD_WAIT:
self._RegisterAsyncWaiterForRead()
return
self._OnError(result)
class Router(MessageReceiverWithResponder):
"""
A Router will handle mojo message and forward those to a Connector. It deals
with parsing of headers and adding of request ids in order to be able to match
a response to a request.
"""
def __init__(self, handle):
MessageReceiverWithResponder.__init__(self)
self._incoming_message_receiver = None
self._next_request_id = 1
self._responders = {}
self._connector = Connector(handle)
self._connector.SetIncomingMessageReceiver(
ForwardingMessageReceiver(_WeakCallback(self._HandleIncomingMessage)))
def Start(self):
self._connector.Start()
def SetIncomingMessageReceiver(self, message_receiver):
"""
Set the MessageReceiver that will receive message from the owned message
pipe.
"""
self._incoming_message_receiver = message_receiver
def SetErrorHandler(self, error_handler):
"""
Set the ConnectionErrorHandler that will be notified of errors on the owned
message pipe.
"""
self._connector.SetErrorHandler(error_handler)
def Accept(self, message):
# A message without responder is directly forwarded to the connector.
return self._connector.Accept(message)
def AcceptWithResponder(self, message, responder):
# The message must have a header.
header = message.header
assert header.expects_response
request_id = self._NextRequestId()
header.request_id = request_id
if not self._connector.Accept(message):
return False
self._responders[request_id] = responder
return True
def Close(self):
self._connector.Close()
def PassMessagePipe(self):
return self._connector.PassMessagePipe()
def _HandleIncomingMessage(self, message):
header = message.header
if header.expects_response:
if self._incoming_message_receiver:
return self._incoming_message_receiver.AcceptWithResponder(
message, self)
# If we receive a request expecting a response when the client is not
# listening, then we have no choice but to tear down the pipe.
self.Close()
return False
if header.is_response:
request_id = header.request_id
responder = self._responders.pop(request_id, None)
if responder is None:
return False
return responder.Accept(message)
if self._incoming_message_receiver:
return self._incoming_message_receiver.Accept(message)
# Ok to drop the message
return False
def _NextRequestId(self):
request_id = self._next_request_id
while request_id == 0 or request_id in self._responders:
request_id = (request_id + 1) % (1 << 64)
self._next_request_id = (request_id + 1) % (1 << 64)
return request_id
class ForwardingMessageReceiver(MessageReceiver):
"""A MessageReceiver that forward calls to |Accept| to a callable."""
def __init__(self, callback):
MessageReceiver.__init__(self)
self._callback = callback
def Accept(self, message):
return self._callback(message)
def _WeakCallback(callback):
func = callback.im_func
self = callback.im_self
if not self:
return callback
weak_self = weakref.ref(self)
def Callback(*args, **kwargs):
self = weak_self()
if self:
return func(self, *args, **kwargs)
return Callback
def _ReadAndDispatchMessage(handle, message_receiver):
dispatched = False
(result, _, sizes) = handle.ReadMessage()
if result == system.RESULT_OK and message_receiver:
dispatched = message_receiver.Accept(Message(bytearray(), []))
if result != system.RESULT_RESOURCE_EXHAUSTED:
return (result, dispatched)
(result, data, _) = handle.ReadMessage(bytearray(sizes[0]), sizes[1])
if result == system.RESULT_OK and message_receiver:
dispatched = message_receiver.Accept(Message(data[0], data[1]))
return (result, dispatched)
def _HasRequestId(flags):
return flags & (MESSAGE_EXPECTS_RESPONSE_FLAG|MESSAGE_IS_RESPONSE_FLAG) != 0

@ -1,221 +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.
"""
Promise used by the python bindings.
The API is following the ECMAScript 6 API for promises.
"""
import sys
class Promise(object):
"""The promise object."""
STATE_PENDING = 0
STATE_FULLFILLED = 1
STATE_REJECTED = 2
STATE_BOUND = 3
def __init__(self, generator_function):
"""
Constructor.
Args:
generator_function: A function taking 2 arguments: resolve and reject.
When |resolve| is called, the promise is fullfilled with the given value.
When |reject| is called, the promise is rejected with the given value.
A promise can only be resolved or rejected once, all following calls will
have no effect.
"""
self._onCatched = []
self._onFulfilled = []
self._onRejected = []
self._state = Promise.STATE_PENDING
self._result = None
try:
generator_function(self._Resolve, self._Reject)
except Exception as e:
# Adding traceback similarly to python 3.0 (pep-3134)
e.__traceback__ = sys.exc_info()[2]
self._Reject(e)
@staticmethod
def Resolve(value):
"""
If value is a promise, make a promise that have the same behavior as value,
otherwise make a promise that fulfills to value.
"""
if isinstance(value, Promise):
return value
return Promise(lambda x, y: x(value))
@staticmethod
def Reject(reason):
"Make a promise that rejects to reason."""
return Promise(lambda x, y: y(reason))
@staticmethod
def All(*iterable):
"""
Make a promise that fulfills when every item in the array fulfills, and
rejects if (and when) any item rejects. Each array item is passed to
Promise.resolve, so the array can be a mixture of promise-like objects and
other objects. The fulfillment value is an array (in order) of fulfillment
values. The rejection value is the first rejection value.
"""
def GeneratorFunction(resolve, reject):
state = {
'rejected': False,
'nb_resolved': 0,
}
promises = [Promise.Resolve(x) for x in iterable]
results = [None for x in promises]
def OnFullfilled(i):
def OnFullfilled(res):
if state['rejected']:
return
results[i] = res
state['nb_resolved'] = state['nb_resolved'] + 1
if state['nb_resolved'] == len(results):
resolve(results)
return OnFullfilled
def OnRejected(reason):
if state['rejected']:
return
state['rejected'] = True
reject(reason)
for (i, promise) in enumerate(promises):
promise.Then(OnFullfilled(i), OnRejected)
return Promise(GeneratorFunction)
@staticmethod
def Race(*iterable):
"""
Make a Promise that fulfills as soon as any item fulfills, or rejects as
soon as any item rejects, whichever happens first.
"""
def GeneratorFunction(resolve, reject):
state = {
'ended': False
}
def OnEvent(callback):
def OnEvent(res):
if state['ended']:
return
state['ended'] = True
callback(res)
return OnEvent
for promise in [Promise.Resolve(x) for x in iterable]:
promise.Then(OnEvent(resolve), OnEvent(reject))
return Promise(GeneratorFunction)
@property
def state(self):
if isinstance(self._result, Promise):
return self._result.state
return self._state
def Then(self, onFullfilled=None, onRejected=None):
"""
onFulfilled is called when/if this promise resolves. onRejected is called
when/if this promise rejects. Both are optional, if either/both are omitted
the next onFulfilled/onRejected in the chain is called. Both callbacks have
a single parameter, the fulfillment value or rejection reason. |Then|
returns a new promise equivalent to the value you return from
onFulfilled/onRejected after being passed through Resolve. If an
error is thrown in the callback, the returned promise rejects with that
error.
"""
if isinstance(self._result, Promise):
return self._result.Then(onFullfilled, onRejected)
def GeneratorFunction(resolve, reject):
recover = reject
if onRejected:
recover = resolve
if self._state == Promise.STATE_PENDING:
self._onFulfilled.append(_Delegate(resolve, reject, onFullfilled))
self._onRejected.append(_Delegate(recover, reject, onRejected))
if self._state == self.STATE_FULLFILLED:
_Delegate(resolve, reject, onFullfilled)(self._result)
if self._state == self.STATE_REJECTED:
_Delegate(recover, reject, onRejected)(self._result)
return Promise(GeneratorFunction)
def Catch(self, onCatched):
"""Equivalent to |Then(None, onCatched)|"""
return self.Then(None, onCatched)
def __getattr__(self, attribute):
"""
Allows to get member of a promise. It will return a promise that will
resolve to the member of the result.
"""
return self.Then(lambda v: getattr(v, attribute))
def __call__(self, *args, **kwargs):
"""
Allows to call this promise. It will return a promise that will resolved to
the result of calling the result of this promise with the given arguments.
"""
return self.Then(lambda v: v(*args, **kwargs))
def _Resolve(self, value):
if self.state != Promise.STATE_PENDING:
return
self._result = value
if isinstance(value, Promise):
self._state = Promise.STATE_BOUND
self._result.Then(_IterateAction(self._onFulfilled),
_IterateAction(self._onRejected))
return
self._state = Promise.STATE_FULLFILLED
for f in self._onFulfilled:
f(value)
self._onFulfilled = None
self._onRejected = None
def _Reject(self, reason):
if self.state != Promise.STATE_PENDING:
return
self._result = reason
self._state = Promise.STATE_REJECTED
for f in self._onRejected:
f(reason)
self._onFulfilled = None
self._onRejected = None
def async(f):
def _ResolvePromises(*args, **kwargs):
keys = kwargs.keys()
values = kwargs.values()
all_args = list(args) + values
return Promise.All(*all_args).Then(
lambda r: f(*r[:len(args)], **dict(zip(keys, r[len(args):]))))
return _ResolvePromises
def _IterateAction(iterable):
def _Run(x):
for f in iterable:
f(x)
return _Run
def _Delegate(resolve, reject, action):
def _Run(x):
try:
if action:
resolve(action(x))
else:
resolve(x)
except Exception as e:
# Adding traceback similarly to python 3.0 (pep-3134)
e.__traceback__ = sys.exc_info()[2]
reject(e)
return _Run

@ -1,310 +0,0 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""The metaclasses used by the mojo python bindings."""
import itertools
# pylint: disable=F0401
import mojo_bindings.serialization as serialization
class MojoEnumType(type):
"""Meta class for enumerations.
Usage:
class MyEnum(object):
__metaclass__ = MojoEnumType
VALUES = [
('A', 0),
'B',
('C', 5),
]
This will define a enum with 3 values, 'A' = 0, 'B' = 1 and 'C' = 5.
"""
def __new__(mcs, name, bases, dictionary):
dictionary['__slots__'] = ()
dictionary['__new__'] = None
for value in dictionary.pop('VALUES', []):
if not isinstance(value, tuple):
raise ValueError('incorrect value: %r' % value)
key, enum_value = value
if isinstance(key, str) and isinstance(enum_value, int):
dictionary[key] = enum_value
else:
raise ValueError('incorrect value: %r' % value)
return type.__new__(mcs, name, bases, dictionary)
def __setattr__(cls, key, value):
raise AttributeError('can\'t set attribute')
def __delattr__(cls, key):
raise AttributeError('can\'t delete attribute')
class MojoStructType(type):
"""Meta class for structs.
Usage:
class MyStruct(object):
__metaclass__ = MojoStructType
DESCRIPTOR = {
'constants': {
'C1': 1,
'C2': 2,
},
'enums': {
'ENUM1': [
('V1', 1),
'V2',
],
'ENUM2': [
('V1', 1),
'V2',
],
},
'fields': [
SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
],
}
This will define an struct, with:
- 2 constants 'C1' and 'C2';
- 2 enums 'ENUM1' and 'ENUM2', each of those having 2 values, 'V1' and
'V2';
- 1 int32 field named 'x'.
"""
def __new__(mcs, name, bases, dictionary):
dictionary['__slots__'] = ('_fields')
descriptor = dictionary.pop('DESCRIPTOR', {})
# Add constants
dictionary.update(descriptor.get('constants', {}))
# Add enums
enums = descriptor.get('enums', {})
for key in enums:
dictionary[key] = MojoEnumType(key, (object,), { 'VALUES': enums[key] })
# Add fields
groups = descriptor.get('fields', [])
fields = list(
itertools.chain.from_iterable([group.descriptors for group in groups]))
fields.sort(key=lambda f: f.index)
for field in fields:
dictionary[field.name] = _BuildProperty(field)
# Add init
dictionary['__init__'] = _StructInit(fields)
# Add serialization method
serialization_object = serialization.Serialization(groups)
def Serialize(self, handle_offset=0):
return serialization_object.Serialize(self, handle_offset)
dictionary['Serialize'] = Serialize
# pylint: disable=W0212
def AsDict(self):
return self._fields
dictionary['AsDict'] = AsDict
def Deserialize(cls, context):
result = cls.__new__(cls)
fields = {}
serialization_object.Deserialize(fields, context)
result._fields = fields
return result
dictionary['Deserialize'] = classmethod(Deserialize)
dictionary['__eq__'] = _StructEq(fields)
dictionary['__ne__'] = _StructNe
return type.__new__(mcs, name, bases, dictionary)
# Prevent adding new attributes, or mutating constants.
def __setattr__(cls, key, value):
raise AttributeError('can\'t set attribute')
# Prevent deleting constants.
def __delattr__(cls, key):
raise AttributeError('can\'t delete attribute')
class MojoUnionType(type):
def __new__(mcs, name, bases, dictionary):
dictionary['__slots__'] = ('_cur_field', '_data')
descriptor = dictionary.pop('DESCRIPTOR', {})
fields = descriptor.get('fields', [])
def _BuildUnionProperty(field):
# pylint: disable=W0212
def Get(self):
if self._cur_field != field:
raise AttributeError('%s is not currently set' % field.name,
field.name, self._cur_field.name)
return self._data
# pylint: disable=W0212
def Set(self, value):
self._cur_field = field
self._data = field.field_type.Convert(value)
return property(Get, Set)
for field in fields:
dictionary[field.name] = _BuildUnionProperty(field)
def UnionInit(self, **kwargs):
self.SetInternals(None, None)
items = kwargs.items()
if len(items) == 0:
return
if len(items) > 1:
raise TypeError('only 1 member may be set on a union.')
setattr(self, items[0][0], items[0][1])
dictionary['__init__'] = UnionInit
serializer = serialization.UnionSerializer(fields)
def SerializeUnionInline(self, handle_offset=0):
return serializer.SerializeInline(self, handle_offset)
dictionary['SerializeInline'] = SerializeUnionInline
def SerializeUnion(self, handle_offset=0):
return serializer.Serialize(self, handle_offset)
dictionary['Serialize'] = SerializeUnion
def DeserializeUnion(cls, context):
return serializer.Deserialize(context, cls)
dictionary['Deserialize'] = classmethod(DeserializeUnion)
class Tags(object):
__metaclass__ = MojoEnumType
VALUES = [(field.name, field.index) for field in fields]
dictionary['Tags'] = Tags
def GetTag(self):
return self._cur_field.index
dictionary['tag'] = property(GetTag, None)
def GetData(self):
return self._data
dictionary['data'] = property(GetData, None)
def IsUnknown(self):
return not self._cur_field
dictionary['IsUnknown'] = IsUnknown
def UnionEq(self, other):
return (
(type(self) is type(other))
and (self.tag == other.tag)
and (self.data == other.data))
dictionary['__eq__'] = UnionEq
def UnionNe(self, other):
return not self.__eq__(other)
dictionary['__ne__'] = UnionNe
def UnionStr(self):
return '<%s.%s(%s): %s>' % (
self.__class__.__name__,
self._cur_field.name,
self.tag,
self.data)
dictionary['__str__'] = UnionStr
dictionary['__repr__'] = UnionStr
def SetInternals(self, field, data):
self._cur_field = field
self._data = data
dictionary['SetInternals'] = SetInternals
return type.__new__(mcs, name, bases, dictionary)
class InterfaceRequest(object):
"""
An interface request allows to send a request for an interface to a remote
object and start using it immediately.
"""
def __init__(self, handle):
self._handle = handle
def IsPending(self):
return self._handle.IsValid()
def PassMessagePipe(self):
result = self._handle
self._handle = None
return result
def Bind(self, impl):
type(impl).manager.Bind(impl, self.PassMessagePipe())
class InterfaceProxy(object):
"""
A proxy allows to access a remote interface through a message pipe.
"""
pass
def _StructInit(fields):
def _Init(self, *args, **kwargs):
if len(args) + len(kwargs) > len(fields):
raise TypeError('__init__() takes %d argument (%d given)' %
(len(fields), len(args) + len(kwargs)))
self._fields = {}
for f, a in zip(fields, args):
self.__setattr__(f.name, a)
remaining_fields = set(x.name for x in fields[len(args):])
for name in kwargs:
if not name in remaining_fields:
if name in (x.name for x in fields[:len(args)]):
raise TypeError(
'__init__() got multiple values for keyword argument %r' % name)
raise TypeError('__init__() got an unexpected keyword argument %r' %
name)
self.__setattr__(name, kwargs[name])
return _Init
def _BuildProperty(field):
"""Build the property for the given field."""
# pylint: disable=W0212
def Get(self):
if field.name not in self._fields:
self._fields[field.name] = field.GetDefaultValue()
return self._fields[field.name]
# pylint: disable=W0212
def Set(self, value):
self._fields[field.name] = field.field_type.Convert(value)
return property(Get, Set)
def _StructEq(fields):
def _Eq(self, other):
if type(self) is not type(other):
return False
for field in fields:
if getattr(self, field.name) != getattr(other, field.name):
return False
return True
return _Eq
def _StructNe(self, other):
return not self.__eq__(other)

@ -1,309 +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.
"""Utility classes for serialization"""
import struct
# Format of a header for a struct, array or union.
HEADER_STRUCT = struct.Struct("<II")
# Format for a pointer.
POINTER_STRUCT = struct.Struct("<Q")
def Flatten(value):
"""Flattens nested lists/tuples into an one-level list. If value is not a
list/tuple, it is converted to an one-item list. For example,
(1, 2, [3, 4, ('56', '7')]) is converted to [1, 2, 3, 4, '56', '7'];
1 is converted to [1].
"""
if isinstance(value, (list, tuple)):
result = []
for item in value:
result.extend(Flatten(item))
return result
return [value]
class SerializationException(Exception):
"""Error when strying to serialize a struct."""
pass
class DeserializationException(Exception):
"""Error when strying to deserialize a struct."""
pass
class DeserializationContext(object):
def ClaimHandle(self, handle):
raise NotImplementedError()
def ClaimMemory(self, start, size):
raise NotImplementedError()
def GetSubContext(self, offset):
raise NotImplementedError()
def IsInitialContext(self):
raise NotImplementedError()
class RootDeserializationContext(DeserializationContext):
def __init__(self, data, handles):
if isinstance(data, buffer):
self.data = data
else:
self.data = buffer(data)
self._handles = handles
self._next_handle = 0;
self._next_memory = 0;
def ClaimHandle(self, handle):
if handle < self._next_handle:
raise DeserializationException('Accessing handles out of order.')
self._next_handle = handle + 1
return self._handles[handle]
def ClaimMemory(self, start, size):
if start < self._next_memory:
raise DeserializationException('Accessing buffer out of order.')
self._next_memory = start + size
def GetSubContext(self, offset):
return _ChildDeserializationContext(self, offset)
def IsInitialContext(self):
return True
class _ChildDeserializationContext(DeserializationContext):
def __init__(self, parent, offset):
self._parent = parent
self._offset = offset
self.data = buffer(parent.data, offset)
def ClaimHandle(self, handle):
return self._parent.ClaimHandle(handle)
def ClaimMemory(self, start, size):
return self._parent.ClaimMemory(self._offset + start, size)
def GetSubContext(self, offset):
return self._parent.GetSubContext(self._offset + offset)
def IsInitialContext(self):
return False
class Serialization(object):
"""
Helper class to serialize/deserialize a struct.
"""
def __init__(self, groups):
self.version = _GetVersion(groups)
self._groups = groups
main_struct = _GetStruct(groups)
self.size = HEADER_STRUCT.size + main_struct.size
self._struct_per_version = {
self.version: main_struct,
}
self._groups_per_version = {
self.version: groups,
}
def _GetMainStruct(self):
return self._GetStruct(self.version)
def _GetGroups(self, version):
# If asking for a version greater than the last known.
version = min(version, self.version)
if version not in self._groups_per_version:
self._groups_per_version[version] = _FilterGroups(self._groups, version)
return self._groups_per_version[version]
def _GetStruct(self, version):
# If asking for a version greater than the last known.
version = min(version, self.version)
if version not in self._struct_per_version:
self._struct_per_version[version] = _GetStruct(self._GetGroups(version))
return self._struct_per_version[version]
def Serialize(self, obj, handle_offset):
"""
Serialize the given obj. handle_offset is the the first value to use when
encoding handles.
"""
handles = []
data = bytearray(self.size)
HEADER_STRUCT.pack_into(data, 0, self.size, self.version)
position = HEADER_STRUCT.size
to_pack = []
for group in self._groups:
position = position + NeededPaddingForAlignment(position,
group.GetAlignment())
(entry, new_handles) = group.Serialize(
obj,
len(data) - position,
data,
handle_offset + len(handles))
to_pack.extend(Flatten(entry))
handles.extend(new_handles)
position = position + group.GetByteSize()
self._GetMainStruct().pack_into(data, HEADER_STRUCT.size, *to_pack)
return (data, handles)
def Deserialize(self, fields, context):
if len(context.data) < HEADER_STRUCT.size:
raise DeserializationException(
'Available data too short to contain header.')
(size, version) = HEADER_STRUCT.unpack_from(context.data)
if len(context.data) < size or size < HEADER_STRUCT.size:
raise DeserializationException('Header size is incorrect.')
if context.IsInitialContext():
context.ClaimMemory(0, size)
version_struct = self._GetStruct(version)
entities = version_struct.unpack_from(context.data, HEADER_STRUCT.size)
filtered_groups = self._GetGroups(version)
if ((version <= self.version and
size != version_struct.size + HEADER_STRUCT.size) or
size < version_struct.size + HEADER_STRUCT.size):
raise DeserializationException('Struct size in incorrect.')
position = HEADER_STRUCT.size
enties_index = 0
for group in filtered_groups:
position = position + NeededPaddingForAlignment(position,
group.GetAlignment())
enties_count = len(group.GetTypeCode())
if enties_count == 1:
value = entities[enties_index]
else:
value = tuple(entities[enties_index:enties_index+enties_count])
fields.update(group.Deserialize(value, context.GetSubContext(position)))
position += group.GetByteSize()
enties_index += enties_count
def NeededPaddingForAlignment(value, alignment=8):
"""Returns the padding necessary to align value with the given alignment."""
if value % alignment:
return alignment - (value % alignment)
return 0
def _GetVersion(groups):
if not len(groups):
return 0
return max([x.GetMaxVersion() for x in groups])
def _FilterGroups(groups, version):
return [group.Filter(version) for
group in groups if group.GetMinVersion() <= version]
def _GetStruct(groups):
index = 0
codes = [ '<' ]
for group in groups:
code = group.GetTypeCode()
needed_padding = NeededPaddingForAlignment(index, group.GetAlignment())
if needed_padding:
codes.append('x' * needed_padding)
index = index + needed_padding
codes.append(code)
index = index + group.GetByteSize()
alignment_needed = NeededPaddingForAlignment(index)
if alignment_needed:
codes.append('x' * alignment_needed)
return struct.Struct(''.join(codes))
class UnionSerializer(object):
"""
Helper class to serialize/deserialize a union.
"""
def __init__(self, fields):
self._fields = {field.index: field for field in fields}
def SerializeInline(self, union, handle_offset):
data = bytearray()
field = self._fields[union.tag]
# If the union value is a simple type or a nested union, it is returned as
# entry.
# Otherwise, the serialized value is appended to data and the value of entry
# is -1. The caller will need to set entry to the location where the
# caller will append data.
(entry, handles) = field.field_type.Serialize(
union.data, -1, data, handle_offset)
# If the value contained in the union is itself a union, we append its
# serialized value to data and set entry to -1. The caller will need to set
# entry to the location where the caller will append data.
if field.field_type.IsUnion():
nested_union = bytearray(16)
HEADER_STRUCT.pack_into(nested_union, 0, entry[0], entry[1])
POINTER_STRUCT.pack_into(nested_union, 8, entry[2])
data = nested_union + data
# Since we do not know where the caller will append the nested union,
# we set entry to an invalid value and let the caller figure out the right
# value.
entry = -1
return (16, union.tag, entry, data), handles
def Serialize(self, union, handle_offset):
(size, tag, entry, extra_data), handles = self.SerializeInline(
union, handle_offset)
data = bytearray(16)
if extra_data:
entry = 8
data.extend(extra_data)
field = self._fields[union.tag]
HEADER_STRUCT.pack_into(data, 0, size, tag)
typecode = field.GetTypeCode()
# If the value is a nested union, we store a 64 bits pointer to it.
if field.field_type.IsUnion():
typecode = 'Q'
struct.pack_into('<%s' % typecode, data, 8, entry)
return data, handles
def Deserialize(self, context, union_class):
if len(context.data) < HEADER_STRUCT.size:
raise DeserializationException(
'Available data too short to contain header.')
(size, tag) = HEADER_STRUCT.unpack_from(context.data)
if size == 0:
return None
if size != 16:
raise DeserializationException('Invalid union size %s' % size)
union = union_class.__new__(union_class)
if tag not in self._fields:
union.SetInternals(None, None)
return union
field = self._fields[tag]
if field.field_type.IsUnion():
ptr = POINTER_STRUCT.unpack_from(context.data, 8)[0]
value = field.field_type.Deserialize(ptr, context.GetSubContext(ptr+8))
else:
raw_value = struct.unpack_from(
field.GetTypeCode(), context.data, 8)[0]
value = field.field_type.Deserialize(raw_value, context.GetSubContext(8))
union.SetInternals(field, value)
return union

@ -1,803 +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.
# distutils language = c++
cimport c_core
cimport c_export # needed so the init function gets exported
cimport c_thunks
from cpython.buffer cimport PyBUF_CONTIG
from cpython.buffer cimport PyBUF_CONTIG_RO
from cpython.buffer cimport Py_buffer
from cpython.buffer cimport PyBuffer_FillInfo
from cpython.buffer cimport PyBuffer_Release
from cpython.buffer cimport PyObject_GetBuffer
from cpython.mem cimport PyMem_Malloc, PyMem_Free
from cpython.object cimport Py_EQ, Py_NE
from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t, uintptr_t
import weakref
import threading
import mojo_system_impl
def SetSystemThunks(system_thunks_as_object):
"""Bind the basic Mojo Core functions.
This should only be used by the embedder.
"""
cdef const c_thunks.MojoSystemThunks* system_thunks = (
<const c_thunks.MojoSystemThunks*><uintptr_t>system_thunks_as_object)
c_thunks.MojoSetSystemThunks(system_thunks)
HANDLE_INVALID = c_core.MOJO_HANDLE_INVALID
RESULT_OK = c_core.MOJO_RESULT_OK
RESULT_CANCELLED = c_core.MOJO_RESULT_CANCELLED
RESULT_UNKNOWN = c_core.MOJO_RESULT_UNKNOWN
RESULT_INVALID_ARGUMENT = c_core.MOJO_RESULT_INVALID_ARGUMENT
RESULT_DEADLINE_EXCEEDED = c_core.MOJO_RESULT_DEADLINE_EXCEEDED
RESULT_NOT_FOUND = c_core.MOJO_RESULT_NOT_FOUND
RESULT_ALREADY_EXISTS = c_core.MOJO_RESULT_ALREADY_EXISTS
RESULT_PERMISSION_DENIED = c_core.MOJO_RESULT_PERMISSION_DENIED
RESULT_RESOURCE_EXHAUSTED = c_core.MOJO_RESULT_RESOURCE_EXHAUSTED
RESULT_FAILED_PRECONDITION = c_core.MOJO_RESULT_FAILED_PRECONDITION
RESULT_ABORTED = c_core.MOJO_RESULT_ABORTED
RESULT_OUT_OF_RANGE = c_core.MOJO_RESULT_OUT_OF_RANGE
RESULT_UNIMPLEMENTED = c_core.MOJO_RESULT_UNIMPLEMENTED
RESULT_INTERNAL = c_core.MOJO_RESULT_INTERNAL
RESULT_UNAVAILABLE = c_core.MOJO_RESULT_UNAVAILABLE
RESULT_DATA_LOSS = c_core.MOJO_RESULT_DATA_LOSS
RESULT_BUSY = c_core.MOJO_RESULT_BUSY
RESULT_SHOULD_WAIT = c_core.MOJO_RESULT_SHOULD_WAIT
DEADLINE_INDEFINITE = c_core.MOJO_DEADLINE_INDEFINITE
HANDLE_SIGNAL_NONE = c_core.MOJO_HANDLE_SIGNAL_NONE
HANDLE_SIGNAL_READABLE = c_core.MOJO_HANDLE_SIGNAL_READABLE
HANDLE_SIGNAL_WRITABLE = c_core.MOJO_HANDLE_SIGNAL_WRITABLE
HANDLE_SIGNAL_PEER_CLOSED = c_core.MOJO_HANDLE_SIGNAL_PEER_CLOSED
WRITE_MESSAGE_FLAG_NONE = c_core.MOJO_WRITE_MESSAGE_FLAG_NONE
READ_MESSAGE_FLAG_NONE = c_core.MOJO_READ_MESSAGE_FLAG_NONE
READ_MESSAGE_FLAG_MAY_DISCARD = c_core.MOJO_READ_MESSAGE_FLAG_MAY_DISCARD
WRITE_DATA_FLAG_NONE = c_core.MOJO_WRITE_DATA_FLAG_NONE
WRITE_DATA_FLAG_ALL_OR_NONE = c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
READ_DATA_FLAG_NONE = c_core.MOJO_READ_DATA_FLAG_NONE
READ_DATA_FLAG_ALL_OR_NONE = c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE
READ_DATA_FLAG_DISCARD = c_core.MOJO_READ_DATA_FLAG_DISCARD
READ_DATA_FLAG_QUERY = c_core.MOJO_READ_DATA_FLAG_QUERY
READ_DATA_FLAG_PEEK = c_core.MOJO_READ_DATA_FLAG_PEEK
MAP_BUFFER_FLAG_NONE = c_core.MOJO_MAP_BUFFER_FLAG_NONE
_WAITMANY_NO_SIGNAL_STATE_ERRORS = [RESULT_INVALID_ARGUMENT,
RESULT_RESOURCE_EXHAUSTED]
def GetTimeTicksNow():
"""Monotonically increasing tick count representing "right now."
See mojo/public/c/system/functions.h
"""
return c_core.MojoGetTimeTicksNow()
cdef class _ScopedMemory:
"""Allocate memory at creation, and deallocate it at destruction."""
cdef void* memory
def __init__(self, size):
self.memory = PyMem_Malloc(size)
def __dealloc__(self):
PyMem_Free(self.memory)
cdef class _ScopedBuffer:
"""Retrieve pointer to a buffer a creation, and release it at destruction.
"""
cdef Py_buffer _buf
cdef void* buf
cdef Py_ssize_t len
def __init__(self, obj, flags=PyBUF_CONTIG_RO):
if obj:
if PyObject_GetBuffer(obj, &self._buf, flags) < 0:
raise TypeError('Unable to read buffer.')
self.buf = self._buf.buf
self.len = self._buf.len
else:
self.buf = NULL
self.len = 0
def __dealloc__(self):
if self.buf:
PyBuffer_Release(&self._buf)
def _SliceBuffer(buffer, size):
"""Slice the given buffer, reducing it to the given size.
Return None if None is passed in.
"""
if not buffer:
return buffer
return buffer[:size]
cdef class _NativeMemoryView(object):
"""Create a python buffer wrapping the given memory.
Will also retain the given handle until this object is deallocated.
"""
cdef void* _memory
cdef uint32_t _size
cdef char _read_only
cdef char _wrapped
cdef object _handle
def __init__(self, handle):
self._handle = handle
def __cinit__(self):
self._memory = NULL
self._size = 0
self._read_only = True
self._wrapped = False
cdef Wrap(self,
const void* memory,
uint32_t size,
read_only=True):
"""Makes this buffer wraps the given memory.
Must be called before using this buffer, and must only be called once.
"""
assert not self._wrapped
self._wrapped = True
self._memory = <void*>memory
self._size = size
self._read_only = read_only
# buffer interface (PEP 3118)
def __getbuffer__(self, Py_buffer *view, int flags):
assert self._wrapped
if view == NULL:
return
PyBuffer_FillInfo(view,
self,
self._memory,
self._size,
self._read_only,
flags)
def __releasebuffer__(self, Py_buffer *view):
assert self._wrapped
pass
# legacy buffer interface
def __getsegcount__(self, Py_ssize_t *sizes):
assert self._wrapped
if sizes != NULL:
sizes[0] = self._size
return 1
def __getreadbuffer__(self, Py_ssize_t index, void **data):
assert self._wrapped
if index != 0:
raise SystemError('Index out of bounds: %d' % index)
data[0] = self._memory
return self._size
def __getwritebuffer__(self, Py_ssize_t index, void **data):
assert self._wrapped
if index != 0:
raise SystemError('Index out of bounds: %d' % index)
if self._read_only:
raise TypeError('Buffer is read-only.')
data[0] = self._memory
return self._size
class MojoException(Exception):
"""Exception wrapping a mojo result error code."""
def __init__(self, mojo_result):
self.mojo_result = mojo_result
def WaitMany(handles_and_signals, deadline):
"""Waits on a list of handles.
Args:
handles_and_signals: list of tuples of handle and signal.
See mojo/public/c/system/functions.h
"""
cdef uint32_t length = len(handles_and_signals)
cdef uint32_t result_index = <uint32_t>(-1)
cdef _ScopedMemory handles_alloc = _ScopedMemory(
sizeof(c_core.MojoHandle) * length)
cdef _ScopedMemory signals_alloc = _ScopedMemory(
sizeof(c_core.MojoHandleSignals) * length)
cdef _ScopedMemory states_alloc = _ScopedMemory(
sizeof(c_core.MojoHandleSignalsState) * length)
cdef c_core.MojoHandle* handles = <c_core.MojoHandle*>handles_alloc.memory
cdef c_core.MojoHandleSignals* signals = (
<c_core.MojoHandleSignals*>signals_alloc.memory)
cdef c_core.MojoHandleSignalsState* states = (
<c_core.MojoHandleSignalsState*>states_alloc.memory)
cdef int index = 0
for (h, s) in handles_and_signals:
handles[index] = (<Handle?>h)._mojo_handle
signals[index] = s
index += 1
cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK
cdef c_core.MojoDeadline cdeadline = deadline
with nogil:
result = c_core.MojoWaitMany(handles, signals, length, cdeadline,
&result_index, states)
returned_result_index = None
if result_index != <uint32_t>(-1):
returned_result_index = result_index
returned_states = None
if result not in _WAITMANY_NO_SIGNAL_STATE_ERRORS:
returned_states = [(states[i].satisfied_signals,
states[i].satisfiable_signals) for i in xrange(length)]
return (result, returned_result_index, returned_states)
cdef class DataPipeTwoPhaseBuffer(object):
"""Return value for two phases read and write.
The buffer field contains the python buffer where data can be read or written.
When done with the buffer, the |end| method must be called with the number of
bytes read or written.
"""
cdef object _buffer
cdef Handle _handle
cdef char _read
def __init__(self, handle, buffer, read=True):
self._buffer = buffer
self._handle = handle
self._read = read
def End(self, num_bytes):
self._buffer = None
cdef c_core.MojoResult result
if self._read:
result = c_core.MojoEndReadData(self._handle._mojo_handle, num_bytes)
else:
result = c_core.MojoEndWriteData(self._handle._mojo_handle, num_bytes)
self._handle = None
return result
@property
def buffer(self):
return self._buffer
def __dealloc__(self):
assert not self._buffer
cdef class MappedBuffer(object):
"""Return value for the |map| operation on shared buffer handles.
The buffer field contains the python buffer where data can be read or written.
When done with the buffer, the |unmap| method must be called.
"""
cdef object _buffer
cdef object _handle
cdef object _cleanup
def __init__(self, handle, buffer, cleanup):
self._buffer = buffer
self._handle = handle
self._cleanup = cleanup
def UnMap(self):
self._buffer = None
cdef c_core.MojoResult result = self._cleanup()
self._cleanup = None
self._handle = None
return result
@property
def buffer(self):
return self._buffer
def __dealloc__(self):
if self._buffer:
self.UnMap()
cdef class Handle(object):
"""A mojo object."""
cdef c_core.MojoHandle _mojo_handle
def __init__(self, mojo_handle=c_core.MOJO_HANDLE_INVALID):
self._mojo_handle = mojo_handle
def _Invalidate(self):
"""Invalidate the current handle.
The close operation is not called. It is the responsability of the caller to
ensure that the handle is not leaked.
"""
self._mojo_handle = c_core.MOJO_HANDLE_INVALID
def __richcmp__(self, other, op):
if op != Py_EQ and op != Py_NE:
raise TypeError('Handle is not ordered')
cdef int equality
if type(self) is not type(other):
equality = id(self) == id(other)
else:
equality = (<Handle>self)._mojo_handle == (<Handle>other)._mojo_handle
if op == Py_EQ:
return equality
else:
return not equality
def IsValid(self):
"""Returns whether this handle is valid."""
return self._mojo_handle != c_core.MOJO_HANDLE_INVALID
def Close(self):
"""Closes this handle.
See mojo/public/c/system/functions.h
"""
cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK
if self.IsValid():
result = c_core.MojoClose(self._mojo_handle)
self._Invalidate()
return result
def __dealloc__(self):
self.Close()
def Wait(self, signals, deadline):
"""Waits on the given handle.
See mojo/public/c/system/functions.h
"""
cdef c_core.MojoHandle handle = self._mojo_handle
cdef c_core.MojoHandleSignals csignals = signals
cdef c_core.MojoDeadline cdeadline = deadline
cdef c_core.MojoHandleSignalsState signal_states
cdef c_core.MojoResult result
with nogil:
result = c_core.MojoWait(handle, csignals, cdeadline, &signal_states)
returned_states = None
if result not in _WAITMANY_NO_SIGNAL_STATE_ERRORS:
returned_states = (signal_states.satisfied_signals,
signal_states.satisfiable_signals)
return (result, returned_states)
def AsyncWait(self, signals, deadline, callback):
cdef c_core.MojoHandle handle = self._mojo_handle
cdef c_core.MojoHandleSignals csignals = signals
cdef c_core.MojoDeadline cdeadline = deadline
wait_id = _ASYNC_WAITER.AsyncWait(
handle,
csignals,
cdeadline,
callback)
def cancel():
_ASYNC_WAITER.CancelWait(wait_id)
return cancel
def WriteMessage(self,
buffer=None,
handles=None,
flags=WRITE_MESSAGE_FLAG_NONE):
"""Writes a message to the message pipe.
This method can only be used on a handle obtained from |MessagePipe()|.
See mojo/public/c/system/message_pipe.h
"""
cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer)
cdef uint32_t input_buffer_length = buffer_as_buffer.len
cdef c_core.MojoHandle* input_handles = NULL
cdef uint32_t input_handles_length = 0
cdef _ScopedMemory handles_alloc = None
if handles:
input_handles_length = len(handles)
handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) *
input_handles_length)
input_handles = <c_core.MojoHandle*>handles_alloc.memory
for i in xrange(input_handles_length):
input_handles[i] = (<Handle?>handles[i])._mojo_handle
cdef c_core.MojoResult res = c_core.MojoWriteMessage(self._mojo_handle,
buffer_as_buffer.buf,
input_buffer_length,
input_handles,
input_handles_length,
flags)
if res == c_core.MOJO_RESULT_OK and handles:
# Handles have been transferred. Let's invalidate those.
for handle in handles:
handle._Invalidate()
return res
def ReadMessage(self,
buffer=None,
max_number_of_handles=0,
flags=READ_MESSAGE_FLAG_NONE):
"""Reads a message from the message pipe.
This method can only be used on a handle obtained from |MessagePipe()|.
This method returns a triplet of value (code, data, sizes):
- if code is RESULT_OK, sizes will be None, and data will be a pair of
(buffer, handles) where buffer is a view of the input buffer with the read
data, and handles is a list of received handles.
- if code is RESULT_RESOURCE_EXHAUSTED, data will be None and sizes will be
a pair of (buffer_size, handles_size) where buffer_size is the size of the
next message data and handles_size is the number of handles in the next
message.
- if code is any other value, data and sizes will be None.
See mojo/public/c/system/message_pipe.h
"""
cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer, PyBUF_CONTIG)
cdef uint32_t input_buffer_length = buffer_as_buffer.len
cdef c_core.MojoHandle* input_handles = NULL
cdef uint32_t input_handles_length = 0
cdef _ScopedMemory handles_alloc = None
if max_number_of_handles > 0:
input_handles_length = max_number_of_handles
handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) *
input_handles_length)
input_handles = <c_core.MojoHandle*>handles_alloc.memory
cdef res = c_core.MojoReadMessage(self._mojo_handle,
buffer_as_buffer.buf,
&input_buffer_length,
input_handles,
&input_handles_length,
flags)
if res == c_core.MOJO_RESULT_RESOURCE_EXHAUSTED:
return (res, None, (input_buffer_length, input_handles_length))
if res == c_core.MOJO_RESULT_OK:
returned_handles = [Handle(input_handles[i])
for i in xrange(input_handles_length)]
return (res,
(_SliceBuffer(buffer, input_buffer_length), returned_handles),
None)
return (res, None, None)
def WriteData(self, buffer=None, flags=WRITE_DATA_FLAG_NONE):
"""
Writes the given data to the data pipe producer.
This method can only be used on a producer handle obtained from
|DataPipe()|.
This method returns a tuple (code, num_bytes).
- If code is RESULT_OK, num_bytes is the number of written bytes.
- Otherwise, num_bytes is None.
See mojo/public/c/system/data_pipe.h
"""
cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer)
cdef uint32_t input_buffer_length = buffer_as_buffer.len
cdef c_core.MojoResult res = c_core.MojoWriteData(self._mojo_handle,
buffer_as_buffer.buf,
&input_buffer_length,
flags)
if res == c_core.MOJO_RESULT_OK:
return (res, input_buffer_length)
return (res, None)
def BeginWriteData(self,
min_size=None,
flags=WRITE_DATA_FLAG_NONE):
"""
Begins a two-phase write to the data pipe producer.
This method can only be used on a producer handle obtained from
|DataPipe()|.
This method returns a tuple (code, two_phase_buffer).
- If code is RESULT_OK, two_phase_buffer is a writable
DataPipeTwoPhaseBuffer
- Otherwise, two_phase_buffer is None.
See mojo/public/c/system/data_pipe.h
"""
cdef void* out_buffer
cdef uint32_t out_size = 0
if min_size:
flags |= c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
out_size = min_size
cdef c_core.MojoResult res = c_core.MojoBeginWriteData(self._mojo_handle,
&out_buffer,
&out_size,
flags)
if res != c_core.MOJO_RESULT_OK:
return (res, None)
cdef _NativeMemoryView view_buffer = _NativeMemoryView(self)
view_buffer.Wrap(out_buffer, out_size, read_only=False)
return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), False))
def ReadData(self, buffer=None, flags=READ_DATA_FLAG_NONE):
"""Reads data from the data pipe consumer.
This method can only be used on a consumer handle obtained from
|DataPipe()|.
This method returns a tuple (code, buffer)
- if code is RESULT_OK, buffer will be a view of the input buffer with the
read data.
- otherwise, buffer will be None.
See mojo/public/c/system/data_pipe.h
"""
cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer)
cdef uint32_t input_buffer_length = buffer_as_buffer.len
cdef c_core.MojoResult res = c_core.MojoReadData(self._mojo_handle,
buffer_as_buffer.buf,
&input_buffer_length,
flags)
if res == c_core.MOJO_RESULT_OK:
return (res, _SliceBuffer(buffer, input_buffer_length))
return (res, None)
def QueryData(self, flags=READ_DATA_FLAG_NONE):
"""Queries the amount of data available on the data pipe consumer.
This method can only be used on a consumer handle obtained from
|DataPipe()|.
This method returns a tuple (code, num_bytes)
- if code is RESULT_OK, num_bytes will be the number of bytes available on
the data pipe consumer.
- otherwise, num_bytes will be None.
See mojo/public/c/system/data_pipe.h
"""
cdef uint32_t num_bytes = 0
cdef c_core.MojoResult res = c_core.MojoReadData(
self._mojo_handle,
NULL,
&num_bytes,
flags|c_core.MOJO_READ_DATA_FLAG_QUERY)
return (res, num_bytes)
def BeginReadData(self, min_size=None, flags=READ_DATA_FLAG_NONE):
"""
Begins a two-phase read to the data pipe consumer.
This method can only be used on a consumer handle obtained from
|DataPipe()|.
This method returns a tuple (code, two_phase_buffer).
- If code is RESULT_OK, two_phase_buffer is a readable
DataPipeTwoPhaseBuffer
- Otherwise, two_phase_buffer is None.
See mojo/public/c/system/data_pipe.h
"""
cdef const void* out_buffer
cdef uint32_t out_size = 0
if min_size:
flags |= c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE
out_size = min_size
cdef c_core.MojoResult res = c_core.MojoBeginReadData(self._mojo_handle,
&out_buffer,
&out_size,
flags)
if res != c_core.MOJO_RESULT_OK:
return (res, None)
cdef _NativeMemoryView view_buffer = _NativeMemoryView(self)
view_buffer.Wrap(out_buffer, out_size, read_only=True)
return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), True))
def Duplicate(self, options=None):
"""Duplicate the shared buffer handle.
This method can only be used on a handle obtained from
|CreateSharedBuffer()| or |Duplicate()|.
See mojo/public/c/system/buffer.h
"""
cdef c_core.MojoDuplicateBufferHandleOptions coptions
cdef c_core.MojoDuplicateBufferHandleOptions* coptions_ptr = NULL
cdef c_core.MojoHandle cnew_handle = c_core.MOJO_HANDLE_INVALID
if options:
coptions.struct_size = sizeof(c_core.MojoDuplicateBufferHandleOptions)
coptions.flags = options.flags
coptions_ptr = &coptions
cdef c_core.MojoResult result = c_core.MojoDuplicateBufferHandle(
self._mojo_handle, coptions_ptr, &cnew_handle)
new_handle = Handle(cnew_handle)
if result != c_core.MOJO_RESULT_OK:
raise MojoException(result)
return new_handle
def Map(self, offset, num_bytes, flags=MAP_BUFFER_FLAG_NONE):
"""Maps the part (at offset |offset| of length |num_bytes|) of the buffer.
This method can only be used on a handle obtained from
|CreateSharedBuffer()| or |Duplicate()|.
This method returns a tuple (code, mapped_buffer).
- If code is RESULT_OK, mapped_buffer is a readable/writable
MappedBuffer
- Otherwise, mapped_buffer is None.
See mojo/public/c/system/buffer.h
"""
cdef void* buffer
res = c_core.MojoMapBuffer(self._mojo_handle,
offset,
num_bytes,
&buffer,
flags)
if res != c_core.MOJO_RESULT_OK:
return (res, None)
cdef _NativeMemoryView view_buffer = _NativeMemoryView(self)
view_buffer.Wrap(buffer, num_bytes, read_only=False)
return (res, MappedBuffer(self,
memoryview(view_buffer),
lambda: c_core.MojoUnmapBuffer(buffer)))
class CreateMessagePipeOptions(object):
"""Options for creating a message pipe.
See mojo/public/c/system/message_pipe.h
"""
FLAG_NONE = c_core.MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE
def __init__(self):
self.flags = CreateMessagePipeOptions.FLAG_NONE
class MessagePipe(object):
"""Creates a message pipe.
The two ends of the message pipe are accessible with the members handle0 and
handle1.
See mojo/public/c/system/message_pipe.h
"""
def __init__(self, options=None):
cdef c_core.MojoCreateMessagePipeOptions coptions
cdef c_core.MojoCreateMessagePipeOptions* coptions_ptr = NULL
cdef c_core.MojoHandle chandle0 = c_core.MOJO_HANDLE_INVALID
cdef c_core.MojoHandle chandle1 = c_core.MOJO_HANDLE_INVALID
if options:
coptions.struct_size = sizeof(c_core.MojoCreateMessagePipeOptions)
coptions.flags = options.flags
coptions_ptr = &coptions
cdef c_core.MojoResult result = c_core.MojoCreateMessagePipe(coptions_ptr,
&chandle0,
&chandle1)
self.handle0 = Handle(chandle0)
self.handle1 = Handle(chandle1)
if result != c_core.MOJO_RESULT_OK:
raise c_core.MojoException(result)
class CreateDataPipeOptions(object):
"""Options for creating a data pipe.
See mojo/public/c/system/data_pipe.h
"""
FLAG_NONE = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE
def __init__(self):
self.flags = CreateDataPipeOptions.FLAG_NONE
self.element_num_bytes = 1
self.capacity_num_bytes = 0
class DataPipe(object):
"""Creates a data pipe.
The producer end of the data pipe is accessible with the member
producer_handle and the consumer end of the data pipe is accessible with the
member cconsumer_handle.
See mojo/public/c/system/data_pipe.h
"""
def __init__(self, options=None):
cdef c_core.MojoCreateDataPipeOptions coptions
cdef c_core.MojoCreateDataPipeOptions* coptions_ptr = NULL
cdef c_core.MojoHandle cproducer_handle = c_core.MOJO_HANDLE_INVALID
cdef c_core.MojoHandle cconsumer_handle = c_core.MOJO_HANDLE_INVALID
if options:
coptions.struct_size = sizeof(c_core.MojoCreateDataPipeOptions)
coptions.flags = options.flags
coptions.element_num_bytes = options.element_num_bytes
coptions.capacity_num_bytes = options.capacity_num_bytes
coptions_ptr = &coptions
cdef c_core.MojoResult result = c_core.MojoCreateDataPipe(coptions_ptr,
&cproducer_handle,
&cconsumer_handle)
self.producer_handle = Handle(cproducer_handle)
self.consumer_handle = Handle(cconsumer_handle)
if result != c_core.MOJO_RESULT_OK:
raise MojoException(result)
class CreateSharedBufferOptions(object):
"""Options for creating a shared buffer.
See mojo/public/c/system/buffer.h
"""
FLAG_NONE = c_core.MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE
def __init__(self):
self.flags = CreateSharedBufferOptions.FLAG_NONE
def CreateSharedBuffer(num_bytes, options=None):
"""Creates a buffer of size |num_bytes| bytes that can be shared.
See mojo/public/c/system/buffer.h
"""
cdef c_core.MojoCreateSharedBufferOptions coptions
cdef c_core.MojoCreateSharedBufferOptions* coptions_ptr = NULL
cdef c_core.MojoHandle chandle = c_core.MOJO_HANDLE_INVALID
if options:
coptions.struct_size = sizeof(c_core.MojoCreateSharedBufferOptions)
coptions.flags = options.flags
coptions_ptr = &coptions
cdef c_core.MojoResult result = c_core.MojoCreateSharedBuffer(coptions_ptr,
num_bytes,
&chandle)
handle = Handle(chandle)
if result != c_core.MOJO_RESULT_OK:
raise MojoException(result)
return handle
class DuplicateSharedBufferOptions(object):
"""Options for duplicating a shared buffer.
See mojo/public/c/system/buffer.h
"""
FLAG_NONE = c_core.MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE
def __init__(self):
self.flags = DuplicateSharedBufferOptions.FLAG_NONE
# Keeps a thread local weak reference to the current run loop.
_RUN_LOOPS = threading.local()
class RunLoop(object):
"""RunLoop to use when using asynchronous operations on handles."""
def __init__(self):
self.__run_loop = mojo_system_impl.RunLoop()
_RUN_LOOPS.loop = weakref.ref(self)
def __del__(self):
del _RUN_LOOPS.loop
def Run(self):
"""Run the runloop until Quit is called."""
return self.__run_loop.Run()
def RunUntilIdle(self):
"""Run the runloop until Quit is called or no operation is waiting."""
return self.__run_loop.RunUntilIdle()
def Quit(self):
"""Quit the runloop."""
return self.__run_loop.Quit()
def PostDelayedTask(self, runnable, delay=0):
"""
Post a task on the runloop. This must be called from the thread owning the
runloop.
"""
return self.__run_loop.PostDelayedTask(runnable, delay)
@staticmethod
def Current():
if hasattr(_RUN_LOOPS, 'loop'):
return _RUN_LOOPS.loop()
return None
_ASYNC_WAITER = mojo_system_impl.AsyncWaiter()

@ -1,75 +0,0 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# distutils language = c++
cimport c_async_waiter
cimport c_environment
cimport c_export # needed so the init function gets exported
cimport c_thunks
from libc.stdint cimport uintptr_t
def SetSystemThunks(system_thunks_as_object):
"""Bind the basic Mojo Core functions.
"""
cdef const c_thunks.MojoSystemThunks* system_thunks = (
<const c_thunks.MojoSystemThunks*><uintptr_t>system_thunks_as_object)
c_thunks.MojoSetSystemThunks(system_thunks)
cdef class RunLoop(object):
"""RunLoop to use when using asynchronous operations on handles."""
cdef c_environment.CRunLoop* c_run_loop
def __init__(self):
assert not <uintptr_t>(c_environment.CRunLoopCurrent())
self.c_run_loop = new c_environment.CRunLoop()
def __dealloc__(self):
del self.c_run_loop
def Run(self):
"""Run the runloop until Quit is called."""
self.c_run_loop.Run()
def RunUntilIdle(self):
"""Run the runloop until Quit is called or no operation is waiting."""
self.c_run_loop.RunUntilIdle()
def Quit(self):
"""Quit the runloop."""
self.c_run_loop.Quit()
def PostDelayedTask(self, runnable, delay=0):
"""
Post a task on the runloop. This must be called from the thread owning the
runloop.
"""
cdef c_environment.CClosure closure = c_environment.BuildClosure(runnable)
self.c_run_loop.PostDelayedTask(closure, delay)
# We use a wrapping class to be able to call the C++ class PythonAsyncWaiter
# across module boundaries.
cdef class AsyncWaiter(object):
cdef c_environment.CEnvironment* _cenvironment
cdef c_async_waiter.PythonAsyncWaiter* _c_async_waiter
def __init__(self):
self._cenvironment = new c_environment.CEnvironment()
self._c_async_waiter = c_environment.NewAsyncWaiter()
def __dealloc__(self):
del self._c_async_waiter
del self._cenvironment
def AsyncWait(self, handle, signals, deadline, callback):
return self._c_async_waiter.AsyncWait(handle, signals, deadline, callback)
def CancelWait(self, wait_id):
self._c_async_waiter.CancelWait(wait_id)

@ -1,118 +0,0 @@
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Rules to generate python packaged applications for Mojo
import("../mojo_sdk.gni")
template("python_package") {
action(target_name) {
script = rebase_path("mojo/public/tools/gn/zip.py", ".", mojo_root)
inputs = invoker.sources
deps = []
zip_inputs = []
if (defined(invoker.deps)) {
deps += invoker.deps
foreach(d, invoker.deps) {
dep_name = get_label_info(d, "name")
dep_target_out_dir = get_label_info(d, "target_out_dir")
zip_inputs += [ "$dep_target_out_dir/$dep_name.pyzip" ]
}
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
output = "$target_out_dir/$target_name.pyzip"
outputs = [
output,
]
rebase_base_dir =
rebase_path(get_label_info(":$target_name", "dir"), root_build_dir)
rebase_inputs = rebase_path(inputs, root_build_dir)
rebase_zip_inputs = rebase_path(zip_inputs, root_build_dir)
rebase_output = rebase_path(output, root_build_dir)
args = [
"--base-dir=$rebase_base_dir",
"--inputs=$rebase_inputs",
"--zip-inputs=$rebase_zip_inputs",
"--output=$rebase_output",
]
}
}
# Use this template to generate a .mojo python application. One of the source
# files should be named __mojo__.py and contain a MojoMain function as the
# entry point. Dependencies of python_packaged_application targets should be
# either mojom targets (and specified using the mojom_deps variable) or
# python_package targets.
template("python_packaged_application") {
package_name = "${target_name}_package"
package_output = "$target_out_dir/$package_name.pyzip"
if (defined(invoker.output_name)) {
mojo_output = "$root_out_dir/" + invoker.output_name + ".mojo"
} else {
mojo_output = "$root_out_dir/" + target_name + ".mojo"
}
if (defined(invoker.debug) && invoker.debug) {
content_handler_param = "?debug=true"
} else {
content_handler_param = ""
}
python_package(package_name) {
sources = invoker.sources
if (defined(invoker.deps)) {
deps = invoker.deps
}
if (defined(invoker.mojom_deps)) {
mojom_deps = invoker.mojom_deps
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
}
action(target_name) {
script = rebase_path("mojo/public/tools/prepend.py", ".", mojo_root)
input = package_output
inputs = [
input,
]
output = mojo_output
outputs = [
output,
]
deps = [
":$package_name",
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
if (defined(invoker.mojom_deps)) {
deps += invoker.mojom_deps
}
if (defined(invoker.datadeps)) {
datadeps = invoker.datadeps
}
rebase_input = rebase_path(input, root_build_dir)
rebase_output = rebase_path(output, root_build_dir)
args = [
"--input=$rebase_input",
"--output=$rebase_output",
"--line=#!mojo mojo:py_content_handler${content_handler_param}",
]
}
}

@ -1,190 +0,0 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/python/src/common.h"
#include <Python.h>
#include "mojo/public/c/environment/async_waiter.h"
#include "mojo/public/cpp/bindings/callback.h"
#include "mojo/public/cpp/bindings/lib/shared_ptr.h"
#include "mojo/public/cpp/environment/logging.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/public/cpp/system/macros.h"
#include "mojo/public/cpp/utility/run_loop.h"
namespace {
void AsyncCallbackForwarder(void* closure, MojoResult result) {
mojo::Callback<void(MojoResult)>* callback =
static_cast<mojo::Callback<void(MojoResult)>*>(closure);
// callback will be deleted when it is run.
callback->Run(result);
}
} // namespace
namespace mojo {
namespace python {
ScopedGIL::ScopedGIL() {
state_ = PyGILState_Ensure();
}
ScopedGIL::~ScopedGIL() {
PyGILState_Release(state_);
}
ScopedPyRef::ScopedPyRef(PyObject* object) : object_(object) {
}
ScopedPyRef::ScopedPyRef(PyObject* object, ScopedPyRefAcquire)
: object_(object) {
if (object_)
Py_XINCREF(object_);
}
ScopedPyRef::ScopedPyRef(const ScopedPyRef& other)
: ScopedPyRef(other, kAcquire) {
}
PyObject* ScopedPyRef::Release() {
PyObject* object = object_;
object_ = nullptr;
return object;
}
ScopedPyRef::~ScopedPyRef() {
if (object_) {
ScopedGIL acquire_gil;
Py_DECREF(object_);
}
}
ScopedPyRef& ScopedPyRef::operator=(const ScopedPyRef& other) {
if (other)
Py_XINCREF(other);
PyObject* old = object_;
object_ = other;
if (old)
Py_DECREF(old);
return *this;
}
PythonClosure::PythonClosure(PyObject* callable, const mojo::Closure& quit)
: callable_(callable, kAcquire), quit_(quit) {
MOJO_DCHECK(callable);
}
PythonClosure::~PythonClosure() {}
void PythonClosure::Run() const {
ScopedGIL acquire_gil;
ScopedPyRef empty_tuple(PyTuple_New(0));
if (!empty_tuple) {
quit_.Run();
return;
}
ScopedPyRef result(PyObject_CallObject(callable_, empty_tuple));
if (!result) {
quit_.Run();
return;
}
}
Closure::Runnable* NewRunnableFromCallable(PyObject* callable,
const mojo::Closure& quit_closure) {
MOJO_DCHECK(PyCallable_Check(callable));
return new PythonClosure(callable, quit_closure);
}
class PythonAsyncWaiter::AsyncWaiterRunnable
: public mojo::Callback<void(MojoResult)>::Runnable {
public:
AsyncWaiterRunnable(PyObject* callable,
CallbackMap* callbacks,
const mojo::Closure& quit)
: wait_id_(0),
callable_(callable, kAcquire),
callbacks_(callbacks),
quit_(quit) {
MOJO_DCHECK(callable_);
MOJO_DCHECK(callbacks_);
}
void set_wait_id(MojoAsyncWaitID wait_id) { wait_id_ = wait_id; }
void Run(MojoResult mojo_result) const override {
MOJO_DCHECK(wait_id_);
// Remove to reference to this object from PythonAsyncWaiter and ensure this
// object will be destroyed when this method exits.
MOJO_DCHECK(callbacks_->find(wait_id_) != callbacks_->end());
internal::SharedPtr<mojo::Callback<void(MojoResult)>> self =
(*callbacks_)[wait_id_];
callbacks_->erase(wait_id_);
ScopedGIL acquire_gil;
ScopedPyRef args_tuple(Py_BuildValue("(i)", mojo_result));
if (!args_tuple) {
quit_.Run();
return;
}
ScopedPyRef result(PyObject_CallObject(callable_, args_tuple));
if (!result) {
quit_.Run();
return;
}
}
private:
MojoAsyncWaitID wait_id_;
ScopedPyRef callable_;
CallbackMap* callbacks_;
const mojo::Closure quit_;
MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiterRunnable);
};
PythonAsyncWaiter::PythonAsyncWaiter(const mojo::Closure& quit_closure)
: quit_(quit_closure) {
async_waiter_ = Environment::GetDefaultAsyncWaiter();
}
PythonAsyncWaiter::~PythonAsyncWaiter() {
for (CallbackMap::const_iterator it = callbacks_.begin();
it != callbacks_.end();
++it) {
async_waiter_->CancelWait(it->first);
}
}
MojoAsyncWaitID PythonAsyncWaiter::AsyncWait(MojoHandle handle,
MojoHandleSignals signals,
MojoDeadline deadline,
PyObject* callable) {
AsyncWaiterRunnable* runner =
new AsyncWaiterRunnable(callable, &callbacks_, quit_);
internal::SharedPtr<mojo::Callback<void(MojoResult)>> callback(
new mojo::Callback<void(MojoResult)>(
static_cast<mojo::Callback<void(MojoResult)>::Runnable*>(runner)));
MojoAsyncWaitID wait_id = async_waiter_->AsyncWait(
handle, signals, deadline, &AsyncCallbackForwarder, callback.get());
callbacks_[wait_id] = callback;
runner->set_wait_id(wait_id);
return wait_id;
}
void PythonAsyncWaiter::CancelWait(MojoAsyncWaitID wait_id) {
if (callbacks_.find(wait_id) != callbacks_.end()) {
async_waiter_->CancelWait(wait_id);
callbacks_.erase(wait_id);
}
}
} // namespace python
} // namespace mojo

@ -1,107 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_PYTHON_SRC_COMMON_H_
#define MOJO_PUBLIC_PYTHON_SRC_COMMON_H_
#include <Python.h>
#include <map>
#include "mojo/public/c/environment/async_waiter.h"
#include "mojo/public/cpp/bindings/callback.h"
#include "mojo/public/cpp/bindings/lib/shared_ptr.h"
#include "mojo/public/cpp/system/core.h"
namespace mojo {
namespace python {
class ScopedGIL {
public:
ScopedGIL();
~ScopedGIL();
private:
PyGILState_STATE state_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedGIL);
};
enum ScopedPyRefAcquire {
kAcquire,
};
class ScopedPyRef {
public:
explicit ScopedPyRef(PyObject* object);
ScopedPyRef(PyObject* object, ScopedPyRefAcquire);
ScopedPyRef(const ScopedPyRef& other);
~ScopedPyRef();
// Releases ownership of the python object contained by this instance.
PyObject* Release();
operator PyObject*() const { return object_; }
ScopedPyRef& operator=(const ScopedPyRef& other);
private:
PyObject* object_;
};
class PythonClosure : public mojo::Closure::Runnable {
public:
PythonClosure(PyObject* callable, const mojo::Closure& quit);
~PythonClosure() override;
void Run() const override;
private:
ScopedPyRef callable_;
const mojo::Closure quit_;
MOJO_DISALLOW_COPY_AND_ASSIGN(PythonClosure);
};
// Create a mojo::Closure from a callable python object.
Closure::Runnable* NewRunnableFromCallable(PyObject* callable,
const Closure& quit_closure);
// AsyncWaiter for python, used to execute a python closure after waiting. If an
// error occurs while executing the closure, the current message loop will be
// exited. See |AsyncWaiter| in mojo/public/c/environment/async_waiter.h for
// more details.
class PythonAsyncWaiter {
public:
explicit PythonAsyncWaiter(const mojo::Closure& quit_closure);
~PythonAsyncWaiter();
MojoAsyncWaitID AsyncWait(MojoHandle handle,
MojoHandleSignals signals,
MojoDeadline deadline,
PyObject* callable);
void CancelWait(MojoAsyncWaitID wait_id);
private:
class AsyncWaiterRunnable;
typedef std::map<MojoAsyncWaitID,
internal::SharedPtr<mojo::Callback<void(MojoResult)> > >
CallbackMap;
CallbackMap callbacks_;
const MojoAsyncWaiter* async_waiter_;
const mojo::Closure quit_;
MOJO_DISALLOW_COPY_AND_ASSIGN(PythonAsyncWaiter);
};
} // namespace python
} // namespace mojo
#endif // MOJO_PUBLIC_PYTHON_SRC_COMMON_H_

@ -1,43 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/python/src/python_system_helper.h"
#include "Python.h"
#include "mojo/public/cpp/utility/run_loop.h"
#include "mojo/public/python/src/common.h"
namespace {
class QuitCurrentRunLoop : public mojo::Closure::Runnable {
public:
void Run() const override {
mojo::RunLoop::current()->Quit();
}
static mojo::Closure NewQuitClosure() {
return mojo::Closure(
static_cast<mojo::Closure::Runnable*>(new QuitCurrentRunLoop()));
}
};
} // namespace
namespace mojo {
namespace python {
Closure BuildClosure(PyObject* callable) {
if (!PyCallable_Check(callable))
return Closure();
return mojo::Closure(
NewRunnableFromCallable(callable, QuitCurrentRunLoop::NewQuitClosure()));
}
PythonAsyncWaiter* NewAsyncWaiter() {
return new PythonAsyncWaiter(QuitCurrentRunLoop::NewQuitClosure());
}
} // namespace python
} // namespace mojo

@ -1,30 +0,0 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_PYTHON_SRC_PYTHON_SYSTEM_HELPER_H_
#define MOJO_PUBLIC_PYTHON_SRC_PYTHON_SYSTEM_HELPER_H_
// Python must be the first include, as it defines preprocessor variable without
// checking if they already exist.
#include <Python.h>
#include <map>
#include "mojo/public/cpp/bindings/callback.h"
#include "mojo/public/python/src/common.h"
namespace mojo {
namespace python {
// Create a mojo::Closure from a callable python object. If an error occurs
// while executing callable, the closure will quit the current run loop.
Closure BuildClosure(PyObject* callable);
// Create a new PythonAsyncWaiter object. Ownership is passed to the caller.
PythonAsyncWaiter* NewAsyncWaiter();
} // namespace python
} // namespace mojo
#endif // MOJO_PUBLIC_PYTHON_SRC_PYTHON_SYSTEM_HELPER_H_

@ -1,118 +0,0 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/module_args/mojo.gni")
import("../mojo.gni")
if (mojo_use_prebuilt_mojo_shell) {
copy("copy_mojo_shell") {
filename = "mojo_shell"
if (is_android) {
filename = "MojoShell.apk"
sources = [
"prebuilt/shell/android-arm/$filename",
]
outputs = [
"$root_out_dir/apks/$filename",
]
} else {
assert(is_linux)
sources = [
"prebuilt/shell/linux-x64/$filename",
]
outputs = [
"$root_out_dir/$filename",
]
}
}
}
if (mojo_use_prebuilt_dart_snapshotter) {
copy("copy_dart_snapshotter") {
if (host_os == "linux") {
platform = "linux-x64"
} else if (host_os == "mac") {
platform = "mac-x64"
} else {
assert(false, "$host_os not supported")
}
sources = [
"prebuilt/dart_snapshotter/$platform/dart_snapshotter",
]
outputs = [
"$root_out_dir/dart_snapshotter",
]
}
}
if (mojo_use_prebuilt_network_service) {
copy("copy_network_service") {
filename = "network_service.mojo"
if (defined(mojo_prebuilt_network_service_location) &&
mojo_prebuilt_network_service_location != "") {
sources = [
"$mojo_prebuilt_network_service_location",
]
} else {
if (is_android) {
assert(current_cpu == "arm",
"Only arm version prebuilt netowrk_service.mojo is available.")
sources = [
"prebuilt/network_service/android-arm/$filename",
]
} else {
assert(is_linux)
sources = [
"prebuilt/network_service/linux-x64/$filename",
]
}
}
outputs = [
"$root_out_dir/$filename",
]
}
copy("copy_network_service_apptests") {
filename = "network_service_apptests.mojo"
if (defined(mojo_prebuilt_network_service_apptests_location) &&
mojo_prebuilt_network_service_apptests_location != "") {
sources = [
"$mojo_prebuilt_network_service_apptests_location",
]
} else {
if (is_android) {
assert(
target_cpu == "arm",
"Only arm version prebuilt netowrk_service_apptests.mojo is available.")
sources = [
"prebuilt/network_service_apptests/android-arm/$filename",
]
} else {
assert(is_linux)
sources = [
"prebuilt/network_service_apptests/linux-x64/$filename",
]
}
}
outputs = [
"$root_out_dir/$filename",
]
}
}
# This rule can be seen as a sort of adapter. This takes a dart framework
# loaded from Google Storage and then puts it in a rule which the
# "dartzip_package" template in mojo/public/dart/rules.gni can introspect on,
# accessing the 'label' and 'target_out_dir' variables.
if (mojo_use_dart_apptest_framework) {
copy("dart_apptest_framework") {
sources = [
"prebuilt/frameworks/apptest.dartzip",
]
outputs = [
"$target_out_dir/dart_apptest_framework.dartzip",
]
}
}

@ -1 +0,0 @@
1b87e90f670ebfee2b55df21b07dc37dc628fe40

@ -1,88 +0,0 @@
{%- macro encode(variable, kind, offset, bit, level=0, check_for_null=True) %}
{%- if kind|is_pointer_array_kind %}
{%- set sub_kind = kind.kind %}
{%- set sub_kind_size = "bindings.kPointerSize" %}
{%- if sub_kind|is_union_kind %}
{%- set sub_kind_size = "bindings.kUnionSize" %}
{%- endif %}
{%- if check_for_null %}
if ({{variable}} == null) {
encoder{{level}}.encodeNullPointer({{offset}}, {{kind|is_nullable_kind|dart_true_false}});
} else {
{%- else %}
{
{%- endif %}
{%- if sub_kind|is_union_kind %}
var encoder{{level + 1}} = encoder{{level}}.encodeUnionArray({{variable}}.length, {{offset}}, {{kind|array_expected_length}});
{%- else %}
var encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}, {{kind|array_expected_length}});
{%- endif %}
for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) {
{{encode(variable~'[i'~level~']', sub_kind, 'bindings.ArrayDataHeader.kHeaderSize + ' ~ sub_kind_size ~ ' * i'~level, 0, level+1)|indent(4)}}
}
}
{%- elif kind|is_map_kind %}
if ({{variable}} == null) {
encoder{{level}}.encodeNullPointer({{offset}}, {{kind|is_nullable_kind|dart_true_false}});
} else {
var encoder{{level + 1}} = encoder{{level}}.encoderForMap({{offset}});
int size{{level}} = {{variable}}.length;
var keys{{level}} = {{variable}}.keys.toList();
var values{{level}} = {{variable}}.values.toList();
{{encode('keys'~level, kind.key_kind|array, 'bindings.ArrayDataHeader.kHeaderSize', 0, level+1, False)|indent(2)}}
{{encode('values'~level, kind.value_kind|array, 'bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize', 0, level+1, False)|indent(2)}}
}
{%- else %}
encoder{{level}}.{{kind|encode_method(variable, offset, bit)}};
{%- endif %}
{%- endmacro %}
{%- macro decode(variable, kind, offset, bit, level=0) %}
{%- if kind|is_struct_kind or
kind|is_pointer_array_kind or
kind|is_map_kind %}
var decoder{{level+1}} = decoder{{level}}.decodePointer({{offset}}, {{kind|is_nullable_kind|dart_true_false}});
{%- if kind|is_struct_kind %}
{{variable}} = {{kind|dart_type}}.decode(decoder{{level+1}});
{%- else %}{# kind|is_pointer_array_kind or is_map_kind #}
{%- if kind|is_nullable_kind %}
if (decoder{{level+1}} == null) {
{{variable}} = null;
} else {
{%- else %}
{
{%- endif %}
{%- if kind|is_map_kind %}
decoder{{level+1}}.decodeDataHeaderForMap();
List<{{kind.key_kind|dart_type}}> keys{{level}};
List<{{kind.value_kind|dart_type}}> values{{level}};
{
{{decode('keys'~level, kind.key_kind|array, 'bindings.ArrayDataHeader.kHeaderSize', 0, level+1)|indent(4)}}
}
{
{{decode('values'~level, kind.value_kind|array('keys'~level~'.length'), 'bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize', 0, level+1)|indent(4)}}
}
{{variable}} = new Map<{{kind.key_kind|dart_type}}, {{kind.value_kind|dart_type}}>.fromIterables(
keys{{level}}, values{{level}});
{%- else %}
{%- set sub_kind = kind.kind %}
{%- if sub_kind|is_union_kind %}
{%- set sub_kind_size = "bindings.kUnionSize" %}
var si{{level+1}} = decoder{{level+1}}.decodeDataHeaderForUnionArray({{kind|array_expected_length}});
{%- else %}
{%- set sub_kind_size = "bindings.kPointerSize" %}
var si{{level+1}} = decoder{{level+1}}.decodeDataHeaderForPointerArray({{kind|array_expected_length}});
{%- endif %}
{{variable}} = new {{kind|dart_type}}(si{{level+1}}.numElements);
for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numElements; ++i{{level+1}}) {
{{decode(variable~'[i'~(level+1)~']', kind.kind, 'bindings.ArrayDataHeader.kHeaderSize + ' ~ sub_kind_size ~ ' * i'~(level+1), 0, level+1)|indent(4)}}
}
{%- endif %}
}
{%- endif %}
{%- elif kind|is_union_kind %}
{{variable}} = {{kind|dart_type}}.decode(decoder{{level}}, {{offset}});
{%- else %}
{{variable}} = decoder{{level}}.{{kind|decode_method(offset, bit)}};
{%- endif %}
{%- endmacro %}

@ -1,5 +0,0 @@
{%- macro enum_def(prefix, enum) -%}
{%- for field in enum.fields %}
{{prefix}}const int {{enum.name}}_{{field.name}} = {{field.resolved_value}};
{%- endfor %}
{%- endmacro %}

@ -1,274 +0,0 @@
{%- for method in interface.methods %}
const int k{{interface|name}}_{{method|name}}_name = {{method.ordinal}};
{%- endfor %}
const String {{interface|name}}Name =
'{{namespace|replace(".","::")}}::{{interface.name}}';
abstract class {{interface|name}} {
{%- for method in interface.methods %}
{%- if method.response_parameters == None %}
void {{method|name}}(
{%- for parameter in method.parameters -%}
{{parameter.kind|dart_type}} {{parameter|name}}{% if not loop.last %}, {% endif %}
{%- endfor -%}
);
{%- else %}
{%- set response_struct = method.response_param_struct %}
Future<{{response_struct|name}}> {{method|name}}(
{%- for parameter in method.parameters -%}
{{parameter.kind|dart_type}} {{parameter|name}},
{%- endfor -%}
[Function responseFactory = null]);
{%- endif %}
{%- endfor %}
{#--- Interface Constants #}
{% for constant in interface.constants %}
static const {{constant|name}} = {{constant.value|expression_to_text}};
{%- endfor %}
{#--- Interface Enums #}
{%- from "enum_definition.tmpl" import enum_def -%}
{%- for enum in interface.enums %}
{{ enum_def(" static ", enum) }}
{%- endfor %}
}
class {{interface|name}}ProxyImpl extends bindings.Proxy {
{{interface|name}}ProxyImpl.fromEndpoint(
core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
{{interface|name}}ProxyImpl.fromHandle(core.MojoHandle handle) :
super.fromHandle(handle);
{{interface|name}}ProxyImpl.unbound() : super.unbound();
static {{interface|name}}ProxyImpl newFromEndpoint(
core.MojoMessagePipeEndpoint endpoint) {
assert(endpoint.setDescription("For {{interface|name}}ProxyImpl"));
return new {{interface|name}}ProxyImpl.fromEndpoint(endpoint);
}
String get name => {{interface|name}}Name;
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
{%- for method in interface.methods %}
{%- if method.response_parameters != None %}
{%- set response_struct = method.response_param_struct %}
case k{{interface|name}}_{{method|name}}_name:
var r = {{response_struct|name}}.deserialize(
message.payload);
if (!message.header.hasRequestId) {
throw 'Expected a message with a valid request Id.';
}
Completer c = completerMap[message.header.requestId];
if (c == null) {
throw 'Message had unknown request Id: ${message.header.requestId}';
}
completerMap.remove(message.header.requestId);
assert(!c.isCompleted);
c.complete(r);
break;
{%- endif %}
{%- endfor %}
default:
throw new bindings.MojoCodecError("Unexpected message name");
break;
}
}
String toString() {
var superString = super.toString();
return "{{interface|name}}ProxyImpl($superString)";
}
}
class _{{interface|name}}ProxyCalls implements {{interface|name}} {
{{interface|name}}ProxyImpl _proxyImpl;
_{{interface|name}}ProxyCalls(this._proxyImpl);
{%- for method in interface.methods %}
{%- if method.response_parameters == None %}
void {{method|name}}(
{%- for parameter in method.parameters -%}
{{parameter.kind|dart_type}} {{parameter|name}}{% if not loop.last %}, {% endif %}
{%- endfor -%}
{%- set request_struct = method.param_struct -%}
) {
assert(_proxyImpl.isBound);
var params = new {{request_struct|name}}();
{%- for parameter in method.parameters %}
params.{{parameter|name}} = {{parameter|name}};
{%- endfor %}
_proxyImpl.sendMessage(params, k{{interface|name}}_{{method|name}}_name);
}
{% else %}
{%- set response_struct = method.response_param_struct %}
{%- set request_struct = method.param_struct %}
Future<{{response_struct|name}}> {{method|name}}(
{%- for parameter in method.parameters -%}
{{parameter.kind|dart_type}} {{parameter|name}},
{%- endfor -%}
[Function responseFactory = null]) {
assert(_proxyImpl.isBound);
var params = new {{request_struct|name}}();
{%- for parameter in method.parameters %}
params.{{parameter|name}} = {{parameter|name}};
{%- endfor %}
return _proxyImpl.sendMessageWithRequestId(
params,
k{{interface|name}}_{{method|name}}_name,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
{%- endif %}
{%- endfor %}
}
class {{interface|name}}Proxy implements bindings.ProxyBase {
final bindings.Proxy impl;
{{interface|name}} ptr;
final String name = {{interface|name}}Name;
{{interface|name}}Proxy({{interface|name}}ProxyImpl proxyImpl) :
impl = proxyImpl,
ptr = new _{{interface|name}}ProxyCalls(proxyImpl);
{{interface|name}}Proxy.fromEndpoint(
core.MojoMessagePipeEndpoint endpoint) :
impl = new {{interface|name}}ProxyImpl.fromEndpoint(endpoint) {
ptr = new _{{interface|name}}ProxyCalls(impl);
}
{{interface|name}}Proxy.fromHandle(core.MojoHandle handle) :
impl = new {{interface|name}}ProxyImpl.fromHandle(handle) {
ptr = new _{{interface|name}}ProxyCalls(impl);
}
{{interface|name}}Proxy.unbound() :
impl = new {{interface|name}}ProxyImpl.unbound() {
ptr = new _{{interface|name}}ProxyCalls(impl);
}
static {{interface|name}}Proxy newFromEndpoint(
core.MojoMessagePipeEndpoint endpoint) {
assert(endpoint.setDescription("For {{interface|name}}Proxy"));
return new {{interface|name}}Proxy.fromEndpoint(endpoint);
}
Future close({bool immediate: false}) => impl.close(immediate: immediate);
int get version => impl.version;
Future<int> queryVersion() => impl.queryVersion();
void requireVersion(int requiredVersion) {
impl.requireVersion(requiredVersion);
}
String toString() {
return "{{interface|name}}Proxy($impl)";
}
}
class {{interface|name}}Stub extends bindings.Stub {
{{interface|name}} _impl = null;
{{interface|name}}Stub.fromEndpoint(
core.MojoMessagePipeEndpoint endpoint, [this._impl])
: super.fromEndpoint(endpoint);
{{interface|name}}Stub.fromHandle(core.MojoHandle handle, [this._impl])
: super.fromHandle(handle);
{{interface|name}}Stub.unbound() : super.unbound();
static {{interface|name}}Stub newFromEndpoint(
core.MojoMessagePipeEndpoint endpoint) {
assert(endpoint.setDescription("For {{interface|name}}Stub"));
return new {{interface|name}}Stub.fromEndpoint(endpoint);
}
static const String name = {{interface|name}}Name;
{% for method in interface.methods %}
{%- if method.response_parameters != None %}
{%- set response_struct = method.response_param_struct %}
{{response_struct|name}} _{{response_struct|name}}Factory(
{%- for param in method.response_parameters -%}
{{param.kind|dart_type}} {{param|name}}{% if not loop.last %}, {% endif %}
{%- endfor -%}
) {
var result = new {{response_struct|name}}();
{%- for param in method.response_parameters %}
result.{{param|name}} = {{param|name}};
{%- endfor %}
return result;
}
{%- endif %}
{%- endfor %}
Future<bindings.Message> handleMessage(bindings.ServiceMessage message) {
if (bindings.ControlMessageHandler.isControlMessage(message)) {
return bindings.ControlMessageHandler.handleMessage(this,
{{interface.version}},
message);
}
assert(_impl != null);
switch (message.header.type) {
{%- for method in interface.methods %}
{%- set request_struct = method.param_struct %}
case k{{interface|name}}_{{method|name}}_name:
var params = {{request_struct|name}}.deserialize(
message.payload);
{%- if method.response_parameters == None %}
_impl.{{method|name}}(
{%- for parameter in method.parameters -%}
params.{{parameter|name}}{% if not loop.last %}, {% endif %}
{%- endfor -%}
);
{%- else %}
{%- set response_struct = method.response_param_struct %}
return _impl.{{method|name}}(
{%- for parameter in method.parameters -%}
params.{{parameter|name}},
{%- endfor -%}
_{{response_struct|name}}Factory).then((response) {
if (response != null) {
return buildResponseWithId(
response,
k{{interface|name}}_{{method|name}}_name,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
});
{%- endif %}
break;
{%- endfor %}
default:
throw new bindings.MojoCodecError("Unexpected message name");
break;
}
return null;
}
{{interface|name}} get impl => _impl;
set impl({{interface|name}} d) {
assert(_impl == null);
_impl = d;
}
String toString() {
var superString = super.toString();
return "{{interface|name}}Stub($superString)";
}
int get version => {{interface.version}};
}

@ -1,16 +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.
library {{module.name|dot_to_underscore}};
import 'dart:async';
import 'package:mojo/bindings.dart' as bindings;
import 'package:mojo/core.dart' as core;
{%- for import in imports %}
import 'package:{{import.rebased_path}}.dart' as {{import.unique_name}};
{%- endfor %}
{%- include "module_definition.tmpl" %}

@ -1,27 +0,0 @@
{#--- Constants #}
{%- for constant in module.constants %}
const {{constant.name}} = {{constant.value|expression_to_text}};
{%- endfor %}
{#--- Enums #}
{%- from "enum_definition.tmpl" import enum_def %}
{%- for enum in enums %}
{{ enum_def("", enum) }}
{%- endfor %}
{#--- Struct definitions #}
{%- from "struct_definition.tmpl" import struct_def %}
{% for struct in structs %}
{{ struct_def(struct) }}
{%- endfor -%}
{#--- Union definitions #}
{%- from "union_definition.tmpl" import union_def %}
{% for union in unions %}
{{ union_def(union) }}
{%- endfor -%}
{#--- Interface definitions #}
{%- for interface in interfaces -%}
{%- include "interface_definition.tmpl" %}
{%- endfor %}

@ -1,96 +0,0 @@
{#--- Begin #}
{%- import "encoding_macros.tmpl" as encoding_macros %}
{%- macro struct_def(struct) %}
class {{struct|name}} extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
{%- for version in struct.versions %}
const bindings.StructDataHeader({{version.num_bytes}}, {{version.version}}){% if not loop.last %},{% endif %}
{%- endfor %}
];
{#--- Enums #}
{%- from "enum_definition.tmpl" import enum_def %}
{%- for enum in struct.enums %}
{{enum_def(" static ", enum)}}
{%- endfor %}
{#--- Constants #}
{%- for constant in struct.constants %}
static const {{constant.name}} = {{constant.value|expression_to_text}};
{%- endfor %}
{#--- initDefaults() #}
{%- for packed_field in struct.packed.packed_fields %}
{{packed_field.field.kind|dart_type}} {{packed_field.field|name}} = {{packed_field.field|default_value}};
{%- endfor %}
{{struct|name}}() : super(kVersions.last.size);
static {{struct|name}} deserialize(bindings.Message message) {
var decoder = new bindings.Decoder(message);
var result = decode(decoder);
decoder.excessHandles.forEach((h) => h.close());
return result;
}
static {{struct|name}} decode(bindings.Decoder decoder0) {
if (decoder0 == null) {
return null;
}
{{struct|name}} result = new {{struct|name}}();
var mainDataHeader = decoder0.decodeStructDataHeader();
if (mainDataHeader.version <= kVersions.last.version) {
// Scan in reverse order to optimize for more recent versions.
for (int i = kVersions.length - 1; i >= 0; --i) {
if (mainDataHeader.version >= kVersions[i].version) {
if (mainDataHeader.size == kVersions[i].size) {
// Found a match.
break;
}
throw new bindings.MojoCodecError(
'Header size doesn\'t correspond to known version size.');
}
}
} else if (mainDataHeader.size < kVersions.last.size) {
throw new bindings.MojoCodecError(
'Message newer than the last known version cannot be shorter than '
'required by the last known version.');
}
{%- for byte in struct.bytes %}
{%- for packed_field in byte.packed_fields %}
if (mainDataHeader.version >= {{packed_field.min_version}}) {
{{encoding_macros.decode('result.' ~ packed_field.field|name, packed_field.field.kind, 8+packed_field.offset, packed_field.bit)|indent(6)}}
}
{%- endfor %}
{%- endfor %}
return result;
}
void encode(bindings.Encoder encoder) {
{%- if not struct.bytes %}
encoder.getStructEncoderAtOffset(kVersions.last);
{%- else %}
var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
{%- endif %}
{%- for byte in struct.bytes %}
{%- for packed_field in byte.packed_fields %}
{{encoding_macros.encode(packed_field.field|name, packed_field.field.kind, 8+packed_field.offset, packed_field.bit)|indent(4)}}
{%- endfor %}
{%- endfor %}
}
String toString() {
return "{{struct|name}}("
{%- for packed_field in struct.packed.packed_fields %}
"{{packed_field.field|name}}: ${{packed_field.field|name}}" {% if not loop.last %}", "{% endif %}
{%- endfor %}")";
}
}
{%- endmacro %}

@ -1,110 +0,0 @@
{#--- Begin #}
{%- import "encoding_macros.tmpl" as encoding_macros %}
{%- macro enum_def(union) %}
enum {{union|name}}Tag {
{%- for field in union.fields %}
{{field|tag_name}},
{%- endfor %}
unknown
}
{%- endmacro %}
{%- macro wrapper_def(union) %}
class {{union|name}} extends bindings.Union {
static final _tag_to_int = const {
{%- for field in union.fields %}
{{union|name}}Tag.{{field|tag_name}}: {{field.ordinal}},
{%- endfor %}
};
static final _int_to_tag = const {
{%- for field in union.fields %}
{{field.ordinal}}: {{union|name}}Tag.{{field|tag_name}},
{%- endfor %}
};
var _data;
{{union|name}}Tag _tag = {{union|name}}Tag.unknown;
{{union|name}}Tag get tag => _tag;
{%- for field in union.fields %}
{{field.kind|dart_type}} get {{field|name}} {
if (_tag != {{union|name}}Tag.{{field|tag_name}}) {
throw new bindings.UnsetUnionTagError(_tag, {{union|name}}Tag.{{field|tag_name}});
}
return _data;
}
set {{field|name}}({{field.kind|dart_type}} value) {
_tag = {{union|name}}Tag.{{field|tag_name}};
_data = value;
}
{%- endfor %}
static {{union|name}} decode(bindings.Decoder decoder0, int offset) {
int size = decoder0.decodeUint32(offset);
if (size == 0) {
return null;
}
{{union|name}} result = new {{union|name}}();
// TODO(azani): Handle unknown union member.
{{union|name}}Tag tag = _int_to_tag[decoder0.decodeUint32(offset + 4)];
switch (tag) {
{%- for field in union.fields %}
case {{union|name}}Tag.{{field|tag_name}}:
{%- if field.kind|is_union_kind %}
var decoder1 = decoder0.decodePointer(offset + 8, {{field.kind|is_nullable_kind|dart_true_false}});
result.{{field|name}} = {{field.kind|dart_type}}.decode(decoder1, 0);
{%- else %}
{{encoding_macros.decode('result.' ~ field|name, field.kind, "offset + 8", 0)|indent(8)}}
{%- endif %}
break;
{%- endfor %}
}
return result;
}
void encode(bindings.Encoder encoder0, int offset) {
// TODO(azani): Error when trying to encode an unknown member.
encoder0.encodeUint32(16, offset);
encoder0.encodeUint32(_tag_to_int[_tag], offset + 4);
switch (_tag) {
{%- for field in union.fields %}
case {{union|name}}Tag.{{field|tag_name}}:
{%- if field.kind|is_union_kind %}
encoder0.encodeNestedUnion({{field|name}}, offset + 8, {{field.kind|is_nullable_kind|dart_true_false}});
{%- else %}
{{encoding_macros.encode(field|name, field.kind, "offset + 8", 0)|indent(8)}}
{%- endif %}
break;
{%- endfor %}
}
}
String toString() {
String result = "{{union|name}}(";
switch (_tag) {
{%- for field in union.fields %}
case {{union|name}}Tag.{{field|tag_name}}:
result += "{{field|name}}";
break;
{%- endfor %}
default:
result += "unknown";
}
result += ": $_data)";
return result;
}
}
{%- endmacro %}
{%- macro union_def(union) %}
{{enum_def(union)}}
{{wrapper_def(union)}}
{%- endmacro %}

@ -1,209 +0,0 @@
{% macro encode(value, kind, level=0) %}
{% if kind|is_nullable %}
if {{value}} == nil {
{% if kind|is_interface %}
encoder.WriteInvalidInterface()
{% elif kind|is_handle %}
encoder.WriteInvalidHandle()
{% elif kind|is_union %}
encoder.WriteNullUnion()
{% else %}
encoder.WriteNullPointer()
{% endif %}
} else {
{% if not kind|is_union %}
{% set value = '(*'~value~')' %}
{% endif %}
{{encodeNonNullable(value, kind, level)|tab_indent()}}
}
{% else -%}
{{encodeNonNullable(value, kind, level)}}
{%- endif %}
{% endmacro %}
{% macro encodeNonNullable(value, kind, level=0) %}
{% if kind|is_pointer %}
if err := encoder.WritePointer(); err != nil {
return err
}
{% elif kind|is_union and not kind|is_nullable %}
if {{value}} == nil {
return &bindings.ValidationError{bindings.UnexpectedNullUnion, "unexpected null union"}
}
{% endif %}
{% if kind|is_struct or kind|is_union %}
if err := {{value}}.Encode(encoder); err != nil {
return err
}
{% elif kind|is_array %}
encoder.StartArray(uint32(len({{value}})), {{kind.kind|bit_size}})
for _, elem{{level}} := range {{value}} {
{{encode('elem'~level, kind.kind, level+1)|tab_indent()}}
}
if err := encoder.Finish(); err != nil {
return err
}
{% elif kind|is_map %}
encoder.StartMap()
{
var keys{{level}} {{kind.key_kind|array|go_type}}
var values{{level}} {{kind.value_kind|array|go_type}}
for key{{level}}, value{{level}} := range {{value}} {
keys{{level}} = append(keys{{level}}, key{{level}})
values{{level}} = append(values{{level}}, value{{level}})
}
{{encode('keys'~level, kind.key_kind|array, level+1)|tab_indent()}}
{{encode('values'~level, kind.value_kind|array, level+1)|tab_indent()}}
}
if err := encoder.Finish(); err != nil {
return err
}
{% elif kind|is_enum %}
if err := encoder.WriteInt32(int32({{value}})); err != nil {
return err
}
{% elif kind|is_interface %}
if err := encoder.WriteInterface({{value}}.PassMessagePipe()); err != nil {
return err
}
{% elif kind|is_interface_request %}
if err := encoder.WriteHandle({{value}}.PassMessagePipe()); err != nil {
return err
}
{% else %}
if err := encoder.Write{{kind|encode_suffix}}({{value}}); err != nil {
return err
}
{% endif %}
{% endmacro %}
{% macro decode(value, kind, level=0) %}
{% if kind|is_pointer %}
pointer{{level}}, err := decoder.ReadPointer()
if err != nil {
return err
}
if pointer{{level}} == 0 {
{% if kind|is_nullable %}
{{value}} = nil
} else {
{{value}} = new({{kind|go_type(False)}})
{{decodePointerValue('(*'~value~')', kind, level)|tab_indent()}}
}
{% else %}
return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
} else {
{{decodePointerValue(value, kind, level)|tab_indent()}}
}
{% endif %}
{% elif kind|is_union %}
var err error
{% set decoding_function = ('Decode'~ kind|name)|qualified(kind|package) %}
{{value}}, err = {{decoding_function}}(decoder)
if err != nil {
return err
}
{% if not kind|is_nullable %}
if {{value}} == nil {
return &bindings.ValidationError{bindings.UnexpectedNullUnion, "unexpected null union"}
}
{% endif %}
{% elif kind|is_handle or kind|is_interface %}
handle{{level}}, err := decoder.Read{{kind|decode_suffix}}()
if err != nil {
return err
}
if handle{{level}}.IsValid() {
{% if kind|is_interface or kind|is_interface_request %}
handleOwner := bindings.NewMessagePipeHandleOwner(handle{{level}})
{{value}} = {% if kind|is_nullable %}&{% endif %}{{kind|go_type(False)}}{handleOwner}
{% else %}
{{value}} = {% if kind|is_nullable %}&{% endif %}handle{{level}}
{% endif %}
} else {
{% if kind|is_nullable %}
{{value}} = nil
{% else %}
return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"}
{% endif %}
}
{% elif kind|is_enum %}
value{{level}}, err := decoder.Read{{kind|decode_suffix}}()
if err != nil {
return err
}
{{value}} = {% if kind|is_nullable %}&{% endif %}{{kind|go_type(False)}}(value{{level}})
{% else %}
value{{level}}, err := decoder.Read{{kind|decode_suffix}}()
if err != nil {
return err
}
{{value}} = {% if kind|is_nullable %}&{% endif %}value{{level}}
{% endif %}
{% endmacro %}
{% macro decodePointerValue(value, kind, level=0) %}
{% if kind|is_struct %}
if err := {{value}}.Decode(decoder); err != nil {
return err
}
{% elif kind|is_array %}
len{{level}}, err := decoder.StartArray({{kind.kind|bit_size}})
if err != nil {
return err
}
{% if kind.length %}
if len{{level}} != {{kind.length}} {
return &bindings.ValidationError{bindings.UnexpectedArrayHeader,
fmt.Sprintf("invalid array length: expected %d, got %d", {{kind.length}}, len{{level}}),
}
}
{% else %}
{{value}} = make({{kind|go_type(False)}}, len{{level}})
{% endif %}
for i{{level}} := uint32(0); i{{level}} < len{{level}}; i{{level}}++ {
{{decode(value~'[i'~level~']', kind.kind, level+1)|tab_indent()}}
}
if err := decoder.Finish(); err != nil {
return err
}
{% elif kind|is_map %}
if err := decoder.StartMap(); err != nil {
return err
}
var keys{{level}} {{kind.key_kind|array|go_type}}
{
{{decode('keys'~level, kind.key_kind|array, level+1)|tab_indent()}}
}
var values{{level}} {{kind.value_kind|array|go_type}}
{
{{decode('values'~level, kind.value_kind|array, level+1)|tab_indent()}}
}
if len(keys{{level}}) != len(values{{level}}) {
return &bindings.ValidationError{bindings.DifferentSizedArraysInMap,
fmt.Sprintf("Number of keys %d is different from number of values %d", len(keys{{level}}), len(values{{level}})),
}
}
if err := decoder.Finish(); err != nil {
return err
}
len{{level}} := len(keys{{level}})
map{{level}} := make({{kind|go_type(False)}})
for i{{level}} := 0; i{{level}} < len{{level}}; i{{level}}++ {
map{{level}}[keys{{level}}[i{{level}}]] = values{{level}}[i{{level}}]
}
{{value}} = map{{level}}
{% else %}
value{{level}}, err := decoder.Read{{kind|decode_suffix}}()
if err != nil {
return err
}
{{value}} = value{{level}}
{% endif %}
{% endmacro %}

@ -1,20 +0,0 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
{% macro define(enum) %}
type {{enum|name}} int32
const (
{% for field in enum.fields %}
{% if field.value %}
{{enum|name}}_{{field|name}} = {{field.value|expression_to_text}}
{% elif loop.first %}
{{enum|name}}_{{field|name}} = 0
{% else %}
{{enum|name}}_{{field|name}} = {{enum|name}}_{{enum.fields[loop.index0 - 1]|name}} + 1;
{% endif %}
{% endfor %}
)
{% endmacro %}

@ -1,229 +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 "struct.tmpl" as struct_macros %}
{%- macro declare_params(struct) %}
{%- for field in struct.fields -%}
{{field|name(False)}} {{field.kind|go_type}}{% if not loop.last %}, {% endif %}
{%- endfor %}
{%- endmacro %}
{% macro declare_request_params(method) %}
({{declare_params(method.param_struct)}})
{%- if method.response_parameters|is_none_or_empty -%}
{{' (err error)'}}
{%- else -%}
{{' '}}({{declare_params(method.response_param_struct)}}, err error)
{%- endif -%}
{% endmacro %}
{%- macro flags(response_parameters, is_response) -%}
{%- if not response_parameters -%}
bindings.MessageNoFlag
{%- elif is_response: -%}
bindings.MessageIsResponseFlag
{%- else -%}
bindings.MessageExpectsResponseFlag
{%- endif -%}
{%- endmacro -%}
{% macro define(interface) %}
type {{interface|name}} interface {
{% for method in interface.methods %}
{{method|name}}{{declare_request_params(method)}}
{% endfor %}
}
var {{interface|name(False)}}_Name = "{{interface.module.namespace|replace(".","::")}}::{{interface.name}}"
type {{interface|name}}_Request bindings.InterfaceRequest
func (r *{{interface|name}}_Request) Name() string {
return {{interface|name(False)}}_Name
}
type {{interface|name}}_Pointer bindings.InterfacePointer
func (p *{{interface|name}}_Pointer) Name() string {
return {{interface|name(False)}}_Name
}
type {{interface|name}}_ServiceFactory struct{
Delegate {{interface|name}}_Factory
}
type {{interface|name}}_Factory interface {
Create(request {{interface|name}}_Request)
}
func (f *{{interface|name}}_ServiceFactory) Name() string {
return {{interface|name(False)}}_Name
}
func (f *{{interface|name}}_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
request := {{interface|name}}_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
f.Delegate.Create(request)
}
// CreateMessagePipeFor{{interface|name}} creates a message pipe for use with the
// {{interface|name}} interface with a {{interface|name}}_Request on one end and a {{interface|name}}_Pointer on the other.
func CreateMessagePipeFor{{interface|name}}() ({{interface|name}}_Request, {{interface|name}}_Pointer) {
r, p := bindings.CreateMessagePipeForMojoInterface()
return {{interface|name}}_Request(r), {{interface|name}}_Pointer(p)
}
{% for method in interface.methods %}
const {{interface|name(False)}}_{{method|name}}_Name uint32 = {{method.ordinal}}
{% endfor %}
type {{interface|name}}_Proxy struct {
router *bindings.Router
ids bindings.Counter
}
func New{{interface|name}}Proxy(p {{interface|name}}_Pointer, waiter bindings.AsyncWaiter) *{{interface|name}}_Proxy {
return &{{interface|name}}_Proxy{
bindings.NewRouter(p.PassMessagePipe(), waiter),
bindings.NewCounter(),
}
}
func (p *{{interface|name}}_Proxy) Close_Proxy() {
p.router.Close()
}
{% for method in interface.methods %}
{{struct_macros.define(method.param_struct, False)}}
{%- if method.response_parameters %}
{{struct_macros.define(method.response_param_struct, False)}}
{%- endif %}
func (p *{{interface|name}}_Proxy) {{method|name}}{{declare_request_params(method)}} {
payload := &{{method.param_struct|name(False)}}{
{% for field in (method.param_struct).fields %}
{{field|name(False)}},
{% endfor %}
}
header := bindings.MessageHeader{
Type: {{interface|name(False)}}_{{method|name}}_Name,
Flags: {{flags(method.response_parameters, False)}},
{% if method.response_parameters %}
RequestId: p.ids.Count(),
{% endif %}
}
var message *bindings.Message
if message, err = bindings.EncodeMessage(header, payload); err != nil {
err = fmt.Errorf("can't encode request: %v", err.Error())
p.Close_Proxy()
return
}
{% if method.response_parameters %}
readResult := <-p.router.AcceptWithResponse(message)
if err = readResult.Error; err != nil {
p.Close_Proxy()
return
}
if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
}
return
}
if got, want := readResult.Message.Header.Type, {{interface|name(False)}}_{{method|name}}_Name; got != want {
err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
}
return
}
var response {{method.response_param_struct|name(False)}}
if err = readResult.Message.DecodePayload(&response); err != nil {
p.Close_Proxy()
return
}
{% for field in (method.response_param_struct).fields %}
{{field|name(False)}} = response.{{field|name(False)}}
{% endfor %}
{% else %}
if err = p.router.Accept(message); err != nil {
p.Close_Proxy()
return
}
{% endif %}
return
}
{% endfor %}
type {{interface|name(False)}}_Stub struct {
connector *bindings.Connector
impl {{interface|name}}
}
func New{{interface|name}}Stub(r {{interface|name}}_Request, impl {{interface|name}}, waiter bindings.AsyncWaiter) *bindings.Stub {
connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
return bindings.NewStub(connector, &{{interface|name(False)}}_Stub{connector, impl})
}
func (s *{{interface|name(False)}}_Stub) Accept(message *bindings.Message) (err error) {
switch message.Header.Type {
{% for method in interface.methods %}
case {{interface|name(False)}}_{{method|name}}_Name:
{% if method.response_parameters %}
if message.Header.Flags != bindings.MessageExpectsResponseFlag {
{% else %}
if message.Header.Flags != bindings.MessageNoFlag {
{% endif %}
return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
}
}
var request {{method.param_struct|name(False)}}
if err := message.DecodePayload(&request); err != nil {
return err
}
{% if method.response_parameters %}
var response {{method.response_param_struct|name(False)}}
{% endif %}
{% if method.response_parameters|is_none_or_empty %}
err = s.impl.{{method|name}}(
{%- else -%}
{% for field in (method.response_param_struct).fields %}
response.{{field|name(False)}}{{', '}}
{%- endfor -%}err = s.impl.{{method|name}}(
{%- endif -%}
{%- for field in (method.param_struct).fields -%}
request.{{field|name(False)}}{% if not loop.last %}, {% endif %}
{%- endfor -%}
)
if err != nil {
return
}
{% if method.response_parameters %}
header := bindings.MessageHeader{
Type: {{interface|name(False)}}_{{method|name}}_Name,
Flags: {{flags(method.response_parameters, True)}},
RequestId: message.Header.RequestId,
}
message, err = bindings.EncodeMessage(header, &response)
if err != nil {
return err
}
return s.connector.WriteMessage(message)
{% endif %}
{% endfor %}
default:
return &bindings.ValidationError{
bindings.MessageHeaderUnknownMethod,
fmt.Sprintf("unknown method %v", message.Header.Type),
}
}
return
}
{% endmacro %}

@ -1,42 +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 file is autogenerated by:
// mojo/public/tools/bindings/mojom_bindings_generator.py
// For:
// {{module.path}}
//
package {{package}}
import (
{% for i in imports %}
{{i}}
{% endfor %}
)
{% import "enum.tmpl" as enum_macros %}
{% import "interface.tmpl" as interface_macros %}
{% import "struct.tmpl" as struct_macros %}
{% import "union.tmpl" as union_macros %}
{#- Enum definitions #}
{% for enum in enums %}
{{enum_macros.define(enum)}}
{%- endfor %}
{#- Interface definitions #}
{% for interface in interfaces %}
{{interface_macros.define(interface)}}
{%- endfor %}
{#- Struct definitions #}
{% for struct in structs %}
{{struct_macros.define(struct)}}
{%- endfor %}
{#- Union definitions #}
{% for union in unions %}
{{union_macros.define(union)}}
{%- endfor %}

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