From fab160cfcec556772e6685529bce6871a70fe3ce Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 29 Oct 2015 10:47:34 -0700 Subject: [PATCH] Rationalize embedder.dart and shell.dart This patch combines embedder.dart and shell.dart into one thing. We should now handle a bunch of error cases better. * embedder.connectToApplication has moved to shell.connectToApplication, matching the rest of the mojo universe. * embedder.connecttoService has moved to shell.connnectToService (and merged with shell.requestService). * shell.requestService is now shell.connectToService, matching the rest of the mojo universe. * serviceRegistry has moved from embedder.serviceRegistry to a top-level getter. Fixes #1803 --- examples/widgets/piano.dart | 2 +- packages/flutter/lib/services.dart | 1 - .../flutter/lib/src/services/activity.dart | 4 +- .../lib/src/services/asset_bundle.dart | 2 +- .../flutter/lib/src/services/embedder.dart | 72 ---------------- packages/flutter/lib/src/services/fetch.dart | 2 +- .../flutter/lib/src/services/keyboard.dart | 2 +- .../lib/src/services/service_registry.dart | 18 ++++ packages/flutter/lib/src/services/shell.dart | 83 ++++++++++++------- packages/flutter_sprites/lib/src/sound.dart | 4 +- .../unit/test/services/mock_services.dart | 4 +- packages/updater/lib/main.dart | 2 +- 12 files changed, 84 insertions(+), 112 deletions(-) delete mode 100644 packages/flutter/lib/src/services/embedder.dart create mode 100644 packages/flutter/lib/src/services/service_registry.dart diff --git a/examples/widgets/piano.dart b/examples/widgets/piano.dart index d63266a5b6..e63872a62a 100644 --- a/examples/widgets/piano.dart +++ b/examples/widgets/piano.dart @@ -68,7 +68,7 @@ class PianoApp extends StatelessComponent { Future _loadSounds() async { MediaServiceProxy mediaService = new MediaServiceProxy.unbound(); try { - shell.requestService(null, mediaService); + shell.connectToService(null, mediaService); List> pending = >[]; for (PianoKey key in keys) pending.add(key.load(mediaService)); diff --git a/packages/flutter/lib/services.dart b/packages/flutter/lib/services.dart index 67387b1d3b..844f28bddf 100644 --- a/packages/flutter/lib/services.dart +++ b/packages/flutter/lib/services.dart @@ -13,7 +13,6 @@ library services; export 'src/services/activity.dart'; export 'src/services/asset_bundle.dart'; -export 'src/services/embedder.dart'; export 'src/services/fetch.dart'; export 'src/services/image_cache.dart'; export 'src/services/image_decoder.dart'; diff --git a/packages/flutter/lib/src/services/activity.dart b/packages/flutter/lib/src/services/activity.dart index 0079a1573f..6891a9928b 100644 --- a/packages/flutter/lib/src/services/activity.dart +++ b/packages/flutter/lib/src/services/activity.dart @@ -22,7 +22,7 @@ const int MULTIPLE_TASK = 0x08000000; ActivityProxy _initActivityProxy() { ActivityProxy activity = new ActivityProxy.unbound(); - shell.requestService('mojo:sky_viewer', activity); + shell.connectToService(null, activity); return activity; } @@ -40,7 +40,7 @@ final UserFeedback userFeedback = _userFeedbackProxy.ptr; PathServiceProxy _initPathServiceProxy() { PathServiceProxy proxy = new PathServiceProxy.unbound(); - shell.requestService(null, proxy); + shell.connectToService(null, proxy); return proxy; } diff --git a/packages/flutter/lib/src/services/asset_bundle.dart b/packages/flutter/lib/src/services/asset_bundle.dart index ee6d0ff9a5..2700005515 100644 --- a/packages/flutter/lib/src/services/asset_bundle.dart +++ b/packages/flutter/lib/src/services/asset_bundle.dart @@ -44,7 +44,7 @@ class NetworkAssetBundle extends AssetBundle { Future _fetchAndUnpackBundle(String relativeUrl, AssetBundleProxy bundle) async { core.MojoDataPipeConsumer bundleData = (await fetchUrl(relativeUrl)).body; AssetUnpackerProxy unpacker = new AssetUnpackerProxy.unbound(); - shell.requestService("mojo:asset_bundle", unpacker); + shell.connectToService("mojo:asset_bundle", unpacker); unpacker.ptr.unpackZipStream(bundleData, bundle); unpacker.close(); } diff --git a/packages/flutter/lib/src/services/embedder.dart b/packages/flutter/lib/src/services/embedder.dart deleted file mode 100644 index f2e21214cc..0000000000 --- a/packages/flutter/lib/src/services/embedder.dart +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:ui_internals' as internals; - -import 'package:mojo/application.dart'; -import 'package:mojo/bindings.dart' as bindings; -import 'package:mojo/core.dart' as core; -import 'package:mojo/mojo/service_provider.mojom.dart'; -import 'package:mojo/mojo/shell.mojom.dart'; -import 'package:mojo_services/mojo/service_registry.mojom.dart'; - -final _EmbedderImpl embedder = new _EmbedderImpl(); - -class _EmbedderImpl { - ApplicationConnection _connection; - ServiceRegistryProxy _serviceRegistry; - ShellProxy _shell; - bool _internalsHasNoShell = false; - - ShellProxy get shell { - if (_internalsHasNoShell || _shell != null) return _shell; - - try { - _shell = new ShellProxy.fromHandle( - new core.MojoHandle(internals.takeShellProxyHandle())); - } catch (e) { - _internalsHasNoShell = true; - } - return _shell; - } - - ApplicationConnection get connection { - if (_connection == null) { - var stubHandle = - new core.MojoHandle(internals.takeServicesProvidedToEmbedder()); - var proxyHandle = - new core.MojoHandle(internals.takeServicesProvidedByEmbedder()); - _connection = new ApplicationConnection(stubHandle.isValid - ? new ServiceProviderStub.fromHandle(stubHandle) - : null, proxyHandle.isValid - ? new ServiceProviderProxy.fromHandle(proxyHandle) - : null); - } - return _connection; - } - - ApplicationConnection connectToApplication(String url) { - var proxy = new ServiceProviderProxy.unbound(); - var stub = new ServiceProviderStub.unbound(); - shell.ptr.connectToApplication(url, proxy, stub); - return new ApplicationConnection(stub, proxy); - } - - void connectToService(String url, bindings.ProxyBase proxy) { - var appSp = new ServiceProviderProxy.unbound(); - shell.ptr.connectToApplication(url, appSp, null); - var pipe = new core.MojoMessagePipe(); - proxy.impl.bind(pipe.endpoints[0]); - appSp.ptr.connectToService(proxy.name, pipe.endpoints[1]); - appSp.close(); - } - - ServiceRegistryProxy get serviceRegistry { - if (_serviceRegistry == null) { - _serviceRegistry = new ServiceRegistryProxy.fromHandle( - new core.MojoHandle(internals.takeServiceRegistry())); - } - return _serviceRegistry; - } -} diff --git a/packages/flutter/lib/src/services/fetch.dart b/packages/flutter/lib/src/services/fetch.dart index 047241bf07..4b1fee20a8 100644 --- a/packages/flutter/lib/src/services/fetch.dart +++ b/packages/flutter/lib/src/services/fetch.dart @@ -17,7 +17,7 @@ export 'package:mojo/mojo/url_response.mojom.dart' show UrlResponse; NetworkServiceProxy _initNetworkService() { NetworkServiceProxy networkService = new NetworkServiceProxy.unbound(); - shell.requestService("mojo:authenticated_network_service", networkService); + shell.connectToService("mojo:authenticated_network_service", networkService); return networkService; } diff --git a/packages/flutter/lib/src/services/keyboard.dart b/packages/flutter/lib/src/services/keyboard.dart index a6c2b2afff..a1dfa795d4 100644 --- a/packages/flutter/lib/src/services/keyboard.dart +++ b/packages/flutter/lib/src/services/keyboard.dart @@ -14,7 +14,7 @@ class _KeyboardConnection { _KeyboardConnection() { proxy = new KeyboardServiceProxy.unbound(); - shell.requestService("mojo:keyboard", proxy); + shell.connectToService("mojo:keyboard", proxy); } KeyboardServiceProxy proxy; diff --git a/packages/flutter/lib/src/services/service_registry.dart b/packages/flutter/lib/src/services/service_registry.dart new file mode 100644 index 0000000000..66424f3d6a --- /dev/null +++ b/packages/flutter/lib/src/services/service_registry.dart @@ -0,0 +1,18 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ui_internals' as internals; + +import 'package:mojo_services/mojo/service_registry.mojom.dart'; +import 'package:mojo/core.dart' as core; + +ServiceRegistryProxy _initServiceRegistryProxy() { + core.MojoHandle serviceRegistryHandle = new core.MojoHandle(internals.takeShellProxyHandle()); + if (!serviceRegistryHandle.isValid) + return null; + return new ServiceRegistryProxy.fromHandle(serviceRegistryHandle); +} + +final ServiceRegistryProxy _serviceRegistryProxy = _initServiceRegistryProxy(); +final ServiceRegistry serviceRegistry = _serviceRegistryProxy?.ptr; diff --git a/packages/flutter/lib/src/services/shell.dart b/packages/flutter/lib/src/services/shell.dart index e2bbffad21..86856c807e 100644 --- a/packages/flutter/lib/src/services/shell.dart +++ b/packages/flutter/lib/src/services/shell.dart @@ -5,47 +5,74 @@ import 'dart:ui_internals' as internals; import 'package:mojo/application.dart'; +import 'package:mojo/bindings.dart' as bindings; import 'package:mojo/core.dart' as core; import 'package:mojo/mojo/service_provider.mojom.dart'; +import 'package:mojo/mojo/shell.mojom.dart'; -import 'embedder.dart'; - -ApplicationConnection _initConnection() { - int rawHandle = internals.takeServicesProvidedByEmbedder(); - core.MojoHandle proxyHandle = new core.MojoHandle(rawHandle); - ServiceProviderProxy serviceProvider = null; - if (proxyHandle.isValid) serviceProvider = - new ServiceProviderProxy.fromHandle(proxyHandle); - return new ApplicationConnection(null, serviceProvider); -} - -// A replacement for requestService. Implementations should return true +// A replacement for shell.connectToService. Implementations should return true // if they handled the request, or false if the request should fall through // to the default requestService. -typedef bool OverrideRequestService(String url, Object proxy); +typedef bool OverrideConnectToService(String url, Object proxy); -// Set this to intercept calls to requestService and supply an alternative -// implementation of a service (for example, a mock for testing). -OverrideRequestService overrideRequestService; +// Set this to intercept calls to shell.connectToService and supply an +// alternative implementation of a service (for example, a mock for testing). +OverrideConnectToService overrideConnectToService; -class _ShellImpl { - _ShellImpl._(); +ShellProxy _initShellProxy() { + core.MojoHandle shellHandle = new core.MojoHandle(internals.takeShellProxyHandle()); + if (!shellHandle.isValid) + return null; + return new ShellProxy.fromHandle(shellHandle); +} - final ApplicationConnection _connection = _initConnection(); +ApplicationConnection _initEmbedderConnection() { + core.MojoHandle servicesHandle = new core.MojoHandle(internals.takeServicesProvidedByEmbedder()); + core.MojoHandle exposedServicesHandle = new core.MojoHandle(internals.takeServicesProvidedToEmbedder()); + ServiceProviderProxy services = servicesHandle.isValid ? + new ServiceProviderProxy.fromHandle(servicesHandle) : null; + ServiceProviderStub exposedServices = exposedServicesHandle.isValid ? + new ServiceProviderStub.fromHandle(exposedServicesHandle) : null; + return new ApplicationConnection(exposedServices, services); +} - void _requestService(String url, Object proxy) { - if (embedder.shell == null) _connection.requestService(proxy); - else embedder.connectToService(url, proxy); +final ShellProxy _shellProxy = _initShellProxy(); +final Shell _shell = _shellProxy?.ptr; +final ApplicationConnection _embedderConnection = _initEmbedderConnection(); + +class _Shell { + _Shell._(); + + ApplicationConnection connectToApplication(String url) { + if (_shell == null) + return null; + ServiceProviderProxy services = new ServiceProviderProxy.unbound(); + ServiceProviderStub exposedServices = new ServiceProviderStub.unbound(); + _shell.connectToApplication(url, services, exposedServices); + return new ApplicationConnection(exposedServices, services); } - void requestService(String url, Object proxy) { - if (overrideRequestService != null) { - if (overrideRequestService(url, proxy)) - return; + void _connectToService(String url, bindings.ProxyBase proxy) { + if (_shell == null || url == null) { + // If we don't have a shell or a url, we try to get the services from the + // embedder directly instead of using the shell to connect. + _embedderConnection.requestService(proxy); + return; } - _requestService(url, proxy); + ServiceProviderProxy services = new ServiceProviderProxy.unbound(); + _shell.connectToApplication(url, services, null); + var pipe = new core.MojoMessagePipe(); + proxy.impl.bind(pipe.endpoints[0]); + services.ptr.connectToService(proxy.name, pipe.endpoints[1]); + services.close(); + } + + void connectToService(String url, Object proxy) { + if (overrideConnectToService != null && overrideConnectToService(url, proxy)) + return; + _connectToService(url, proxy); } } -final _ShellImpl shell = new _ShellImpl._(); +final _Shell shell = new _Shell._(); diff --git a/packages/flutter_sprites/lib/src/sound.dart b/packages/flutter_sprites/lib/src/sound.dart index 60e8e74563..aadf317143 100644 --- a/packages/flutter_sprites/lib/src/sound.dart +++ b/packages/flutter_sprites/lib/src/sound.dart @@ -55,7 +55,7 @@ class SoundEffectPlayer { SoundEffectPlayer() { _mediaService = new MediaServiceProxy.unbound(); - shell.requestService(null, _mediaService); + shell.connectToService(null, _mediaService); } MediaServiceProxy _mediaService; @@ -165,7 +165,7 @@ class SoundTrackPlayer { SoundTrackPlayer() { _mediaService = new MediaServiceProxy.unbound(); - shell.requestService(null, _mediaService); + shell.connectToService(null, _mediaService); } MediaServiceProxy _mediaService; diff --git a/packages/unit/test/services/mock_services.dart b/packages/unit/test/services/mock_services.dart index 06242c5958..69537780ec 100644 --- a/packages/unit/test/services/mock_services.dart +++ b/packages/unit/test/services/mock_services.dart @@ -4,13 +4,13 @@ import 'package:flutter/src/services/shell.dart' as shell; // of Mojo services. class _ServiceMocker { _ServiceMocker() { - shell.overrideRequestService = _requestService; + shell.overrideConnectToService = _connectToService; } // Map of interface names to mock implementations. Map _interfaceMock = new Map(); - bool _requestService(String url, dynamic proxy) { + bool _connectToService(String url, dynamic proxy) { Object mock = _interfaceMock[proxy.impl.name]; if (mock != null) { // Replace the proxy's implementation of the service interface with the diff --git a/packages/updater/lib/main.dart b/packages/updater/lib/main.dart index 9f2e2a740e..d95c5523ab 100644 --- a/packages/updater/lib/main.dart +++ b/packages/updater/lib/main.dart @@ -23,7 +23,7 @@ const String kBundleFile = 'app.flx'; UpdateServiceProxy _initUpdateService() { UpdateServiceProxy updateService = new UpdateServiceProxy.unbound(); - shell.requestService(null, updateService); + shell.connectToService(null, updateService); return updateService; }