From 7ec0061a32e822d7917a1e9ca7c5020bf366c938 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 26 May 2016 13:36:42 -0700 Subject: [PATCH 1/2] Update to mojo 7d579155cc597aa3befcbfad66eef54bda06b57c --- DEPS | 2 +- mojo/VERSION | 2 +- .../application_runner_chromium.cc | 3 +- mojo/application/content_handler_factory.cc | 20 +- mojo/application/content_handler_factory.h | 22 +- mojo/common/BUILD.gn | 11 +- mojo/common/trace_provider_impl.cc | 1 - mojo/dart/packages/mojo/CHANGELOG.md | 18 + mojo/dart/packages/mojo/lib/bindings.dart | 1 + mojo/dart/packages/mojo/lib/core.dart | 7 +- .../mojo/lib/mojo/application.mojom.dart | 259 +++---- .../lib/mojo/application_connector.mojom.dart | 233 ++++--- .../bindings/types/mojom_files.mojom.dart | 33 +- .../bindings/types/mojom_types.mojom.dart | 312 ++++----- .../types/service_describer.mojom.dart | 441 ++++++------ .../mojo/lib/mojo/service_provider.mojom.dart | 205 +++--- .../packages/mojo/lib/mojo/shell.mojom.dart | 233 ++++--- .../packages/mojo/lib/src/application.dart | 32 +- .../mojo/lib/src/application_connection.dart | 30 +- mojo/dart/packages/mojo/lib/src/buffer.dart | 3 +- mojo/dart/packages/mojo/lib/src/codec.dart | 67 +- .../mojo/lib/src/control_message.dart | 20 +- .../{event_stream.dart => event_handler.dart} | 189 +----- .../mojo/lib/src/event_subscription.dart | 129 ++++ mojo/dart/packages/mojo/lib/src/handle.dart | 8 +- .../packages/mojo/lib/src/interfaces.dart | 23 + mojo/dart/packages/mojo/lib/src/internal.dart | 10 + .../mojo/lib/src/internal_contract.dart | 637 ++++++++++++++++++ .../packages/mojo/lib/src/message_pipe.dart | 4 +- mojo/dart/packages/mojo/lib/src/proxy.dart | 104 ++- mojo/dart/packages/mojo/lib/src/stub.dart | 107 ++- mojo/dart/packages/mojo/pubspec.yaml | 2 +- .../mojo/sdk_ext/src/handle_watcher.dart | 56 -- .../packages/mojo/sdk_ext/src/natives.dart | 409 ----------- mojo/dart/packages/mojo/sources.gni | 6 +- .../packages/mojo/test/standalone_test.dart | 27 + mojo/data_pipe_utils/BUILD.gn | 6 +- mojo/edk/embedder/embedder.cc | 13 +- mojo/edk/embedder/entrypoints.cc | 17 + .../system_impl_private_entrypoints.cc | 45 +- mojo/edk/system/channel.cc | 2 +- mojo/edk/system/core.cc | 174 +++-- mojo/edk/system/core.h | 45 +- mojo/edk/system/core_test_base.cc | 32 +- mojo/edk/system/core_test_base.h | 13 +- mojo/edk/system/core_unittest.cc | 162 ++++- .../system/data_pipe_consumer_dispatcher.cc | 3 +- .../system/data_pipe_consumer_dispatcher.h | 2 +- mojo/edk/system/data_pipe_impl_unittest.cc | 2 +- .../system/data_pipe_producer_dispatcher.h | 4 +- mojo/edk/system/dispatcher.cc | 20 + mojo/edk/system/dispatcher.h | 12 + mojo/edk/system/dispatcher_unittest.cc | 13 + mojo/edk/system/entrypoint_class.h | 4 + mojo/edk/system/handle.h | 4 + mojo/edk/system/handle_unittest.cc | 45 ++ mojo/edk/system/message_in_transit.cc | 14 +- mojo/edk/system/message_in_transit.h | 3 - mojo/edk/system/message_pipe_dispatcher.cc | 3 +- mojo/edk/system/message_pipe_dispatcher.h | 3 +- .../message_pipe_dispatcher_unittest.cc | 1 + mojo/edk/system/message_pipe_endpoint.h | 1 + mojo/edk/system/message_pipe_test_utils.h | 1 + mojo/edk/system/mock_simple_dispatcher.cc | 8 +- mojo/edk/system/mock_simple_dispatcher.h | 2 + .../multiprocess_message_pipe_unittest.cc | 5 +- mojo/edk/system/platform_handle_dispatcher.cc | 2 +- .../platform_handle_dispatcher_unittest.cc | 1 + .../system/remote_data_pipe_impl_unittest.cc | 9 +- .../system/remote_message_pipe_unittest.cc | 18 +- mojo/edk/system/shared_buffer_dispatcher.cc | 12 +- mojo/edk/system/shared_buffer_dispatcher.h | 7 +- .../shared_buffer_dispatcher_unittest.cc | 44 ++ mojo/edk/system/transport_data.cc | 56 +- mojo/edk/system/transport_data.h | 11 +- mojo/environment/environment.cc | 29 +- mojo/icu/icu.cc | 5 +- mojo/icu/icu.h | 4 +- mojo/message_pump/BUILD.gn | 8 +- .../files/c/tests/mojio_impl_test_base.cc | 4 +- .../composition/interfaces/renderers.mojom | 4 + .../gfx/composition/interfaces/scenes.mojom | 8 +- .../composition/interfaces/scheduling.mojom | 19 +- mojo/services/log/cpp/log_client.h | 17 +- .../core/interfaces/seeking_reader.mojom | 1 - .../native_viewport_event_dispatcher.mojom | 1 - .../ui/views/interfaces/view_associates.mojom | 14 +- .../ui/views/interfaces/view_manager.mojom | 26 + mojo/skia/ganesh_image_factory.cc | 2 +- 89 files changed, 2803 insertions(+), 1824 deletions(-) rename mojo/dart/packages/mojo/lib/src/{event_stream.dart => event_handler.dart} (61%) create mode 100644 mojo/dart/packages/mojo/lib/src/event_subscription.dart create mode 100644 mojo/dart/packages/mojo/lib/src/interfaces.dart create mode 100644 mojo/dart/packages/mojo/lib/src/internal.dart create mode 100644 mojo/dart/packages/mojo/lib/src/internal_contract.dart create mode 100644 mojo/dart/packages/mojo/test/standalone_test.dart diff --git a/DEPS b/DEPS index ea24ccbb48d33..54e903eccdb62 100644 --- a/DEPS +++ b/DEPS @@ -19,7 +19,7 @@ vars = { 'chromium_git': 'https://chromium.googlesource.com', - 'mojo_sdk_revision': '55352570f8c52ca1282dcfa26a4a32adc08495d6', + 'mojo_sdk_revision': 'fbe912aa65e0346382bc1e2874eb88fa3aad3358', 'base_revision': '672b04e54b937ec899429a6bd5409c5a6300d151', 'skia_revision': '8cc209111876b7c78b5ec577c9221d8ed5e21024', diff --git a/mojo/VERSION b/mojo/VERSION index 26ad926d185fa..61841886ceb9c 100644 --- a/mojo/VERSION +++ b/mojo/VERSION @@ -1 +1 @@ -9a791294e429f9f2ca4f427796a284edb6f6768e \ No newline at end of file +7d579155cc597aa3befcbfad66eef54bda06b57c \ No newline at end of file diff --git a/mojo/application/application_runner_chromium.cc b/mojo/application/application_runner_chromium.cc index b52803476b4f8..7a4635e9b6c38 100644 --- a/mojo/application/application_runner_chromium.cc +++ b/mojo/application/application_runner_chromium.cc @@ -11,13 +11,14 @@ #include "mojo/message_pump/message_pump_mojo.h" #include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/application_impl_base.h" #include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/message_pipe.h" namespace mojo { // static -void ApplicationImpl::Terminate() { +void ApplicationImplBase::Terminate() { if (base::MessageLoop::current()->is_running()) base::MessageLoop::current()->Quit(); } diff --git a/mojo/application/content_handler_factory.cc b/mojo/application/content_handler_factory.cc index a8c3b92027f47..e27996adfa92b 100644 --- a/mojo/application/content_handler_factory.cc +++ b/mojo/application/content_handler_factory.cc @@ -4,7 +4,7 @@ #include "mojo/application/content_handler_factory.h" -#include +#include #include "base/bind.h" #include "base/callback.h" @@ -14,7 +14,6 @@ #include "base/trace_event/trace_event.h" #include "mojo/application/application_runner_chromium.h" #include "mojo/message_pump/message_pump_mojo.h" -#include "mojo/public/cpp/application/application_connection.h" #include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" #include "mojo/public/cpp/bindings/strong_binding.h" @@ -112,11 +111,13 @@ class ContentHandlerImpl : public ContentHandler { } // namespace -ContentHandlerFactory::ContentHandlerFactory(Delegate* delegate) - : delegate_(delegate) { -} - -ContentHandlerFactory::~ContentHandlerFactory() { +// static +ServiceProviderImpl::InterfaceRequestHandler +ContentHandlerFactory::GetInterfaceRequestHandler(Delegate* delegate) { + return [delegate](const ConnectionContext& connection_context, + InterfaceRequest content_handler_request) { + new ContentHandlerImpl(delegate, content_handler_request.Pass()); + }; } void ContentHandlerFactory::ManagedDelegate::RunApplication( @@ -129,9 +130,4 @@ void ContentHandlerFactory::ManagedDelegate::RunApplication( loop.Run(); } -void ContentHandlerFactory::Create(ApplicationConnection* connection, - InterfaceRequest request) { - new ContentHandlerImpl(delegate_, request.Pass()); -} - } // namespace mojo diff --git a/mojo/application/content_handler_factory.h b/mojo/application/content_handler_factory.h index be472075cba83..b1ebccccb493e 100644 --- a/mojo/application/content_handler_factory.h +++ b/mojo/application/content_handler_factory.h @@ -6,14 +6,18 @@ #define MOJO_APPLICATION_CONTENT_HANDLER_FACTORY_H_ #include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/application/interface_factory.h" +#include "mojo/public/cpp/application/service_provider_impl.h" #include "mojo/public/interfaces/application/shell.mojom.h" #include "mojo/services/content_handler/interfaces/content_handler.mojom.h" #include "mojo/services/network/interfaces/url_loader.mojom.h" namespace mojo { -class ContentHandlerFactory : public InterfaceFactory { +struct ConnectionContext; + +// TODO(vtl): Nuke this class. Now it's only a "namespace" for stuff, most of +// which is overcomplicated. +class ContentHandlerFactory { public: class HandledApplicationHolder { public: @@ -46,17 +50,9 @@ class ContentHandlerFactory : public InterfaceFactory { URLResponsePtr response) override; }; - explicit ContentHandlerFactory(Delegate* delegate); - ~ContentHandlerFactory() override; - - private: - // From InterfaceFactory: - void Create(ApplicationConnection* connection, - InterfaceRequest request) override; - - Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(ContentHandlerFactory); + // For use with |ServiceProviderImpl::AddService()|. + static ServiceProviderImpl::InterfaceRequestHandler + GetInterfaceRequestHandler(Delegate* delegate); }; template diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn index 3410af218085d..527c4a133467e 100644 --- a/mojo/common/BUILD.gn +++ b/mojo/common/BUILD.gn @@ -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("//mojo/public/mojo_application.gni") import("//mojo/public/tools/bindings/mojom.gni") import("//testing/test.gni") @@ -40,13 +41,13 @@ source_set("tests") { ] } -test("mojo_common_unittests") { +mojo_native_application("mojo_common_apptests") { + testonly = true + deps = [ ":tests", - "//mojo/data_pipe_utils:tests", - "//mojo/edk/test:run_all_unittests", - "//mojo/environment:chromium", - "//mojo/message_pump:tests", + "//mojo/application", + "//mojo/application:test_support", ] } diff --git a/mojo/common/trace_provider_impl.cc b/mojo/common/trace_provider_impl.cc index cda6b6195d721..2139b7c4a6ede 100644 --- a/mojo/common/trace_provider_impl.cc +++ b/mojo/common/trace_provider_impl.cc @@ -12,7 +12,6 @@ #include "base/time/time.h" #include "base/trace_event/trace_config.h" #include "base/trace_event/trace_event.h" -#include "mojo/public/cpp/application/application_connection.h" #include "mojo/public/cpp/application/application_impl.h" namespace mojo { diff --git a/mojo/dart/packages/mojo/CHANGELOG.md b/mojo/dart/packages/mojo/CHANGELOG.md index 45796583752aa..dc12ca26b201d 100644 --- a/mojo/dart/packages/mojo/CHANGELOG.md +++ b/mojo/dart/packages/mojo/CHANGELOG.md @@ -1,3 +1,21 @@ +## 0.4.23 + + - 28 changes: https://github.com/domokit/mojo/compare/107bac0...ef5cd66 + + MOJO_SDK: ef5cd660ec6f1c50eaff62c81ea7662662d04e15 + +## 0.4.22 + + - 22 changes: https://github.com/domokit/mojo/compare/12d71ee...f56fd59 + + MOJO_SDK: f56fd59ec51e1ecdd52fb848ceff1b6b6fe7f7fa + +## 0.4.21 + + - 35 changes: https://github.com/domokit/mojo/compare/e95b5db...c200560 + + MOJO_SDK: c200560ac45a79b61b8e8c0444af471789f5669f + ## 0.4.20 - 125 changes: https://github.com/domokit/mojo/compare/2f662f4...705723c diff --git a/mojo/dart/packages/mojo/lib/bindings.dart b/mojo/dart/packages/mojo/lib/bindings.dart index 24c12bf98f3ed..d60480370504a 100644 --- a/mojo/dart/packages/mojo/lib/bindings.dart +++ b/mojo/dart/packages/mojo/lib/bindings.dart @@ -17,6 +17,7 @@ import 'package:mojo/mojo/bindings/types/service_describer.mojom.dart' part 'src/control_message.dart'; part 'src/codec.dart'; part 'src/enum.dart'; +part 'src/interfaces.dart'; part 'src/message.dart'; part 'src/proxy.dart'; part 'src/struct.dart'; diff --git a/mojo/dart/packages/mojo/lib/core.dart b/mojo/dart/packages/mojo/lib/core.dart index d504d0fc6b9fa..19dae70e0e6ea 100644 --- a/mojo/dart/packages/mojo/lib/core.dart +++ b/mojo/dart/packages/mojo/lib/core.dart @@ -5,15 +5,16 @@ library core; import 'dart:async'; -import 'dart:collection'; import 'dart:isolate'; -import 'dart:mojo.internal'; import 'dart:typed_data'; +import 'src/internal.dart'; + part 'src/buffer.dart'; part 'src/data_pipe.dart'; part 'src/drain_data.dart'; -part 'src/event_stream.dart'; +part 'src/event_subscription.dart'; +part 'src/event_handler.dart'; part 'src/fill_data.dart'; part 'src/handle.dart'; part 'src/message_pipe.dart'; diff --git a/mojo/dart/packages/mojo/lib/mojo/application.mojom.dart b/mojo/dart/packages/mojo/lib/mojo/application.mojom.dart index 2eaf40c6c8bb7..8830c277fa5af 100644 --- a/mojo/dart/packages/mojo/lib/mojo/application.mojom.dart +++ b/mojo/dart/packages/mojo/lib/mojo/application.mojom.dart @@ -16,7 +16,7 @@ class _ApplicationInitializeParams extends bindings.Struct { static const List kVersions = const [ const bindings.StructDataHeader(32, 0) ]; - Object shell = null; + shell_mojom.ShellInterface shell = null; List args = null; String url = null; @@ -131,8 +131,8 @@ class _ApplicationAcceptConnectionParams extends bindings.Struct { const bindings.StructDataHeader(40, 0) ]; String requestorUrl = null; - Object services = null; - Object exposedServices = null; + service_provider_mojom.ServiceProviderInterfaceRequest services = null; + service_provider_mojom.ServiceProviderInterface exposedServices = null; String resolvedUrl = null; _ApplicationAcceptConnectionParams() : super(kVersions.last.size); @@ -310,29 +310,61 @@ class _ApplicationServiceDescription implements service_describer.ServiceDescrip abstract class Application { static const String serviceName = null; - void initialize(Object shell, List args, String url); - void acceptConnection(String requestorUrl, Object services, Object exposedServices, String resolvedUrl); + + static service_describer.ServiceDescription _cachedServiceDescription; + static service_describer.ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _ApplicationServiceDescription(); + } + return _cachedServiceDescription; + } + + static ApplicationProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + ApplicationProxy p = new ApplicationProxy.unbound(); + String name = serviceName ?? Application.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } + void initialize(shell_mojom.ShellInterface shell, List args, String url); + void acceptConnection(String requestorUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices, String resolvedUrl); void requestQuit(); } +abstract class ApplicationInterface + implements bindings.MojoInterface, + Application { + factory ApplicationInterface([Application impl]) => + new ApplicationStub.unbound(impl); + factory ApplicationInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [Application impl]) => + new ApplicationStub.fromEndpoint(endpoint, impl); +} -class _ApplicationProxyImpl extends bindings.Proxy { - _ApplicationProxyImpl.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); +abstract class ApplicationInterfaceRequest + implements bindings.MojoInterface, + Application { + factory ApplicationInterfaceRequest() => + new ApplicationProxy.unbound(); +} - _ApplicationProxyImpl.fromHandle(core.MojoHandle handle) : - super.fromHandle(handle); +class _ApplicationProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl { + _ApplicationProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); - _ApplicationProxyImpl.unbound() : super.unbound(); + _ApplicationProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); - static _ApplicationProxyImpl newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For _ApplicationProxyImpl")); - return new _ApplicationProxyImpl.fromEndpoint(endpoint); - } + _ApplicationProxyControl.unbound() : super.unbound(); - service_describer.ServiceDescription get serviceDescription => - new _ApplicationServiceDescription(); + String get serviceName => Application.serviceName; void handleResponse(bindings.ServiceMessage message) { switch (message.header.type) { @@ -343,81 +375,32 @@ class _ApplicationProxyImpl extends bindings.Proxy { } } + Application get impl => null; + set impl(Application _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override String toString() { var superString = super.toString(); - return "_ApplicationProxyImpl($superString)"; + return "_ApplicationProxyControl($superString)"; } } - -class _ApplicationProxyCalls implements Application { - _ApplicationProxyImpl _proxyImpl; - - _ApplicationProxyCalls(this._proxyImpl); - void initialize(Object shell, List args, String url) { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ApplicationInitializeParams(); - params.shell = shell; - params.args = args; - params.url = url; - _proxyImpl.sendMessage(params, _applicationMethodInitializeName); - } - void acceptConnection(String requestorUrl, Object services, Object exposedServices, String resolvedUrl) { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ApplicationAcceptConnectionParams(); - params.requestorUrl = requestorUrl; - params.services = services; - params.exposedServices = exposedServices; - params.resolvedUrl = resolvedUrl; - _proxyImpl.sendMessage(params, _applicationMethodAcceptConnectionName); - } - void requestQuit() { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ApplicationRequestQuitParams(); - _proxyImpl.sendMessage(params, _applicationMethodRequestQuitName); - } -} - - -class ApplicationProxy implements bindings.ProxyBase { - final bindings.Proxy impl; - Application ptr; - - ApplicationProxy(_ApplicationProxyImpl proxyImpl) : - impl = proxyImpl, - ptr = new _ApplicationProxyCalls(proxyImpl); - +class ApplicationProxy + extends bindings.Proxy + implements Application, + ApplicationInterface, + ApplicationInterfaceRequest { ApplicationProxy.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : - impl = new _ApplicationProxyImpl.fromEndpoint(endpoint) { - ptr = new _ApplicationProxyCalls(impl); - } + core.MojoMessagePipeEndpoint endpoint) + : super(new _ApplicationProxyControl.fromEndpoint(endpoint)); - ApplicationProxy.fromHandle(core.MojoHandle handle) : - impl = new _ApplicationProxyImpl.fromHandle(handle) { - ptr = new _ApplicationProxyCalls(impl); - } + ApplicationProxy.fromHandle(core.MojoHandle handle) + : super(new _ApplicationProxyControl.fromHandle(handle)); - ApplicationProxy.unbound() : - impl = new _ApplicationProxyImpl.unbound() { - ptr = new _ApplicationProxyCalls(impl); - } - - factory ApplicationProxy.connectToService( - bindings.ServiceConnector s, String url, [String serviceName]) { - ApplicationProxy p = new ApplicationProxy.unbound(); - s.connectToService(url, p, serviceName); - return p; - } + ApplicationProxy.unbound() + : super(new _ApplicationProxyControl.unbound()); static ApplicationProxy newFromEndpoint( core.MojoMessagePipeEndpoint endpoint) { @@ -425,50 +408,63 @@ class ApplicationProxy implements bindings.ProxyBase { return new ApplicationProxy.fromEndpoint(endpoint); } - String get serviceName => Application.serviceName; - - Future close({bool immediate: false}) => impl.close(immediate: immediate); - - Future responseOrError(Future f) => impl.responseOrError(f); - - Future get errorFuture => impl.errorFuture; - int get version => impl.version; - - Future queryVersion() => impl.queryVersion(); - - void requireVersion(int requiredVersion) { - impl.requireVersion(requiredVersion); + void initialize(shell_mojom.ShellInterface shell, List args, String url) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ApplicationInitializeParams(); + params.shell = shell; + params.args = args; + params.url = url; + ctrl.sendMessage(params, + _applicationMethodInitializeName); } - - String toString() { - return "ApplicationProxy($impl)"; + void acceptConnection(String requestorUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices, String resolvedUrl) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ApplicationAcceptConnectionParams(); + params.requestorUrl = requestorUrl; + params.services = services; + params.exposedServices = exposedServices; + params.resolvedUrl = resolvedUrl; + ctrl.sendMessage(params, + _applicationMethodAcceptConnectionName); + } + void requestQuit() { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ApplicationRequestQuitParams(); + ctrl.sendMessage(params, + _applicationMethodRequestQuitName); } } - -class ApplicationStub extends bindings.Stub { +class _ApplicationStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl { Application _impl; - ApplicationStub.fromEndpoint( + _ApplicationStubControl.fromEndpoint( core.MojoMessagePipeEndpoint endpoint, [Application impl]) : super.fromEndpoint(endpoint, autoBegin: impl != null) { _impl = impl; } - ApplicationStub.fromHandle( + _ApplicationStubControl.fromHandle( core.MojoHandle handle, [Application impl]) : super.fromHandle(handle, autoBegin: impl != null) { _impl = impl; } - ApplicationStub.unbound() : super.unbound(); + _ApplicationStubControl.unbound([this._impl]) : super.unbound(); - static ApplicationStub newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For ApplicationStub")); - return new ApplicationStub.fromEndpoint(endpoint); - } + String get serviceName => Application.serviceName; @@ -521,19 +517,46 @@ class ApplicationStub extends bindings.Stub { } } + @override String toString() { var superString = super.toString(); - return "ApplicationStub($superString)"; + return "_ApplicationStubControl($superString)"; } int get version => 0; +} - static service_describer.ServiceDescription _cachedServiceDescription; - static service_describer.ServiceDescription get serviceDescription { - if (_cachedServiceDescription == null) { - _cachedServiceDescription = new _ApplicationServiceDescription(); - } - return _cachedServiceDescription; +class ApplicationStub + extends bindings.Stub + implements Application, + ApplicationInterface, + ApplicationInterfaceRequest { + ApplicationStub.unbound([Application impl]) + : super(new _ApplicationStubControl.unbound(impl)); + + ApplicationStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [Application impl]) + : super(new _ApplicationStubControl.fromEndpoint(endpoint, impl)); + + ApplicationStub.fromHandle( + core.MojoHandle handle, [Application impl]) + : super(new _ApplicationStubControl.fromHandle(handle, impl)); + + static ApplicationStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For ApplicationStub")); + return new ApplicationStub.fromEndpoint(endpoint); + } + + + void initialize(shell_mojom.ShellInterface shell, List args, String url) { + return impl.initialize(shell, args, url); + } + void acceptConnection(String requestorUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices, String resolvedUrl) { + return impl.acceptConnection(requestorUrl, services, exposedServices, resolvedUrl); + } + void requestQuit() { + return impl.requestQuit(); } } diff --git a/mojo/dart/packages/mojo/lib/mojo/application_connector.mojom.dart b/mojo/dart/packages/mojo/lib/mojo/application_connector.mojom.dart index c4653baba388a..289f257b56e99 100644 --- a/mojo/dart/packages/mojo/lib/mojo/application_connector.mojom.dart +++ b/mojo/dart/packages/mojo/lib/mojo/application_connector.mojom.dart @@ -16,8 +16,8 @@ class _ApplicationConnectorConnectToApplicationParams extends bindings.Struct { const bindings.StructDataHeader(32, 0) ]; String applicationUrl = null; - Object services = null; - Object exposedServices = null; + service_provider_mojom.ServiceProviderInterfaceRequest services = null; + service_provider_mojom.ServiceProviderInterface exposedServices = null; _ApplicationConnectorConnectToApplicationParams() : super(kVersions.last.size); @@ -112,7 +112,7 @@ class _ApplicationConnectorDuplicateParams extends bindings.Struct { static const List kVersions = const [ const bindings.StructDataHeader(16, 0) ]; - Object applicationConnectorRequest = null; + ApplicationConnectorInterfaceRequest applicationConnectorRequest = null; _ApplicationConnectorDuplicateParams() : super(kVersions.last.size); @@ -194,28 +194,60 @@ class _ApplicationConnectorServiceDescription implements service_describer.Servi abstract class ApplicationConnector { static const String serviceName = null; - void connectToApplication(String applicationUrl, Object services, Object exposedServices); - void duplicate(Object applicationConnectorRequest); + + static service_describer.ServiceDescription _cachedServiceDescription; + static service_describer.ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _ApplicationConnectorServiceDescription(); + } + return _cachedServiceDescription; + } + + static ApplicationConnectorProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + ApplicationConnectorProxy p = new ApplicationConnectorProxy.unbound(); + String name = serviceName ?? ApplicationConnector.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } + void connectToApplication(String applicationUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices); + void duplicate(ApplicationConnectorInterfaceRequest applicationConnectorRequest); } +abstract class ApplicationConnectorInterface + implements bindings.MojoInterface, + ApplicationConnector { + factory ApplicationConnectorInterface([ApplicationConnector impl]) => + new ApplicationConnectorStub.unbound(impl); + factory ApplicationConnectorInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [ApplicationConnector impl]) => + new ApplicationConnectorStub.fromEndpoint(endpoint, impl); +} -class _ApplicationConnectorProxyImpl extends bindings.Proxy { - _ApplicationConnectorProxyImpl.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); +abstract class ApplicationConnectorInterfaceRequest + implements bindings.MojoInterface, + ApplicationConnector { + factory ApplicationConnectorInterfaceRequest() => + new ApplicationConnectorProxy.unbound(); +} - _ApplicationConnectorProxyImpl.fromHandle(core.MojoHandle handle) : - super.fromHandle(handle); +class _ApplicationConnectorProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl { + _ApplicationConnectorProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); - _ApplicationConnectorProxyImpl.unbound() : super.unbound(); + _ApplicationConnectorProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); - static _ApplicationConnectorProxyImpl newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For _ApplicationConnectorProxyImpl")); - return new _ApplicationConnectorProxyImpl.fromEndpoint(endpoint); - } + _ApplicationConnectorProxyControl.unbound() : super.unbound(); - service_describer.ServiceDescription get serviceDescription => - new _ApplicationConnectorServiceDescription(); + String get serviceName => ApplicationConnector.serviceName; void handleResponse(bindings.ServiceMessage message) { switch (message.header.type) { @@ -226,70 +258,32 @@ class _ApplicationConnectorProxyImpl extends bindings.Proxy { } } + ApplicationConnector get impl => null; + set impl(ApplicationConnector _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override String toString() { var superString = super.toString(); - return "_ApplicationConnectorProxyImpl($superString)"; + return "_ApplicationConnectorProxyControl($superString)"; } } - -class _ApplicationConnectorProxyCalls implements ApplicationConnector { - _ApplicationConnectorProxyImpl _proxyImpl; - - _ApplicationConnectorProxyCalls(this._proxyImpl); - void connectToApplication(String applicationUrl, Object services, Object exposedServices) { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ApplicationConnectorConnectToApplicationParams(); - params.applicationUrl = applicationUrl; - params.services = services; - params.exposedServices = exposedServices; - _proxyImpl.sendMessage(params, _applicationConnectorMethodConnectToApplicationName); - } - void duplicate(Object applicationConnectorRequest) { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ApplicationConnectorDuplicateParams(); - params.applicationConnectorRequest = applicationConnectorRequest; - _proxyImpl.sendMessage(params, _applicationConnectorMethodDuplicateName); - } -} - - -class ApplicationConnectorProxy implements bindings.ProxyBase { - final bindings.Proxy impl; - ApplicationConnector ptr; - - ApplicationConnectorProxy(_ApplicationConnectorProxyImpl proxyImpl) : - impl = proxyImpl, - ptr = new _ApplicationConnectorProxyCalls(proxyImpl); - +class ApplicationConnectorProxy + extends bindings.Proxy + implements ApplicationConnector, + ApplicationConnectorInterface, + ApplicationConnectorInterfaceRequest { ApplicationConnectorProxy.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : - impl = new _ApplicationConnectorProxyImpl.fromEndpoint(endpoint) { - ptr = new _ApplicationConnectorProxyCalls(impl); - } - - ApplicationConnectorProxy.fromHandle(core.MojoHandle handle) : - impl = new _ApplicationConnectorProxyImpl.fromHandle(handle) { - ptr = new _ApplicationConnectorProxyCalls(impl); - } + core.MojoMessagePipeEndpoint endpoint) + : super(new _ApplicationConnectorProxyControl.fromEndpoint(endpoint)); - ApplicationConnectorProxy.unbound() : - impl = new _ApplicationConnectorProxyImpl.unbound() { - ptr = new _ApplicationConnectorProxyCalls(impl); - } + ApplicationConnectorProxy.fromHandle(core.MojoHandle handle) + : super(new _ApplicationConnectorProxyControl.fromHandle(handle)); - factory ApplicationConnectorProxy.connectToService( - bindings.ServiceConnector s, String url, [String serviceName]) { - ApplicationConnectorProxy p = new ApplicationConnectorProxy.unbound(); - s.connectToService(url, p, serviceName); - return p; - } + ApplicationConnectorProxy.unbound() + : super(new _ApplicationConnectorProxyControl.unbound()); static ApplicationConnectorProxy newFromEndpoint( core.MojoMessagePipeEndpoint endpoint) { @@ -297,50 +291,51 @@ class ApplicationConnectorProxy implements bindings.ProxyBase { return new ApplicationConnectorProxy.fromEndpoint(endpoint); } - String get serviceName => ApplicationConnector.serviceName; - - Future close({bool immediate: false}) => impl.close(immediate: immediate); - - Future responseOrError(Future f) => impl.responseOrError(f); - - Future get errorFuture => impl.errorFuture; - - int get version => impl.version; - - Future queryVersion() => impl.queryVersion(); - void requireVersion(int requiredVersion) { - impl.requireVersion(requiredVersion); + void connectToApplication(String applicationUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ApplicationConnectorConnectToApplicationParams(); + params.applicationUrl = applicationUrl; + params.services = services; + params.exposedServices = exposedServices; + ctrl.sendMessage(params, + _applicationConnectorMethodConnectToApplicationName); } - - String toString() { - return "ApplicationConnectorProxy($impl)"; + void duplicate(ApplicationConnectorInterfaceRequest applicationConnectorRequest) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ApplicationConnectorDuplicateParams(); + params.applicationConnectorRequest = applicationConnectorRequest; + ctrl.sendMessage(params, + _applicationConnectorMethodDuplicateName); } } - -class ApplicationConnectorStub extends bindings.Stub { +class _ApplicationConnectorStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl { ApplicationConnector _impl; - ApplicationConnectorStub.fromEndpoint( + _ApplicationConnectorStubControl.fromEndpoint( core.MojoMessagePipeEndpoint endpoint, [ApplicationConnector impl]) : super.fromEndpoint(endpoint, autoBegin: impl != null) { _impl = impl; } - ApplicationConnectorStub.fromHandle( + _ApplicationConnectorStubControl.fromHandle( core.MojoHandle handle, [ApplicationConnector impl]) : super.fromHandle(handle, autoBegin: impl != null) { _impl = impl; } - ApplicationConnectorStub.unbound() : super.unbound(); + _ApplicationConnectorStubControl.unbound([this._impl]) : super.unbound(); - static ApplicationConnectorStub newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For ApplicationConnectorStub")); - return new ApplicationConnectorStub.fromEndpoint(endpoint); - } + String get serviceName => ApplicationConnector.serviceName; @@ -390,19 +385,43 @@ class ApplicationConnectorStub extends bindings.Stub { } } + @override String toString() { var superString = super.toString(); - return "ApplicationConnectorStub($superString)"; + return "_ApplicationConnectorStubControl($superString)"; } int get version => 0; +} - static service_describer.ServiceDescription _cachedServiceDescription; - static service_describer.ServiceDescription get serviceDescription { - if (_cachedServiceDescription == null) { - _cachedServiceDescription = new _ApplicationConnectorServiceDescription(); - } - return _cachedServiceDescription; +class ApplicationConnectorStub + extends bindings.Stub + implements ApplicationConnector, + ApplicationConnectorInterface, + ApplicationConnectorInterfaceRequest { + ApplicationConnectorStub.unbound([ApplicationConnector impl]) + : super(new _ApplicationConnectorStubControl.unbound(impl)); + + ApplicationConnectorStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [ApplicationConnector impl]) + : super(new _ApplicationConnectorStubControl.fromEndpoint(endpoint, impl)); + + ApplicationConnectorStub.fromHandle( + core.MojoHandle handle, [ApplicationConnector impl]) + : super(new _ApplicationConnectorStubControl.fromHandle(handle, impl)); + + static ApplicationConnectorStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For ApplicationConnectorStub")); + return new ApplicationConnectorStub.fromEndpoint(endpoint); + } + + + void connectToApplication(String applicationUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices) { + return impl.connectToApplication(applicationUrl, services, exposedServices); + } + void duplicate(ApplicationConnectorInterfaceRequest applicationConnectorRequest) { + return impl.duplicate(applicationConnectorRequest); } } diff --git a/mojo/dart/packages/mojo/lib/mojo/bindings/types/mojom_files.mojom.dart b/mojo/dart/packages/mojo/lib/mojo/bindings/types/mojom_files.mojom.dart index bccd03912c594..ade7eb4c7e0c0 100644 --- a/mojo/dart/packages/mojo/lib/mojo/bindings/types/mojom_files.mojom.dart +++ b/mojo/dart/packages/mojo/lib/mojo/bindings/types/mojom_files.mojom.dart @@ -207,7 +207,7 @@ class MojomFileGraph extends bindings.Struct { ]; Map files = null; Map resolvedTypes = null; - Map resolvedValues = null; + Map resolvedConstants = null; MojomFileGraph() : super(kVersions.last.size); @@ -325,7 +325,7 @@ class MojomFileGraph extends bindings.Struct { { decoder1.decodeDataHeaderForMap(); List keys0; - List values0; + List values0; { var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize, false); @@ -342,19 +342,16 @@ class MojomFileGraph extends bindings.Struct { var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize, false); { - var si2 = decoder2.decodeDataHeaderForUnionArray(keys0.length); - values0 = new List(si2.numElements); + var si2 = decoder2.decodeDataHeaderForPointerArray(keys0.length); + values0 = new List(si2.numElements); for (int i2 = 0; i2 < si2.numElements; ++i2) { - values0[i2] = mojom_types_mojom.UserDefinedValue.decode(decoder2, bindings.ArrayDataHeader.kHeaderSize + bindings.kUnionSize * i2); - if (values0[i2] == null) { - throw new bindings.MojoCodecError( - 'Trying to decode null union for non-nullable mojom_types_mojom.UserDefinedValue.'); - } + var decoder3 = decoder2.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i2, false); + values0[i2] = mojom_types_mojom.DeclaredConstant.decode(decoder3); } } } - result.resolvedValues = new Map.fromIterables( + result.resolvedConstants = new Map.fromIterables( keys0, values0); } } @@ -418,12 +415,12 @@ class MojomFileGraph extends bindings.Struct { rethrow; } try { - if (resolvedValues == null) { + if (resolvedConstants == null) { encoder0.encodeNullPointer(24, false); } else { var encoder1 = encoder0.encoderForMap(24); - var keys0 = resolvedValues.keys.toList(); - var values0 = resolvedValues.values.toList(); + var keys0 = resolvedConstants.keys.toList(); + var values0 = resolvedConstants.values.toList(); { var encoder2 = encoder1.encodePointerArray(keys0.length, bindings.ArrayDataHeader.kHeaderSize, bindings.kUnspecifiedArrayLength); @@ -433,15 +430,15 @@ class MojomFileGraph extends bindings.Struct { } { - var encoder2 = encoder1.encodeUnionArray(values0.length, bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize, bindings.kUnspecifiedArrayLength); + var encoder2 = encoder1.encodePointerArray(values0.length, bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize, bindings.kUnspecifiedArrayLength); for (int i1 = 0; i1 < values0.length; ++i1) { - encoder2.encodeUnion(values0[i1], bindings.ArrayDataHeader.kHeaderSize + bindings.kUnionSize * i1, false); + encoder2.encodeStruct(values0[i1], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false); } } } } on bindings.MojoCodecError catch(e) { e.message = "Error encountered while encoding field " - "resolvedValues of struct MojomFileGraph: $e"; + "resolvedConstants of struct MojomFileGraph: $e"; rethrow; } } @@ -450,14 +447,14 @@ class MojomFileGraph extends bindings.Struct { return "MojomFileGraph(" "files: $files" ", " "resolvedTypes: $resolvedTypes" ", " - "resolvedValues: $resolvedValues" ")"; + "resolvedConstants: $resolvedConstants" ")"; } Map toJson() { Map map = new Map(); map["files"] = files; map["resolvedTypes"] = resolvedTypes; - map["resolvedValues"] = resolvedValues; + map["resolvedConstants"] = resolvedConstants; return map; } } diff --git a/mojo/dart/packages/mojo/lib/mojo/bindings/types/mojom_types.mojom.dart b/mojo/dart/packages/mojo/lib/mojo/bindings/types/mojom_types.mojom.dart index f98a5a6ba6c3e..4ef15b2ad8001 100644 --- a/mojo/dart/packages/mojo/lib/mojo/bindings/types/mojom_types.mojom.dart +++ b/mojo/dart/packages/mojo/lib/mojo/bindings/types/mojom_types.mojom.dart @@ -1414,10 +1414,9 @@ class MojomUnion extends bindings.Struct { class EnumValue extends bindings.Struct { static const List kVersions = const [ - const bindings.StructDataHeader(48, 0) + const bindings.StructDataHeader(40, 0) ]; DeclarationData declData = null; - String enumTypeKey = null; Value initializerValue = null; int intValue = 0; @@ -1463,15 +1462,11 @@ class EnumValue extends bindings.Struct { } if (mainDataHeader.version >= 0) { - result.enumTypeKey = decoder0.decodeString(16, false); - } - if (mainDataHeader.version >= 0) { - - result.initializerValue = Value.decode(decoder0, 24); + result.initializerValue = Value.decode(decoder0, 16); } if (mainDataHeader.version >= 0) { - result.intValue = decoder0.decodeInt32(40); + result.intValue = decoder0.decodeInt32(32); } return result; } @@ -1486,21 +1481,14 @@ class EnumValue extends bindings.Struct { rethrow; } try { - encoder0.encodeString(enumTypeKey, 16, false); - } on bindings.MojoCodecError catch(e) { - e.message = "Error encountered while encoding field " - "enumTypeKey of struct EnumValue: $e"; - rethrow; - } - try { - encoder0.encodeUnion(initializerValue, 24, true); + encoder0.encodeUnion(initializerValue, 16, true); } on bindings.MojoCodecError catch(e) { e.message = "Error encountered while encoding field " "initializerValue of struct EnumValue: $e"; rethrow; } try { - encoder0.encodeInt32(intValue, 40); + encoder0.encodeInt32(intValue, 32); } on bindings.MojoCodecError catch(e) { e.message = "Error encountered while encoding field " "intValue of struct EnumValue: $e"; @@ -1511,7 +1499,6 @@ class EnumValue extends bindings.Struct { String toString() { return "EnumValue(" "declData: $declData" ", " - "enumTypeKey: $enumTypeKey" ", " "initializerValue: $initializerValue" ", " "intValue: $intValue" ")"; } @@ -1519,7 +1506,6 @@ class EnumValue extends bindings.Struct { Map toJson() { Map map = new Map(); map["declData"] = declData; - map["enumTypeKey"] = enumTypeKey; map["initializerValue"] = initializerValue; map["intValue"] = intValue; return map; @@ -1914,16 +1900,16 @@ class MojomInterface extends bindings.Struct { } -class UserValueReference extends bindings.Struct { +class ConstantReference extends bindings.Struct { static const List kVersions = const [ const bindings.StructDataHeader(24, 0) ]; String identifier = null; - String valueKey = null; + String constantKey = null; - UserValueReference() : super(kVersions.last.size); + ConstantReference() : super(kVersions.last.size); - static UserValueReference deserialize(bindings.Message message) { + static ConstantReference deserialize(bindings.Message message) { var decoder = new bindings.Decoder(message); var result = decode(decoder); if (decoder.excessHandles != null) { @@ -1932,11 +1918,11 @@ class UserValueReference extends bindings.Struct { return result; } - static UserValueReference decode(bindings.Decoder decoder0) { + static ConstantReference decode(bindings.Decoder decoder0) { if (decoder0 == null) { return null; } - UserValueReference result = new UserValueReference(); + ConstantReference result = new ConstantReference(); var mainDataHeader = decoder0.decodeStructDataHeader(); if (mainDataHeader.version <= kVersions.last.version) { @@ -1962,7 +1948,7 @@ class UserValueReference extends bindings.Struct { } if (mainDataHeader.version >= 0) { - result.valueKey = decoder0.decodeString(16, true); + result.constantKey = decoder0.decodeString(16, false); } return result; } @@ -1973,28 +1959,128 @@ class UserValueReference extends bindings.Struct { encoder0.encodeString(identifier, 8, false); } on bindings.MojoCodecError catch(e) { e.message = "Error encountered while encoding field " - "identifier of struct UserValueReference: $e"; + "identifier of struct ConstantReference: $e"; rethrow; } try { - encoder0.encodeString(valueKey, 16, true); + encoder0.encodeString(constantKey, 16, false); } on bindings.MojoCodecError catch(e) { e.message = "Error encountered while encoding field " - "valueKey of struct UserValueReference: $e"; + "constantKey of struct ConstantReference: $e"; rethrow; } } String toString() { - return "UserValueReference(" + return "ConstantReference(" "identifier: $identifier" ", " - "valueKey: $valueKey" ")"; + "constantKey: $constantKey" ")"; } Map toJson() { Map map = new Map(); map["identifier"] = identifier; - map["valueKey"] = valueKey; + map["constantKey"] = constantKey; + return map; + } +} + + +class EnumValueReference extends bindings.Struct { + static const List kVersions = const [ + const bindings.StructDataHeader(32, 0) + ]; + String identifier = null; + String enumTypeKey = null; + int enumValueIndex = 0; + + EnumValueReference() : super(kVersions.last.size); + + static EnumValueReference deserialize(bindings.Message message) { + var decoder = new bindings.Decoder(message); + var result = decode(decoder); + if (decoder.excessHandles != null) { + decoder.excessHandles.forEach((h) => h.close()); + } + return result; + } + + static EnumValueReference decode(bindings.Decoder decoder0) { + if (decoder0 == null) { + return null; + } + EnumValueReference result = new EnumValueReference(); + + var mainDataHeader = decoder0.decodeStructDataHeader(); + if (mainDataHeader.version <= kVersions.last.version) { + // Scan in reverse order to optimize for more recent versions. + for (int i = kVersions.length - 1; i >= 0; --i) { + if (mainDataHeader.version >= kVersions[i].version) { + if (mainDataHeader.size == kVersions[i].size) { + // Found a match. + break; + } + throw new bindings.MojoCodecError( + 'Header size doesn\'t correspond to known version size.'); + } + } + } else if (mainDataHeader.size < kVersions.last.size) { + throw new bindings.MojoCodecError( + 'Message newer than the last known version cannot be shorter than ' + 'required by the last known version.'); + } + if (mainDataHeader.version >= 0) { + + result.identifier = decoder0.decodeString(8, false); + } + if (mainDataHeader.version >= 0) { + + result.enumTypeKey = decoder0.decodeString(16, false); + } + if (mainDataHeader.version >= 0) { + + result.enumValueIndex = decoder0.decodeUint32(24); + } + return result; + } + + void encode(bindings.Encoder encoder) { + var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last); + try { + encoder0.encodeString(identifier, 8, false); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "identifier of struct EnumValueReference: $e"; + rethrow; + } + try { + encoder0.encodeString(enumTypeKey, 16, false); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "enumTypeKey of struct EnumValueReference: $e"; + rethrow; + } + try { + encoder0.encodeUint32(enumValueIndex, 24); + } on bindings.MojoCodecError catch(e) { + e.message = "Error encountered while encoding field " + "enumValueIndex of struct EnumValueReference: $e"; + rethrow; + } + } + + String toString() { + return "EnumValueReference(" + "identifier: $identifier" ", " + "enumTypeKey: $enumTypeKey" ", " + "enumValueIndex: $enumValueIndex" ")"; + } + + Map toJson() { + Map map = new Map(); + map["identifier"] = identifier; + map["enumTypeKey"] = enumTypeKey; + map["enumValueIndex"] = enumValueIndex; return map; } } @@ -3285,7 +3371,8 @@ class DefaultFieldValue extends bindings.Union { enum ValueTag { literalValue, - userValueReference, + constantReference, + enumValueReference, builtinValue, unknown } @@ -3293,14 +3380,16 @@ enum ValueTag { class Value extends bindings.Union { static final _tagToInt = const { ValueTag.literalValue: 0, - ValueTag.userValueReference: 1, - ValueTag.builtinValue: 2, + ValueTag.constantReference: 1, + ValueTag.enumValueReference: 2, + ValueTag.builtinValue: 3, }; static final _intToTag = const { 0: ValueTag.literalValue, - 1: ValueTag.userValueReference, - 2: ValueTag.builtinValue, + 1: ValueTag.constantReference, + 2: ValueTag.enumValueReference, + 3: ValueTag.builtinValue, }; var _data; @@ -3318,15 +3407,26 @@ class Value extends bindings.Union { _tag = ValueTag.literalValue; _data = value; } - UserValueReference get userValueReference { - if (_tag != ValueTag.userValueReference) { - throw new bindings.UnsetUnionTagError(_tag, ValueTag.userValueReference); + ConstantReference get constantReference { + if (_tag != ValueTag.constantReference) { + throw new bindings.UnsetUnionTagError(_tag, ValueTag.constantReference); } return _data; } - set userValueReference(UserValueReference value) { - _tag = ValueTag.userValueReference; + set constantReference(ConstantReference value) { + _tag = ValueTag.constantReference; + _data = value; + } + EnumValueReference get enumValueReference { + if (_tag != ValueTag.enumValueReference) { + throw new bindings.UnsetUnionTagError(_tag, ValueTag.enumValueReference); + } + return _data; + } + + set enumValueReference(EnumValueReference value) { + _tag = ValueTag.enumValueReference; _data = value; } BuiltinConstantValue get builtinValue { @@ -3355,10 +3455,15 @@ class Value extends bindings.Union { var decoder1 = decoder0.decodePointer(offset + 8, false); result.literalValue = LiteralValue.decode(decoder1, 0); break; - case ValueTag.userValueReference: + case ValueTag.constantReference: var decoder1 = decoder0.decodePointer(offset + 8, false); - result.userValueReference = UserValueReference.decode(decoder1); + result.constantReference = ConstantReference.decode(decoder1); + break; + case ValueTag.enumValueReference: + + var decoder1 = decoder0.decodePointer(offset + 8, false); + result.enumValueReference = EnumValueReference.decode(decoder1); break; case ValueTag.builtinValue: @@ -3383,8 +3488,11 @@ class Value extends bindings.Union { case ValueTag.literalValue: encoder0.encodeNestedUnion(literalValue, offset + 8, false); break; - case ValueTag.userValueReference: - encoder0.encodeStruct(userValueReference, offset + 8, false); + case ValueTag.constantReference: + encoder0.encodeStruct(constantReference, offset + 8, false); + break; + case ValueTag.enumValueReference: + encoder0.encodeStruct(enumValueReference, offset + 8, false); break; case ValueTag.builtinValue: encoder0.encodeEnum(builtinValue, offset + 8); @@ -3400,8 +3508,11 @@ class Value extends bindings.Union { case ValueTag.literalValue: result += "literalValue"; break; - case ValueTag.userValueReference: - result += "userValueReference"; + case ValueTag.constantReference: + result += "constantReference"; + break; + case ValueTag.enumValueReference: + result += "enumValueReference"; break; case ValueTag.builtinValue: result += "builtinValue"; @@ -3758,108 +3869,3 @@ class LiteralValue extends bindings.Union { } -enum UserDefinedValueTag { - enumValue, - declaredConstant, - unknown -} - -class UserDefinedValue extends bindings.Union { - static final _tagToInt = const { - UserDefinedValueTag.enumValue: 0, - UserDefinedValueTag.declaredConstant: 1, - }; - - static final _intToTag = const { - 0: UserDefinedValueTag.enumValue, - 1: UserDefinedValueTag.declaredConstant, - }; - - var _data; - UserDefinedValueTag _tag = UserDefinedValueTag.unknown; - - UserDefinedValueTag get tag => _tag; - EnumValue get enumValue { - if (_tag != UserDefinedValueTag.enumValue) { - throw new bindings.UnsetUnionTagError(_tag, UserDefinedValueTag.enumValue); - } - return _data; - } - - set enumValue(EnumValue value) { - _tag = UserDefinedValueTag.enumValue; - _data = value; - } - DeclaredConstant get declaredConstant { - if (_tag != UserDefinedValueTag.declaredConstant) { - throw new bindings.UnsetUnionTagError(_tag, UserDefinedValueTag.declaredConstant); - } - return _data; - } - - set declaredConstant(DeclaredConstant value) { - _tag = UserDefinedValueTag.declaredConstant; - _data = value; - } - - static UserDefinedValue decode(bindings.Decoder decoder0, int offset) { - int size = decoder0.decodeUint32(offset); - if (size == 0) { - return null; - } - UserDefinedValue result = new UserDefinedValue(); - - - UserDefinedValueTag tag = _intToTag[decoder0.decodeUint32(offset + 4)]; - switch (tag) { - case UserDefinedValueTag.enumValue: - - var decoder1 = decoder0.decodePointer(offset + 8, false); - result.enumValue = EnumValue.decode(decoder1); - break; - case UserDefinedValueTag.declaredConstant: - - var decoder1 = decoder0.decodePointer(offset + 8, false); - result.declaredConstant = DeclaredConstant.decode(decoder1); - break; - default: - throw new bindings.MojoCodecError("Bad union tag: $tag"); - } - - return result; - } - - void encode(bindings.Encoder encoder0, int offset) { - - encoder0.encodeUint32(16, offset); - encoder0.encodeUint32(_tagToInt[_tag], offset + 4); - switch (_tag) { - case UserDefinedValueTag.enumValue: - encoder0.encodeStruct(enumValue, offset + 8, false); - break; - case UserDefinedValueTag.declaredConstant: - encoder0.encodeStruct(declaredConstant, offset + 8, false); - break; - default: - throw new bindings.MojoCodecError("Bad union tag: $_tag"); - } - } - - String toString() { - String result = "UserDefinedValue("; - switch (_tag) { - case UserDefinedValueTag.enumValue: - result += "enumValue"; - break; - case UserDefinedValueTag.declaredConstant: - result += "declaredConstant"; - break; - default: - result += "unknown"; - } - result += ": $_data)"; - return result; - } -} - - diff --git a/mojo/dart/packages/mojo/lib/mojo/bindings/types/service_describer.mojom.dart b/mojo/dart/packages/mojo/lib/mojo/bindings/types/service_describer.mojom.dart index be58b3e8ff7ea..9cd09ce093470 100644 --- a/mojo/dart/packages/mojo/lib/mojo/bindings/types/service_describer.mojom.dart +++ b/mojo/dart/packages/mojo/lib/mojo/bindings/types/service_describer.mojom.dart @@ -16,7 +16,7 @@ class _ServiceDescriberDescribeServiceParams extends bindings.Struct { const bindings.StructDataHeader(24, 0) ]; String interfaceName = null; - Object descriptionRequest = null; + ServiceDescriptionInterfaceRequest descriptionRequest = null; _ServiceDescriberDescribeServiceParams() : super(kVersions.last.size); @@ -571,27 +571,59 @@ class _ServiceDescriberServiceDescription implements ServiceDescription { abstract class ServiceDescriber { static const String serviceName = "mojo::bindings::types::ServiceDescriber"; - void describeService(String interfaceName, Object descriptionRequest); + + static ServiceDescription _cachedServiceDescription; + static ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _ServiceDescriberServiceDescription(); + } + return _cachedServiceDescription; + } + + static ServiceDescriberProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + ServiceDescriberProxy p = new ServiceDescriberProxy.unbound(); + String name = serviceName ?? ServiceDescriber.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } + void describeService(String interfaceName, ServiceDescriptionInterfaceRequest descriptionRequest); } +abstract class ServiceDescriberInterface + implements bindings.MojoInterface, + ServiceDescriber { + factory ServiceDescriberInterface([ServiceDescriber impl]) => + new ServiceDescriberStub.unbound(impl); + factory ServiceDescriberInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [ServiceDescriber impl]) => + new ServiceDescriberStub.fromEndpoint(endpoint, impl); +} -class _ServiceDescriberProxyImpl extends bindings.Proxy { - _ServiceDescriberProxyImpl.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); +abstract class ServiceDescriberInterfaceRequest + implements bindings.MojoInterface, + ServiceDescriber { + factory ServiceDescriberInterfaceRequest() => + new ServiceDescriberProxy.unbound(); +} - _ServiceDescriberProxyImpl.fromHandle(core.MojoHandle handle) : - super.fromHandle(handle); +class _ServiceDescriberProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl { + _ServiceDescriberProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); - _ServiceDescriberProxyImpl.unbound() : super.unbound(); + _ServiceDescriberProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); - static _ServiceDescriberProxyImpl newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For _ServiceDescriberProxyImpl")); - return new _ServiceDescriberProxyImpl.fromEndpoint(endpoint); - } + _ServiceDescriberProxyControl.unbound() : super.unbound(); - ServiceDescription get serviceDescription => - new _ServiceDescriberServiceDescription(); + String get serviceName => ServiceDescriber.serviceName; void handleResponse(bindings.ServiceMessage message) { switch (message.header.type) { @@ -602,60 +634,32 @@ class _ServiceDescriberProxyImpl extends bindings.Proxy { } } + ServiceDescriber get impl => null; + set impl(ServiceDescriber _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override String toString() { var superString = super.toString(); - return "_ServiceDescriberProxyImpl($superString)"; + return "_ServiceDescriberProxyControl($superString)"; } } - -class _ServiceDescriberProxyCalls implements ServiceDescriber { - _ServiceDescriberProxyImpl _proxyImpl; - - _ServiceDescriberProxyCalls(this._proxyImpl); - void describeService(String interfaceName, Object descriptionRequest) { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ServiceDescriberDescribeServiceParams(); - params.interfaceName = interfaceName; - params.descriptionRequest = descriptionRequest; - _proxyImpl.sendMessage(params, _serviceDescriberMethodDescribeServiceName); - } -} - - -class ServiceDescriberProxy implements bindings.ProxyBase { - final bindings.Proxy impl; - ServiceDescriber ptr; - - ServiceDescriberProxy(_ServiceDescriberProxyImpl proxyImpl) : - impl = proxyImpl, - ptr = new _ServiceDescriberProxyCalls(proxyImpl); - +class ServiceDescriberProxy + extends bindings.Proxy + implements ServiceDescriber, + ServiceDescriberInterface, + ServiceDescriberInterfaceRequest { ServiceDescriberProxy.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : - impl = new _ServiceDescriberProxyImpl.fromEndpoint(endpoint) { - ptr = new _ServiceDescriberProxyCalls(impl); - } + core.MojoMessagePipeEndpoint endpoint) + : super(new _ServiceDescriberProxyControl.fromEndpoint(endpoint)); - ServiceDescriberProxy.fromHandle(core.MojoHandle handle) : - impl = new _ServiceDescriberProxyImpl.fromHandle(handle) { - ptr = new _ServiceDescriberProxyCalls(impl); - } - - ServiceDescriberProxy.unbound() : - impl = new _ServiceDescriberProxyImpl.unbound() { - ptr = new _ServiceDescriberProxyCalls(impl); - } + ServiceDescriberProxy.fromHandle(core.MojoHandle handle) + : super(new _ServiceDescriberProxyControl.fromHandle(handle)); - factory ServiceDescriberProxy.connectToService( - bindings.ServiceConnector s, String url, [String serviceName]) { - ServiceDescriberProxy p = new ServiceDescriberProxy.unbound(); - s.connectToService(url, p, serviceName); - return p; - } + ServiceDescriberProxy.unbound() + : super(new _ServiceDescriberProxyControl.unbound()); static ServiceDescriberProxy newFromEndpoint( core.MojoMessagePipeEndpoint endpoint) { @@ -663,50 +667,40 @@ class ServiceDescriberProxy implements bindings.ProxyBase { return new ServiceDescriberProxy.fromEndpoint(endpoint); } - String get serviceName => ServiceDescriber.serviceName; - Future close({bool immediate: false}) => impl.close(immediate: immediate); - - Future responseOrError(Future f) => impl.responseOrError(f); - - Future get errorFuture => impl.errorFuture; - - int get version => impl.version; - - Future queryVersion() => impl.queryVersion(); - - void requireVersion(int requiredVersion) { - impl.requireVersion(requiredVersion); - } - - String toString() { - return "ServiceDescriberProxy($impl)"; + void describeService(String interfaceName, ServiceDescriptionInterfaceRequest descriptionRequest) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ServiceDescriberDescribeServiceParams(); + params.interfaceName = interfaceName; + params.descriptionRequest = descriptionRequest; + ctrl.sendMessage(params, + _serviceDescriberMethodDescribeServiceName); } } - -class ServiceDescriberStub extends bindings.Stub { +class _ServiceDescriberStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl { ServiceDescriber _impl; - ServiceDescriberStub.fromEndpoint( + _ServiceDescriberStubControl.fromEndpoint( core.MojoMessagePipeEndpoint endpoint, [ServiceDescriber impl]) : super.fromEndpoint(endpoint, autoBegin: impl != null) { _impl = impl; } - ServiceDescriberStub.fromHandle( + _ServiceDescriberStubControl.fromHandle( core.MojoHandle handle, [ServiceDescriber impl]) : super.fromHandle(handle, autoBegin: impl != null) { _impl = impl; } - ServiceDescriberStub.unbound() : super.unbound(); + _ServiceDescriberStubControl.unbound([this._impl]) : super.unbound(); - static ServiceDescriberStub newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For ServiceDescriberStub")); - return new ServiceDescriberStub.fromEndpoint(endpoint); - } + String get serviceName => ServiceDescriber.serviceName; @@ -751,19 +745,40 @@ class ServiceDescriberStub extends bindings.Stub { } } + @override String toString() { var superString = super.toString(); - return "ServiceDescriberStub($superString)"; + return "_ServiceDescriberStubControl($superString)"; } int get version => 0; +} - static ServiceDescription _cachedServiceDescription; - static ServiceDescription get serviceDescription { - if (_cachedServiceDescription == null) { - _cachedServiceDescription = new _ServiceDescriberServiceDescription(); - } - return _cachedServiceDescription; +class ServiceDescriberStub + extends bindings.Stub + implements ServiceDescriber, + ServiceDescriberInterface, + ServiceDescriberInterfaceRequest { + ServiceDescriberStub.unbound([ServiceDescriber impl]) + : super(new _ServiceDescriberStubControl.unbound(impl)); + + ServiceDescriberStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [ServiceDescriber impl]) + : super(new _ServiceDescriberStubControl.fromEndpoint(endpoint, impl)); + + ServiceDescriberStub.fromHandle( + core.MojoHandle handle, [ServiceDescriber impl]) + : super(new _ServiceDescriberStubControl.fromHandle(handle, impl)); + + static ServiceDescriberStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For ServiceDescriberStub")); + return new ServiceDescriberStub.fromEndpoint(endpoint); + } + + + void describeService(String interfaceName, ServiceDescriptionInterfaceRequest descriptionRequest) { + return impl.describeService(interfaceName, descriptionRequest); } } @@ -784,29 +799,61 @@ class _ServiceDescriptionServiceDescription implements ServiceDescription { abstract class ServiceDescription { static const String serviceName = null; + + static ServiceDescription _cachedServiceDescription; + static ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _ServiceDescriptionServiceDescription(); + } + return _cachedServiceDescription; + } + + static ServiceDescriptionProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + ServiceDescriptionProxy p = new ServiceDescriptionProxy.unbound(); + String name = serviceName ?? ServiceDescription.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } dynamic getTopLevelInterface([Function responseFactory = null]); dynamic getTypeDefinition(String typeKey,[Function responseFactory = null]); dynamic getAllTypeDefinitions([Function responseFactory = null]); } +abstract class ServiceDescriptionInterface + implements bindings.MojoInterface, + ServiceDescription { + factory ServiceDescriptionInterface([ServiceDescription impl]) => + new ServiceDescriptionStub.unbound(impl); + factory ServiceDescriptionInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [ServiceDescription impl]) => + new ServiceDescriptionStub.fromEndpoint(endpoint, impl); +} -class _ServiceDescriptionProxyImpl extends bindings.Proxy { - _ServiceDescriptionProxyImpl.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); +abstract class ServiceDescriptionInterfaceRequest + implements bindings.MojoInterface, + ServiceDescription { + factory ServiceDescriptionInterfaceRequest() => + new ServiceDescriptionProxy.unbound(); +} - _ServiceDescriptionProxyImpl.fromHandle(core.MojoHandle handle) : - super.fromHandle(handle); +class _ServiceDescriptionProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl { + _ServiceDescriptionProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); - _ServiceDescriptionProxyImpl.unbound() : super.unbound(); + _ServiceDescriptionProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); - static _ServiceDescriptionProxyImpl newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For _ServiceDescriptionProxyImpl")); - return new _ServiceDescriptionProxyImpl.fromEndpoint(endpoint); - } + _ServiceDescriptionProxyControl.unbound() : super.unbound(); - ServiceDescription get serviceDescription => - new _ServiceDescriptionServiceDescription(); + String get serviceName => ServiceDescription.serviceName; void handleResponse(bindings.ServiceMessage message) { switch (message.header.type) { @@ -877,75 +924,32 @@ class _ServiceDescriptionProxyImpl extends bindings.Proxy { } } + ServiceDescription get impl => null; + set impl(ServiceDescription _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override String toString() { var superString = super.toString(); - return "_ServiceDescriptionProxyImpl($superString)"; + return "_ServiceDescriptionProxyControl($superString)"; } } - -class _ServiceDescriptionProxyCalls implements ServiceDescription { - _ServiceDescriptionProxyImpl _proxyImpl; - - _ServiceDescriptionProxyCalls(this._proxyImpl); - dynamic getTopLevelInterface([Function responseFactory = null]) { - var params = new _ServiceDescriptionGetTopLevelInterfaceParams(); - return _proxyImpl.sendMessageWithRequestId( - params, - _serviceDescriptionMethodGetTopLevelInterfaceName, - -1, - bindings.MessageHeader.kMessageExpectsResponse); - } - dynamic getTypeDefinition(String typeKey,[Function responseFactory = null]) { - var params = new _ServiceDescriptionGetTypeDefinitionParams(); - params.typeKey = typeKey; - return _proxyImpl.sendMessageWithRequestId( - params, - _serviceDescriptionMethodGetTypeDefinitionName, - -1, - bindings.MessageHeader.kMessageExpectsResponse); - } - dynamic getAllTypeDefinitions([Function responseFactory = null]) { - var params = new _ServiceDescriptionGetAllTypeDefinitionsParams(); - return _proxyImpl.sendMessageWithRequestId( - params, - _serviceDescriptionMethodGetAllTypeDefinitionsName, - -1, - bindings.MessageHeader.kMessageExpectsResponse); - } -} - - -class ServiceDescriptionProxy implements bindings.ProxyBase { - final bindings.Proxy impl; - ServiceDescription ptr; - - ServiceDescriptionProxy(_ServiceDescriptionProxyImpl proxyImpl) : - impl = proxyImpl, - ptr = new _ServiceDescriptionProxyCalls(proxyImpl); - +class ServiceDescriptionProxy + extends bindings.Proxy + implements ServiceDescription, + ServiceDescriptionInterface, + ServiceDescriptionInterfaceRequest { ServiceDescriptionProxy.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : - impl = new _ServiceDescriptionProxyImpl.fromEndpoint(endpoint) { - ptr = new _ServiceDescriptionProxyCalls(impl); - } + core.MojoMessagePipeEndpoint endpoint) + : super(new _ServiceDescriptionProxyControl.fromEndpoint(endpoint)); - ServiceDescriptionProxy.fromHandle(core.MojoHandle handle) : - impl = new _ServiceDescriptionProxyImpl.fromHandle(handle) { - ptr = new _ServiceDescriptionProxyCalls(impl); - } - - ServiceDescriptionProxy.unbound() : - impl = new _ServiceDescriptionProxyImpl.unbound() { - ptr = new _ServiceDescriptionProxyCalls(impl); - } + ServiceDescriptionProxy.fromHandle(core.MojoHandle handle) + : super(new _ServiceDescriptionProxyControl.fromHandle(handle)); - factory ServiceDescriptionProxy.connectToService( - bindings.ServiceConnector s, String url, [String serviceName]) { - ServiceDescriptionProxy p = new ServiceDescriptionProxy.unbound(); - s.connectToService(url, p, serviceName); - return p; - } + ServiceDescriptionProxy.unbound() + : super(new _ServiceDescriptionProxyControl.unbound()); static ServiceDescriptionProxy newFromEndpoint( core.MojoMessagePipeEndpoint endpoint) { @@ -953,50 +957,54 @@ class ServiceDescriptionProxy implements bindings.ProxyBase { return new ServiceDescriptionProxy.fromEndpoint(endpoint); } - String get serviceName => ServiceDescription.serviceName; - Future close({bool immediate: false}) => impl.close(immediate: immediate); - - Future responseOrError(Future f) => impl.responseOrError(f); - - Future get errorFuture => impl.errorFuture; - - int get version => impl.version; - - Future queryVersion() => impl.queryVersion(); - - void requireVersion(int requiredVersion) { - impl.requireVersion(requiredVersion); - } - - String toString() { - return "ServiceDescriptionProxy($impl)"; + dynamic getTopLevelInterface([Function responseFactory = null]) { + var params = new _ServiceDescriptionGetTopLevelInterfaceParams(); + return ctrl.sendMessageWithRequestId( + params, + _serviceDescriptionMethodGetTopLevelInterfaceName, + -1, + bindings.MessageHeader.kMessageExpectsResponse); + } + dynamic getTypeDefinition(String typeKey,[Function responseFactory = null]) { + var params = new _ServiceDescriptionGetTypeDefinitionParams(); + params.typeKey = typeKey; + return ctrl.sendMessageWithRequestId( + params, + _serviceDescriptionMethodGetTypeDefinitionName, + -1, + bindings.MessageHeader.kMessageExpectsResponse); + } + dynamic getAllTypeDefinitions([Function responseFactory = null]) { + var params = new _ServiceDescriptionGetAllTypeDefinitionsParams(); + return ctrl.sendMessageWithRequestId( + params, + _serviceDescriptionMethodGetAllTypeDefinitionsName, + -1, + bindings.MessageHeader.kMessageExpectsResponse); } } - -class ServiceDescriptionStub extends bindings.Stub { +class _ServiceDescriptionStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl { ServiceDescription _impl; - ServiceDescriptionStub.fromEndpoint( + _ServiceDescriptionStubControl.fromEndpoint( core.MojoMessagePipeEndpoint endpoint, [ServiceDescription impl]) : super.fromEndpoint(endpoint, autoBegin: impl != null) { _impl = impl; } - ServiceDescriptionStub.fromHandle( + _ServiceDescriptionStubControl.fromHandle( core.MojoHandle handle, [ServiceDescription impl]) : super.fromHandle(handle, autoBegin: impl != null) { _impl = impl; } - ServiceDescriptionStub.unbound() : super.unbound(); + _ServiceDescriptionStubControl.unbound([this._impl]) : super.unbound(); - static ServiceDescriptionStub newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For ServiceDescriptionStub")); - return new ServiceDescriptionStub.fromEndpoint(endpoint); - } + String get serviceName => ServiceDescription.serviceName; ServiceDescriptionGetTopLevelInterfaceResponseParams _serviceDescriptionGetTopLevelInterfaceResponseParamsFactory(mojom_types_mojom.MojomInterface mojomInterface) { @@ -1113,19 +1121,46 @@ class ServiceDescriptionStub extends bindings.Stub { } } + @override String toString() { var superString = super.toString(); - return "ServiceDescriptionStub($superString)"; + return "_ServiceDescriptionStubControl($superString)"; } int get version => 0; +} - static ServiceDescription _cachedServiceDescription; - static ServiceDescription get serviceDescription { - if (_cachedServiceDescription == null) { - _cachedServiceDescription = new _ServiceDescriptionServiceDescription(); - } - return _cachedServiceDescription; +class ServiceDescriptionStub + extends bindings.Stub + implements ServiceDescription, + ServiceDescriptionInterface, + ServiceDescriptionInterfaceRequest { + ServiceDescriptionStub.unbound([ServiceDescription impl]) + : super(new _ServiceDescriptionStubControl.unbound(impl)); + + ServiceDescriptionStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [ServiceDescription impl]) + : super(new _ServiceDescriptionStubControl.fromEndpoint(endpoint, impl)); + + ServiceDescriptionStub.fromHandle( + core.MojoHandle handle, [ServiceDescription impl]) + : super(new _ServiceDescriptionStubControl.fromHandle(handle, impl)); + + static ServiceDescriptionStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For ServiceDescriptionStub")); + return new ServiceDescriptionStub.fromEndpoint(endpoint); + } + + + dynamic getTopLevelInterface([Function responseFactory = null]) { + return impl.getTopLevelInterface(responseFactory); + } + dynamic getTypeDefinition(String typeKey,[Function responseFactory = null]) { + return impl.getTypeDefinition(typeKey,responseFactory); + } + dynamic getAllTypeDefinitions([Function responseFactory = null]) { + return impl.getAllTypeDefinitions(responseFactory); } } diff --git a/mojo/dart/packages/mojo/lib/mojo/service_provider.mojom.dart b/mojo/dart/packages/mojo/lib/mojo/service_provider.mojom.dart index 18d9420d1ed20..3956995ae8e12 100644 --- a/mojo/dart/packages/mojo/lib/mojo/service_provider.mojom.dart +++ b/mojo/dart/packages/mojo/lib/mojo/service_provider.mojom.dart @@ -108,27 +108,59 @@ class _ServiceProviderServiceDescription implements service_describer.ServiceDes abstract class ServiceProvider { static const String serviceName = null; - void connectToService(String interfaceName, core.MojoMessagePipeEndpoint pipe); + + static service_describer.ServiceDescription _cachedServiceDescription; + static service_describer.ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _ServiceProviderServiceDescription(); + } + return _cachedServiceDescription; + } + + static ServiceProviderProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + ServiceProviderProxy p = new ServiceProviderProxy.unbound(); + String name = serviceName ?? ServiceProvider.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } + void connectToService_(String interfaceName, core.MojoMessagePipeEndpoint pipe); } +abstract class ServiceProviderInterface + implements bindings.MojoInterface, + ServiceProvider { + factory ServiceProviderInterface([ServiceProvider impl]) => + new ServiceProviderStub.unbound(impl); + factory ServiceProviderInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [ServiceProvider impl]) => + new ServiceProviderStub.fromEndpoint(endpoint, impl); +} -class _ServiceProviderProxyImpl extends bindings.Proxy { - _ServiceProviderProxyImpl.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); +abstract class ServiceProviderInterfaceRequest + implements bindings.MojoInterface, + ServiceProvider { + factory ServiceProviderInterfaceRequest() => + new ServiceProviderProxy.unbound(); +} - _ServiceProviderProxyImpl.fromHandle(core.MojoHandle handle) : - super.fromHandle(handle); +class _ServiceProviderProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl { + _ServiceProviderProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); - _ServiceProviderProxyImpl.unbound() : super.unbound(); + _ServiceProviderProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); - static _ServiceProviderProxyImpl newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For _ServiceProviderProxyImpl")); - return new _ServiceProviderProxyImpl.fromEndpoint(endpoint); - } + _ServiceProviderProxyControl.unbound() : super.unbound(); - service_describer.ServiceDescription get serviceDescription => - new _ServiceProviderServiceDescription(); + String get serviceName => ServiceProvider.serviceName; void handleResponse(bindings.ServiceMessage message) { switch (message.header.type) { @@ -139,60 +171,32 @@ class _ServiceProviderProxyImpl extends bindings.Proxy { } } + ServiceProvider get impl => null; + set impl(ServiceProvider _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override String toString() { var superString = super.toString(); - return "_ServiceProviderProxyImpl($superString)"; + return "_ServiceProviderProxyControl($superString)"; } } - -class _ServiceProviderProxyCalls implements ServiceProvider { - _ServiceProviderProxyImpl _proxyImpl; - - _ServiceProviderProxyCalls(this._proxyImpl); - void connectToService(String interfaceName, core.MojoMessagePipeEndpoint pipe) { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ServiceProviderConnectToServiceParams(); - params.interfaceName = interfaceName; - params.pipe = pipe; - _proxyImpl.sendMessage(params, _serviceProviderMethodConnectToServiceName); - } -} - - -class ServiceProviderProxy implements bindings.ProxyBase { - final bindings.Proxy impl; - ServiceProvider ptr; - - ServiceProviderProxy(_ServiceProviderProxyImpl proxyImpl) : - impl = proxyImpl, - ptr = new _ServiceProviderProxyCalls(proxyImpl); - +class ServiceProviderProxy + extends bindings.Proxy + implements ServiceProvider, + ServiceProviderInterface, + ServiceProviderInterfaceRequest { ServiceProviderProxy.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : - impl = new _ServiceProviderProxyImpl.fromEndpoint(endpoint) { - ptr = new _ServiceProviderProxyCalls(impl); - } - - ServiceProviderProxy.fromHandle(core.MojoHandle handle) : - impl = new _ServiceProviderProxyImpl.fromHandle(handle) { - ptr = new _ServiceProviderProxyCalls(impl); - } + core.MojoMessagePipeEndpoint endpoint) + : super(new _ServiceProviderProxyControl.fromEndpoint(endpoint)); - ServiceProviderProxy.unbound() : - impl = new _ServiceProviderProxyImpl.unbound() { - ptr = new _ServiceProviderProxyCalls(impl); - } + ServiceProviderProxy.fromHandle(core.MojoHandle handle) + : super(new _ServiceProviderProxyControl.fromHandle(handle)); - factory ServiceProviderProxy.connectToService( - bindings.ServiceConnector s, String url, [String serviceName]) { - ServiceProviderProxy p = new ServiceProviderProxy.unbound(); - s.connectToService(url, p, serviceName); - return p; - } + ServiceProviderProxy.unbound() + : super(new _ServiceProviderProxyControl.unbound()); static ServiceProviderProxy newFromEndpoint( core.MojoMessagePipeEndpoint endpoint) { @@ -200,50 +204,40 @@ class ServiceProviderProxy implements bindings.ProxyBase { return new ServiceProviderProxy.fromEndpoint(endpoint); } - String get serviceName => ServiceProvider.serviceName; - - Future close({bool immediate: false}) => impl.close(immediate: immediate); - - Future responseOrError(Future f) => impl.responseOrError(f); - - Future get errorFuture => impl.errorFuture; - - int get version => impl.version; - - Future queryVersion() => impl.queryVersion(); - void requireVersion(int requiredVersion) { - impl.requireVersion(requiredVersion); - } - - String toString() { - return "ServiceProviderProxy($impl)"; + void connectToService_(String interfaceName, core.MojoMessagePipeEndpoint pipe) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ServiceProviderConnectToServiceParams(); + params.interfaceName = interfaceName; + params.pipe = pipe; + ctrl.sendMessage(params, + _serviceProviderMethodConnectToServiceName); } } - -class ServiceProviderStub extends bindings.Stub { +class _ServiceProviderStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl { ServiceProvider _impl; - ServiceProviderStub.fromEndpoint( + _ServiceProviderStubControl.fromEndpoint( core.MojoMessagePipeEndpoint endpoint, [ServiceProvider impl]) : super.fromEndpoint(endpoint, autoBegin: impl != null) { _impl = impl; } - ServiceProviderStub.fromHandle( + _ServiceProviderStubControl.fromHandle( core.MojoHandle handle, [ServiceProvider impl]) : super.fromHandle(handle, autoBegin: impl != null) { _impl = impl; } - ServiceProviderStub.unbound() : super.unbound(); + _ServiceProviderStubControl.unbound([this._impl]) : super.unbound(); - static ServiceProviderStub newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For ServiceProviderStub")); - return new ServiceProviderStub.fromEndpoint(endpoint); - } + String get serviceName => ServiceProvider.serviceName; @@ -260,7 +254,7 @@ class ServiceProviderStub extends bindings.Stub { case _serviceProviderMethodConnectToServiceName: var params = _ServiceProviderConnectToServiceParams.deserialize( message.payload); - _impl.connectToService(params.interfaceName, params.pipe); + _impl.connectToService_(params.interfaceName, params.pipe); break; default: throw new bindings.MojoCodecError("Unexpected message name"); @@ -288,19 +282,40 @@ class ServiceProviderStub extends bindings.Stub { } } + @override String toString() { var superString = super.toString(); - return "ServiceProviderStub($superString)"; + return "_ServiceProviderStubControl($superString)"; } int get version => 0; +} - static service_describer.ServiceDescription _cachedServiceDescription; - static service_describer.ServiceDescription get serviceDescription { - if (_cachedServiceDescription == null) { - _cachedServiceDescription = new _ServiceProviderServiceDescription(); - } - return _cachedServiceDescription; +class ServiceProviderStub + extends bindings.Stub + implements ServiceProvider, + ServiceProviderInterface, + ServiceProviderInterfaceRequest { + ServiceProviderStub.unbound([ServiceProvider impl]) + : super(new _ServiceProviderStubControl.unbound(impl)); + + ServiceProviderStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [ServiceProvider impl]) + : super(new _ServiceProviderStubControl.fromEndpoint(endpoint, impl)); + + ServiceProviderStub.fromHandle( + core.MojoHandle handle, [ServiceProvider impl]) + : super(new _ServiceProviderStubControl.fromHandle(handle, impl)); + + static ServiceProviderStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For ServiceProviderStub")); + return new ServiceProviderStub.fromEndpoint(endpoint); + } + + + void connectToService_(String interfaceName, core.MojoMessagePipeEndpoint pipe) { + return impl.connectToService_(interfaceName, pipe); } } diff --git a/mojo/dart/packages/mojo/lib/mojo/shell.mojom.dart b/mojo/dart/packages/mojo/lib/mojo/shell.mojom.dart index a4a587a4c5181..56908acf6e287 100644 --- a/mojo/dart/packages/mojo/lib/mojo/shell.mojom.dart +++ b/mojo/dart/packages/mojo/lib/mojo/shell.mojom.dart @@ -17,8 +17,8 @@ class _ShellConnectToApplicationParams extends bindings.Struct { const bindings.StructDataHeader(32, 0) ]; String applicationUrl = null; - Object services = null; - Object exposedServices = null; + service_provider_mojom.ServiceProviderInterfaceRequest services = null; + service_provider_mojom.ServiceProviderInterface exposedServices = null; _ShellConnectToApplicationParams() : super(kVersions.last.size); @@ -113,7 +113,7 @@ class _ShellCreateApplicationConnectorParams extends bindings.Struct { static const List kVersions = const [ const bindings.StructDataHeader(16, 0) ]; - Object applicationConnectorRequest = null; + application_connector_mojom.ApplicationConnectorInterfaceRequest applicationConnectorRequest = null; _ShellCreateApplicationConnectorParams() : super(kVersions.last.size); @@ -195,28 +195,60 @@ class _ShellServiceDescription implements service_describer.ServiceDescription { abstract class Shell { static const String serviceName = null; - void connectToApplication(String applicationUrl, Object services, Object exposedServices); - void createApplicationConnector(Object applicationConnectorRequest); + + static service_describer.ServiceDescription _cachedServiceDescription; + static service_describer.ServiceDescription get serviceDescription { + if (_cachedServiceDescription == null) { + _cachedServiceDescription = new _ShellServiceDescription(); + } + return _cachedServiceDescription; + } + + static ShellProxy connectToService( + bindings.ServiceConnector s, String url, [String serviceName]) { + ShellProxy p = new ShellProxy.unbound(); + String name = serviceName ?? Shell.serviceName; + if ((name == null) || name.isEmpty) { + throw new core.MojoApiError( + "If an interface has no ServiceName, then one must be provided."); + } + s.connectToService(url, p, name); + return p; + } + void connectToApplication(String applicationUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices); + void createApplicationConnector(application_connector_mojom.ApplicationConnectorInterfaceRequest applicationConnectorRequest); } +abstract class ShellInterface + implements bindings.MojoInterface, + Shell { + factory ShellInterface([Shell impl]) => + new ShellStub.unbound(impl); + factory ShellInterface.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, + [Shell impl]) => + new ShellStub.fromEndpoint(endpoint, impl); +} -class _ShellProxyImpl extends bindings.Proxy { - _ShellProxyImpl.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); +abstract class ShellInterfaceRequest + implements bindings.MojoInterface, + Shell { + factory ShellInterfaceRequest() => + new ShellProxy.unbound(); +} - _ShellProxyImpl.fromHandle(core.MojoHandle handle) : - super.fromHandle(handle); +class _ShellProxyControl + extends bindings.ProxyMessageHandler + implements bindings.ProxyControl { + _ShellProxyControl.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); - _ShellProxyImpl.unbound() : super.unbound(); + _ShellProxyControl.fromHandle( + core.MojoHandle handle) : super.fromHandle(handle); - static _ShellProxyImpl newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For _ShellProxyImpl")); - return new _ShellProxyImpl.fromEndpoint(endpoint); - } + _ShellProxyControl.unbound() : super.unbound(); - service_describer.ServiceDescription get serviceDescription => - new _ShellServiceDescription(); + String get serviceName => Shell.serviceName; void handleResponse(bindings.ServiceMessage message) { switch (message.header.type) { @@ -227,70 +259,32 @@ class _ShellProxyImpl extends bindings.Proxy { } } + Shell get impl => null; + set impl(Shell _) { + throw new core.MojoApiError("The impl of a Proxy cannot be set."); + } + + @override String toString() { var superString = super.toString(); - return "_ShellProxyImpl($superString)"; + return "_ShellProxyControl($superString)"; } } - -class _ShellProxyCalls implements Shell { - _ShellProxyImpl _proxyImpl; - - _ShellProxyCalls(this._proxyImpl); - void connectToApplication(String applicationUrl, Object services, Object exposedServices) { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ShellConnectToApplicationParams(); - params.applicationUrl = applicationUrl; - params.services = services; - params.exposedServices = exposedServices; - _proxyImpl.sendMessage(params, _shellMethodConnectToApplicationName); - } - void createApplicationConnector(Object applicationConnectorRequest) { - if (!_proxyImpl.isBound) { - _proxyImpl.proxyError("The Proxy is closed."); - return; - } - var params = new _ShellCreateApplicationConnectorParams(); - params.applicationConnectorRequest = applicationConnectorRequest; - _proxyImpl.sendMessage(params, _shellMethodCreateApplicationConnectorName); - } -} - - -class ShellProxy implements bindings.ProxyBase { - final bindings.Proxy impl; - Shell ptr; - - ShellProxy(_ShellProxyImpl proxyImpl) : - impl = proxyImpl, - ptr = new _ShellProxyCalls(proxyImpl); - +class ShellProxy + extends bindings.Proxy + implements Shell, + ShellInterface, + ShellInterfaceRequest { ShellProxy.fromEndpoint( - core.MojoMessagePipeEndpoint endpoint) : - impl = new _ShellProxyImpl.fromEndpoint(endpoint) { - ptr = new _ShellProxyCalls(impl); - } - - ShellProxy.fromHandle(core.MojoHandle handle) : - impl = new _ShellProxyImpl.fromHandle(handle) { - ptr = new _ShellProxyCalls(impl); - } + core.MojoMessagePipeEndpoint endpoint) + : super(new _ShellProxyControl.fromEndpoint(endpoint)); - ShellProxy.unbound() : - impl = new _ShellProxyImpl.unbound() { - ptr = new _ShellProxyCalls(impl); - } + ShellProxy.fromHandle(core.MojoHandle handle) + : super(new _ShellProxyControl.fromHandle(handle)); - factory ShellProxy.connectToService( - bindings.ServiceConnector s, String url, [String serviceName]) { - ShellProxy p = new ShellProxy.unbound(); - s.connectToService(url, p, serviceName); - return p; - } + ShellProxy.unbound() + : super(new _ShellProxyControl.unbound()); static ShellProxy newFromEndpoint( core.MojoMessagePipeEndpoint endpoint) { @@ -298,50 +292,51 @@ class ShellProxy implements bindings.ProxyBase { return new ShellProxy.fromEndpoint(endpoint); } - String get serviceName => Shell.serviceName; - - Future close({bool immediate: false}) => impl.close(immediate: immediate); - - Future responseOrError(Future f) => impl.responseOrError(f); - - Future get errorFuture => impl.errorFuture; - - int get version => impl.version; - - Future queryVersion() => impl.queryVersion(); - void requireVersion(int requiredVersion) { - impl.requireVersion(requiredVersion); + void connectToApplication(String applicationUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ShellConnectToApplicationParams(); + params.applicationUrl = applicationUrl; + params.services = services; + params.exposedServices = exposedServices; + ctrl.sendMessage(params, + _shellMethodConnectToApplicationName); } - - String toString() { - return "ShellProxy($impl)"; + void createApplicationConnector(application_connector_mojom.ApplicationConnectorInterfaceRequest applicationConnectorRequest) { + if (!ctrl.isBound) { + ctrl.proxyError("The Proxy is closed."); + return; + } + var params = new _ShellCreateApplicationConnectorParams(); + params.applicationConnectorRequest = applicationConnectorRequest; + ctrl.sendMessage(params, + _shellMethodCreateApplicationConnectorName); } } - -class ShellStub extends bindings.Stub { +class _ShellStubControl + extends bindings.StubMessageHandler + implements bindings.StubControl { Shell _impl; - ShellStub.fromEndpoint( + _ShellStubControl.fromEndpoint( core.MojoMessagePipeEndpoint endpoint, [Shell impl]) : super.fromEndpoint(endpoint, autoBegin: impl != null) { _impl = impl; } - ShellStub.fromHandle( + _ShellStubControl.fromHandle( core.MojoHandle handle, [Shell impl]) : super.fromHandle(handle, autoBegin: impl != null) { _impl = impl; } - ShellStub.unbound() : super.unbound(); + _ShellStubControl.unbound([this._impl]) : super.unbound(); - static ShellStub newFromEndpoint( - core.MojoMessagePipeEndpoint endpoint) { - assert(endpoint.setDescription("For ShellStub")); - return new ShellStub.fromEndpoint(endpoint); - } + String get serviceName => Shell.serviceName; @@ -391,19 +386,43 @@ class ShellStub extends bindings.Stub { } } + @override String toString() { var superString = super.toString(); - return "ShellStub($superString)"; + return "_ShellStubControl($superString)"; } int get version => 0; +} - static service_describer.ServiceDescription _cachedServiceDescription; - static service_describer.ServiceDescription get serviceDescription { - if (_cachedServiceDescription == null) { - _cachedServiceDescription = new _ShellServiceDescription(); - } - return _cachedServiceDescription; +class ShellStub + extends bindings.Stub + implements Shell, + ShellInterface, + ShellInterfaceRequest { + ShellStub.unbound([Shell impl]) + : super(new _ShellStubControl.unbound(impl)); + + ShellStub.fromEndpoint( + core.MojoMessagePipeEndpoint endpoint, [Shell impl]) + : super(new _ShellStubControl.fromEndpoint(endpoint, impl)); + + ShellStub.fromHandle( + core.MojoHandle handle, [Shell impl]) + : super(new _ShellStubControl.fromHandle(handle, impl)); + + static ShellStub newFromEndpoint( + core.MojoMessagePipeEndpoint endpoint) { + assert(endpoint.setDescription("For ShellStub")); + return new ShellStub.fromEndpoint(endpoint); + } + + + void connectToApplication(String applicationUrl, service_provider_mojom.ServiceProviderInterfaceRequest services, service_provider_mojom.ServiceProviderInterface exposedServices) { + return impl.connectToApplication(applicationUrl, services, exposedServices); + } + void createApplicationConnector(application_connector_mojom.ApplicationConnectorInterfaceRequest applicationConnectorRequest) { + return impl.createApplicationConnector(applicationConnectorRequest); } } diff --git a/mojo/dart/packages/mojo/lib/src/application.dart b/mojo/dart/packages/mojo/lib/src/application.dart index 885996f51f455..6072ddaa089e9 100644 --- a/mojo/dart/packages/mojo/lib/src/application.dart +++ b/mojo/dart/packages/mojo/lib/src/application.dart @@ -6,20 +6,20 @@ part of application; class _ApplicationImpl implements application_mojom.Application { application_mojom.ApplicationStub _stub; - shell_mojom.ShellProxy shell; + shell_mojom.ShellInterface shell; Application _application; _ApplicationImpl( Application application, core.MojoMessagePipeEndpoint endpoint) { _application = application; _stub = new application_mojom.ApplicationStub.fromEndpoint(endpoint, this); - _stub.onError = ((_) => close()); + _stub.ctrl.onError = ((_) => close()); } _ApplicationImpl.fromHandle(Application application, core.MojoHandle handle) { _application = application; _stub = new application_mojom.ApplicationStub.fromHandle(handle, this); - _stub.onError = ((_) => close()); + _stub.ctrl.onError = ((_) => close()); } _ApplicationImpl.fromStub(Application application, @@ -27,23 +27,26 @@ class _ApplicationImpl implements application_mojom.Application { _application = application; _stub = applicationStub; _stub.impl = this; - _stub.onError = ((_) => close()); + _stub.ctrl.onError = ((_) => close()); } set onError(core.ErrorHandler f) { - _stub.onError = f; + _stub.ctrl.onError = f; } - void initialize( - bindings.ProxyBase shellProxy, List args, String url) { + void initialize(shell_mojom.ShellInterface shellInterface, + List args, + String url) { assert(shell == null); - shell = shellProxy; + shell = shellInterface; _application.initialize(args, url); } @override - void acceptConnection(String requestorUrl, ServiceProviderStub services, - bindings.ProxyBase exposedServices, String resolvedUrl) => + void acceptConnection(String requestorUrl, + ServiceProviderInterfaceRequest services, + ServiceProviderInterface exposedServices, + String resolvedUrl) => _application._acceptConnection( requestorUrl, services, exposedServices, resolvedUrl); @@ -97,16 +100,15 @@ abstract class Application implements bindings.ServiceConnector { // Returns a connection to the app at |url|. ApplicationConnection connectToApplication(String url) { var proxy = new ServiceProviderProxy.unbound(); - var stub = new ServiceProviderStub.unbound(); - _applicationImpl.shell.ptr.connectToApplication(url, proxy, stub); - var connection = new ApplicationConnection(stub, proxy); + _applicationImpl.shell.connectToApplication(url, proxy, null); + var connection = new ApplicationConnection(null, proxy); _applicationConnections.add(connection); return connection; } - void connectToService(String url, bindings.ProxyBase proxy, + void connectToService(String url, bindings.MojoInterface iface, [String serviceName]) { - connectToApplication(url).requestService(proxy, serviceName); + connectToApplication(url).requestService(iface, serviceName); } void requestQuit() {} diff --git a/mojo/dart/packages/mojo/lib/src/application_connection.dart b/mojo/dart/packages/mojo/lib/src/application_connection.dart index ad0dbb0469466..eecc23caee124 100644 --- a/mojo/dart/packages/mojo/lib/src/application_connection.dart +++ b/mojo/dart/packages/mojo/lib/src/application_connection.dart @@ -14,18 +14,18 @@ class LocalServiceProvider implements ServiceProvider { LocalServiceProvider(this.connection, this._stub) { _stub.impl = this; - if (!_stub.isOpen) { + if (!_stub.ctrl.isOpen) { throw new core.MojoApiError("The service provider stub must be open"); } } set onError(Function f) { - _stub.onError = f; + _stub.ctrl.onError = f; } Future close({bool immediate: false}) => _stub.close(immediate: immediate); - void connectToService( + void connectToService_( String interfaceName, core.MojoMessagePipeEndpoint pipe) { if (connection._nameToServiceFactory.containsKey(interfaceName)) { connection._nameToServiceFactory[interfaceName](pipe); @@ -49,8 +49,8 @@ class LocalServiceProvider implements ServiceProvider { /// [Application.acceptConnection]. /// /// To request a service (e.g. `Foo`) from the remote application: -/// var fooProxy = -/// applicationConnection.requestService(new FooProxy.unbound()); +/// var foo = new FooInterfaceRequest(); +/// applicationConnection.requestService(foo); /// /// To provide a service to the remote application, specify a function that /// instantiantes a service. For example: @@ -62,6 +62,9 @@ class LocalServiceProvider implements ServiceProvider { /// To handle requests for services beyond those set up with [provideService], /// set [fallbackServiceFactory] to a function that instantiates a service as in /// the [provideService] case, or closes the pipe. +// TODO(vtl): Once "exposed_services" is removed from Shell's +// ConnectToApplication() (and Application's AcceptConnection(), etc.), this +// class will be a bit of overkill. https://github.com/domokit/mojo/issues/762 class ApplicationConnection { ServiceProviderProxy remoteServiceProvider; LocalServiceProvider _localServiceProvider; @@ -87,25 +90,24 @@ class ApplicationConnection { _fallbackServiceFactory = f; } - bindings.ProxyBase requestService(bindings.ProxyBase proxy, - [String serviceName]) { - if (proxy.impl.isBound || + void requestService(bindings.MojoInterface iface, [String serviceName]) { + if (iface.ctrl.isBound || (remoteServiceProvider == null) || - !remoteServiceProvider.impl.isBound) { + !remoteServiceProvider.ctrl.isBound) { throw new core.MojoApiError( - "The proxy is bound, or there is no remove service provider proxy"); + "The interface is already bound, " + "or there is no remote service provider"); } - var name = serviceName ?? proxy.serviceName; + var name = serviceName ?? iface.ctrl.serviceName; if ((name == null) || name.isEmpty) { throw new core.MojoApiError( "If an interface has no ServiceName, then one must be provided."); } var pipe = new core.MojoMessagePipe(); - proxy.impl.bind(pipe.endpoints[0]); - remoteServiceProvider.ptr.connectToService(name, pipe.endpoints[1]); - return proxy; + iface.ctrl.bind(pipe.endpoints[0]); + remoteServiceProvider.connectToService_(name, pipe.endpoints[1]); } /// Prepares this connection to provide the specified service when a call for diff --git a/mojo/dart/packages/mojo/lib/src/buffer.dart b/mojo/dart/packages/mojo/lib/src/buffer.dart index df55eab5f742f..b3de67dbb3405 100644 --- a/mojo/dart/packages/mojo/lib/src/buffer.dart +++ b/mojo/dart/packages/mojo/lib/src/buffer.dart @@ -60,8 +60,7 @@ class MojoSharedBuffer { return null; } - List result = - MojoSharedBufferNatives.GetInformation(handle.h); + List result = MojoSharedBufferNatives.GetInformation(handle.h); if (result[0] != MojoResult.kOk) { _status = result[0]; diff --git a/mojo/dart/packages/mojo/lib/src/codec.dart b/mojo/dart/packages/mojo/lib/src/codec.dart index 092a9607026f2..ad99890a3876e 100644 --- a/mojo/dart/packages/mojo/lib/src/codec.dart +++ b/mojo/dart/packages/mojo/lib/src/codec.dart @@ -210,68 +210,51 @@ class Encoder { encodeHandle(value != null ? value.handle : null, offset, nullable); void encodeInterface( - core.MojoEventHandler interface, int offset, bool nullable) { - if (interface == null) { + MojoInterface mojoInterface, int offset, bool nullable) { + if (mojoInterface == null) { encodeInvalideHandle(offset, nullable); // Set the version field to 0. encodeUint32(0, offset + kSerializedHandleSize); return; } - if (interface is Stub) { - if (interface.isBound) { - throw new MojoCodecError( - 'Cannot encode a bound stub for an interface'); - } + if (!mojoInterface.ctrl.isBound) { var pipe = new core.MojoMessagePipe(); - interface.bind(pipe.endpoints[0]); + mojoInterface.ctrl.bind(pipe.endpoints[0]); encodeMessagePipeHandle(pipe.endpoints[1], offset, nullable); // Set the version to the version in the stub. - encodeUint32(interface.version, offset + kSerializedHandleSize); - } else if (interface is Proxy) { - if (!interface.isBound) { - throw new MojoCodecError( - 'Cannot encode an unbound proxy for an interface'); - } - if (!interface.isOpen) { + encodeUint32(mojoInterface.ctrl.version, offset + kSerializedHandleSize); + } else { + if (!mojoInterface.ctrl.isOpen) { // Make sure that we are listening so that state for the proxy is // cleaned up when the message is sent and the handle is closed. - interface.beginHandlingEvents(); + mojoInterface.ctrl.beginHandlingEvents(); } - encodeMessagePipeHandle(interface.endpoint, offset, nullable); + encodeMessagePipeHandle(mojoInterface.ctrl.endpoint, offset, nullable); // Set the version to the current version of the proxy. - encodeUint32(interface.version, offset + kSerializedHandleSize); - } else { - throw new MojoCodecError('Cannot encode an unknown MojoEventHandler'); + encodeUint32(mojoInterface.ctrl.version, offset + kSerializedHandleSize); } } - void encodeInterfaceRequest(Object request, int offset, bool nullable) { - if (request == null) { + void encodeInterfaceRequest( + MojoInterface mojoInterface, int offset, bool nullable) { + if (mojoInterface == null) { encodeInvalideHandle(offset, nullable); return; } - if (request is ProxyBase) { - if (request.impl.isBound) { - throw new MojoCodecError( - 'Cannot encode a bound proxy for an interface request'); - } + if (!mojoInterface.ctrl.isBound) { var pipe = new core.MojoMessagePipe(); - request.impl.bind(pipe.endpoints[0]); - request.impl.beginHandlingEvents(); + mojoInterface.ctrl.bind(pipe.endpoints[0]); + mojoInterface.ctrl.beginHandlingEvents(); encodeMessagePipeHandle(pipe.endpoints[1], offset, nullable); - } else if (request is Stub) { - if (!request.isBound) { - throw new MojoCodecError( - 'Cannot encode an unbound stub for an interface request'); - } - if (!request.isOpen) { + } else { + if (!mojoInterface.ctrl.isOpen) { // Make sure that we are listening so that state for the stub is // cleaned up when the message is sent and the handle is closed. - request.beginHandlingEvents(); + mojoInterface.ctrl.beginHandlingEvents(); } - encodeMessagePipeHandle(request.endpoint, offset, nullable); + encodeMessagePipeHandle(mojoInterface.ctrl.endpoint, offset, nullable); // Set the version to the current version of the stub. - encodeUint32(request.version, offset + kSerializedHandleSize); + encodeUint32(mojoInterface.ctrl.version, offset + kSerializedHandleSize); } } @@ -746,19 +729,19 @@ class Decoder { core.MojoSharedBuffer decodeSharedBufferHandle(int offset, bool nullable) => new core.MojoSharedBuffer(decodeHandle(offset, nullable)); - ProxyBase decodeServiceInterface( + MojoInterface decodeServiceInterface( int offset, bool nullable, Function clientFactory) { var endpoint = decodeMessagePipeHandle(offset, nullable); var version = decodeUint32(offset + kSerializedHandleSize); if (!endpoint.handle.isValid) { return null; } - ProxyBase client = clientFactory(endpoint); - client.impl._version = version; + Proxy client = clientFactory(endpoint); + client.ctrl._version = version; return client; } - Stub decodeInterfaceRequest( + MojoInterface decodeInterfaceRequest( int offset, bool nullable, Function interfaceFactory) { var endpoint = decodeMessagePipeHandle(offset, nullable); return endpoint.handle.isValid ? interfaceFactory(endpoint) : null; diff --git a/mojo/dart/packages/mojo/lib/src/control_message.dart b/mojo/dart/packages/mojo/lib/src/control_message.dart index e5cd5827dc7b9..407800a729e66 100644 --- a/mojo/dart/packages/mojo/lib/src/control_message.dart +++ b/mojo/dart/packages/mojo/lib/src/control_message.dart @@ -15,19 +15,19 @@ class ControlMessageHandler { static bool _isRunOrClose(ServiceMessage message) => (message.header.type == icm.kRunOrClosePipeMessageId); - static Future handleMessage(Stub stub, + static Future handleMessage(StubControl stubControl, int interface_version, ServiceMessage message) { assert(isControlMessage(message)); if (_isRun(message)) { - return _handleRun(stub, interface_version, message); + return _handleRun(stubControl, interface_version, message); } else { assert(_isRunOrClose(message)); - return _handleRunOrClose(stub, interface_version, message); + return _handleRunOrClose(stubControl, interface_version, message); } } - static Future _handleRun(Stub stub, + static Future _handleRun(StubControl stubControl, int interface_version, ServiceMessage message) { // Construct RunMessage response. @@ -38,13 +38,13 @@ class ControlMessageHandler { response.queryVersionResult.version = interface_version; // Return response. return new Future.value( - stub.buildResponseWithId(response, - icm.kRunMessageId, - message.header.requestId, - MessageHeader.kMessageIsResponse)); + stubControl.buildResponseWithId(response, + icm.kRunMessageId, + message.header.requestId, + MessageHeader.kMessageIsResponse)); } - static Future _handleRunOrClose(Stub stub, + static Future _handleRunOrClose(StubControl stubControl, int interface_version, ServiceMessage message) { // Deserialize message. @@ -53,7 +53,7 @@ class ControlMessageHandler { var requiredVersion = params.requireVersion.version; if (interface_version < requiredVersion) { // Stub does not implement required version. Close the pipe immediately. - stub.close(immediate: true); + stubControl.close(immediate: true); } return null; } diff --git a/mojo/dart/packages/mojo/lib/src/event_stream.dart b/mojo/dart/packages/mojo/lib/src/event_handler.dart similarity index 61% rename from mojo/dart/packages/mojo/lib/src/event_stream.dart rename to mojo/dart/packages/mojo/lib/src/event_handler.dart index ea3e5f513319d..cbdefa3c62088 100644 --- a/mojo/dart/packages/mojo/lib/src/event_stream.dart +++ b/mojo/dart/packages/mojo/lib/src/event_handler.dart @@ -1,148 +1,24 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. part of core; -class MojoEventSubscription { - // The underlying Mojo handle. - MojoHandle _handle; - - // The send port that we give to the handle watcher to notify us of handle - // events. - SendPort _sendPort; - - // The receive port on which we listen and receive events from the handle - // watcher. - RawReceivePort _receivePort; - - // The signals on this handle that we're interested in. - int _signals; - - // Whether subscribe() has been called. - bool _isSubscribed; - - MojoEventSubscription(MojoHandle handle, - [int signals = MojoHandleSignals.kPeerClosedReadable]) - : _handle = handle, - _signals = signals, - _isSubscribed = false { - if (!MojoHandle.registerFinalizer(this)) { - throw new MojoInternalError("Failed to register the MojoHandle."); - } - } - - Future close({bool immediate: false}) => _close(immediate: immediate); - - void subscribe(void handler(int event)) { - if (_isSubscribed) { - throw new MojoApiError("Already subscribed: $this."); - } - _receivePort = new RawReceivePort(handler); - _sendPort = _receivePort.sendPort; - - if (_signals != MojoHandleSignals.kNone) { - int res = MojoHandleWatcher.add(_handle.h, _sendPort, _signals); - if (res != MojoResult.kOk) { - throw new MojoInternalError("MojoHandleWatcher add failed: $res"); - } - } - _isSubscribed = true; - } - - bool enableSignals([int signals]) { - if (signals != null) { - _signals = signals; - } - if (_isSubscribed) { - return MojoHandleWatcher.add(_handle.h, _sendPort, _signals) == - MojoResult.kOk; - } - return false; - } - - bool enableReadEvents() => - enableSignals(MojoHandleSignals.kPeerClosedReadable); - bool enableWriteEvents() => enableSignals(MojoHandleSignals.kWritable); - bool enableAllEvents() => enableSignals(MojoHandleSignals.kReadWrite); - - /// End the subscription by removing the handle from the handle watcher and - /// closing the Dart port, but do not close the underlying handle. The handle - /// can then be reused, or closed at a later time. - void unsubscribe({bool immediate: false}) { - if ((_handle == null) || !_isSubscribed || (_receivePort == null)) { - throw new MojoApiError("Cannont unsubscribe from a MojoEventSubscription " - "that has not been subscribed to"); - } - MojoHandleWatcher.remove(_handle.h); - _receivePort.close(); - _receivePort = null; - _sendPort = null; - _isSubscribed = false; - } - - Future _close({bool immediate: false, bool local: false}) { - if (_handle != null) { - if (_isSubscribed && !local) { - return _handleWatcherClose(immediate: immediate).then((result) { - // If the handle watcher is gone, then close the handle ourselves. - if (result != MojoResult.kOk) { - _localClose(); - } - }); - } else { - _localClose(); - } - } - return new Future.value(null); - } - - Future _handleWatcherClose({bool immediate: false}) { - assert(_handle != null); - MojoHandleNatives.removeOpenHandle(_handle.h); - return MojoHandleWatcher.close(_handle.h, wait: !immediate).then((r) { - if (_receivePort != null) { - _receivePort.close(); - _receivePort = null; - } - return r; - }); - } - - void _localClose() { - if (_handle != null) { - _handle.close(); - _handle = null; - } - if (_receivePort != null) { - _receivePort.close(); - _receivePort = null; - } - } - - bool get readyRead => _handle.readyRead; - bool get readyWrite => _handle.readyWrite; - int get signals => _signals; - - String toString() => "$_handle"; -} - -/// Object returned to pipe's error handlers containing both the thrown error -/// and the associated stack trace. -class MojoHandlerError { +/// The object passed to the handler's error handling function containing both +/// the thrown error and the associated stack trace. +class MojoEventHandlerError { final Object error; final StackTrace stacktrace; - MojoHandlerError(this.error, this.stacktrace); + MojoEventHandlerError(this.error, this.stacktrace); + @override String toString() => error.toString(); } -typedef void ErrorHandler(MojoHandlerError e); +typedef void ErrorHandler(MojoEventHandlerError e); class MojoEventHandler { - ErrorHandler onError; - MojoMessagePipeEndpoint _endpoint; MojoEventSubscription _eventSubscription; bool _isOpen = false; @@ -168,6 +44,29 @@ class MojoEventHandler { MojoEventHandler.unbound(); + /// The event handler calls the [handleRead] method when the underlying Mojo + /// message pipe endpoint has a message available to be read. Implementers + /// should read, decode, and handle the message. If [handleRead] throws + /// an exception derived from [Error], the exception will be thrown into the + /// root zone, and the application will end. Otherwise, the exception object + /// will be passed to [onError] if it has been set, and the exception will + /// not be propagated to the root zone. + void handleRead() {} + + /// Like [handleRead] but indicating that the underlying message pipe endpoint + /// is ready for writing. + void handleWrite() {} + + /// Called when [handleRead] or [handleWrite] throw an exception generated by + /// Mojo library code. Other exceptions will be re-thrown. + ErrorHandler onError; + + MojoMessagePipeEndpoint get endpoint => _endpoint; + bool get isOpen => _isOpen; + bool get isInHandler => _isInHandler; + bool get isBound => _endpoint != null; + bool get isPeerClosed => _isPeerClosed; + void bind(MojoMessagePipeEndpoint endpoint) { if (isBound) { throw new MojoApiError("MojoEventHandler is already bound."); @@ -252,6 +151,10 @@ class MojoEventHandler { return result != null ? result : new Future.value(null); } + @override + String toString() => "MojoEventHandler(" + "isOpen: $_isOpen, isBound: $isBound, endpoint: $_endpoint)"; + void _tryHandleEvent(int event) { // This callback is running in the handler for a RawReceivePort. All // exceptions rethrown or not caught here will be unhandled exceptions in @@ -271,7 +174,7 @@ class MojoEventHandler { } catch (e, s) { close(immediate: true).then((_) { if (onError != null) { - onError(new MojoHandlerError(e, s)); + onError(new MojoEventHandlerError(e, s)); } }); } @@ -302,26 +205,4 @@ class MojoEventHandler { }); } } - - /// The event handler calls the [handleRead] method when the underlying Mojo - /// message pipe endpoint has a message available to be read. Implementers - /// should read, decode, and handle the message. If [handleRead] throws - /// an exception derived from [Error], the exception will be thrown into the - /// root zone, and the application will end. Otherwise, the exception object - /// will be passed to [onError] if it has been set, and the exception will - /// not be propagated to the root zone. - void handleRead() {} - - /// Like [handleRead] but indicating that the underlying message pipe endpoint - /// is ready for writing. - void handleWrite() {} - - MojoMessagePipeEndpoint get endpoint => _endpoint; - bool get isOpen => _isOpen; - bool get isInHandler => _isInHandler; - bool get isBound => _endpoint != null; - bool get isPeerClosed => _isPeerClosed; - - String toString() => "MojoEventHandler(" - "isOpen: $_isOpen, isBound: $isBound, endpoint: $_endpoint)"; } diff --git a/mojo/dart/packages/mojo/lib/src/event_subscription.dart b/mojo/dart/packages/mojo/lib/src/event_subscription.dart new file mode 100644 index 0000000000000..1e01f7ea9fa2e --- /dev/null +++ b/mojo/dart/packages/mojo/lib/src/event_subscription.dart @@ -0,0 +1,129 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of core; + +class MojoEventSubscription { + // The underlying Mojo handle. + MojoHandle _handle; + + // The send port that we give to the handle watcher to notify us of handle + // events. + SendPort _sendPort; + + // The receive port on which we listen and receive events from the handle + // watcher. + RawReceivePort _receivePort; + + // The signals on this handle that we're interested in. + int _signals; + + // Whether subscribe() has been called. + bool _isSubscribed; + + MojoEventSubscription(MojoHandle handle, + [int signals = MojoHandleSignals.kPeerClosedReadable]) + : _handle = handle, + _signals = signals, + _isSubscribed = false { + if (!MojoHandle.registerFinalizer(this)) { + throw new MojoInternalError("Failed to register the MojoHandle."); + } + } + + bool get readyRead => _handle.readyRead; + bool get readyWrite => _handle.readyWrite; + int get signals => _signals; + + Future close({bool immediate: false}) => _close(immediate: immediate); + + void subscribe(void handler(int event)) { + if (_isSubscribed) { + throw new MojoApiError("Already subscribed: $this."); + } + _receivePort = new RawReceivePort(handler); + _sendPort = _receivePort.sendPort; + + if (_signals != MojoHandleSignals.kNone) { + int res = MojoHandleWatcher.add(_handle.h, _sendPort, _signals); + if (res != MojoResult.kOk) { + throw new MojoInternalError("MojoHandleWatcher add failed: $res"); + } + } + _isSubscribed = true; + } + + bool enableSignals([int signals]) { + if (signals != null) { + _signals = signals; + } + if (_isSubscribed) { + return MojoHandleWatcher.add(_handle.h, _sendPort, _signals) == + MojoResult.kOk; + } + return false; + } + + bool enableReadEvents() => + enableSignals(MojoHandleSignals.kPeerClosedReadable); + bool enableWriteEvents() => enableSignals(MojoHandleSignals.kWritable); + bool enableAllEvents() => enableSignals(MojoHandleSignals.kReadWrite); + + /// End the subscription by removing the handle from the handle watcher and + /// closing the Dart port, but do not close the underlying handle. The handle + /// can then be reused, or closed at a later time. + void unsubscribe({bool immediate: false}) { + if ((_handle == null) || !_isSubscribed || (_receivePort == null)) { + throw new MojoApiError("Cannont unsubscribe from a MojoEventSubscription " + "that has not been subscribed to"); + } + MojoHandleWatcher.remove(_handle.h); + _receivePort.close(); + _receivePort = null; + _sendPort = null; + _isSubscribed = false; + } + + @override + String toString() => "$_handle"; + + Future _close({bool immediate: false, bool local: false}) { + if (_handle != null) { + if (_isSubscribed && !local) { + return _handleWatcherClose(immediate: immediate).then((result) { + // If the handle watcher is gone, then close the handle ourselves. + if (result != MojoResult.kOk) { + _localClose(); + } + }); + } else { + _localClose(); + } + } + return new Future.value(null); + } + + Future _handleWatcherClose({bool immediate: false}) { + assert(_handle != null); + MojoHandleNatives.removeOpenHandle(_handle.h); + return MojoHandleWatcher.close(_handle.h, wait: !immediate).then((r) { + if (_receivePort != null) { + _receivePort.close(); + _receivePort = null; + } + return r; + }); + } + + void _localClose() { + if (_handle != null) { + _handle.close(); + _handle = null; + } + if (_receivePort != null) { + _receivePort.close(); + _receivePort = null; + } + } +} diff --git a/mojo/dart/packages/mojo/lib/src/handle.dart b/mojo/dart/packages/mojo/lib/src/handle.dart index 3c98ff491fccb..fbc664da37d4f 100644 --- a/mojo/dart/packages/mojo/lib/src/handle.dart +++ b/mojo/dart/packages/mojo/lib/src/handle.dart @@ -5,11 +5,15 @@ part of core; class MojoHandle { + // TODO(floitsch): get the INVALID value from the backing internal + // implementation. static const int INVALID = 0; static const int DEADLINE_INDEFINITE = -1; - int _h; - int get h => _h; + // The type of this field is determined by the backing internal + // implementation. + Object _h; + Object get h => _h; MojoHandle(this._h, {String description}) { MojoHandleNatives.addOpenHandle(_h, description: description); diff --git a/mojo/dart/packages/mojo/lib/src/interfaces.dart b/mojo/dart/packages/mojo/lib/src/interfaces.dart new file mode 100644 index 0000000000000..1c90a5feb1c69 --- /dev/null +++ b/mojo/dart/packages/mojo/lib/src/interfaces.dart @@ -0,0 +1,23 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of bindings; + +/// [MojoInterface] is the interface implemented by the generated +/// Interface and InterfaceRequest classes. The [MojoInterfaceControl] field +/// [ctrl] gives access to the underlying implementation of the interface, which +/// is either a [ProxyControl] or [StubControl] depending on the situation. +abstract class MojoInterface { + MojoInterfaceControl get ctrl; + T impl; + Future close({bool immediate: false}); +} + +/// This interface is implemented by [ProxyMessageHandler] and +/// [StubMessageHandler]. Most of the interface is inherited from, and +/// ultimately implemented by [core.MojoEventHandler]. +abstract class MojoInterfaceControl implements core.MojoEventHandler { + String get serviceName; + int get version; +} diff --git a/mojo/dart/packages/mojo/lib/src/internal.dart b/mojo/dart/packages/mojo/lib/src/internal.dart new file mode 100644 index 0000000000000..3c6b9b736cd7c --- /dev/null +++ b/mojo/dart/packages/mojo/lib/src/internal.dart @@ -0,0 +1,10 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +library mojo_internal; + +// Import 'internal_contract.dart' by default, but use 'dart:mojo.internal' if +// the embedder supports it. +export 'internal_contract.dart' + if (dart.library.mojo.internal) 'dart:mojo.internal'; diff --git a/mojo/dart/packages/mojo/lib/src/internal_contract.dart b/mojo/dart/packages/mojo/lib/src/internal_contract.dart new file mode 100644 index 0000000000000..fe2376415a875 --- /dev/null +++ b/mojo/dart/packages/mojo/lib/src/internal_contract.dart @@ -0,0 +1,637 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:isolate' show SendPort; +import 'dart:typed_data' show ByteData; + +// The following import is only here to get references in the documentation +// to work. There is no dependency from the internal library to 'core'. +// TODO(floitsch): move the constants into the internal-library, and +// reference them from the package-classes. +import '../core.dart' + show + MojoResult, + MojoHandleSignals, + MojoMessagePipe, + MojoMessagePipeEndpoint, + MojoDataPipe, + MojoDataPipeProducer, + MojoDataPipeConsumer, + MojoEventSubscription, + MojoSharedBuffer; + +/// This class contains static methods to send a stream of events to application +/// isolates that register Mojo handles with it. +class MojoHandleWatcher { + /// Starts watching for events on the given [handleToken]. + /// + /// Returns an integer, encoding the result as specified in the [MojoResult] + /// class. In particular, a successful operation returns [MojoResult.kOk]. + /// + /// Instructs the MojoHandleWatcher isolate to add [handleToken] to the set of + /// handles it watches, and to notify the calling isolate only for the events + /// specified by [signals] using the send port [port]. + // TODO(floitsch): what does "MojoHandleWatcher isolate" mean? + // TODO(floitsch): what is the calling isolate? + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// + /// The filtering [signals] are encoded as specified in the + /// [MojoHandleSignals] class. For example, setting [signals] to + /// [MojoHandleSignals.kPeerClosedReadable] instructs the handle watcher to + /// notify the caller, when the handle becomes readable (that is, has data + /// available for reading), or when it is closed. + static int add(Object handleToken, SendPort port, int signals) { + throw new UnsupportedError("MojoHandleWatcher.add on contract"); + } + + /// Stops watching the given [handleToken]. + /// + /// Returns an integer, encoding the result as specified in the [MojoResult] + /// class. In particular, a successful operation returns [MojoResult.kOk]. + /// + /// Instructs the MojoHandleWatcher isolate to remove [handleToken] from the + /// set of handles it watches. This allows the application isolate + /// to, for example, pause the stream of events. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + static int remove(Object handleToken) { + throw new UnsupportedError("MojoHandleWatcher.remove on contract"); + } + + /// Stops watching and closes the given [handleToken]. + /// + /// Returns an integer, encoding the result as specified in the [MojoResult] + /// class. In particular, a successful operation returns [MojoResult.kOk]. + /// + /// Notifies the HandleWatcherIsolate that a handle it is + /// watching should be removed from its set and closed. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// + /// If [wait] is true, returns a future that resolves only after the handle + // has actually been closed by the handle watcher. Otherwise, returns a + // future that resolves immediately. + static Future close(Object handleToken, {bool wait: false}) { + throw new UnsupportedError("MojoHandleWatcher.close on contract"); + } + + /// Requests a notification on the given [port] at [deadline]. + /// + /// Returns an integer, encoding the result as specified in the [MojoResult] + /// class. In particular, a successful operation returns [MojoResult.kOk]. + /// + /// The [deadline] is in milliseconds, with + /// [MojoCoreNatives.timerMillisecondClock] as reference. + /// + /// If the given [port] was already registered for a timer (in any isolate), + /// then the old value is discarded. + /// + /// A negative [deadline] is used to remove a port. That is, a negative value + /// is ignored after any existing value for the port has been discarded. + static int timer(Object ignored, SendPort port, int deadline) { + throw new UnsupportedError("MojoHandleWatcher.timer on contract"); + } +} + +class MojoCoreNatives { + /// 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. + static int getTimeTicksNow() { + throw new UnsupportedError("MojoCoreNatives.getTimeTicksNow on contract"); + } + + /// Returns the time, in milliseconds, since some undefined point in the past. + /// + /// This method is equivalent to `getTimeTicksNow() ~/ 1000`. + static int timerMillisecondClock() { + throw new UnsupportedError( + "MojoCoreNatives.timerMillisecondClock on contract"); + } +} + +class MojoHandleNatives { + /// Puts the given [handleToken] with the given [description] into the set of + /// open handles. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// + /// This method is only used to report open handles (see [reportOpenHandles]). + static void addOpenHandle(Object handleToken, {String description}) { + throw new UnsupportedError("MojoHandleNatives.addOpenHandle on contract"); + } + + /// Removes the given [handleToken] from the set of open handles. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// + /// This method is only used to report open handles (see [reportOpenHandles]). + /// + /// Handles are removed from the set when they are closed, but also, when they + /// are serialized in the mojo encoder [codec.dart]. + static void removeOpenHandle(Object handleToken) { + throw new UnsupportedError( + "MojoHandleNatives.removeOpenHandle on contract"); + } + + /// Prints a list of all open handles. + /// + /// Returns `true` if there are no open handles. + /// + /// Prints all handles that have been added with [addOpenHandle] but haven't + /// been removed with [removeOpenHandle]. + /// + /// Programs should not have open handles when the program terminates. + static bool reportOpenHandles() { + throw new UnsupportedError( + "MojoHandleNatives.reportOpenHandles on contract"); + } + + /// Updates the description of the given [handleToken] in the set of open + /// handles. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// + /// Does nothing, if the [handleToken] isn't in the set. + static bool setDescription(Object handleToken, String description) { + throw new UnsupportedError("MojoHandleNatives.setDescription on contract"); + } + + /// Registers a finalizer on [eventSubscription] to close the given + /// [handleToken]. + /// + /// Returns an integer, encoding the result as specified in the [MojoResult] + /// class. In particular, a successful operation returns [MojoResult.kOk]. + /// + /// When [eventSubscription] (currently an Instance of the + /// [MojoEventSubscription] class) is garbage-collected, invokes [close] on + /// the [handleToken]. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// Since the token can be an integer, it's not possible to install the + /// finalizer directly on the token. + static int registerFinalizer(Object eventStream, Object handleToken) { + throw new UnsupportedError( + "MojoHandleNatives.registerFinalizer on contract"); + } + + /// Closes the given [handleToken]. + /// + /// Returns an integer, encoding the result as specified in the [MojoResult] + /// class. In particular, a successful operation returns [MojoResult.kOk]. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + static int close(Object handleToken) { + throw new UnsupportedError("MojoHandleNatives.close on contract"); + } + + /// Waits on the given [handleToken] for a signal. + /// + /// Returns a list of two elements. The first entry is an integer, encoding + /// if the operation was a success or not, as specified in the [MojoResult] + /// class. In particular, a successful operation is signaled by + /// [MojoResult.kOk]. The second entry is itself a list of 2 elements: + /// an integer of satisfied signals, and an integer of satisfiable signals. + /// Both entries are encoded as specified in [MojoHandleSignals]. + /// + /// A signal is satisfiable, if the signal may become true in the future. + /// + /// The [deadline] specifies how long the call should wait (if no signal is + /// triggered). If the deadline passes, the returned result-integer is + /// [MojoResult.kDeadlineExceeded]. If the deadline is 0, then the result + /// is only [MojoResult.kDeadlineExceeded] if no other termination condition + /// is already satisfied (see below). + /// + /// The [signals] integer encodes the signals this method should wait for. + /// The integer is encoded as specified in [MojoHandleSignals]. + /// + /// Waits on the given handle until one of the following happens: + /// - A signal indicated by [signals] is satisfied. + /// - It becomes known that no signal indicated by [signals] will ever be + /// satisfied (for example the handle has been closed on the other side). + /// - The [deadline] has passed. + static List wait(Object handleToken, int signals, int deadline) { + throw new UnsupportedError("MojoHandleNatives.woit on contract"); + } + + /// Waits on many handles at the same time. + /// + /// Returns a list with exactly 3 elements: + /// - the result integer, encoded as specified in [MojoResult]. In particular, + /// [MojoResult.kOk] signals success. + /// - the index of the handle that caused the return. May be `null` if the + /// operation didn't succeed. + /// - a list of signal states. May be `null` if the operation didn't succeed. + /// Each signal state is represented by a list of 2 elements: an integer of + /// satisfied signals, and an integer of satisfiable signals (see [wait]). + /// + /// Behaves as if [wait] was called on each of the [handleTokens] separately, + /// completing when the first would complete. + static List waitMany( + List handleTokens, List signals, int deadline) { + throw new UnsupportedError("MojoHandleNatives.wainMany on contract"); + } +} + +class MojoMessagePipeNatives { + /// Creates a message pipe represented by its two endpoints (handles). + /// + /// Returns a list with exactly 3 elements: + /// - the result integer, encoded as specified in [MojoResult]. In particular, + /// [MojoResult.kOk] signals a successful creation. + /// - the two endpoints of the message pipe. These tokens can be used in the + /// methods of [MojoHandleNatives]. + /// + /// The parameter [flags] is reserved for future use and should currently be + /// set to [MojoMessagePipe.FLAG_NONE] (equal to 0). + static List MojoCreateMessagePipe(int flags) { + throw new UnsupportedError( + "MojoMessagePipeNatives.MojoCreateMessagePipe on contract"); + } + + /// Writes a message into the endpoint [handleToken]. + /// + /// Returns a result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful write. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// + /// A message is composed of [numBytes] bytes of [data], and a list of + /// [handleTokens]. + /// + /// The parameter [flags] is reserved for future use and should currently be + /// set to [MojoMessagePipeEndpoint.WRITE_FLAG_NONE] (equal to 0). + static int MojoWriteMessage(Object handleToken, ByteData data, int numBytes, + List handleTokens, int flags) { + throw new UnsupportedError( + "MojoMessagePipeNatives.MojoWriteMessage on contract"); + } + + /// Reads a message from the endpoint [handleToken]. + /// + /// Returns `null` if the parameters are invalid. Otherwise returns a list of + /// exactly 3 elements: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful read. + /// 2. the number of bytes read (or bytes available if the message couldn't + /// be read). + /// 3. the number of handles read (or handles available if the message + /// couldn't be read). + /// + /// If no message is available, the result-integer is set to + /// [MojoResult.kShouldWait]. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// + /// Both [data], and [handleTokens] may be null. If [data] is null, then + /// [numBytes] must be 0. + /// + /// A message is always read in its entirety. That is, if a message doesn't + /// fit into [data] and/or [handleTokens], then the message is left in the + /// pipe or discarded (see the description of [flags] below). + /// + /// If the message wasn't read because [data] or [handleTokens] was too small, + /// the result integer is set to [MojoResult.kResourceExhausted]. + /// + /// The returned list *always* contains the size of the message (independent + /// if it was actually read into [data] and [handleTokens]). + /// A common pattern thus consists of invoking this method with + /// [data] and [handleTokens] set to `null` to query the size of the next + /// message that is in the pipe. + /// + /// The parameter [flags] may set to either + /// [MojoMessagePipeEndpoint.READ_FLAG_NONE] (equal to 0) or + /// [MojoMessagePipeEndpoint.READ_FLAG_MAY_DISCARD] (equal to 1). In the + /// latter case messages that couldn't be read (for example, because the + /// [data] or [handleTokens] wasn't big enough) are discarded. + static List MojoReadMessage(Object handleToken, ByteData data, int numBytes, + List handleTokens, int flags) { + throw new UnsupportedError( + "MojoMessagePipeNatives.MojoReadMessage on contract"); + } + + /// Reads a message from the endpoint [handleToken]. + /// + /// The result is returned in the provided list [result], which must have + /// a length of at least 5. + /// + /// The elements in [result] are: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful read. This value is + /// only used as output. + /// 2. the [ByteData] data array. This entry is used both as input and output. + /// If the array is non-null and big enough it is used to store the + /// byte-data of the message. Otherwise a new [ByteData] array of the + /// required length is allocated and stored in this slot. + /// 3. a list, used to store handles. This entry is used both as input and + /// output. If the list is big enough it is filled with the read handles. + /// Otherwise, a new list of the required length is allocated and used + /// instead. + /// 4. the size of the read byte data. Only used as output. + /// 5. the number of read handles. Only used as output. + /// + /// The [handleToken] is a token that identifies the Mojo handle. + /// + /// The parameter [flags] may set to either + /// [MojoMessagePipeEndpoint.READ_FLAG_NONE] (equal to 0) or + /// [MojoMessagePipeEndpoint.READ_FLAG_MAY_DISCARD] (equal to 1). In the + /// latter case messages that couldn't be read are discarded. + /// + /// Also see [MojoReadMessage]. + static void MojoQueryAndReadMessage( + Object handleToken, int flags, List result) { + throw new UnsupportedError( + "MojoMessagePipeNatives.MojoQueryAndReadMessage on contract"); + } +} + +class MojoDataPipeNatives { + /// Creates a (unidirectional) data pipe represented by its two endpoints + /// (handles). + /// + /// Returns a list with exactly 3 elements: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful creation. + /// 2. the producer endpoint. A handle token. + /// 3. the consumer endpoint. A handle token. + /// + /// The parameter [elementBytes] specifies the size of an element in bytes. + /// All transactions and buffers consist of an integral number of elements. + /// The integer [elementBytes] must be non-zero. The default should be + /// [MojoDataPipe.DEFAULT_ELEMENT_SIZE] (equal to 1). + /// + /// The parameter [capacityBytes] specifies the capacity of the data-pipe, in + /// bytes. The parameter must be a multiple of [elementBytes]. The data-pipe + /// will always be able to queue *at least* this much data. If [capacityBytes] + /// is set to zero, a system-dependent automatically-calculated capacity is + /// used. The default should be [MojoDataPipe.DEFAULT_CAPACITY] (equal to 0). + /// + /// The parameter [flags] is reserved for future use and should currently be + /// set to [MojoDataPipe.FLAG_NONE] (equal to 0). + static List MojoCreateDataPipe( + int elementBytes, int capacityBytes, int flags) { + throw new UnsupportedError( + "MojoDataPipeNatives.MojoCreateDataPipe on contract"); + } + + /// Writes [numBytes] bytes from [data] into the producer handle. + /// + /// Returns an integer, encoding the result as specified in the [MojoResult] + /// class. In particular, a successful operation returns [MojoResult.kOk]. + /// + /// The argument [handleToken] must be a producer handle created through + /// [MojoCreateDataPipe]. + /// + /// The argument [numBytes] should be a multiple of the data pipe's + /// element size. + /// + /// The argument [flags] can be + /// - [MojoDataPipeProducer.FLAG_NONE] (equal to 0), or + /// - [MojoDataPipeProducer.FLAG_ALL_OR_NONE] (equal to 1). + /// + /// If [flags] is equal to [MojoDataPipeProducer.FLAG_ALL_OR_NONE], then + /// either all data is written, or none is. If the data can't be written, then + /// the result integer is set to [MojoResult.kOutOfRange]. + /// + /// If no data can currently be written to an open consumer (and [flags] is + /// *not* set to [MojoDataPipeProducer.FLAG_ALL_OR_NONE]), then the + /// result-integer is set to [MojoResult.kShouldWait]. + static List MojoWriteData( + Object handleToken, ByteData data, int numBytes, int flags) { + throw new UnsupportedError("MojoDataPipeNatives.MojoWriteData on contract"); + } + + /// Starts a two-phase write. + /// + /// Returns a List of exactly 2 elements: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// 2. a [ByteData] object (when successful), or `null` (if unsuccessful). + /// + /// The argument [handleToken] must be a producer handle created through + /// [MojoCreateDataPipe]. + /// + /// A two-phase write consists of requesting a buffer to write to (this + /// function), followed by a call to [MojoEndWriteData] to signal that the + /// buffer has been filled with data and is ready to write. + /// + /// While the system waits for the [MojoEndWriteData], the underlying + /// data pipe is set to non-writable. + /// + /// A two-phase write is only started if the result integer (the first + /// argument of the returned list) is equal to [MojoResult.kOk]. Otherwise, + /// the underlying pipe stays writable (assuming it was before), and does not + /// expect a call to [MojoEndWriteData]. + /// + /// The result integer is equal to [MojoResult.kBusy] if the pipe is already + /// executing a two-phase write. + /// + /// The parameter [flags] is reserved for future use and should currently be + /// set to [MojoDataPipeProducer.FLAG_NONE] (equal to 0). + static List MojoBeginWriteData(Object handleToken, int flags) { + throw new UnsupportedError( + "MojoDataPipeNatives.MojoBeginWriteData on contract"); + } + + /// Finishes a two-phase write. + /// + /// Returns a result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// + /// The argument [handleToken] must be a producer handle created through + /// [MojoCreateDataPipe] and must be the same that was given to a previous + /// call to [MojoBeginWriteData]. + /// + /// Writes [bytesWritten] bytes of the [ByteData] buffer provided by + /// [MojoBeginWriteData] into the pipe. The parameter [bytesWritten] must be + /// less or equal to the size of the [ByteData] buffer and must be a multiple + /// of the data pipe's element size. + static int MojoEndWriteData(Object handleToken, int bytesWritten) { + throw new UnsupportedError( + "MojoDataPipeNatives.MojoEndWriteData on contract"); + } + + /// Reads up to [numBytes] from the given consumer [handleToken]. + /// + /// Returns a list of exactly two elements: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// 2. an integer `readBytes` (having different semantics depending on the + /// flags. See below for the different cases. + /// + /// The argument [handleToken] must be a consumer handle created through + /// [MojoCreateDataPipe]. + /// + /// The argument [numBytes] must be a multiple of the data pipe's element + /// size. + /// + /// If [flags] has neither [MojoDataPipeConsumer.FLAG_DISCARD] (equal to 2), + /// nor [MojoDataPipeConsumer.FLAG_QUERY] (equal to 4) set, tries to read up + /// to [numBytes] bytes of data into the [data] buffer and set + /// `readBytes` (the second element of the returned list) to the amount + /// actually read. + /// + /// If [flags] has [MojoDataPipeConsumer.FLAG_ALL_OR_NONE] (equal to 1) set, + /// either reads exactly [numBytes] bytes of data or none. Additionally, if + /// [flags] has [MojoDataPipeConsumer.FLAG_PEEK] (equal to 8) set, the data + /// read remains in the pipe and is available to future reads. + /// + /// If [flags] has [MojoDataPipeConsumer.FLAG_DISCARD] (equal to 2) set, it + /// discards up to [numBytes] (which again must be a multiple of the element + /// size) bytes of data, setting `readBytes` to the amount actually + /// discarded. If [flags] has [MojoDataPipeConsumer.FLAG_ALL_OR_NONE] (equal + /// to 1), either discards exactly [numBytes] bytes of data or none. In this + /// case, [MojoDataPipeConsumer.FLAG_QUERY] must not be set, and + /// the [data] buffer is ignored (and should typically be set to + /// null). + /// + /// If flags has [MojoDataPipeConsumer.FLAG_QUERY] set, queries the amount of + /// data available, setting `readBytes` to the number of bytes available. In + /// this case, [MojoDataPipeConsumer.FLAG_DISCARD] must not be set, and + /// [MojoDataPipeConsumer.FLAG_ALL_OR_NONE] is ignored, as are [data] and + /// [numBytes]. + static List MojoReadData( + Object handleToken, ByteData data, int numBytes, int flags) { + throw new UnsupportedError("MojoDataPipeNatives.MojoReadData on contract"); + } + + /// Starts a two-phase read. + /// + /// Returns a List of exactly 2 elements: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// 2. a [ByteData] object (when successful), or `null` (if unsuccessful). + /// + /// The argument [handleToken] must be a consumer handle created through + /// [MojoCreateDataPipe]. + /// + /// A two-phase write consists of requesting a buffer to read from (this + /// function), followed by a call to [MojoEndReadData] to signal that the + /// buffer has been read. + /// + /// While the system waits for the [MojoEndReadData], the underlying + /// data pipe is set to non-readable. + /// + /// A two-phase read is only started if the result integer (the first + /// argument of the returned list) is equal to [MojoResult.kOk]. Otherwise, + /// the underlying pipe stays readable (assuming it was before), and does not + /// expect a call to [MojoEndReadData]. + /// + /// The result integer is equal to [MojoResult.kBusy] if the pipe is already + /// executing a two-phase read. + /// + /// The result integer is equal to [MojoResult.kShouldWait] if the pipe has + /// no data available. + /// + /// The parameter [flags] is reserved for future use and should currently be + /// set to [MojoDataPipeConsumer.FLAG_NONE] (equal to 0). + static List MojoBeginReadData(Object handleToken, int flags) { + throw new UnsupportedError( + "MojoDataPipeNatives.MojoBeginReadData on contract"); + } + + /// Finishes a two-phase read. + /// + /// Returns a result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// + /// The argument [handleToken] must be a consumer handle created through + /// [MojoCreateDataPipe] and must be the same that was given to a previous + /// call to [MojoBeginReadData]. + /// + /// Consumes [bytesRead] bytes of the [ByteData] buffer provided by + /// [MojoBeginReadData]. The parameter [bytesWritten] must be + /// less or equal to the size of the [ByteData] buffer and must be a multiple + /// of the data pipe's element size. + static int MojoEndReadData(Object handleToken, int bytesRead) { + throw new UnsupportedError( + "MojoDataPipeNatives.MojoEndReadData on contract"); + } +} + +class MojoSharedBufferNatives { + /// Creates a shared buffer of [numBytes] bytes. + /// + /// Returns a List of exactly 2 elements: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// 2. a handle. + /// + /// A shared buffer can be shared between applications (by duplicating the + /// handle -- see [Duplicate] -- and passing it over a message pipe). + /// + /// A shared buffer can be accessed through by invoking [Map]. + /// + /// The parameter [flags] is reserved for future use and should currently be + /// set to [MojoSharedBuffer.createFlagNone] (equal to 0). + static List Create(int numBytes, int flags) { + throw new UnsupportedError("MojoSharedBufferNatives.Create on contract"); + } + + /// Duplicates the given [bufferHandleToken] so that it can be shared through + /// a message pipe. + /// + /// Returns a list of exactly 2 elements: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// 2. the duplicated handle. + /// + /// The [bufferHandleToken] must be a handle created by [Create]. + /// + /// Creates another handle (returned as second element in the returned list) + /// which can then be sent to another application over a message pipe, while + /// retaining access to the [bufferHandleToken] (and any mappings that it may + /// have). + /// + /// The parameter [flags] is reserved for future use and should currently be + /// set to [MojoSharedBuffer.duplicateFlagNone] (equal to 0). + static List Duplicate(Object bufferHandleToken, int flags) { + throw new UnsupportedError("MojoSharedBufferNatives.Duplicate on contract"); + } + + /// Maps the given [bufferHandleToken] so that its data can be access through + /// a [ByteData] buffer. + /// + /// Returns a list of exactly 2 elements: + /// 1. the result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// 2. a [ByteData] buffer that maps to the data in the shared buffer. + /// + /// The [bufferHandleToken] must be a handle created by [Create]. + /// + /// Maps [numBytes] of data, starting at offset [offset] into a [ByteData] + /// buffer. + /// + /// Note: there is no `unmap` call, since this is supposed to happen via + /// finalizers. + /// + /// The parameter [flags] is reserved for future use and should currently be + /// set to [MojoSharedBuffer.mapFlagNone] (equal to 0). + static List Map( + Object bufferHandleToken, int offset, int numBytes, int flags) { + throw new UnsupportedError("MojoSharedBufferNatives.Map on contract"); + } + + /// Returns information about [bufferHandleToken]. + /// + /// Returns a list of exactly 3 elements: + /// 1. The result integer, encoded as specified in [MojoResult]. In + /// particular, [MojoResult.kOk] signals a successful operation. + /// 2. The flags of the buffer (currently unused). + /// 3. The size of the buffer (in bytes). + /// + /// The [bufferHandleToken] must be a handle created by [Create]. + static List GetInformation(Object bufferHandleToken) { + throw new UnsupportedError( + "MojoSharedBufferNatives.GetInformation on contract"); + } +} diff --git a/mojo/dart/packages/mojo/lib/src/message_pipe.dart b/mojo/dart/packages/mojo/lib/src/message_pipe.dart index 7ecf10137393f..e687bcd1026fc 100644 --- a/mojo/dart/packages/mojo/lib/src/message_pipe.dart +++ b/mojo/dart/packages/mojo/lib/src/message_pipe.dart @@ -84,9 +84,9 @@ class MojoMessagePipeEndpoint { } // handles may be null, otherwise convert to ints. - List mojoHandles; + List mojoHandles; if (handles != null) { - mojoHandles = new List(handles.length); + mojoHandles = new List(handles.length); for (int i = 0; i < handles.length; i++) { mojoHandles[i] = handles[i].h; } diff --git a/mojo/dart/packages/mojo/lib/src/proxy.dart b/mojo/dart/packages/mojo/lib/src/proxy.dart index 9ca4f13b79d26..77197d64fe245 100644 --- a/mojo/dart/packages/mojo/lib/src/proxy.dart +++ b/mojo/dart/packages/mojo/lib/src/proxy.dart @@ -4,13 +4,71 @@ part of bindings; +/// The object that [ProxyMessageHandler.errorFuture] completes with when there +/// is an error. class ProxyError { final String message; ProxyError(this.message); String toString() => "ProxyError: $message"; } -abstract class Proxy extends core.MojoEventHandler { +/// Generated ProxyControl classes implement this interface. +/// ProxyControl objects are accessible through the [ctrl] field on Proxies. +abstract class ProxyControl implements ProxyMessageHandler { + // TODO(zra): This is only used by ApplicationConnection.requestService(), so + // try to remove when/after ApplicationConnection is removed/refactored. + String get serviceName; + + // Currently we don't have impl hooked up to anything for Proxies, but we have + // the field here so that there is a consistent interface with Stubs. By + // having the field here we can also retain the option of hooking a proxy + // up to something other than the remote implementation in the future. + T impl; +} + +/// Generated Proxy classes extend this base class. +class Proxy implements MojoInterface { + // In general it's probalby better to avoid adding fields and methods to this + // class. Names added to this class have to be mangled by Mojo bindings + // generation to avoid name conflicts. + + /// Proxies control the ProxyMessageHandler by way of this [ProxyControl] + /// object. + final ProxyControl ctrl; + + Proxy(this.ctrl); + + /// This is a convenience method that simply forwards to ctrl.close(). + /// If a Mojo interface has a method 'close', its name will be mangled to be + /// 'close_'. + Future close({bool immediate: false}) => ctrl.close(immediate: immediate); + + /// This is a convenience method that simply forwards to + /// ctrl.responseOrError(). If a Mojo interface has a method + /// 'responseOrError', its name will be mangled to be 'responseOrError_'. + Future responseOrError(Future f) => ctrl.responseOrError(f); + + /// This getter and setter pair is for convenience and simply forwards to + /// ctrl.impl. If a Mojo interface has a method 'close', its name will be + /// mangled to be 'impl_'. + T get impl => ctrl.impl; + set impl(T impl) { + ctrl.impl = impl; + } +} + +/// Generated Proxy classes have a factory Proxy.connectToService which takes +/// a ServiceConnector, a url, and optionally a service name and returns a +/// bound Proxy. For example, every class extending the Application base class +/// in package:mojo/application.dart inherits an implementation of the +/// ServiceConnector interface. +abstract class ServiceConnector { + /// Connects [proxy] to the service called [serviceName] that lives at [url]. + void connectToService(String url, Proxy proxy, [String serviceName]); +} + +abstract class ProxyMessageHandler extends core.MojoEventHandler + implements MojoInterfaceControl { HashMap _completerMap = new HashMap(); Completer _errorCompleter = new Completer(); Set _errorCompleters; @@ -18,14 +76,18 @@ abstract class Proxy extends core.MojoEventHandler { int _version = 0; int _pendingCount = 0; - Proxy.fromEndpoint(core.MojoMessagePipeEndpoint endpoint) + ProxyMessageHandler.fromEndpoint(core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint); - Proxy.fromHandle(core.MojoHandle handle) : super.fromHandle(handle); + ProxyMessageHandler.fromHandle(core.MojoHandle handle) + : super.fromHandle(handle); - Proxy.unbound() : super.unbound(); + ProxyMessageHandler.unbound() : super.unbound(); - void handleResponse(ServiceMessage reader); + /// The function that handles responses to sent proxy message. It should be + /// implemented by the generated ProxyControl classes that extend + /// [ProxyMessageHandler]. + void handleResponse(ServiceMessage msg); /// If there is an error in using this proxy, this future completes with /// a ProxyError. @@ -40,6 +102,7 @@ abstract class Proxy extends core.MojoEventHandler { /// Note: The description is null or incomplete if type info is unavailable. service_describer.ServiceDescription get description => null; + @override void handleRead() { var result = endpoint.queryAndRead(); if ((result.data == null) || (result.dataLength == 0)) { @@ -61,6 +124,7 @@ abstract class Proxy extends core.MojoEventHandler { } } + @override void handleWrite() { proxyError("Unexpected writable signal"); } @@ -71,9 +135,9 @@ abstract class Proxy extends core.MojoEventHandler { // complete. _completerMap.clear(); - // Signal to any pending calls that the Proxy is closed. + // Signal to any pending calls that the ProxyMessageHandler is closed. if (_pendingCount > 0) { - proxyError("The Proxy is closed."); + proxyError("The ProxyMessageHandler is closed."); } return super.close(immediate: immediate); @@ -81,7 +145,7 @@ abstract class Proxy extends core.MojoEventHandler { void sendMessage(Struct message, int name) { if (!isBound) { - proxyError("The Proxy is closed."); + proxyError("The ProxyMessageHandler is closed."); return; } if (!isOpen) { @@ -99,7 +163,7 @@ abstract class Proxy extends core.MojoEventHandler { Future sendMessageWithRequestId(Struct message, int name, int id, int flags) { var completer = new Completer(); if (!isBound) { - proxyError("The Proxy is closed."); + proxyError("The ProxyMessageHandler is closed."); return completer.future; } if (!isOpen) { @@ -126,9 +190,10 @@ abstract class Proxy extends core.MojoEventHandler { // Need a getter for this for access in subclasses. HashMap get completerMap => _completerMap; + @override String toString() { var superString = super.toString(); - return "Proxy(${superString})"; + return "ProxyMessageHandler(${superString})"; } /// Queries the max version that the remote side supports. @@ -186,7 +251,7 @@ abstract class Proxy extends core.MojoEventHandler { /// Example usage: /// /// try { - /// result = await MyProxy.responseOrError(MyProxy.ptr.call(a,b,c)); + /// result = await myProxy.responseOrError(myProxy.call(a,b,c)); /// } catch (e) { /// ... /// } @@ -241,20 +306,3 @@ abstract class Proxy extends core.MojoEventHandler { c.complete(response); } } - -/// Generated Proxy classes implement this interface. -abstract class ProxyBase { - final Proxy impl = null; - final String serviceName = null; - Object get ptr; -} - -/// Generated Proxy classes have a factory Proxy.connectToService which takes -/// a ServiceConnector, a url, and optionally a service name and returns a -/// bound Proxy. For example, every class extending the Application base class -/// in package:mojo/application.dart inherits and implementation of the -/// ServiceConnector interface. -abstract class ServiceConnector { - /// Connects [proxy] to the service called [serviceName] that lives at [url]. - void connectToService(String url, ProxyBase proxy, [String serviceName]); -} diff --git a/mojo/dart/packages/mojo/lib/src/stub.dart b/mojo/dart/packages/mojo/lib/src/stub.dart index 2b95ea777ee2a..88715488838a3 100644 --- a/mojo/dart/packages/mojo/lib/src/stub.dart +++ b/mojo/dart/packages/mojo/lib/src/stub.dart @@ -4,22 +4,67 @@ part of bindings; -abstract class Stub extends core.MojoEventHandler { +/// Generated StubControl classes implement this interface. +/// StubControl objects are accessible through the [ctrl] field on Stubs. +abstract class StubControl implements StubMessageHandler { + // TODO(zra): This is only used by ApplicationConnection.requestService(), so + // try to remove when/after ApplicationConnection is removed/refactored. + String get serviceName; + + /// [impl] refers to the implementation of the methods of the interface T. + T impl; +} + +/// Generated Stub classes extend this base class. +class Stub implements MojoInterface { + // In general it's probalby better to avoid adding fields and methods to this + // class. Names added to this class have to be mangled by Mojo bindings + // generation to avoid name conflicts. + + /// Proxies control the StubMessageHandler by way of this [StubControl] + /// object. + final StubControl ctrl; + + Stub(this.ctrl); + + /// This is a convenience method that simply forwards to ctrl.close(). + /// If a Mojo interface has a method 'close', its name will be mangled to be + /// 'close_'. + Future close({bool immediate: false}) => ctrl.close(immediate: immediate); + + /// This getter and setter pair is for convenience and simply forwards to + /// ctrl.impl. If a Mojo interface has a method 'impl', its name will be + /// mangled to be 'impl_'. + T get impl => ctrl.impl; + set impl(T impl) { + ctrl.impl = impl; + } +} + +abstract class StubMessageHandler extends core.MojoEventHandler + implements MojoInterfaceControl { int _outstandingResponseFutures = 0; bool _isClosing = false; Completer _closeCompleter; - Stub.fromEndpoint(core.MojoMessagePipeEndpoint endpoint, - {bool autoBegin: true}) + StubMessageHandler.fromEndpoint(core.MojoMessagePipeEndpoint endpoint, + {bool autoBegin: true}) : super.fromEndpoint(endpoint, autoBegin: autoBegin); - Stub.fromHandle(core.MojoHandle handle, {bool autoBegin: true}) + StubMessageHandler.fromHandle(core.MojoHandle handle, {bool autoBegin: true}) : super.fromHandle(handle, autoBegin: autoBegin); - Stub.unbound() : super.unbound(); + StubMessageHandler.unbound() : super.unbound(); + /// Generated StubControl classes implement this method to route messages to + /// the correct implementation method. dynamic handleMessage(ServiceMessage message); + /// Generated StubControl classes implement this getter to return the version + /// of the mojom interface for which the bindings are generated. + int get version; + + @override void handleRead() { var result = endpoint.queryAndRead(); if ((result.data == null) || (result.dataLength == 0)) { @@ -64,29 +109,7 @@ abstract class Stub extends core.MojoEventHandler { } } - void _sendResponse(Message response) { - if (isOpen) { - endpoint.write( - response.buffer, response.buffer.lengthInBytes, response.handles); - // FailedPrecondition is only used to indicate that the other end of - // the pipe has been closed. We can ignore the close here and wait for - // the PeerClosed signal on the event stream. - assert((endpoint.status == core.MojoResult.kOk) || - (endpoint.status == core.MojoResult.kFailedPrecondition)); - if (_isClosing && (_outstandingResponseFutures == 0)) { - // This was the final response future for which we needed to send - // a response. It is safe to close. - super.close().then((_) { - if (_isClosing) { - _isClosing = false; - _closeCompleter.complete(null); - _closeCompleter = null; - } - }); - } - } - } - + @override void handleWrite() { throw 'Unexpected write signal in client.'; } @@ -128,15 +151,37 @@ abstract class Stub extends core.MojoEventHandler { return response.serializeWithHeader(header); } + @override String toString() { var superString = super.toString(); - return "Stub(${superString})"; + return "StubMessageHandler(${superString})"; } - int get version; - /// Returns a service description, which exposes the mojom type information /// of the service being stubbed. /// Note: The description is null or incomplete if type info is unavailable. service_describer.ServiceDescription get description => null; + + void _sendResponse(Message response) { + if (isOpen) { + endpoint.write( + response.buffer, response.buffer.lengthInBytes, response.handles); + // FailedPrecondition is only used to indicate that the other end of + // the pipe has been closed. We can ignore the close here and wait for + // the PeerClosed signal on the event stream. + assert((endpoint.status == core.MojoResult.kOk) || + (endpoint.status == core.MojoResult.kFailedPrecondition)); + if (_isClosing && (_outstandingResponseFutures == 0)) { + // This was the final response future for which we needed to send + // a response. It is safe to close. + super.close().then((_) { + if (_isClosing) { + _isClosing = false; + _closeCompleter.complete(null); + _closeCompleter = null; + } + }); + } + } + } } diff --git a/mojo/dart/packages/mojo/pubspec.yaml b/mojo/dart/packages/mojo/pubspec.yaml index 6fb178cd0c75a..0ba66cf6f96c9 100644 --- a/mojo/dart/packages/mojo/pubspec.yaml +++ b/mojo/dart/packages/mojo/pubspec.yaml @@ -2,4 +2,4 @@ author: Chromium Authors description: Dart files to support executing inside Mojo. homepage: https://github.com/domokit/mojo name: mojo -version: 0.4.20 +version: 0.4.23 diff --git a/mojo/dart/packages/mojo/sdk_ext/src/handle_watcher.dart b/mojo/dart/packages/mojo/sdk_ext/src/handle_watcher.dart index 3e6201a0f4105..2d508f89e707d 100644 --- a/mojo/dart/packages/mojo/sdk_ext/src/handle_watcher.dart +++ b/mojo/dart/packages/mojo/sdk_ext/src/handle_watcher.dart @@ -4,8 +4,6 @@ part of internal; -/// This class contains static methods to send a stream of events to application -/// isolates that register Mojo handles with it. class MojoHandleWatcher { // Control commands. static const int _ADD = 0; @@ -32,19 +30,6 @@ class MojoHandleWatcher { return result; } - /// Stops watching and closes the given [handleToken]. - /// - /// Returns an integer, encoding the result as specified in the [MojoResult] - /// class. In particular, a successful operation returns [MojoResult.kOk]. - /// - /// Notifies the HandleWatcherIsolate that a handle it is - /// watching should be removed from its set and closed. - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// - /// If [wait] is true, returns a future that resolves only after the handle - // has actually been closed by the handle watcher. Otherwise, returns a - // future that resolves immediately. static Future close(int handleToken, {bool wait: false}) { if (!wait) { return new Future.value(_sendControlData(_CLOSE, handleToken, null, 0)); @@ -61,55 +46,14 @@ class MojoHandleWatcher { }); } - /// Starts watching for events on the given [handleToken]. - /// - /// Returns an integer, encoding the result as specified in the [MojoResult] - /// class. In particular, a successful operation returns [MojoResult.kOk]. - /// - /// Instructs the MojoHandleWatcher isolate to add [handleToken] to the set of - /// handles it watches, and to notify the calling isolate only for the events - /// specified by [signals] using the send port [port]. - // TODO(floitsch): what does "MojoHandleWatcher isolate" mean? - // TODO(floitsch): what is the calling isolate? - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// - /// The filtering [signals] are encoded as specified in the - /// [MojoHandleSignals] class. For example, setting [signals] to - /// [MojoHandleSignals.kPeerClosedReadable] instructs the handle watcher to - /// notify the caller, when the handle becomes readable (that is, has data - /// available for reading), or when it is closed. static int add(int handleToken, SendPort port, int signals) { return _sendControlData(_ADD, handleToken, port, signals); } - /// Stops watching the given [handleToken]. - /// - /// Returns an integer, encoding the result as specified in the [MojoResult] - /// class. In particular, a successful operation returns [MojoResult.kOk]. - /// - /// Instructs the MojoHandleWatcher isolate to remove [handleToken] from the - /// set of handles it watches. This allows the application isolate - /// to, for example, pause the stream of events. - /// - /// The [handleToken] is a token that identifies the Mojo handle. static int remove(int handleToken) { return _sendControlData(_REMOVE, handleToken, null, 0); } - /// Requests a notification on the given [port] at [deadline]. - /// - /// Returns an integer, encoding the result as specified in the [MojoResult] - /// class. In particular, a successful operation returns [MojoResult.kOk]. - /// - /// The [deadline] is in milliseconds, with - /// [MojoCoreNatives.timerMillisecondClock] as reference. - /// - /// If the given [port] was already registered for a timer (in any isolate), - /// then the old value is discarded. - /// - /// A negative [deadline] is used to remove a port. That is, a negative value - /// is ignored after any existing value for the port has been discarded. static int timer(Object ignored, SendPort port, int deadline) { // The deadline will be unwrapped before sending to the handle watcher. return _sendControlData(_TIMER, deadline, port, 0); diff --git a/mojo/dart/packages/mojo/sdk_ext/src/natives.dart b/mojo/dart/packages/mojo/sdk_ext/src/natives.dart index dc0de37f87c19..16f7c41531b10 100644 --- a/mojo/dart/packages/mojo/sdk_ext/src/natives.dart +++ b/mojo/dart/packages/mojo/sdk_ext/src/natives.dart @@ -12,32 +12,14 @@ class _OpenHandle { } class MojoCoreNatives { - /// 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. static int getTimeTicksNow() native "Mojo_GetTimeTicksNow"; - /// Returns the time, in milliseconds, since some undefined point in the past. - /// - /// This method is equivalent to `getTimeTicksNow() ~/ 1000`. static int timerMillisecondClock() => getTimeTicksNow() ~/ 1000; } class MojoHandleNatives { static HashMap _openHandles = new HashMap(); - /// Puts the given [handleToken] with the given [description] into the set of - /// open handles. - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// - /// This method is only used to report open handles (see [reportOpenHandles]). static void addOpenHandle(int handleToken, {String description}) { var stack; // We only remember a stack trace when in checked mode. @@ -46,14 +28,6 @@ class MojoHandleNatives { _openHandles[handleToken] = openHandle; } - /// Removes the given [handleToken] from the set of open handles. - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// - /// This method is only used to report open handles (see [reportOpenHandles]). - /// - /// Handles are removed from the set when they are closed, but also, when they - /// are serialized in the mojo encoder [codec.dart]. static void removeOpenHandle(int handleToken) { _openHandles.remove(handleToken); } @@ -73,14 +47,6 @@ class MojoHandleNatives { print(sb.toString()); } - /// Prints a list of all open handles. - /// - /// Returns `true` if there are no open handles. - /// - /// Prints all handles that have been added with [addOpenHandle] but haven't - /// been removed with [removeOpenHandle]. - /// - /// Programs should not have open handles when the program terminates. static bool reportOpenHandles() { if (_openHandles.length == 0) { return true; @@ -89,12 +55,6 @@ class MojoHandleNatives { return false; } - /// Updates the description of the given [handleToken] in the set of open - /// handles. - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// - /// Does nothing, if the [handleToken] isn't in the set. static bool setDescription(int handleToken, String description) { _OpenHandle openHandle = _openHandles[handleToken]; if (openHandle != null) { @@ -103,71 +63,14 @@ class MojoHandleNatives { return true; } - /// Registers a finalizer on [eventSubscription] to close the given - /// [handleToken]. - /// - /// Returns an integer, encoding the result as specified in the [MojoResult] - /// class. In particular, a successful operation returns [MojoResult.kOk]. - /// - /// When [eventSubscription] (currently an Instance of the - /// [MojoEventSubscription] class) is garbage-collected, invokes [close] on - /// the [handleToken]. - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// Since the token can be an integer, it's not possible to install the - /// finalizer directly on the token. static int registerFinalizer(Object eventSubscription, int handleToken) native "MojoHandle_RegisterFinalizer"; - /// Closes the given [handleToken]. - /// - /// Returns an integer, encoding the result as specified in the [MojoResult] - /// class. In particular, a successful operation returns [MojoResult.kOk]. - /// - /// The [handleToken] is a token that identifies the Mojo handle. static int close(int handleToken) native "MojoHandle_Close"; - /// Waits on the given [handleToken] for a signal. - /// - /// Returns a list of two elements. The first entry is an integer, encoding - /// if the operation was a success or not, as specified in the [MojoResult] - /// class. In particular, a successful operation is signaled by - /// [MojoResult.kOk]. The second entry is itself a list of 2 elements: - /// an integer of satisfied signals, and an integer of satisfiable signals. - /// Both entries are encoded as specified in [MojoHandleSignals]. - /// - /// A signal is satisfiable, if the signal may become true in the future. - /// - /// The [deadline] specifies how long the call should wait (if no signal is - /// triggered). If the deadline passes, the returned result-integer is - /// [MojoResult.kDeadlineExceeded]. If the deadline is 0, then the result - /// is only [MojoResult.kDeadlineExceeded] if no other termination condition - /// is already satisfied (see below). - /// - /// The [signals] integer encodes the signals this method should wait for. - /// The integer is encoded as specified in [MojoHandleSignals]. - /// - /// Waits on the given handle until one of the following happens: - /// - A signal indicated by [signals] is satisfied. - /// - It becomes known that no signal indicated by [signals] will ever be - /// satisfied (for example the handle has been closed on the other side). - /// - The [deadline] has passed. static List wait(int handleToken, int signals, int deadline) native "MojoHandle_Wait"; - /// Waits on many handles at the same time. - /// - /// Returns a list with exactly 3 elements: - /// - the result integer, encoded as specified in [MojoResult]. In particular, - /// [MojoResult.kOk] signals success. - /// - the index of the handle that caused the return. May be `null` if the - /// operation didn't succeed. - /// - a list of signal states. May be `null` if the operation didn't succeed. - /// Each signal state is represented by a list of 2 elements: an integer of - /// satisfied signals, and an integer of satisfiable signals (see [wait]). - /// - /// Behaves as if [wait] was called on each of the [handleTokens] separately, - /// completing when the first would complete. static List waitMany(List handleTokens, List signals, int deadline) native "MojoHandle_WaitMany"; @@ -195,362 +98,50 @@ class _MojoHandleWatcherNatives { } class MojoMessagePipeNatives { - /// Creates a message pipe represented by its two endpoints (handles). - /// - /// Returns a list with exactly 3 elements: - /// - the result integer, encoded as specified in [MojoResult]. In particular, - /// [MojoResult.kOk] signals a successful creation. - /// - the two endpoints of the message pipe. These tokens can be used in the - /// methods of [MojoHandleNatives]. - /// - /// The parameter [flags] is reserved for future use and should currently be - /// set to [MojoMessagePipe.FLAG_NONE] (equal to 0). static List MojoCreateMessagePipe(int flags) native "MojoMessagePipe_Create"; - /// Writes a message into the endpoint [handleToken]. - /// - /// Returns a result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful write. - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// - /// A message is composed of [numBytes] bytes of [data], and a list of - /// [handleTokens]. - /// - /// The parameter [flags] is reserved for future use and should currently be - /// set to [MojoMessagePipeEndpoint.WRITE_FLAG_NONE] (equal to 0). static int MojoWriteMessage(int handleToken, ByteData data, int numBytes, List handles, int flags) native "MojoMessagePipe_Write"; - /// Reads a message from the endpoint [handleToken]. - /// - /// Returns `null` if the parameters are invalid. Otherwise returns a list of - /// exactly 3 elements: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful read. - /// 2. the number of bytes read (or bytes available if the message couldn't - /// be read). - /// 3. the number of handles read (or handles available if the message - /// couldn't be read). - /// - /// If no message is available, the result-integer is set to - /// [MojoResult.kShouldWait]. - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// - /// Both [data], and [handleTokens] may be null. If [data] is null, then - /// [numBytes] must be 0. - /// - /// A message is always read in its entirety. That is, if a message doesn't - /// fit into [data] and/or [handleTokens], then the message is left in the - /// pipe or discarded (see the description of [flags] below). - /// - /// If the message wasn't read because [data] or [handleTokens] was too small, - /// the result integer is set to [MojoResult.kResourceExhausted]. - /// - /// The returned list *always* contains the size of the message (independent - /// if it was actually read into [data] and [handleTokens]). - /// A common pattern thus consists of invoking this method with - /// [data] and [handleTokens] set to `null` to query the size of the next - /// message that is in the pipe. - /// - /// The parameter [flags] may set to either - /// [MojoMessagePipeEndpoint.READ_FLAG_NONE] (equal to 0) or - /// [MojoMessagePipeEndpoint.READ_FLAG_MAY_DISCARD] (equal to 1). In the - /// latter case messages that couldn't be read (for example, because the - /// [data] or [handleTokens] wasn't big enough) are discarded. static List MojoReadMessage(int handleToken, ByteData data, int numBytes, List handleTokens, int flags) native "MojoMessagePipe_Read"; - /// Reads a message from the endpoint [handleToken]. - /// - /// The result is returned in the provided list [result], which must have - /// a length of at least 5. - /// - /// The elements in [result] are: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful read. This value is - /// only used as output. - /// 2. the [ByteData] data array. This entry is used both as input and output. - /// If the array is non-null and big enough it is used to store the - /// byte-data of the message. Otherwise a new [ByteData] array of the - /// required length is allocated and stored in this slot. - /// 3. a list, used to store handles. This entry is used both as input and - /// output. If the list is big enough it is filled with the read handles. - /// Otherwise, a new list of the required length is allocated and used - /// instead. - /// 4. the size of the read byte data. Only used as output. - /// 5. the number of read handles. Only used as output. - /// - /// The [handleToken] is a token that identifies the Mojo handle. - /// - /// The parameter [flags] may set to either - /// [MojoMessagePipeEndpoint.READ_FLAG_NONE] (equal to 0) or - /// [MojoMessagePipeEndpoint.READ_FLAG_MAY_DISCARD] (equal to 1). In the - /// latter case messages that couldn't be read are discarded. - /// - /// Also see [MojoReadMessage]. static void MojoQueryAndReadMessage(int handleToken, int flags, List result) native "MojoMessagePipe_QueryAndRead"; } class MojoDataPipeNatives { - /// Creates a (unidirectional) data pipe represented by its two endpoints - /// (handles). - /// - /// Returns a list with exactly 3 elements: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful creation. - /// 2. the producer endpoint. A handle token. - /// 3. the consumer endpoint. A handle token. - /// - /// The parameter [elementBytes] specifies the size of an element in bytes. - /// All transactions and buffers consist of an integral number of elements. - /// The integer [elementBytes] must be non-zero. The default should be - /// [MojoDataPipe.DEFAULT_ELEMENT_SIZE] (equal to 1). - /// - /// The parameter [capacityBytes] specifies the capacity of the data-pipe, in - /// bytes. The parameter must be a multiple of [elementBytes]. The data-pipe - /// will always be able to queue *at least* this much data. If [capacityBytes] - /// is set to zero, a system-dependent automatically-calculated capacity is - /// used. The default should be [MojoDataPipe.DEFAULT_CAPACITY] (equal to 0). - /// - /// The parameter [flags] is reserved for future use and should currently be - /// set to [MojoDataPipe.FLAG_NONE] (equal to 0). static List MojoCreateDataPipe(int elementBytes, int capacityBytes, int flags) native "MojoDataPipe_Create"; - /// Writes [numBytes] bytes from [data] into the producer handle. - /// - /// Returns an integer, encoding the result as specified in the [MojoResult] - /// class. In particular, a successful operation returns [MojoResult.kOk]. - /// - /// The argument [handleToken] must be a producer handle created through - /// [MojoCreateDataPipe]. - /// - /// The argument [numBytes] should be a multiple of the data pipe's - /// element size. - /// - /// The argument [flags] can be - /// - [MojoDataPipeProducer.FLAG_NONE] (equal to 0), or - /// - [MojoDataPipeProducer.FLAG_ALL_OR_NONE] (equal to 1). - /// - /// If [flags] is equal to [MojoDataPipeProducer.FLAG_ALL_OR_NONE], then - /// either all data is written, or none is. If the data can't be written, then - /// the result integer is set to [MojoResult.kOutOfRange]. - /// - /// If no data can currently be written to an open consumer (and [flags] is - /// *not* set to [MojoDataPipeProducer.FLAG_ALL_OR_NONE]), then the - /// result-integer is set to [MojoResult.kShouldWait]. static List MojoWriteData(int handle, ByteData data, int numBytes, int flags) native "MojoDataPipe_WriteData"; - /// Starts a two-phase write. - /// - /// Returns a List of exactly 2 elements: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// 2. a [ByteData] object (when successful), or `null` (if unsuccessful). - /// - /// The argument [handleToken] must be a producer handle created through - /// [MojoCreateDataPipe]. - /// - /// A two-phase write consists of requesting a buffer to write to (this - /// function), followed by a call to [MojoEndWriteData] to signal that the - /// buffer has been filled with data and is ready to write. - /// - /// While the system waits for the [MojoEndWriteData], the underlying - /// data pipe is set to non-writable. - /// - /// A two-phase write is only started if the result integer (the first - /// argument of the returned list) is equal to [MojoResult.kOk]. Otherwise, - /// the underlying pipe stays writable (assuming it was before), and does not - /// expect a call to [MojoEndWriteData]. - /// - /// The result integer is equal to [MojoResult.kBusy] if the pipe is already - /// executing a two-phase write. - /// - /// The parameter [flags] is reserved for future use and should currently be - /// set to [MojoDataPipeProducer.FLAG_NONE] (equal to 0). static List MojoBeginWriteData(int handleToken, int flags) native "MojoDataPipe_BeginWriteData"; - /// Finishes a two-phase write. - /// - /// Returns a result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// - /// The argument [handleToken] must be a producer handle created through - /// [MojoCreateDataPipe] and must be the same that was given to a previous - /// call to [MojoBeginWriteData]. - /// - /// Writes [bytesWritten] bytes of the [ByteData] buffer provided by - /// [MojoBeginWriteData] into the pipe. The parameter [bytesWritten] must be - /// less or equal to the size of the [ByteData] buffer and must be a multiple - /// of the data pipe's element size. static int MojoEndWriteData(int handleToken, int bytesWritten) native "MojoDataPipe_EndWriteData"; - /// Reads up to [numBytes] from the given consumer [handleToken]. - /// - /// Returns a list of exactly two elements: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// 2. an integer `readBytes` (having different semantics depending on the - /// flags. See below for the different cases. - /// - /// The argument [handleToken] must be a consumer handle created through - /// [MojoCreateDataPipe]. - /// - /// The argument [numBytes] must be a multiple of the data pipe's element - /// size. - /// - /// If [flags] has neither [MojoDataPipeConsumer.FLAG_DISCARD] (equal to 2), - /// nor [MojoDataPipeConsumer.FLAG_QUERY] (equal to 4) set, tries to read up - /// to [numBytes] bytes of data into the [data] buffer and set - /// `readBytes` (the second element of the returned list) to the amount - /// actually read. - /// - /// If [flags] has [MojoDataPipeConsumer.FLAG_ALL_OR_NONE] (equal to 1) set, - /// either reads exactly [numBytes] bytes of data or none. Additionally, if - /// [flags] has [MojoDataPipeConsumer.FLAG_PEEK] (equal to 8) set, the data - /// read remains in the pipe and is available to future reads. - /// - /// If [flags] has [MojoDataPipeConsumer.FLAG_DISCARD] (equal to 2) set, it - /// discards up to [numBytes] (which again must be a multiple of the element - /// size) bytes of data, setting `readBytes` to the amount actually - /// discarded. If [flags] has [MojoDataPipeConsumer.FLAG_ALL_OR_NONE] (equal - /// to 1), either discards exactly [numBytes] bytes of data or none. In this - /// case, [MojoDataPipeConsumer.FLAG_QUERY] must not be set, and - /// the [data] buffer is ignored (and should typically be set to - /// null). - /// - /// If flags has [MojoDataPipeConsumer.FLAG_QUERY] set, queries the amount of - /// data available, setting `readBytes` to the number of bytes available. In - /// this case, [MojoDataPipeConsumer.FLAG_DISCARD] must not be set, and - /// [MojoDataPipeConsumer.FLAG_ALL_OR_NONE] is ignored, as are [data] and - /// [numBytes]. static List MojoReadData(int handleToken, ByteData data, int numBytes, int flags) native "MojoDataPipe_ReadData"; - /// Starts a two-phase read. - /// - /// Returns a List of exactly 2 elements: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// 2. a [ByteData] object (when successful), or `null` (if unsuccessful). - /// - /// The argument [handleToken] must be a consumer handle created through - /// [MojoCreateDataPipe]. - /// - /// A two-phase write consists of requesting a buffer to read from (this - /// function), followed by a call to [MojoEndReadData] to signal that the - /// buffer has been read. - /// - /// While the system waits for the [MojoEndReadData], the underlying - /// data pipe is set to non-readable. - /// - /// A two-phase read is only started if the result integer (the first - /// argument of the returned list) is equal to [MojoResult.kOk]. Otherwise, - /// the underlying pipe stays readable (assuming it was before), and does not - /// expect a call to [MojoEndReadData]. - /// - /// The result integer is equal to [MojoResult.kBusy] if the pipe is already - /// executing a two-phase read. - /// - /// The result integer is equal to [MojoResult.kShouldWait] if the pipe has - /// no data available. - /// - /// The parameter [flags] is reserved for future use and should currently be - /// set to [MojoDataPipeConsumer.FLAG_NONE] (equal to 0). static List MojoBeginReadData(int handleToken, int flags) native "MojoDataPipe_BeginReadData"; - /// Finishes a two-phase read. - /// - /// Returns a result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// - /// The argument [handleToken] must be a consumer handle created through - /// [MojoCreateDataPipe] and must be the same that was given to a previous - /// call to [MojoBeginReadData]. - /// - /// Consumes [bytesRead] bytes of the [ByteData] buffer provided by - /// [MojoBeginReadData]. The parameter [bytesWritten] must be - /// less or equal to the size of the [ByteData] buffer and must be a multiple - /// of the data pipe's element size. static int MojoEndReadData(int handleToken, int bytesRead) native "MojoDataPipe_EndReadData"; } class MojoSharedBufferNatives { - /// Creates a shared buffer of [numBytes] bytes. - /// - /// Returns a List of exactly 2 elements: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// 2. a handle. - /// - /// A shared buffer can be shared between applications (by duplicating the - /// handle -- see [Duplicate] -- and passing it over a message pipe). - /// - /// A shared buffer can be accessed through by invoking [Map]. - /// - /// The parameter [flags] is reserved for future use and should currently be - /// set to [MojoSharedBuffer.createFlagNone] (equal to 0). static List Create(int numBytes, int flags) native "MojoSharedBuffer_Create"; - /// Duplicates the given [bufferHandleToken] so that it can be shared through - /// a message pipe. - /// - /// Returns a list of exactly 2 elements: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// 2. the duplicated handle. - /// - /// The [bufferHandleToken] must be a handle created by [Create]. - /// - /// Creates another handle (returned as second element in the returned list) - /// which can then be sent to another application over a message pipe, while - /// retaining access to the [bufferHandleToken] (and any mappings that it may - /// have). - /// - /// The parameter [flags] is reserved for future use and should currently be - /// set to [MojoSharedBuffer.duplicateFlagNone] (equal to 0). static List Duplicate(int bufferHandleToken, int flags) native "MojoSharedBuffer_Duplicate"; - /// Maps the given [bufferHandleToken] so that its data can be access through - /// a [ByteData] buffer. - /// - /// Returns a list of exactly 2 elements: - /// 1. the result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// 2. a [ByteData] buffer that maps to the data in the shared buffer. - /// - /// The [bufferHandleToken] must be a handle created by [Create]. - /// - /// Maps [numBytes] of data, starting at offset [offset] into a [ByteData] - /// buffer. - /// - /// Note: there is no `unmap` call, since this is supposed to happen via - /// finalizers. - /// - /// The parameter [flags] is reserved for future use and should currently be - /// set to [MojoSharedBuffer.mapFlagNone] (equal to 0). static List Map(int bufferHandleToken, int offset, int numBytes, int flags) native "MojoSharedBuffer_Map"; - - /// Returns information about [bufferHandleToken]. - /// - /// Returns a list of exactly 3 elements: - /// 1. The result integer, encoded as specified in [MojoResult]. In - /// particular, [MojoResult.kOk] signals a successful operation. - /// 2. The flags of the buffer (currently unused). - /// 3. The size of the buffer (in bytes). - /// - /// The [bufferHandleToken] must be a handle created by [Create]. static List GetInformation(int bufferHandleToken) native "MojoSharedBuffer_GetInformation"; } diff --git a/mojo/dart/packages/mojo/sources.gni b/mojo/dart/packages/mojo/sources.gni index 7e9fd8197fa2a..e457945665785 100644 --- a/mojo/dart/packages/mojo/sources.gni +++ b/mojo/dart/packages/mojo/sources.gni @@ -34,9 +34,13 @@ package_mojo_sources = [ "lib/src/data_pipe.dart", "lib/src/drain_data.dart", "lib/src/enum.dart", - "lib/src/event_stream.dart", + "lib/src/event_handler.dart", + "lib/src/event_subscription.dart", "lib/src/fill_data.dart", "lib/src/handle.dart", + "lib/src/interfaces.dart", + "lib/src/internal_contract.dart", + "lib/src/internal.dart", "lib/src/message.dart", "lib/src/message_pipe.dart", "lib/src/proxy.dart", diff --git a/mojo/dart/packages/mojo/test/standalone_test.dart b/mojo/dart/packages/mojo/test/standalone_test.dart new file mode 100644 index 0000000000000..62c983e484664 --- /dev/null +++ b/mojo/dart/packages/mojo/test/standalone_test.dart @@ -0,0 +1,27 @@ +// Copyright 2016 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. + +// Test that an import of 'package:mojo' doesn't fail on the VM. +import 'package:mojo/core.dart'; + +shouldThrowUnsupported(description, f) { + try { + f(); + throw "$description did not throw as expected."; + } catch (e) { + if (e is! UnsupportedError) { + throw "$description error is not an UnsupportedError $e."; + } + } +} + +main() { + var invalid = new MojoHandle.invalid(); + shouldThrowUnsupported("getTimeTicksNow()", () => getTimeTicksNow()); + shouldThrowUnsupported( + "MojoMessagePipe allocation", () => new MojoMessagePipe()); + shouldThrowUnsupported("MojoDataPipe allocation", () => new MojoDataPipe()); + shouldThrowUnsupported( + "MojoSharedBuffer allocation", () => new MojoSharedBuffer.create(1024)); +} diff --git a/mojo/data_pipe_utils/BUILD.gn b/mojo/data_pipe_utils/BUILD.gn index 0798050c6f3c8..53d297d43f1fb 100644 --- a/mojo/data_pipe_utils/BUILD.gn +++ b/mojo/data_pipe_utils/BUILD.gn @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//mojo/public/mojo_application.gni") + source_set("data_pipe_utils") { sources = [ "data_pipe_drainer.cc", @@ -27,7 +29,7 @@ source_set("data_pipe_utils") { ] } -source_set("tests") { +mojo_native_application("mojo_data_pipe_utils_apptests") { testonly = true sources = [ @@ -37,6 +39,8 @@ source_set("tests") { deps = [ ":data_pipe_utils", "//base", + "//mojo/application", + "//mojo/application:test_support", "//testing/gtest", ] } diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index ac2536209cb69..3724de1f1af7e 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc @@ -73,17 +73,20 @@ MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, DCHECK(platform_handle); DCHECK(internal::g_core); - RefPtr dispatcher; - MojoResult result = internal::g_core->GetDispatcher( - platform_handle_wrapper_handle, &dispatcher); + system::Handle h; + MojoResult result = + internal::g_core->GetHandle(platform_handle_wrapper_handle, &h); if (result != MOJO_RESULT_OK) return result; - if (dispatcher->GetType() != system::Dispatcher::Type::PLATFORM_HANDLE) + if (h.dispatcher->GetType() != system::Dispatcher::Type::PLATFORM_HANDLE) return MOJO_RESULT_INVALID_ARGUMENT; + if (!h.has_all_rights(MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE)) + return MOJO_RESULT_PERMISSION_DENIED; + *platform_handle = - static_cast(dispatcher.get()) + static_cast(h.dispatcher.get()) ->PassPlatformHandle(); return MOJO_RESULT_OK; } diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc index 44c1e2293cb15..260eae0b83f6e 100644 --- a/mojo/edk/embedder/entrypoints.cc +++ b/mojo/edk/embedder/entrypoints.cc @@ -27,6 +27,23 @@ MojoResult MojoClose(MojoHandle handle) { return g_core->Close(handle); } +MojoResult MojoGetRights(MojoHandle handle, MojoHandleRights* rights) { + return g_core->GetRights(handle, MakeUserPointer(rights)); +} + +MojoResult MojoDuplicateHandleWithReducedRights( + MojoHandle handle, + MojoHandleRights rights_to_remove, + MojoHandle* new_handle) { + return g_core->DuplicateHandleWithReducedRights(handle, rights_to_remove, + MakeUserPointer(new_handle)); +} + +MojoResult MojoDuplicateHandle(MojoHandle handle, MojoHandle* new_handle) { + return g_core->DuplicateHandleWithReducedRights( + handle, MOJO_HANDLE_RIGHT_NONE, MakeUserPointer(new_handle)); +} + MojoResult MojoWait(MojoHandle handle, MojoHandleSignals signals, MojoDeadline deadline, diff --git a/mojo/edk/embedder/system_impl_private_entrypoints.cc b/mojo/edk/embedder/system_impl_private_entrypoints.cc index 79cd3096dc76d..fb705c4038933 100644 --- a/mojo/edk/embedder/system_impl_private_entrypoints.cc +++ b/mojo/edk/embedder/system_impl_private_entrypoints.cc @@ -20,6 +20,7 @@ using mojo::embedder::internal::g_core; using mojo::system::Core; using mojo::system::Dispatcher; +using mojo::system::Handle; using mojo::system::MakeUserPointer; using mojo::util::RefPtr; @@ -55,23 +56,23 @@ MojoResult MojoSystemImplTransferHandle(MojoSystemImpl from_system, if (result_handle == nullptr) return MOJO_RESULT_INVALID_ARGUMENT; - RefPtr d; - MojoResult result = from_core->GetAndRemoveDispatcher(handle, &d); + Handle h; + MojoResult result = from_core->GetAndRemoveHandle(handle, &h); if (result != MOJO_RESULT_OK) return result; - // TODO(vtl): The rights should come from the original handle (to be dealt - // with when I fix/replace |Core::GetAndRemoveDispatcher()|. - MojoHandle created_handle = to_core->AddHandle(mojo::system::Handle( - d.Clone(), MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ | - MOJO_HANDLE_RIGHT_WRITE)); + MojoHandle created_handle = + to_core->AddHandle(Handle(h.dispatcher.Clone(), h.rights)); if (created_handle == MOJO_HANDLE_INVALID) { // The handle has been lost, unfortunately. There's no guarentee we can put // it back where it came from, or get the original ID back. Holding locks // for multiple cores risks deadlock, so that isn't a solution. This case // should not happen for reasonable uses of this API, however. + // TODO(vtl): This behaviour is pretty crappy. This can be fixed by marking + // the original handle as busy and only removing it on success, though + // that'd require some work. LOG(ERROR) << "Could not transfer handle"; - d->Close(); + h.dispatcher->Close(); return MOJO_RESULT_RESOURCE_EXHAUSTED; } @@ -91,6 +92,34 @@ MojoResult MojoSystemImplClose(MojoSystemImpl system, MojoHandle handle) { return core->Close(handle); } +MojoResult MojoSystemImplGetRights(MojoSystemImpl system, + MojoHandle handle, + MojoHandleRights* rights) { + mojo::system::Core* core = static_cast(system); + DCHECK(core); + return core->GetRights(handle, MakeUserPointer(rights)); +} + +MojoResult MojoSystemImplDuplicateHandleWithReducedRights( + MojoSystemImpl system, + MojoHandle handle, + MojoHandleRights rights_to_remove, + MojoHandle* new_handle) { + mojo::system::Core* core = static_cast(system); + DCHECK(core); + return core->DuplicateHandleWithReducedRights(handle, rights_to_remove, + MakeUserPointer(new_handle)); +} + +MojoResult MojoSystemImplDuplicateHandle(MojoSystemImpl system, + MojoHandle handle, + MojoHandle* new_handle) { + mojo::system::Core* core = static_cast(system); + DCHECK(core); + return core->DuplicateHandleWithReducedRights(handle, MOJO_HANDLE_RIGHT_NONE, + MakeUserPointer(new_handle)); +} + MojoResult MojoSystemImplWait(MojoSystemImpl system, MojoHandle handle, MojoHandleSignals signals, diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc index b52cba61157a5..7ce9e76d58a8a 100644 --- a/mojo/edk/system/channel.cc +++ b/mojo/edk/system/channel.cc @@ -408,7 +408,7 @@ void Channel::OnReadMessageForEndpoint( std::unique_ptr message(new MessageInTransit(message_view)); if (message_view.transport_data_buffer_size() > 0) { DCHECK(message_view.transport_data_buffer()); - message->SetDispatchers(TransportData::DeserializeDispatchers( + message->SetHandles(TransportData::DeserializeHandles( message_view.transport_data_buffer(), message_view.transport_data_buffer_size(), std::move(platform_handles), this)); diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index 9a167acf69a94..7780977918dd5 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc @@ -90,45 +90,58 @@ Core::Core(embedder::PlatformSupport* platform_support) : platform_support_(platform_support), handle_table_(GetConfiguration().max_handle_table_size) {} -Core::~Core() { -} +Core::~Core() {} MojoHandle Core::AddHandle(Handle&& handle) { MutexLocker locker(&handle_table_mutex_); return handle_table_.AddHandle(std::move(handle)); } -MojoResult Core::GetDispatcher(MojoHandle handle, - RefPtr* dispatcher) { +MojoResult Core::GetHandle(MojoHandle handle, Handle* h) { if (handle == MOJO_HANDLE_INVALID) return MOJO_RESULT_INVALID_ARGUMENT; MutexLocker locker(&handle_table_mutex_); - Handle h; - MojoResult rv = handle_table_.GetHandle(handle, &h); - if (rv == MOJO_RESULT_OK) - *dispatcher = std::move(h.dispatcher); - return rv; + return handle_table_.GetHandle(handle, h); } -MojoResult Core::GetAndRemoveDispatcher(MojoHandle handle, - RefPtr* dispatcher) { +MojoResult Core::GetAndRemoveHandle(MojoHandle handle, Handle* h) { if (handle == MOJO_HANDLE_INVALID) return MOJO_RESULT_INVALID_ARGUMENT; MutexLocker locker(&handle_table_mutex_); + return handle_table_.GetAndRemoveHandle(handle, h); +} + +MojoResult Core::GetDispatcherAndCheckRights( + MojoHandle handle, + MojoHandleRights required_handle_rights, + EntrypointClass entrypoint_class, + util::RefPtr* dispatcher) { + if (handle == MOJO_HANDLE_INVALID) + return MOJO_RESULT_INVALID_ARGUMENT; + Handle h; - MojoResult rv = handle_table_.GetAndRemoveHandle(handle, &h); - if (rv == MOJO_RESULT_OK) - *dispatcher = std::move(h.dispatcher); - return rv; + MojoResult result = GetHandle(handle, &h); + if (result != MOJO_RESULT_OK) + return result; + + if (!h.has_all_rights(required_handle_rights)) { + return h.dispatcher->SupportsEntrypointClass(entrypoint_class) + ? MOJO_RESULT_PERMISSION_DENIED + : MOJO_RESULT_INVALID_ARGUMENT; + } + + *dispatcher = std::move(h.dispatcher); + return MOJO_RESULT_OK; } MojoResult Core::AsyncWait(MojoHandle handle, MojoHandleSignals signals, const std::function& callback) { RefPtr dispatcher; - MojoResult result = GetDispatcher(handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + handle, MOJO_HANDLE_RIGHT_NONE, EntrypointClass::NONE, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -162,6 +175,46 @@ MojoResult Core::Close(MojoHandle handle) { return h.dispatcher->Close(); } +MojoResult Core::GetRights(MojoHandle handle, + UserPointer rights) { + Handle h; + MojoResult result = GetHandle(handle, &h); + if (result != MOJO_RESULT_OK) + return result; + + rights.Put(h.rights); + return MOJO_RESULT_OK; +} + +MojoResult Core::DuplicateHandleWithReducedRights( + MojoHandle handle, + MojoHandleRights rights_to_remove, + UserPointer new_handle) { + Handle h; + MojoResult result = GetHandle(handle, &h); + if (result != MOJO_RESULT_OK) + return result; + + if (!h.has_all_rights(MOJO_HANDLE_RIGHT_DUPLICATE)) + return MOJO_RESULT_PERMISSION_DENIED; + + RefPtr new_dispatcher; + result = h.dispatcher->DuplicateDispatcher(&new_dispatcher); + if (result != MOJO_RESULT_OK) + return result; + + MojoHandle new_handle_value = + AddHandle(Handle(new_dispatcher.Clone(), h.rights & ~rights_to_remove)); + if (new_handle_value == MOJO_HANDLE_INVALID) { + LOG(ERROR) << "Handle table full"; + new_dispatcher->Close(); + return MOJO_RESULT_RESOURCE_EXHAUSTED; + } + + new_handle.Put(new_handle_value); + return MOJO_RESULT_OK; +} + MojoResult Core::Wait(MojoHandle handle, MojoHandleSignals signals, MojoDeadline deadline, @@ -265,7 +318,9 @@ MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, uint32_t num_handles, MojoWriteMessageFlags flags) { RefPtr dispatcher; - MojoResult result = GetDispatcher(message_pipe_handle, &dispatcher); + MojoResult result = + GetDispatcherAndCheckRights(message_pipe_handle, MOJO_HANDLE_RIGHT_WRITE, + EntrypointClass::MESSAGE_PIPE, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -332,7 +387,9 @@ MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, UserPointer num_handles, MojoReadMessageFlags flags) { RefPtr dispatcher; - MojoResult result = GetDispatcher(message_pipe_handle, &dispatcher); + MojoResult result = + GetDispatcherAndCheckRights(message_pipe_handle, MOJO_HANDLE_RIGHT_READ, + EntrypointClass::MESSAGE_PIPE, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -423,7 +480,9 @@ MojoResult Core::SetDataPipeProducerOptions( MojoHandle data_pipe_producer_handle, UserPointer options) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_producer_handle, MOJO_HANDLE_RIGHT_SET_OPTIONS, + EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -435,7 +494,9 @@ MojoResult Core::GetDataPipeProducerOptions( UserPointer options, uint32_t options_num_bytes) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_producer_handle, MOJO_HANDLE_RIGHT_GET_OPTIONS, + EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -447,7 +508,9 @@ MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, UserPointer num_bytes, MojoWriteDataFlags flags) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE, + EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -459,7 +522,9 @@ MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, UserPointer buffer_num_bytes, MojoWriteDataFlags flags) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE, + EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -469,7 +534,9 @@ MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, uint32_t num_bytes_written) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_producer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_producer_handle, MOJO_HANDLE_RIGHT_WRITE, + EntrypointClass::DATA_PIPE_PRODUCER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -480,7 +547,9 @@ MojoResult Core::SetDataPipeConsumerOptions( MojoHandle data_pipe_consumer_handle, UserPointer options) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_SET_OPTIONS, + EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -492,7 +561,9 @@ MojoResult Core::GetDataPipeConsumerOptions( UserPointer options, uint32_t options_num_bytes) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_GET_OPTIONS, + EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -504,7 +575,9 @@ MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, UserPointer num_bytes, MojoReadDataFlags flags) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ, + EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -516,7 +589,9 @@ MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, UserPointer buffer_num_bytes, MojoReadDataFlags flags) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ, + EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -526,7 +601,9 @@ MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, uint32_t num_bytes_read) { RefPtr dispatcher; - MojoResult result = GetDispatcher(data_pipe_consumer_handle, &dispatcher); + MojoResult result = GetDispatcherAndCheckRights( + data_pipe_consumer_handle, MOJO_HANDLE_RIGHT_READ, + EntrypointClass::DATA_PIPE_CONSUMER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -550,15 +627,15 @@ MojoResult Core::CreateSharedBuffer( return result; } - MojoHandle h = AddHandle( + MojoHandle handle = AddHandle( Handle(dispatcher.Clone(), SharedBufferDispatcher::kDefaultHandleRights)); - if (h == MOJO_HANDLE_INVALID) { + if (handle == MOJO_HANDLE_INVALID) { LOG(ERROR) << "Handle table full"; dispatcher->Close(); return MOJO_RESULT_RESOURCE_EXHAUSTED; } - shared_buffer_handle.Put(h); + shared_buffer_handle.Put(handle); return MOJO_RESULT_OK; } @@ -566,27 +643,34 @@ MojoResult Core::DuplicateBufferHandle( MojoHandle buffer_handle, UserPointer options, UserPointer new_buffer_handle) { - RefPtr dispatcher; - MojoResult result = GetDispatcher(buffer_handle, &dispatcher); + // TODO(vtl): This is a big ugly and duplicates some code, but the plan is to + // remove this method anyway. + Handle h; + MojoResult result = GetHandle(buffer_handle, &h); if (result != MOJO_RESULT_OK) return result; + if (!h.has_all_rights(MOJO_HANDLE_RIGHT_DUPLICATE)) { + return h.dispatcher->SupportsEntrypointClass(EntrypointClass::BUFFER) + ? MOJO_RESULT_PERMISSION_DENIED + : MOJO_RESULT_INVALID_ARGUMENT; + } + // Don't verify |options| here; that's the dispatcher's job. RefPtr new_dispatcher; - result = dispatcher->DuplicateBufferHandle(options, &new_dispatcher); + result = h.dispatcher->DuplicateBufferHandle(options, &new_dispatcher); if (result != MOJO_RESULT_OK) return result; - // TODO(vtl): This should be done with the original handle's rights. - MojoHandle new_handle = AddHandle(Handle( - new_dispatcher.Clone(), SharedBufferDispatcher::kDefaultHandleRights)); - if (new_handle == MOJO_HANDLE_INVALID) { + MojoHandle new_handle_value = + AddHandle(Handle(new_dispatcher.Clone(), h.rights)); + if (new_handle_value == MOJO_HANDLE_INVALID) { LOG(ERROR) << "Handle table full"; new_dispatcher->Close(); return MOJO_RESULT_RESOURCE_EXHAUSTED; } - new_buffer_handle.Put(new_handle); + new_buffer_handle.Put(new_handle_value); return MOJO_RESULT_OK; } @@ -594,7 +678,9 @@ MojoResult Core::GetBufferInformation(MojoHandle buffer_handle, UserPointer info, uint32_t info_num_bytes) { RefPtr dispatcher; - MojoResult result = GetDispatcher(buffer_handle, &dispatcher); + MojoResult result = + GetDispatcherAndCheckRights(buffer_handle, MOJO_HANDLE_RIGHT_GET_OPTIONS, + EntrypointClass::BUFFER, &dispatcher); if (result != MOJO_RESULT_OK) return result; @@ -607,7 +693,13 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle, UserPointer buffer, MojoMapBufferFlags flags) { RefPtr dispatcher; - MojoResult result = GetDispatcher(buffer_handle, &dispatcher); + // TODO(vtl): Currently we can only map read/write. So both + // |MOJO_HANDLE_RIGHT_MAP_READABLE| and |MOJO_HANDLE_RIGHT_MAP_WRITABLE| are + // required. + MojoResult result = GetDispatcherAndCheckRights( + buffer_handle, + MOJO_HANDLE_RIGHT_MAP_READABLE | MOJO_HANDLE_RIGHT_MAP_WRITABLE, + EntrypointClass::BUFFER, &dispatcher); if (result != MOJO_RESULT_OK) return result; diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h index 18ad059ecce4c..b4cfbda02ef69 100644 --- a/mojo/edk/system/core.h +++ b/mojo/edk/system/core.h @@ -9,6 +9,7 @@ #include +#include "mojo/edk/system/entrypoint_class.h" #include "mojo/edk/system/handle.h" #include "mojo/edk/system/handle_table.h" #include "mojo/edk/system/mapping_table.h" @@ -55,18 +56,37 @@ class Core { // if the handle table is full. MojoHandle AddHandle(Handle&& h); - // Looks up the dispatcher for the given handle value. On success, gets the - // dispatcher for a given handle value. On failure, returns an appropriate - // result and leaves |dispatcher| alone), namely - // |MOJO_RESULT_INVALID_ARGUMENT| if the handle value is invalid or - // |MOJO_RESULT_BUSY| if the handle is marked as busy. - MojoResult GetDispatcher(MojoHandle handle, - util::RefPtr* dispatcher); + // Gets the handle for the given handle value. On success, returns + // |MOJO_RESULT_OK| (and sets |*h|). On failure, returns an appropriate result + // (and leaves |*h| alone), namely |MOJO_RESULT_INVALID_ARGUMENT| if the + // handle value is invalid or |MOJO_RESULT_BUSY| if the handle is marked as + // busy. + MojoResult GetHandle(MojoHandle handle, Handle* h); - // Like |GetDispatcher()|, but on success also removes the handle from the + // Like |GetHandle()|, but on success also removes the handle from the // handle table. - MojoResult GetAndRemoveDispatcher(MojoHandle handle, - util::RefPtr* dispatcher); + MojoResult GetAndRemoveHandle(MojoHandle handle, Handle* h); + + // Gets the dispatcher for the given handle value, which must have (all of) + // the rights in |required_handle_rights|. + // + // On success, returns |MOJO_RESULT_OK| and sets |*dispatcher| appropriately. + // On failure, returns: + // - |MOJO_RESULT_INVALID_ARGUMENT| if there's no handle for the given + // handle value (or the handle value was |MOJO_HANDLE_INVALID|), + // - |MOJO_RESULT_BUSY| if the handle is marked as busy, + // - |MOJO_RESULT_PERMISSION_DENIED| if the handle does not have the + // required rights *and* the dispatcher supports the specified + // |entrypoint_class|, or + // - |MOJO_RESULT_INVALID_ARGUMENT| if the handle does not have the required + // rights *but* the dispatcher does not support |entrypoint_class|. + // (Warning: if the handle has the required rights, then its dispatcher will + // be returned even if the dispatcher does not support |entrypoint_class|.) + MojoResult GetDispatcherAndCheckRights( + MojoHandle handle_value, + MojoHandleRights required_handle_rights, + EntrypointClass entrypoint_class, + util::RefPtr* dispatcher); // Watches on the given handle for the given signals, calling |callback| when // a signal is satisfied or when all signals become unsatisfiable. |callback| @@ -96,6 +116,11 @@ class Core { // This method corresponds to the API function defined in // "mojo/public/c/system/handle.h": MojoResult Close(MojoHandle handle); + MojoResult GetRights(MojoHandle handle, UserPointer rights); + MojoResult DuplicateHandleWithReducedRights( + MojoHandle handle, + MojoHandleRights rights_to_remove, + UserPointer new_handle); // These methods correspond to the API functions defined in // "mojo/public/c/system/wait.h": diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc index d44c60ca44235..be805c2dd8955 100644 --- a/mojo/edk/system/core_test_base.cc +++ b/mojo/edk/system/core_test_base.cc @@ -56,6 +56,13 @@ class MockDispatcher : public Dispatcher { mutex().AssertHeld(); } + MojoResult DuplicateDispatcherImplNoLock( + util::RefPtr* new_dispatcher) override { + info_->IncrementDuplicateDispatcherCallCount(); + *new_dispatcher = MockDispatcher::Create(info_); + return MOJO_RESULT_OK; + } + MojoResult WriteMessageImplNoLock(UserPointer bytes, uint32_t num_bytes, std::vector* transports, @@ -208,6 +215,9 @@ class MockDispatcher : public Dispatcher { // CoreTestBase ---------------------------------------------------------------- +// static +constexpr MojoHandleRights CoreTestBase::kDefaultMockHandleRights; + CoreTestBase::CoreTestBase() : platform_support_(embedder::CreateSimplePlatformSupport()) {} @@ -226,11 +236,13 @@ void CoreTestBase::TearDown() { MojoHandle CoreTestBase::CreateMockHandle(CoreTestBase::MockHandleInfo* info) { CHECK(core_); auto dispatcher = MockDispatcher::Create(info); - MojoHandle rv = core_->AddHandle( - Handle(std::move(dispatcher), - MOJO_HANDLE_RIGHT_DUPLICATE | MOJO_HANDLE_RIGHT_TRANSFER | - MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE | - MOJO_HANDLE_RIGHT_EXECUTE)); + MojoHandle rv = core_->AddHandle(Handle( + std::move(dispatcher), + MOJO_HANDLE_RIGHT_DUPLICATE | MOJO_HANDLE_RIGHT_TRANSFER | + MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE | + MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS | + MOJO_HANDLE_RIGHT_MAP_READABLE | MOJO_HANDLE_RIGHT_MAP_WRITABLE | + MOJO_HANDLE_RIGHT_MAP_EXECUTABLE)); CHECK_NE(rv, MOJO_HANDLE_INVALID); return rv; } @@ -256,6 +268,11 @@ unsigned CoreTestBase_MockHandleInfo::GetCloseCallCount() const { return close_call_count_; } +unsigned CoreTestBase_MockHandleInfo::GetDuplicateDispatcherCallCount() const { + MutexLocker locker(&mutex_); + return duplicate_dispatcher_call_count_; +} + unsigned CoreTestBase_MockHandleInfo::GetWriteMessageCallCount() const { MutexLocker locker(&mutex_); return write_message_call_count_; @@ -352,6 +369,11 @@ void CoreTestBase_MockHandleInfo::IncrementCloseCallCount() { close_call_count_++; } +void CoreTestBase_MockHandleInfo::IncrementDuplicateDispatcherCallCount() { + MutexLocker locker(&mutex_); + duplicate_dispatcher_call_count_++; +} + void CoreTestBase_MockHandleInfo::IncrementWriteMessageCallCount() { MutexLocker locker(&mutex_); write_message_call_count_++; diff --git a/mojo/edk/system/core_test_base.h b/mojo/edk/system/core_test_base.h index a3dd3fda97289..c1734ae8c8a9c 100644 --- a/mojo/edk/system/core_test_base.h +++ b/mojo/edk/system/core_test_base.h @@ -32,6 +32,13 @@ class CoreTestBase : public testing::Test { public: using MockHandleInfo = CoreTestBase_MockHandleInfo; + static constexpr MojoHandleRights kDefaultMockHandleRights = + MOJO_HANDLE_RIGHT_DUPLICATE | MOJO_HANDLE_RIGHT_TRANSFER | + MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE | + MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS | + MOJO_HANDLE_RIGHT_MAP_READABLE | MOJO_HANDLE_RIGHT_MAP_WRITABLE | + MOJO_HANDLE_RIGHT_MAP_EXECUTABLE; + CoreTestBase(); ~CoreTestBase() override; @@ -39,7 +46,8 @@ class CoreTestBase : public testing::Test { void TearDown() override; protected: - // |info| must remain alive until the returned handle is closed. + // |info| must remain alive until the returned handle and any handles + // duplicated from it are closed. MojoHandle CreateMockHandle(MockHandleInfo* info); Core* core() { return core_.get(); } @@ -59,6 +67,7 @@ class CoreTestBase_MockHandleInfo { unsigned GetCtorCallCount() const; unsigned GetDtorCallCount() const; unsigned GetCloseCallCount() const; + unsigned GetDuplicateDispatcherCallCount() const; unsigned GetWriteMessageCallCount() const; unsigned GetReadMessageCallCount() const; unsigned GetWriteDataCallCount() const; @@ -81,6 +90,7 @@ class CoreTestBase_MockHandleInfo { void IncrementCtorCallCount(); void IncrementDtorCallCount(); void IncrementCloseCallCount(); + void IncrementDuplicateDispatcherCallCount(); void IncrementWriteMessageCallCount(); void IncrementReadMessageCallCount(); void IncrementWriteDataCallCount(); @@ -105,6 +115,7 @@ class CoreTestBase_MockHandleInfo { unsigned ctor_call_count_ MOJO_GUARDED_BY(mutex_) = 0; unsigned dtor_call_count_ MOJO_GUARDED_BY(mutex_) = 0; unsigned close_call_count_ MOJO_GUARDED_BY(mutex_) = 0; + unsigned duplicate_dispatcher_call_count_ MOJO_GUARDED_BY(mutex_) = 0; unsigned write_message_call_count_ MOJO_GUARDED_BY(mutex_) = 0; unsigned read_message_call_count_ MOJO_GUARDED_BY(mutex_) = 0; unsigned write_data_call_count_ MOJO_GUARDED_BY(mutex_) = 0; diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc index 1b3c1facdd30e..005dede1c62d1 100644 --- a/mojo/edk/system/core_unittest.cc +++ b/mojo/edk/system/core_unittest.cc @@ -20,6 +20,17 @@ namespace mojo { namespace system { namespace { +const MojoHandleRights kDefaultMessagePipeHandleRights = + MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ | + MOJO_HANDLE_RIGHT_WRITE | MOJO_HANDLE_RIGHT_GET_OPTIONS | + MOJO_HANDLE_RIGHT_SET_OPTIONS; +const MojoHandleRights kDefaultDataPipeProducerHandleRights = + MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_WRITE | + MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS; +const MojoHandleRights kDefaultDataPipeConsumerHandleRights = + MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ | + MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS; + const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u}; const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u}; @@ -44,6 +55,35 @@ TEST_F(CoreTest, Basic) { EXPECT_EQ(1u, info.GetCtorCallCount()); EXPECT_NE(h, MOJO_HANDLE_INVALID); + MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(h, MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultMockHandleRights, rights); + + MojoHandle h_dup = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, + core()->DuplicateHandleWithReducedRights( + h, MOJO_HANDLE_RIGHT_DUPLICATE, MakeUserPointer(&h_dup))); + EXPECT_EQ(1u, info.GetDuplicateDispatcherCallCount()); + EXPECT_NE(h_dup, MOJO_HANDLE_INVALID); + EXPECT_NE(h_dup, h); + rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(h_dup, MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultMockHandleRights & ~MOJO_HANDLE_RIGHT_DUPLICATE, rights); + MojoHandle h_denied = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_PERMISSION_DENIED, + core()->DuplicateHandleWithReducedRights( + h_dup, MOJO_HANDLE_RIGHT_NONE, MakeUserPointer(&h_denied))); + EXPECT_EQ(1u, info.GetDuplicateDispatcherCallCount()); + EXPECT_EQ(MOJO_HANDLE_INVALID, h_denied); + + EXPECT_EQ(0u, info.GetDtorCallCount()); + EXPECT_EQ(0u, info.GetCloseCallCount()); + EXPECT_EQ(0u, info.GetCancelAllAwakablesCallCount()); + EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h_dup)); + EXPECT_EQ(1u, info.GetDtorCallCount()); + EXPECT_EQ(1u, info.GetCloseCallCount()); + EXPECT_EQ(1u, info.GetCancelAllAwakablesCallCount()); + EXPECT_EQ(0u, info.GetWriteMessageCallCount()); EXPECT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h, NullUserPointer(), 0, NullUserPointer(), 0, @@ -176,13 +216,14 @@ TEST_F(CoreTest, Basic) { EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); - EXPECT_EQ(0u, info.GetDtorCallCount()); - EXPECT_EQ(0u, info.GetCloseCallCount()); - EXPECT_EQ(0u, info.GetCancelAllAwakablesCallCount()); - EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - EXPECT_EQ(1u, info.GetCancelAllAwakablesCallCount()); - EXPECT_EQ(1u, info.GetCloseCallCount()); + // |h| shares |info| with |h_dup|, which was closed above. EXPECT_EQ(1u, info.GetDtorCallCount()); + EXPECT_EQ(1u, info.GetCloseCallCount()); + EXPECT_EQ(1u, info.GetCancelAllAwakablesCallCount()); + EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); + EXPECT_EQ(2u, info.GetDtorCallCount()); + EXPECT_EQ(2u, info.GetCloseCallCount()); + EXPECT_EQ(2u, info.GetCancelAllAwakablesCallCount()); // No awakables should ever have ever been added. EXPECT_EQ(0u, info.GetRemoveAwakableCallCount()); @@ -204,6 +245,31 @@ TEST_F(CoreTest, InvalidArguments) { EXPECT_EQ(1u, info.GetCloseCallCount()); } + // |GetRights()|: + { + MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + core()->GetRights(MOJO_HANDLE_INVALID, MakeUserPointer(&rights))); + EXPECT_EQ(0u, rights); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + core()->GetRights(10, MakeUserPointer(&rights))); + EXPECT_EQ(0u, rights); + } + + // |DuplicateHandleWithReducedRights()|: + { + MojoHandle h = MOJO_HANDLE_INVALID; + EXPECT_EQ( + MOJO_RESULT_INVALID_ARGUMENT, + core()->DuplicateHandleWithReducedRights( + MOJO_HANDLE_INVALID, MOJO_HANDLE_RIGHT_NONE, MakeUserPointer(&h))); + EXPECT_EQ(MOJO_HANDLE_INVALID, h); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + core()->DuplicateHandleWithReducedRights( + 10, MOJO_HANDLE_RIGHT_NONE, MakeUserPointer(&h))); + EXPECT_EQ(MOJO_HANDLE_INVALID, h); + } + // |Wait()|: { EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, @@ -556,6 +622,27 @@ TEST_F(CoreTest, InvalidArguments) { TEST_F(CoreTest, InvalidArgumentsDeath) { const char kMemoryCheckFailedRegex[] = "Check failed"; + // |GetRights()|: + { + MockHandleInfo info; + MojoHandle h = CreateMockHandle(&info); + EXPECT_DEATH_IF_SUPPORTED(core()->GetRights(h, NullUserPointer()), + kMemoryCheckFailedRegex); + + EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); + } + + // |DuplicateHandleWithReducedRights()|: + { + MockHandleInfo info; + MojoHandle h = CreateMockHandle(&info); + EXPECT_DEATH_IF_SUPPORTED(core()->DuplicateHandleWithReducedRights( + h, MOJO_HANDLE_RIGHT_NONE, NullUserPointer()), + kMemoryCheckFailedRegex); + + EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); + } + // |WaitMany()|: { MojoHandle handle = MOJO_HANDLE_INVALID; @@ -632,7 +719,7 @@ TEST_F(CoreTest, InvalidArgumentsDeath) { // same/different signals) TEST_F(CoreTest, MessagePipe) { - MojoHandle h[2]; + MojoHandle h[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID}; MojoHandleSignalsState hss[2]; uint32_t result_index; @@ -644,6 +731,24 @@ TEST_F(CoreTest, MessagePipe) { EXPECT_NE(h[1], MOJO_HANDLE_INVALID); EXPECT_NE(h[0], h[1]); + // Both should have the correct rights. + MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(h[0], MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultMessagePipeHandleRights, rights); + rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(h[1], MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultMessagePipeHandleRights, rights); + + // Neither should be duplicatable. + MojoHandle h_denied = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_PERMISSION_DENIED, + core()->DuplicateHandleWithReducedRights( + h[0], MOJO_HANDLE_RIGHT_NONE, MakeUserPointer(&h_denied))); + EXPECT_EQ(MOJO_RESULT_PERMISSION_DENIED, + core()->DuplicateHandleWithReducedRights( + h[1], MOJO_HANDLE_RIGHT_NONE, MakeUserPointer(&h_denied))); + EXPECT_EQ(MOJO_HANDLE_INVALID, h_denied); + // Neither should be readable. MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE}; @@ -944,6 +1049,12 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { // fails. See above note. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(h_passed[1])); + // Check that |h_received| still has the expected rights. + MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, + core()->GetRights(h_received, MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultMessagePipeHandleRights, rights); + // Write to |h_passed[0]|. Should receive on |h_received|. EXPECT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h_passed[0], UserPointer(kHello), @@ -976,7 +1087,9 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) { } TEST_F(CoreTest, DataPipe) { - MojoHandle ph, ch; // p is for producer and c is for consumer. + // p is for producer and c is for consumer. + MojoHandle ph = MOJO_HANDLE_INVALID; + MojoHandle ch = MOJO_HANDLE_INVALID; MojoHandleSignalsState hss; EXPECT_EQ(MOJO_RESULT_OK, @@ -987,6 +1100,24 @@ TEST_F(CoreTest, DataPipe) { EXPECT_NE(ch, MOJO_HANDLE_INVALID); EXPECT_NE(ph, ch); + // Both should have the correct rights. + MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(ph, MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultDataPipeProducerHandleRights, rights); + rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, core()->GetRights(ch, MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultDataPipeConsumerHandleRights, rights); + + // Neither should be duplicatable. + MojoHandle h_denied = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_PERMISSION_DENIED, + core()->DuplicateHandleWithReducedRights( + ph, MOJO_HANDLE_RIGHT_NONE, MakeUserPointer(&h_denied))); + EXPECT_EQ(MOJO_RESULT_PERMISSION_DENIED, + core()->DuplicateHandleWithReducedRights( + ch, MOJO_HANDLE_RIGHT_NONE, MakeUserPointer(&h_denied))); + EXPECT_EQ(MOJO_HANDLE_INVALID, h_denied); + // Producer should be never-readable, but already writable. hss = kEmptyMojoHandleSignalsState; EXPECT_EQ( @@ -1411,6 +1542,12 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { // above note. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ch)); + // Check that |ch_received| still has the expected rights. + MojoHandleRights rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, + core()->GetRights(ch_received, MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultDataPipeConsumerHandleRights, rights); + // Write to |ph|. Should receive on |ch_received|. num_bytes = kWorldSize; EXPECT_EQ(MOJO_RESULT_OK, @@ -1471,6 +1608,12 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) { // above note. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, core()->Close(ph)); + // Check that |ph_received| still has the expected rights. + rights = MOJO_HANDLE_RIGHT_NONE; + EXPECT_EQ(MOJO_RESULT_OK, + core()->GetRights(ph_received, MakeUserPointer(&rights))); + EXPECT_EQ(kDefaultDataPipeProducerHandleRights, rights); + // Write to |ph_received|. Should receive on |ch_received|. num_bytes = kHelloSize; EXPECT_EQ(MOJO_RESULT_OK, @@ -1681,7 +1824,8 @@ TEST_F(CoreTest, AsyncWait) { EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); } -// TODO(vtl): Test |DuplicateBufferHandle()| and |MapBuffer()|. +// TODO(vtl): Test |CreateSharedBuffer()|, |DuplicateBufferHandle()|, and +// |MapBuffer()|. } // namespace } // namespace system diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/mojo/edk/system/data_pipe_consumer_dispatcher.cc index 1d515b2d9067f..304ee2930d824 100644 --- a/mojo/edk/system/data_pipe_consumer_dispatcher.cc +++ b/mojo/edk/system/data_pipe_consumer_dispatcher.cc @@ -32,7 +32,8 @@ Dispatcher::Type DataPipeConsumerDispatcher::GetType() const { bool DataPipeConsumerDispatcher::SupportsEntrypointClass( EntrypointClass entrypoint_class) const { - return (entrypoint_class == EntrypointClass::DATA_PIPE_CONSUMER); + return (entrypoint_class == EntrypointClass::NONE || + entrypoint_class == EntrypointClass::DATA_PIPE_CONSUMER); } // static diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.h b/mojo/edk/system/data_pipe_consumer_dispatcher.h index a9c99c3a2dd04..cee289b439a67 100644 --- a/mojo/edk/system/data_pipe_consumer_dispatcher.h +++ b/mojo/edk/system/data_pipe_consumer_dispatcher.h @@ -23,7 +23,7 @@ class DataPipeConsumerDispatcher final : public Dispatcher { // The default/standard rights for a data pipe consumer handle. static constexpr MojoHandleRights kDefaultHandleRights = MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ | - MOJO_HANDLE_RIGHT_WRITE; + MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS; static util::RefPtr Create() { return AdoptRef(new DataPipeConsumerDispatcher()); diff --git a/mojo/edk/system/data_pipe_impl_unittest.cc b/mojo/edk/system/data_pipe_impl_unittest.cc index c50e6499e0341..53b0ad55dadb5 100644 --- a/mojo/edk/system/data_pipe_impl_unittest.cc +++ b/mojo/edk/system/data_pipe_impl_unittest.cc @@ -316,7 +316,7 @@ class RemoteDataPipeImplTestHelper : public DataPipeImplTestHelper { ASSERT_EQ(1u, read_num_handles); ASSERT_TRUE(read_handles[0]); EXPECT_TRUE(read_handles[0].dispatcher->HasOneRef()); - // TODO(vtl): Also check the rights here once they're actually preserved? + EXPECT_EQ(handle_to_send.rights, read_handles[0].rights); *handle_to_receive = std::move(read_handles[0]); } diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.h b/mojo/edk/system/data_pipe_producer_dispatcher.h index 415b75675bd62..a821ac6090ab7 100644 --- a/mojo/edk/system/data_pipe_producer_dispatcher.h +++ b/mojo/edk/system/data_pipe_producer_dispatcher.h @@ -22,8 +22,8 @@ class DataPipeProducerDispatcher final : public Dispatcher { public: // The default/standard rights for a data pipe consumer handle. static constexpr MojoHandleRights kDefaultHandleRights = - MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ | - MOJO_HANDLE_RIGHT_WRITE; + MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_WRITE | + MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS; static util::RefPtr Create() { return AdoptRef(new DataPipeProducerDispatcher()); diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc index 9d4d8db4fdfb0..4900b0d6980ea 100644 --- a/mojo/edk/system/dispatcher.cc +++ b/mojo/edk/system/dispatcher.cc @@ -108,6 +108,15 @@ MojoResult Dispatcher::Close() { return MOJO_RESULT_OK; } +MojoResult Dispatcher::DuplicateDispatcher( + util::RefPtr* new_dispatcher) { + MutexLocker locker(&mutex_); + if (is_closed_) + return MOJO_RESULT_INVALID_ARGUMENT; + + return DuplicateDispatcherImplNoLock(new_dispatcher); +} + MojoResult Dispatcher::WriteMessage(UserPointer bytes, uint32_t num_bytes, std::vector* transports, @@ -318,6 +327,17 @@ void Dispatcher::CloseImplNoLock() { // any actual close-time cleanup necessary. } +MojoResult Dispatcher::DuplicateDispatcherImplNoLock( + util::RefPtr* new_dispatcher) { + mutex_.AssertHeld(); + DCHECK(!is_closed_); + // By default, this is not supported. However, this should only be reachable + // if a handle has the |MOJO_HANDLE_RIGHT_DUPLICATE| right, which it should + // only have if it is supported. + NOTREACHED(); + return MOJO_RESULT_INTERNAL; +} + MojoResult Dispatcher::WriteMessageImplNoLock( UserPointer /*bytes*/, uint32_t /*num_bytes*/, diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h index 24a59203e6a5d..db27ec879b5a7 100644 --- a/mojo/edk/system/dispatcher.h +++ b/mojo/edk/system/dispatcher.h @@ -98,7 +98,13 @@ class Dispatcher : public util::RefCountedThreadSafe { // NOTE(vtl): This puts a big lock around each dispatcher (i.e., handle), and // prevents the various |...ImplNoLock()|s from releasing the lock as soon as // possible. If this becomes an issue, we can rethink this. + + // No |EntrypointClass|: + // All dispatchers must support this. MojoResult Close(); + // This actually supports |MojoDuplicateHandle[WithReducedRights]()|; rights + // are handled by |Core|. + MojoResult DuplicateDispatcher(util::RefPtr* new_dispatcher); // |EntrypointClass::MESSAGE_PIPE|: // |transports| may be non-null if and only if there are handles to be @@ -262,6 +268,12 @@ class Dispatcher : public util::RefCountedThreadSafe { virtual void CancelAllAwakablesNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); virtual void CloseImplNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + // All dispatcher types whose handles may ever have the + // |MOJO_HANDLE_RIGHT_DUPLICATE| right must override this. + virtual MojoResult DuplicateDispatcherImplNoLock( + util::RefPtr* new_dispatcher) + MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + // This is called by |CreateEquivalentDispatcherAndCloseNoLock()|. It should // "close" this dispatcher and return a new one equivalent to it. Note: // Probably the first thing an implementation should do is call diff --git a/mojo/edk/system/dispatcher_unittest.cc b/mojo/edk/system/dispatcher_unittest.cc index dcbc999256f0e..033c1601947f8 100644 --- a/mojo/edk/system/dispatcher_unittest.cc +++ b/mojo/edk/system/dispatcher_unittest.cc @@ -141,6 +141,7 @@ TEST(DispatcherTest, Basic) { enum class DispatcherOp { CLOSE = 0, + DUPLICATE_DISPATCHER, WRITE_MESSAGE, READ_MESSAGE, SET_DATA_PIPE_PRODUCER_OPTIONS, @@ -178,6 +179,18 @@ void ThreadSafetyStressHelper(ManualResetWaitableEvent* event, << "Result: " << r; break; } + case DispatcherOp::DUPLICATE_DISPATCHER: { + RefPtr new_dispatcher; + MojoResult r = dispatcher->DuplicateDispatcher(&new_dispatcher); + if (r == MOJO_RESULT_OK) { + EXPECT_TRUE(new_dispatcher); + EXPECT_EQ(MOJO_RESULT_OK, new_dispatcher->Close()); + } else { + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, r); + EXPECT_FALSE(new_dispatcher); + } + break; + } case DispatcherOp::WRITE_MESSAGE: EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher->WriteMessage(NullUserPointer(), 0, nullptr, diff --git a/mojo/edk/system/entrypoint_class.h b/mojo/edk/system/entrypoint_class.h index 05c172b77028e..d6828a96fdb7f 100644 --- a/mojo/edk/system/entrypoint_class.h +++ b/mojo/edk/system/entrypoint_class.h @@ -15,6 +15,10 @@ namespace system { // |SupportsEntrypointClass()| indicates that the method's class is not // supported. enum class EntrypointClass { + // Not an entrypoint; all implementations of + // |Dispatcher::SupportsEntrypointClass()| should return true for this: + NONE, + // |Dispatcher::ReadMessage()|, |Dispatcher::WriteMessage()|: MESSAGE_PIPE, diff --git a/mojo/edk/system/handle.h b/mojo/edk/system/handle.h index c02fa1d974702..1a01c364efcbb 100644 --- a/mojo/edk/system/handle.h +++ b/mojo/edk/system/handle.h @@ -48,6 +48,10 @@ struct Handle { void reset() { *this = Handle(); } + bool has_all_rights(MojoHandleRights required_rights) const { + return (rights & required_rights) == required_rights; + } + // Note: |dispatcher| is guaranteed to be null if default-constructed or // moved-from, but we make no guarantees about the value of |rights| in either // case. diff --git a/mojo/edk/system/handle_unittest.cc b/mojo/edk/system/handle_unittest.cc index 5183c9c2814b7..5dc27cde0babe 100644 --- a/mojo/edk/system/handle_unittest.cc +++ b/mojo/edk/system/handle_unittest.cc @@ -114,6 +114,51 @@ TEST(HandleTest, Basic) { } } +TEST(HandleTest, HasAllRights) { + { + Handle h; + + EXPECT_TRUE(h.has_all_rights(MOJO_HANDLE_RIGHT_NONE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_DUPLICATE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_TRANSFER)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_READ)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_WRITE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_GET_OPTIONS)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_SET_OPTIONS)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_MAP_READABLE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_MAP_WRITABLE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_MAP_EXECUTABLE)); + } + + { + Handle h(MakeRefCounted(), + MOJO_HANDLE_RIGHT_DUPLICATE | MOJO_HANDLE_RIGHT_READ); + + EXPECT_TRUE(h.has_all_rights(MOJO_HANDLE_RIGHT_NONE)); + EXPECT_TRUE(h.has_all_rights(MOJO_HANDLE_RIGHT_DUPLICATE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_TRANSFER)); + EXPECT_TRUE(h.has_all_rights(MOJO_HANDLE_RIGHT_READ)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_WRITE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_GET_OPTIONS)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_SET_OPTIONS)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_MAP_READABLE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_MAP_WRITABLE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_MAP_EXECUTABLE)); + + EXPECT_TRUE( + h.has_all_rights(MOJO_HANDLE_RIGHT_DUPLICATE | MOJO_HANDLE_RIGHT_READ)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_DUPLICATE | + MOJO_HANDLE_RIGHT_READ | + MOJO_HANDLE_RIGHT_WRITE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_DUPLICATE | + MOJO_HANDLE_RIGHT_WRITE)); + EXPECT_FALSE(h.has_all_rights(MOJO_HANDLE_RIGHT_GET_OPTIONS | + MOJO_HANDLE_RIGHT_SET_OPTIONS)); + + EXPECT_EQ(MOJO_RESULT_OK, h.dispatcher->Close()); + } +} + } // namespace } // namespace system } // namespace mojo diff --git a/mojo/edk/system/message_in_transit.cc b/mojo/edk/system/message_in_transit.cc index 4dbcf7d7dd583..c40b9f52aae4f 100644 --- a/mojo/edk/system/message_in_transit.cc +++ b/mojo/edk/system/message_in_transit.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "mojo/edk/system/configuration.h" +#include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/transport_data.h" using mojo::platform::AlignedAlloc; @@ -155,19 +156,6 @@ void MessageInTransit::SetHandles(std::unique_ptr handles) { #endif } -void MessageInTransit::SetDispatchers( - std::unique_ptr dispatchers) { - DCHECK(dispatchers); - - std::unique_ptr handles(new HandleVector()); - handles->reserve(dispatchers->size()); - for (size_t i = 0; i < dispatchers->size(); i++) { - handles->push_back( - Handle(std::move(dispatchers->at(i)), MOJO_HANDLE_RIGHT_NONE)); - } - SetHandles(std::move(handles)); -} - void MessageInTransit::SetTransportData( std::unique_ptr transport_data) { DCHECK(transport_data); diff --git a/mojo/edk/system/message_in_transit.h b/mojo/edk/system/message_in_transit.h index f2ec0262b9fe7..654311e0ac7a3 100644 --- a/mojo/edk/system/message_in_transit.h +++ b/mojo/edk/system/message_in_transit.h @@ -14,7 +14,6 @@ #include "mojo/edk/platform/aligned_alloc.h" #include "mojo/edk/system/channel_endpoint_id.h" -#include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/handle.h" #include "mojo/edk/system/memory.h" #include "mojo/public/cpp/system/macros.h" @@ -189,8 +188,6 @@ class MessageInTransit { // handle in the handle table), i.e., the dispatcher must have a reference // count of 1. This message must not already have handles. void SetHandles(std::unique_ptr handles); - // TODO(vtl): Delete this. - void SetDispatchers(std::unique_ptr dispatchers); // Sets the |TransportData| for this message. This should only be done when // there are no handles and no existing |TransportData|. diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc index 2f72bbd3c1e2e..e0f02fcafce3d 100644 --- a/mojo/edk/system/message_pipe_dispatcher.cc +++ b/mojo/edk/system/message_pipe_dispatcher.cc @@ -77,7 +77,8 @@ Dispatcher::Type MessagePipeDispatcher::GetType() const { bool MessagePipeDispatcher::SupportsEntrypointClass( EntrypointClass entrypoint_class) const { - return (entrypoint_class == EntrypointClass::MESSAGE_PIPE); + return (entrypoint_class == EntrypointClass::NONE || + entrypoint_class == EntrypointClass::MESSAGE_PIPE); } // static diff --git a/mojo/edk/system/message_pipe_dispatcher.h b/mojo/edk/system/message_pipe_dispatcher.h index 968e3188c244a..9921644b281ab 100644 --- a/mojo/edk/system/message_pipe_dispatcher.h +++ b/mojo/edk/system/message_pipe_dispatcher.h @@ -24,7 +24,8 @@ class MessagePipeDispatcher final : public Dispatcher { // The default/standard rights for a message pipe handle. static constexpr MojoHandleRights kDefaultHandleRights = MOJO_HANDLE_RIGHT_TRANSFER | MOJO_HANDLE_RIGHT_READ | - MOJO_HANDLE_RIGHT_WRITE; + MOJO_HANDLE_RIGHT_WRITE | MOJO_HANDLE_RIGHT_GET_OPTIONS | + MOJO_HANDLE_RIGHT_SET_OPTIONS; // The default options to use for |MojoCreateMessagePipe()|. (Real uses // should obtain this via |ValidateCreateOptions()| with a null |in_options|; diff --git a/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/mojo/edk/system/message_pipe_dispatcher_unittest.cc index fa35f7ae7dd6a..f0550436d7ea5 100644 --- a/mojo/edk/system/message_pipe_dispatcher_unittest.cc +++ b/mojo/edk/system/message_pipe_dispatcher_unittest.cc @@ -180,6 +180,7 @@ TEST(MessagePipeDispatcherTest, SupportsEntrypointClass) { EXPECT_EQ(MOJO_RESULT_OK, d_peer->Close()); } + EXPECT_TRUE(d->SupportsEntrypointClass(EntrypointClass::NONE)); EXPECT_TRUE(d->SupportsEntrypointClass(EntrypointClass::MESSAGE_PIPE)); EXPECT_FALSE(d->SupportsEntrypointClass(EntrypointClass::DATA_PIPE_PRODUCER)); EXPECT_FALSE(d->SupportsEntrypointClass(EntrypointClass::DATA_PIPE_CONSUMER)); diff --git a/mojo/edk/system/message_pipe_endpoint.h b/mojo/edk/system/message_pipe_endpoint.h index 65462eae27fa0..837e66003a79f 100644 --- a/mojo/edk/system/message_pipe_endpoint.h +++ b/mojo/edk/system/message_pipe_endpoint.h @@ -11,6 +11,7 @@ #include #include "mojo/edk/system/handle.h" +#include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/memory.h" #include "mojo/edk/system/message_in_transit.h" #include "mojo/public/c/system/handle.h" diff --git a/mojo/edk/system/message_pipe_test_utils.h b/mojo/edk/system/message_pipe_test_utils.h index 23a96f6fa108d..6f2ebdf800e9f 100644 --- a/mojo/edk/system/message_pipe_test_utils.h +++ b/mojo/edk/system/message_pipe_test_utils.h @@ -9,6 +9,7 @@ #include "mojo/edk/platform/scoped_platform_handle.h" #include "mojo/edk/system/channel.h" +#include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/test/test_io_thread.h" #include "mojo/edk/test/multiprocess_test_helper.h" #include "mojo/edk/util/ref_ptr.h" diff --git a/mojo/edk/system/mock_simple_dispatcher.cc b/mojo/edk/system/mock_simple_dispatcher.cc index a1f080f68c1cc..58243c106e8c7 100644 --- a/mojo/edk/system/mock_simple_dispatcher.cc +++ b/mojo/edk/system/mock_simple_dispatcher.cc @@ -52,7 +52,7 @@ Dispatcher::Type MockSimpleDispatcher::GetType() const { bool MockSimpleDispatcher::SupportsEntrypointClass( EntrypointClass entrypoint_class) const { - return false; + return (entrypoint_class == EntrypointClass::NONE); } MockSimpleDispatcher::MockSimpleDispatcher( @@ -65,6 +65,12 @@ MockSimpleDispatcher::MockSimpleDispatcher(const HandleSignalsState& state) MockSimpleDispatcher::~MockSimpleDispatcher() {} +MojoResult MockSimpleDispatcher::DuplicateDispatcherImplNoLock( + util::RefPtr* new_dispatcher) { + *new_dispatcher = MakeRefCounted(state_); + return MOJO_RESULT_OK; +} + RefPtr MockSimpleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock( MessagePipe* /*message_pipe*/, diff --git a/mojo/edk/system/mock_simple_dispatcher.h b/mojo/edk/system/mock_simple_dispatcher.h index a57824805e614..fb45ab44c8980 100644 --- a/mojo/edk/system/mock_simple_dispatcher.h +++ b/mojo/edk/system/mock_simple_dispatcher.h @@ -37,6 +37,8 @@ class MockSimpleDispatcher final : public SimpleDispatcher { explicit MockSimpleDispatcher(const HandleSignalsState& state); ~MockSimpleDispatcher() override; + MojoResult DuplicateDispatcherImplNoLock( + util::RefPtr* new_dispatcher) override; util::RefPtr CreateEquivalentDispatcherAndCloseImplNoLock( MessagePipe* message_pipe, unsigned port) override; diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc index 3efa58f905294..6d5c57cf25498 100644 --- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc @@ -249,7 +249,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { CHECK_EQ(num_handles, 1u); CHECK_EQ(handles[0].dispatcher->GetType(), Dispatcher::Type::SHARED_BUFFER); - // TODO(vtl): Also check the rights here once they're actually preserved? + CHECK_EQ(handles[0].rights, SharedBufferDispatcher::kDefaultHandleRights); RefPtr dispatcher( static_cast(handles[0].dispatcher.get())); @@ -437,7 +437,8 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { for (size_t i = 0; i < num_read_handles; ++i) { CHECK_EQ(read_handles[i].dispatcher->GetType(), Dispatcher::Type::PLATFORM_HANDLE); - // TODO(vtl): Also check the rights here once they're actually preserved? + CHECK_EQ(read_handles[i].rights, + PlatformHandleDispatcher::kDefaultHandleRights); RefPtr dispatcher( static_cast( diff --git a/mojo/edk/system/platform_handle_dispatcher.cc b/mojo/edk/system/platform_handle_dispatcher.cc index 0d52529a9fba9..3f78d96db9b3d 100644 --- a/mojo/edk/system/platform_handle_dispatcher.cc +++ b/mojo/edk/system/platform_handle_dispatcher.cc @@ -40,7 +40,7 @@ Dispatcher::Type PlatformHandleDispatcher::GetType() const { bool PlatformHandleDispatcher::SupportsEntrypointClass( EntrypointClass entrypoint_class) const { - return false; + return (entrypoint_class == EntrypointClass::NONE); } // static diff --git a/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/mojo/edk/system/platform_handle_dispatcher_unittest.cc index 626991a1dac5c..70f5df77eb6a3 100644 --- a/mojo/edk/system/platform_handle_dispatcher_unittest.cc +++ b/mojo/edk/system/platform_handle_dispatcher_unittest.cc @@ -76,6 +76,7 @@ TEST(PlatformHandleDispatcher, SupportsEntrypointClass) { ASSERT_TRUE(d); EXPECT_FALSE(h.is_valid()); + EXPECT_TRUE(d->SupportsEntrypointClass(EntrypointClass::NONE)); EXPECT_FALSE(d->SupportsEntrypointClass(EntrypointClass::MESSAGE_PIPE)); EXPECT_FALSE(d->SupportsEntrypointClass(EntrypointClass::DATA_PIPE_PRODUCER)); EXPECT_FALSE(d->SupportsEntrypointClass(EntrypointClass::DATA_PIPE_CONSUMER)); diff --git a/mojo/edk/system/remote_data_pipe_impl_unittest.cc b/mojo/edk/system/remote_data_pipe_impl_unittest.cc index 24df824482d16..86c54ce171e24 100644 --- a/mojo/edk/system/remote_data_pipe_impl_unittest.cc +++ b/mojo/edk/system/remote_data_pipe_impl_unittest.cc @@ -234,7 +234,8 @@ TEST_F(RemoteDataPipeImplTest, SendConsumerWithClosedProducer) { EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved? + EXPECT_EQ(DataPipeConsumerDispatcher::kDefaultHandleRights, + read_handles[0].rights); consumer = RefPtr( static_cast( read_handles[0].dispatcher.get())); @@ -356,7 +357,8 @@ TEST_F(RemoteDataPipeImplTest, SendConsumerDuringTwoPhaseWrite) { EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved? + EXPECT_EQ(DataPipeConsumerDispatcher::kDefaultHandleRights, + read_handles[0].rights); consumer = RefPtr( static_cast( read_handles[0].dispatcher.get())); @@ -482,7 +484,8 @@ TEST_F(RemoteDataPipeImplTest, SendConsumerDuringSecondTwoPhaseWrite) { EXPECT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved? + EXPECT_EQ(DataPipeConsumerDispatcher::kDefaultHandleRights, + read_handles[0].rights); consumer = RefPtr( static_cast( read_handles[0].dispatcher.get())); diff --git a/mojo/edk/system/remote_message_pipe_unittest.cc b/mojo/edk/system/remote_message_pipe_unittest.cc index f273445ee976d..8d88b40abf38c 100644 --- a/mojo/edk/system/remote_message_pipe_unittest.cc +++ b/mojo/edk/system/remote_message_pipe_unittest.cc @@ -690,7 +690,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved. + EXPECT_EQ(MessagePipeDispatcher::kDefaultHandleRights, + read_handles[0].rights); dispatcher = RefPtr( static_cast(read_handles[0].dispatcher.get())); @@ -879,7 +880,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) { EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved. + EXPECT_EQ(MessagePipeDispatcher::kDefaultHandleRights, + read_handles[0].rights); dispatcher = RefPtr( static_cast(read_handles[0].dispatcher.get())); @@ -1012,7 +1014,8 @@ TEST_F(RemoteMessagePipeTest, SharedBufferPassing) { EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved. + EXPECT_EQ(SharedBufferDispatcher::kDefaultHandleRights, + read_handles[0].rights); dispatcher = RefPtr( static_cast(read_handles[0].dispatcher.get())); @@ -1126,7 +1129,8 @@ TEST_F(RemoteMessagePipeTest, PlatformHandlePassing) { EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved. + EXPECT_EQ(PlatformHandleDispatcher::kDefaultHandleRights, + read_handles[0].rights); dispatcher = RefPtr( static_cast(read_handles[0].dispatcher.get())); @@ -1265,7 +1269,8 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved. + EXPECT_EQ(MessagePipeDispatcher::kDefaultHandleRights, + read_handles[0].rights); handle = std::move(read_handles[0]); read_handles.clear(); @@ -1324,7 +1329,8 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { EXPECT_EQ(Dispatcher::Type::MESSAGE_PIPE, read_handles[0].dispatcher->GetType()); - // TODO(vtl): Also check the rights here once they're actually preserved. + EXPECT_EQ(MessagePipeDispatcher::kDefaultHandleRights, + read_handles[0].rights); dispatcher = RefPtr( static_cast(read_handles[0].dispatcher.get())); read_handles.clear(); diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc index 43af5f11900d5..af3ed3161d33a 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.cc +++ b/mojo/edk/system/shared_buffer_dispatcher.cc @@ -102,7 +102,8 @@ Dispatcher::Type SharedBufferDispatcher::GetType() const { bool SharedBufferDispatcher::SupportsEntrypointClass( EntrypointClass entrypoint_class) const { - return (entrypoint_class == EntrypointClass::BUFFER); + return (entrypoint_class == EntrypointClass::NONE || + entrypoint_class == EntrypointClass::BUFFER); } // static @@ -218,6 +219,15 @@ void SharedBufferDispatcher::CloseImplNoLock() { shared_buffer_ = nullptr; } +MojoResult SharedBufferDispatcher::DuplicateDispatcherImplNoLock( + util::RefPtr* new_dispatcher) { + mutex().AssertHeld(); + + // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. + *new_dispatcher = CreateInternal(shared_buffer_.Clone()); + return MOJO_RESULT_OK; +} + RefPtr SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock( MessagePipe* /*message_pipe*/, diff --git a/mojo/edk/system/shared_buffer_dispatcher.h b/mojo/edk/system/shared_buffer_dispatcher.h index 0dd2fc0f0d589..059f74e6eda0e 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.h +++ b/mojo/edk/system/shared_buffer_dispatcher.h @@ -36,8 +36,9 @@ class SharedBufferDispatcher final : public SimpleDispatcher { // duplicable by default. static constexpr MojoHandleRights kDefaultHandleRights = MOJO_HANDLE_RIGHT_DUPLICATE | MOJO_HANDLE_RIGHT_TRANSFER | - MOJO_HANDLE_RIGHT_READ | MOJO_HANDLE_RIGHT_WRITE | - MOJO_HANDLE_RIGHT_EXECUTE; + MOJO_HANDLE_RIGHT_GET_OPTIONS | MOJO_HANDLE_RIGHT_SET_OPTIONS | + MOJO_HANDLE_RIGHT_MAP_READABLE | MOJO_HANDLE_RIGHT_MAP_WRITABLE | + MOJO_HANDLE_RIGHT_MAP_EXECUTABLE; // The default options to use for |MojoCreateSharedBuffer()|. (Real uses // should obtain this via |ValidateCreateOptions()| with a null |in_options|; @@ -95,6 +96,8 @@ class SharedBufferDispatcher final : public SimpleDispatcher { // |Dispatcher| protected methods: void CloseImplNoLock() override; + MojoResult DuplicateDispatcherImplNoLock( + util::RefPtr* new_dispatcher) override; util::RefPtr CreateEquivalentDispatcherAndCloseImplNoLock( MessagePipe* message_pipe, unsigned port) override; diff --git a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc index c6bbe59d9ae5c..bf8a1ddbf4607 100644 --- a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc +++ b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc @@ -191,6 +191,7 @@ TEST_F(SharedBufferDispatcherTest, SupportsEntrypointClass) { ASSERT_TRUE(d); EXPECT_EQ(MOJO_RESULT_OK, result); + EXPECT_TRUE(d->SupportsEntrypointClass(EntrypointClass::NONE)); EXPECT_FALSE(d->SupportsEntrypointClass(EntrypointClass::MESSAGE_PIPE)); EXPECT_FALSE(d->SupportsEntrypointClass(EntrypointClass::DATA_PIPE_PRODUCER)); EXPECT_FALSE(d->SupportsEntrypointClass(EntrypointClass::DATA_PIPE_CONSUMER)); @@ -202,6 +203,49 @@ TEST_F(SharedBufferDispatcherTest, SupportsEntrypointClass) { EXPECT_EQ(MOJO_RESULT_OK, d->Close()); } +TEST_F(SharedBufferDispatcherTest, DuplicateDispatcher) { + const uint64_t kSize = 100u; + + MojoResult result = MOJO_RESULT_INTERNAL; + auto dispatcher1 = SharedBufferDispatcher::Create( + platform_support(), SharedBufferDispatcher::kDefaultCreateOptions, kSize, + &result); + EXPECT_EQ(MOJO_RESULT_OK, result); + + // Map and write something. + std::unique_ptr mapping; + EXPECT_EQ( + MOJO_RESULT_OK, + dispatcher1->MapBuffer(0u, kSize, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); + static_cast(mapping->GetBase())[0] = 'x'; + mapping.reset(); + + // Duplicate |dispatcher1| and then close it. + RefPtr dispatcher2; + EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateDispatcher(&dispatcher2)); + ASSERT_TRUE(dispatcher2); + EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType()); + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); + + // Make sure that |dispatcher2| still reports the right information. + MojoBufferInformation info = {}; + EXPECT_EQ(MOJO_RESULT_OK, + dispatcher2->GetBufferInformation( + MakeUserPointer(&info), static_cast(sizeof(info)))); + EXPECT_EQ(sizeof(MojoBufferInformation), info.struct_size); + EXPECT_EQ(MOJO_BUFFER_INFORMATION_FLAG_NONE, info.flags); + EXPECT_EQ(kSize, info.num_bytes); + + // Map |dispatcher2| and read something. + EXPECT_EQ( + MOJO_RESULT_OK, + dispatcher2->MapBuffer(0u, kSize, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); + EXPECT_EQ('x', static_cast(mapping->GetBase())[0]); + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); +} + TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { const uint64_t kSize = 100u; diff --git a/mojo/edk/system/transport_data.cc b/mojo/edk/system/transport_data.cc index 058d795af6fdc..05a03ba258b6d 100644 --- a/mojo/edk/system/transport_data.cc +++ b/mojo/edk/system/transport_data.cc @@ -19,22 +19,6 @@ using mojo::platform::ScopedPlatformHandle; namespace mojo { namespace system { -namespace { - -// TODO(vtl): Temporary, until |TransportData| really supports handles. -std::unique_ptr DispatcherVectorFromHandleVector( - std::unique_ptr handles) { - DCHECK(handles); - - std::unique_ptr dispatchers(new DispatcherVector()); - dispatchers->reserve(handles->size()); - for (size_t i = 0; i < handles->size(); i++) - dispatchers->push_back(std::move(handles->at(i).dispatcher)); - return dispatchers; -} - -} // namespace - // The maximum amount of space needed per platform handle. // (|{Channel,RawChannel}::GetSerializedPlatformHandleSize()| should always // return a value which is at most this. This is only used to calculate @@ -79,19 +63,13 @@ struct TransportData::PrivateStructForCompileAsserts { "alignment"); }; -// TODO(vtl): Make this the real one. TransportData::TransportData(std::unique_ptr handles, Channel* channel) - : TransportData(DispatcherVectorFromHandleVector(std::move(handles)), - channel) {} - -TransportData::TransportData(std::unique_ptr dispatchers, - Channel* channel) : buffer_size_() { - DCHECK(dispatchers); + DCHECK(handles); DCHECK(channel); - const size_t num_handles = dispatchers->size(); + const size_t num_handles = handles->size(); DCHECK_GT(num_handles, 0u); // The offset to the start of the (Mojo) handle table. @@ -108,11 +86,12 @@ TransportData::TransportData(std::unique_ptr dispatchers, std::vector all_max_platform_handles(num_handles); #endif for (size_t i = 0; i < num_handles; i++) { - if (Dispatcher* dispatcher = (*dispatchers)[i].get()) { + if (handles->at(i)) { size_t max_size = 0; size_t max_platform_handles = 0; Dispatcher::TransportDataAccess::StartSerialize( - dispatcher, channel, &max_size, &max_platform_handles); + handles->at(i).dispatcher.get(), channel, &max_size, + &max_platform_handles); DCHECK_LE(max_size, kMaxSerializedDispatcherSize); estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size); @@ -159,8 +138,8 @@ TransportData::TransportData(std::unique_ptr dispatchers, buffer_.get() + handle_table_start_offset); size_t current_offset = serialized_dispatcher_start_offset; for (size_t i = 0; i < num_handles; i++) { - Dispatcher* dispatcher = (*dispatchers)[i].get(); - if (!dispatcher) { + Handle& handle = handles->at(i); + if (!handle) { static_assert(static_cast(Dispatcher::Type::UNKNOWN) == 0, "Value of Dispatcher::Type::UNKNOWN must be 0"); continue; @@ -174,12 +153,12 @@ TransportData::TransportData(std::unique_ptr dispatchers, void* destination = buffer_.get() + current_offset; size_t actual_size = 0; if (Dispatcher::TransportDataAccess::EndSerializeAndClose( - dispatcher, channel, destination, &actual_size, + handle.dispatcher.get(), channel, destination, &actual_size, platform_handles_.get())) { - handle_table[i].type = static_cast(dispatcher->GetType()); + handle_table[i].type = static_cast(handle.dispatcher->GetType()); handle_table[i].offset = static_cast(current_offset); handle_table[i].size = static_cast(actual_size); -// (Okay to not set |unused| since we cleared the entire buffer.) + handle_table[i].rights = handle.rights; #if DCHECK_IS_ON() DCHECK_LE(actual_size, all_max_sizes[i]); @@ -212,8 +191,6 @@ TransportData::TransportData(std::unique_ptr dispatchers, // There's no aligned realloc, so it's no good way to release unused space (if // we overshot our estimated space requirements). buffer_size_ = current_offset; - - // |dispatchers_| will be destroyed as it goes out of scope. } TransportData::TransportData( @@ -331,7 +308,7 @@ void TransportData::GetPlatformHandleTable(const void* transport_data_buffer, } // static -std::unique_ptr TransportData::DeserializeDispatchers( +std::unique_ptr TransportData::DeserializeHandles( const void* buffer, size_t buffer_size, std::unique_ptr> platform_handles, @@ -342,8 +319,7 @@ std::unique_ptr TransportData::DeserializeDispatchers( const Header* header = static_cast(buffer); const size_t num_handles = header->num_handles; - std::unique_ptr dispatchers( - new DispatcherVector(num_handles)); + std::unique_ptr handles(new HandleVector(num_handles)); const HandleTableEntry* handle_table = reinterpret_cast( @@ -357,11 +333,13 @@ std::unique_ptr TransportData::DeserializeDispatchers( DCHECK_LE(offset + size, buffer_size); const void* source = static_cast(buffer) + offset; - (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize( - channel, handle_table[i].type, source, size, platform_handles.get()); + (*handles)[i] = Handle(Dispatcher::TransportDataAccess::Deserialize( + channel, handle_table[i].type, source, size, + platform_handles.get()), + handle_table[i].rights); } - return dispatchers; + return handles; } } // namespace system diff --git a/mojo/edk/system/transport_data.h b/mojo/edk/system/transport_data.h index 8698a6d388fe7..310e33d85cdaa 100644 --- a/mojo/edk/system/transport_data.h +++ b/mojo/edk/system/transport_data.h @@ -13,6 +13,8 @@ #include "mojo/edk/platform/aligned_alloc.h" #include "mojo/edk/platform/scoped_platform_handle.h" #include "mojo/edk/system/dispatcher.h" +#include "mojo/edk/system/handle.h" +#include "mojo/public/c/system/handle.h" #include "mojo/public/cpp/system/macros.h" namespace mojo { @@ -87,9 +89,6 @@ class TransportData { static size_t GetMaxPlatformHandles(); TransportData(std::unique_ptr handles, Channel* channel); - // TODO(vtl): Remove this, once |TransportData| really supports handles. - TransportData(std::unique_ptr dispatchers, - Channel* channel); // This is used for users of |MessageInTransit|/|TransportData|/|RawChannel| // that want to simply transport data and platform handles, and not @@ -138,10 +137,10 @@ class TransportData { size_t* num_platform_handles, const void** platform_handle_table); - // Deserializes dispatchers from the given (serialized) transport data buffer + // Deserializes handles from the given (serialized) transport data buffer // (typically from a |MessageInTransit::View|) and vector of platform handles. // |buffer| should be non-null and |buffer_size| should be nonzero. - static std::unique_ptr DeserializeDispatchers( + static std::unique_ptr DeserializeHandles( const void* buffer, size_t buffer_size, std::unique_ptr> @@ -168,7 +167,7 @@ class TransportData { int32_t type; // From |Dispatcher::Type| (|UNKNOWN| for "invalid"). uint32_t offset; // Relative to the start of the "secondary buffer". uint32_t size; // (Not including any padding.) - uint32_t unused; + MojoHandleRights rights; }; const Header* header() const { diff --git a/mojo/environment/environment.cc b/mojo/environment/environment.cc index 8867dd088342f..aa7ab9834e14e 100644 --- a/mojo/environment/environment.cc +++ b/mojo/environment/environment.cc @@ -10,32 +10,33 @@ namespace mojo { -// These methods are intentionally not implemented so that there is a link -// error if someone uses them in a Chromium-environment. -#if 0 -Environment::Environment() { -} +// TODO(vtl): Probably we should share the following async waiter and logger +// code with the "standalone" implementation. (The only difference is what the +// |internal::kDefault...| are.) -Environment::Environment(const MojoAsyncWaiter* default_async_waiter, - const MojoLogger* default_logger) { -} +const MojoAsyncWaiter* g_default_async_waiter = &internal::kDefaultAsyncWaiter; +const MojoLogger* g_default_logger = &internal::kDefaultLogger; -Environment::~Environment() { +// static +const MojoAsyncWaiter* Environment::GetDefaultAsyncWaiter() { + return g_default_async_waiter; } -#endif // static -const MojoAsyncWaiter* Environment::GetDefaultAsyncWaiter() { - return &internal::kDefaultAsyncWaiter; +void Environment::SetDefaultAsyncWaiter(const MojoAsyncWaiter* async_waiter) { + g_default_async_waiter = + async_waiter ? async_waiter : &internal::kDefaultAsyncWaiter; } // static const MojoLogger* Environment::GetDefaultLogger() { - return &internal::kDefaultLogger; + return g_default_logger; } // static -void Environment::SetDefaultLogger(const MojoLogger* logger) {} +void Environment::SetDefaultLogger(const MojoLogger* logger) { + g_default_logger = logger ? logger : &internal::kDefaultLogger; +} // static void Environment::InstantiateDefaultRunLoop() { diff --git a/mojo/icu/icu.cc b/mojo/icu/icu.cc index 993880d36ce6a..cd5f9b8c75e88 100644 --- a/mojo/icu/icu.cc +++ b/mojo/icu/icu.cc @@ -5,7 +5,6 @@ #include "mojo/icu/icu.h" #include "mojo/icu/constants.h" -#include "mojo/public/cpp/application/application_impl.h" #include "mojo/public/cpp/application/connect.h" #include "mojo/services/icu_data/interfaces/icu_data.mojom.h" #include "third_party/icu/source/common/unicode/putil.h" @@ -34,7 +33,7 @@ class Callback { } // namespace -void Initialize(ApplicationImpl* app) { +void Initialize(ApplicationConnector* application_connector) { #if !defined(OS_ANDROID) // On desktop platforms, the icu data table is stored in a file on disk, which // can be loaded using base. @@ -43,7 +42,7 @@ void Initialize(ApplicationImpl* app) { #endif icu_data::ICUDataPtr icu_data; - ConnectToService(app->shell(), "mojo:icu_data", GetProxy(&icu_data)); + ConnectToService(application_connector, "mojo:icu_data", GetProxy(&icu_data)); icu_data->Map(kDataHash, Callback()); icu_data.WaitForIncomingResponse(); } diff --git a/mojo/icu/icu.h b/mojo/icu/icu.h index 9b28cb910fca2..60edfbac56c24 100644 --- a/mojo/icu/icu.h +++ b/mojo/icu/icu.h @@ -6,11 +6,11 @@ #define MOJO_ICU_ICU_H_ namespace mojo { -class ApplicationImpl; +class ApplicationConnector; namespace icu { -void Initialize(ApplicationImpl* app); +void Initialize(ApplicationConnector* application_connector); } // namespace icu } // namespace mojo diff --git a/mojo/message_pump/BUILD.gn b/mojo/message_pump/BUILD.gn index 14daad6df93d3..c039429c53f1e 100644 --- a/mojo/message_pump/BUILD.gn +++ b/mojo/message_pump/BUILD.gn @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//mojo/public/mojo_application.gni") + source_set("message_pump") { sources = [ "handle_watcher.cc", @@ -19,7 +21,7 @@ source_set("message_pump") { ] } -source_set("tests") { +mojo_native_application("mojo_message_pump_apptests") { testonly = true sources = [ @@ -30,8 +32,10 @@ source_set("tests") { deps = [ ":message_pump", "//base", - "//base/test:test_support", "//base:message_loop_tests", + "//base/test:test_support", + "//mojo/application", + "//mojo/application:test_support", "//mojo/public/cpp/system", "//mojo/public/cpp/test_support:test_utils", "//testing/gtest", diff --git a/mojo/services/files/c/tests/mojio_impl_test_base.cc b/mojo/services/files/c/tests/mojio_impl_test_base.cc index 96abd9fc1853d..3b345ee59433b 100644 --- a/mojo/services/files/c/tests/mojio_impl_test_base.cc +++ b/mojo/services/files/c/tests/mojio_impl_test_base.cc @@ -6,7 +6,6 @@ #include "files/interfaces/files.mojom-sync.h" #include "files/interfaces/files.mojom.h" -#include "mojo/public/cpp/application/application_impl.h" #include "mojo/public/cpp/application/connect.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/bindings/synchronous_interface_ptr.h" @@ -27,8 +26,7 @@ void MojioImplTestBase::SetUp() { mojo::test::ApplicationTestBase::SetUp(); SynchronousInterfacePtr files; - mojo::ConnectToService(application_impl()->shell(), "mojo:files", - GetSynchronousProxy(&files)); + mojo::ConnectToService(shell(), "mojo:files", GetSynchronousProxy(&files)); mojo::files::Error error = mojo::files::Error::INTERNAL; MOJO_CHECK( diff --git a/mojo/services/gfx/composition/interfaces/renderers.mojom b/mojo/services/gfx/composition/interfaces/renderers.mojom index a911d405f6dc3..97f8d89822528 100644 --- a/mojo/services/gfx/composition/interfaces/renderers.mojom +++ b/mojo/services/gfx/composition/interfaces/renderers.mojom @@ -8,6 +8,7 @@ module mojo.gfx.composition; import "mojo/services/geometry/interfaces/geometry.mojom"; import "mojo/services/gfx/composition/interfaces/hit_tests.mojom"; import "mojo/services/gfx/composition/interfaces/scene_token.mojom"; +import "mojo/services/gfx/composition/interfaces/scheduling.mojom"; // The renderer is a service which renders a scene graph to a display. // @@ -36,6 +37,9 @@ interface Renderer { // Dissociates the root scene from the renderer. ClearRootScene(); + // Gets a scheduler to receive frame timing information for the renderer. + GetScheduler(FrameScheduler& scheduler); + // Provides an interface which can be used to perform hit tests on the // contents of the renderer's scene graph. GetHitTester(HitTester& hit_tester); diff --git a/mojo/services/gfx/composition/interfaces/scenes.mojom b/mojo/services/gfx/composition/interfaces/scenes.mojom index 158f964df1870..d4dadec7b28b4 100644 --- a/mojo/services/gfx/composition/interfaces/scenes.mojom +++ b/mojo/services/gfx/composition/interfaces/scenes.mojom @@ -117,8 +117,8 @@ const uint32 kSceneVersionNone = 0; // // SCHEDULING // -// The scene provides support for scheduling update via its associated -// |SceneScheduler| interface. Use the scheduler to obtain frame timing +// The scene provides support for scheduling frames via its associated +// |FrameScheduler| interface. Use the scheduler to obtain frame timing // information and to throttle updates to match the display refresh rate // (ie. with vsync). interface Scene { @@ -155,8 +155,8 @@ interface Scene { // introducing cycles in the scene's nodes; the connection will be closed. Publish(SceneMetadata? metadata); - // Gets a scheduler for scheduling upcoming scene operations. - GetScheduler(SceneScheduler& scheduler); + // Gets a scheduler to receive frame timing information for the scene. + GetScheduler(FrameScheduler& scheduler); }; // An interface applications may implement to receive events from a scene. diff --git a/mojo/services/gfx/composition/interfaces/scheduling.mojom b/mojo/services/gfx/composition/interfaces/scheduling.mojom index 7b5dee1c4d28b..91b09ae61a67c 100644 --- a/mojo/services/gfx/composition/interfaces/scheduling.mojom +++ b/mojo/services/gfx/composition/interfaces/scheduling.mojom @@ -5,26 +5,25 @@ [DartPackage="mojo_services"] module mojo.gfx.composition; -// Provides support for scheduling drawing and composition operations -// for a particular scene. +// Provides support for scheduling drawing and composition operations. // -// Instances of this interface must be obtained from a |Scene|. This interface -// is modeled separately so as to allow applications to use different threads -// for scheduling work as opposed to publishing scene updates. -interface SceneScheduler { +// Instances of this interface must be obtained from a |Scene| or |Renderer|. +interface FrameScheduler { // Asks the compositor to invoke the callback when it is a good time to // draw the next frame. // // The rate at which the callback is invoked may depend on how the scene // has been embedded. The scene will only receive frame callbacks while // it is attached to a scene graph which the compositor has been asked - // to renderer since timing information ultimately derives from the + // to render since timing information ultimately derives from the // renderer. If the same scene is being rendered to multiple destinations - // with different timing requirements, the compositor will perform rate - // adaptation as required behind the scenes. + // with different timing requirements, the compositor will couple the + // scene scheduling to one of the renderers. // // The returned |frame_info| provides information about the frame to - // be drawn. + // be drawn. This information should be passed to a + // |mojo::gfx::composition::FrameTracker| to apply compensation for + // skipped frames before using it. // // TODO(jeffbrown): Consider whether we should have the callback be invoked // immediately rather than on schedule, letting the client set its own diff --git a/mojo/services/log/cpp/log_client.h b/mojo/services/log/cpp/log_client.h index fa860b1a125f3..049ed16a705c1 100644 --- a/mojo/services/log/cpp/log_client.h +++ b/mojo/services/log/cpp/log_client.h @@ -8,24 +8,25 @@ // // Example application that uses this log client to talk to the log service: // -// class MyDelegate : public mojo::ApplicationDelegate { +// class MyApp : public mojo::ApplicationImplBase { // public: -// void Initialize(mojo::ApplicationImpl* app) override { +// void OnInitialize() override { // LogPtr log; -// app->ConnectToService("mojo:log", &log); +// mojo::ConnectToService(shell(), "mojo:log", &log); // mojo::log::InitializeLogger(std::move(log), -// ApplicationRunner::GetDefaultLogger()); -// mojo::ApplicationRunner::SetDefaultLogger(mojo::log::GetLogger()); +// mojo::Environment::GetDefaultLogger()); +// mojo::Environment::SetDefaultLogger(mojo::log::GetLogger()); // } // -// void Quit() { +// void OnQuit() override { // mojo::log::DestroyLogger(); // } // }; // // MojoResult MojoMain(MojoHandle app_request) { -// mojo::ApplicationRunner runner(new MyDelegate); -// return runner.Run(app_request); +// MyApp app; +// mojo::RunApplication(&app); +// return MOJO_RESULT_OK; // } #ifndef MOJO_SERVICES_LOG_CPP_LOG_CLIENT_H_ diff --git a/mojo/services/media/core/interfaces/seeking_reader.mojom b/mojo/services/media/core/interfaces/seeking_reader.mojom index 014761233c5c4..f7a5ffde9dac5 100644 --- a/mojo/services/media/core/interfaces/seeking_reader.mojom +++ b/mojo/services/media/core/interfaces/seeking_reader.mojom @@ -5,7 +5,6 @@ [DartPackage="mojo_services"] module mojo.media; -import "mojo/services/files/interfaces/types.mojom"; import "mojo/services/media/common/interfaces/media_common.mojom"; // Reader with seek semantics. diff --git a/mojo/services/native_viewport/interfaces/native_viewport_event_dispatcher.mojom b/mojo/services/native_viewport/interfaces/native_viewport_event_dispatcher.mojom index 66533cf72c595..394a30aa59837 100644 --- a/mojo/services/native_viewport/interfaces/native_viewport_event_dispatcher.mojom +++ b/mojo/services/native_viewport/interfaces/native_viewport_event_dispatcher.mojom @@ -7,7 +7,6 @@ module mojo; import "input_events/interfaces/input_events.mojom"; -[ServiceName="mojo::NativeViewportEventDispatcher"] interface NativeViewportEventDispatcher { OnEvent(Event event) => (); }; diff --git a/mojo/services/ui/views/interfaces/view_associates.mojom b/mojo/services/ui/views/interfaces/view_associates.mojom index 8fcac9c8fb9e5..a1d575e57fa43 100644 --- a/mojo/services/ui/views/interfaces/view_associates.mojom +++ b/mojo/services/ui/views/interfaces/view_associates.mojom @@ -27,11 +27,6 @@ import "mojo/services/ui/views/interfaces/view_tree_token.mojom"; // This mechanism is designed to avoid a potential explosion in complexity // if all features which depend on the state of views were implemented // in one place. -// -// TODO(jeffbrown): In the current implementation, the view manager binds -// to a hard coded set of associates at start up time which can be overridden -// from the command-line. We should find a better way to register associates -// once we decide how the system as a whole should be initialized. [ServiceName="mojo::ui::ViewAssociate"] interface ViewAssociate { // Connects to the associate. @@ -65,6 +60,15 @@ interface ViewAssociate { handle pipe); }; +// ViewAssociateOwner is used as a transferable reference which can +// be passed to a ViewAssociate's intended container as part of a request to +// register the ViewAssociate with the ViewManager. The ViewAssociateOwner will +// get a connection error callback if the corresponding ViewAssociate is +// destroyed, and similarly the ViewAssociate that it owns will be killed if +// this object is destroyed. +[ServiceName="mojo::ui::ViewAssociateOwner"] +interface ViewAssociateOwner {}; + // Provides information about the services offered by an associate. struct ViewAssociateInfo { // The names of view services offered by the associate. diff --git a/mojo/services/ui/views/interfaces/view_manager.mojom b/mojo/services/ui/views/interfaces/view_manager.mojom index 6592ea9119d0c..68487bcf56c08 100644 --- a/mojo/services/ui/views/interfaces/view_manager.mojom +++ b/mojo/services/ui/views/interfaces/view_manager.mojom @@ -67,4 +67,30 @@ interface ViewManager { CreateViewTree(mojo.ui.ViewTree& view_tree, mojo.ui.ViewTreeListener view_tree_listener, string? label); + + // Registers a view associate with the view manager. + // + // The services provided by |view_associate| will be made available to views. + // + // You receive a |view_associate_owner| which will receive a connection error + // callback if |view_associate| is closed. Conversely, the service for + // |view_associate| will be destroyed if |view_associate_owner| is destroyed. + // + // |label| is used to identify the ViewAssociate for debug purposes. + // + // TODO(mikejurka): This method should only be made accessible to trusted + // services, once we have a security story + RegisterViewAssociate(mojo.ui.ViewAssociate view_associate, + mojo.ui.ViewAssociateOwner& view_associate_owner, string? label); + + // Tells the view manager we've registered all our view associates. + // + // This allows it to prevent views from requesting services from ViewAssociate + // before all the ViewAssociates have been registered. + // + // TODO(mikejurka): This method should only be made accessible to trusted + // services, once we have a security story + // TODO(mikejurka): We should remove this method once we have a way of + // dynamically registering and unregistering ViewAssociates + FinishedRegisteringViewAssociates(); }; diff --git a/mojo/skia/ganesh_image_factory.cc b/mojo/skia/ganesh_image_factory.cc index 67b4cb8d381b0..da797a5fba0c3 100644 --- a/mojo/skia/ganesh_image_factory.cc +++ b/mojo/skia/ganesh_image_factory.cc @@ -41,7 +41,7 @@ sk_sp CreateImageFromTexture( info.fID = texture_id; GrBackendTextureDesc desc; - desc.fFlags = kRenderTarget_GrBackendTextureFlag; + desc.fFlags = kNone_GrBackendTextureFlag; desc.fWidth = width; desc.fHeight = height; desc.fConfig = kSkia8888_GrPixelConfig; From 1d01e023ce31c6dd983216de879520dd3cdcae87 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 26 May 2016 15:53:33 -0700 Subject: [PATCH 2/2] Update to new API --- .../service_xcode_harness/ServiceMain.cc | 1 - sky/packages/sky_services/pubspec.yaml | 2 +- sky/services/activity/ios/activity_impl.h | 8 ---- sky/services/activity/ios/activity_impl.mm | 6 --- sky/services/dynamic/dynamic_service_dylib.cc | 15 +++--- sky/services/editing/ios/clipboard_impl.h | 9 ---- sky/services/editing/ios/clipboard_impl.mm | 6 --- sky/services/editing/ios/keyboard_impl.h | 9 ---- sky/services/editing/ios/keyboard_impl.mm | 6 --- sky/services/engine/sky_engine.mojom | 2 +- sky/services/media/ios/media_player_impl.h | 7 --- sky/services/media/ios/media_player_impl.mm | 6 --- sky/services/media/ios/media_service_impl.h | 10 ---- sky/services/media/ios/media_service_impl.mm | 10 +--- sky/services/media/ios/sound_pool_impl.h | 7 --- sky/services/media/ios/sound_pool_impl.mm | 6 --- sky/services/ns_net/network_service_impl.h | 7 --- sky/services/ns_net/network_service_impl.mm | 5 -- sky/services/ns_net/url_loader_impl.h | 1 - .../platform/ios/haptic_feedback_impl.h | 7 --- .../platform/ios/haptic_feedback_impl.mm | 6 --- .../platform/ios/path_provider_impl.h | 7 --- .../platform/ios/path_provider_impl.mm | 5 -- .../platform/ios/system_chrome_impl.h | 7 --- .../platform/ios/system_chrome_impl.mm | 5 -- sky/services/platform/ios/system_sound_impl.h | 7 --- .../platform/ios/system_sound_impl.mm | 5 -- sky/services/vsync/ios/vsync_provider_impl.h | 8 ---- sky/services/vsync/ios/vsync_provider_impl.mm | 6 --- .../platform/mac/platform_service_provider.cc | 48 +++++++++---------- .../platform/mac/platform_service_provider.h | 12 ----- .../platform/mac/view_service_provider.cc | 4 +- .../platform/mac/view_service_provider.h | 3 -- sky/shell/platform/mojo/main_mojo.cc | 24 +++++----- sky/shell/platform/mojo/view_impl.cc | 2 +- sky/shell/ui/animator.cc | 4 +- sky/shell/ui/animator.h | 8 ++-- sky/shell/ui/engine.cc | 4 +- sky/shell/ui/engine.h | 1 - 39 files changed, 59 insertions(+), 237 deletions(-) diff --git a/sky/build/service_xcode_harness/ServiceMain.cc b/sky/build/service_xcode_harness/ServiceMain.cc index 52c44bf5be8b8..8acf58fd4d706 100644 --- a/sky/build/service_xcode_harness/ServiceMain.cc +++ b/sky/build/service_xcode_harness/ServiceMain.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" void FlutterServicePerform(mojo::ScopedMessagePipeHandle client_handle, diff --git a/sky/packages/sky_services/pubspec.yaml b/sky/packages/sky_services/pubspec.yaml index d59b650891af0..904e5331b3cd9 100644 --- a/sky/packages/sky_services/pubspec.yaml +++ b/sky/packages/sky_services/pubspec.yaml @@ -4,6 +4,6 @@ author: Flutter Authors description: Mojom interfaces associated with Flutter homepage: http://flutter.io dependencies: - mojo_sdk: 0.2.24 + mojo_sdk: 0.2.27 environment: sdk: '>=1.8.0 <2.0.0' diff --git a/sky/services/activity/ios/activity_impl.h b/sky/services/activity/ios/activity_impl.h index 9fe71d13ac1c7..08e0da2f0f8a0 100644 --- a/sky/services/activity/ios/activity_impl.h +++ b/sky/services/activity/ios/activity_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_ACTIVITY_IOS_ACTIVITY_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/activity/activity.mojom.h" @@ -30,13 +29,6 @@ class ActivityImpl : public ::activity::Activity { DISALLOW_COPY_AND_ASSIGN(ActivityImpl); }; -class ActivityFactory - : public mojo::InterfaceFactory<::activity::Activity> { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::activity::Activity> request) override; -}; - } // namespace activity } // namespace services } // namespace sky diff --git a/sky/services/activity/ios/activity_impl.mm b/sky/services/activity/ios/activity_impl.mm index 912de2f895367..8c2fd1b3713e7 100644 --- a/sky/services/activity/ios/activity_impl.mm +++ b/sky/services/activity/ios/activity_impl.mm @@ -30,12 +30,6 @@ // No counterpart on iOS but is a benign operation. So no asserts. } -void ActivityFactory::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::activity::Activity> request) { - new ActivityImpl(request.Pass()); -} - } // namespace activity } // namespace services } // namespace sky diff --git a/sky/services/dynamic/dynamic_service_dylib.cc b/sky/services/dynamic/dynamic_service_dylib.cc index 7313ee521b211..50979932b48f5 100644 --- a/sky/services/dynamic/dynamic_service_dylib.cc +++ b/sky/services/dynamic/dynamic_service_dylib.cc @@ -9,17 +9,19 @@ #include "sky/services/dynamic/dynamic_service_dylib.h" #include "mojo/public/cpp/environment/environment.h" -static mojo::Environment* g_dylib_environment; +static bool g_did_initialize_environment = false; void FlutterServiceOnLoad(const MojoAsyncWaiter* waiter, const MojoLogger* logger) { // Assert that the dylib environment is not already initialized somehow. - assert(g_dylib_environment == nullptr); - g_dylib_environment = new mojo::Environment(waiter, logger); + assert(!g_did_initialize_environment); + g_did_initialize_environment = true; + mojo::Environment::SetDefaultAsyncWaiter(waiter); + mojo::Environment::SetDefaultLogger(logger); } void FlutterServiceInvoke(MojoHandle client_handle, const char* service_name) { - assert(g_dylib_environment != nullptr); + assert(g_did_initialize_environment); // The service is always responsible for releasing the client handle. Create // a scoped handle immediately. @@ -35,7 +37,6 @@ void FlutterServiceInvoke(MojoHandle client_handle, const char* service_name) { void FlutterServiceOnUnload() { // Make sure the library is not being unloaded without the OnLoad callback // being called already. - assert(g_dylib_environment != nullptr); - delete g_dylib_environment; - g_dylib_environment = nullptr; + assert(g_did_initialize_environment); + g_did_initialize_environment = false; } diff --git a/sky/services/editing/ios/clipboard_impl.h b/sky/services/editing/ios/clipboard_impl.h index ab46e496500b9..7e7fb9871f9bd 100644 --- a/sky/services/editing/ios/clipboard_impl.h +++ b/sky/services/editing/ios/clipboard_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_CLIPBOARD_IOS_CLIPBOARD_SERVICE_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/editing/editing.mojom.h" @@ -29,14 +28,6 @@ class ClipboardImpl : public ::editing::Clipboard { DISALLOW_COPY_AND_ASSIGN(ClipboardImpl); }; -class ClipboardFactory - : public mojo::InterfaceFactory<::editing::Clipboard> { - public: - void Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::editing::Clipboard> request) override; -}; - } // namespace editing } // namespace services } // namespace sky diff --git a/sky/services/editing/ios/clipboard_impl.mm b/sky/services/editing/ios/clipboard_impl.mm index d0fc5ea15845c..7197c51a94394 100644 --- a/sky/services/editing/ios/clipboard_impl.mm +++ b/sky/services/editing/ios/clipboard_impl.mm @@ -46,12 +46,6 @@ callback.Run(clip.Pass()); } -void ClipboardFactory::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::editing::Clipboard> request) { - new ClipboardImpl(request.Pass()); -} - } // namespace editing } // namespace services } // namespace sky diff --git a/sky/services/editing/ios/keyboard_impl.h b/sky/services/editing/ios/keyboard_impl.h index 21ce0f1a02df6..d7154509741e4 100644 --- a/sky/services/editing/ios/keyboard_impl.h +++ b/sky/services/editing/ios/keyboard_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_KEYBOARD_IOS_KEYBOARD_SERVICE_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/editing/editing.mojom.h" @@ -37,14 +36,6 @@ class KeyboardImpl : public ::editing::Keyboard { DISALLOW_COPY_AND_ASSIGN(KeyboardImpl); }; -class KeyboardFactory - : public mojo::InterfaceFactory<::editing::Keyboard> { - public: - void Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::editing::Keyboard> request) override; -}; - } // namespace editing } // namespace services } // namespace sky diff --git a/sky/services/editing/ios/keyboard_impl.mm b/sky/services/editing/ios/keyboard_impl.mm index e64bdeab9c2ab..c2ecf7cc66a3e 100644 --- a/sky/services/editing/ios/keyboard_impl.mm +++ b/sky/services/editing/ios/keyboard_impl.mm @@ -157,12 +157,6 @@ - (void)deleteBackward { [client_ hide]; } -void KeyboardFactory::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::editing::Keyboard> request) { - new KeyboardImpl(request.Pass()); -} - } // namespace editing } // namespace services } // namespace sky diff --git a/sky/services/engine/sky_engine.mojom b/sky/services/engine/sky_engine.mojom index b5fd0f2ce9eb0..05a981517ea40 100644 --- a/sky/services/engine/sky_engine.mojom +++ b/sky/services/engine/sky_engine.mojom @@ -34,7 +34,7 @@ struct ServicesData { mojo.ServiceProvider&? outgoing_services; mojo.ui.View? view; mojo.ServiceProvider? view_services; - mojo.gfx.composition.SceneScheduler? scene_scheduler; + mojo.gfx.composition.FrameScheduler? frame_scheduler; }; [ServiceName="sky::SkyEngine"] diff --git a/sky/services/media/ios/media_player_impl.h b/sky/services/media/ios/media_player_impl.h index 59a7d111e74fc..3661003d1d9d9 100644 --- a/sky/services/media/ios/media_player_impl.h +++ b/sky/services/media/ios/media_player_impl.h @@ -7,7 +7,6 @@ #include "base/files/file_path.h" #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/media/media.mojom.h" @@ -47,12 +46,6 @@ class MediaPlayerImpl : public ::media::MediaPlayer { DISALLOW_COPY_AND_ASSIGN(MediaPlayerImpl); }; -class MediaPlayerFactory : public mojo::InterfaceFactory<::media::MediaPlayer> { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::media::MediaPlayer> request) override; -}; - } // namespace media } // namespace services } // namespace sky diff --git a/sky/services/media/ios/media_player_impl.mm b/sky/services/media/ios/media_player_impl.mm index 71547cacc2fec..0f0a8afa0d35d 100644 --- a/sky/services/media/ios/media_player_impl.mm +++ b/sky/services/media/ios/media_player_impl.mm @@ -162,12 +162,6 @@ - (void)dealloc { [audio_client_ setLooping:looping]; } -void MediaPlayerFactory::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::media::MediaPlayer> request) { - new MediaPlayerImpl(request.Pass()); -} - } // namespace media } // namespace services } // namespace sky diff --git a/sky/services/media/ios/media_service_impl.h b/sky/services/media/ios/media_service_impl.h index 9635e556ae3af..c3ffb88d86101 100644 --- a/sky/services/media/ios/media_service_impl.h +++ b/sky/services/media/ios/media_service_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_MEDIA_IOS_MEDIA_SERVICE_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/media/media.mojom.h" #include "sky/services/media/ios/media_player_impl.h" @@ -29,19 +28,10 @@ class MediaServiceImpl : public ::media::MediaService { private: mojo::StrongBinding<::media::MediaService> binding_; - MediaPlayerFactory media_player_; - SoundPoolFactory sound_pool_; DISALLOW_COPY_AND_ASSIGN(MediaServiceImpl); }; -class MediaServiceFactory - : public mojo::InterfaceFactory<::media::MediaService> { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::media::MediaService> request) override; -}; - } // namespace media } // namespace services } // namespace sky diff --git a/sky/services/media/ios/media_service_impl.mm b/sky/services/media/ios/media_service_impl.mm index 9f2762a3eb23c..8715fa04255c1 100644 --- a/sky/services/media/ios/media_service_impl.mm +++ b/sky/services/media/ios/media_service_impl.mm @@ -17,19 +17,13 @@ void MediaServiceImpl::CreatePlayer( mojo::InterfaceRequest<::media::MediaPlayer> player) { - media_player_.Create(nullptr, player.Pass()); + new MediaPlayerImpl(player.Pass()); } void MediaServiceImpl::CreateSoundPool( mojo::InterfaceRequest<::media::SoundPool> pool, int32_t max_streams) { - sound_pool_.Create(nullptr, pool.Pass()); -} - -void MediaServiceFactory::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::media::MediaService> request) { - new MediaServiceImpl(request.Pass()); + new SoundPoolImpl(pool.Pass()); } } // namespace media diff --git a/sky/services/media/ios/sound_pool_impl.h b/sky/services/media/ios/sound_pool_impl.h index 1244b19147977..7146ecb39f1f4 100644 --- a/sky/services/media/ios/sound_pool_impl.h +++ b/sky/services/media/ios/sound_pool_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_MEDIA_IOS_SOUND_POOL_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/media/media.mojom.h" #include "sky/services/media/ios/media_player_impl.h" @@ -64,12 +63,6 @@ class SoundPoolImpl : public ::media::SoundPool { DISALLOW_COPY_AND_ASSIGN(SoundPoolImpl); }; -class SoundPoolFactory : public mojo::InterfaceFactory<::media::SoundPool> { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::media::SoundPool> request) override; -}; - } // namespace media } // namespace services } // namespace sky diff --git a/sky/services/media/ios/sound_pool_impl.mm b/sky/services/media/ios/sound_pool_impl.mm index 1aa2b340026c2..dd7a3b0c355a6 100644 --- a/sky/services/media/ios/sound_pool_impl.mm +++ b/sky/services/media/ios/sound_pool_impl.mm @@ -298,12 +298,6 @@ static float AverageVolume(mojo::Array& channel_volumes) { [sound_pool_ resumeAll]; } -void SoundPoolFactory::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::media::SoundPool> request) { - new SoundPoolImpl(request.Pass()); -} - } // namespace media } // namespace services } // namespace sky diff --git a/sky/services/ns_net/network_service_impl.h b/sky/services/ns_net/network_service_impl.h index a1e62cc71b8ba..f6d124644aede 100644 --- a/sky/services/ns_net/network_service_impl.h +++ b/sky/services/ns_net/network_service_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_NSNET_NETWORK_SERVICE_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/services/network/interfaces/network_service.mojom.h" @@ -45,12 +44,6 @@ class NetworkServiceImpl : public NetworkService { DISALLOW_COPY_AND_ASSIGN(NetworkServiceImpl); }; -class NetworkServiceFactory : public InterfaceFactory { - public: - void Create(ApplicationConnection* connection, - InterfaceRequest request) override; -}; - } // namespace mojo #endif // SKY_SERVICES_NSNET_NETWORK_SERVICE_IMPL_H_ diff --git a/sky/services/ns_net/network_service_impl.mm b/sky/services/ns_net/network_service_impl.mm index 8c78dcdb49806..11dbeba541952 100644 --- a/sky/services/ns_net/network_service_impl.mm +++ b/sky/services/ns_net/network_service_impl.mm @@ -63,9 +63,4 @@ DCHECK(false); } -void NetworkServiceFactory::Create(ApplicationConnection* connection, - InterfaceRequest request) { - new NetworkServiceImpl(request.Pass()); -} - } // namespace mojo diff --git a/sky/services/ns_net/url_loader_impl.h b/sky/services/ns_net/url_loader_impl.h index af9d1d76a7b36..8ecf6e4808c24 100644 --- a/sky/services/ns_net/url_loader_impl.h +++ b/sky/services/ns_net/url_loader_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_NSNET_URLLOADER_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/services/network/interfaces/url_loader.mojom.h" diff --git a/sky/services/platform/ios/haptic_feedback_impl.h b/sky/services/platform/ios/haptic_feedback_impl.h index 47cad6948c396..96dffcc3a64c1 100644 --- a/sky/services/platform/ios/haptic_feedback_impl.h +++ b/sky/services/platform/ios/haptic_feedback_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_PLATFORM_IOS_HAPTIC_FEEDBACK_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/platform/haptic_feedback.mojom.h" @@ -27,12 +26,6 @@ class HapticFeedbackImpl : public HapticFeedback { DISALLOW_COPY_AND_ASSIGN(HapticFeedbackImpl); }; -class HapticFeedbackFactory : public mojo::InterfaceFactory { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) override; -}; - } // namespace platform } // namespace flutter diff --git a/sky/services/platform/ios/haptic_feedback_impl.mm b/sky/services/platform/ios/haptic_feedback_impl.mm index 3ddcb6d5af0ab..0450edbfec73e 100644 --- a/sky/services/platform/ios/haptic_feedback_impl.mm +++ b/sky/services/platform/ios/haptic_feedback_impl.mm @@ -14,12 +14,6 @@ HapticFeedbackImpl::~HapticFeedbackImpl() {} -void HapticFeedbackFactory::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) { - new HapticFeedbackImpl(request.Pass()); -} - void HapticFeedbackImpl::Vibrate(const VibrateCallback& callback) { AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); } diff --git a/sky/services/platform/ios/path_provider_impl.h b/sky/services/platform/ios/path_provider_impl.h index 6e1965489375d..2392ddb632e4b 100644 --- a/sky/services/platform/ios/path_provider_impl.h +++ b/sky/services/platform/ios/path_provider_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_PLATFORM_IOS_PATH_PROVIDER_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/platform/path_provider.mojom.h" @@ -30,12 +29,6 @@ class PathProviderImpl : public PathProvider { DISALLOW_COPY_AND_ASSIGN(PathProviderImpl); }; -class PathProviderFactory : public mojo::InterfaceFactory { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) override; -}; - } // namespace platform } // namespace flutter diff --git a/sky/services/platform/ios/path_provider_impl.mm b/sky/services/platform/ios/path_provider_impl.mm index 255df587f861e..9ab21a98619bd 100644 --- a/sky/services/platform/ios/path_provider_impl.mm +++ b/sky/services/platform/ios/path_provider_impl.mm @@ -17,11 +17,6 @@ PathProviderImpl::~PathProviderImpl() {} -void PathProviderFactory::Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) { - new PathProviderImpl(request.Pass()); -} - static std::string GetDirectoryOfType(NSSearchPathDirectory dir) { base::mac::ScopedNSAutoreleasePool pool; NSArray* paths = diff --git a/sky/services/platform/ios/system_chrome_impl.h b/sky/services/platform/ios/system_chrome_impl.h index e97ce6adb73b5..50755ea56d30d 100644 --- a/sky/services/platform/ios/system_chrome_impl.h +++ b/sky/services/platform/ios/system_chrome_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_PLATFORM_IOS_SYSTEM_CHROME_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/platform/system_chrome.mojom.h" @@ -33,12 +32,6 @@ class SystemChromeImpl : public SystemChrome { DISALLOW_COPY_AND_ASSIGN(SystemChromeImpl); }; -class SystemChromeFactory : public mojo::InterfaceFactory { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) override; -}; - extern const char* const kOrientationUpdateNotificationName; extern const char* const kOrientationUpdateNotificationKey; diff --git a/sky/services/platform/ios/system_chrome_impl.mm b/sky/services/platform/ios/system_chrome_impl.mm index efa758fa3ea4d..cadd139c4ec5f 100644 --- a/sky/services/platform/ios/system_chrome_impl.mm +++ b/sky/services/platform/ios/system_chrome_impl.mm @@ -14,11 +14,6 @@ SystemChromeImpl::~SystemChromeImpl() {} -void SystemChromeFactory::Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) { - new SystemChromeImpl(request.Pass()); -} - /// Desugars a typed enum value and checks if it is set in a mask template ::value>::type> diff --git a/sky/services/platform/ios/system_sound_impl.h b/sky/services/platform/ios/system_sound_impl.h index 7f9a66a017fbe..37867f0e36370 100644 --- a/sky/services/platform/ios/system_sound_impl.h +++ b/sky/services/platform/ios/system_sound_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_PLATFORM_IOS_SYSTEM_SOUND_IMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "sky/services/platform/system_sound.mojom.h" @@ -27,12 +26,6 @@ class SystemSoundImpl : public SystemSound { DISALLOW_COPY_AND_ASSIGN(SystemSoundImpl); }; -class SystemSoundFactory : public mojo::InterfaceFactory { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) override; -}; - } // namespace platform } // namespace flutter diff --git a/sky/services/platform/ios/system_sound_impl.mm b/sky/services/platform/ios/system_sound_impl.mm index a6e6338ccea31..7cfaec0f49a90 100644 --- a/sky/services/platform/ios/system_sound_impl.mm +++ b/sky/services/platform/ios/system_sound_impl.mm @@ -14,11 +14,6 @@ SystemSoundImpl::~SystemSoundImpl() {} -void SystemSoundFactory::Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) { - new SystemSoundImpl(request.Pass()); -} - void SystemSoundImpl::Play(SystemSoundType type, const PlayCallback& callback) { base::mac::ScopedNSAutoreleasePool pool; diff --git a/sky/services/vsync/ios/vsync_provider_impl.h b/sky/services/vsync/ios/vsync_provider_impl.h index 5e064d94fa50b..ec86c0a95e7fa 100644 --- a/sky/services/vsync/ios/vsync_provider_impl.h +++ b/sky/services/vsync/ios/vsync_provider_impl.h @@ -6,7 +6,6 @@ #define SKY_SERVICES_VSYNC_IOS_VSYNCPROVIDERIMPL_H_ #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/services/vsync/interfaces/vsync.mojom.h" @@ -34,13 +33,6 @@ class VsyncProviderImpl : public ::vsync::VSyncProvider { DISALLOW_COPY_AND_ASSIGN(VsyncProviderImpl); }; -class VSyncProviderFactory - : public mojo::InterfaceFactory<::vsync::VSyncProvider> { - public: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::vsync::VSyncProvider> request) override; -}; - } // namespace vsync } // namespace services } // namespace sky diff --git a/sky/services/vsync/ios/vsync_provider_impl.mm b/sky/services/vsync/ios/vsync_provider_impl.mm index 15c3b34588b9a..18499a0a21307 100644 --- a/sky/services/vsync/ios/vsync_provider_impl.mm +++ b/sky/services/vsync/ios/vsync_provider_impl.mm @@ -85,12 +85,6 @@ - (void)dealloc { [client_ await:callback]; } -void VSyncProviderFactory::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<::vsync::VSyncProvider> request) { - new VsyncProviderImpl(request.Pass()); -} - } // namespace vsync } // namespace services } // namespace sky diff --git a/sky/shell/platform/mac/platform_service_provider.cc b/sky/shell/platform/mac/platform_service_provider.cc index feb214ca51e06..40e6c765db9e2 100644 --- a/sky/shell/platform/mac/platform_service_provider.cc +++ b/sky/shell/platform/mac/platform_service_provider.cc @@ -19,58 +19,58 @@ void PlatformServiceProvider::ConnectToService( const mojo::String& service_name, mojo::ScopedMessagePipeHandle client_handle) { if (service_name == mojo::NetworkService::Name_) { - network_.Create( - nullptr, mojo::InterfaceRequest(client_handle.Pass())); + new mojo::NetworkServiceImpl( + mojo::InterfaceRequest(client_handle.Pass())); return; } #if TARGET_OS_IPHONE if (service_name == ::media::MediaPlayer::Name_) { - media_player_.Create( - nullptr, mojo::InterfaceRequest<::media::MediaPlayer>(client_handle.Pass())); + new sky::services::media::MediaPlayerImpl( + mojo::InterfaceRequest<::media::MediaPlayer>(client_handle.Pass())); return; } if (service_name == ::media::MediaService::Name_) { - media_service_.Create(nullptr, mojo::InterfaceRequest<::media::MediaService>( - client_handle.Pass())); + new sky::services::media::MediaServiceImpl( + mojo::InterfaceRequest<::media::MediaService>(client_handle.Pass())); return; } if (service_name == ::vsync::VSyncProvider::Name_) { - vsync_.Create(nullptr, mojo::InterfaceRequest<::vsync::VSyncProvider>( - client_handle.Pass())); + new sky::services::vsync::VsyncProviderImpl( + mojo::InterfaceRequest<::vsync::VSyncProvider>(client_handle.Pass())); return; } if (service_name == ::activity::Activity::Name_) { - activity_.Create( - nullptr, mojo::InterfaceRequest<::activity::Activity>(client_handle.Pass())); + new sky::services::activity::ActivityImpl( + mojo::InterfaceRequest<::activity::Activity>(client_handle.Pass())); return; } if (service_name == ::editing::Clipboard::Name_) { - clipboard_.Create( - nullptr, mojo::InterfaceRequest<::editing::Clipboard>(client_handle.Pass())); + new sky::services::editing::ClipboardImpl( + mojo::InterfaceRequest<::editing::Clipboard>(client_handle.Pass())); return; } if (service_name == flutter::platform::HapticFeedback::Name_) { - haptic_feedback_.Create( - nullptr, mojo::InterfaceRequest( - client_handle.Pass())); + new flutter::platform::HapticFeedbackImpl( + mojo::InterfaceRequest( + client_handle.Pass())); return; } if (service_name == flutter::platform::PathProvider::Name_) { - path_provider_.Create(nullptr, - mojo::InterfaceRequest( - client_handle.Pass())); + new flutter::platform::PathProviderImpl( + mojo::InterfaceRequest( + client_handle.Pass())); return; } if (service_name == flutter::platform::SystemChrome::Name_) { - system_chrome_.Create(nullptr, - mojo::InterfaceRequest( - client_handle.Pass())); + new flutter::platform::SystemChromeImpl( + mojo::InterfaceRequest( + client_handle.Pass())); return; } if (service_name == flutter::platform::SystemSound::Name_) { - system_sound_.Create(nullptr, - mojo::InterfaceRequest( - client_handle.Pass())); + new flutter::platform::SystemSoundImpl( + mojo::InterfaceRequest( + client_handle.Pass())); return; } #endif diff --git a/sky/shell/platform/mac/platform_service_provider.h b/sky/shell/platform/mac/platform_service_provider.h index ec16c4f71b656..122a5ff51ed22 100644 --- a/sky/shell/platform/mac/platform_service_provider.h +++ b/sky/shell/platform/mac/platform_service_provider.h @@ -45,18 +45,6 @@ class PlatformServiceProvider : public mojo::ServiceProvider { private: DynamicServiceProviderCallback dynamic_service_provider_; mojo::StrongBinding binding_; - mojo::NetworkServiceFactory network_; -#if TARGET_OS_IPHONE - flutter::platform::HapticFeedbackFactory haptic_feedback_; - flutter::platform::PathProviderFactory path_provider_; - flutter::platform::SystemChromeFactory system_chrome_; - flutter::platform::SystemSoundFactory system_sound_; - sky::services::activity::ActivityFactory activity_; - sky::services::editing::ClipboardFactory clipboard_; - sky::services::media::MediaPlayerFactory media_player_; - sky::services::media::MediaServiceFactory media_service_; - sky::services::vsync::VSyncProviderFactory vsync_; -#endif DISALLOW_COPY_AND_ASSIGN(PlatformServiceProvider); }; diff --git a/sky/shell/platform/mac/view_service_provider.cc b/sky/shell/platform/mac/view_service_provider.cc index d5998f86cf496..f0b3217d386b1 100644 --- a/sky/shell/platform/mac/view_service_provider.cc +++ b/sky/shell/platform/mac/view_service_provider.cc @@ -30,8 +30,8 @@ void ViewServiceProvider::ConnectToService( } #if TARGET_OS_IPHONE if (service_name == ::editing::Keyboard::Name_) { - keyboard_.Create( - nullptr, mojo::InterfaceRequest<::editing::Keyboard>(client_handle.Pass())); + new sky::services::editing::KeyboardImpl( + mojo::InterfaceRequest<::editing::Keyboard>(client_handle.Pass())); return; } #endif diff --git a/sky/shell/platform/mac/view_service_provider.h b/sky/shell/platform/mac/view_service_provider.h index 28d94b412cf8f..441746b168c05 100644 --- a/sky/shell/platform/mac/view_service_provider.h +++ b/sky/shell/platform/mac/view_service_provider.h @@ -34,9 +34,6 @@ class ViewServiceProvider : public mojo::ServiceProvider { private: mojo::StrongBinding binding_; AppMesssagesConnector connect_to_app_messages_; -#if TARGET_OS_IPHONE - sky::services::editing::KeyboardFactory keyboard_; -#endif DISALLOW_COPY_AND_ASSIGN(ViewServiceProvider); }; diff --git a/sky/shell/platform/mojo/main_mojo.cc b/sky/shell/platform/mojo/main_mojo.cc index 77eb32b201309..03dfac6a35cd1 100644 --- a/sky/shell/platform/mojo/main_mojo.cc +++ b/sky/shell/platform/mojo/main_mojo.cc @@ -9,9 +9,9 @@ #include "mojo/common/tracing_impl.h" #include "mojo/icu/icu.h" #include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" #include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/connect.h" #include "mojo/services/content_handler/interfaces/content_handler.mojom.h" #include "sky/engine/public/platform/sky_settings.h" #include "sky/shell/shell.h" @@ -25,8 +25,7 @@ const char kEnableCheckedMode[] = "--enable-checked-mode"; } // namespace -class MojoApp : public mojo::ApplicationDelegate, - public mojo::InterfaceFactory { +class MojoApp : public mojo::ApplicationDelegate { public: MojoApp() {} ~MojoApp() override { } @@ -34,7 +33,10 @@ class MojoApp : public mojo::ApplicationDelegate, private: // Overridden from ApplicationDelegate: void Initialize(mojo::ApplicationImpl* app) override { - mojo::icu::Initialize(app); + mojo::ApplicationConnectorPtr application_connector = + mojo::ApplicationConnectorPtr::Create( + mojo::CreateApplicationConnector(app->shell())); + mojo::icu::Initialize(application_connector.get()); tracing_.Initialize(app); blink::SkySettings settings; @@ -46,17 +48,15 @@ class MojoApp : public mojo::ApplicationDelegate, } bool ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) override { - connection->AddService(this); + mojo::ServiceProviderImpl* service_provider_impl) override { + service_provider_impl->AddService( + [](const mojo::ConnectionContext& connection_context, + mojo::InterfaceRequest request) { + new ContentHandlerImpl(request.Pass()); + }); return true; } - // Overridden from InterfaceFactory - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest request) override { - new ContentHandlerImpl(request.Pass()); - } - mojo::TracingImpl tracing_; DISALLOW_COPY_AND_ASSIGN(MojoApp); diff --git a/sky/shell/platform/mojo/view_impl.cc b/sky/shell/platform/mojo/view_impl.cc index be07d4d25a327..1ce085a49412c 100644 --- a/sky/shell/platform/mojo/view_impl.cc +++ b/sky/shell/platform/mojo/view_impl.cc @@ -74,7 +74,7 @@ ViewImpl::ViewImpl(mojo::InterfaceRequest view_owner, // Compositing mojo::gfx::composition::ScenePtr scene; view->CreateScene(mojo::GetProxy(&scene)); - scene->GetScheduler(mojo::GetProxy(&services->scene_scheduler)); + scene->GetScheduler(mojo::GetProxy(&services->frame_scheduler)); services->view = view.Pass(); // Engine diff --git a/sky/shell/ui/animator.cc b/sky/shell/ui/animator.cc index cc123db31d9a8..29c58d8e18ae3 100644 --- a/sky/shell/ui/animator.cc +++ b/sky/shell/ui/animator.cc @@ -131,8 +131,8 @@ void Animator::OnFrameComplete() { } bool Animator::AwaitVSync() { - if (scene_scheduler_) { - scene_scheduler_->ScheduleFrame( + if (frame_scheduler_) { + frame_scheduler_->ScheduleFrame( base::Bind(&Animator::Animate, weak_factory_.GetWeakPtr())); return true; } else if (vsync_provider_) { diff --git a/sky/shell/ui/animator.h b/sky/shell/ui/animator.h index 7395106e5d818..af296c543c328 100644 --- a/sky/shell/ui/animator.h +++ b/sky/shell/ui/animator.h @@ -31,9 +31,9 @@ class Animator { void set_vsync_provider(vsync::VSyncProviderPtr vsync_provider); - void set_scene_scheduler( - mojo::InterfaceHandle scene_scheduler) { - scene_scheduler_ = mojo::gfx::composition::SceneSchedulerPtr::Create(scene_scheduler.Pass()); + void set_frame_scheduler( + mojo::InterfaceHandle frame_scheduler) { + frame_scheduler_ = mojo::gfx::composition::FrameSchedulerPtr::Create(frame_scheduler.Pass()); } @@ -46,7 +46,7 @@ class Animator { Engine::Config config_; rasterizer::RasterizerPtr rasterizer_; Engine* engine_; - mojo::gfx::composition::SceneSchedulerPtr scene_scheduler_; + mojo::gfx::composition::FrameSchedulerPtr frame_scheduler_; vsync::VSyncProviderPtr vsync_provider_; int outstanding_requests_; bool did_defer_frame_request_; diff --git a/sky/shell/ui/engine.cc b/sky/shell/ui/engine.cc index fed8cb823b7c6..1002a503aa02e 100644 --- a/sky/shell/ui/engine.cc +++ b/sky/shell/ui/engine.cc @@ -97,9 +97,9 @@ void Engine::SetServices(ServicesDataPtr services) { incoming_services_.get()); } - if (services_->scene_scheduler) { + if (services_->frame_scheduler) { animator_->Reset(); - animator_->set_scene_scheduler(services_->scene_scheduler.Pass()); + animator_->set_frame_scheduler(services_->frame_scheduler.Pass()); } else { #if defined(OS_ANDROID) || defined(OS_IOS) vsync::VSyncProviderPtr vsync_provider; diff --git a/sky/shell/ui/engine.h b/sky/shell/ui/engine.h index a31e0a899356f..ac7eea6c67d6b 100644 --- a/sky/shell/ui/engine.h +++ b/sky/shell/ui/engine.h @@ -10,7 +10,6 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "mojo/common/binding_set.h" -#include "mojo/public/cpp/application/interface_factory.h" #include "mojo/public/cpp/application/service_provider_impl.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/data_pipe.h"