Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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
17 changes: 14 additions & 3 deletions shell/platform/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ source_set("flutter_linux_sources") {
]

# Set flag to stop headers being directly included (library users should not do this)
defines = [ "FLUTTER_LINUX_COMPILATION" ]
defines = [
"FLUTTER_LINUX_COMPILATION",
"FLUTTER_ENGINE_NO_PROTOTYPES",
]

deps = [
"//flutter/shell/platform/common/cpp:common_cpp_input",
Expand All @@ -138,6 +141,8 @@ source_set("flutter_linux") {
"//third_party/khronos:khronos_headers",
]

defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES" ]

public_deps = [ ":flutter_linux_sources" ]

deps = [ "//flutter/shell/platform/embedder:embedder_as_internal_library" ]
Expand Down Expand Up @@ -182,14 +187,20 @@ executable("flutter_linux_unittests") {
"//flutter/shell/platform/linux/config:x11",
]

# Set flag to allow public headers to be directly included (library users should not do this)
defines = [ "FLUTTER_LINUX_COMPILATION" ]
defines = [
"FLUTTER_ENGINE_NO_PROTOTYPES",

# Set flag to allow public headers to be directly included
# (library users should not do this)
"FLUTTER_LINUX_COMPILATION",
]

deps = [
":flutter_linux_fixtures",
":flutter_linux_sources",
"//flutter/runtime:libdart",
"//flutter/shell/platform/embedder:embedder_headers",
"//flutter/shell/platform/embedder:embedder_test_utils",
"//flutter/testing",
]
}
Expand Down
47 changes: 44 additions & 3 deletions shell/platform/linux/fl_basic_message_channel_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,54 @@
// Included first as it collides with the X11 headers.
#include "gtest/gtest.h"

#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_message_codec.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"
#include "flutter/shell/platform/linux/testing/mock_renderer.h"

// Checks sending a message without a reponse works.
TEST(FlBasicMessageChannelTest, SendMessageWithoutResponse) {
g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);

g_autoptr(FlEngine) engine = make_mock_engine();
FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

bool called = false;
embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
SendPlatformMessage,
([&called](auto engine, const FlutterPlatformMessage* message) {
called = true;
EXPECT_STREQ(message->channel, "test");
EXPECT_EQ(message->response_handle, nullptr);

g_autoptr(GBytes) message_bytes =
g_bytes_new(message->message, message->message_size);
g_autoptr(FlStandardMessageCodec) codec =
fl_standard_message_codec_new();
FlValue* message_value = fl_message_codec_decode_message(
FL_MESSAGE_CODEC(codec), message_bytes, nullptr);
EXPECT_EQ(fl_value_get_type(message_value), FL_VALUE_TYPE_STRING);
EXPECT_STREQ(fl_value_get_string(message_value), "Hello World!");

return kSuccess;
}));

FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new();
g_autoptr(FlBasicMessageChannel) channel =
fl_basic_message_channel_new(messenger, "test", FL_MESSAGE_CODEC(codec));
g_autoptr(FlValue) message = fl_value_new_string("Hello World!");
fl_basic_message_channel_send(channel, message, nullptr, nullptr, loop);

EXPECT_TRUE(called);
}

