Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ad79d23

Browse files
authored
Refactor platform message logic (#22181)
1 parent 2c975c0 commit ad79d23

File tree

14 files changed

+1421
-404
lines changed

14 files changed

+1421
-404
lines changed

lib/ui/channel_buffers.dart

Lines changed: 473 additions & 144 deletions
Large diffs are not rendered by default.

lib/ui/hooks.dart

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ void _invoke(void Function()? callback, Zone zone) {
159159
}
160160

161161
/// Invokes [callback] inside the given [zone] passing it [arg].
162+
///
163+
/// The 1 in the name refers to the number of arguments expected by
164+
/// the callback (and thus passed to this function, in addition to the
165+
/// callback itself and the zone in which the callback is executed).
162166
void _invoke1<A>(void Function(A a)? callback, Zone zone, A arg) {
163167
if (callback == null) {
164168
return;
@@ -173,14 +177,33 @@ void _invoke1<A>(void Function(A a)? callback, Zone zone, A arg) {
173177
}
174178
}
175179

180+
/// Invokes [callback] inside the given [zone] passing it [arg1] and [arg2].
181+
///
182+
/// The 2 in the name refers to the number of arguments expected by
183+
/// the callback (and thus passed to this function, in addition to the
184+
/// callback itself and the zone in which the callback is executed).
185+
void _invoke2<A1, A2>(void Function(A1 a1, A2 a2)? callback, Zone zone, A1 arg1, A2 arg2) {
186+
if (callback == null) {
187+
return;
188+
}
189+
190+
assert(zone != null); // ignore: unnecessary_null_comparison
191+
192+
if (identical(zone, Zone.current)) {
193+
callback(arg1, arg2);
194+
} else {
195+
zone.runGuarded(() {
196+
callback(arg1, arg2);
197+
});
198+
}
199+
}
200+
176201
/// Invokes [callback] inside the given [zone] passing it [arg1], [arg2], and [arg3].
177-
void _invoke3<A1, A2, A3>(
178-
void Function(A1 a1, A2 a2, A3 a3)? callback,
179-
Zone zone,
180-
A1 arg1,
181-
A2 arg2,
182-
A3 arg3,
183-
) {
202+
///
203+
/// The 3 in the name refers to the number of arguments expected by
204+
/// the callback (and thus passed to this function, in addition to the
205+
/// callback itself and the zone in which the callback is executed).
206+
void _invoke3<A1, A2, A3>(void Function(A1 a1, A2 a2, A3 a3)? callback, Zone zone, A1 arg1, A2 arg2, A3 arg3) {
184207
if (callback == null) {
185208
return;
186209
}

lib/ui/platform_dispatcher.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ typedef SemanticsActionCallback = void Function(int id, SemanticsAction action,
3838
typedef PlatformMessageResponseCallback = void Function(ByteData? data);
3939

4040
/// Signature for [PlatformDispatcher.onPlatformMessage].
41+
// TODO(ianh): deprecate once framework uses [ChannelBuffers.setListener].
4142
typedef PlatformMessageCallback = void Function(String name, ByteData? data, PlatformMessageResponseCallback? callback);
4243

4344
// Signature for _setNeedsReportTimings.
@@ -409,6 +410,8 @@ class PlatformDispatcher {
409410
///
410411
/// The framework invokes this callback in the same zone in which the callback
411412
/// was set.
413+
// TODO(ianh): Deprecate onPlatformMessage once the framework is moved over
414+
// to using channel buffers exclusively.
412415
PlatformMessageCallback? get onPlatformMessage => _onPlatformMessage;
413416
PlatformMessageCallback? _onPlatformMessage;
414417
Zone _onPlatformMessageZone = Zone.root;
@@ -438,13 +441,15 @@ class PlatformDispatcher {
438441
};
439442
}
440443

441-
// Called from the engine, via hooks.dart
444+
/// Send a message to the framework using the [ChannelBuffers].
445+
///
446+
/// This method constructs the appropriate callback to respond
447+
/// with the given `responseId`. It should only be called for messages
448+
/// from the platform.
442449
void _dispatchPlatformMessage(String name, ByteData? data, int responseId) {
443450
if (name == ChannelBuffers.kControlChannelName) {
444451
try {
445452
channelBuffers.handleMessage(data!);
446-
} catch (ex) {
447-
_printDebug('Message to "$name" caused exception $ex');
448453
} finally {
449454
_respondToPlatformMessage(responseId, null);
450455
}
@@ -454,7 +459,7 @@ class PlatformDispatcher {
454459
_onPlatformMessageZone,
455460
name,
456461
data,
457-
(ByteData? responseData) {
462+
(ByteData? responseData) {
458463
_respondToPlatformMessage(responseId, responseData);
459464
},
460465
);

lib/ui/text.dart

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,11 +2273,18 @@ final ByteData _fontChangeMessage = utf8.encoder.convert(
22732273
).buffer.asByteData();
22742274

22752275
FutureOr<void> _sendFontChangeMessage() async {
2276-
PlatformDispatcher.instance.onPlatformMessage?.call(
2277-
'flutter/system',
2278-
_fontChangeMessage,
2279-
(_) {},
2280-
);
2276+
const String kSystemChannelName = 'flutter/system';
2277+
if (PlatformDispatcher.instance.onPlatformMessage != null) {
2278+
_invoke3<String, ByteData?, PlatformMessageResponseCallback>(
2279+
PlatformDispatcher.instance.onPlatformMessage,
2280+
PlatformDispatcher.instance._onPlatformMessageZone,
2281+
kSystemChannelName,
2282+
_fontChangeMessage,
2283+
(ByteData? responseData) { },
2284+
);
2285+
} else {
2286+
channelBuffers.push(kSystemChannelName, _fontChangeMessage, (ByteData? responseData) { });
2287+
}
22812288
}
22822289

22832290
// TODO(gspencergoog): remove this template block once the framework templates

lib/ui/window.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ class SingletonFlutterWindow extends FlutterWindow {
696696
///
697697
/// The framework invokes this callback in the same zone in which the
698698
/// callback was set.
699+
// TODO(ianh): deprecate once framework uses [ChannelBuffers.setListener].
699700
PlatformMessageCallback? get onPlatformMessage => platformDispatcher.onPlatformMessage;
700701
set onPlatformMessage(PlatformMessageCallback? callback) {
701702
platformDispatcher.onPlatformMessage = callback;

lib/web_ui/lib/src/engine/keyboard.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,6 @@ class Keyboard {
8181

8282
final html.KeyboardEvent keyboardEvent = event;
8383

84-
if (EnginePlatformDispatcher.instance._onPlatformMessage == null) {
85-
return;
86-
}
87-
8884
if (_shouldPreventDefault(event)) {
8985
event.preventDefault();
9086
}

lib/web_ui/lib/src/engine/navigation/history.dart

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,15 @@ class MultiEntriesBrowserHistory extends BrowserHistory {
151151
currentPath);
152152
}
153153
_lastSeenSerialCount = _currentSerialCount;
154-
if (EnginePlatformDispatcher.instance._onPlatformMessage != null) {
155-
EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
156-
'flutter/navigation',
157-
const JSONMethodCodec().encodeMethodCall(
158-
MethodCall('pushRouteInformation', <dynamic, dynamic>{
159-
'location': currentPath,
160-
'state': event.state?['state'],
161-
})),
162-
(_) {},
163-
);
164-
}
154+
EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
155+
'flutter/navigation',
156+
const JSONMethodCodec().encodeMethodCall(
157+
MethodCall('pushRouteInformation', <dynamic, dynamic>{
158+
'location': currentPath,
159+
'state': event.state?['state'],
160+
})),
161+
(_) {},
162+
);
165163
}
166164

167165
@override
@@ -272,13 +270,11 @@ class SingleEntryBrowserHistory extends BrowserHistory {
272270
_setupFlutterEntry(urlStrategy!);
273271

274272
// 2. Send a 'popRoute' platform message so the app can handle it accordingly.
275-
if (EnginePlatformDispatcher.instance._onPlatformMessage != null) {
276-
EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
277-
'flutter/navigation',
278-
const JSONMethodCodec().encodeMethodCall(_popRouteMethodCall),
279-
(_) {},
280-
);
281-
}
273+
EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
274+
'flutter/navigation',
275+
const JSONMethodCodec().encodeMethodCall(_popRouteMethodCall),
276+
(_) {},
277+
);
282278
} else if (_isFlutterEntry(event.state)) {
283279
// We get into this scenario when the user changes the url manually. It
284280
// causes a new entry to be pushed on top of our "flutter" one. When this
@@ -291,15 +287,13 @@ class SingleEntryBrowserHistory extends BrowserHistory {
291287
_userProvidedRouteName = null;
292288

293289
// Send a 'pushRoute' platform message so the app handles it accordingly.
294-
if (EnginePlatformDispatcher.instance._onPlatformMessage != null) {
295-
EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
296-
'flutter/navigation',
297-
const JSONMethodCodec().encodeMethodCall(
298-
MethodCall('pushRoute', newRouteName),
299-
),
300-
(_) {},
301-
);
302-
}
290+
EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
291+
'flutter/navigation',
292+
const JSONMethodCodec().encodeMethodCall(
293+
MethodCall('pushRoute', newRouteName),
294+
),
295+
(_) {},
296+
);
303297
} else {
304298
// The user has pushed a new entry on top of our flutter entry. This could
305299
// happen when the user modifies the hash part of the url directly, for

0 commit comments

Comments
 (0)