Update engine and Mojo usage (#4258)
The new mojom.dart code makes mocking services a bit tricky. I've filed https://github.com/domokit/mojo/issues/786 about improving that.
This commit is contained in:
parent
49affc4098
commit
d1cb026a65
2
bin/cache/engine.version
vendored
2
bin/cache/engine.version
vendored
@ -1 +1 @@
|
||||
cc2cc42f2d3a56c9176f5a2de02b8993a046f88d
|
||||
b6ad88501f8f712c4181811c05d37afcf8d52168
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:sky_services/media/media.mojom.dart';
|
||||
import 'package:sky_services/media/media.mojom.dart' as mojom;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -24,25 +24,25 @@ class PianoKey {
|
||||
final Color color;
|
||||
final String soundUrl;
|
||||
|
||||
final MediaPlayerProxy player = new MediaPlayerProxy.unbound();
|
||||
final mojom.MediaPlayerProxy player = new mojom.MediaPlayerProxy.unbound();
|
||||
|
||||
bool get isPlayerOpen => player.impl.isOpen;
|
||||
bool get isPlayerOpen => player.ctrl.isOpen;
|
||||
|
||||
void down() {
|
||||
if (!isPlayerOpen) return;
|
||||
player.ptr.seekTo(0);
|
||||
player.ptr.start();
|
||||
player.seekTo(0);
|
||||
player.start();
|
||||
}
|
||||
|
||||
void up() {
|
||||
if (!isPlayerOpen) return;
|
||||
player.ptr.pause();
|
||||
player.pause();
|
||||
}
|
||||
|
||||
Future<Null> load(MediaServiceProxy mediaService) async {
|
||||
Future<Null> load(mojom.MediaServiceProxy mediaService) async {
|
||||
try {
|
||||
mediaService.ptr.createPlayer(player);
|
||||
await player.ptr.prepare(await http.readDataPipe(soundUrl));
|
||||
mediaService.createPlayer(player);
|
||||
await player.prepare(await http.readDataPipe(soundUrl));
|
||||
} catch (e) {
|
||||
print("Error: failed to load sound file $soundUrl");
|
||||
player.close();
|
||||
@ -61,9 +61,10 @@ class PianoApp extends StatelessWidget {
|
||||
];
|
||||
|
||||
Future<Null> loadSounds() async {
|
||||
MediaServiceProxy mediaService = new MediaServiceProxy.unbound();
|
||||
mojom.MediaServiceProxy mediaService = shell.connectToApplicationService(
|
||||
'mojo:media_service', mojom.MediaService.connectToService
|
||||
);
|
||||
try {
|
||||
shell.connectToService("mojo:media_service", mediaService);
|
||||
List<Future<Null>> pending = <Future<Null>>[];
|
||||
for (PianoKey key in keys)
|
||||
pending.add(key.load(mediaService));
|
||||
|
@ -135,8 +135,8 @@ class MojoClient {
|
||||
mojom.UrlRequest request = _prepareRequest('GET', url, headers);
|
||||
mojom.UrlResponse response;
|
||||
try {
|
||||
networkService.ptr.createUrlLoader(loader);
|
||||
response = (await loader.ptr.start(request)).response;
|
||||
networkService.createUrlLoader(loader);
|
||||
response = (await loader.start(request)).response;
|
||||
} catch (exception, stack) {
|
||||
FlutterError.reportError(new FlutterErrorDetails(
|
||||
exception: exception,
|
||||
@ -181,8 +181,8 @@ class MojoClient {
|
||||
mojom.UrlLoaderProxy loader = new mojom.UrlLoaderProxy.unbound();
|
||||
mojom.UrlRequest request = _prepareRequest(method, url, headers, body, encoding);
|
||||
try {
|
||||
networkService.ptr.createUrlLoader(loader);
|
||||
mojom.UrlResponse response = (await loader.ptr.start(request)).response;
|
||||
networkService.createUrlLoader(loader);
|
||||
mojom.UrlResponse response = (await loader.start(request)).response;
|
||||
ByteData data = await mojo.DataPipeDrainer.drainHandle(response.body);
|
||||
Uint8List bodyBytes = new Uint8List.view(data.buffer);
|
||||
Map<String, String> headers = <String, String>{};
|
||||
@ -215,9 +215,7 @@ class MojoClient {
|
||||
}
|
||||
|
||||
static mojom.NetworkServiceProxy _initNetworkService() {
|
||||
mojom.NetworkServiceProxy proxy = new mojom.NetworkServiceProxy.unbound();
|
||||
shell.connectToService("mojo:authenticated_network_service", proxy);
|
||||
return proxy;
|
||||
return shell.connectToApplicationService('mojo:authenticated_network_service', mojom.NetworkService.connectToService);
|
||||
}
|
||||
|
||||
/// A handle to the [NetworkService] object used by [MojoClient].
|
||||
|
@ -34,15 +34,15 @@ mojom.ViewProxy _initViewProxy() {
|
||||
// view keys, which means any scheme for sharing the view host also needs to
|
||||
// provide a mechanism for coordinating about view keys.
|
||||
final mojom.ViewProxy _viewProxy = _initViewProxy();
|
||||
final mojom.View _view = _viewProxy?.ptr;
|
||||
final mojom.View _view = _viewProxy;
|
||||
|
||||
mojom.ViewContainer _initViewContainer() {
|
||||
if (_view == null)
|
||||
return null;
|
||||
mojom.ViewContainerProxy viewContainerProxy = new mojom.ViewContainerProxy.unbound();
|
||||
_view.getContainer(viewContainerProxy);
|
||||
viewContainerProxy.ptr.setListener(new mojom.ViewContainerListenerStub.unbound()..impl = _ViewContainerListenerImpl.instance);
|
||||
return viewContainerProxy.ptr;
|
||||
viewContainerProxy.setListener(new mojom.ViewContainerListenerStub.unbound()..impl = _ViewContainerListenerImpl.instance);
|
||||
return viewContainerProxy;
|
||||
}
|
||||
|
||||
final mojom.ViewContainer _viewContainer = _initViewContainer();
|
||||
@ -75,12 +75,13 @@ class _ViewContainerListenerImpl extends mojom.ViewContainerListener {
|
||||
class ChildViewConnection {
|
||||
/// Establishes a connection to the app at the given URL.
|
||||
ChildViewConnection({ String url }) {
|
||||
mojom.ViewProviderProxy viewProvider = new mojom.ViewProviderProxy.unbound();
|
||||
shell.connectToService(url, viewProvider);
|
||||
mojom.ViewProviderProxy viewProvider = shell.connectToApplicationService(
|
||||
url, mojom.ViewProvider.connectToService
|
||||
);
|
||||
mojom.ServiceProviderProxy incomingServices = new mojom.ServiceProviderProxy.unbound();
|
||||
mojom.ServiceProviderStub outgoingServices = new mojom.ServiceProviderStub.unbound();
|
||||
_viewOwner = new mojom.ViewOwnerProxy.unbound();
|
||||
viewProvider.ptr.createView(_viewOwner, incomingServices, outgoingServices);
|
||||
viewProvider.createView(_viewOwner, incomingServices, outgoingServices);
|
||||
viewProvider.close();
|
||||
_connection = new ApplicationConnection(outgoingServices, incomingServices);
|
||||
}
|
||||
|
@ -552,7 +552,7 @@ class SemanticsServer extends mojom.SemanticsServer {
|
||||
void addSemanticsListener(mojom.SemanticsListenerProxy listener) {
|
||||
// TODO(abarth): We should remove the listener when this pipe closes.
|
||||
// See <https://github.com/flutter/flutter/issues/3342>.
|
||||
SemanticsNode.addListener(listener.ptr);
|
||||
SemanticsNode.addListener(listener);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -36,13 +36,11 @@ const int NEW_TASK = 0x10000000; // ignore: constant_identifier_names
|
||||
const int MULTIPLE_TASK = 0x08000000; // ignore: constant_identifier_names
|
||||
|
||||
ActivityProxy _initActivityProxy() {
|
||||
ActivityProxy activity = new ActivityProxy.unbound();
|
||||
shell.connectToService("mojo:android", activity);
|
||||
return activity;
|
||||
return shell.connectToApplicationService('mojo:android', Activity.connectToService);
|
||||
}
|
||||
|
||||
final ActivityProxy _activityProxy = _initActivityProxy();
|
||||
final Activity activity = _activityProxy.ptr;
|
||||
final Activity activity = _activityProxy;
|
||||
|
||||
Color _cachedPrimaryColor;
|
||||
String _cachedLabel;
|
||||
@ -61,5 +59,5 @@ void updateTaskDescription({ String label, Color color }) {
|
||||
..label = label
|
||||
..primaryColor = color?.value ?? 0;
|
||||
|
||||
_activityProxy.ptr.setTaskDescription(description);
|
||||
_activityProxy.setTaskDescription(description);
|
||||
}
|
||||
|
@ -10,9 +10,7 @@ import 'package:sky_services/flutter/platform/app_messages.mojom.dart' as mojom;
|
||||
import 'shell.dart';
|
||||
|
||||
mojom.ApplicationMessagesProxy _initHostAppMessagesProxy() {
|
||||
mojom.ApplicationMessagesProxy proxy = new mojom.ApplicationMessagesProxy.unbound();
|
||||
shell.connectToViewAssociatedService(proxy);
|
||||
return proxy;
|
||||
return shell.connectToViewAssociatedService(mojom.ApplicationMessages.connectToService);
|
||||
}
|
||||
|
||||
final mojom.ApplicationMessagesProxy _hostAppMessagesProxy = _initHostAppMessagesProxy();
|
||||
@ -49,7 +47,7 @@ final _ApplicationMessagesImpl _appMessages = new _ApplicationMessagesImpl();
|
||||
class HostMessages {
|
||||
/// Send a message to the host application.
|
||||
static Future<String> sendToHost(String messageName, String message) async {
|
||||
return (await _hostAppMessagesProxy.ptr.sendString(messageName, message)).reply;
|
||||
return (await _hostAppMessagesProxy.sendString(messageName, message)).reply;
|
||||
}
|
||||
|
||||
/// Register a callback for messages received from the host application.
|
||||
|
@ -8,7 +8,7 @@ import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/http.dart' as http;
|
||||
import 'package:mojo/core.dart' as core;
|
||||
import 'package:mojo_services/mojo/asset_bundle/asset_bundle.mojom.dart';
|
||||
import 'package:mojo_services/mojo/asset_bundle/asset_bundle.mojom.dart' as mojom;
|
||||
|
||||
import 'image_cache.dart';
|
||||
import 'image_decoder.dart';
|
||||
@ -122,29 +122,29 @@ abstract class CachingAssetBundle extends AssetBundle {
|
||||
|
||||
/// An [AssetBundle] that loads resources from a Mojo service.
|
||||
class MojoAssetBundle extends CachingAssetBundle {
|
||||
/// Creates an [AssetBundle] interface around the given [AssetBundleProxy] Mojo service.
|
||||
/// Creates an [AssetBundle] interface around the given [mojom.AssetBundleProxy] Mojo service.
|
||||
MojoAssetBundle(this._bundle);
|
||||
|
||||
/// Retrieves the asset bundle located at the given URL, unpacks it, and provides it contents.
|
||||
factory MojoAssetBundle.fromNetwork(String relativeUrl) {
|
||||
AssetBundleProxy bundle = new AssetBundleProxy.unbound();
|
||||
mojom.AssetBundleProxy bundle = new mojom.AssetBundleProxy.unbound();
|
||||
_fetchAndUnpackBundle(relativeUrl, bundle);
|
||||
return new MojoAssetBundle(bundle);
|
||||
}
|
||||
|
||||
static Future<Null> _fetchAndUnpackBundle(String relativeUrl, AssetBundleProxy bundle) async {
|
||||
static Future<Null> _fetchAndUnpackBundle(String relativeUrl, mojom.AssetBundleProxy bundle) async {
|
||||
core.MojoDataPipeConsumer bundleData = await http.readDataPipe(Uri.base.resolve(relativeUrl));
|
||||
AssetUnpackerProxy unpacker = new AssetUnpackerProxy.unbound();
|
||||
shell.connectToService("mojo:asset_bundle", unpacker);
|
||||
unpacker.ptr.unpackZipStream(bundleData, bundle);
|
||||
mojom.AssetUnpackerProxy unpacker = shell.connectToApplicationService(
|
||||
'mojo:asset_bundle', mojom.AssetUnpacker.connectToService);
|
||||
unpacker.unpackZipStream(bundleData, bundle);
|
||||
unpacker.close();
|
||||
}
|
||||
|
||||
AssetBundleProxy _bundle;
|
||||
mojom.AssetBundleProxy _bundle;
|
||||
|
||||
@override
|
||||
Future<core.MojoDataPipeConsumer> load(String key) async {
|
||||
return (await _bundle.ptr.getAsStream(key)).assetData;
|
||||
return (await _bundle.getAsStream(key)).assetData;
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ AssetBundle _initRootBundle() {
|
||||
if (h == core.MojoHandle.INVALID)
|
||||
return new NetworkAssetBundle(Uri.base);
|
||||
core.MojoHandle handle = new core.MojoHandle(h);
|
||||
return new MojoAssetBundle(new AssetBundleProxy.fromHandle(handle));
|
||||
return new MojoAssetBundle(new mojom.AssetBundleProxy.fromHandle(handle));
|
||||
}
|
||||
|
||||
/// The [AssetBundle] from which this application was loaded.
|
||||
|
@ -11,9 +11,7 @@ import 'shell.dart';
|
||||
export 'package:sky_services/editing/editing.mojom.dart' show ClipboardData;
|
||||
|
||||
mojom.ClipboardProxy _initClipboardProxy() {
|
||||
mojom.ClipboardProxy proxy = new mojom.ClipboardProxy.unbound();
|
||||
shell.connectToService('mojo:clipboard', proxy);
|
||||
return proxy;
|
||||
return shell.connectToApplicationService('mojo:clipboard', mojom.Clipboard.connectToService);
|
||||
}
|
||||
|
||||
final mojom.ClipboardProxy _clipboardProxy = _initClipboardProxy();
|
||||
@ -26,10 +24,10 @@ class Clipboard {
|
||||
Clipboard._();
|
||||
|
||||
static void setClipboardData(mojom.ClipboardData clip) {
|
||||
_clipboardProxy.ptr.setClipboardData(clip);
|
||||
_clipboardProxy.setClipboardData(clip);
|
||||
}
|
||||
|
||||
static Future<mojom.ClipboardData> getClipboardData(String format) async {
|
||||
return (await _clipboardProxy.ptr.getClipboardData(format)).clip;
|
||||
return (await _clipboardProxy.getClipboardData(format)).clip;
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,7 @@ import 'package:sky_services/flutter/platform/haptic_feedback.mojom.dart' as moj
|
||||
import 'shell.dart';
|
||||
|
||||
mojom.HapticFeedbackProxy _initHapticFeedbackProxy() {
|
||||
mojom.HapticFeedbackProxy proxy = new mojom.HapticFeedbackProxy.unbound();
|
||||
shell.connectToService('mojo:flutter_platform', proxy);
|
||||
return proxy;
|
||||
return shell.connectToApplicationService('mojo:flutter_platform', mojom.HapticFeedback.connectToService);
|
||||
}
|
||||
|
||||
final mojom.HapticFeedbackProxy _hapticFeedbackProxy = _initHapticFeedbackProxy();
|
||||
@ -39,6 +37,6 @@ class HapticFeedback {
|
||||
/// feedback if the device does not have a vibrator or one is disabled in
|
||||
/// system settings.
|
||||
static Future<bool> vibrate() async {
|
||||
return (await _hapticFeedbackProxy.ptr.vibrate()).success;
|
||||
return (await _hapticFeedbackProxy.vibrate()).success;
|
||||
}
|
||||
}
|
||||
|
@ -83,10 +83,8 @@ class KeyboardHandle {
|
||||
}
|
||||
|
||||
mojom.KeyboardProxy _initKeyboardProxy() {
|
||||
mojom.KeyboardProxy proxy = new mojom.KeyboardProxy.unbound();
|
||||
shell.connectToViewAssociatedService(proxy);
|
||||
return proxy;
|
||||
return shell.connectToViewAssociatedService(mojom.Keyboard.connectToService);
|
||||
}
|
||||
|
||||
final mojom.KeyboardProxy _keyboardProxy = _initKeyboardProxy();
|
||||
final Keyboard keyboard = new Keyboard(_keyboardProxy.ptr);
|
||||
final Keyboard keyboard = new Keyboard(_keyboardProxy);
|
||||
|
@ -10,9 +10,7 @@ import 'package:sky_services/flutter/platform/path_provider.mojom.dart' as mojom
|
||||
import 'shell.dart';
|
||||
|
||||
mojom.PathProviderProxy _initPathProviderProxy() {
|
||||
mojom.PathProviderProxy proxy = new mojom.PathProviderProxy.unbound();
|
||||
shell.connectToService('mojo:flutter_platform', proxy);
|
||||
return proxy;
|
||||
return shell.connectToApplicationService('mojo:flutter_platform', mojom.PathProvider.connectToService);
|
||||
}
|
||||
|
||||
final mojom.PathProviderProxy _pathProviderProxy = _initPathProviderProxy();
|
||||
@ -32,7 +30,7 @@ class PathProvider {
|
||||
/// * _iOS_: `NSTemporaryDirectory()`
|
||||
/// * _Android_: `getCacheDir()` on the context.
|
||||
static Future<Directory> getTemporaryDirectory() async {
|
||||
return new Directory((await _pathProviderProxy.ptr.temporaryDirectory()).path);
|
||||
return new Directory((await _pathProviderProxy.temporaryDirectory()).path);
|
||||
}
|
||||
|
||||
/// Path to a directory where the application may place files that are private
|
||||
@ -44,6 +42,6 @@ class PathProvider {
|
||||
/// * _iOS_: `NSDocumentsDirectory`
|
||||
/// * _Android_: The AppData directory.
|
||||
static Future<Directory> getApplicationDocumentsDirectory() async {
|
||||
return new Directory((await _pathProviderProxy.ptr.applicationDocumentsDirectory()).path);
|
||||
return new Directory((await _pathProviderProxy.applicationDocumentsDirectory()).path);
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,80 @@ import 'package:mojo/core.dart' as core;
|
||||
import 'package:mojo/mojo/service_provider.mojom.dart' as mojom;
|
||||
import 'package:mojo/mojo/shell.mojom.dart' as mojom;
|
||||
|
||||
/// Signature for replacements 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 OverrideConnectToService(String url, Object proxy);
|
||||
/// Signature for connecting to services. The generated mojom.dart code has
|
||||
/// static functions that match this signature on the interface objects. For
|
||||
/// example, the `mojom.Foo` interface has a `mojom.Foo.connectToService`
|
||||
/// function that matches this signature.
|
||||
typedef bindings.Proxy<dynamic> ServiceConnectionCallback(
|
||||
bindings.ServiceConnector s, String url, [String serviceName]);
|
||||
|
||||
/// Signature for replacements for [shell.connectToApplicationService]. If the
|
||||
/// function returns `null`, then [shell.connectToApplicationService] will fall
|
||||
/// back to its default behavior.
|
||||
typedef bindings.Proxy<dynamic> OverrideConnectToService(String url, ServiceConnectionCallback callback);
|
||||
|
||||
ApplicationConnection _initEmbedderConnection() {
|
||||
core.MojoHandle incomingServicesHandle = new core.MojoHandle(ui.MojoServices.takeIncomingServices());
|
||||
core.MojoHandle outgoingServicesHandle = new core.MojoHandle(ui.MojoServices.takeOutgoingServices());
|
||||
if (!incomingServicesHandle.isValid || !outgoingServicesHandle.isValid)
|
||||
return null;
|
||||
mojom.ServiceProviderProxy incomingServices = new mojom.ServiceProviderProxy.fromHandle(incomingServicesHandle);
|
||||
mojom.ServiceProviderStub outgoingServices = new mojom.ServiceProviderStub.fromHandle(outgoingServicesHandle);
|
||||
return new ApplicationConnection(outgoingServices, incomingServices);
|
||||
}
|
||||
|
||||
mojom.ShellProxy _takeShell() {
|
||||
core.MojoHandle shellHandle = new core.MojoHandle(ui.MojoServices.takeShell());
|
||||
if (!shellHandle.isValid)
|
||||
return null;
|
||||
return new mojom.ShellProxy.fromHandle(shellHandle);
|
||||
}
|
||||
|
||||
mojom.ServiceProviderProxy _takeViewServices() {
|
||||
core.MojoHandle services = new core.MojoHandle(ui.MojoServices.takeViewServices());
|
||||
if (!services.isValid)
|
||||
return null;
|
||||
return new mojom.ServiceProviderProxy.fromHandle(services);
|
||||
}
|
||||
|
||||
class _ShellServiceConnector extends bindings.ServiceConnector {
|
||||
@override
|
||||
void connectToService(String url, bindings.Proxy<dynamic> proxy, [String serviceName]) {
|
||||
final MojoShell instance = MojoShell.instance;
|
||||
if (url == null || instance._shell == null) {
|
||||
// If the application URL is null, it means the service to connect
|
||||
// to is one provided by the embedder.
|
||||
// If the applircation URL isn't null but there's no shell, then
|
||||
// ask the embedder in case it provides it. (For example, if you're
|
||||
// running on Android without the Mojo shell, then you can obtain
|
||||
// the media service from the embedder directly, instead of having
|
||||
// to ask the media application for it.)
|
||||
// This makes it easier to write an application that works both
|
||||
// with and without a Mojo environment.
|
||||
instance._embedderConnection?.requestService(proxy);
|
||||
return;
|
||||
}
|
||||
mojom.ServiceProviderProxy services = new mojom.ServiceProviderProxy.unbound();
|
||||
instance._shell.connectToApplication(url, services, null);
|
||||
core.MojoMessagePipe pipe = new core.MojoMessagePipe();
|
||||
proxy.ctrl.bind(pipe.endpoints[0]);
|
||||
services.connectToService_(serviceName, pipe.endpoints[1]);
|
||||
services.close();
|
||||
}
|
||||
}
|
||||
|
||||
class _ViewAssociatedServiceConnector extends bindings.ServiceConnector {
|
||||
final mojom.ServiceProviderProxy _viewServices = _takeViewServices();
|
||||
|
||||
@override
|
||||
void connectToService(String url, bindings.Proxy<dynamic> proxy, [String serviceName]) {
|
||||
if (_viewServices != null) {
|
||||
core.MojoMessagePipe pipe = new core.MojoMessagePipe();
|
||||
proxy.ctrl.bind(pipe.endpoints[0]);
|
||||
_viewServices.connectToService_(serviceName, pipe.endpoints[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Manages connections with embedder-provided services.
|
||||
class MojoShell {
|
||||
@ -30,24 +100,11 @@ class MojoShell {
|
||||
static MojoShell get instance => _instance;
|
||||
static MojoShell _instance;
|
||||
|
||||
static mojom.ShellProxy _initShellProxy() {
|
||||
core.MojoHandle shellHandle = new core.MojoHandle(ui.MojoServices.takeShell());
|
||||
if (!shellHandle.isValid)
|
||||
return null;
|
||||
return new mojom.ShellProxy.fromHandle(shellHandle);
|
||||
}
|
||||
final mojom.Shell _shell = _initShellProxy()?.ptr;
|
||||
|
||||
static ApplicationConnection _initEmbedderConnection() {
|
||||
core.MojoHandle incomingServicesHandle = new core.MojoHandle(ui.MojoServices.takeIncomingServices());
|
||||
core.MojoHandle outgoingServicesHandle = new core.MojoHandle(ui.MojoServices.takeOutgoingServices());
|
||||
if (!incomingServicesHandle.isValid || !outgoingServicesHandle.isValid)
|
||||
return null;
|
||||
mojom.ServiceProviderProxy incomingServices = new mojom.ServiceProviderProxy.fromHandle(incomingServicesHandle);
|
||||
mojom.ServiceProviderStub outgoingServices = new mojom.ServiceProviderStub.fromHandle(outgoingServicesHandle);
|
||||
return new ApplicationConnection(outgoingServices, incomingServices);
|
||||
}
|
||||
final ApplicationConnection _embedderConnection = _initEmbedderConnection();
|
||||
final mojom.Shell _shell = _takeShell();
|
||||
|
||||
final _ShellServiceConnector _shellServiceConnector = new _ShellServiceConnector();
|
||||
final _ViewAssociatedServiceConnector _viewServiceConnector = new _ViewAssociatedServiceConnector();
|
||||
|
||||
/// Whether [connectToApplication] is able to connect to other applications.
|
||||
bool get canConnectToOtherApplications => _shell != null;
|
||||
@ -83,46 +140,21 @@ class MojoShell {
|
||||
/// and then invoke the method `bar()` on it:
|
||||
///
|
||||
/// ```dart
|
||||
/// mojom.FooProxy foo = new mojom.FooProxy.unbound();
|
||||
/// shell.connectToService("mojo:foo", foo);
|
||||
/// foo.ptr.bar();
|
||||
/// mojom.FooProxy foo = shell.connectToApplicationService(
|
||||
/// "mojo:foo", mojom.Foo.connectToService);
|
||||
/// foo.bar();
|
||||
/// ```
|
||||
///
|
||||
/// For examples of mojom files, see the `sky_services` package.
|
||||
///
|
||||
/// See also [connectToViewAssociatedService].
|
||||
void connectToService(String url, bindings.ProxyBase proxy) {
|
||||
if (overrideConnectToService != null && overrideConnectToService(url, proxy))
|
||||
return;
|
||||
if (url == null || _shell == null) {
|
||||
// If the application URL is null, it means the service to connect
|
||||
// to is one provided by the embedder.
|
||||
// If the applircation URL isn't null but there's no shell, then
|
||||
// ask the embedder in case it provides it. (For example, if you're
|
||||
// running on Android without the Mojo shell, then you can obtain
|
||||
// the media service from the embedder directly, instead of having
|
||||
// to ask the media application for it.)
|
||||
// This makes it easier to write an application that works both
|
||||
// with and without a Mojo environment.
|
||||
_embedderConnection?.requestService(proxy);
|
||||
return;
|
||||
}
|
||||
mojom.ServiceProviderProxy services = new mojom.ServiceProviderProxy.unbound();
|
||||
_shell.connectToApplication(url, services, null);
|
||||
core.MojoMessagePipe pipe = new core.MojoMessagePipe();
|
||||
proxy.impl.bind(pipe.endpoints[0]);
|
||||
services.ptr.connectToService(proxy.serviceName, pipe.endpoints[1]);
|
||||
services.close();
|
||||
bindings.Proxy<dynamic> connectToApplicationService(String url, ServiceConnectionCallback callback) {
|
||||
bindings.Proxy<dynamic> proxy;
|
||||
if (overrideConnectToService != null)
|
||||
proxy = overrideConnectToService(url, callback);
|
||||
return proxy ?? callback(_shellServiceConnector, url);
|
||||
}
|
||||
|
||||
static mojom.ServiceProviderProxy _takeViewServices() {
|
||||
core.MojoHandle services = new core.MojoHandle(ui.MojoServices.takeViewServices());
|
||||
if (!services.isValid)
|
||||
return null;
|
||||
return new mojom.ServiceProviderProxy.fromHandle(services);
|
||||
}
|
||||
final mojom.ServiceProviderProxy _viewServices = _takeViewServices();
|
||||
|
||||
/// Attempts to connect to a service provided specifically for the current
|
||||
/// view by the embedder or host platform.
|
||||
///
|
||||
@ -136,26 +168,23 @@ class MojoShell {
|
||||
/// `bar()` on it:
|
||||
///
|
||||
/// ```dart
|
||||
/// mojom.FooProxy foo = new mojom.FooProxy.unbound();
|
||||
/// shell.connectToViewAssociatedService(foo);
|
||||
/// foo.ptr.bar();
|
||||
/// mojom.FooProxy foo = shell.connectToViewAssociatedService(
|
||||
/// mojom.Foo.connectToService);
|
||||
/// foo.bar();
|
||||
/// ```
|
||||
///
|
||||
/// For examples of mojom files, see the `sky_services` package.
|
||||
///
|
||||
/// See also [connectToService].
|
||||
void connectToViewAssociatedService(bindings.ProxyBase proxy) {
|
||||
if (overrideConnectToService != null && overrideConnectToService(null, proxy))
|
||||
return;
|
||||
if (_viewServices == null)
|
||||
return;
|
||||
core.MojoMessagePipe pipe = new core.MojoMessagePipe();
|
||||
proxy.impl.bind(pipe.endpoints[0]);
|
||||
_viewServices.ptr.connectToService(proxy.serviceName, pipe.endpoints[1]);
|
||||
bindings.Proxy<dynamic> connectToViewAssociatedService(ServiceConnectionCallback callback) {
|
||||
bindings.Proxy<dynamic> proxy;
|
||||
if (overrideConnectToService != null)
|
||||
proxy = overrideConnectToService(null, callback);
|
||||
return proxy ?? callback(_viewServiceConnector, null);
|
||||
}
|
||||
|
||||
/// Registers a service to expose to the embedder.
|
||||
///
|
||||
///
|
||||
/// For example, suppose a Flutter application wanted to provide a service
|
||||
/// `Foo` to the embedder, that a mojom file declaring `Foo` was imported with
|
||||
/// the prefix `mojom`, that `package:mojo/core.dart` was imported with the
|
||||
@ -163,7 +192,7 @@ class MojoShell {
|
||||
/// the class `MyFooImplementation`. The following code, run during the
|
||||
/// binding initialization (i.e. during the same call stack as the call to the
|
||||
/// [new MojoShell] constructor) would achieve this:
|
||||
///
|
||||
///
|
||||
/// ```dart
|
||||
/// shell.provideService(mojom.Foo.serviceName, (core.MojoMessagePipeEndpoint endpoint) {
|
||||
/// mojom.FooStub foo = new mojom.FooStub.fromEndpoint(endpoint);
|
||||
|
@ -12,9 +12,7 @@ import 'shell.dart';
|
||||
export 'package:sky_services/flutter/platform/system_chrome.mojom.dart' show DeviceOrientation;
|
||||
|
||||
mojom.SystemChromeProxy _initSystemChromeProxy() {
|
||||
mojom.SystemChromeProxy proxy = new mojom.SystemChromeProxy.unbound();
|
||||
shell.connectToService('mojo:flutter_platform', proxy);
|
||||
return proxy;
|
||||
return shell.connectToApplicationService('mojo:flutter_platform', mojom.SystemChrome.connectToService);
|
||||
}
|
||||
|
||||
final mojom.SystemChromeProxy _systemChromeProxy = _initSystemChromeProxy();
|
||||
@ -36,7 +34,7 @@ class SystemChrome {
|
||||
/// boolean indicating if the orientation mask is valid and the changes
|
||||
/// could be conveyed successfully to the embedder.
|
||||
static Future<bool> setPreferredOrientations(int deviceOrientationMask) async {
|
||||
return (await _systemChromeProxy.ptr.setPreferredOrientations(deviceOrientationMask)).success;
|
||||
return (await _systemChromeProxy.setPreferredOrientations(deviceOrientationMask)).success;
|
||||
}
|
||||
|
||||
/// Specifies the set of overlays visible on the embedder when the
|
||||
@ -58,6 +56,6 @@ class SystemChrome {
|
||||
/// If the overlay is unsupported on the platform, enabling or disabling
|
||||
/// that overlay is a no-op and always return true.
|
||||
static Future<bool> setEnabledSystemUIOverlays(int overlaysMask) async {
|
||||
return (await _systemChromeProxy.ptr.setEnabledSystemUiOverlays(overlaysMask)).success;
|
||||
return (await _systemChromeProxy.setEnabledSystemUiOverlays(overlaysMask)).success;
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,7 @@ import 'shell.dart';
|
||||
export 'package:sky_services/flutter/platform/system_sound.mojom.dart' show SystemSoundType;
|
||||
|
||||
mojom.SystemSoundProxy _initSystemSoundProxy() {
|
||||
mojom.SystemSoundProxy proxy = new mojom.SystemSoundProxy.unbound();
|
||||
shell.connectToService('mojo:flutter_platform', proxy);
|
||||
return proxy;
|
||||
return shell.connectToApplicationService('mojo:flutter_platform', mojom.SystemSound.connectToService);
|
||||
}
|
||||
|
||||
final mojom.SystemSoundProxy _systemChromeProxy = _initSystemSoundProxy();
|
||||
@ -33,6 +31,6 @@ class SystemSound {
|
||||
/// successfully conveyed to the embedder. No sound may actually play if the
|
||||
/// device is muted or the sound was not available on the platform.
|
||||
static Future<bool> play(SystemSoundType type) async {
|
||||
return (await _systemChromeProxy.ptr.play(type)).success;
|
||||
return (await _systemChromeProxy.play(type)).success;
|
||||
}
|
||||
}
|
||||
|
@ -61,9 +61,8 @@ class _RawKeyboardListenerState extends State<RawKeyboardListener> implements mo
|
||||
if (_stub != null)
|
||||
return;
|
||||
_stub = new mojom.RawKeyboardListenerStub.unbound()..impl = this;
|
||||
mojom.RawKeyboardServiceProxy keyboard = new mojom.RawKeyboardServiceProxy.unbound();
|
||||
shell.connectToViewAssociatedService(keyboard);
|
||||
keyboard.ptr.addListener(_stub);
|
||||
mojom.RawKeyboardServiceProxy keyboard = shell.connectToViewAssociatedService(mojom.RawKeyboardService.connectToService);
|
||||
keyboard.addListener(_stub);
|
||||
keyboard.close();
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,9 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sky_services/editing/editing.mojom.dart' as mojom;
|
||||
|
||||
class MockKeyboard implements mojom.Keyboard {
|
||||
class MockKeyboard extends mojom.KeyboardProxy {
|
||||
MockKeyboard() : super.unbound();
|
||||
|
||||
mojom.KeyboardClient client;
|
||||
|
||||
@override
|
||||
@ -28,7 +30,7 @@ void main() {
|
||||
MockKeyboard mockKeyboard = new MockKeyboard();
|
||||
|
||||
setUpAll(() {
|
||||
serviceMocker.registerMockService(mojom.Keyboard.serviceName, mockKeyboard);
|
||||
serviceMocker.registerMockService(mockKeyboard);
|
||||
});
|
||||
|
||||
void enterText(String testValue) {
|
||||
|
@ -7,7 +7,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:sky_services/editing/editing.mojom.dart' as mojom;
|
||||
|
||||
class MockKeyboard implements mojom.Keyboard {
|
||||
class MockKeyboard extends mojom.KeyboardProxy {
|
||||
MockKeyboard() : super.unbound();
|
||||
|
||||
mojom.KeyboardClient client;
|
||||
|
||||
@override
|
||||
@ -25,7 +27,9 @@ class MockKeyboard implements mojom.Keyboard {
|
||||
void setEditingState(mojom.EditingState state) {}
|
||||
}
|
||||
|
||||
class MockClipboard implements mojom.Clipboard {
|
||||
class MockClipboard extends mojom.ClipboardProxy {
|
||||
MockClipboard() : super.unbound();
|
||||
|
||||
mojom.ClipboardData _clip;
|
||||
|
||||
@override
|
||||
@ -41,9 +45,9 @@ class MockClipboard implements mojom.Clipboard {
|
||||
|
||||
void main() {
|
||||
MockKeyboard mockKeyboard = new MockKeyboard();
|
||||
serviceMocker.registerMockService(mojom.Keyboard.serviceName, mockKeyboard);
|
||||
serviceMocker.registerMockService(mockKeyboard);
|
||||
MockClipboard mockClipboard = new MockClipboard();
|
||||
serviceMocker.registerMockService(mojom.Clipboard.serviceName, mockClipboard);
|
||||
serviceMocker.registerMockService(mockClipboard);
|
||||
|
||||
void enterText(String testValue) {
|
||||
// Simulate entry of text through the keyboard.
|
||||
|
@ -39,7 +39,7 @@ class SoundEffectStream {
|
||||
|
||||
/// Stop the sound effect.
|
||||
void stop() {
|
||||
_soundPool.ptr.stop(_streamId);
|
||||
_soundPool.stop(_streamId);
|
||||
}
|
||||
|
||||
/// True if the sound effect is paused.
|
||||
@ -48,9 +48,9 @@ class SoundEffectStream {
|
||||
set paused(bool value) {
|
||||
_paused = value;
|
||||
if (_paused) {
|
||||
_soundPool.ptr.pause(_streamId);
|
||||
_soundPool.pause(_streamId);
|
||||
} else {
|
||||
_soundPool.ptr.resume(_streamId);
|
||||
_soundPool.resume(_streamId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ class SoundEffectStream {
|
||||
double _leftVolume;
|
||||
set leftVolume(double value) {
|
||||
_leftVolume = value;
|
||||
_soundPool.ptr.setVolume(_streamId, <double>[_leftVolume, _rightVolume]);
|
||||
_soundPool.setVolume(_streamId, <double>[_leftVolume, _rightVolume]);
|
||||
}
|
||||
|
||||
/// Right volume of the sound effect, valid values are 0.0 to 1.0.
|
||||
@ -67,7 +67,7 @@ class SoundEffectStream {
|
||||
double _rightVolume;
|
||||
set rightVolume(double value) {
|
||||
_rightVolume = value;
|
||||
_soundPool.ptr.setVolume(_streamId, <double>[_leftVolume, _rightVolume]);
|
||||
_soundPool.setVolume(_streamId, <double>[_leftVolume, _rightVolume]);
|
||||
}
|
||||
|
||||
/// The pitch of the sound effect, a value of 1.0 plays back the sound effect
|
||||
@ -76,7 +76,7 @@ class SoundEffectStream {
|
||||
double _pitch;
|
||||
set pitch(double value) {
|
||||
_pitch = value;
|
||||
_soundPool.ptr.setRate(_streamId, _pitch);
|
||||
_soundPool.setRate(_streamId, _pitch);
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,10 +86,11 @@ class SoundEffectPlayer {
|
||||
/// Creates a new SoundEffectPlayer with a max number of simultaneous
|
||||
/// streams specified.
|
||||
SoundEffectPlayer(int maxStreams) {
|
||||
MediaServiceProxy mediaService = new MediaServiceProxy.unbound();
|
||||
shell.connectToService("mojo:media_service", mediaService);
|
||||
MediaServiceProxy mediaService = shell.connectToApplicationService(
|
||||
'mojo:media_service', MediaService.connectToService
|
||||
);
|
||||
_soundPool = new SoundPoolProxy.unbound();
|
||||
mediaService.ptr.createSoundPool(_soundPool, maxStreams);
|
||||
mediaService.createSoundPool(_soundPool, maxStreams);
|
||||
}
|
||||
|
||||
SoundPoolProxy _soundPool;
|
||||
@ -98,7 +99,7 @@ class SoundEffectPlayer {
|
||||
|
||||
/// Loads a sound effect.
|
||||
Future<SoundEffect> load(MojoDataPipeConsumer data) async {
|
||||
SoundPoolLoadResponseParams result = await _soundPool.ptr.load(data);
|
||||
SoundPoolLoadResponseParams result = await _soundPool.load(data);
|
||||
if (result.success)
|
||||
return new SoundEffect(result.soundId);
|
||||
|
||||
@ -113,7 +114,7 @@ class SoundEffectPlayer {
|
||||
double pitch: 1.0
|
||||
}) async {
|
||||
int streamId = _nextStreamId++;
|
||||
SoundPoolPlayResponseParams result = await _soundPool.ptr.play(
|
||||
SoundPoolPlayResponseParams result = await _soundPool.play(
|
||||
sound._soundId, streamId, <double>[leftVolume, rightVolume], loop, pitch
|
||||
);
|
||||
|
||||
@ -134,9 +135,9 @@ class SoundEffectPlayer {
|
||||
set paused(bool value) {
|
||||
_paused = value;
|
||||
if (_paused) {
|
||||
_soundPool.ptr.pauseAll();
|
||||
_soundPool.pauseAll();
|
||||
} else {
|
||||
_soundPool.ptr.resumeAll();
|
||||
_soundPool.resumeAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -180,8 +181,9 @@ class SoundTrackPlayer {
|
||||
/// Creates a new [SoundTrackPlayer], typically you will want to use the
|
||||
/// [sharedInstance] method to receive the player.
|
||||
SoundTrackPlayer() {
|
||||
_mediaService = new MediaServiceProxy.unbound();
|
||||
shell.connectToService("mojo:media_service", _mediaService);
|
||||
_mediaService = shell.connectToApplicationService(
|
||||
'mojo:media_service', MediaService.connectToService
|
||||
);
|
||||
}
|
||||
|
||||
MediaServiceProxy _mediaService;
|
||||
@ -199,9 +201,9 @@ class SoundTrackPlayer {
|
||||
// Create media player
|
||||
SoundTrack soundTrack = new SoundTrack();
|
||||
soundTrack._player = new MediaPlayerProxy.unbound();
|
||||
_mediaService.ptr.createPlayer(soundTrack._player);
|
||||
_mediaService.createPlayer(soundTrack._player);
|
||||
|
||||
await soundTrack._player.ptr.prepare(await pipe);
|
||||
await soundTrack._player.prepare(await pipe);
|
||||
return soundTrack;
|
||||
}
|
||||
|
||||
@ -217,28 +219,29 @@ class SoundTrackPlayer {
|
||||
double volume: 1.0,
|
||||
double startTime: 0.0
|
||||
}) {
|
||||
soundTrack._player.ptr.setLooping(loop);
|
||||
soundTrack._player.ptr.setVolume(volume);
|
||||
soundTrack._player.ptr.seekTo((startTime * 1000.0).toInt());
|
||||
soundTrack._player.ptr.start();
|
||||
soundTrack._player
|
||||
..setLooping(loop)
|
||||
..setVolume(volume)
|
||||
..seekTo((startTime * 1000.0).toInt())
|
||||
..start();
|
||||
_soundTracks.add(soundTrack);
|
||||
}
|
||||
|
||||
/// Stops a [SoundTrack]. You may also want to call the [unload] method to
|
||||
/// remove if from memory if you are not planning to play it again.
|
||||
void stop(SoundTrack track) {
|
||||
track._player.ptr.pause();
|
||||
track._player.pause();
|
||||
}
|
||||
|
||||
/// Pauses all [SoundTrack]s that are currently playing.
|
||||
void pauseAll() {
|
||||
for (SoundTrack soundTrack in _soundTracks)
|
||||
soundTrack._player.ptr.pause();
|
||||
soundTrack._player.pause();
|
||||
}
|
||||
|
||||
/// Resumes all [SoundTrack]s that have been loaded by this player.
|
||||
void resumeAll() {
|
||||
for (SoundTrack soundTrack in _soundTracks)
|
||||
soundTrack._player.ptr.start();
|
||||
soundTrack._player.start();
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,15 @@ import 'package:mojo/bindings.dart' as bindings;
|
||||
|
||||
import 'binding.dart';
|
||||
|
||||
class _MockServiceConnector extends bindings.ServiceConnector {
|
||||
String serviceName;
|
||||
|
||||
@override
|
||||
void connectToService(String url, bindings.Proxy<dynamic> proxy, [String serviceName]) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests can use [ServiceMocker] to register replacement implementations
|
||||
/// of Mojo services.
|
||||
class ServiceMocker {
|
||||
@ -16,23 +25,18 @@ class ServiceMocker {
|
||||
}
|
||||
|
||||
// Map of interface names to mock implementations.
|
||||
Map<String, Object> _interfaceMocks = <String, Object>{};
|
||||
Map<String, bindings.Proxy<dynamic>> _interfaceMocks = <String, bindings.Proxy<dynamic>>{};
|
||||
|
||||
bool _connectToService(String url, bindings.ProxyBase proxy) {
|
||||
Object mock = _interfaceMocks[proxy.serviceName];
|
||||
if (mock != null) {
|
||||
// Replace the proxy's implementation of the service interface with the
|
||||
// mock. The mojom bindings put the "ptr" field on all proxies.
|
||||
(proxy as dynamic).ptr = mock;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
bindings.Proxy<dynamic> _connectToService(String url, ServiceConnectionCallback callback) {
|
||||
// TODO(abarth): This is quite awkward. See <https://github.com/domokit/mojo/issues/786>.
|
||||
_MockServiceConnector connector = new _MockServiceConnector();
|
||||
callback(connector, url);
|
||||
return _interfaceMocks[connector.serviceName];
|
||||
}
|
||||
|
||||
/// Provide a mock implementation for a Mojo interface.
|
||||
void registerMockService(String interfaceName, Object mock) {
|
||||
_interfaceMocks[interfaceName] = mock;
|
||||
void registerMockService(bindings.Proxy<dynamic> mock) {
|
||||
_interfaceMocks[mock.ctrl.serviceName] = mock;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user