// Called when the message response is received in the SendMessage test.
static void echo_response_cb(GObject* object,
GAsyncResult* result,
Expand All @@ -28,8 +69,8 @@ static void echo_response_cb(GObject* object,
g_main_loop_quit(static_cast<GMainLoop*>(user_data));
}

// Checks sending a message works.
TEST(FlBasicMessageChannelTest, SendMessage) {
// Checks sending a message with a response works.
TEST(FlBasicMessageChannelTest, SendMessageWithResponse) {
g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);

g_autoptr(FlEngine) engine = make_mock_engine();
Expand Down
43 changes: 27 additions & 16 deletions shell/platform/linux/fl_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct _FlEngine {
FlBinaryMessenger* binary_messenger;
FlutterEngineAOTData aot_data;
FLUTTER_API_SYMBOL(FlutterEngine) engine;
FlutterEngineProcTable embedder_api;

// Function to call when a platform message is received.
FlEnginePlatformMessageHandler platform_message_handler;
Expand Down Expand Up @@ -127,7 +128,7 @@ static void setup_locales(FlEngine* self) {
}
FlutterLocale** locales =
reinterpret_cast<FlutterLocale**>(locales_array->pdata);
FlutterEngineResult result = FlutterEngineUpdateLocales(
FlutterEngineResult result = self->embedder_api.UpdateLocales(
self->engine, const_cast<const FlutterLocale**>(locales),
locales_array->len);
if (result != kSuccess) {
Expand All @@ -143,7 +144,7 @@ static gboolean flutter_source_dispatch(GSource* source,
FlEngine* self = fl_source->engine;

FlutterEngineResult result =
FlutterEngineRunTask(self->engine, &fl_source->task);
self->embedder_api.RunTask(self->engine, &fl_source->task);
if (result != kSuccess) {
g_warning("Failed to run Flutter task\n");
}
Expand Down Expand Up @@ -302,12 +303,12 @@ static void fl_engine_dispose(GObject* object) {
FlEngine* self = FL_ENGINE(object);

if (self->engine != nullptr) {
FlutterEngineShutdown(self->engine);
self->embedder_api.Shutdown(self->engine);
self->engine = nullptr;
}

if (self->aot_data != nullptr) {
FlutterEngineCollectAOTData(self->aot_data);
self->embedder_api.CollectAOTData(self->aot_data);
self->aot_data = nullptr;
}

Expand All @@ -332,6 +333,9 @@ static void fl_engine_class_init(FlEngineClass* klass) {
static void fl_engine_init(FlEngine* self) {
self->thread = g_thread_self();

self->embedder_api.struct_size = sizeof(FlutterEngineProcTable);
FlutterEngineGetProcAddresses(&self->embedder_api);

self->binary_messenger = fl_binary_messenger_new(self);
}

Expand Down Expand Up @@ -400,27 +404,28 @@ gboolean fl_engine_start(FlEngine* self, GError** error) {
args.dart_entrypoint_argv =
reinterpret_cast<const char* const*>(dart_entrypoint_args);

if (FlutterEngineRunsAOTCompiledDartCode()) {
if (self->embedder_api.RunsAOTCompiledDartCode()) {
FlutterEngineAOTDataSource source = {};
source.type = kFlutterEngineAOTDataSourceTypeElfPath;
source.elf_path = fl_dart_project_get_aot_library_path(self->project);
if (FlutterEngineCreateAOTData(&source, &self->aot_data) != kSuccess) {
if (self->embedder_api.CreateAOTData(&source, &self->aot_data) !=
kSuccess) {
g_set_error(error, fl_engine_error_quark(), FL_ENGINE_ERROR_FAILED,
"Failed to create AOT data");
return FALSE;
}
args.aot_data = self->aot_data;
}

FlutterEngineResult result = FlutterEngineInitialize(
FlutterEngineResult result = self->embedder_api.Initialize(
FLUTTER_ENGINE_VERSION, &config, &args, self, &self->engine);
if (result != kSuccess) {
g_set_error(error, fl_engine_error_quark(), FL_ENGINE_ERROR_FAILED,
"Failed to initialize Flutter engine");
return FALSE;
}

result = FlutterEngineRunInitialized(self->engine);
result = self->embedder_api.RunInitialized(self->engine);
if (result != kSuccess) {
g_set_error(error, fl_engine_error_quark(), FL_ENGINE_ERROR_FAILED,
"Failed to run Flutter engine");
Expand All @@ -432,6 +437,10 @@ gboolean fl_engine_start(FlEngine* self, GError** error) {
return TRUE;
}

FlutterEngineProcTable* fl_engine_get_embedder_api(FlEngine* self) {
return &(self->embedder_api);
}

void fl_engine_set_platform_message_handler(
FlEngine* self,
FlEnginePlatformMessageHandler handler,
Expand Down Expand Up @@ -470,7 +479,7 @@ gboolean fl_engine_send_platform_message_response(
data =
static_cast<const uint8_t*>(g_bytes_get_data(response, &data_length));
}
FlutterEngineResult result = FlutterEngineSendPlatformMessageResponse(
FlutterEngineResult result = self->embedder_api.SendPlatformMessageResponse(
self->engine, handle, data, data_length);

if (result != kSuccess) {
Expand Down Expand Up @@ -501,9 +510,10 @@ void fl_engine_send_platform_message(FlEngine* self,
return;
}

FlutterEngineResult result = FlutterPlatformMessageCreateResponseHandle(
self->engine, fl_engine_platform_message_response_cb, task,
&response_handle);
FlutterEngineResult result =
self->embedder_api.PlatformMessageCreateResponseHandle(
self->engine, fl_engine_platform_message_response_cb, task,
&response_handle);
if (result != kSuccess) {
g_task_return_new_error(task, fl_engine_error_quark(),
FL_ENGINE_ERROR_FAILED,
Expand All @@ -525,7 +535,7 @@ void fl_engine_send_platform_message(FlEngine* self,
fl_message.message_size = message != nullptr ? g_bytes_get_size(message) : 0;
fl_message.response_handle = response_handle;
FlutterEngineResult result =
FlutterEngineSendPlatformMessage(self->engine, &fl_message);
self->embedder_api.SendPlatformMessage(self->engine, &fl_message);

if (result != kSuccess && task != nullptr) {
g_task_return_new_error(task, fl_engine_error_quark(),
Expand All @@ -535,7 +545,8 @@ void fl_engine_send_platform_message(FlEngine* self,
}

if (response_handle != nullptr) {
FlutterPlatformMessageReleaseResponseHandle(self->engine, response_handle);
self->embedder_api.PlatformMessageReleaseResponseHandle(self->engine,
response_handle);
}
}

Expand Down Expand Up @@ -563,7 +574,7 @@ void fl_engine_send_window_metrics_event(FlEngine* self,
event.width = width;
event.height = height;
event.pixel_ratio = pixel_ratio;
FlutterEngineSendWindowMetricsEvent(self->engine, &event);
self->embedder_api.SendWindowMetricsEvent(self->engine, &event);
}

void fl_engine_send_mouse_pointer_event(FlEngine* self,
Expand Down Expand Up @@ -593,7 +604,7 @@ void fl_engine_send_mouse_pointer_event(FlEngine* self,
fl_event.scroll_delta_y = scroll_delta_y;
fl_event.device_kind = kFlutterPointerDeviceKindMouse;
fl_event.buttons = buttons;
FlutterEngineSendPointerEvent(self->engine, &fl_event, 1);
self->embedder_api.SendPointerEvent(self->engine, &fl_event, 1);
}

G_MODULE_EXPORT FlBinaryMessenger* fl_engine_get_binary_messenger(
Expand Down
10 changes: 10 additions & 0 deletions shell/platform/linux/fl_engine_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ typedef gboolean (*FlEnginePlatformMessageHandler)(
*/
FlEngine* fl_engine_new(FlDartProject* project, FlRenderer* renderer);

/**
* fl_engine_get_embedder_api:
* @engine: an #FlEngine.
*
* Gets the embedder API proc table, allowing modificiations for unit testing.
*
* Returns: a mutable pointer to the embedder API proc table.
*/
FlutterEngineProcTable* fl_engine_get_embedder_api(FlEngine* engine);

/**
* fl_engine_set_platform_message_handler:
* @engine: an #FlEngine.
Expand Down
Loading