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

Extract WideToUTF16String/UTF16StringToWide to FML #39006

Merged
merged 2 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 12 additions & 0 deletions fml/platform/win/wstring_conversion.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,16 @@ std::wstring Utf8ToWideString(const std::string_view str) {
return converter.from_bytes(str.data());
}

std::u16string WideStringToUtf16(const std::wstring_view str) {
static_assert(sizeof(std::wstring::value_type) ==
sizeof(std::u16string::value_type));
return {begin(str), end(str)};
}

std::wstring Utf16ToWideString(const std::u16string_view str) {
static_assert(sizeof(std::wstring::value_type) ==
sizeof(std::u16string::value_type));
return {begin(str), end(str)};
}

} // namespace fml
6 changes: 6 additions & 0 deletions fml/platform/win/wstring_conversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ std::string WideStringToUtf8(const std::wstring_view str);
// string.
std::wstring Utf8ToWideString(const std::string_view str);

// Returns a UTF-16 encoded equivalent of a UTF-16 encoded wide string.
std::u16string WideStringToUtf16(const std::wstring_view str);

// Returns a UTF-16 encoded wide string equivalent of a UTF-16 string.
std::wstring Utf16ToWideString(const std::u16string_view str);

} // namespace fml

#endif // FLUTTER_FML_PLATFORM_WIN_WSTRING_CONVERSION_H_
24 changes: 24 additions & 0 deletions fml/platform/win/wstring_conversion_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,29 @@ TEST(StringConversion, WideStringToUtf8Unicode) {
EXPECT_EQ(WideStringToUtf8(L"\x2603"), "\xe2\x98\x83");
}

TEST(StringConversion, WideStringToUtf16Empty) {
EXPECT_EQ(WideStringToUtf16(L""), u"");
}

TEST(StringConversion, WideStringToUtf16Ascii) {
EXPECT_EQ(WideStringToUtf16(L"abc123"), u"abc123");
}

TEST(StringConversion, WideStringToUtf16Unicode) {
EXPECT_EQ(WideStringToUtf16(L"\xe2\x98\x83"), u"\x2603");
}

TEST(StringConversion, Utf16ToWideStringEmpty) {
EXPECT_EQ(Utf16ToWideString(u""), L"");
}

TEST(StringConversion, Utf16ToWideStringAscii) {
EXPECT_EQ(Utf16ToWideString(u"abc123"), L"abc123");
}

TEST(StringConversion, Utf16ToWideStringUtf8Unicode) {
EXPECT_EQ(Utf16ToWideString(u"\x2603"), L"\xe2\x98\x83");
}

} // namespace testing
} // namespace fml
1 change: 1 addition & 0 deletions third_party/accessibility/ax/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ source_set("ax") {
"oleacc.lib",
"uiautomationcore.lib",
]
deps = [ "//flutter/fml:string_conversion" ]
}

