Commit 060e8b40 authored by Adam Ettenberger's avatar Adam Ettenberger Committed by Commit Bot

Fix DCHECK in AXPlatformNodeTextRangeProviderWin::NormalizeTextRange

With Narrator and UIA enabled if the user navigates to the end of a
document, then the document is modified such that Narrator now has a
range whos |start_| or |end_| position is at the end or start of the
document respectively, |NormalizeTextRange| would have created a
NULL_POSITION for that range edge.

To avoid this, if there is no next/previous character for that edge
of the range, then that edge position will not be modified.

Bug: 1015593
Change-Id: If706057eaf533dfd0ab5e544eefd102d95ca767e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1869716Reviewed-by: default avatarKurt Catti-Schmidt <kschmi@microsoft.com>
Commit-Queue: Adam Ettenberger <adettenb@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#707573}
parent 8fe808b4
......@@ -1015,12 +1015,16 @@ void AXPlatformNodeTextRangeProviderWin::NormalizeTextRange() {
// Only normalize non-degenerate ranges.
if (*start_ != *end_) {
AXPositionInstance normalized_start = start_->AsPositionBeforeCharacter();
AXPositionInstance normalized_end = end_->AsPositionAfterCharacter();
DCHECK_EQ(*start_, *normalized_start);
DCHECK_EQ(*end_, *normalized_end);
if (!normalized_start->IsNullPosition()) {
DCHECK_EQ(*start_, *normalized_start);
start_ = std::move(normalized_start);
}
start_ = std::move(normalized_start);
end_ = std::move(normalized_end);
AXPositionInstance normalized_end = end_->AsPositionAfterCharacter();
if (!normalized_end->IsNullPosition()) {
DCHECK_EQ(*end_, *normalized_end);
end_ = std::move(normalized_end);
}
}
}
......
......@@ -196,6 +196,10 @@ class AXPlatformNodeTextRangeProviderTest : public ui::AXPlatformNodeWinTest {
return text_range->owner_;
}
void NormalizeTextRange(AXPlatformNodeTextRangeProviderWin* text_range) {
text_range->NormalizeTextRange();
}
void GetTextRangeProviderFromTextNode(
ComPtr<ITextRangeProvider>& text_range_provider,
ui::AXNode* text_node) {
......@@ -4501,4 +4505,118 @@ TEST_F(AXPlatformNodeTextRangeProviderTest,
/*expected_count*/ 12);
}
TEST_F(AXPlatformNodeTextRangeProviderTest,
TestNormalizeTextRangePastEndOfDocument) {
ui::AXTreeUpdate initial_state;
ui::AXTreeID tree_id = ui::AXTreeID::CreateNewAXTreeID();
initial_state.tree_data.tree_id = tree_id;
initial_state.has_tree_data = true;
initial_state.root_id = 1;
initial_state.nodes.resize(3);
initial_state.nodes[0].id = 1;
initial_state.nodes[0].child_ids = {2};
initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
initial_state.nodes[1].id = 2;
initial_state.nodes[1].child_ids = {3};
initial_state.nodes[1].role = ax::mojom::Role::kStaticText;
initial_state.nodes[1].SetName("aaa");
initial_state.nodes[2].id = 3;
initial_state.nodes[2].role = ax::mojom::Role::kInlineTextBox;
initial_state.nodes[2].SetName("aaa");
Init(initial_state);
AXNodePosition::SetTree(tree_.get());
ComPtr<ITextRangeProvider> text_range_provider;
GetTextRangeProviderFromTextNode(text_range_provider,
GetNodeFromTree(tree_id, 3));
EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"aaa");
EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Character,
/*count*/ 2,
/*expected_text*/ L"a",
/*expected_count*/ 2);
ComPtr<AXPlatformNodeTextRangeProviderWin> text_range_provider_win;
text_range_provider->QueryInterface(IID_PPV_ARGS(&text_range_provider_win));
const AXNodePosition::AXPositionInstance start_after_move =
GetStart(text_range_provider_win.Get())->Clone();
const AXNodePosition::AXPositionInstance end_after_move =
GetEnd(text_range_provider_win.Get())->Clone();
EXPECT_LT(*start_after_move, *end_after_move);
AXTreeUpdate update;
update.nodes.resize(2);
update.nodes[0] = initial_state.nodes[1];
update.nodes[0].SetName("aa");
update.nodes[1] = initial_state.nodes[2];
update.nodes[1].SetName("aa");
ASSERT_TRUE(tree_->Unserialize(update));
NormalizeTextRange(text_range_provider_win.Get());
EXPECT_EQ(*start_after_move, *GetStart(text_range_provider_win.Get()));
EXPECT_EQ(*end_after_move, *GetEnd(text_range_provider_win.Get()));
}
TEST_F(AXPlatformNodeTextRangeProviderTest,
TestNormalizeTextRangePastEndOfDocumentWithIgnoredNodes) {
ui::AXTreeUpdate initial_state;
ui::AXTreeID tree_id = ui::AXTreeID::CreateNewAXTreeID();
initial_state.tree_data.tree_id = tree_id;
initial_state.has_tree_data = true;
initial_state.root_id = 1;
initial_state.nodes.resize(4);
initial_state.nodes[0].id = 1;
initial_state.nodes[0].child_ids = {2};
initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
initial_state.nodes[1].id = 2;
initial_state.nodes[1].child_ids = {3, 4};
initial_state.nodes[1].role = ax::mojom::Role::kStaticText;
initial_state.nodes[1].SetName("aaa");
initial_state.nodes[2].id = 3;
initial_state.nodes[2].role = ax::mojom::Role::kInlineTextBox;
initial_state.nodes[2].SetName("aaa");
initial_state.nodes[3].id = 4;
initial_state.nodes[3].role = ax::mojom::Role::kInlineTextBox;
initial_state.nodes[3].AddState(ax::mojom::State::kIgnored);
initial_state.nodes[3].SetName("ignored");
Init(initial_state);
AXNodePosition::SetTree(tree_.get());
ComPtr<ITextRangeProvider> text_range_provider;
GetTextRangeProviderFromTextNode(text_range_provider,
GetNodeFromTree(tree_id, 3));
EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"aaa");
EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Character,
/*count*/ 2,
/*expected_text*/ L"a",
/*expected_count*/ 2);
ComPtr<AXPlatformNodeTextRangeProviderWin> text_range_provider_win;
text_range_provider->QueryInterface(IID_PPV_ARGS(&text_range_provider_win));
const AXNodePosition::AXPositionInstance start_after_move =
GetStart(text_range_provider_win.Get())->Clone();
const AXNodePosition::AXPositionInstance end_after_move =
GetEnd(text_range_provider_win.Get())->Clone();
EXPECT_LT(*start_after_move, *end_after_move);
AXTreeUpdate update;
update.nodes.resize(2);
update.nodes[0] = initial_state.nodes[1];
update.nodes[0].SetName("aa");
update.nodes[1] = initial_state.nodes[2];
update.nodes[1].SetName("aa");
ASSERT_TRUE(tree_->Unserialize(update));
NormalizeTextRange(text_range_provider_win.Get());
EXPECT_EQ(*start_after_move, *GetStart(text_range_provider_win.Get()));
EXPECT_EQ(*end_after_move, *GetEnd(text_range_provider_win.Get()));
}
} // namespace ui
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment