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
4 changes: 0 additions & 4 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -3230,8 +3230,6 @@ ORIGIN: ../../../flutter/shell/platform/windows/windows_lifecycle_manager.cc + .
ORIGIN: ../../../flutter/shell/platform/windows/windows_lifecycle_manager.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/windows/windows_proc_table.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/windows/windows_proc_table.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/windows/windows_registry.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/windows/windows_registry.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/windows/windowsx_shim.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/profiling/sampling_profiler.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/profiling/sampling_profiler.h + ../../../flutter/LICENSE
Expand Down Expand Up @@ -5928,8 +5926,6 @@ FILE: ../../../flutter/shell/platform/windows/windows_lifecycle_manager.cc
FILE: ../../../flutter/shell/platform/windows/windows_lifecycle_manager.h
FILE: ../../../flutter/shell/platform/windows/windows_proc_table.cc
FILE: ../../../flutter/shell/platform/windows/windows_proc_table.h
FILE: ../../../flutter/shell/platform/windows/windows_registry.cc
FILE: ../../../flutter/shell/platform/windows/windows_registry.h
FILE: ../../../flutter/shell/platform/windows/windowsx_shim.h
FILE: ../../../flutter/shell/profiling/sampling_profiler.cc
FILE: ../../../flutter/shell/profiling/sampling_profiler.h
Expand Down
2 changes: 0 additions & 2 deletions shell/platform/windows/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ source_set("flutter_windows_source") {
"windows_lifecycle_manager.h",
"windows_proc_table.cc",
"windows_proc_table.h",
"windows_registry.cc",
"windows_registry.h",
"windowsx_shim.h",
]

Expand Down
7 changes: 2 additions & 5 deletions shell/platform/windows/flutter_windows_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,9 @@ FlutterLocale CovertToFlutterLocale(const LanguageInfo& info) {

} // namespace

