diff --git a/shell/platform/common/client_wrapper/basic_message_channel_unittests.cc b/shell/platform/common/client_wrapper/basic_message_channel_unittests.cc index f38595c8c165a..ba24f60b00f1c 100644 --- a/shell/platform/common/client_wrapper/basic_message_channel_unittests.cc +++ b/shell/platform/common/client_wrapper/basic_message_channel_unittests.cc @@ -9,6 +9,7 @@ #include "flutter/shell/platform/common/client_wrapper/include/flutter/binary_messenger.h" #include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h" +#include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_method_codec.h" #include "gtest/gtest.h" namespace flutter { @@ -20,7 +21,12 @@ class TestBinaryMessenger : public BinaryMessenger { void Send(const std::string& channel, const uint8_t* message, const size_t message_size, - BinaryReply reply) const override {} + BinaryReply reply) const override { + send_called_ = true; + int length = static_cast(message_size); + last_message_ = + std::vector(message, message + length * sizeof(uint8_t)); + } void SetMessageHandler(const std::string& channel, BinaryMessageHandler handler) override { @@ -28,15 +34,21 @@ class TestBinaryMessenger : public BinaryMessenger { last_message_handler_ = handler; } + bool send_called() { return send_called_; } + std::string last_message_handler_channel() { return last_message_handler_channel_; } BinaryMessageHandler last_message_handler() { return last_message_handler_; } + std::vector last_message() { return last_message_; } + private: + mutable bool send_called_ = false; std::string last_message_handler_channel_; BinaryMessageHandler last_message_handler_; + mutable std::vector last_message_; }; } // namespace @@ -86,4 +98,68 @@ TEST(BasicMessageChannelTest, Unregistration) { EXPECT_EQ(messenger.last_message_handler(), nullptr); } +// Tests that calling Resize generates the binary message expected by the Dart +// implementation. +TEST(BasicMessageChannelTest, Resize) { + TestBinaryMessenger messenger; + const std::string channel_name("flutter/test"); + BasicMessageChannel channel(&messenger, channel_name, + &flutter::StandardMessageCodec::GetInstance()); + + channel.Resize(3); + + // Because the Dart implementation for the control channel implements its own + // custom deserialization logic, this test compares the generated bytes array + // to the expected one (for instance, the deserialization logic expects the + // size parameter of the resize method call to be an uint32). + // + // The expected content was created from the following Dart code: + // MethodCall call = MethodCall('resize', ['flutter/test',3]); + // StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List(); + const int expected_message_size = 29; + + EXPECT_EQ(messenger.send_called(), true); + EXPECT_EQ(static_cast(messenger.last_message().size()), + expected_message_size); + + int expected[expected_message_size] = { + 7, 6, 114, 101, 115, 105, 122, 101, 12, 2, 7, 12, 102, 108, 117, + 116, 116, 101, 114, 47, 116, 101, 115, 116, 3, 3, 0, 0, 0}; + for (int i = 0; i < expected_message_size; i++) { + EXPECT_EQ(messenger.last_message()[i], expected[i]); + } +} + +// Tests that calling SetWarnsOnOverflow generates the binary message expected +// by the Dart implementation. +TEST(BasicMessageChannelTest, SetWarnsOnOverflow) { + TestBinaryMessenger messenger; + + const std::string channel_name("flutter/test"); + BasicMessageChannel channel(&messenger, channel_name, + &flutter::StandardMessageCodec::GetInstance()); + + channel.SetWarnsOnOverflow(false); + + // Because the Dart implementation for the control channel implements its own + // custom deserialization logic, this test compares the generated bytes array + // to the expected one. + // + // The expected content was created from the following Dart code: + // MethodCall call = MethodCall('overflow',['flutter/test', true]); + // StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List(); + const int expected_message_size = 27; + + EXPECT_EQ(messenger.send_called(), true); + EXPECT_EQ(static_cast(messenger.last_message().size()), + expected_message_size); + + int expected[expected_message_size] = { + 7, 8, 111, 118, 101, 114, 102, 108, 111, 119, 12, 2, 7, 12, + 102, 108, 117, 116, 116, 101, 114, 47, 116, 101, 115, 116, 1}; + for (int i = 0; i < expected_message_size; i++) { + EXPECT_EQ(messenger.last_message()[i], expected[i]); + } +} + } // namespace flutter diff --git a/shell/platform/common/client_wrapper/core_implementations.cc b/shell/platform/common/client_wrapper/core_implementations.cc index 1eb5a5898117d..f682f1b22994e 100644 --- a/shell/platform/common/client_wrapper/core_implementations.cc +++ b/shell/platform/common/client_wrapper/core_implementations.cc @@ -19,6 +19,8 @@ #include "binary_messenger_impl.h" #include "include/flutter/engine_method_result.h" +#include "include/flutter/method_channel.h" +#include "include/flutter/standard_method_codec.h" #include "texture_registrar_impl.h" namespace flutter { @@ -164,6 +166,46 @@ void ReplyManager::SendResponseData(const std::vector* data) { } // namespace internal +// ========== method_channel.h ========== + +namespace { + +constexpr char kControlChannelName[] = "dev.flutter/channel-buffers"; +constexpr char kResizeMethod[] = "resize"; +constexpr char kOverflowMethod[] = "overflow"; + +} // namespace + +namespace internal { + +void ResizeChannel(BinaryMessenger* messenger, std::string name, int new_size) { + auto control_channel = std::make_unique>( + messenger, kControlChannelName, &StandardMethodCodec::GetInstance()); + + // The deserialization logic handles only 32 bits values, see + // https://github.com/flutter/engine/blob/93e8901490e78c7ba7e319cce4470d9c6478c6dc/lib/ui/channel_buffers.dart#L495. + control_channel->InvokeMethod( + kResizeMethod, std::make_unique(EncodableList{ + EncodableValue(name), + EncodableValue(static_cast(new_size)), + })); +} + +void SetChannelWarnsOnOverflow(BinaryMessenger* messenger, + std::string name, + bool warns) { + auto control_channel = std::make_unique>( + messenger, kControlChannelName, &StandardMethodCodec::GetInstance()); + + control_channel->InvokeMethod(kOverflowMethod, + std::make_unique(EncodableList{ + EncodableValue(name), + EncodableValue(!warns), + })); +} + +} // namespace internal + // ========== texture_registrar_impl.h ========== TextureRegistrarImpl::TextureRegistrarImpl( diff --git a/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h b/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h index 4109c59a0a615..27c6cc93d6f50 100644 --- a/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h +++ b/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h @@ -14,6 +14,26 @@ namespace flutter { +namespace internal { +// Internal helper functions used by BasicMessageChannel and MethodChannel. + +// Adjusts the number of messages that will get buffered when sending messages +// to channels that aren't fully set up yet. For example, the engine isn't +// running yet or the channel's message handler isn't set up on the Dart side +// yet. +void ResizeChannel(BinaryMessenger* messenger, std::string name, int new_size); + +// Defines whether the channel should show warning messages when discarding +// messages due to overflow. +// +// When |warns| is false, the channel is expected to overflow and warning +// messages will not be shown. +void SetChannelWarnsOnOverflow(BinaryMessenger* messenger, + std::string name, + bool warns); + +} // namespace internal + class EncodableValue; // A message reply callback. @@ -101,6 +121,23 @@ class BasicMessageChannel { messenger_->SetMessageHandler(name_, std::move(binary_handler)); } + // Adjusts the number of messages that will get buffered when sending messages + // to channels that aren't fully set up yet. For example, the engine isn't + // running yet or the channel's message handler isn't set up on the Dart side + // yet. + void Resize(int new_size) { + internal::ResizeChannel(messenger_, name_, new_size); + } + + // Defines whether the channel should show warning messages when discarding + // messages due to overflow. + // + // When |warns| is false, the channel is expected to overflow and warning + // messages will not be shown. + void SetWarnsOnOverflow(bool warns) { + internal::SetChannelWarnsOnOverflow(messenger_, name_, warns); + } + private: BinaryMessenger* messenger_; std::string name_; diff --git a/shell/platform/common/client_wrapper/include/flutter/method_channel.h b/shell/platform/common/client_wrapper/include/flutter/method_channel.h index 6e39a644f6e08..a4029fccf7a5c 100644 --- a/shell/platform/common/client_wrapper/include/flutter/method_channel.h +++ b/shell/platform/common/client_wrapper/include/flutter/method_channel.h @@ -8,6 +8,7 @@ #include #include +#include "basic_message_channel.h" #include "binary_messenger.h" #include "engine_method_result.h" #include "method_call.h" @@ -122,6 +123,23 @@ class MethodChannel { messenger_->SetMessageHandler(name_, std::move(binary_handler)); } + // Adjusts the number of messages that will get buffered when sending messages + // to channels that aren't fully set up yet. For example, the engine isn't + // running yet or the channel's message handler isn't set up on the Dart side + // yet. + void Resize(int new_size) { + internal::ResizeChannel(messenger_, name_, new_size); + } + + // Defines whether the channel should show warning messages when discarding + // messages due to overflow. + // + // When |warns| is false, the channel is expected to overflow and warning + // messages will not be shown. + void SetWarnsOnOverflow(bool warns) { + internal::SetChannelWarnsOnOverflow(messenger_, name_, warns); + } + private: BinaryMessenger* messenger_; std::string name_; diff --git a/shell/platform/common/client_wrapper/method_channel_unittests.cc b/shell/platform/common/client_wrapper/method_channel_unittests.cc index 55c4529edd581..2edce72a566c6 100644 --- a/shell/platform/common/client_wrapper/method_channel_unittests.cc +++ b/shell/platform/common/client_wrapper/method_channel_unittests.cc @@ -24,6 +24,9 @@ class TestBinaryMessenger : public BinaryMessenger { BinaryReply reply) const override { send_called_ = true; last_reply_handler_ = reply; + int length = static_cast(message_size); + last_message_ = + std::vector(message, message + length * sizeof(uint8_t)); } void SetMessageHandler(const std::string& channel, @@ -42,11 +45,14 @@ class TestBinaryMessenger : public BinaryMessenger { BinaryMessageHandler last_message_handler() { return last_message_handler_; } + std::vector last_message() { return last_message_; } + private: mutable bool send_called_ = false; mutable BinaryReply last_reply_handler_; std::string last_message_handler_channel_; BinaryMessageHandler last_message_handler_; + mutable std::vector last_message_; }; } // namespace @@ -156,4 +162,64 @@ TEST(MethodChannelTest, InvokeNotImplemented) { EXPECT_TRUE(received_not_implemented); } +// Tests that calling Resize generates the binary message expected by the Dart +// implementation. +TEST(MethodChannelTest, Resize) { + TestBinaryMessenger messenger; + const std::string channel_name("flutter/test"); + MethodChannel channel(&messenger, channel_name, + &StandardMethodCodec::GetInstance()); + + channel.Resize(3); + + // Because the Dart implementation for the control channel implements its own + // custom deserialization logic, this test compares the generated bytes array + // to the expected one (for instance, the deserialization logic expects the + // size parameter of the resize method call to be an uint32). + // + // The expected content was created from the following Dart code: + // MethodCall call = MethodCall('resize', ['flutter/test',3]); + // StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List(); + const int expected_message_size = 29; + + EXPECT_EQ(messenger.send_called(), true); + EXPECT_EQ(static_cast(messenger.last_message().size()), + expected_message_size); + + int expected[expected_message_size] = { + 7, 6, 114, 101, 115, 105, 122, 101, 12, 2, 7, 12, 102, 108, 117, + 116, 116, 101, 114, 47, 116, 101, 115, 116, 3, 3, 0, 0, 0}; + for (int i = 0; i < expected_message_size; i++) { + EXPECT_EQ(messenger.last_message()[i], expected[i]); + } +} + +// Tests that calling SetWarnsOnOverflow generates the binary message expected +// by the Dart implementation. +TEST(MethodChannelTest, SetWarnsOnOverflow) { + TestBinaryMessenger messenger; + + const std::string channel_name("flutter/test"); + MethodChannel channel(&messenger, channel_name, + &StandardMethodCodec::GetInstance()); + + channel.SetWarnsOnOverflow(false); + + // The expected content was created from the following Dart code: + // MethodCall call = MethodCall('overflow',['flutter/test', true]); + // StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List(); + const int expected_message_size = 27; + + EXPECT_EQ(messenger.send_called(), true); + EXPECT_EQ(static_cast(messenger.last_message().size()), + expected_message_size); + + int expected[expected_message_size] = { + 7, 8, 111, 118, 101, 114, 102, 108, 111, 119, 12, 2, 7, 12, + 102, 108, 117, 116, 116, 101, 114, 47, 116, 101, 115, 116, 1}; + for (int i = 0; i < expected_message_size; i++) { + EXPECT_EQ(messenger.last_message()[i], expected[i]); + } +} + } // namespace flutter