diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index abb64a11b5a..6c77e2f89e7 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -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") diff --git a/mojo/dart/embedder/BUILD.gn b/mojo/dart/embedder/BUILD.gn index 5cd2274f9f7..67648734d33 100644 --- a/mojo/dart/embedder/BUILD.gn +++ b/mojo/dart/embedder/BUILD.gn @@ -17,6 +17,7 @@ source_set("dart_controller_no_snapshot") { "dart_controller.cc", "dart_controller.h", "io/internet_address.h", + "mojo_dart_state.h", "mojo_io_natives.cc", "mojo_io_natives.h", "mojo_natives.cc", @@ -45,6 +46,7 @@ source_set("dart_controller_no_snapshot") { "//mojo/common", "//mojo/public/c/system", "//mojo/public/cpp/system", + "//mojo/services/network/public/interfaces", ] defines = [] @@ -61,6 +63,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 +123,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", diff --git a/mojo/dart/embedder/builtin.cc b/mojo/dart/embedder/builtin.cc index 8985c1b2333..a169e11d57e 100644 --- a/mojo/dart/embedder/builtin.cc +++ b/mojo/dart/embedder/builtin.cc @@ -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_[] = { diff --git a/mojo/dart/embedder/dart_controller.cc b/mojo/dart/embedder/dart_controller.cc index ac4bf87a336..ff64c9caf51 100644 --- a/mojo/dart/embedder/dart_controller.cc +++ b/mojo/dart/embedder/dart_controller.cc @@ -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" diff --git a/mojo/dart/embedder/dart_controller.h b/mojo/dart/embedder/dart_controller.h index 076701b6c53..b0b53a9bda8 100644 --- a/mojo/dart/embedder/dart_controller.h +++ b/mojo/dart/embedder/dart_controller.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 { diff --git a/mojo/dart/embedder/io/process_patch.dart b/mojo/dart/embedder/io/process_patch.dart new file mode 100644 index 00000000000..f6dc4442f9d --- /dev/null +++ b/mojo/dart/embedder/io/process_patch.dart @@ -0,0 +1,14 @@ +// 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 diff --git a/mojo/dart/embedder/dart_state.h b/mojo/dart/embedder/mojo_dart_state.h similarity index 100% rename from mojo/dart/embedder/dart_state.h rename to mojo/dart/embedder/mojo_dart_state.h diff --git a/mojo/dart/embedder/mojo_io_natives.cc b/mojo/dart/embedder/mojo_io_natives.cc index 7dc768ec1fe..7c3ee74d520 100644 --- a/mojo/dart/embedder/mojo_io_natives.cc +++ b/mojo/dart/embedder/mojo_io_natives.cc @@ -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(pid)); +} + } // namespace dart } // namespace mojo diff --git a/mojo/dart/embedder/mojo_natives.cc b/mojo/dart/embedder/mojo_natives.cc index 6e107eb8c8e..8c6d8278f8c 100644 --- a/mojo/dart/embedder/mojo_natives.cc +++ b/mojo/dart/embedder/mojo_natives.cc @@ -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(MOJO_RESULT_OK)); } +void Mojo_GetTimeTicksNow(Dart_NativeArguments arguments) { + MojoTimeTicks ticks = MojoGetTimeTicksNow(); + Dart_SetIntegerReturnValue(arguments, static_cast(ticks)); +} + void MojoHandle_Close(Dart_NativeArguments arguments) { int64_t raw_handle; CHECK_INTEGER_ARGUMENT(arguments, 0, &raw_handle, InvalidArgument); diff --git a/mojo/dart/mojom/lib/generate.dart b/mojo/dart/mojom/lib/generate.dart index af3e95141ab..1b03cb36f72 100644 --- a/mojo/dart/mojom/lib/generate.dart +++ b/mojo/dart/mojom/lib/generate.dart @@ -29,6 +29,7 @@ part 'src/utils.dart'; bool verbose; bool dryRun; +Map duplicateDetection = new Map(); /// 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'); } diff --git a/mojo/dart/test/core_test.dart b/mojo/dart/test/core_test.dart index f3c321e291e..0162e4e4247 100644 --- a/mojo/dart/test/core_test.dart +++ b/mojo/dart/test/core_test.dart @@ -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(); } diff --git a/mojo/devtools/common/devtoolslib/android_shell.py b/mojo/devtools/common/devtoolslib/android_shell.py index dce9897b4cd..d02ea0cdf41 100644 --- a/mojo/devtools/common/devtoolslib/android_shell.py +++ b/mojo/devtools/common/devtoolslib/android_shell.py @@ -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]) diff --git a/mojo/devtools/common/devtoolslib/apptest_runner.py b/mojo/devtools/common/devtoolslib/apptest_runner.py deleted file mode 100644 index f95199405ad..00000000000 --- a/mojo/devtools/common/devtoolslib/apptest_runner.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""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 diff --git a/mojo/devtools/common/devtoolslib/http_server.py b/mojo/devtools/common/devtoolslib/http_server.py index 97e98a53d67..5199f3ee116 100644 --- a/mojo/devtools/common/devtoolslib/http_server.py +++ b/mojo/devtools/common/devtoolslib/http_server.py @@ -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: diff --git a/mojo/devtools/common/devtoolslib/linux_shell.py b/mojo/devtools/common/devtoolslib/linux_shell.py index d3d8624dd95..6e03e6fb711 100644 --- a/mojo/devtools/common/devtoolslib/linux_shell.py +++ b/mojo/devtools/common/devtoolslib/linux_shell.py @@ -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 diff --git a/mojo/devtools/common/devtoolslib/shell_arguments.py b/mojo/devtools/common/devtoolslib/shell_arguments.py index 49e2b8b86aa..7b61194d726 100644 --- a/mojo/devtools/common/devtoolslib/shell_arguments.py +++ b/mojo/devtools/common/devtoolslib/shell_arguments.py @@ -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 - -# Port on which the mojo:debugger http server will be available on the host -# machine. -_MOJO_DEBUGGER_PORT = 7777 - _SKY_SERVER_PORT = 9998 -def _HostLocalUrlDestination(shell, dest_file, port): +def _is_web_url(dest): + return True if urlparse.urlparse(dest).scheme else False + + +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 = and rewrites the part to be hosted locally using the given function if 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 ' '"="') - 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 ' + '=') + parser.add_argument('--map-origin', action='append', + help='Define a mapping for a url origin in the format ' + '=') + + # 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 diff --git a/mojo/devtools/common/devtoolslib/shell_arguments_unittest.py b/mojo/devtools/common/devtoolslib/shell_arguments_unittest.py index 511ad441cc3..d1b5f37720d 100644 --- a/mojo/devtools/common/devtoolslib/shell_arguments_unittest.py +++ b/mojo/devtools/common/devtoolslib/shell_arguments_unittest.py @@ -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__": diff --git a/mojo/devtools/common/mojo_run b/mojo/devtools/common/mojo_run index 204dd1dd3db..778dd704d19 100755 --- a/mojo/devtools/common/mojo_run +++ b/mojo/devtools/common/mojo_run @@ -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=] " "[--content-handlers=] " "[--enable-external-applications] " @@ -28,149 +26,114 @@ The value of 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']) + chromium_config_group.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 ' - '=') - parser.add_argument('--map-origin', action='append', - help='Define a mapping for a url origin in the format ' - '=') + 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.') + script_args, shell_args = parser.parse_known_args() - # 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) + # 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 + 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.' - 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 + try: + shell, shell_args = shell_arguments.configure_shell(script_args, shell_args) + except shell_arguments.ShellConfigurationException as e: + print e + return 1 - 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 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)) - if launcher_args.android: - verbose_pipe = sys.stdout if launcher_args.verbose else None + shell_args = shell_arguments.append_to_argument(shell_args, '--url-mappings=', + 'mojo:window_manager=%s' % + script_args.window_manager) - 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: + 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 diff --git a/mojo/devtools/common/mojo_test b/mojo/devtools/common/mojo_test index ae94f7188e1..c824f10b1ae 100755 --- a/mojo/devtools/common/mojo_test +++ b/mojo/devtools/common/mojo_test @@ -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']) + # Common shell configuration arguments. + shell_arguments.add_shell_arguments(parser) + script_args, common_shell_args = parser.parse_known_args() - # 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() + try: + shell, common_shell_args = shell_arguments.configure_shell( + script_args, common_shell_args) + except shell_arguments.ShellConfigurationException as e: + print e + return 1 - 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' + 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()) diff --git a/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc b/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc index c7b49c210f0..0b20f4b57b5 100644 --- a/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc +++ b/mojo/edk/embedder/platform_channel_pair_posix_unittest.cc @@ -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(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())); diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn index 5dd2682ceab..ac292d5c4c3 100644 --- a/mojo/edk/system/BUILD.gn +++ b/mojo/edk/system/BUILD.gn @@ -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", diff --git a/mojo/edk/system/connection_manager.h b/mojo/edk/system/connection_manager.h index 5923c75322f..e0c3a6f7003 100644 --- a/mojo/edk/system/connection_manager.h +++ b/mojo/edk/system/connection_manager.h @@ -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: diff --git a/mojo/edk/system/connection_manager_messages.h b/mojo/edk/system/connection_manager_messages.h new file mode 100644 index 00000000000..4117f953682 --- /dev/null +++ b/mojo/edk/system/connection_manager_messages.h @@ -0,0 +1,30 @@ +// 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 + +#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_ diff --git a/mojo/edk/system/connection_manager_unittest.cc b/mojo/edk/system/connection_manager_unittest.cc index 20fa73e3324..7b409c123ce 100644 --- a/mojo/edk/system/connection_manager_unittest.cc +++ b/mojo/edk/system/connection_manager_unittest.cc @@ -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())); diff --git a/mojo/edk/system/ipc_support.cc b/mojo/edk/system/ipc_support.cc index 7c4f3d45e28..1c4b232c1d3 100644 --- a/mojo/edk/system/ipc_support.cc +++ b/mojo/edk/system/ipc_support.cc @@ -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); diff --git a/mojo/edk/system/master_connection_manager.cc b/mojo/edk/system/master_connection_manager.cc index 7e24a4a8248..384be226e86 100644 --- a/mojo/edk/system/master_connection_manager.cc +++ b/mojo/edk/system/master_connection_manager.cc @@ -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(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(sizeof(peer_process_identifier)); - bytes = &peer_process_identifier; + num_bytes = static_cast(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; diff --git a/mojo/edk/system/master_connection_manager.h b/mojo/edk/system/master_connection_manager.h index 497f449e13f..a03719a400e 100644 --- a/mojo/edk/system/master_connection_manager.h +++ b/mojo/edk/system/master_connection_manager.h @@ -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_|: diff --git a/mojo/edk/system/message_in_transit.h b/mojo/edk/system/message_in_transit.h index c61cfd67a37..2edc7762a63 100644 --- a/mojo/edk/system/message_in_transit.h +++ b/mojo/edk/system/message_in_transit.h @@ -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, diff --git a/mojo/edk/system/slave_connection_manager.cc b/mojo/edk/system/slave_connection_manager.cc index 7d0a9987eac..5ed9ba6c9b0 100644 --- a/mojo/edk/system/slave_connection_manager.cc +++ b/mojo/edk/system/slave_connection_manager.cc @@ -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(message_view.bytes()); + // Success acks for "connect" always have a + // |ConnectionManagerAckSuccessConnectData| as data. + CHECK_EQ(num_bytes, sizeof(ConnectionManagerAckSuccessConnectData)); + const ConnectionManagerAckSuccessConnectData& data = + *static_cast( + 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(); } diff --git a/mojo/edk/system/slave_connection_manager.h b/mojo/edk/system/slave_connection_manager.h index b2cd92cd082..664c8dd80f6 100644 --- a/mojo/edk/system/slave_connection_manager.h +++ b/mojo/edk/system/slave_connection_manager.h @@ -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 diff --git a/mojo/environment/BUILD.gn b/mojo/environment/BUILD.gn index 1274a3d4da7..53719351e30 100644 --- a/mojo/environment/BUILD.gn +++ b/mojo/environment/BUILD.gn @@ -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 = [ + "//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", ] } - -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/environment", - ] -} diff --git a/mojo/environment/default_async_waiter_impl.cc b/mojo/environment/default_async_waiter.cc similarity index 84% rename from mojo/environment/default_async_waiter_impl.cc rename to mojo/environment/default_async_waiter.cc index ff7a524752e..863cfe31582 100644 --- a/mojo/environment/default_async_waiter_impl.cc +++ b/mojo/environment/default_async_waiter.cc @@ -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(wait_id); } -const MojoAsyncWaiter kDefaultAsyncWaiter = { - AsyncWait, - CancelWait -}; - } // namespace -const MojoAsyncWaiter* GetDefaultAsyncWaiterImpl() { - return &kDefaultAsyncWaiter; -} +const MojoAsyncWaiter kDefaultAsyncWaiter = {AsyncWait, CancelWait}; } // namespace internal } // namespace mojo diff --git a/mojo/environment/default_run_loop_impl.h b/mojo/environment/default_async_waiter.h similarity index 53% rename from mojo/environment/default_run_loop_impl.h rename to mojo/environment/default_async_waiter.h index eec58fd2b27..2e4bb13c32e 100644 --- a/mojo/environment/default_run_loop_impl.h +++ b/mojo/environment/default_async_waiter.h @@ -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_ diff --git a/mojo/environment/default_async_waiter_impl.h b/mojo/environment/default_async_waiter_impl.h deleted file mode 100644 index e697dfc0168..00000000000 --- a/mojo/environment/default_async_waiter_impl.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_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_ diff --git a/mojo/environment/default_logger_impl.cc b/mojo/environment/default_logger.cc similarity index 89% rename from mojo/environment/default_logger_impl.cc rename to mojo/environment/default_logger.cc index 783c06bb211..693b37b2a7c 100644 --- a/mojo/environment/default_logger_impl.cc +++ b/mojo/environment/default_logger.cc @@ -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 diff --git a/mojo/environment/default_logger_impl.h b/mojo/environment/default_logger.h similarity index 52% rename from mojo/environment/default_logger_impl.h rename to mojo/environment/default_logger.h index 080d259b2f6..41ff646d85e 100644 --- a/mojo/environment/default_logger_impl.h +++ b/mojo/environment/default_logger.h @@ -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_ diff --git a/mojo/environment/default_run_loop_impl.cc b/mojo/environment/default_run_loop_impl.cc deleted file mode 100644 index 4fa9ffd1f46..00000000000 --- a/mojo/environment/default_run_loop_impl.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/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 diff --git a/mojo/environment/default_task_tracker_impl.cc b/mojo/environment/default_task_tracker.cc similarity index 83% rename from mojo/environment/default_task_tracker_impl.cc rename to mojo/environment/default_task_tracker.cc index ccf75311eae..eb7cccf2b52 100644 --- a/mojo/environment/default_task_tracker_impl.cc +++ b/mojo/environment/default_task_tracker.cc @@ -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 diff --git a/mojo/environment/default_task_tracker.h b/mojo/environment/default_task_tracker.h new file mode 100644 index 00000000000..f1f43e50e24 --- /dev/null +++ b/mojo/environment/default_task_tracker.h @@ -0,0 +1,19 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_H_ +#define MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_H_ + +namespace mojo { + +struct TaskTracker; + +namespace internal { + +extern const TaskTracker kDefaultTaskTracker; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_H_ diff --git a/mojo/environment/default_task_tracker_impl.h b/mojo/environment/default_task_tracker_impl.h deleted file mode 100644 index 81048ed2ce9..00000000000 --- a/mojo/environment/default_task_tracker_impl.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_ -#define MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_ - -#include "mojo/public/cpp/environment/task_tracker.h" - -namespace mojo { -namespace internal { - -const TaskTracker* GetDefaultTaskTrackerImpl(); - -} // namespace internal -} // namespace mojo - -#endif // MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_ diff --git a/mojo/environment/environment.cc b/mojo/environment/environment.cc index 105b6aea54f..a5a424cb45e 100644 --- a/mojo/environment/environment.cc +++ b/mojo/environment/environment.cc @@ -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 diff --git a/mojo/gles2/gles2_impl.cc b/mojo/gles2/gles2_impl.cc index 384ffd11a25..94dbae7c32e 100644 --- a/mojo/gles2/gles2_impl.cc +++ b/mojo/gles2/gles2_impl.cc @@ -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" diff --git a/mojo/public/c/gles2/BUILD.gn b/mojo/public/c/gles2/BUILD.gn index 544368dd32d..0ccdbbe6799 100644 --- a/mojo/public/c/gles2/BUILD.gn +++ b/mojo/public/c/gles2/BUILD.gn @@ -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", diff --git a/mojo/public/c/gles2/chromium_resize.h b/mojo/public/c/gles2/chromium_resize.h new file mode 100644 index 00000000000..d8d527a829d --- /dev/null +++ b/mojo/public/c/gles2/chromium_resize.h @@ -0,0 +1,30 @@ +// 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 +#include + +#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_ diff --git a/mojo/public/c/gles2/gles2_call_visitor_chromium_resize_autogen.h b/mojo/public/c/gles2/gles2_call_visitor_chromium_resize_autogen.h new file mode 100644 index 00000000000..be4d6da2f4e --- /dev/null +++ b/mojo/public/c/gles2/gles2_call_visitor_chromium_resize_autogen.h @@ -0,0 +1,14 @@ +// 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. + +// 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)) diff --git a/mojo/public/c/system/functions.h b/mojo/public/c/system/functions.h index c53a4ed0039..8b576c189aa 100644 --- a/mojo/public/c/system/functions.h +++ b/mojo/public/c/system/functions.h @@ -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); diff --git a/mojo/public/cpp/bindings/array.h b/mojo/public/cpp/bindings/array.h index 5194663c51a..c51a455065f 100644 --- a/mojo/public/cpp/bindings/array.h +++ b/mojo/public/cpp/bindings/array.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -207,6 +208,34 @@ struct TypeConverter, Array> { } }; +// A |TypeConverter| that will create an |Array| containing a copy of the +// contents of an |std::set|, using |TypeConverter| to copy each +// element. The returned array will always be non-null. +template +struct TypeConverter, std::set> { + static Array Convert(const std::set& input) { + Array result(0u); + for (auto i : input) + result.push_back(TypeConverter::Convert(i)); + return result.Pass(); + } +}; + +// A |TypeConverter| that will create an |std::set| containing a copy of +// the contents of an |Array|, using |TypeConverter| to copy each +// element. If the input array is null, the output set will be empty. +template +struct TypeConverter, Array> { + static std::set Convert(const Array& input) { + std::set result; + if (!input.is_null()) { + for (size_t i = 0; i < input.size(); ++i) + result.insert(TypeConverter::Convert(input[i])); + } + return result; + } +}; + } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_ diff --git a/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc index 681cc6d368d..6c192854ee7 100644 --- a/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc +++ b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc @@ -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 request) + : d_called_(d_called), + binding_(this, request.Pass()) {} + ~CImpl() override {} + + private: + void D() override { + *d_called_ = true; + } + + bool* d_called_; + StrongBinding binding_; +}; + +class BImpl : public B { + public: + BImpl(bool* d_called, InterfaceRequest request) + : d_called_(d_called), + binding_(this, request.Pass()) {} + ~BImpl() override {} + + private: + void GetC(InterfaceRequest c) override { + new CImpl(d_called_, c.Pass()); + } + + bool* d_called_; + StrongBinding binding_; +}; + +class AImpl : public A { + public: + explicit AImpl(InterfaceRequest request) + : d_called_(false), + binding_(this, request.Pass()) {} + ~AImpl() override {} + + bool d_called() const { return d_called_; } + + private: + void GetB(InterfaceRequest b) override { + new BImpl(&d_called_, b.Pass()); + } + + bool d_called_; + Binding 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 diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc index 39befafdd3b..8f404011b3b 100644 --- a/mojo/public/cpp/bindings/tests/validation_unittest.cc +++ b/mojo/public/cpp/bindings/tests/validation_unittest.cc @@ -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(-4))); + EXPECT_TRUE(BasicEnum_IsValidValue(static_cast(-3))); + EXPECT_FALSE(BasicEnum_IsValidValue(static_cast(-2))); + EXPECT_FALSE(BasicEnum_IsValidValue(static_cast(-1))); + EXPECT_TRUE(BasicEnum_IsValidValue(static_cast(0))); + EXPECT_TRUE(BasicEnum_IsValidValue(static_cast(1))); + EXPECT_FALSE(BasicEnum_IsValidValue(static_cast(2))); + EXPECT_FALSE(BasicEnum_IsValidValue(static_cast(9))); + // In the mojom, we represent this value as hex (0xa). + EXPECT_TRUE(BasicEnum_IsValidValue(static_cast(10))); + EXPECT_FALSE(BasicEnum_IsValidValue(static_cast(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(-1))); + EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue( + static_cast(0))); + EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue( + static_cast(1))); + EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue( + static_cast(2))); + EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue( + static_cast(3))); + EXPECT_FALSE(StructWithEnum::EnumWithin_IsValidValue( + static_cast(4))); +} + } // namespace } // namespace test } // namespace mojo diff --git a/mojo/public/cpp/environment/lib/default_task_tracker.cc b/mojo/public/cpp/environment/lib/default_task_tracker.cc index 17c814db679..a99f1c74e93 100644 --- a/mojo/public/cpp/environment/lib/default_task_tracker.cc +++ b/mojo/public/cpp/environment/lib/default_task_tracker.cc @@ -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 { diff --git a/mojo/public/cpp/environment/lib/default_task_tracker.h b/mojo/public/cpp/environment/lib/default_task_tracker.h index 83b9ae3c9bf..7a0c06478c6 100644 --- a/mojo/public/cpp/environment/lib/default_task_tracker.h +++ b/mojo/public/cpp/environment/lib/default_task_tracker.h @@ -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; diff --git a/mojo/public/cpp/environment/task_tracker.h b/mojo/public/cpp/environment/task_tracker.h index 771dc7f6391..d6d3020d975 100644 --- a/mojo/public/cpp/environment/task_tracker.h +++ b/mojo/public/cpp/environment/task_tracker.h @@ -5,19 +5,15 @@ #ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_ #define MOJO_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_ -#include - -#include "mojo/public/cpp/system/macros.h" +#include 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, diff --git a/mojo/public/dart/BUILD.gn b/mojo/public/dart/BUILD.gn index c069627b858..408f4c999be 100644 --- a/mojo/public/dart/BUILD.gn +++ b/mojo/public/dart/BUILD.gn @@ -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") { diff --git a/mojo/public/dart/lib/core.dart b/mojo/public/dart/lib/core.dart index e72da3f2119..dfaf88a3097 100644 --- a/mojo/public/dart/lib/core.dart +++ b/mojo/public/dart/lib/core.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'; diff --git a/mojo/public/dart/lib/src/utils.dart b/mojo/public/dart/lib/src/utils.dart new file mode 100644 index 00000000000..476fcc84eaf --- /dev/null +++ b/mojo/public/dart/lib/src/utils.dart @@ -0,0 +1,15 @@ +// 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(); +} diff --git a/mojo/public/dart/sdk_ext/src/natives.dart b/mojo/public/dart/sdk_ext/src/natives.dart index a46ddd68a6d..350b0a60ce0 100644 --- a/mojo/public/dart/sdk_ext/src/natives.dart +++ b/mojo/public/dart/sdk_ext/src/natives.dart @@ -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"; diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn index e7efd3d80b2..b0a303f2174 100644 --- a/mojo/public/interfaces/bindings/tests/BUILD.gn +++ b/mojo/public/interfaces/bindings/tests/BUILD.gn @@ -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", diff --git a/mojo/public/interfaces/bindings/tests/scoping.mojom b/mojo/public/interfaces/bindings/tests/scoping.mojom new file mode 100644 index 00000000000..2e9edb10b4e --- /dev/null +++ b/mojo/public/interfaces/bindings/tests/scoping.mojom @@ -0,0 +1,17 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module mojo.test; + +interface A { + GetB(B& b); +}; + +interface B { + GetC(C& c); +}; + +interface C { + D(); +}; diff --git a/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom b/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom index 258c166dc65..dd2eb4cc25b 100644 --- a/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom +++ b/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom @@ -77,3 +77,21 @@ struct BasicStruct { interface IntegrationTestInterface { Method0(BasicStruct param0) => (array 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 + }; +}; diff --git a/mojo/public/platform/native/BUILD.gn b/mojo/public/platform/native/BUILD.gn index df464f81df7..7ca35d3d0fa 100644 --- a/mojo/public/platform/native/BUILD.gn +++ b/mojo/public/platform/native/BUILD.gn @@ -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", diff --git a/mojo/public/platform/native/gles2_impl_chromium_resize_thunks.cc b/mojo/public/platform/native/gles2_impl_chromium_resize_thunks.cc new file mode 100644 index 00000000000..fe03c7bbeed --- /dev/null +++ b/mojo/public/platform/native/gles2_impl_chromium_resize_thunks.cc @@ -0,0 +1,31 @@ +// 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 + +#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" diff --git a/mojo/public/platform/native/gles2_impl_chromium_resize_thunks.h b/mojo/public/platform/native/gles2_impl_chromium_resize_thunks.h new file mode 100644 index 00000000000..f9af8fcf606 --- /dev/null +++ b/mojo/public/platform/native/gles2_impl_chromium_resize_thunks.h @@ -0,0 +1,44 @@ +// 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 + +#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_ diff --git a/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl deleted file mode 100644 index d212e8bacd5..00000000000 --- a/mojo/public/tools/bindings/generators/cpp_templates/enum_declaration.tmpl +++ /dev/null @@ -1,9 +0,0 @@ -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 %} -}; diff --git a/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl new file mode 100644 index 00000000000..0e44acd57e6 --- /dev/null +++ b/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl @@ -0,0 +1,46 @@ +{#--- + 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(value)) { +{%- for enum_field in enum.fields|groupby('numeric_value') %} + case {{enum_field[0]}}: +{%- endfor %} + return true; + } + return false; +} +{%- endmacro %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl index cdfc0ab2709..9edc1db8e5a 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl @@ -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 #} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index 38991a959fd..4bc2a59260d 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl @@ -1,5 +1,7 @@ {%- 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 %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl index 463d2607a2c..05305e19ca0 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl @@ -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 %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index 56a704705d5..39fe8bcd5f7 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl @@ -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 #} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl index 47e2df86fb7..0293accde40 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl @@ -1,12 +1,11 @@ - +{% 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 #} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl index 5ab301cbe2e..8c61c86ab18 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl @@ -1,3 +1,10 @@ +{%- 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; diff --git a/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl index 320abeb9a29..527e15fbfcf 100644 --- a/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl @@ -122,6 +122,7 @@ try { return false; } } catch (org.chromium.mojo.bindings.DeserializationException e) { + System.err.println(e.toString()); return false; } {%- endmacro -%} diff --git a/mojo/public/tools/bindings/generators/mojom_dart_generator.py b/mojo/public/tools/bindings/generators/mojom_dart_generator.py index c324c9c35d2..a0971d5975d 100644 --- a/mojo/public/tools/bindings/generators/mojom_dart_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_dart_generator.py @@ -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) diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni index 03dd431e628..f990b2105a7 100644 --- a/mojo/public/tools/bindings/mojom.gni +++ b/mojo/public/tools/bindings/mojom.gni @@ -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", diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/data.py b/mojo/public/tools/bindings/pylib/mojom/generate/data.py index bc727b4c8f5..0c64d4edece 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/data.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/data.py @@ -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 -> 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 diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py index df5c8dce1e3..8596f22e772 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py @@ -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 - diff --git a/mojo/tools/apptest_runner.py b/mojo/tools/apptest_runner.py index ffe8c906165..b3378efafb6 100755 --- a/mojo/tools/apptest_runner.py +++ b/mojo/tools/apptest_runner.py @@ -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) diff --git a/mojo/tools/get_test_list.py b/mojo/tools/get_test_list.py index ed53a878ff0..47f292cc927 100755 --- a/mojo/tools/get_test_list.py +++ b/mojo/tools/get_test_list.py @@ -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): diff --git a/sky/tools/roll/mojo_dart_embedder.patch b/sky/tools/roll/mojo_dart_embedder.patch new file mode 100644 index 00000000000..a243e78bcb8 --- /dev/null +++ b/sky/tools/roll/mojo_dart_embedder.patch @@ -0,0 +1,12 @@ +diff --git a/mojo/dart/embedder/BUILD.gn b/mojo/dart/embedder/BUILD.gn +index 97a4ee2..6764873 100644 +--- a/mojo/dart/embedder/BUILD.gn ++++ b/mojo/dart/embedder/BUILD.gn +@@ -47,7 +47,6 @@ source_set("dart_controller_no_snapshot") { + "//mojo/public/c/system", + "//mojo/public/cpp/system", + "//mojo/services/network/public/interfaces", +- "//tonic", + ] + + defines = []