[flutter_tools] Forward app.webLaunchUrl event from Flutter to DAP clients (#116275)

* [flutter_tools] Forward app.webLaunchUrl event from Flutter to DAP clients

Fixes https://github.com/Dart-Code/Dart-Code/issues/4292.

* Update packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart

Co-authored-by: Christopher Fujino <fujino@google.com>

* Another static const instead of final

Co-authored-by: Christopher Fujino <fujino@google.com>
This commit is contained in:
Danny Tuppeny 2022-11-30 21:25:07 +00:00 committed by GitHub
parent fcc8ea1177
commit a29796e339
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 10 deletions

View file

@ -51,7 +51,7 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
bool get supportsRestartRequest => true;
/// A list of reverse-requests from `flutter run --machine` that should be forwarded to the client.
final Set<String> _requestsToForwardToClient = <String>{
static const Set<String> _requestsToForwardToClient = <String>{
// The 'app.exposeUrl' request is sent by Flutter to request the client
// exposes a URL to the user and return the public version of that URL.
//
@ -65,6 +65,14 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
'app.exposeUrl',
};
/// A list of events from `flutter run --machine` that should be forwarded to the client.
static const Set<String> _eventsToForwardToClient = <String>{
// The 'app.webLaunchUrl' event is sent to the client to tell it about a URL
// that should be launched (including a flag for whether it has been
// launched by the tool or needs launching by the editor).
'app.webLaunchUrl',
};
/// Completers for reverse requests from Flutter that may need to be handled by the client.
final Map<Object, Completer<Object?>> _reverseRequestCompleters = <Object, Completer<Object?>>{};
@ -454,6 +462,17 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
_handleAppStarted();
break;
}
if (_eventsToForwardToClient.contains(event)) {
// Forward the event to the client.
sendEvent(
RawEventBody(<String, Object?>{
'event': event,
'params': params,
}),
eventType: 'flutter.forwardedEvent',
);
}
}
/// Handles incoming reverse requests from `flutter run --machine`.

View file

@ -121,7 +121,7 @@ void main() {
await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
await terminateCompleter.future;
expect(adapter.flutterRequests, contains('app.stop'));
expect(adapter.dapToFlutterRequests, contains('app.stop'));
});
test('does not call "app.stop" on terminateRequest if app was not started', () async {
@ -145,7 +145,7 @@ void main() {
await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
await terminateCompleter.future;
expect(adapter.flutterRequests, isNot(contains('app.stop')));
expect(adapter.dapToFlutterRequests, isNot(contains('app.stop')));
});
});
@ -210,7 +210,39 @@ void main() {
await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
await terminateCompleter.future;
expect(adapter.flutterRequests, contains('app.detach'));
expect(adapter.dapToFlutterRequests, contains('app.detach'));
});
});
group('forwards events', () {
test('app.webLaunchUrl', () async {
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
fileSystem: MemoryFileSystem.test(style: fsStyle),
platform: platform,
);
// Simulate Flutter asking for a URL to be launched.
adapter.simulateStdoutMessage(<String, Object?>{
'event': 'app.webLaunchUrl',
'params': <String, Object?>{
'url': 'http://localhost:123/',
'launched': false,
}
});
// Allow the handler to be processed.
await pumpEventQueue(times: 5000);
// Find the forwarded event.
final Map<String, Object?> message = adapter.dapToClientMessages.singleWhere((Map<String, Object?> data) => data['event'] == 'flutter.forwardedEvent');
// Ensure the body of the event matches the original event sent by Flutter.
expect(message['body'], <String, Object?>{
'event': 'app.webLaunchUrl',
'params': <String, Object?>{
'url': 'http://localhost:123/',
'launched': false,
}
});
});
});
@ -238,7 +270,7 @@ void main() {
// Allow the handler to be processed.
await pumpEventQueue(times: 5000);
final Map<String, Object?> message = adapter.flutterMessages.singleWhere((Map<String, Object?> data) => data['id'] == requestId);
final Map<String, Object?> message = adapter.dapToFlutterMessages.singleWhere((Map<String, Object?> data) => data['id'] == requestId);
expect(message['result'], 'http://mapped-host:123/');
});
});

View file

@ -53,11 +53,15 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter {
late List<String> processArgs;
late Map<String, String>? env;
/// A list of all messages sent to the `flutter run` processes `stdin`.
final List<Map<String, Object?>> flutterMessages = <Map<String, Object?>>[];
/// A list of all messages sent from the adapter back to the client.
final List<Map<String, Object?>> dapToClientMessages = <Map<String, Object?>>[];
/// The `method`s of all requests send to the `flutter run` processes `stdin`.
List<String> get flutterRequests => flutterMessages
/// A list of all messages sent from the adapter to the `flutter run` processes `stdin`.
final List<Map<String, Object?>> dapToFlutterMessages = <Map<String, Object?>>[];
/// The `method`s of all mesages sent to the `flutter run` processes `stdin`
/// by the debug adapter.
List<String> get dapToFlutterRequests => dapToFlutterMessages
.map((Map<String, Object?> message) => message['method'] as String?)
.whereNotNull()
.toList();
@ -92,6 +96,8 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter {
/// Handles messages sent from the debug adapter back to the client.
void _handleDapToClientMessage(ProtocolMessage message) {
dapToClientMessages.add(message.toJson());
// Pretend to be the client, delegating any reverse-requests to the relevant
// handler that is provided by the test.
if (message is Event && message.event == 'flutter.forwardedRequest') {
@ -133,7 +139,7 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter {
@override
void sendFlutterMessage(Map<String, Object?> message) {
flutterMessages.add(message);
dapToFlutterMessages.add(message);
// Don't call super because it will try to write to the process that we
// didn't actually spawn.
}