Channel buffers (#40165)
Started reading stored channel messages from ui.channelBuffers when handlers get set.
diff --git a/packages/flutter/lib/src/services/binding.dart b/packages/flutter/lib/src/services/binding.dart
index 2fb3d3b..428ebe1 100644
--- a/packages/flutter/lib/src/services/binding.dart
+++ b/packages/flutter/lib/src/services/binding.dart
@@ -186,8 +186,11 @@
ByteData response;
try {
final MessageHandler handler = _handlers[channel];
- if (handler != null)
+ if (handler != null) {
response = await handler(data);
+ } else {
+ ui.channelBuffers.push(channel, data, callback);
+ }
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
@@ -214,6 +217,9 @@
_handlers.remove(channel);
else
_handlers[channel] = handler;
+ ui.channelBuffers.drain(channel, (ByteData data, ui.PlatformMessageResponseCallback callback) async {
+ await handlePlatformMessage(channel, data, callback);
+ });
}
@override
diff --git a/packages/flutter/test/services/channel_buffers_test.dart b/packages/flutter/test/services/channel_buffers_test.dart
new file mode 100644
index 0000000..3c249d5
--- /dev/null
+++ b/packages/flutter/test/services/channel_buffers_test.dart
@@ -0,0 +1,50 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:typed_data';
+import 'dart:ui' as ui;
+import 'package:flutter/foundation.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+class TestChannelBuffersFlutterBinding extends BindingBase with ServicesBinding {
+}
+
+void main() {
+ ByteData _makeByteData(String str) {
+ final List<int> list = utf8.encode(str);
+ final ByteBuffer buffer = list is Uint8List ? list.buffer : Uint8List.fromList(list).buffer;
+ return ByteData.view(buffer);
+ }
+
+ String _getString(ByteData data) {
+ final ByteBuffer buffer = data.buffer;
+ final List<int> list = buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
+ return utf8.decode(list);
+ }
+
+ test('does drain channel buffers', () async {
+ const String channel = 'foo';
+ final TestChannelBuffersFlutterBinding binding = TestChannelBuffersFlutterBinding();
+ expect(binding.defaultBinaryMessenger, isNotNull);
+ bool didCallCallback = false;
+ final ui.PlatformMessageResponseCallback callback = (ByteData responseData) {
+ didCallCallback = true;
+ };
+ const String payload = 'bar';
+ final ByteData data = _makeByteData(payload);
+ ui.channelBuffers.push(channel, data, callback);
+ bool didDrainData = false;
+ binding.defaultBinaryMessenger.setMessageHandler(channel, (ByteData message) async {
+ expect(_getString(message), payload);
+ didDrainData= true;
+ return null;
+ });
+ // Flush the event queue.
+ await Future<void>((){});
+ expect(didDrainData, isTrue);
+ expect(didCallCallback, isTrue);
+ });
+}
diff --git a/packages/flutter_web_plugins/lib/src/plugin_registry.dart b/packages/flutter_web_plugins/lib/src/plugin_registry.dart
index a48d50c..a867b2a 100644
--- a/packages/flutter_web_plugins/lib/src/plugin_registry.dart
+++ b/packages/flutter_web_plugins/lib/src/plugin_registry.dart
@@ -80,6 +80,8 @@
final MessageHandler handler = _handlers[channel];
if (handler != null) {
response = await handler(data);
+ } else {
+ ui.channelBuffers.push(channel, data, callback);
}
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
@@ -119,6 +121,9 @@
_handlers.remove(channel);
else
_handlers[channel] = handler;
+ ui.channelBuffers.drain(channel, (ByteData data, ui.PlatformMessageResponseCallback callback) async {
+ await handlePlatformMessage(channel, data, callback);
+ });
}
@override