public_deps = [
Expand Down
57 changes: 27 additions & 30 deletions third_party/accessibility/ax/ax_node_position_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "ax/ax_tree_id.h"
#include "ax/ax_tree_update.h"
#include "ax/test_ax_tree_manager.h"
#include "flutter/fml/platform/win/wstring_conversion.h"
#include "gtest/gtest.h"

namespace ui {
Expand All @@ -28,10 +29,6 @@ using TestPositionRange = AXRange<AXPosition<AXNodePosition, AXNode>>;

namespace {

std::u16string WideToUTF16(const std::wstring wide) {
return std::u16string(wide.begin(), wide.end());
}

constexpr AXNode::AXID ROOT_ID = 1;
constexpr AXNode::AXID BUTTON_ID = 2;
constexpr AXNode::AXID CHECK_BOX_ID = 3;
Expand All @@ -43,20 +40,20 @@ constexpr AXNode::AXID STATIC_TEXT2_ID = 8;
constexpr AXNode::AXID INLINE_BOX2_ID = 9;

// A group of basic and extended characters.
constexpr const wchar_t* kGraphemeClusters[] = {
constexpr const char16_t* kGraphemeClusters[] = {
// The English word "hey" consisting of four ASCII characters.
L"h",
L"e",
L"y",
u"h",
u"e",
u"y",
// A Hindi word (which means "Hindi") consisting of two Devanagari
// grapheme clusters.
L"\x0939\x093F",
L"\x0928\x094D\x0926\x0940",
u"\x0939\x093F",
u"\x0928\x094D\x0926\x0940",
// A Thai word (which means "feel") consisting of three Thai grapheme
// clusters.
L"\x0E23\x0E39\x0E49",
L"\x0E2A\x0E36",
L"\x0E01",
u"\x0E23\x0E39\x0E49",
u"\x0E2A\x0E36",
u"\x0E01",
};

class AXPositionTest : public testing::Test, public TestAXTreeManager {
Expand Down Expand Up @@ -419,7 +416,7 @@ std::unique_ptr<AXTree> AXPositionTest::CreateMultilingualDocument(

std::u16string english_text;
for (int i = 0; i < 3; ++i) {
std::u16string grapheme = WideToUTF16(kGraphemeClusters[i]);
std::u16string grapheme = kGraphemeClusters[i];
EXPECT_EQ(1u, grapheme.length())
<< "All English characters should be one UTF16 code unit in length.";
text_offsets->push_back(text_offsets->back() +
Expand All @@ -429,7 +426,7 @@ std::unique_ptr<AXTree> AXPositionTest::CreateMultilingualDocument(

std::u16string hindi_text;
for (int i = 3; i < 5; ++i) {
std::u16string grapheme = WideToUTF16(kGraphemeClusters[i]);
std::u16string grapheme = kGraphemeClusters[i];
EXPECT_LE(2u, grapheme.length()) << "All Hindi characters should be two "
"or more UTF16 code units in length.";
text_offsets->push_back(text_offsets->back() +
Expand All @@ -439,7 +436,7 @@ std::unique_ptr<AXTree> AXPositionTest::CreateMultilingualDocument(

std::u16string thai_text;
for (int i = 5; i < 8; ++i) {
std::u16string grapheme = WideToUTF16(kGraphemeClusters[i]);
std::u16string grapheme = kGraphemeClusters[i];
EXPECT_LT(0u, grapheme.length())
<< "One of the Thai characters should be one UTF16 code unit, "
"whilst others should be two or more.";
Expand Down Expand Up @@ -618,7 +615,7 @@ TEST_F(AXPositionTest, ToString) {
AXNodeData static_text_data_2;
static_text_data_2.id = 3;
static_text_data_2.role = ax::mojom::Role::kStaticText;
static_text_data_2.SetName(WideToUTF16(L"\xfffc"));
static_text_data_2.SetName(u"\xfffc");

AXNodeData static_text_data_3;
static_text_data_3.id = 4;
Expand Down Expand Up @@ -876,7 +873,7 @@ TEST_F(AXPositionTest, GetTextFromNullPosition) {
TestPositionType text_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsNullPosition());
ASSERT_EQ(WideToUTF16(L""), text_position->GetText());
ASSERT_EQ(u"", text_position->GetText());
}

TEST_F(AXPositionTest, GetTextFromRoot) {
Expand All @@ -885,7 +882,7 @@ TEST_F(AXPositionTest, GetTextFromRoot) {
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(WideToUTF16(L"Line 1\nLine 2"), text_position->GetText());
ASSERT_EQ(u"Line 1\nLine 2", text_position->GetText());
}

TEST_F(AXPositionTest, GetTextFromButton) {
Expand All @@ -894,7 +891,7 @@ TEST_F(AXPositionTest, GetTextFromButton) {
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(WideToUTF16(L""), text_position->GetText());
ASSERT_EQ(u"", text_position->GetText());
}

TEST_F(AXPositionTest, GetTextFromCheckbox) {
Expand All @@ -903,7 +900,7 @@ TEST_F(AXPositionTest, GetTextFromCheckbox) {
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(WideToUTF16(L""), text_position->GetText());
ASSERT_EQ(u"", text_position->GetText());
}

TEST_F(AXPositionTest, GetTextFromTextField) {
Expand All @@ -912,7 +909,7 @@ TEST_F(AXPositionTest, GetTextFromTextField) {
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(WideToUTF16(L"Line 1\nLine 2"), text_position->GetText());
ASSERT_EQ(u"Line 1\nLine 2", text_position->GetText());
}

TEST_F(AXPositionTest, GetTextFromStaticText) {
Expand All @@ -921,7 +918,7 @@ TEST_F(AXPositionTest, GetTextFromStaticText) {
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(WideToUTF16(L"Line 1"), text_position->GetText());
ASSERT_EQ(u"Line 1", text_position->GetText());
}

TEST_F(AXPositionTest, GetTextFromInlineTextBox) {
Expand All @@ -930,7 +927,7 @@ TEST_F(AXPositionTest, GetTextFromInlineTextBox) {
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(WideToUTF16(L"Line 1"), text_position->GetText());
ASSERT_EQ(u"Line 1", text_position->GetText());
}

TEST_F(AXPositionTest, GetTextFromLineBreak) {
Expand All @@ -939,7 +936,7 @@ TEST_F(AXPositionTest, GetTextFromLineBreak) {
ax::mojom::TextAffinity::kUpstream);
ASSERT_NE(nullptr, text_position);
ASSERT_TRUE(text_position->IsTextPosition());
ASSERT_EQ(WideToUTF16(L"\n"), text_position->GetText());
ASSERT_EQ(u"\n", text_position->GetText());
}

TEST_F(AXPositionTest, GetMaxTextOffsetFromNullPosition) {
Expand Down Expand Up @@ -1106,7 +1103,7 @@ TEST_F(AXPositionTest, GetMaxTextOffsetAndGetTextWithGeneratedContent) {
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->IsTextPosition());
EXPECT_EQ(38, text_position->MaxTextOffset());
EXPECT_EQ(WideToUTF16(L"Placeholder from generated content3.14"),
EXPECT_EQ(u"Placeholder from generated content3.14",
text_position->GetText());
}

Expand Down Expand Up @@ -7712,10 +7709,10 @@ TEST_F(AXPositionTest, EmptyObjectReplacedByCharacterTextNavigation) {
GetTreeID(), root_1.id, 0 /* text_offset */,
ax::mojom::TextAffinity::kDownstream);

expected_text = WideToUTF16(L"Hello ") + AXNodePosition::kEmbeddedCharacter +
WideToUTF16(L" world3.14") +
AXNodePosition::kEmbeddedCharacter + WideToUTF16(L"hey") +
AXNodePosition::kEmbeddedCharacter;
expected_text =
std::u16string(u"Hello ") + AXNodePosition::kEmbeddedCharacter +
std::u16string(u" world3.14") + AXNodePosition::kEmbeddedCharacter +
std::u16string(u"hey") + AXNodePosition::kEmbeddedCharacter;
ASSERT_EQ(expected_text, position->GetText());

// MaxTextOffset() with an embedded object replacement character.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ TEST_F(AXPlatformNodeTextProviderTest,
base::win::ScopedBstr text_content;
EXPECT_HRESULT_SUCCEEDED(
text_range_provider->GetText(-1, text_content.Receive()));
EXPECT_EQ(base::WideToUTF16(text_content.Get()),
EXPECT_EQ(fml::WideStringToUtf16(text_content.Get()),
u"Dialog label.Dialog description." + kEmbeddedCharacterAsString +
u"ok.Some more detail " + u"about dialog.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ax/platform/ax_platform_node_win.h"
#include "ax/platform/ax_platform_tree_manager.h"
#include "base/win/variant_vector.h"
#include "flutter/fml/platform/win/wstring_conversion.h"

#define UIA_VALIDATE_TEXTRANGEPROVIDER_CALL() \
if (!GetOwner() || !GetOwner()->GetDelegate() || !start() || \
Expand Down Expand Up @@ -483,7 +484,7 @@ HRESULT AXPlatformNodeTextRangeProviderWin::FindText(
ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior(
AXEmbeddedObjectBehavior::kSuppressCharacter);

std::u16string search_string = base::WideToUTF16(string);
std::u16string search_string = fml::WideStringToUtf16(string);
if (search_string.length() <= 0)
return E_INVALIDARG;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "base/logging.h"
#include "base/win/atl_module.h"
#include "base/win/display.h"
#include "flutter/fml/platform/win/wstring_conversion.h"
#include "gfx/geometry/rect_conversions.h"

// From ax.constants.mojom
Expand Down Expand Up @@ -1739,7 +1740,7 @@ IFACEMETHODIMP AXPlatformNodeWin::SetValue(LPCWSTR value) {

AXActionData data;
data.action = ax::mojom::Action::kSetValue;
data.value = base::UTF16ToUTF8(base::WideToUTF16(value));
data.value = base::UTF16ToUTF8(fml::WideStringToUtf16(value));
if (GetDelegate()->AccessibilityPerformAction(data))
return S_OK;
return E_FAIL;
Expand Down