提交 add369a2 编写于 作者: A Adam Barth

Update to mojo eb9330c8d7eccbd8318f0e4f622282926f144870

上级 3d5231bb
......@@ -3300,7 +3300,7 @@ _FUNCTION_INFO = {
'type': 'Custom',
'impl_func': False,
'unit_test': False,
'extension': True,
'extension': 'CHROMIUM_resize',
'chromium': True,
},
'GetRequestableExtensionsCHROMIUM': {
......@@ -10646,6 +10646,9 @@ def main(argv):
gen.WriteMojoGLCallVisitorForExtension(
mojo_gles2_prefix + "_chromium_miscellaneous_autogen.h",
"CHROMIUM_miscellaneous")
gen.WriteMojoGLCallVisitorForExtension(
mojo_gles2_prefix + "_chromium_resize_autogen.h",
"CHROMIUM_resize")
gen.WriteMojoGLCallVisitorForExtension(
mojo_gles2_prefix + "_occlusion_query_ext_autogen.h",
"occlusion_query_EXT")
......
......@@ -17,6 +17,7 @@ source_set("dart_controller_no_snapshot") {
"dart_controller.cc",
"dart_controller.h",
"io/internet_address.h",
"mojo_dart_state.h",
"mojo_io_natives.cc",
"mojo_io_natives.h",
"mojo_natives.cc",
......@@ -45,6 +46,8 @@ source_set("dart_controller_no_snapshot") {
"//mojo/common",
"//mojo/public/c/system",
"//mojo/public/cpp/system",
"//mojo/services/network/public/interfaces",
"//tonic",
]
defines = []
......@@ -61,6 +64,7 @@ dart_embedder_resources("generate_dart_embedder_patch_resources_cc") {
"//mojo/dart/embedder/io/internet_address_patch.dart",
"//mojo/dart/embedder/io/mojo_patch.dart",
"//mojo/dart/embedder/io/platform_patch.dart",
"//mojo/dart/embedder/io/process_patch.dart",
"//mojo/dart/embedder/io/socket_patch.dart",
"//mojo/dart/embedder/io/server_socket_patch.dart",
]
......@@ -120,6 +124,7 @@ action_foreach("dart_embedder_package_sdk") {
"//mojo/public/dart/lib/src/stub.dart",
"//mojo/public/dart/lib/src/types.dart",
"//mojo/public/dart/lib/src/union.dart",
"//mojo/public/dart/lib/src/utils.dart",
"//mojo/public/dart/sdk_ext/internal.dart",
"//mojo/public/dart/sdk_ext/src/handle_watcher.dart",
"//mojo/public/dart/sdk_ext/src/natives.dart",
......
......@@ -42,12 +42,13 @@ const char* Builtin::mojo_core_patch_resource_names_[] = {
};
const char* Builtin::mojo_io_patch_resource_names_[] = {
"/io/internet_address_patch.dart",
"/io/mojo_patch.dart",
"/io/platform_patch.dart",
"/io/socket_patch.dart",
"/io/server_socket_patch.dart",
NULL,
"/io/internet_address_patch.dart",
"/io/mojo_patch.dart",
"/io/platform_patch.dart",
"/io/process_patch.dart",
"/io/socket_patch.dart",
"/io/server_socket_patch.dart",
NULL,
};
Builtin::builtin_lib_props Builtin::builtin_libraries_[] = {
......
......@@ -16,7 +16,7 @@
#include "mojo/common/message_pump_mojo.h"
#include "mojo/dart/embedder/builtin.h"
#include "mojo/dart/embedder/dart_controller.h"
#include "mojo/dart/embedder/dart_state.h"
#include "mojo/dart/embedder/mojo_dart_state.h"
#include "mojo/dart/embedder/vmservice.h"
#include "mojo/public/c/system/core.h"
#include "tonic/dart_converter.h"
......
......@@ -9,7 +9,7 @@
#include "base/synchronization/lock.h"
#include "dart/runtime/include/dart_api.h"
#include "mojo/dart/embedder/dart_state.h"
#include "mojo/dart/embedder/mojo_dart_state.h"
#include "mojo/public/c/system/types.h"
namespace tonic {
......
// 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.
patch class _ProcessUtils {
/* patch */ static int _pid(Process p) {
if (p != null) {
throw new UnimplementedError('Process objects not currently supported.');
}
return _getPid();
}
}
int _getPid() native "Process_Pid";
\ No newline at end of file
......@@ -10,8 +10,8 @@
#include "dart/runtime/include/dart_api.h"
#include "mojo/dart/embedder/builtin.h"
#include "mojo/dart/embedder/common.h"
#include "mojo/dart/embedder/dart_state.h"
#include "mojo/dart/embedder/io/internet_address.h"
#include "mojo/dart/embedder/mojo_dart_state.h"
namespace mojo {
......@@ -29,6 +29,7 @@ namespace dart {
V(Platform_ExecutableArguments, 0) \
V(Platform_PackageRoot, 0) \
V(Platform_GetVersion, 0) \
V(Process_Pid, 0) \
MOJO_IO_NATIVE_LIST(DECLARE_FUNCTION);
......@@ -171,5 +172,13 @@ void Platform_GetVersion(Dart_NativeArguments arguments) {
Dart_NewStringFromCString(Dart_VersionString()));
}
void Process_Pid(Dart_NativeArguments arguments) {
// TODO(rudominer) After sandboxing is implemented getpid() will not return
// the real pid. Most likely it will return the value 1. We need to decide
// what behavior we want Dart's pid getter to have when sandboxed.
pid_t pid = getpid();
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(pid));
}
} // namespace dart
} // namespace mojo
......@@ -12,7 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "dart/runtime/include/dart_api.h"
#include "mojo/dart/embedder/builtin.h"
#include "mojo/dart/embedder/dart_state.h"
#include "mojo/dart/embedder/mojo_dart_state.h"
#include "mojo/public/c/system/core.h"
#include "mojo/public/cpp/system/core.h"
......@@ -34,6 +34,7 @@ namespace dart {
V(MojoMessagePipe_Create, 1) \
V(MojoMessagePipe_Write, 5) \
V(MojoMessagePipe_Read, 5) \
V(Mojo_GetTimeTicksNow, 0) \
V(MojoHandle_Close, 1) \
V(MojoHandle_Wait, 3) \
V(MojoHandle_Register, 2) \
......@@ -163,6 +164,11 @@ void MojoHandle_Register(Dart_NativeArguments arguments) {
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(MOJO_RESULT_OK));
}
void Mojo_GetTimeTicksNow(Dart_NativeArguments arguments) {
MojoTimeTicks ticks = MojoGetTimeTicksNow();
Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(ticks));
}
void MojoHandle_Close(Dart_NativeArguments arguments) {
int64_t raw_handle;
CHECK_INTEGER_ARGUMENT(arguments, 0, &raw_handle, InvalidArgument);
......
......@@ -29,6 +29,7 @@ part 'src/utils.dart';
bool verbose;
bool dryRun;
Map<String, String> duplicateDetection = new Map<String, String>();
/// Searches for .mojom.dart files under [mojomDirectory] and copies them to
/// the 'mojom' packages.
......@@ -42,6 +43,12 @@ copyAction(PackageIterData data, Directory mojomDirectory) async {
final dest = path.join(data.mojomPackage.path, relative);
final destDirectory = new Directory(path.dirname(dest));
if (duplicateDetection.containsKey(dest)) {
String original = duplicateDetection[dest];
throw new GenerationError('Conflict: Both ${original} and ${mojom.path} supply ${dest}');
}
duplicateDetection[dest] = mojom.path;
if (verbose || dryRun) {
print('Copying $mojom to $dest');
}
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'dart:typed_data';
import 'package:_testing/expect.dart';
......@@ -19,9 +20,8 @@ invalidHandleTest() {
invalidHandle.wait(MojoHandleSignals.kReadWrite, 1000000);
Expect.isTrue(mwr.result.isInvalidArgument);
MojoWaitManyResult mwmr = MojoHandle.waitMany([invalidHandle.h], [
MojoHandleSignals.kReadWrite
], MojoHandle.DEADLINE_INDEFINITE);
MojoWaitManyResult mwmr = MojoHandle.waitMany([invalidHandle.h],
[MojoHandleSignals.kReadWrite], MojoHandle.DEADLINE_INDEFINITE);
Expect.isTrue(mwmr.result.isInvalidArgument);
// Message pipe.
......@@ -106,9 +106,8 @@ basicMessagePipeTest() {
Expect.isTrue(result.isOk);
// end0 should now be readable.
MojoWaitManyResult mwmr = MojoHandle.waitMany([end0.handle.h], [
MojoHandleSignals.kReadable
], MojoHandle.DEADLINE_INDEFINITE);
MojoWaitManyResult mwmr = MojoHandle.waitMany([end0.handle.h],
[MojoHandleSignals.kReadable], MojoHandle.DEADLINE_INDEFINITE);
Expect.isTrue(mwmr.result.isOk);
// Read from end0.
......@@ -178,9 +177,8 @@ basicDataPipeTest() {
Expect.equals(written, helloData.lengthInBytes);
// Now that we have written, the consumer should be readable.
MojoWaitManyResult mwmr = MojoHandle.waitMany([consumer.handle.h], [
MojoHandleSignals.kReadable
], MojoHandle.DEADLINE_INDEFINITE);
MojoWaitManyResult mwmr = MojoHandle.waitMany([consumer.handle.h],
[MojoHandleSignals.kReadable], MojoHandle.DEADLINE_INDEFINITE);
Expect.isTrue(mwr.result.isOk);
// Do a two-phase write to the producer.
......@@ -293,9 +291,28 @@ basicSharedBufferTest() {
duplicate = null;
}
utilsTest() {
int ticksa = getTimeTicksNow();
Expect.isTrue(1000 < ticksa);
// Wait for the clock to advance.
MojoWaitResult mwr = (new MojoMessagePipe()).endpoints[0].handle.wait(
MojoHandleSignals.kReadable, 1);
Expect.isTrue(mwr.result.isDeadlineExceeded);
int ticksb = getTimeTicksNow();
Expect.isTrue(ticksa < ticksb);
}
// TODO(rudominer) This probably belongs in a different file.
processTest() {
Expect.isTrue(pid > 0);
}
main() {
invalidHandleTest();
basicMessagePipeTest();
basicDataPipeTest();
basicSharedBufferTest();
utilsTest();
processTest();
}
......@@ -16,7 +16,7 @@ import tempfile
import threading
import time
from devtoolslib.http_server import StartHttpServer
from devtoolslib.http_server import start_http_server
from devtoolslib.shell import Shell
......@@ -41,13 +41,13 @@ _MOJO_SHELL_PACKAGE_NAME = 'org.chromium.mojo.shell'
_logger = logging.getLogger()
def _ExitIfNeeded(process):
def _exit_if_needed(process):
"""Exits |process| if it is still alive."""
if process.poll() is None:
process.kill()
def _FindAvailablePort(netstat_output, max_attempts=10000):
def _find_available_port(netstat_output, max_attempts=10000):
opened = [int(x.strip().split()[3].split(':')[1])
for x in netstat_output if x.startswith(' tcp')]
for _ in xrange(max_attempts):
......@@ -58,9 +58,9 @@ def _FindAvailablePort(netstat_output, max_attempts=10000):
raise Exception('Failed to identify an available port.')
def _FindAvailableHostPort():
def _find_available_host_port():
netstat_output = subprocess.check_output(['netstat'])
return _FindAvailablePort(netstat_output)
return _find_available_port(netstat_output)
class AndroidShell(Shell):
......@@ -113,7 +113,7 @@ class AndroidShell(Shell):
_WaitForFifo()
stdout_cat = subprocess.Popen(
self._AdbCommand(['shell', 'cat', fifo_path]), stdout=pipe)
atexit.register(_ExitIfNeeded, stdout_cat)
atexit.register(_exit_if_needed, stdout_cat)
stdout_cat.wait()
if on_fifo_closed:
on_fifo_closed()
......@@ -124,7 +124,7 @@ class AndroidShell(Shell):
def _FindAvailableDevicePort(self):
netstat_output = subprocess.check_output(
self._AdbCommand(['shell', 'netstat']))
return _FindAvailablePort(netstat_output)
return _find_available_port(netstat_output)
def _ForwardDevicePortToHost(self, device_port, host_port):
"""Maps the device port to the host port. If |device_port| is 0, a random
......@@ -165,7 +165,7 @@ class AndroidShell(Shell):
if host_port == 0:
# TODO(ppi): Should we have a retry loop to handle the unlikely races?
host_port = _FindAvailableHostPort()
host_port = _find_available_host_port()
subprocess.check_call(self._AdbCommand([
"forward", 'tcp:%d' % host_port, 'tcp:%d' % device_port]))
......@@ -279,7 +279,7 @@ class AndroidShell(Shell):
Args:
arguments: List of arguments for the shell. It must contain the
"--origin=" arg. shell_arguments.ConfigureLocalOrigin() can be used
"--origin=" arg. shell_arguments.configure_local_origin() can be used
to set up a local directory on the host machine as origin.
stdout: Valid argument for subprocess.Popen() or None.
"""
......@@ -344,7 +344,7 @@ class AndroidShell(Shell):
logcat = subprocess.Popen(
self._AdbCommand(['logcat', '-s', ' '.join(tags)]),
stdout=sys.stdout)
atexit.register(_ExitIfNeeded, logcat)
atexit.register(_exit_if_needed, logcat)
return logcat
def ForwardObservatoryPorts(self):
......@@ -352,7 +352,7 @@ class AndroidShell(Shell):
"""
logcat = subprocess.Popen(self._AdbCommand(['logcat']),
stdout=subprocess.PIPE)
atexit.register(_ExitIfNeeded, logcat)
atexit.register(_exit_if_needed, logcat)
def _ForwardObservatoriesAsNeeded():
while True:
......@@ -389,8 +389,8 @@ class AndroidShell(Shell):
The url that the shell can use to access the content of |local_dir_path|.
"""
assert local_dir_path
server_address = StartHttpServer(local_dir_path, host_port=port,
additional_mappings=additional_mappings)
server_address = start_http_server(local_dir_path, host_port=port,
additional_mappings=additional_mappings)
return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost(
port, server_address[1])
......
# 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.
"""High-level apptest runner that runs all tests specified in a list.
TODO(ppi): merge this into `mojo_test` once all clients are switched to use
`mojo_test` instead of calling run_apptests() directly.
"""
import sys
import logging
from .apptest_dart import run_dart_apptest
from .apptest_gtest import run_gtest_apptest
_logger = logging.getLogger()
def run_apptests(shell, common_shell_args, test_list):
"""Runs the apptests specified in |test_list| using the given |shell|.
Args:
shell: Shell that will run the tests, see shell.py.
common_shell_args: Arguments that will be passed to the shell on each run.
These will be appended to the shell-args specified for individual tests.
test_list: List of tests to be run in the format described in the
docstring of `mojo_test`.
Returns:
True iff all tests succeeded, False otherwise.
"""
succeeded = True
for test_dict in test_list:
test = test_dict["test"]
test_name = test_dict.get("name", test)
test_type = test_dict.get("type", "gtest")
test_args = test_dict.get("test-args", [])
shell_args = test_dict.get("shell-args", []) + common_shell_args
_logger.info("Will start: %s" % test_name)
print "Running %s...." % test_name,
sys.stdout.flush()
if test_type == "dart":
apptest_result = run_dart_apptest(shell, shell_args, test, test_args)
elif test_type == "gtest":
apptest_result = run_gtest_apptest(shell, shell_args, test, test_args,
False)
elif test_type == "gtest_isolated":
apptest_result = run_gtest_apptest(shell, shell_args, test, test_args,
True)
else:
apptest_result = False
print "Unrecognized test type in %r" % test_dict
print "Succeeded" if apptest_result else "Failed"
_logger.info("Completed: %s" % test_name)
if not apptest_result:
succeeded = False
return succeeded
......@@ -171,7 +171,7 @@ def _GetHandlerClassForPath(mappings):
return RequestHandler
def StartHttpServer(local_dir_path, host_port=0, additional_mappings=None):
def start_http_server(local_dir_path, host_port=0, additional_mappings=None):
"""Starts an http server serving files from |local_dir_path| on |host_port|.
Args:
......
......@@ -39,8 +39,8 @@ class LinuxShell(Shell):
Returns:
The url that the shell can use to access the content of |local_dir_path|.
"""
return 'http://%s:%d/' % http_server.StartHttpServer(local_dir_path, port,
additional_mappings)
return 'http://%s:%d/' % http_server.start_http_server(local_dir_path, port,
additional_mappings)
def ForwardHostPortToShell(self, host_port):
"""Forwards a port on the host machine to the same port wherever the shell
......
......@@ -7,21 +7,24 @@ list.
"""
import os.path
import sys
import urlparse
from devtoolslib.android_shell import AndroidShell
from devtoolslib.linux_shell import LinuxShell
# When spinning up servers for local origins, we want to use predictable ports
# so that caching works between subsequent runs with the same command line.
_LOCAL_ORIGIN_PORT = 31840
_MAPPINGS_BASE_PORT = 31841
_SKY_SERVER_PORT = 9998
# Port on which the mojo:debugger http server will be available on the host
# machine.
_MOJO_DEBUGGER_PORT = 7777
_SKY_SERVER_PORT = 9998
def _is_web_url(dest):
return True if urlparse.urlparse(dest).scheme else False
def _HostLocalUrlDestination(shell, dest_file, port):
def _host_local_url_destination(shell, dest_file, port):
"""Starts a local server to host |dest_file|.
Returns:
......@@ -35,7 +38,7 @@ def _HostLocalUrlDestination(shell, dest_file, port):
return server_url + os.path.relpath(dest_file, directory)
def _HostLocalOriginDestination(shell, dest_dir, port):
def _host_local_origin_destination(shell, dest_dir, port):
"""Starts a local server to host |dest_dir|.
Returns:
......@@ -44,7 +47,7 @@ def _HostLocalOriginDestination(shell, dest_dir, port):
return shell.ServeLocalDirectory(dest_dir, port)
def _Rewrite(mapping, host_destination_functon, shell, port):
def _rewrite(mapping, host_destination_functon, shell, port):
"""Takes a mapping given as <src>=<dest> and rewrites the <dest> part to be
hosted locally using the given function if <dest> is not a web url.
"""
......@@ -52,7 +55,7 @@ def _Rewrite(mapping, host_destination_functon, shell, port):
if len(parts) != 2:
raise ValueError('each mapping value should be in format '
'"<url>=<url-or-local-path>"')
if urlparse.urlparse(parts[1])[0]:
if _is_web_url(parts[1]):
# The destination is a web url, do nothing.
return mapping
......@@ -61,8 +64,7 @@ def _Rewrite(mapping, host_destination_functon, shell, port):
return src + '=' + dest
def ApplyMappings(shell, original_arguments, map_urls, map_origins):
def _apply_appings(shell, original_arguments, map_urls, map_origins):
"""Applies mappings for specified urls and origins. For each local path
specified as destination a local server will be spawned and the mapping will
be rewritten accordingly.
......@@ -83,14 +85,14 @@ def ApplyMappings(shell, original_arguments, map_urls, map_origins):
if map_urls:
# Sort the mappings to preserve caching regardless of argument order.
for map_url in sorted(map_urls):
mapping = _Rewrite(map_url, _HostLocalUrlDestination, shell, next_port)
mapping = _rewrite(map_url, _host_local_url_destination, shell, next_port)
next_port += 1
# All url mappings need to be coalesced into one shell argument.
args = AppendToArgument(args, '--url-mappings=', mapping)
args = append_to_argument(args, '--url-mappings=', mapping)
if map_origins:
for map_origin in sorted(map_origins):
mapping = _Rewrite(map_origin, _HostLocalOriginDestination, shell,
mapping = _rewrite(map_origin, _host_local_origin_destination, shell,
next_port)
next_port += 1
# Origin mappings are specified as separate, repeated shell arguments.
......@@ -98,19 +100,7 @@ def ApplyMappings(shell, original_arguments, map_urls, map_origins):
return args
def ConfigureDebugger(shell):
"""Configures mojo:debugger to run and sets up port forwarding for its http
server if the shell is running on a device.
Returns:
Arguments that need to be appended to the shell argument list in order to
run with the debugger.
"""
shell.ForwardHostPortToShell(_MOJO_DEBUGGER_PORT)
return ['mojo:debugger %d' % _MOJO_DEBUGGER_PORT]
def ConfigureSky(shell, root_path, sky_packages_path, sky_target):
def _configure_sky(shell, root_path, sky_packages_path, sky_target):
"""Configures additional mappings and a server needed to run the given Sky
app.
......@@ -140,10 +130,10 @@ def ConfigureSky(shell, root_path, sky_packages_path, sky_target):
# application/dart content-type as Sky apps.
# TODO(ppi): drop this part once we can rely on the Sky files declaring
# correct shebang.
args = AppendToArgument(args, '--content-handlers=',
'text/sky,mojo:sky_viewer')
args = AppendToArgument(args, '--content-handlers=',
'application/dart,mojo:sky_viewer')
args = append_to_argument(args, '--content-handlers=',
'text/sky,mojo:sky_viewer')
args = append_to_argument(args, '--content-handlers=',
'application/dart,mojo:sky_viewer')
# Configure the window manager to embed the sky_viewer.
sky_url = server_url + sky_target
......@@ -151,7 +141,7 @@ def ConfigureSky(shell, root_path, sky_packages_path, sky_target):
return args
def ConfigureLocalOrigin(shell, local_dir, fixed_port=True):
def configure_local_origin(shell, local_dir, fixed_port=True):
"""Sets up a local http server to serve files in |local_dir| along with
device port forwarding if needed.
......@@ -164,7 +154,7 @@ def ConfigureLocalOrigin(shell, local_dir, fixed_port=True):
return ["--origin=" + origin_url]
def AppendToArgument(arguments, key, value, delimiter=","):
def append_to_argument(arguments, key, value, delimiter=","):
"""Looks for an argument of the form "key=val1,val2" within |arguments| and
appends |value| to it.
......@@ -192,3 +182,95 @@ def AppendToArgument(arguments, key, value, delimiter=","):
arguments.append(key + value)
return arguments
def add_shell_arguments(parser):
"""Adds argparse arguments allowing to configure shell abstraction using
configure_shell() below.
"""
# Arguments indicating paths to binaries and tools.
parser.add_argument('--adb-path', help='Path of the adb binary.')
parser.add_argument('--shell-path', help='Path of the Mojo shell binary.')
# Arguments configuring the shell run.
parser.add_argument('--android', help='Run on Android',
action='store_true')
parser.add_argument('--origin', help='Origin for mojo: URLs. This can be a '
'web url or a local directory path.')
parser.add_argument('--map-url', action='append',
help='Define a mapping for a url in the format '
'<url>=<url-or-local-file-path>')
parser.add_argument('--map-origin', action='append',
help='Define a mapping for a url origin in the format '
'<origin>=<url-or-local-file-path>')
# Android-only arguments.
parser.add_argument('--target-device',
help='(android-only) Device to run on.')
parser.add_argument('--logcat-tags',
help='(android-only) Comma-separated list of additional '
'logcat tags to display on the console.')
# Desktop-only arguments.
parser.add_argument('--use-osmesa', action='store_true',
help='(linux-only) Configure the native viewport service '
'for off-screen rendering.')
# Other configuration.
parser.add_argument('-v', '--verbose', action="store_true",
help="Increase output verbosity")
class ShellConfigurationException(Exception):
"""Represents an error preventing creating a functional shell abstraction."""
pass
def configure_shell(config_args, shell_args):
"""
Produces a shell abstraction configured using the parsed arguments defined in
add_shell_arguments().
Args:
config_args: Parsed arguments added using add_shell_arguments().
shell_args: Additional raw shell arguments to be passed to the shell. We
need to take these into account as some parameters need to appear only
once on the argument list (e.g. url-mappings) so we need to coalesce any
overrides and the existing value into just one argument.
Returns:
A tuple of (shell, shell_args).
Throws:
ShellConfigurationException if shell abstraction could not be configured.
"""
if config_args.android:
verbose_pipe = sys.stdout if config_args.verbose else None
shell = AndroidShell(config_args.adb_path, config_args.target_device,
logcat_tags=config_args.logcat_tags,
verbose_pipe=verbose_pipe)
device_status, error = shell.CheckDevice()
if not device_status:
raise ShellConfigurationException('Device check failed: ' + error)
if config_args.shell_path:
shell.InstallApk(config_args.shell_path)
shell_args = _apply_appings(shell, shell_args, config_args.map_url,
config_args.map_origin)
else:
if not config_args.shell_path:
raise ShellConfigurationException('Can not run without a shell binary. '
'Please pass --shell-path.')
shell = LinuxShell(config_args.shell_path)
if config_args.use_osmesa:
shell_args.append('--args-for=mojo:native_viewport_service --use-osmesa')
if config_args.origin:
if _is_web_url(config_args.origin):
shell_args.append('--origin=' + config_args.origin)
else:
shell_args.extend(configure_local_origin(shell, config_args.origin,
fixed_port=True))
return shell, shell_args
......@@ -11,7 +11,7 @@ try:
imp.find_module("devtoolslib")
except ImportError:
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from devtoolslib.shell_arguments import AppendToArgument
from devtoolslib import shell_arguments
class AppendToArgumentTest(unittest.TestCase):
......@@ -22,21 +22,24 @@ class AppendToArgumentTest(unittest.TestCase):
key = '--something='
value = 'val'
expected_result = ['--something=val']
self.assertEquals(expected_result, AppendToArgument(arguments, key, value))
self.assertEquals(expected_result, shell_arguments.append_to_argument(
arguments, key, value))
def testAppendToNonEmpty(self):
arguments = ['--other']
key = '--something='
value = 'val'
expected_result = ['--other', '--something=val']
self.assertEquals(expected_result, AppendToArgument(arguments, key, value))
self.assertEquals(expected_result, shell_arguments.append_to_argument(
arguments, key, value))
def testAppendToExisting(self):
arguments = ['--something=old_val']
key = '--something='
value = 'val'
expected_result = ['--something=old_val,val']
self.assertEquals(expected_result, AppendToArgument(arguments, key, value))
self.assertEquals(expected_result, shell_arguments.append_to_argument(
arguments, key, value))
if __name__ == "__main__":
......
......@@ -7,12 +7,10 @@ import argparse
import logging
import sys
from devtoolslib.android_shell import AndroidShell
from devtoolslib.linux_shell import LinuxShell
from devtoolslib import paths
from devtoolslib import shell_arguments
USAGE = ("mojo_run "
_USAGE = ("mojo_run "
"[--args-for=<mojo-app>] "
"[--content-handlers=<handlers>] "
"[--enable-external-applications] "
......@@ -28,149 +26,114 @@ The value of <handlers> is a comma separated list like:
text/html,mojo:html_viewer,application/javascript,mojo:js_content_handler
""")
_DESCRIPTION = """Runner for Mojo applications.
Any arguments not recognized by the script will be passed on as shell arguments.
"""
# Port on which the mojo:debugger http server will be available on the host
# machine.
_MOJO_DEBUGGER_PORT = 7777
_DEFAULT_WINDOW_MANAGER = "mojo:kiosk_wm"
def _configure_debugger(shell):
"""Configures mojo:debugger to run and sets up port forwarding for its http
server if the shell is running on a device.
Returns:
Arguments that need to be appended to the shell argument list in order to
run with the debugger.
"""
shell.ForwardHostPortToShell(_MOJO_DEBUGGER_PORT)
return ['mojo:debugger %d' % _MOJO_DEBUGGER_PORT]
def main():
logging.basicConfig()
parser = argparse.ArgumentParser(usage=USAGE)
parser = argparse.ArgumentParser(usage=_USAGE, description=_DESCRIPTION)
# Arguments indicating the configuration we are targeting.
parser.add_argument('--android', help='Run on Android',
action='store_true')
debug_group = parser.add_mutually_exclusive_group()
# Arguments allowing to indicate the configuration we are targeting when
# running within a Chromium-like checkout. These will go away once we have
# devtools config files, see https://github.com/domokit/devtools/issues/28.
chromium_config_group = parser.add_argument_group('Chromium configuration',
'These arguments allow to infer paths to tools and build results '
'when running withing a Chromium-like checkout')
debug_group = chromium_config_group.add_mutually_exclusive_group()
debug_group.add_argument('--debug', help='Debug build (default)',
default=True, action='store_true')
debug_group.add_argument('--release', help='Release build', default=False,
dest='debug', action='store_false')
parser.add_argument('--target-cpu', help='CPU architecture to run for.',
choices=['x64', 'x86', 'arm'])
# Arguments indicating paths to binaries and tools.
parser.add_argument('--adb-path', help='Path of the adb binary.')
parser.add_argument('--shell-path', help='Path of the Mojo shell binary.')
parser.add_argument('--origin-path', help='Path of a directory to be set as '
'the origin for mojo: urls')
# Arguments configuring the shell run.
parser.add_argument('--origin', help='Origin for mojo: URLs.')
parser.add_argument('--map-url', action='append',
help='Define a mapping for a url in the format '
'<url>=<url-or-local-file-path>')
parser.add_argument('--map-origin', action='append',
help='Define a mapping for a url origin in the format '
'<origin>=<url-or-local-file-path>')
chromium_config_group.add_argument('--target-cpu',
help='CPU architecture to run for.',
choices=['x64', 'x86', 'arm'])
shell_arguments.add_shell_arguments(parser)
parser.add_argument('--no-debugger', action="store_true",
help='Do not spawn mojo:debugger.')
parser.add_argument('--window-manager', default=_DEFAULT_WINDOW_MANAGER,
help='Window manager app to be mapped as '
'mojo:window_manager. By default it is ' +
_DEFAULT_WINDOW_MANAGER)
parser.add_argument('--no-debugger', action="store_true",
help='Do not spawn mojo:debugger.')
parser.add_argument('--sky',
help='Loads the given Sky file.')
parser.add_argument('-v', '--verbose', action="store_true",
help="Increase output verbosity")
# Android-only arguments.
parser.add_argument('--target-device',
help='(android-only) Device to run on.')
parser.add_argument('--logcat-tags',
help='(android-only) Comma-separated list of additional '
'logcat tags to display on the console.')
# Desktop-only arguments.
parser.add_argument('--use-osmesa', action='store_true',
help='(linux-only) Configure the native viewport service '
'for off-screen rendering.')
launcher_args, args = parser.parse_known_args()
# |mojo_paths| is a hack that allows to automagically get the correct
# configuration when running within the Mojo repository. This will go away
# once we have devtools config files, see
# https://github.com/domokit/devtools/issues/28.
mojo_paths, _ = paths.infer_mojo_paths(launcher_args.android,
launcher_args.debug,
launcher_args.target_cpu)
script_args, shell_args = parser.parse_known_args()
# Infer paths based on the config if running within a Chromium-like checkout.
mojo_paths, _ = paths.infer_mojo_paths(script_args.android,
script_args.debug,
script_args.target_cpu)
if mojo_paths:
if launcher_args.android:
adb_path = mojo_paths['adb']
shell_binary_path = mojo_paths['shell']
local_origin_path = mojo_paths['build']
if launcher_args.verbose:
if script_args.android and not script_args.adb_path:
script_args.adb_path = mojo_paths['adb']
if script_args.android and not script_args.origin:
script_args.origin = mojo_paths['build']
if not script_args.shell_path:
script_args.shell_path = mojo_paths['shell']
if script_args.verbose:
print 'Running within a Chromium-style checkout.'
else:
if launcher_args.android:
adb_path = 'adb'
shell_binary_path = None
local_origin_path = '.'
if launcher_args.verbose:
print 'Running outside a Chromium-style checkout:'
else:
print 'Running outside a Mojo checkout is not supported on Linux yet.'
return 1
if launcher_args.adb_path:
adb_path = launcher_args.adb_path
if launcher_args.shell_path:
shell_binary_path = launcher_args.shell_path
if launcher_args.origin_path:
local_origin_path = launcher_args.origin_path
if launcher_args.verbose:
if shell_binary_path:
print 'Using the locally built shell at ' + shell_binary_path
if local_origin_path:
print 'Using the local origin of ' + local_origin_path
if launcher_args.android:
verbose_pipe = sys.stdout if launcher_args.verbose else None
shell = AndroidShell(adb_path, launcher_args.target_device,
logcat_tags=launcher_args.logcat_tags,
verbose_pipe=verbose_pipe)
device_status, error = shell.CheckDevice()
if not device_status:
print 'Device check failed: ' + error
return 1
if shell_binary_path:
shell.InstallApk(shell_binary_path)
args = shell_arguments.ApplyMappings(shell, args, launcher_args.map_url,
launcher_args.map_origin)
if not launcher_args.origin:
args.extend(shell_arguments.ConfigureLocalOrigin(shell,
local_origin_path))
else:
if not shell_binary_path:
print 'Can not run without a shell binary. Please pass --shell-path.'
return 1
shell = LinuxShell(shell_binary_path)
if launcher_args.use_osmesa:
args.append('--args-for=mojo:native_viewport_service --use-osmesa')
if launcher_args.origin:
args.append('--origin=' + launcher_args.origin)
args = shell_arguments.AppendToArgument(args, '--url-mappings=',
'mojo:window_manager=%s' %
launcher_args.window_manager)
if not launcher_args.no_debugger:
args.extend(shell_arguments.ConfigureDebugger(shell))
if launcher_args.sky:
print ' - using the locally built shell at: ' + script_args.shell_path
if script_args.origin:
print ' - using the origin: ' + script_args.origin
if script_args.android:
print ' - using the adb path: ' + script_args.adb_path
elif script_args.verbose:
print 'Running outside a Chromium-style checkout.'
try:
shell, shell_args = shell_arguments.configure_shell(script_args, shell_args)
except shell_arguments.ShellConfigurationException as e:
print e
return 1
if not script_args.no_debugger:
if script_args.verbose:
print 'Spawning mojo:debugger, use `mojo_debug` to inspect the shell.'
print 'Note that mojo:debugger will prevent the shell from terminating,'
print ' pass --no-debugger to skip spawning mojo:debugger.'
shell_args.extend(_configure_debugger(shell))
shell_args = shell_arguments.append_to_argument(shell_args, '--url-mappings=',
'mojo:window_manager=%s' %
script_args.window_manager)
if script_args.sky:
if not mojo_paths:
print 'Running with --sky is not supported outside of the Mojo checkout.'
# See https://github.com/domokit/devtools/issues/27.
return 1
args.extend(shell_arguments.ConfigureSky(shell, mojo_paths['root'],
mojo_paths['sky_packages'],
launcher_args.sky))
shell_args.extend(shell_arguments._configure_sky(shell, mojo_paths['root'],
mojo_paths['sky_packages'],
script_args.sky))
if launcher_args.verbose:
print "Shell arguments: " + str(args)
if script_args.verbose:
print "Shell arguments: " + str(shell_args)
shell.Run(args)
shell.Run(shell_args)
return 0
......
......@@ -5,8 +5,21 @@
"""Test runner for Mojo application tests.
The file describing the list of tests has to be a valid Python program that sets
a |tests| global variable, containing entries of the following form:
TODO(vtl|msw): Add a way of specifying data dependencies.
"""
import argparse
import logging
import sys
from devtoolslib import apptest_dart
from devtoolslib import apptest_gtest
from devtoolslib import shell_arguments
_DESCRIPTION = """Runner for Mojo application tests.
|test_list_file| has to be a valid Python program that sets a |tests| global
variable, containing entries of the following form:
{
# Required URL for apptest.
......@@ -16,86 +29,77 @@ a |tests| global variable, containing entries of the following form:
# Optional test type. Valid values:
# * "gtest" (default)
# * "gtest_isolated": like "gtest", but run with fixture isolation,
# i.e., each test in a fresh mojo_shell)
# * "dart".
# i.e., each test in a fresh mojo_shell
# * "dart"
"type": "gtest",
# Optional arguments for the apptest.
# Optional arguments to be passed to the apptest.
"test-args": ["--an_arg", "another_arg"],
# Optional arguments for the shell.
# Optional shell arguments.
"shell-args": ["--some-flag-for-the-shell", "--another-flag"],
}
The program may use the |target_os| global that will be any of ['android',
'linux'], indicating the system on which the tests are to be run.
|test_list_file| may reference the |target_os| global that will be any of
['android', 'linux'], indicating the system on which the tests are to be run.
TODO(vtl|msw): Add a way of specifying data dependencies.
Any arguments not recognized by the script will be passed on as shell arguments.
"""
import argparse
import sys
from devtoolslib.android_shell import AndroidShell
from devtoolslib.linux_shell import LinuxShell
from devtoolslib.apptest_runner import run_apptests
from devtoolslib import shell_arguments
_logger = logging.getLogger()
def main():
parser = argparse.ArgumentParser(description="Test runner for Mojo "
"application tests.")
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=_DESCRIPTION)
parser.add_argument("test_list_file", type=file,
help="a file listing apptests to run")
# Arguments indicating the configuration we are targeting.
parser.add_argument('--android', help='Run on Android',
action='store_true')
debug_group = parser.add_mutually_exclusive_group()
debug_group.add_argument('--debug', help='Debug build (default)',
default=True, action='store_true')
debug_group.add_argument('--release', help='Release build', default=False,
dest='debug', action='store_false')
parser.add_argument('--target-cpu', help='CPU architecture to run for.',
choices=['x64', 'x86', 'arm'])
# Arguments indicating paths to binaries and tools.
parser.add_argument('--adb-path', help='Path of the adb binary.')
parser.add_argument('--shell-path', help='Path of the Mojo shell binary.')
parser.add_argument('--origin-path', help='Path of a directory to be set as '
'the origin for mojo: urls')
args = parser.parse_args()
extra_shell_args = []
if args.android:
if not args.adb_path:
print 'Indicate path to adb in --adb-path.'
return 1
shell = AndroidShell(args.adb_path)
device_status, error = shell.CheckDevice()
if not device_status:
print 'Device check failed: ' + error
return 1
if not args.shell_path:
print 'Indicate path to the shell binary in --shell-path'
return 1
shell.InstallApk(args.shell_path)
if args.origin_path:
extra_shell_args.extend(shell_arguments.ConfigureLocalOrigin(
shell, args.origin_path, fixed_port=True))
else:
if not args.shell_path:
print 'Indicate path to the shell binary in --shell-path'
return 1
shell = LinuxShell(args.shell_path)
target_os = 'android' if args.android else 'linux'
# Common shell configuration arguments.
shell_arguments.add_shell_arguments(parser)
script_args, common_shell_args = parser.parse_known_args()
try:
shell, common_shell_args = shell_arguments.configure_shell(
script_args, common_shell_args)
except shell_arguments.ShellConfigurationException as e:
print e
return 1
target_os = "android" if script_args.android else "linux"
test_list_globals = {"target_os": target_os}
exec args.test_list_file in test_list_globals
apptests_result = run_apptests(shell, extra_shell_args,
test_list_globals["tests"])
return 0 if apptests_result else 1
exec script_args.test_list_file in test_list_globals
test_list = test_list_globals["tests"]
succeeded = True
for test_dict in test_list:
test = test_dict["test"]
test_name = test_dict.get("name", test)
test_type = test_dict.get("type", "gtest")
test_args = test_dict.get("test-args", [])
shell_args = test_dict.get("shell-args", []) + common_shell_args
_logger.info("Will start: %s" % test_name)
print "Running %s...." % test_name,
sys.stdout.flush()
if test_type == "dart":
apptest_result = apptest_dart.run_dart_apptest(shell, shell_args, test,
test_args)
elif test_type == "gtest":
apptest_result = apptest_gtest.run_gtest_apptest(shell, shell_args, test,
test_args, False)
elif test_type == "gtest_isolated":
apptest_result = apptest_gtest.run_gtest_apptest(shell, shell_args, test,
test_args, True)
else:
apptest_result = False
print "Unrecognized test type in %r" % test_dict
print "Succeeded" if apptest_result else "Failed"
_logger.info("Completed: %s" % test_name)
if not apptest_result:
succeeded = False
return 0 if succeeded else 1
if __name__ == '__main__':
sys.exit(main())
......@@ -17,6 +17,7 @@
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_handle.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
......@@ -25,6 +26,11 @@
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_ANDROID)
#include "base/android/path_utils.h"
#include "base/files/file_path.h"
#endif
namespace mojo {
namespace embedder {
namespace {
......@@ -36,6 +42,22 @@ void WaitReadable(PlatformHandle h) {
CHECK_EQ(poll(&pfds, 1, -1), 1);
}
FILE* NewTmpFile() {
#if defined(OS_ANDROID)
base::FilePath tmpdir;
if (!base::android::GetCacheDirectory(&tmpdir))
return nullptr;
std::string templ = tmpdir.Append("XXXXXXXX").value();
int fd = mkstemp(const_cast<char*>(templ.c_str()));
if (fd == -1)
return nullptr;
CHECK(unlink(templ.c_str()) == 0);
return fdopen(fd, "w+");
#else
return tmpfile();
#endif
}
class PlatformChannelPairPosixTest : public testing::Test {
public:
PlatformChannelPairPosixTest() {}
......@@ -144,7 +166,7 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) {
const char c = '0' + (i % 10);
ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector);
for (size_t j = 1; j <= i; j++) {
base::ScopedFILE fp(tmpfile());
base::ScopedFILE fp(NewTmpFile());
ASSERT_TRUE(fp);
ASSERT_EQ(j, fwrite(std::string(j, c).data(), 1, j, fp.get()));
platform_handles->push_back(
......@@ -195,7 +217,7 @@ TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) {
const std::string file_contents("hello world");
{
base::ScopedFILE fp(tmpfile());
base::ScopedFILE fp(NewTmpFile());
ASSERT_TRUE(fp);
ASSERT_EQ(file_contents.size(),
fwrite(file_contents.data(), 1, file_contents.size(), fp.get()));
......
......@@ -41,6 +41,7 @@ component("system") {
"connection_identifier.h",
"connection_manager.cc",
"connection_manager.h",
"connection_manager_messages.h",
"core.cc",
"core.h",
"data_pipe.cc",
......
......@@ -99,12 +99,14 @@ class MOJO_SYSTEM_IMPL_EXPORT ConnectionManager {
// Connects a pending connection; to be called only after both parties have
// called |AllowConnect()|. On success, |Result::SUCCESS_CONNECT_...| is
// returned and |peer_process_identifier| is set to an unique identifier for
// the peer process. In the case of |SUCCESS_CONNECT_SAME_PROCESS|,
// returned, |peer_process_identifier| is set to an unique identifier for the
// peer process, and |is_first| is set to true if this is the first party to
// call |Connect()|. In the case of |SUCCESS_CONNECT_SAME_PROCESS|,
// |*platform_handle| is set to a suitable native handle connecting the two
// parties.
virtual Result Connect(const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle) = 0;
protected:
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_EDK_SYSTEM_CONNECTION_MANAGER_MESSAGES_H_
#define MOJO_EDK_SYSTEM_CONNECTION_MANAGER_MESSAGES_H_
#include <string.h>
#include "mojo/edk/system/process_identifier.h"
#include "mojo/edk/system/system_impl_export.h"
namespace mojo {
namespace system {
struct ConnectionManagerAckSuccessConnectData {
// Set to the process identifier of the process that the receiver of this ack
// ack should connect to.
ProcessIdentifier peer_process_identifier;
// Whether the receiver of this ack is the first party in the connection. This
// is typically used to decide whether the receiver should initiate the
// message (or data) pipe (i.e., allocate endpoint IDs, etc.).
bool is_first;
};
} // namespace system
} // namespace mojo
#endif // MOJO_EDK_SYSTEM_CONNECTION_MANAGER_MESSAGES_H_
......@@ -225,16 +225,19 @@ TEST_F(ConnectionManagerTest, BasicConnectSlaves) {
EXPECT_TRUE(slave2.AllowConnect(connection_id));
ProcessIdentifier peer1 = kInvalidProcessIdentifier;
bool is_first = false;
embedder::ScopedPlatformHandle h1;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
slave1.Connect(connection_id, &peer1, &h1));
slave1.Connect(connection_id, &peer1, &is_first, &h1));
EXPECT_EQ(slave2_id, peer1);
EXPECT_TRUE(is_first);
EXPECT_TRUE(h1.is_valid());
ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
slave2.Connect(connection_id, &peer2, &h2));
slave2.Connect(connection_id, &peer2, &is_first, &h2));
EXPECT_EQ(slave1_id, peer2);
EXPECT_FALSE(is_first);
EXPECT_TRUE(h2.is_valid());
EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get()));
......@@ -320,10 +323,12 @@ TEST_F(ConnectionManagerTest, SlaveCancelConnect) {
EXPECT_TRUE(slave1.CancelConnect(connection_id));
ProcessIdentifier peer2 = kInvalidProcessIdentifier;
bool is_first = false;
embedder::ScopedPlatformHandle h2;
EXPECT_EQ(ConnectionManager::Result::FAILURE,
slave2.Connect(connection_id, &peer2, &h2));
slave2.Connect(connection_id, &peer2, &is_first, &h2));
EXPECT_EQ(kInvalidProcessIdentifier, peer2);
EXPECT_FALSE(is_first);
EXPECT_FALSE(h2.is_valid());
slave1.Shutdown();
......@@ -363,10 +368,12 @@ TEST_F(ConnectionManagerTest, ErrorRemovePending) {
EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls());
ProcessIdentifier peer2 = kInvalidProcessIdentifier;
bool is_first = false;
embedder::ScopedPlatformHandle h2;
EXPECT_EQ(ConnectionManager::Result::FAILURE,
slave2.Connect(connection_id, &peer2, &h2));
slave2.Connect(connection_id, &peer2, &is_first, &h2));
EXPECT_EQ(kInvalidProcessIdentifier, peer2);
EXPECT_FALSE(is_first);
EXPECT_FALSE(h2.is_valid());
slave2.Shutdown();
......@@ -389,16 +396,19 @@ TEST_F(ConnectionManagerTest, ConnectSlaveToSelf) {
EXPECT_TRUE(slave.AllowConnect(connection_id));
ProcessIdentifier peer1 = kInvalidProcessIdentifier;
bool is_first = false;
embedder::ScopedPlatformHandle h1;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS,
slave.Connect(connection_id, &peer1, &h1));
slave.Connect(connection_id, &peer1, &is_first, &h1));
EXPECT_EQ(slave_id, peer1);
EXPECT_TRUE(is_first);
EXPECT_FALSE(h1.is_valid());
ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS,
slave.Connect(connection_id, &peer2, &h2));
slave.Connect(connection_id, &peer2, &is_first, &h2));
EXPECT_EQ(slave_id, peer2);
EXPECT_FALSE(is_first);
EXPECT_FALSE(h2.is_valid());
slave.Shutdown();
......@@ -428,15 +438,18 @@ TEST_F(ConnectionManagerTest, ConnectSlavesTwice) {
EXPECT_TRUE(slave2.AllowConnect(connection_id));
ProcessIdentifier peer1 = kInvalidProcessIdentifier;
bool is_first = false;
embedder::ScopedPlatformHandle h1;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
slave1.Connect(connection_id, &peer1, &h1));
slave1.Connect(connection_id, &peer1, &is_first, &h1));
EXPECT_EQ(slave2_id, peer1);
EXPECT_TRUE(is_first);
ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
slave2.Connect(connection_id, &peer2, &h2));
slave2.Connect(connection_id, &peer2, &is_first, &h2));
EXPECT_EQ(slave1_id, peer2);
EXPECT_FALSE(is_first);
EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get()));
......@@ -455,13 +468,14 @@ TEST_F(ConnectionManagerTest, ConnectSlavesTwice) {
// SUCCESS_CONNECT_REUSE_CONNECTION.
ProcessIdentifier second_peer2 = kInvalidProcessIdentifier;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
slave2.Connect(connection_id, &second_peer2, &h2));
slave2.Connect(connection_id, &second_peer2, &is_first, &h2));
EXPECT_EQ(peer2, second_peer2);
EXPECT_TRUE(is_first);
ProcessIdentifier second_peer1 = kInvalidProcessIdentifier;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
slave1.Connect(connection_id, &second_peer1, &h1));
slave1.Connect(connection_id, &second_peer1, &is_first, &h1));
EXPECT_EQ(peer1, second_peer1);
EXPECT_EQ(peer2, second_peer2);
EXPECT_FALSE(is_first);
EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get()));
slave2.Shutdown();
......@@ -485,16 +499,19 @@ TEST_F(ConnectionManagerTest, ConnectMasterToSlave) {
EXPECT_TRUE(slave.AllowConnect(connection_id));
ProcessIdentifier master_peer = kInvalidProcessIdentifier;
bool is_first = false;
embedder::ScopedPlatformHandle master_h;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
master.Connect(connection_id, &master_peer, &master_h));
master.Connect(connection_id, &master_peer, &is_first, &master_h));
EXPECT_EQ(slave_id, master_peer);
EXPECT_TRUE(is_first);
EXPECT_TRUE(master_h.is_valid());
ProcessIdentifier slave_peer = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle slave_h;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
slave.Connect(connection_id, &slave_peer, &slave_h));
slave.Connect(connection_id, &slave_peer, &is_first, &slave_h));
EXPECT_EQ(kMasterProcessIdentifier, slave_peer);
EXPECT_FALSE(is_first);
EXPECT_TRUE(slave_h.is_valid());
EXPECT_TRUE(ArePlatformHandlesConnected(master_h.get(), slave_h.get()));
......@@ -513,16 +530,19 @@ TEST_F(ConnectionManagerTest, ConnectMasterToSelf) {
EXPECT_TRUE(master.AllowConnect(connection_id));
ProcessIdentifier peer1 = kInvalidProcessIdentifier;
bool is_first = false;
embedder::ScopedPlatformHandle h1;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS,
master.Connect(connection_id, &peer1, &h1));
master.Connect(connection_id, &peer1, &is_first, &h1));
EXPECT_EQ(kMasterProcessIdentifier, peer1);
EXPECT_TRUE(is_first);
EXPECT_FALSE(h1.is_valid());
ProcessIdentifier peer2 = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_SAME_PROCESS,
master.Connect(connection_id, &peer2, &h2));
master.Connect(connection_id, &peer2, &is_first, &h2));
EXPECT_EQ(kMasterProcessIdentifier, peer2);
EXPECT_FALSE(is_first);
EXPECT_FALSE(h2.is_valid());
EXPECT_EQ(peer1, peer2);
......@@ -547,10 +567,12 @@ TEST_F(ConnectionManagerTest, MasterCancelConnect) {
EXPECT_TRUE(master.CancelConnect(connection_id));
ProcessIdentifier peer = kInvalidProcessIdentifier;
bool is_first = false;
embedder::ScopedPlatformHandle h;
EXPECT_EQ(ConnectionManager::Result::FAILURE,
slave.Connect(connection_id, &peer, &h));
slave.Connect(connection_id, &peer, &is_first, &h));
EXPECT_EQ(kInvalidProcessIdentifier, peer);
EXPECT_FALSE(is_first);
EXPECT_FALSE(h.is_valid());
slave.Shutdown();
......@@ -586,9 +608,11 @@ TEST_F(ConnectionManagerTest, AddSlaveAndBootstrap) {
embedder::ScopedPlatformHandle h1;
ProcessIdentifier master_peer = kInvalidProcessIdentifier;
bool is_first = false;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
master.Connect(connection_id, &master_peer, &h1));
master.Connect(connection_id, &master_peer, &is_first, &h1));
EXPECT_EQ(slave_id, master_peer);
EXPECT_TRUE(is_first);
EXPECT_TRUE(h1.is_valid());
// We can delay creating/initializing |slave| for quite a while.
......@@ -600,8 +624,9 @@ TEST_F(ConnectionManagerTest, AddSlaveAndBootstrap) {
ProcessIdentifier slave_peer = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle h2;
EXPECT_EQ(ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION,
slave.Connect(connection_id, &slave_peer, &h2));
slave.Connect(connection_id, &slave_peer, &is_first, &h2));
EXPECT_EQ(kMasterProcessIdentifier, slave_peer);
EXPECT_FALSE(is_first);
EXPECT_TRUE(ArePlatformHandlesConnected(h1.get(), h2.get()));
......
......@@ -140,8 +140,9 @@ embedder::ScopedPlatformHandle IPCSupport::ConnectToSlaveInternal(
connection_id);
system::ProcessIdentifier peer_id = system::kInvalidProcessIdentifier;
bool is_first;
embedder::ScopedPlatformHandle platform_connection_handle;
CHECK_EQ(connection_manager()->Connect(connection_id, &peer_id,
CHECK_EQ(connection_manager()->Connect(connection_id, &peer_id, &is_first,
&platform_connection_handle),
ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION);
DCHECK_EQ(peer_id, *slave_process_identifier);
......@@ -153,9 +154,10 @@ embedder::ScopedPlatformHandle IPCSupport::ConnectToMasterInternal(
const ConnectionIdentifier& connection_id) {
DCHECK_EQ(process_type_, embedder::ProcessType::SLAVE);
system::ProcessIdentifier peer_id;
system::ProcessIdentifier peer_id = system::kInvalidProcessIdentifier;
bool is_first;
embedder::ScopedPlatformHandle platform_connection_handle;
CHECK_EQ(connection_manager()->Connect(connection_id, &peer_id,
CHECK_EQ(connection_manager()->Connect(connection_id, &peer_id, &is_first,
&platform_connection_handle),
ConnectionManager::Result::SUCCESS_CONNECT_NEW_CONNECTION);
DCHECK_EQ(peer_id, system::kMasterProcessIdentifier);
......
......@@ -13,6 +13,7 @@
#include "mojo/edk/embedder/master_process_delegate.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/system/connection_manager_messages.h"
#include "mojo/edk/system/message_in_transit.h"
#include "mojo/edk/system/raw_channel.h"
#include "mojo/edk/system/transport_data.h"
......@@ -141,7 +142,9 @@ void MasterConnectionManager::Helper::OnReadMessage(
const ConnectionIdentifier* connection_id =
reinterpret_cast<const ConnectionIdentifier*>(message_view.bytes());
Result result = Result::FAILURE;
ProcessIdentifier peer_process_identifier = kInvalidProcessIdentifier;
// Note: It's important to fully zero-initialize |data|, including padding,
// since it'll be sent to another process.
ConnectionManagerAckSuccessConnectData data = {};
embedder::ScopedPlatformHandle platform_handle;
uint32_t num_bytes = 0;
const void* bytes = nullptr;
......@@ -158,7 +161,8 @@ void MasterConnectionManager::Helper::OnReadMessage(
break;
case MessageInTransit::Subtype::CONNECTION_MANAGER_CONNECT: {
result = owner_->ConnectImpl(process_identifier_, *connection_id,
&peer_process_identifier, &platform_handle);
&data.peer_process_identifier,
&data.is_first, &platform_handle);
DCHECK_NE(result, Result::SUCCESS);
// TODO(vtl): FIXME -- currently, nothing should generate
// SUCCESS_CONNECT_REUSE_CONNECTION.
......@@ -167,8 +171,8 @@ void MasterConnectionManager::Helper::OnReadMessage(
// (and also a platform handle in the case of "new connection" -- handled
// further below).
if (result != Result::FAILURE) {
num_bytes = static_cast<uint32_t>(sizeof(peer_process_identifier));
bytes = &peer_process_identifier;
num_bytes = static_cast<uint32_t>(sizeof(data));
bytes = &data;
}
break;
}
......@@ -365,9 +369,10 @@ bool MasterConnectionManager::CancelConnect(
ConnectionManager::Result MasterConnectionManager::Connect(
const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle) {
return ConnectImpl(kMasterProcessIdentifier, connection_id,
peer_process_identifier, platform_handle);
peer_process_identifier, is_first, platform_handle);
}
bool MasterConnectionManager::AllowConnectImpl(
......@@ -445,9 +450,11 @@ ConnectionManager::Result MasterConnectionManager::ConnectImpl(
ProcessIdentifier process_identifier,
const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle) {
DCHECK_NE(process_identifier, kInvalidProcessIdentifier);
DCHECK(peer_process_identifier);
DCHECK(is_first);
DCHECK(platform_handle);
DCHECK(!platform_handle->is_valid()); // Not technically wrong, but unlikely.
......@@ -479,6 +486,8 @@ ConnectionManager::Result MasterConnectionManager::ConnectImpl(
return Result::FAILURE;
}
*is_first = true;
// TODO(vtl): FIXME -- add stuff for SUCCESS_CONNECT_REUSE_CONNECTION here.
Result result = Result::FAILURE;
if (info->first == info->second) {
......@@ -529,6 +538,7 @@ ConnectionManager::Result MasterConnectionManager::ConnectImpl(
}
*peer_process_identifier = peer;
*is_first = false;
// TODO(vtl): FIXME -- add stuff for SUCCESS_CONNECT_REUSE_CONNECTION here.
Result result = Result::FAILURE;
......
......@@ -81,6 +81,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager final
bool CancelConnect(const ConnectionIdentifier& connection_id) override;
Result Connect(const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle) override;
private:
......@@ -95,6 +96,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager final
Result ConnectImpl(ProcessIdentifier process_identifier,
const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle);
// These should only be called on |private_thread_|:
......
......@@ -83,10 +83,8 @@ class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
// Subtypes for type |Type::CONNECTION_MANAGER_ACK|, corresponding to
// |ConnectionManager::Result| values (failure and non-"connect" acks never
// have any message contents; success acks for "connect" always have a
// |ProcessIdentifier| as data and also a platform handle attached for "new
// connection"):
// TODO(vtl): FIXME -- probably, in the "connect, reuse connection" case,
// we'll have to send more information.
// |ConnectionManagerAckSuccessConnectData| as data and also a platform
// handle attached for "new connection"):
CONNECTION_MANAGER_ACK_FAILURE = 0,
CONNECTION_MANAGER_ACK_SUCCESS = 1,
CONNECTION_MANAGER_ACK_SUCCESS_CONNECT_SAME_PROCESS = 2,
......
......@@ -9,6 +9,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "mojo/edk/system/connection_manager_messages.h"
#include "mojo/edk/system/message_in_transit.h"
namespace mojo {
......@@ -24,6 +25,7 @@ SlaveConnectionManager::SlaveConnectionManager(
awaiting_ack_type_(NOT_AWAITING_ACK),
ack_result_(nullptr),
ack_peer_process_identifier_(nullptr),
ack_is_first_(nullptr),
ack_platform_handle_(nullptr),
event_(false, false) { // Auto-reset, not initially signalled.
}
......@@ -35,6 +37,7 @@ SlaveConnectionManager::~SlaveConnectionManager() {
DCHECK_EQ(awaiting_ack_type_, NOT_AWAITING_ACK);
DCHECK(!ack_result_);
DCHECK(!ack_peer_process_identifier_);
DCHECK(!ack_is_first_);
DCHECK(!ack_platform_handle_);
}
......@@ -107,15 +110,21 @@ bool SlaveConnectionManager::CancelConnect(
ConnectionManager::Result SlaveConnectionManager::Connect(
const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle) {
AssertNotOnPrivateThread();
DCHECK(peer_process_identifier);
DCHECK(is_first);
DCHECK(platform_handle);
DCHECK(!platform_handle->is_valid()); // Not technically wrong, but unlikely.
MutexLocker locker(&mutex_);
Result result = Result::FAILURE;
private_thread_.message_loop()->PostTask(
FROM_HERE, base::Bind(&SlaveConnectionManager::ConnectOnPrivateThread,
base::Unretained(this), connection_id, &result,
peer_process_identifier, platform_handle));
FROM_HERE,
base::Bind(&SlaveConnectionManager::ConnectOnPrivateThread,
base::Unretained(this), connection_id, &result,
peer_process_identifier, is_first, platform_handle));
event_.Wait();
return result;
}
......@@ -193,10 +202,9 @@ void SlaveConnectionManager::ConnectOnPrivateThread(
const ConnectionIdentifier& connection_id,
Result* result,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle) {
DCHECK(result);
DCHECK(platform_handle);
DCHECK(!platform_handle->is_valid()); // Not technically wrong, but unlikely.
AssertOnPrivateThread();
// This should only posted (from another thread, to |private_thread_|) with
// the lock held (until this thread triggers |event_|).
......@@ -217,6 +225,7 @@ void SlaveConnectionManager::ConnectOnPrivateThread(
awaiting_ack_type_ = AWAITING_CONNECT_ACK;
ack_result_ = result;
ack_peer_process_identifier_ = peer_process_identifier;
ack_is_first_ = is_first;
ack_platform_handle_ = platform_handle;
}
......@@ -255,12 +264,17 @@ void SlaveConnectionManager::OnReadMessage(
DCHECK_EQ(num_platform_handles, 0u);
*ack_result_ = Result::SUCCESS;
DCHECK(!ack_peer_process_identifier_);
DCHECK(!ack_is_first_);
DCHECK(!ack_platform_handle_);
} else {
// Success acks for "connect" always have a |ProcessIdentifier| as data.
CHECK_EQ(num_bytes, sizeof(ProcessIdentifier));
*ack_peer_process_identifier_ =
*reinterpret_cast<const ProcessIdentifier*>(message_view.bytes());
// Success acks for "connect" always have a
// |ConnectionManagerAckSuccessConnectData| as data.
CHECK_EQ(num_bytes, sizeof(ConnectionManagerAckSuccessConnectData));
const ConnectionManagerAckSuccessConnectData& data =
*static_cast<const ConnectionManagerAckSuccessConnectData*>(
message_view.bytes());
*ack_peer_process_identifier_ = data.peer_process_identifier;
*ack_is_first_ = data.is_first;
switch (message_view.subtype()) {
case MessageInTransit::Subtype::
......@@ -294,6 +308,7 @@ void SlaveConnectionManager::OnReadMessage(
awaiting_ack_type_ = NOT_AWAITING_ACK;
ack_result_ = nullptr;
ack_peer_process_identifier_ = nullptr;
ack_is_first_ = nullptr;
ack_platform_handle_ = nullptr;
event_.Signal();
}
......
......@@ -60,6 +60,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager final
bool CancelConnect(const ConnectionIdentifier& connection_id) override;
Result Connect(const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle) override;
private:
......@@ -73,6 +74,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager final
void ConnectOnPrivateThread(const ConnectionIdentifier& connection_id,
Result* result,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle);
// |RawChannel::Delegate| methods (only called on |private_thread_|):
......@@ -115,6 +117,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SlaveConnectionManager final
Result* ack_result_;
// Used only when waiting for the ack to "connect":
ProcessIdentifier* ack_peer_process_identifier_;
bool* ack_is_first_;
embedder::ScopedPlatformHandle* ack_platform_handle_;
// The (synchronous) |ConnectionManager| methods are implemented in the
......
......@@ -6,6 +6,12 @@ source_set("chromium") {
output_name = "mojo_environment_chromium"
sources = [
"default_async_waiter.cc",
"default_async_waiter.h",
"default_logger.cc",
"default_logger.h",
"default_task_tracker.cc",
"default_task_tracker.h",
"environment.cc",
# TODO(vtl): This is kind of ugly. (See TODO in logging.h.)
......@@ -17,38 +23,13 @@ source_set("chromium") {
"../public/cpp/environment/logging.h",
]
public_deps = [
":chromium_impl",
]
deps = [
"//mojo/public/c/environment",
"//mojo/public/cpp/bindings:callback",
"//mojo/public/cpp/environment",
"//mojo/public/cpp/system",
]
}
component("chromium_impl") {
output_name = "mojo_environment_impl"
visibility = [ "//mojo/*" ]
sources = [
"default_async_waiter_impl.cc",
"default_async_waiter_impl.h",
"default_logger_impl.cc",
"default_logger_impl.h",
"default_run_loop_impl.cc",
"default_run_loop_impl.h",
"default_task_tracker_impl.cc",
"default_task_tracker_impl.h",
]
deps = [
"//base",
"//base/third_party/dynamic_annotations",
"//mojo/common",
"//mojo/public/c/environment",
"//mojo/public/cpp/bindings:callback",
"//mojo/public/cpp/environment",
"//mojo/public/cpp/system",
]
}
......@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/environment/default_async_waiter_impl.h"
#include "mojo/environment/default_async_waiter.h"
#include "base/bind.h"
#include "mojo/common/handle_watcher.h"
#include "mojo/public/c/environment/async_waiter.h"
namespace mojo {
namespace internal {
......@@ -35,16 +36,9 @@ void CancelWait(MojoAsyncWaitID wait_id) {
delete reinterpret_cast<common::HandleWatcher*>(wait_id);
}
const MojoAsyncWaiter kDefaultAsyncWaiter = {
AsyncWait,
CancelWait
};
} // namespace
const MojoAsyncWaiter* GetDefaultAsyncWaiterImpl() {
return &kDefaultAsyncWaiter;
}
const MojoAsyncWaiter kDefaultAsyncWaiter = {AsyncWait, CancelWait};
} // namespace internal
} // namespace mojo
......@@ -2,16 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_ENVIRONMENT_DEFAULT_RUN_LOOP_IMPL_H_
#define MOJO_ENVIRONMENT_DEFAULT_RUN_LOOP_IMPL_H_
#ifndef MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
#define MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
struct MojoAsyncWaiter;
namespace mojo {
namespace internal {
void InstantiateDefaultRunLoopImpl();
void DestroyDefaultRunLoopImpl();
extern const MojoAsyncWaiter kDefaultAsyncWaiter;
} // namespace internal
} // namespace mojo
#endif // MOJO_ENVIRONMENT_DEFAULT_RUN_LOOP_IMPL_H_
#endif // MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
......@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/environment/default_logger_impl.h"
#include "mojo/environment/default_logger.h"
#include "base/logging.h"
#include "base/macros.h"
#include "mojo/public/c/environment/logger.h"
namespace mojo {
namespace internal {
......@@ -61,17 +62,11 @@ void SetMinimumLogLevel(MojoLogLevel log_level) {
logging::SetMinLogLevel(MojoToChromiumLogLevel(log_level));
}
const MojoLogger kDefaultLogger = {
LogMessage,
GetMinimumLogLevel,
SetMinimumLogLevel
};
} // namespace
const MojoLogger* GetDefaultLoggerImpl() {
return &kDefaultLogger;
}
const MojoLogger kDefaultLogger = {LogMessage,
GetMinimumLogLevel,
SetMinimumLogLevel};
} // namespace internal
} // namespace mojo
......@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_ENVIRONMENT_DEFAULT_LOGGER_IMPL_H_
#define MOJO_ENVIRONMENT_DEFAULT_LOGGER_IMPL_H_
#ifndef MOJO_ENVIRONMENT_DEFAULT_LOGGER_H_
#define MOJO_ENVIRONMENT_DEFAULT_LOGGER_H_
#include "mojo/public/c/environment/logger.h"
struct MojoLogger;
namespace mojo {
namespace internal {
const MojoLogger* GetDefaultLoggerImpl();
extern const MojoLogger kDefaultLogger;
} // namespace internal
} // namespace mojo
#endif // MOJO_ENVIRONMENT_DEFAULT_LOGGER_IMPL_H_
#endif // MOJO_ENVIRONMENT_DEFAULT_LOGGER_H_
// 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/environment/default_run_loop_impl.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
namespace mojo {
namespace internal {
void InstantiateDefaultRunLoopImpl() {
CHECK(!base::MessageLoop::current());
// Not leaked: accessible from |base::MessageLoop::current()|.
base::MessageLoop* message_loop = new base::MessageLoop();
CHECK_EQ(message_loop, base::MessageLoop::current());
}
void DestroyDefaultRunLoopImpl() {
CHECK(base::MessageLoop::current());
delete base::MessageLoop::current();
CHECK(!base::MessageLoop::current());
}
} // namespace internal
} // namespace mojo
......@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/environment/default_task_tracker_impl.h"
#include "mojo/environment/default_task_tracker.h"
#include "base/logging.h"
#include "mojo/common/task_tracker.h"
#include "mojo/public/cpp/environment/task_tracker.h"
namespace mojo {
namespace internal {
......@@ -21,7 +22,7 @@ TaskTrackingId StartTracking(const char* function_name,
return TaskTrackingId(0);
return common::TaskTracker::StartTracking(function_name, file_name,
line_number, program_counter);
line_number, program_counter);
}
void EndTracking(const TaskTrackingId id) {
......@@ -37,15 +38,11 @@ void SetEnabled(bool enabled) {
g_enabled = enabled;
}
} // namespace
const TaskTracker kDefaultTaskTracker = {&StartTracking,
&EndTracking,
&SetEnabled};
} // namespace
const TaskTracker* GetDefaultTaskTrackerImpl() {
return &kDefaultTaskTracker;
}
} // namespace internal
} // namespace mojo
......@@ -2,17 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_
#define MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_
#include "mojo/public/cpp/environment/task_tracker.h"
#ifndef MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_H_
#define MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_H_
namespace mojo {
struct TaskTracker;
namespace internal {
const TaskTracker* GetDefaultTaskTrackerImpl();
extern const TaskTracker kDefaultTaskTracker;
} // namespace internal
} // namespace mojo
#endif // MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_
#endif // MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_H_
......@@ -4,10 +4,10 @@
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/environment/default_async_waiter_impl.h"
#include "mojo/environment/default_logger_impl.h"
#include "mojo/environment/default_run_loop_impl.h"
#include "mojo/environment/default_task_tracker_impl.h"
#include "base/message_loop/message_loop.h"
#include "mojo/environment/default_async_waiter.h"
#include "mojo/environment/default_logger.h"
#include "mojo/environment/default_task_tracker.h"
namespace mojo {
......@@ -27,27 +27,32 @@ Environment::~Environment() {
// static
const MojoAsyncWaiter* Environment::GetDefaultAsyncWaiter() {
return internal::GetDefaultAsyncWaiterImpl();
return &internal::kDefaultAsyncWaiter;
}
// static
const MojoLogger* Environment::GetDefaultLogger() {
return internal::GetDefaultLoggerImpl();
return &internal::kDefaultLogger;
}
// static
const TaskTracker* Environment::GetDefaultTaskTracker() {
return internal::GetDefaultTaskTrackerImpl();
return &internal::kDefaultTaskTracker;
}
// static
void Environment::InstantiateDefaultRunLoop() {
internal::InstantiateDefaultRunLoopImpl();
CHECK(!base::MessageLoop::current());
// Not leaked: accessible from |base::MessageLoop::current()|.
base::MessageLoop* message_loop = new base::MessageLoop();
CHECK_EQ(message_loop, base::MessageLoop::current());
}
// static
void Environment::DestroyDefaultRunLoop() {
internal::DestroyDefaultRunLoopImpl();
CHECK(base::MessageLoop::current());
delete base::MessageLoop::current();
CHECK(!base::MessageLoop::current());
}
} // namespace mojo
......@@ -71,11 +71,12 @@ void MojoGLES2SignalSyncPoint(MojoGLES2Context context,
return g_gpu_interface.Get().Get()->Function ARGUMENTS; \
}
#include "mojo/public/c/gles2/gles2_call_visitor_autogen.h"
#include "mojo/public/c/gles2/gles2_call_visitor_occlusion_query_ext_autogen.h"
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_miscellaneous_autogen.h"
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_resize_autogen.h"
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_sub_image_autogen.h"
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_sync_point_autogen.h"
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_texture_mailbox_autogen.h"
#include "mojo/public/c/gles2/gles2_call_visitor_occlusion_query_ext_autogen.h"
#undef VISIT_GL_CALL
} // extern "C"
......@@ -24,6 +24,7 @@ mojo_sdk_source_set("headers") {
"chromium_image.h",
"chromium_miscellaneous.h",
"chromium_pixel_transfer_buffer_object.h",
"chromium_resize.h",
"chromium_sub_image.h",
"chromium_sync_point.h",
"chromium_texture_mailbox.h",
......@@ -33,6 +34,7 @@ mojo_sdk_source_set("headers") {
"gles2_call_visitor_chromium_image_autogen.h",
"gles2_call_visitor_chromium_miscellaneous_autogen.h",
"gles2_call_visitor_chromium_pixel_transfer_buffer_object_autogen.h",
"gles2_call_visitor_chromium_resize_autogen.h",
"gles2_call_visitor_chromium_sub_image_autogen.h",
"gles2_call_visitor_chromium_sync_point_autogen.h",
"gles2_call_visitor_chromium_texture_mailbox_autogen.h",
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_C_GLES2_CHROMIUM_RESIZE_H_
#define MOJO_PUBLIC_C_GLES2_CHROMIUM_RESIZE_H_
// Note: This header should be compilable as C.
#include <stdint.h>
#include <GLES2/gl2.h>
#include "mojo/public/c/gles2/gles2_export.h"
#include "mojo/public/c/gles2/gles2_types.h"
#include "mojo/public/c/system/types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define VISIT_GL_CALL(Function, ReturnType, PARAMETERS, ARGUMENTS) \
MOJO_GLES2_EXPORT ReturnType GL_APIENTRY gl##Function PARAMETERS;
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_resize_autogen.h"
#undef VISIT_GL_CALL
#ifdef __cplusplus
} // extern "C"
#endif
#endif // MOJO_PUBLIC_C_GLES2_CHROMIUM_RESIZE_H_
......@@ -2,17 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_
#define MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_
#include "mojo/public/c/environment/async_waiter.h"
namespace mojo {
namespace internal {
const MojoAsyncWaiter* GetDefaultAsyncWaiterImpl();
} // namespace internal
} // namespace mojo
#endif // MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_
// This file is auto-generated from
// gpu/command_buffer/build_gles2_cmd_buffer.py
// It's formatted by clang-format using chromium coding style:
// clang-format -i -style=chromium filename
// DO NOT EDIT!
VISIT_GL_CALL(ResizeCHROMIUM,
void,
(GLuint width, GLuint height, GLfloat scale_factor),
(width, height, scale_factor))
......@@ -26,7 +26,7 @@ extern "C" {
// 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-increasing with the passage of real time.
// 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.
MOJO_SYSTEM_EXPORT MojoTimeTicks MojoGetTimeTicksNow(void);
......
......@@ -8,6 +8,7 @@
#include <string.h>
#include <algorithm>
#include <set>
#include <string>
#include <vector>
......@@ -207,6 +208,34 @@ struct TypeConverter<std::vector<E>, Array<T>> {
}
};
// A |TypeConverter| that will create an |Array<T>| containing a copy of the
// contents of an |std::set<E>|, using |TypeConverter<T, E>| to copy each
// element. The returned array will always be non-null.
template <typename T, typename E>
struct TypeConverter<Array<T>, std::set<E>> {
static Array<T> Convert(const std::set<E>& input) {
Array<T> result(0u);
for (auto i : input)
result.push_back(TypeConverter<T, E>::Convert(i));
return result.Pass();
}
};
// A |TypeConverter| that will create an |std::set<E>| containing a copy of
// the contents of an |Array<T>|, using |TypeConverter<E, T>| to copy each
// element. If the input array is null, the output set will be empty.
template <typename E, typename T>
struct TypeConverter<std::set<E>, Array<T>> {
static std::set<E> Convert(const Array<T>& input) {
std::set<E> result;
if (!input.is_null()) {
for (size_t i = 0; i < input.size(); ++i)
result.insert(TypeConverter<E, T>::Convert(input[i]));
}
return result;
}
};
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_
......@@ -9,6 +9,7 @@
#include "mojo/public/interfaces/bindings/tests/math_calculator.mojom.h"
#include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h"
#include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
#include "mojo/public/interfaces/bindings/tests/scoping.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
......@@ -572,6 +573,77 @@ TEST(WeakConnectorTest, Math) {
EXPECT_FALSE(destroyed);
}
class CImpl : public C {
public:
CImpl(bool* d_called, InterfaceRequest<C> request)
: d_called_(d_called),
binding_(this, request.Pass()) {}
~CImpl() override {}
private:
void D() override {
*d_called_ = true;
}
bool* d_called_;
StrongBinding<C> binding_;
};
class BImpl : public B {
public:
BImpl(bool* d_called, InterfaceRequest<B> request)
: d_called_(d_called),
binding_(this, request.Pass()) {}
~BImpl() override {}
private:
void GetC(InterfaceRequest<C> c) override {
new CImpl(d_called_, c.Pass());
}
bool* d_called_;
StrongBinding<B> binding_;
};
class AImpl : public A {
public:
explicit AImpl(InterfaceRequest<A> request)
: d_called_(false),
binding_(this, request.Pass()) {}
~AImpl() override {}
bool d_called() const { return d_called_; }
private:
void GetB(InterfaceRequest<B> b) override {
new BImpl(&d_called_, b.Pass());
}
bool d_called_;
Binding<A> binding_;
};
TEST_F(InterfacePtrTest, Scoping) {
APtr a;
AImpl a_impl(GetProxy(&a));
EXPECT_FALSE(a_impl.d_called());
{
BPtr b;
a->GetB(GetProxy(&b));
CPtr c;
b->GetC(GetProxy(&c));
c->D();
}
// While B & C have fallen out of scope, the pipes will remain until they are
// flushed.
EXPECT_FALSE(a_impl.d_called());
PumpMessages();
EXPECT_TRUE(a_impl.d_called());
}
} // namespace
} // namespace test
} // namespace mojo
......@@ -431,6 +431,39 @@ TEST_F(ValidationIntegrationTest, Binding) {
RunValidationTests("integration_msghdr", test_message_receiver());
}
// Tests the IsValidValue() function generated for BasicEnum.
TEST(EnumValueValidationTest, BasicEnum) {
// BasicEnum can have -3,0,1,10 as possible integral values.
EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(-4)));
EXPECT_TRUE(BasicEnum_IsValidValue(static_cast<BasicEnum>(-3)));
EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(-2)));
EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(-1)));
EXPECT_TRUE(BasicEnum_IsValidValue(static_cast<BasicEnum>(0)));
EXPECT_TRUE(BasicEnum_IsValidValue(static_cast<BasicEnum>(1)));
EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(2)));
EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(9)));
// In the mojom, we represent this value as hex (0xa).
EXPECT_TRUE(BasicEnum_IsValidValue(static_cast<BasicEnum>(10)));
EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(11)));
}
// Tests the IsValidValue() method generated for StructWithEnum.
TEST(EnumValueValidationTest, EnumWithin) {
// StructWithEnum::EnumWithin can have [0,4] as possible integral values.
EXPECT_FALSE(StructWithEnum::EnumWithin_IsValidValue(
static_cast<StructWithEnum::EnumWithin>(-1)));
EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue(
static_cast<StructWithEnum::EnumWithin>(0)));
EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue(
static_cast<StructWithEnum::EnumWithin>(1)));
EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue(
static_cast<StructWithEnum::EnumWithin>(2)));
EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue(
static_cast<StructWithEnum::EnumWithin>(3)));
EXPECT_FALSE(StructWithEnum::EnumWithin_IsValidValue(
static_cast<StructWithEnum::EnumWithin>(4)));
}
} // namespace
} // namespace test
} // namespace mojo
......@@ -4,6 +4,8 @@
#include "mojo/public/cpp/environment/lib/default_task_tracker.h"
#include "mojo/public/cpp/environment/task_tracker.h"
namespace mojo {
namespace {
......
......@@ -5,9 +5,10 @@
#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_TASK_TRACKER_H_
#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_TASK_TRACKER_H_
#include "mojo/public/cpp/environment/task_tracker.h"
namespace mojo {
struct TaskTracker;
namespace internal {
extern const TaskTracker kDefaultTaskTracker;
......
......@@ -5,19 +5,15 @@
#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_
#define MOJO_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_
#include <sstream>
#include "mojo/public/cpp/system/macros.h"
#include <stdint.h>
namespace mojo {
typedef intptr_t TaskTrackingId;
// Interface for wiring task-level profiling, which is implemented through
// tracked_objects system in chrome.
// This API is mainly used from generated interface implementation.
// Interface for wiring task-level profiling. This API is mainly used by the
// generated interface implementation.
struct TaskTracker {
public:
// Start tracking. The returned id must be reclaimed through |EndTracking()|.
TaskTrackingId (*StartTracking)(const char* function_name,
const char* file_name,
......
......@@ -22,8 +22,9 @@ dart_mojo_sdk_sources = [
"lib/src/proxy.dart",
"lib/src/struct.dart",
"lib/src/stub.dart",
"lib/src/union.dart",
"lib/src/types.dart",
"lib/src/union.dart",
"lib/src/utils.dart",
]
dartzip_package("dart") {
......
......@@ -17,3 +17,4 @@ part 'src/event_stream.dart';
part 'src/handle.dart';
part 'src/message_pipe.dart';
part 'src/types.dart';
part 'src/utils.dart';
// 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();
}
......@@ -4,6 +4,10 @@
part of internal;
class MojoCoreNatives {
static int getTimeTicksNow() native "Mojo_GetTimeTicksNow";
}
class MojoHandleNatives {
static int register(
Object eventStream, int handle) native "MojoHandle_Register";
......
......@@ -17,6 +17,7 @@ mojom("test_interfaces") {
"sample_import2.mojom",
"sample_interfaces.mojom",
"sample_service.mojom",
"scoping.mojom",
"serialization_test_structs.mojom",
"test_constants.mojom",
"test_structs.mojom",
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module mojo.test;
interface A {
GetB(B& b);
};
interface B {
GetC(C& c);
};
interface C {
D();
};
......@@ -77,3 +77,21 @@ struct BasicStruct {
interface IntegrationTestInterface {
Method0(BasicStruct param0) => (array<uint8> param0);
};
// An enum generates a enum-value validation function, so we want to test it.
// E.g., valid enum values for this enum should be: -3, 0, 1, 10
enum BasicEnum {
A,
B,
C = A,
D = -3,
E = 0xA
};
// The enum validation function should be generated within the scope of this
// struct.
struct StructWithEnum {
enum EnumWithin {
A, B, C, D
};
};
......@@ -70,6 +70,8 @@ mojo_sdk_source_set("gles2") {
"gles2_impl_chromium_miscellaneous_thunks.h",
"gles2_impl_chromium_pixel_transfer_buffer_object_thunks.cc",
"gles2_impl_chromium_pixel_transfer_buffer_object_thunks.h",
"gles2_impl_chromium_resize_thunks.cc",
"gles2_impl_chromium_resize_thunks.h",
"gles2_impl_chromium_sub_image_thunks.cc",
"gles2_impl_chromium_sub_image_thunks.h",
"gles2_impl_chromium_sync_point_thunks.cc",
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/platform/native/gles2_impl_chromium_resize_thunks.h"
#include <assert.h>
#include "mojo/public/platform/native/thunk_export.h"
extern "C" {
static MojoGLES2ImplChromiumResizeThunks g_impl_chromium_resize_thunks = {0};
#define VISIT_GL_CALL(Function, ReturnType, PARAMETERS, ARGUMENTS) \
ReturnType gl##Function PARAMETERS { \
assert(g_impl_chromium_resize_thunks.Function); \
return g_impl_chromium_resize_thunks.Function ARGUMENTS; \
}
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_resize_autogen.h"
#undef VISIT_GL_CALL
extern "C" THUNK_EXPORT size_t
MojoSetGLES2ImplChromiumResizeThunks(const MojoGLES2ImplChromiumResizeThunks*
gles2_impl_chromium_resize_thunks) {
if (gles2_impl_chromium_resize_thunks->size >=
sizeof(g_impl_chromium_resize_thunks))
g_impl_chromium_resize_thunks = *gles2_impl_chromium_resize_thunks;
return sizeof(g_impl_chromium_resize_thunks);
}
} // extern "C"
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_PLATFORM_NATIVE_GLES2_IMPL_CHROMIUM_RESIZE_THUNKS_H_
#define MOJO_PUBLIC_PLATFORM_NATIVE_GLES2_IMPL_CHROMIUM_RESIZE_THUNKS_H_
#include <stddef.h>
#include "mojo/public/c/gles2/chromium_resize.h"
// Specifies the frozen API for the GLES2 CHROMIUM_resize extension.
#pragma pack(push, 8)
struct MojoGLES2ImplChromiumResizeThunks {
size_t size; // Should be set to sizeof(*this).
#define VISIT_GL_CALL(Function, ReturnType, PARAMETERS, ARGUMENTS) \
ReturnType(*Function) PARAMETERS;
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_resize_autogen.h"
#undef VISIT_GL_CALL
};
#pragma pack(pop)
// Intended to be called from the embedder to get the embedder's implementation
// of GLES2.
inline MojoGLES2ImplChromiumResizeThunks
MojoMakeGLES2ImplChromiumResizeThunks() {
MojoGLES2ImplChromiumResizeThunks gles2_impl_chromium_resize_thunks = {
sizeof(MojoGLES2ImplChromiumResizeThunks),
#define VISIT_GL_CALL(Function, ReturnType, PARAMETERS, ARGUMENTS) gl##Function,
#include "mojo/public/c/gles2/gles2_call_visitor_chromium_resize_autogen.h"
#undef VISIT_GL_CALL
};
return gles2_impl_chromium_resize_thunks;
}
// Use this type for the function found by dynamically discovering it in
// a DSO linked with mojo_system.
// The contents of |gles2_impl_chromium_resize_thunks| are copied.
typedef size_t (*MojoSetGLES2ImplChromiumResizeThunksFn)(
const MojoGLES2ImplChromiumResizeThunks* thunks);
#endif // MOJO_PUBLIC_PLATFORM_NATIVE_GLES2_IMPL_CHROMIUM_RESIZE_THUNKS_H_
enum {{enum.name}} : int32_t {
{%- for field in enum.fields %}
{%- if field.value %}
{{enum.name|to_all_caps}}_{{field.name}} = {{field.value|expression_to_text}},
{%- else %}
{{enum.name|to_all_caps}}_{{field.name}},
{%- endif %}
{%- endfor %}
};
{#---
Macro for enum definition, and the declaration of associated functions.
`is_static` is relevant if this enum declaration is defined within a class, in
which case associated functions need to be static.
---#}
{%- macro enum_decl(enum, is_static=false) %}
enum {{enum.name}} : int32_t {
{%- for field in enum.fields %}
{%- if field.value %}
{{enum.name|to_all_caps}}_{{field.name}} = {{field.value|expression_to_text}},
{%- else %}
{{enum.name|to_all_caps}}_{{field.name}},
{%- endif %}
{%- endfor %}
};
{{is_valid_enum_decl(enum, is_static)}}
{%- endmacro %}
{#--- macros for the declaration & definitions of enum-associated functions.
Namely:
* {enum_name}_IsValidValue: returns true if the given enum has a valid value
for this generated version of enum.
---#}
{%- macro is_valid_enum_decl(enum, is_static=false) %}
{% if is_static %}static {% endif -%}
bool {{enum.name}}_IsValidValue({{enum.name}} value);
{%- endmacro %}
{%- macro is_valid_enum_def(enum, class_name = '') %}
{% if class_name != '' -%}
// static
bool {{class_name}}::
{%- else -%}
{{"bool "}}
{%- endif -%}
{{enum.name}}_IsValidValue({{enum.name}} value) {
switch (static_cast<int32_t>(value)) {
{%- for enum_field in enum.fields|groupby('numeric_value') %}
case {{enum_field[0]}}:
{%- endfor %}
return true;
}
return false;
}
{%- endmacro %}
......@@ -23,9 +23,9 @@ class {{interface.name}} {
{%- endif %}
{#--- Enums #}
{% from "enum_macros.tmpl" import enum_decl -%}
{%- for enum in interface.enums %}
{% macro enum_def() %}{% include "enum_declaration.tmpl" %}{% endmacro %}
{{enum_def()|indent(2)}}
{{enum_decl(enum, is_static=true)|indent(2)}}
{%- endfor %}
{#--- Constants #}
......
{%- import "interface_macros.tmpl" as interface_macros %}
{%- import "struct_macros.tmpl" as struct_macros %}
{%- from "enum_macros.tmpl" import is_valid_enum_def %}
{%- set class_name = interface.name %}
{%- set proxy_name = interface.name ~ "Proxy" %}
{%- set namespace_as_string = "%s"|format(namespace|replace(".","::")) %}
......@@ -42,6 +44,11 @@ MOJO_STATIC_CONST_MEMBER_DEFINITION const {{constant.kind|cpp_pod_type}} {{inter
{%- endif %}
{%- endfor %}
{#--- Enums #}
{%- for enum in interface.enums %}
{{is_valid_enum_def(enum, class_name=interface.name)|indent(2)}}
{%- endfor %}
{#--- ForwardToCallback definition #}
{%- for method in interface.methods -%}
{%- if method.response_parameters != None %}
......
......@@ -78,6 +78,12 @@ const uint32_t {{method_name}} = {{method.ordinal}};
} // namespace internal
{#--- Enums #}
{%- from "enum_macros.tmpl" import is_valid_enum_def -%}
{%- for enum in enums -%}
{{is_valid_enum_def(enum, class_name='')}}
{%- endfor %}
{#--- Struct Constants #}
{%- for struct in structs %}
{%- for constant in struct.constants %}
......
......@@ -31,8 +31,9 @@ namespace {{namespace}} {
{%- endfor %}
{#--- Enums #}
{% from "enum_macros.tmpl" import enum_decl -%}
{% for enum in enums %}
{% include "enum_declaration.tmpl" %}
{{enum_decl(enum)}}
{%- endfor %}
{#--- Constants #}
......
{% from "enum_macros.tmpl" import enum_decl -%}
class {{struct.name}} {
public:
using Data_ = internal::{{struct.name}}_Data;
{#--- Enums #}
{%- for enum in struct.enums -%}
{% macro enum_def() %}{% include "enum_declaration.tmpl" %}{% endmacro %}
{{enum_def()|indent(2)}}
{{enum_decl(enum, is_static=true)|indent(2)}}
{%- endfor %}
{#--- Constants #}
......
{%- from "enum_macros.tmpl" import is_valid_enum_def %}
{#--- Enums #}
{%- for enum in struct.enums -%}
{{is_valid_enum_def(enum, class_name=struct.name)}}
{%- endfor %}
// static
{{struct.name}}Ptr {{struct.name}}::New() {
{{struct.name}}Ptr rv;
......
......@@ -122,6 +122,7 @@ try {
return false;
}
} catch (org.chromium.mojo.bindings.DeserializationException e) {
System.err.println(e.toString());
return false;
}
{%- endmacro -%}
......
......@@ -373,10 +373,21 @@ def IsPointerArrayKind(kind):
sub_kind = kind.kind
return mojom.IsObjectKind(sub_kind)
def ParseStringAttribute(attribute):
assert isinstance(attribute, basestring)
return attribute
def GetPackage(module):
if module.attributes and 'DartPackage' in module.attributes:
return ParseStringAttribute(module.attributes['DartPackage'])
# Default package.
return 'mojom'
def GetImportUri(module):
package = GetPackage(module);
elements = module.namespace.split('.')
elements.append("%s" % module.name)
return os.path.join("mojom", *elements)
return os.path.join(package, *elements)
class Generator(generator.Generator):
......@@ -423,8 +434,9 @@ class Generator(generator.Generator):
elements = self.module.namespace.split('.')
elements.append("%s.dart" % self.module.name)
package_name = GetPackage(self.module)
lib_module = self.GenerateLibModule(args)
pkg_path = os.path.join("dart-pkg", "mojom/lib", *elements)
pkg_path = os.path.join("dart-pkg", package_name, "lib", *elements)
self.Write(lib_module, pkg_path)
gen_path = os.path.join("dart-gen", "mojom/lib", *elements)
......
......@@ -55,7 +55,7 @@ template("mojom") {
generator_script = "$generator_root/mojom_bindings_generator.py"
generator_sources = [
generator_script,
"$generator_root/generators/cpp_templates/enum_declaration.tmpl",
"$generator_root/generators/cpp_templates/enum_macros.tmpl",
"$generator_root/generators/cpp_templates/interface_declaration.tmpl",
"$generator_root/generators/cpp_templates/interface_definition.tmpl",
"$generator_root/generators/cpp_templates/interface_macros.tmpl",
......
......@@ -347,6 +347,33 @@ def EnumFieldFromData(module, enum, data, parent_kind):
module.values[value.GetSpec()] = value
return field
def ResolveNumericEnumValues(enum_fields):
"""
Given a reference to a list of mojom.EnumField, resolves and assigns their
values to EnumField.numeric_value.
"""
# map of <name> -> integral value
resolved_enum_values = {}
prev_value = -1
for field in enum_fields:
# This enum value is +1 the previous enum value (e.g: BEGIN).
if field.value is None:
prev_value += 1
# Integral value (e.g: BEGIN = -0x1).
elif type(field.value) is str:
prev_value = int(field.value, 0)
# Reference to a previous enum value (e.g: INIT = BEGIN).
elif type(field.value) is mojom.EnumValue:
prev_value = resolved_enum_values[field.value.name]
else:
raise Exception("Unresolved enum value.")
resolved_enum_values[field.name] = prev_value
field.numeric_value = prev_value
def EnumFromData(module, data, parent_kind):
enum = mojom.Enum(module=module)
enum.name = data['name']
......@@ -359,6 +386,7 @@ def EnumFromData(module, data, parent_kind):
lambda field: EnumFieldFromData(module, enum, field, parent_kind),
data['fields'])
enum.attributes = data.get('attributes')
ResolveNumericEnumValues(enum.fields)
module.kinds[enum.spec] = enum
return enum
......
......@@ -386,10 +386,12 @@ class Interface(ReferenceKind):
class EnumField(object):
def __init__(self, name=None, value=None, attributes=None):
def __init__(self, name=None, value=None, attributes=None,
numeric_value=None):
self.name = name
self.value = value
self.attributes = attributes
self.numeric_value = numeric_value
@property
def min_version(self):
......@@ -572,4 +574,3 @@ def HasCallbacks(interface):
if method.response_parameters != None:
return True
return False
......@@ -39,15 +39,15 @@ def main():
command_line = [os.path.join(os.path.dirname(__file__), os.path.pardir,
"devtools", "common", "mojo_test"),
str(args.test_list_file)]
if config.is_debug:
command_line.append("--debug")
else:
command_line.append("--release")
if config.target_os == Config.OS_ANDROID:
command_line.append("--android")
command_line.append("--adb-path=" + paths.adb_path)
command_line.append("--origin=" + paths.build_dir)
command_line.append("--shell-path=" + paths.target_mojo_shell_path)
command_line.append("--origin-path=" + paths.build_dir)
if args.verbose_count:
command_line.append("--verbose")
gtest.set_color()
print "Running " + str(command_line)
......
......@@ -172,14 +172,6 @@ def GetTestList(config, verbose_count=0):
"mojom_fetcher",
"mojom_fetcher_tests.py")])
# Dart mojom package generate.dart script tests:
if target_os == Config.OS_LINUX:
AddEntry("Dart mojom package generate tests",
[os.path.join("third_party", "dart-sdk", "dart-sdk", "bin", "dart"),
"--checked",
"-p", os.path.join("mojo", "dart", "mojom", "packages"),
os.path.join("mojo", "dart", "mojom", "test", "generate_test.dart")])
# Perf tests -----------------------------------------------------------------
if target_os == Config.OS_LINUX and ShouldRunTest(Config.TEST_TYPE_PERF):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册