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

Commit 91eab23

Browse files
Switch Windows embedding to proc table embedder API (#22211)
Switches the Windows embedding from the standard C API to the new proctable version, to allow for unit testing of the embedding layer separately from the embedder APIs implementation. This includes moving some engine messaging that was still in flutter_windows to the C++ engine class to better encapsulate the proc table.
1 parent d27ff81 commit 91eab23

12 files changed

+281
-67
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,7 @@ FILE: ../../../flutter/shell/platform/windows/flutter_project_bundle_unittests.c
14001400
FILE: ../../../flutter/shell/platform/windows/flutter_windows.cc
14011401
FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine.cc
14021402
FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine.h
1403+
FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine_unittests.cc
14031404
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc
14041405
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h
14051406
FILE: ../../../flutter/shell/platform/windows/key_event_handler.cc

shell/platform/windows/BUILD.gn

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ source_set("flutter_windows_source") {
8282

8383
public_configs = [ ":relative_angle_headers" ]
8484

85+
defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES" ]
86+
8587
deps = [
8688
":flutter_windows_headers",
8789
"//flutter/shell/platform/common/cpp:common_cpp",
@@ -123,8 +125,10 @@ executable("flutter_windows_unittests") {
123125

124126
sources = [
125127
"flutter_project_bundle_unittests.cc",
128+
"flutter_windows_engine_unittests.cc",
126129
"string_conversion_unittests.cc",
127130
"system_utils_unittests.cc",
131+
"testing/engine_embedder_api_modifier.h",
128132
"testing/mock_win32_window.cc",
129133
"testing/mock_win32_window.h",
130134
"testing/win32_flutter_window_test.cc",
@@ -141,6 +145,8 @@ executable("flutter_windows_unittests") {
141145
":flutter_windows_fixtures",
142146
":flutter_windows_headers",
143147
":flutter_windows_source",
148+
"//flutter/shell/platform/embedder:embedder_as_internal_library",
149+
"//flutter/shell/platform/embedder:embedder_test_utils",
144150
"//flutter/testing",
145151
"//third_party/rapidjson",
146152
]

shell/platform/windows/flutter_project_bundle.cc

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,29 +52,30 @@ bool FlutterProjectBundle::HasValidPaths() {
5252

5353
// Attempts to load AOT data from the given path, which must be absolute and
5454
// non-empty. Logs and returns nullptr on failure.
55-
UniqueAotDataPtr FlutterProjectBundle::LoadAotData() {
55+
UniqueAotDataPtr FlutterProjectBundle::LoadAotData(
56+
const FlutterEngineProcTable& engine_procs) {
5657
if (aot_library_path_.empty()) {
5758
std::cerr
5859
<< "Attempted to load AOT data, but no aot_library_path was provided."
5960
<< std::endl;
60-
return nullptr;
61+
return UniqueAotDataPtr(nullptr, nullptr);
6162
}
6263
if (!std::filesystem::exists(aot_library_path_)) {
6364
std::cerr << "Can't load AOT data from " << aot_library_path_.u8string()
6465
<< "; no such file." << std::endl;
65-
return nullptr;
66+
return UniqueAotDataPtr(nullptr, nullptr);
6667
}
6768
std::string path_string = aot_library_path_.u8string();
6869
FlutterEngineAOTDataSource source = {};
6970
source.type = kFlutterEngineAOTDataSourceTypeElfPath;
7071
source.elf_path = path_string.c_str();
7172
FlutterEngineAOTData data = nullptr;
72-
auto result = FlutterEngineCreateAOTData(&source, &data);
73+
auto result = engine_procs.CreateAOTData(&source, &data);
7374
if (result != kSuccess) {
7475
std::cerr << "Failed to load AOT data from: " << path_string << std::endl;
75-
return nullptr;
76+
return UniqueAotDataPtr(nullptr, nullptr);
7677
}
77-
return UniqueAotDataPtr(data);
78+
return UniqueAotDataPtr(data, engine_procs.CollectAOTData);
7879
}
7980

8081
FlutterProjectBundle::~FlutterProjectBundle() {}

shell/platform/windows/flutter_project_bundle.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@
1414

1515
namespace flutter {
1616

17-
struct AotDataDeleter {
18-
void operator()(FlutterEngineAOTData aot_data) {
19-
FlutterEngineCollectAOTData(aot_data);
20-
}
21-
};
22-
using UniqueAotDataPtr = std::unique_ptr<_FlutterEngineAOTData, AotDataDeleter>;
17+
using UniqueAotDataPtr =
18+
std::unique_ptr<_FlutterEngineAOTData, FlutterEngineCollectAOTDataFnPtr>;
2319

2420
// The data associated with a Flutter project needed to run it in an engine.
2521
class FlutterProjectBundle {
@@ -49,7 +45,7 @@ class FlutterProjectBundle {
4945
// retained until any engine instance it is passed to has been shut down.
5046
//
5147
// Logs and returns nullptr on failure.
52-
UniqueAotDataPtr LoadAotData();
48+
UniqueAotDataPtr LoadAotData(const FlutterEngineProcTable& engine_procs);
5349

5450
// Returns the command line arguments to be passed through to the Dart
5551
// entrypoint.

shell/platform/windows/flutter_windows.cc

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine) {
137137
}
138138

139139
void FlutterDesktopEngineReloadSystemFonts(FlutterDesktopEngineRef engine) {
140-
FlutterEngineReloadSystemFonts(EngineFromHandle(engine)->engine());
140+
EngineFromHandle(engine)->ReloadSystemFonts();
141141
}
142142

143143
FlutterDesktopPluginRegistrarRef FlutterDesktopEngineGetPluginRegistrar(
@@ -217,33 +217,8 @@ bool FlutterDesktopMessengerSendWithReply(FlutterDesktopMessengerRef messenger,
217217
const size_t message_size,
218218
const FlutterDesktopBinaryReply reply,
219219
void* user_data) {
220-
FlutterPlatformMessageResponseHandle* response_handle = nullptr;
221-
if (reply != nullptr && user_data != nullptr) {
222-
FlutterEngineResult result = FlutterPlatformMessageCreateResponseHandle(
223-
messenger->engine->engine(), reply, user_data, &response_handle);
224-
if (result != kSuccess) {
225-
std::cout << "Failed to create response handle\n";
226-
return false;
227-
}
228-
}
229-
230-
FlutterPlatformMessage platform_message = {
231-
sizeof(FlutterPlatformMessage),
232-
channel,
233-
message,
234-
message_size,
235-
response_handle,
236-
};
237-
238-
FlutterEngineResult message_result = FlutterEngineSendPlatformMessage(
239-
messenger->engine->engine(), &platform_message);
240-
241-
if (response_handle != nullptr) {
242-
FlutterPlatformMessageReleaseResponseHandle(messenger->engine->engine(),
243-
response_handle);
244-
}
245-
246-
return message_result == kSuccess;
220+
return messenger->engine->SendPlatformMessage(channel, message, message_size,
221+
reply, user_data);
247222
}
248223

249224
bool FlutterDesktopMessengerSend(FlutterDesktopMessengerRef messenger,
@@ -259,8 +234,7 @@ void FlutterDesktopMessengerSendResponse(
259234
const FlutterDesktopMessageResponseHandle* handle,
260235
const uint8_t* data,
261236
size_t data_length) {
262-
FlutterEngineSendPlatformMessageResponse(messenger->engine->engine(), handle,
263-
data, data_length);
237+
messenger->engine->SendPlatformMessageResponse(handle, data, data_length);
264238
}
265239

266240
void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger,

shell/platform/windows/flutter_windows_engine.cc

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,20 @@ FlutterLocale CovertToFlutterLocale(const LanguageInfo& info) {
9090
} // namespace
9191

9292
FlutterWindowsEngine::FlutterWindowsEngine(const FlutterProjectBundle& project)
93-
: project_(std::make_unique<FlutterProjectBundle>(project)) {
93+
: project_(std::make_unique<FlutterProjectBundle>(project)),
94+
aot_data_(nullptr, nullptr) {
95+
embedder_api_.struct_size = sizeof(FlutterEngineProcTable);
96+
FlutterEngineGetProcAddresses(&embedder_api_);
97+
9498
task_runner_ = std::make_unique<Win32TaskRunner>(
95-
GetCurrentThreadId(), [this](const auto* task) {
99+
GetCurrentThreadId(), embedder_api_.GetCurrentTime,
100+
[this](const auto* task) {
96101
if (!engine_) {
97102
std::cerr << "Cannot post an engine task when engine is not running."
98103
<< std::endl;
99104
return;
100105
}
101-
if (FlutterEngineRunTask(engine_, task) != kSuccess) {
106+
if (embedder_api_.RunTask(engine_, task) != kSuccess) {
102107
std::cerr << "Failed to post an engine task." << std::endl;
103108
}
104109
});
@@ -126,8 +131,8 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
126131
}
127132
std::string assets_path_string = project_->assets_path().u8string();
128133
std::string icu_path_string = project_->icu_path().u8string();
129-
if (FlutterEngineRunsAOTCompiledDartCode()) {
130-
aot_data_ = project_->LoadAotData();
134+
if (embedder_api_.RunsAOTCompiledDartCode()) {
135+
aot_data_ = project_->LoadAotData(embedder_api_);
131136
if (!aot_data_) {
132137
std::cerr << "Unable to start engine without AOT data." << std::endl;
133138
return false;
@@ -193,8 +198,8 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
193198

194199
FlutterRendererConfig renderer_config = GetRendererConfig();
195200

196-
auto result = FlutterEngineRun(FLUTTER_ENGINE_VERSION, &renderer_config,
197-
&args, this, &engine_);
201+
auto result = embedder_api_.Run(FLUTTER_ENGINE_VERSION, &renderer_config,
202+
&args, this, &engine_);
198203
if (result != kSuccess || engine_ == nullptr) {
199204
std::cerr << "Failed to start Flutter engine: error " << result
200205
<< std::endl;
@@ -211,7 +216,7 @@ bool FlutterWindowsEngine::Stop() {
211216
if (plugin_registrar_destruction_callback_) {
212217
plugin_registrar_destruction_callback_(plugin_registrar_.get());
213218
}
214-
FlutterEngineResult result = FlutterEngineShutdown(engine_);
219+
FlutterEngineResult result = embedder_api_.Shutdown(engine_);
215220
engine_ = nullptr;
216221
return (result == kSuccess);
217222
}
@@ -232,6 +237,60 @@ void FlutterWindowsEngine::SetPluginRegistrarDestructionCallback(
232237
plugin_registrar_destruction_callback_ = callback;
233238
}
234239

240+
void FlutterWindowsEngine::SendWindowMetricsEvent(
241+
const FlutterWindowMetricsEvent& event) {
242+
if (engine_) {
243+
embedder_api_.SendWindowMetricsEvent(engine_, &event);
244+
}
245+
}
246+
247+
void FlutterWindowsEngine::SendPointerEvent(const FlutterPointerEvent& event) {
248+
if (engine_) {
249+
embedder_api_.SendPointerEvent(engine_, &event, 1);
250+
}
251+
}
252+
253+
bool FlutterWindowsEngine::SendPlatformMessage(
254+
const char* channel,
255+
const uint8_t* message,
256+
const size_t message_size,
257+
const FlutterDesktopBinaryReply reply,
258+
void* user_data) {
259+
FlutterPlatformMessageResponseHandle* response_handle = nullptr;
260+
if (reply != nullptr && user_data != nullptr) {
261+
FlutterEngineResult result =
262+
embedder_api_.PlatformMessageCreateResponseHandle(
263+
engine_, reply, user_data, &response_handle);
264+
if (result != kSuccess) {
265+
std::cout << "Failed to create response handle\n";
266+
return false;
267+
}
268+
}
269+
270+
FlutterPlatformMessage platform_message = {
271+
sizeof(FlutterPlatformMessage),
272+
channel,
273+
message,
274+
message_size,
275+
response_handle,
276+
};
277+
278+
FlutterEngineResult message_result =
279+
embedder_api_.SendPlatformMessage(engine_, &platform_message);
280+
if (response_handle != nullptr) {
281+
embedder_api_.PlatformMessageReleaseResponseHandle(engine_,
282+
response_handle);
283+
}
284+
return message_result == kSuccess;
285+
}
286+
287+
void FlutterWindowsEngine::SendPlatformMessageResponse(
288+
const FlutterDesktopMessageResponseHandle* handle,
289+
const uint8_t* data,
290+
size_t data_length) {
291+
embedder_api_.SendPlatformMessageResponse(engine_, handle, data, data_length);
292+
}
293+
235294
void FlutterWindowsEngine::HandlePlatformMessage(
236295
const FlutterPlatformMessage* engine_message) {
237296
if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
@@ -247,6 +306,10 @@ void FlutterWindowsEngine::HandlePlatformMessage(
247306
message, [this] {}, [this] {});
248307
}
249308

309+
void FlutterWindowsEngine::ReloadSystemFonts() {
310+
embedder_api_.ReloadSystemFonts(engine_);
311+
}
312+
250313
void FlutterWindowsEngine::SendSystemSettings() {
251314
std::vector<LanguageInfo> languages = GetPreferredLanguageInfo();
252315
std::vector<FlutterLocale> flutter_locales;
@@ -261,8 +324,8 @@ void FlutterWindowsEngine::SendSystemSettings() {
261324
flutter_locales.begin(), flutter_locales.end(),
262325
std::back_inserter(flutter_locale_list),
263326
[](const auto& arg) -> const auto* { return &arg; });
264-
FlutterEngineUpdateLocales(engine_, flutter_locale_list.data(),
265-
flutter_locale_list.size());
327+
embedder_api_.UpdateLocales(engine_, flutter_locale_list.data(),
328+
flutter_locale_list.size());
266329

267330
// TODO: Send 'flutter/settings' channel settings here as well.
268331
}

shell/platform/windows/flutter_windows_engine.h

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <vector>
1212

1313
#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
14+
#include "flutter/shell/platform/embedder/embedder.h"
1415
#include "flutter/shell/platform/windows/flutter_project_bundle.h"
1516
#include "flutter/shell/platform/windows/public/flutter_windows.h"
1617
#include "flutter/shell/platform/windows/win32_task_runner.h"
@@ -65,8 +66,6 @@ class FlutterWindowsEngine {
6566
void SetPluginRegistrarDestructionCallback(
6667
FlutterDesktopOnPluginRegistrarDestroyed callback);
6768

68-
FLUTTER_API_SYMBOL(FlutterEngine) engine() { return engine_; }
69-
7069
FlutterDesktopMessengerRef messenger() { return messenger_.get(); }
7170

7271
IncomingMessageDispatcher* message_dispatcher() {
@@ -79,11 +78,37 @@ class FlutterWindowsEngine {
7978
return window_proc_delegate_manager_.get();
8079
}
8180

81+
// Informs the engine that the window metrics have changed.
82+
void SendWindowMetricsEvent(const FlutterWindowMetricsEvent& event);
83+
84+
// Informs the engine of an incoming pointer event.
85+
void SendPointerEvent(const FlutterPointerEvent& event);
86+
87+
// Sends the given message to the engine, calling |reply| with |user_data|
88+
// when a reponse is received from the engine if they are non-null.
89+
bool SendPlatformMessage(const char* channel,
90+
const uint8_t* message,
91+
const size_t message_size,
92+
const FlutterDesktopBinaryReply reply,
93+
void* user_data);
94+
95+
// Sends the given data as the response to an earlier platform message.
96+
void SendPlatformMessageResponse(
97+
const FlutterDesktopMessageResponseHandle* handle,
98+
const uint8_t* data,
99+
size_t data_length);
100+
82101
// Callback passed to Flutter engine for notifying window of platform
83102
// messages.
84103
void HandlePlatformMessage(const FlutterPlatformMessage*);
85104

105+
// Informs the engine that the system font list has changed.
106+
void ReloadSystemFonts();
107+
86108
private:
109+
// Allows swapping out embedder_api_ calls in tests.
110+
friend class EngineEmbedderApiModifier;
111+
87112
// Sends system settings (e.g., locale) to the engine.
88113
//
89114
// Should be called just after the engine is run, and after any relevant
@@ -93,6 +118,8 @@ class FlutterWindowsEngine {
93118
// The handle to the embedder.h engine instance.
94119
FLUTTER_API_SYMBOL(FlutterEngine) engine_ = nullptr;
95120

121+
FlutterEngineProcTable embedder_api_ = {};
122+
96123
std::unique_ptr<FlutterProjectBundle> project_;
97124

98125
// AOT data, if any.

0 commit comments

Comments
 (0)