FlutterWindowsEngine::FlutterWindowsEngine(
const FlutterProjectBundle& project,
std::unique_ptr<WindowsRegistry> registry)
FlutterWindowsEngine::FlutterWindowsEngine(const FlutterProjectBundle& project)
: project_(std::make_unique<FlutterProjectBundle>(project)),
aot_data_(nullptr, nullptr),
windows_registry_(std::move(registry)),
lifecycle_manager_(std::make_unique<WindowsLifecycleManager>(this)) {
embedder_api_.struct_size = sizeof(FlutterEngineProcTable);
FlutterEngineGetProcAddresses(&embedder_api_);
Expand Down Expand Up @@ -572,7 +569,7 @@ void FlutterWindowsEngine::SetLifecycleState(flutter::AppLifecycleState state) {

void FlutterWindowsEngine::SendSystemLocales() {
std::vector<LanguageInfo> languages =
GetPreferredLanguageInfo(*windows_registry_);
GetPreferredLanguageInfo(windows_proc_table_);
std::vector<FlutterLocale> flutter_locales;
flutter_locales.reserve(languages.size());
for (const auto& info : languages) {
Expand Down
14 changes: 4 additions & 10 deletions shell/platform/windows/flutter_windows_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#include "flutter/shell/platform/windows/window_proc_delegate_manager.h"
#include "flutter/shell/platform/windows/window_state.h"
#include "flutter/shell/platform/windows/windows_lifecycle_manager.h"
#include "flutter/shell/platform/windows/windows_registry.h"
#include "flutter/shell/platform/windows/windows_proc_table.h"
#include "third_party/rapidjson/include/rapidjson/document.h"

namespace flutter {
Expand Down Expand Up @@ -77,13 +77,8 @@ static void WindowsPlatformThreadPrioritySetter(
// run in headless mode.
class FlutterWindowsEngine {
public:
// Creates a new Flutter engine with an injectible windows registry.
FlutterWindowsEngine(const FlutterProjectBundle& project,
std::unique_ptr<WindowsRegistry> windows_registry);

// Creates a new Flutter engine object configured to run |project|.
explicit FlutterWindowsEngine(const FlutterProjectBundle& project)
: FlutterWindowsEngine(project, std::make_unique<WindowsRegistry>()) {}
explicit FlutterWindowsEngine(const FlutterProjectBundle& project);

virtual ~FlutterWindowsEngine();

Expand Down Expand Up @@ -405,12 +400,11 @@ class FlutterWindowsEngine {
// The on frame drawn callback.
fml::closure next_frame_callback_;

// Wrapper providing Windows registry access.
std::unique_ptr<WindowsRegistry> windows_registry_;

// Handler for top level window messages.
std::unique_ptr<WindowsLifecycleManager> lifecycle_manager_;

WindowsProcTable windows_proc_table_;

FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsEngine);
};

Expand Down
57 changes: 12 additions & 45 deletions shell/platform/windows/system_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
namespace flutter {

std::vector<LanguageInfo> GetPreferredLanguageInfo(
const WindowsRegistry& registry) {
std::vector<std::wstring> languages = GetPreferredLanguages(registry);
const WindowsProcTable& windows_proc_table) {
std::vector<std::wstring> languages =
GetPreferredLanguages(windows_proc_table);
std::vector<LanguageInfo> language_info;
language_info.reserve(languages.size());

Expand All @@ -24,63 +25,29 @@ std::vector<LanguageInfo> GetPreferredLanguageInfo(
return language_info;
}

std::wstring GetPreferredLanguagesFromRegistry(const WindowsRegistry& registry,
ULONG buffer_size) {
std::wstring buffer(buffer_size, '\0');
if (registry.GetRegistryValue(HKEY_CURRENT_USER, kGetPreferredLanguageRegKey,
kGetPreferredLanguageRegValue,
RRF_RT_REG_MULTI_SZ, NULL, buffer.data(),
&buffer_size) != ERROR_SUCCESS) {
return std::wstring();
}
return buffer;
}

std::wstring GetPreferredLanguagesFromMUI() {
ULONG buffer_size;
std::wstring GetPreferredLanguagesFromMUI(
const WindowsProcTable& windows_proc_table) {
ULONG buffer_size = 0;
ULONG count = 0;
DWORD flags = MUI_LANGUAGE_NAME | MUI_UI_FALLBACK;
if (!GetThreadPreferredUILanguages(flags, &count, nullptr, &buffer_size)) {
if (!windows_proc_table.GetThreadPreferredUILanguages(flags, &count, nullptr,
&buffer_size)) {
return std::wstring();
}
std::wstring buffer(buffer_size, '\0');
if (!GetThreadPreferredUILanguages(flags, &count, buffer.data(),
&buffer_size)) {
if (!windows_proc_table.GetThreadPreferredUILanguages(
flags, &count, buffer.data(), &buffer_size)) {
return std::wstring();
}
return buffer;
}

std::vector<std::wstring> GetPreferredLanguages(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now have no more use for GetPreferredLanguagesFromRegistry. Should we remove the function altogether?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please remove this. If needed, we can always use git's history to resurrect the code.

const WindowsRegistry& registry) {
const WindowsProcTable& windows_proc_table) {
std::vector<std::wstring> languages;
BOOL languages_from_registry = TRUE;
ULONG buffer_size = 0;
ULONG count = 0;
DWORD flags = MUI_LANGUAGE_NAME | MUI_UI_FALLBACK;

// Determine where languages are defined and get buffer length
if (registry.GetRegistryValue(HKEY_CURRENT_USER, kGetPreferredLanguageRegKey,
kGetPreferredLanguageRegValue,
RRF_RT_REG_MULTI_SZ, NULL, NULL,
&buffer_size) != ERROR_SUCCESS) {
languages_from_registry = FALSE;
}

// Multi-string must be at least 3-long if non-empty,
// as a multi-string is terminated with 2 nulls.
//
// See:
// https://learn.microsoft.com/windows/win32/sysinfo/registry-value-types
if (languages_from_registry && buffer_size < 3) {
languages_from_registry = FALSE;
}

// Initialize the buffer
std::wstring buffer =
languages_from_registry
? GetPreferredLanguagesFromRegistry(registry, buffer_size)
: GetPreferredLanguagesFromMUI();
std::wstring buffer = GetPreferredLanguagesFromMUI(windows_proc_table);

// Extract the individual languages from the buffer.
size_t start = 0;
Expand Down
13 changes: 5 additions & 8 deletions shell/platform/windows/system_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <string>
#include <vector>

#include "flutter/shell/platform/windows/windows_registry.h"
#include "flutter/shell/platform/windows/windows_proc_table.h"

namespace flutter {

Expand All @@ -29,20 +29,17 @@ struct LanguageInfo {
// Returns the list of user-preferred languages, in preference order,
// parsed into LanguageInfo structures.
std::vector<LanguageInfo> GetPreferredLanguageInfo(
const WindowsRegistry& registry);

// Retrieve the preferred languages from the registry.
std::wstring GetPreferredLanguagesFromRegistry(const WindowsRegistry& registry,
ULONG buffer_size);
const WindowsProcTable& windows_proc_table);

// Retrieve the preferred languages from the MUI API.
std::wstring GetPreferredLanguagesFromMUI();
std::wstring GetPreferredLanguagesFromMUI(
const WindowsProcTable& windows_proc_table);

// Returns the list of user-preferred languages, in preference order.
// The language names are as described at:
// https://docs.microsoft.com/en-us/windows/win32/intl/language-names
std::vector<std::wstring> GetPreferredLanguages(
const WindowsRegistry& registry);
const WindowsProcTable& windows_proc_table);

// Parses a Windows language name into its components.
LanguageInfo ParseLanguageName(std::wstring language_name);
Expand Down
68 changes: 22 additions & 46 deletions shell/platform/windows/system_utils_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,71 +7,47 @@

#include "flutter/fml/macros.h"
#include "flutter/shell/platform/windows/system_utils.h"
#include "flutter/shell/platform/windows/testing/mock_windows_proc_table.h"
#include "gtest/gtest.h"

namespace flutter {
namespace testing {

class MockWindowsRegistry : public WindowsRegistry {
public:
MockWindowsRegistry() = default;
virtual ~MockWindowsRegistry() = default;

virtual LSTATUS GetRegistryValue(HKEY hkey,
LPCWSTR key,
LPCWSTR value,
DWORD flags,
LPDWORD type,
PVOID data,
LPDWORD data_size) const {
using namespace std::string_literals;
static const std::wstring locales =
L"en-US\0zh-Hans-CN\0ja\0zh-Hant-TW\0he\0\0"s;
static DWORD locales_len = locales.size() * sizeof(wchar_t);
if (data != nullptr) {
if (*data_size < locales_len) {
return ERROR_MORE_DATA;
}
std::memcpy(data, locales.data(), locales_len);
*data_size = locales_len;
} else if (data_size != NULL) {
*data_size = locales_len;
}
return ERROR_SUCCESS;
}

private:
FML_DISALLOW_COPY_AND_ASSIGN(MockWindowsRegistry);
};

TEST(SystemUtils, GetPreferredLanguageInfo) {
WindowsRegistry registry;
std::vector<LanguageInfo> languages = GetPreferredLanguageInfo(registry);
WindowsProcTable proc_table;
std::vector<LanguageInfo> languages =
GetPreferredLanguageInfo(WindowsProcTable());
// There should be at least one language.
ASSERT_GE(languages.size(), 1);
// The info should have a valid languge.
EXPECT_GE(languages[0].language.size(), 2);
}

TEST(SystemUtils, GetPreferredLanguages) {
WindowsRegistry registry;
std::vector<std::wstring> languages = GetPreferredLanguages(registry);
MockWindowsProcTable proc_table;
ON_CALL(proc_table, GetThreadPreferredUILanguages)
.WillByDefault(
[](DWORD flags, PULONG count, PZZWSTR languages, PULONG size) {
// Languages string ends in a double-null.
static const wchar_t lang[] = L"en-US\0";
static const size_t lang_len = sizeof(lang) / sizeof(wchar_t);
static const int cnt = 1;
if (languages == nullptr) {
*size = lang_len;
*count = cnt;
} else if (*size >= lang_len) {
memcpy(languages, lang, lang_len * sizeof(wchar_t));
}
return TRUE;
});
std::vector<std::wstring> languages = GetPreferredLanguages(proc_table);
// There should be at least one language.
ASSERT_GE(languages.size(), 1);
// The language should be non-empty.
EXPECT_FALSE(languages[0].empty());
// There should not be a trailing null from the parsing step.
EXPECT_EQ(languages[0].size(), wcslen(languages[0].c_str()));

// Test mock results
MockWindowsRegistry mock_registry;
languages = GetPreferredLanguages(mock_registry);
ASSERT_EQ(languages.size(), 5);
ASSERT_EQ(languages[0], std::wstring(L"en-US"));
ASSERT_EQ(languages[1], std::wstring(L"zh-Hans-CN"));
ASSERT_EQ(languages[2], std::wstring(L"ja"));
ASSERT_EQ(languages[3], std::wstring(L"zh-Hant-TW"));
ASSERT_EQ(languages[4], std::wstring(L"he"));
EXPECT_EQ(languages[0], L"en-US");
}

TEST(SystemUtils, ParseLanguageNameGeneric) {
Expand Down
3 changes: 3 additions & 0 deletions shell/platform/windows/testing/mock_windows_proc_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class MockWindowsProcTable : public WindowsProcTable {
MOCK_METHOD2(GetPointerType,
BOOL(UINT32 pointer_id, POINTER_INPUT_TYPE* pointer_type));

MOCK_CONST_METHOD4(GetThreadPreferredUILanguages,
LRESULT(DWORD, PULONG, PZZWSTR, PULONG));

private:
FML_DISALLOW_COPY_AND_ASSIGN(MockWindowsProcTable);
};
Expand Down
7 changes: 7 additions & 0 deletions shell/platform/windows/windows_proc_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,11 @@ BOOL WindowsProcTable::GetPointerType(UINT32 pointer_id,
return get_pointer_type_.value()(pointer_id, pointer_type);
}

LRESULT WindowsProcTable::GetThreadPreferredUILanguages(DWORD flags,
PULONG count,
PZZWSTR languages,
PULONG length) const {
return ::GetThreadPreferredUILanguages(flags, count, languages, length);
}

} // namespace flutter
11 changes: 10 additions & 1 deletion shell/platform/windows/windows_proc_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace flutter {

// Lookup table for Windows APIs that aren't available on all versions of
// Windows.
// Windows, or for mocking Windows API calls.
class WindowsProcTable {
public:
WindowsProcTable();
Expand All @@ -26,6 +26,15 @@ class WindowsProcTable {
virtual BOOL GetPointerType(UINT32 pointer_id,
POINTER_INPUT_TYPE* pointer_type);

// Get the preferred languages for the thread, and optionally the process,
// and system, in that order, depending on the flags.
// See
// https://learn.microsoft.com/windows/win32/api/winnls/nf-winnls-getthreadpreferreduilanguages
virtual LRESULT GetThreadPreferredUILanguages(DWORD flags,
PULONG count,
PZZWSTR languages,
PULONG length) const;

private:
using GetPointerType_ = BOOL __stdcall(UINT32 pointerId,
POINTER_INPUT_TYPE* pointerType);
Expand Down
19 changes: 0 additions & 19 deletions shell/platform/windows/windows_registry.cc

This file was deleted.

Loading