Skip to content

Commit b30089f

Browse files
DanTupchristopherfujino
authored andcommitted
[flutter_tools] Forward app.webLaunchUrl event from Flutter to DAP clients (flutter#116275)
* [flutter_tools] Forward app.webLaunchUrl event from Flutter to DAP clients Fixes Dart-Code/Dart-Code#4292. * Update packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart Co-authored-by: Christopher Fujino <[email protected]> * Another static const instead of final Co-authored-by: Christopher Fujino <[email protected]>
1 parent 7b2be93 commit b30089f

File tree

3 files changed

+67
-10
lines changed

3 files changed

+67
-10
lines changed

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

+20-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
5151
bool get supportsRestartRequest => true;
5252

5353
/// A list of reverse-requests from `flutter run --machine` that should be forwarded to the client.
54-
final Set<String> _requestsToForwardToClient = <String>{
54+
static const Set<String> _requestsToForwardToClient = <String>{
5555
// The 'app.exposeUrl' request is sent by Flutter to request the client
5656
// exposes a URL to the user and return the public version of that URL.
5757
//
@@ -65,6 +65,14 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
6565
'app.exposeUrl',
6666
};
6767

68+
/// A list of events from `flutter run --machine` that should be forwarded to the client.
69+
static const Set<String> _eventsToForwardToClient = <String>{
70+
// The 'app.webLaunchUrl' event is sent to the client to tell it about a URL
71+
// that should be launched (including a flag for whether it has been
72+
// launched by the tool or needs launching by the editor).
73+
'app.webLaunchUrl',
74+
};
75+
6876
/// Completers for reverse requests from Flutter that may need to be handled by the client.
6977
final Map<Object, Completer<Object?>> _reverseRequestCompleters = <Object, Completer<Object?>>{};
7078

@@ -454,6 +462,17 @@ class FlutterDebugAdapter extends FlutterBaseDebugAdapter {
454462
_handleAppStarted();
455463
break;
456464
}
465+
466+
if (_eventsToForwardToClient.contains(event)) {
467+
// Forward the event to the client.
468+
sendEvent(
469+
RawEventBody(<String, Object?>{
470+
'event': event,
471+
'params': params,
472+
}),
473+
eventType: 'flutter.forwardedEvent',
474+
);
475+
}
457476
}
458477

459478
/// Handles incoming reverse requests from `flutter run --machine`.

packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart

+36-4
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ void main() {
121121
await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
122122
await terminateCompleter.future;
123123

124-
expect(adapter.flutterRequests, contains('app.stop'));
124+
expect(adapter.dapToFlutterRequests, contains('app.stop'));
125125
});
126126

127127
test('does not call "app.stop" on terminateRequest if app was not started', () async {
@@ -145,7 +145,7 @@ void main() {
145145
await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
146146
await terminateCompleter.future;
147147

148-
expect(adapter.flutterRequests, isNot(contains('app.stop')));
148+
expect(adapter.dapToFlutterRequests, isNot(contains('app.stop')));
149149
});
150150
});
151151

@@ -210,7 +210,39 @@ void main() {
210210
await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
211211
await terminateCompleter.future;
212212

213-
expect(adapter.flutterRequests, contains('app.detach'));
213+
expect(adapter.dapToFlutterRequests, contains('app.detach'));
214+
});
215+
});
216+
217+
group('forwards events', () {
218+
test('app.webLaunchUrl', () async {
219+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
220+
fileSystem: MemoryFileSystem.test(style: fsStyle),
221+
platform: platform,
222+
);
223+
224+
// Simulate Flutter asking for a URL to be launched.
225+
adapter.simulateStdoutMessage(<String, Object?>{
226+
'event': 'app.webLaunchUrl',
227+
'params': <String, Object?>{
228+
'url': 'http://localhost:123/',
229+
'launched': false,
230+
}
231+
});
232+
233+
// Allow the handler to be processed.
234+
await pumpEventQueue(times: 5000);
235+
236+
// Find the forwarded event.
237+
final Map<String, Object?> message = adapter.dapToClientMessages.singleWhere((Map<String, Object?> data) => data['event'] == 'flutter.forwardedEvent');
238+
// Ensure the body of the event matches the original event sent by Flutter.
239+
expect(message['body'], <String, Object?>{
240+
'event': 'app.webLaunchUrl',
241+
'params': <String, Object?>{
242+
'url': 'http://localhost:123/',
243+
'launched': false,
244+
}
245+
});
214246
});
215247
});
216248

@@ -238,7 +270,7 @@ void main() {
238270
// Allow the handler to be processed.
239271
await pumpEventQueue(times: 5000);
240272

241-
final Map<String, Object?> message = adapter.flutterMessages.singleWhere((Map<String, Object?> data) => data['id'] == requestId);
273+
final Map<String, Object?> message = adapter.dapToFlutterMessages.singleWhere((Map<String, Object?> data) => data['id'] == requestId);
242274
expect(message['result'], 'http://mapped-host:123/');
243275
});
244276
});

packages/flutter_tools/test/general.shard/dap/mocks.dart

+11-5
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,15 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter {
5353
late List<String> processArgs;
5454
late Map<String, String>? env;
5555

56-
/// A list of all messages sent to the `flutter run` processes `stdin`.
57-
final List<Map<String, Object?>> flutterMessages = <Map<String, Object?>>[];
56+
/// A list of all messages sent from the adapter back to the client.
57+
final List<Map<String, Object?>> dapToClientMessages = <Map<String, Object?>>[];
5858

59-
/// The `method`s of all requests send to the `flutter run` processes `stdin`.
60-
List<String> get flutterRequests => flutterMessages
59+
/// A list of all messages sent from the adapter to the `flutter run` processes `stdin`.
60+
final List<Map<String, Object?>> dapToFlutterMessages = <Map<String, Object?>>[];
61+
62+
/// The `method`s of all mesages sent to the `flutter run` processes `stdin`
63+
/// by the debug adapter.
64+
List<String> get dapToFlutterRequests => dapToFlutterMessages
6165
.map((Map<String, Object?> message) => message['method'] as String?)
6266
.whereNotNull()
6367
.toList();
@@ -92,6 +96,8 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter {
9296

9397
/// Handles messages sent from the debug adapter back to the client.
9498
void _handleDapToClientMessage(ProtocolMessage message) {
99+
dapToClientMessages.add(message.toJson());
100+
95101
// Pretend to be the client, delegating any reverse-requests to the relevant
96102
// handler that is provided by the test.
97103
if (message is Event && message.event == 'flutter.forwardedRequest') {
@@ -133,7 +139,7 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter {
133139

134140
@override
135141
void sendFlutterMessage(Map<String, Object?> message) {
136-
flutterMessages.add(message);
142+
dapToFlutterMessages.add(message);
137143
// Don't call super because it will try to write to the process that we
138144
// didn't actually spawn.
139145
}

0 commit comments

Comments
 (0)