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

[Windows] Expose channel buffers 'resize' and 'overflow' control commands exposed by the control channel. #47158

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -20,23 +21,34 @@ 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<int>(message_size);
last_message_ =
std::vector<uint8_t>(message, message + length * sizeof(uint8_t));
}

void SetMessageHandler(const std::string& channel,
BinaryMessageHandler handler) override {
last_message_handler_channel_ = channel;
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<uint8_t> last_message() { return last_message_; }

private:
mutable bool send_called_ = false;
std::string last_message_handler_channel_;
BinaryMessageHandler last_message_handler_;
mutable std::vector<uint8_t> last_message_;
};

} // namespace
Expand Down Expand Up @@ -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<int>(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<int>(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
42 changes: 42 additions & 0 deletions shell/platform/common/client_wrapper/core_implementations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -164,6 +166,46 @@ void ReplyManager::SendResponseData(const std::vector<uint8_t>* 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<MethodChannel<EncodableValue>>(
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<EncodableValue>(EncodableList{
EncodableValue(name),
EncodableValue(static_cast<int32_t>(new_size)),
}));
}

void SetChannelWarnsOnOverflow(BinaryMessenger* messenger,
std::string name,
bool warns) {
auto control_channel = std::make_unique<MethodChannel<EncodableValue>>(
messenger, kControlChannelName, &StandardMethodCodec::GetInstance());

control_channel->InvokeMethod(kOverflowMethod,
std::make_unique<EncodableValue>(EncodableList{
EncodableValue(name),
EncodableValue(!warns),
}));
}

} // namespace internal

// ========== texture_registrar_impl.h ==========

TextureRegistrarImpl::TextureRegistrarImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <iostream>
#include <string>

#include "basic_message_channel.h"
#include "binary_messenger.h"
#include "engine_method_result.h"
#include "method_call.h"
Expand Down Expand Up @@ -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_;
Expand Down
66 changes: 66 additions & 0 deletions shell/platform/common/client_wrapper/method_channel_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class TestBinaryMessenger : public BinaryMessenger {
BinaryReply reply) const override {
send_called_ = true;
last_reply_handler_ = reply;
int length = static_cast<int>(message_size);
last_message_ =
std::vector<uint8_t>(message, message + length * sizeof(uint8_t));
}

void SetMessageHandler(const std::string& channel,
Expand All @@ -42,11 +45,14 @@ class TestBinaryMessenger : public BinaryMessenger {

BinaryMessageHandler last_message_handler() { return last_message_handler_; }

std::vector<uint8_t> 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<uint8_t> last_message_;
};

} // namespace
Expand Down Expand Up @@ -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<int>(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<int>(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