Commit a8f6f44a authored by Adam Barth's avatar Adam Barth Committed by GitHub

Update engine to include new version of Mojo (#4668)

This required switching from the Future-based bindings to the callback-based
bindings.
parent f307735e
e0ae976409ccbf25e8e26d66c4575d081fc2abdf
f91f5ad62f7a61de787e3e6397f0b63e9eab534e
......@@ -42,7 +42,7 @@ class PianoKey {
Future<Null> load(mojom.MediaServiceProxy mediaService) async {
try {
mediaService.createPlayer(player);
await player.prepare(await http.readDataPipe(soundUrl));
player.prepare(await http.readDataPipe(soundUrl), (bool ignored) { });
} catch (e) {
print("Error: failed to load sound file $soundUrl");
player.close();
......
......@@ -130,28 +130,26 @@ class MojoClient {
///
/// The Future will emit a [ClientException] if the response doesn't have a
/// success status code.
Future<mojo.MojoDataPipeConsumer> readDataPipe(dynamic url, { Map<String, String> headers }) async {
Future<mojo.MojoDataPipeConsumer> readDataPipe(dynamic url, { Map<String, String> headers }) {
Completer<mojo.MojoDataPipeConsumer> completer = new Completer<mojo.MojoDataPipeConsumer>();
mojom.UrlLoaderProxy loader = new mojom.UrlLoaderProxy.unbound();
mojom.UrlRequest request = _prepareRequest('GET', url, headers);
mojom.UrlResponse response;
try {
networkService.createUrlLoader(loader);
response = (await loader.start(request)).response;
} catch (exception, stack) {
FlutterError.reportError(new FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'networking HTTP library',
context: 'while sending bytes to the Mojo network library',
silent: true
));
return null;
} finally {
networkService.createUrlLoader(loader);
loader.start(_prepareRequest('GET', url, headers), (mojom.UrlResponse response) {
loader.close();
}
if (response.statusCode < 400)
return response.body;
throw new Exception("Request to $url failed with status ${response.statusCode}.");
if (response.statusCode < 400) {
completer.complete(response.body);
} else {
Exception exception = new Exception("Request to $url failed with status ${response.statusCode}.");
FlutterError.reportError(new FlutterErrorDetails(
exception: exception,
library: 'networking HTTP library',
context: 'while sending bytes to the Mojo network library',
silent: true
));
completer.completeError(exception);
}
});
return completer.future;
}
mojom.UrlRequest _prepareRequest(String method, dynamic url, Map<String, String> headers, [dynamic body, Encoding encoding = UTF8]) {
......@@ -177,35 +175,37 @@ class MojoClient {
return request;
}
Future<Response> _send(String method, dynamic url, Map<String, String> headers, [dynamic body, Encoding encoding = UTF8]) async {
Future<Response> _send(String method, dynamic url, Map<String, String> headers, [dynamic body, Encoding encoding = UTF8]) {
Completer<Response> completer = new Completer<Response>();
mojom.UrlLoaderProxy loader = new mojom.UrlLoaderProxy.unbound();
networkService.createUrlLoader(loader);
mojom.UrlRequest request = _prepareRequest(method, url, headers, body, encoding);
try {
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>{};
if (response.headers != null) {
for (mojom.HttpHeader header in response.headers) {
String headerName = header.name.toLowerCase();
String existingValue = headers[headerName];
headers[headerName] = existingValue != null ? '$existingValue, ${header.value}' : header.value;
loader.start(request, (mojom.UrlResponse response) async {
loader.close();
try {
ByteData data = await mojo.DataPipeDrainer.drainHandle(response.body);
Uint8List bodyBytes = new Uint8List.view(data.buffer);
Map<String, String> headers = <String, String>{};
if (response.headers != null) {
for (mojom.HttpHeader header in response.headers) {
String headerName = header.name.toLowerCase();
String existingValue = headers[headerName];
headers[headerName] = existingValue != null ? '$existingValue, ${header.value}' : header.value;
}
}
completer.complete(new Response.bytes(bodyBytes, response.statusCode, headers: headers));
} catch (exception, stack) {
FlutterError.reportError(new FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'networking HTTP library',
context: 'while sending bytes to the Mojo network library',
silent: true
));
completer.complete(new Response.bytes(null, 500));
}
return new Response.bytes(bodyBytes, response.statusCode, headers: headers);
} catch (exception, stack) {
FlutterError.reportError(new FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'networking HTTP library',
context: 'while sending bytes to the Mojo network library',
silent: true
));
return new Response.bytes(null, 500);
} finally {
loader.close();
}
});
return completer.future;
}
void _checkResponseSuccess(dynamic url, Response response) {
......
......@@ -79,11 +79,10 @@ class ChildViewConnection {
url, mojom.ViewProvider.connectToService
);
mojom.ServiceProviderProxy incomingServices = new mojom.ServiceProviderProxy.unbound();
mojom.ServiceProviderStub outgoingServices = new mojom.ServiceProviderStub.unbound();
_viewOwner = new mojom.ViewOwnerProxy.unbound();
viewProvider.createView(_viewOwner, incomingServices, outgoingServices);
viewProvider.createView(_viewOwner, incomingServices);
viewProvider.close();
_connection = new ApplicationConnection(outgoingServices, incomingServices);
_connection = new ApplicationConnection(null, incomingServices);
}
/// Wraps an already-established connection to a child app.
......
......@@ -180,8 +180,12 @@ class MojoAssetBundle extends CachingAssetBundle {
mojom.AssetBundleProxy _bundle;
@override
Future<core.MojoDataPipeConsumer> load(String key) async {
return (await _bundle.getAsStream(key)).assetData;
Future<core.MojoDataPipeConsumer> load(String key) {
Completer<core.MojoDataPipeConsumer> completer = new Completer<core.MojoDataPipeConsumer>();
_bundle.getAsStream(key, (core.MojoDataPipeConsumer assetData) {
completer.complete(assetData);
});
return completer.future;
}
}
......
......@@ -31,7 +31,11 @@ class Clipboard {
/// Retrieves data from the clipboard that matches the given format.
///
/// * `format` is a media type, such as `text/plain`.
static Future<mojom.ClipboardData> getClipboardData(String format) async {
return (await _clipboardProxy.getClipboardData(format)).clip;
static Future<mojom.ClipboardData> getClipboardData(String format) {
Completer<mojom.ClipboardData> completer = new Completer<mojom.ClipboardData>();
_clipboardProxy.getClipboardData(format, (mojom.ClipboardData clip) {
completer.complete(clip);
});
return completer.future;
}
}
......@@ -36,7 +36,11 @@ class HapticFeedback {
/// was successfully conveyed to the embedder. There may not be any actual
/// feedback if the device does not have a vibrator or one is disabled in
/// system settings.
static Future<bool> vibrate() async {
return (await _hapticFeedbackProxy.vibrate()).success;
static Future<bool> vibrate() {
Completer<bool> completer = new Completer<bool>();
_hapticFeedbackProxy.vibrate((bool result) {
completer.complete(result);
});
return completer.future;
}
}
......@@ -49,13 +49,21 @@ final _ApplicationMessagesImpl _appMessages = new _ApplicationMessagesImpl();
/// Flutter framework to exchange application-specific messages.
class HostMessages {
/// Send a message to the host application.
static Future<String> sendToHost(String messageName, [String message = '']) async {
return (await _hostAppMessagesProxy.sendString(messageName, message)).reply;
static Future<String> sendToHost(String messageName, [String message = '']) {
Completer<String> completer = new Completer<String>();
_hostAppMessagesProxy.sendString(messageName, message, (String reply) {
completer.complete(reply);
});
return completer.future;
}
/// Sends a JSON-encoded message to the host application and JSON-decodes the response.
static Future<dynamic> sendJSON(String messageName, [dynamic json]) async {
return JSON.decode((await _hostAppMessagesProxy.sendString(messageName, JSON.encode(json))).reply);
Completer<dynamic> completer = new Completer<dynamic>();
_hostAppMessagesProxy.sendString(messageName, JSON.encode(json), (String reply) {
completer.complete(JSON.decode(reply));
});
return completer.future;
}
/// Register a callback for receiving messages from the host application.
......
......@@ -29,8 +29,12 @@ class PathProvider {
///
/// * _iOS_: `NSTemporaryDirectory()`
/// * _Android_: `getCacheDir()` on the context.
static Future<Directory> getTemporaryDirectory() async {
return new Directory((await _pathProviderProxy.temporaryDirectory()).path);
static Future<Directory> getTemporaryDirectory() {
Completer<Directory> completer = new Completer<Directory>();
_pathProviderProxy.temporaryDirectory((String path) {
completer.complete(new Directory(path));
});
return completer.future;
}
/// Path to a directory where the application may place files that are private
......@@ -41,7 +45,11 @@ class PathProvider {
///
/// * _iOS_: `NSDocumentsDirectory`
/// * _Android_: The AppData directory.
static Future<Directory> getApplicationDocumentsDirectory() async {
return new Directory((await _pathProviderProxy.applicationDocumentsDirectory()).path);
static Future<Directory> getApplicationDocumentsDirectory() {
Completer<Directory> completer = new Completer<Directory>();
_pathProviderProxy.applicationDocumentsDirectory((String path) {
completer.complete(new Directory(path));
});
return completer.future;
}
}
......@@ -64,7 +64,7 @@ class _ShellServiceConnector extends bindings.ServiceConnector {
return;
}
mojom.ServiceProviderProxy services = new mojom.ServiceProviderProxy.unbound();
instance._shell.connectToApplication(url, services, null);
instance._shell.connectToApplication(url, services);
core.MojoMessagePipe pipe = new core.MojoMessagePipe();
proxy.ctrl.bind(pipe.endpoints[0]);
services.connectToService_(serviceName, pipe.endpoints[1]);
......@@ -116,9 +116,8 @@ class MojoShell {
if (_shell == null)
return null;
mojom.ServiceProviderProxy services = new mojom.ServiceProviderProxy.unbound();
mojom.ServiceProviderStub exposedServices = new mojom.ServiceProviderStub.unbound();
_shell.connectToApplication(url, services, exposedServices);
return new ApplicationConnection(exposedServices, services);
_shell.connectToApplication(url, services);
return new ApplicationConnection(null, services);
}
/// Interceptor for calls to [connectToService] and
......
......@@ -33,8 +33,12 @@ 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.setPreferredOrientations(deviceOrientationMask)).success;
static Future<bool> setPreferredOrientations(int deviceOrientationMask) {
Completer<bool> completer = new Completer<bool>();
_systemChromeProxy.setPreferredOrientations(deviceOrientationMask, (bool success) {
completer.complete(success);
});
return completer.future;
}
/// Specifies the description of the current state of the application as it
......@@ -53,32 +57,12 @@ class SystemChrome {
///
/// If application-specified metadata is unsupported on the platform,
/// specifying it is a no-op and always return true.
static Future<bool> setApplicationSwitcherDescription(mojom.ApplicationSwitcherDescription description) async {
return (await _systemChromeProxy.setApplicationSwitcherDescription(
description)).success;
}
/// Specifies the set of overlays visible on the embedder when the
/// application is running. The embedder may choose to ignore unsupported
/// overlays
///
/// Arguments:
///
/// * [overlaysMask]: A mask of [SystemUIOverlay] enum values that denotes
/// the overlays to show.
///
/// Return Value:
///
/// boolean indicating if the preference was conveyed successfully to the
/// embedder.
///
/// Platform Specific Notes:
///
/// 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.setEnabledSystemUiOverlays(
overlaysMask)).success;
static Future<bool> setApplicationSwitcherDescription(mojom.ApplicationSwitcherDescription description) {
Completer<bool> completer = new Completer<bool>();
_systemChromeProxy.setApplicationSwitcherDescription(description, (bool success) {
completer.complete(success);
});
return completer.future;
}
/// Specifies the style of the system overlays that are visible on the
......@@ -106,7 +90,9 @@ class SystemChrome {
scheduleMicrotask(() {
assert(_pendingStyle != null);
if (_pendingStyle != _latestStyle) {
_systemChromeProxy.setSystemUiOverlayStyle(_pendingStyle);
_systemChromeProxy.setSystemUiOverlayStyle(_pendingStyle, (bool success) {
// Ignored.
});
_latestStyle = _pendingStyle;
}
_pendingStyle = null;
......
......@@ -30,7 +30,11 @@ class SystemSound {
/// boolean indicating if the intent to play the specified sound was
/// 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.play(type)).success;
static Future<bool> play(SystemSoundType type) {
Completer<bool> completer = new Completer<bool>();
_systemChromeProxy.play(type, (bool success) {
completer.complete(success);
});
return completer.future;
}
}
......@@ -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 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
......@@ -38,8 +40,10 @@ class MockClipboard extends mojom.ClipboardProxy {
}
@override
dynamic getClipboardData(String format,[Function responseFactory = null]) {
return new mojom.ClipboardGetClipboardDataResponseParams()..clip = _clip;
void getClipboardData(String format, void callback(mojom.ClipboardData clip)) {
scheduleMicrotask(() {
callback(_clip);
});
}
}
......
......@@ -98,12 +98,15 @@ class SoundEffectPlayer {
int _nextStreamId = 0;
/// Loads a sound effect.
Future<SoundEffect> load(MojoDataPipeConsumer data) async {
SoundPoolLoadResponseParams result = await _soundPool.load(data);
if (result.success)
return new SoundEffect(result.soundId);
throw new Exception('Unable to load sound');
Future<SoundEffect> load(MojoDataPipeConsumer data) {
Completer<SoundEffect> completer = new Completer<SoundEffect>();
_soundPool.load(data, (bool success, int soundId) {
if (success)
completer.complete(new SoundEffect(soundId));
else
completer.completeError(new Exception('Unable to load sound'));
});
return completer.future;
}
/// Plays a sound effect.
......@@ -112,21 +115,26 @@ class SoundEffectPlayer {
double rightVolume: 1.0,
bool loop: false,
double pitch: 1.0
}) async {
}) {
Completer<SoundEffectStream> completer = new Completer<SoundEffectStream>();
int streamId = _nextStreamId++;
SoundPoolPlayResponseParams result = await _soundPool.play(
sound._soundId, streamId, <double>[leftVolume, rightVolume], loop, pitch
);
if (result.success) {
return new SoundEffectStream(this, streamId,
leftVolume: leftVolume,
rightVolume: rightVolume,
pitch: pitch
);
}
throw new Exception('Unable to play sound');
_soundPool.play(sound._soundId,
streamId,
<double>[leftVolume, rightVolume],
loop,
pitch,
(bool success) {
if (success) {
completer.complete(new SoundEffectStream(this, streamId,
leftVolume: leftVolume,
rightVolume: rightVolume,
pitch: pitch
));
} else {
completer.completeError(new Exception('Unable to play sound'));
}
});
return completer.future;
}
/// Set to true to pause a sound effect.
......@@ -203,8 +211,11 @@ class SoundTrackPlayer {
soundTrack._player = new MediaPlayerProxy.unbound();
_mediaService.createPlayer(soundTrack._player);
await soundTrack._player.prepare(await pipe);
return soundTrack;
Completer<SoundTrack> completer = new Completer<SoundTrack>();
soundTrack._player.prepare(await pipe, (bool ignored) {
completer.complete(soundTrack);
});
return await completer.future;
}
/// Unloads a [SoundTrack] from memory.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment