Commit 9cfec76a authored by Hiroki Sato's avatar Hiroki Sato Committed by Commit Bot

Do not set textField role from its class name

AccessibilityNodeInfoDataWrapper::PopulateAXRole assigns a Chrome role
to each node, and the last logic to decide a role is using an Android
class name.

Some Android app disguise its class name to control what TalkBack
announces. This is sometimes helpful, but may break ChromeVox
navigation.

Gmail has a header which ax tree looks like below:
++ textField [Search mail]
++++ button [Open navigation drawer]
++++ genericContainer [Compose]
++++ genericContainer [Open account menu]
The root of this is assigned textField role from its className.
Clicking the node opens the input field, so that role should not be
textField.
(Note that these four nodes are all clickable.)

This change deletes EditText from the map of className to Chrome role.
Even after changing this, as normal textFields have editable property,
their role is populated correctly.

Bug: b/150827734
Test: unit_tests --gtest_filter="AXTreeSourceArcTest.*"
Test: manual. Open Gmail, and OpenSearchBar is correctly focused.
Change-Id: I7d0f867ba842585d7c222b9f96edfd958e5ad90d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2104743Reviewed-by: default avatarSara Kato <sarakato@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Commit-Queue: Hiroki Sato <hirokisato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751321}
parent b8530cca
...@@ -208,13 +208,13 @@ void AccessibilityNodeInfoDataWrapper::PopulateAXRole( ...@@ -208,13 +208,13 @@ void AccessibilityNodeInfoDataWrapper::PopulateAXRole(
// These mappings were taken from accessibility utils (Android -> Chrome) and // These mappings were taken from accessibility utils (Android -> Chrome) and
// BrowserAccessibilityAndroid. They do not completely match the above two // BrowserAccessibilityAndroid. They do not completely match the above two
// sources. // sources.
// EditText is excluded because it can be a container (b/150827734).
MAP_ROLE(ui::kAXAbsListViewClassname, ax::mojom::Role::kList); MAP_ROLE(ui::kAXAbsListViewClassname, ax::mojom::Role::kList);
MAP_ROLE(ui::kAXButtonClassname, ax::mojom::Role::kButton); MAP_ROLE(ui::kAXButtonClassname, ax::mojom::Role::kButton);
MAP_ROLE(ui::kAXCheckBoxClassname, ax::mojom::Role::kCheckBox); MAP_ROLE(ui::kAXCheckBoxClassname, ax::mojom::Role::kCheckBox);
MAP_ROLE(ui::kAXCheckedTextViewClassname, ax::mojom::Role::kStaticText); MAP_ROLE(ui::kAXCheckedTextViewClassname, ax::mojom::Role::kStaticText);
MAP_ROLE(ui::kAXCompoundButtonClassname, ax::mojom::Role::kCheckBox); MAP_ROLE(ui::kAXCompoundButtonClassname, ax::mojom::Role::kCheckBox);
MAP_ROLE(ui::kAXDialogClassname, ax::mojom::Role::kDialog); MAP_ROLE(ui::kAXDialogClassname, ax::mojom::Role::kDialog);
MAP_ROLE(ui::kAXEditTextClassname, ax::mojom::Role::kTextField);
MAP_ROLE(ui::kAXGridViewClassname, ax::mojom::Role::kTable); MAP_ROLE(ui::kAXGridViewClassname, ax::mojom::Role::kTable);
MAP_ROLE(ui::kAXHorizontalScrollViewClassname, ax::mojom::Role::kScrollView); MAP_ROLE(ui::kAXHorizontalScrollViewClassname, ax::mojom::Role::kScrollView);
MAP_ROLE(ui::kAXImageClassname, ax::mojom::Role::kImage); MAP_ROLE(ui::kAXImageClassname, ax::mojom::Role::kImage);
...@@ -242,7 +242,9 @@ void AccessibilityNodeInfoDataWrapper::PopulateAXRole( ...@@ -242,7 +242,9 @@ void AccessibilityNodeInfoDataWrapper::PopulateAXRole(
std::string text; std::string text;
GetProperty(AXStringProperty::TEXT, &text); GetProperty(AXStringProperty::TEXT, &text);
if (!text.empty()) std::vector<AccessibilityInfoDataWrapper*> children;
GetChildren(&children);
if (!text.empty() && children.empty())
out_data->role = ax::mojom::Role::kStaticText; out_data->role = ax::mojom::Role::kStaticText;
else else
out_data->role = ax::mojom::Role::kGenericContainer; out_data->role = ax::mojom::Role::kGenericContainer;
......
...@@ -817,6 +817,54 @@ TEST_F(AXTreeSourceArcTest, StateComputations) { ...@@ -817,6 +817,54 @@ TEST_F(AXTreeSourceArcTest, StateComputations) {
EXPECT_TRUE(data->HasState(ax::mojom::State::kExpanded)); EXPECT_TRUE(data->HasState(ax::mojom::State::kExpanded));
} }
TEST_F(AXTreeSourceArcTest, RoleComputationEditText) {
auto event = AXEventData::New();
event->source_id = 1;
event->task_id = 1;
event->event_type = AXEventType::VIEW_FOCUSED;
event->node_data.push_back(AXNodeInfoData::New());
AXNodeInfoData* root = event->node_data.back().get();
SetProperty(root, AXIntListProperty::CHILD_NODE_IDS, std::vector<int>({2}));
root->id = 1;
event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>();
event->window_data->push_back(AXWindowInfoData::New());
AXWindowInfoData* root_window = event->window_data->back().get();
root_window->window_id = 100;
root_window->root_node_id = 1;
// Add a child node.
event->node_data.push_back(AXNodeInfoData::New());
AXNodeInfoData* node = event->node_data.back().get();
node->id = 2;
CallNotifyAccessibilityEvent(event.get());
std::unique_ptr<ui::AXNodeData> data;
// Editable node is textField.
SetProperty(node, AXStringProperty::CLASS_NAME, ui::kAXEditTextClassname);
SetProperty(node, AXBooleanProperty::EDITABLE, true);
CallSerializeNode(node, &data);
EXPECT_EQ(ax::mojom::Role::kTextField, data->role);
// Non-editable node is not textField even if it has EditTextClassname.
// When it has text and no children, it is staticText. Otherwise, it's
// genericContainer.
SetProperty(node, AXBooleanProperty::EDITABLE, false);
SetProperty(node, AXStringProperty::TEXT, "text");
CallSerializeNode(node, &data);
EXPECT_EQ(ax::mojom::Role::kStaticText, data->role);
// Add a child.
SetProperty(node, AXIntListProperty::CHILD_NODE_IDS, std::vector<int>({3}));
event->node_data.push_back(AXNodeInfoData::New());
AXNodeInfoData* child = event->node_data.back().get();
child->id = 3;
CallSerializeNode(node, &data);
EXPECT_EQ(ax::mojom::Role::kGenericContainer, data->role);
}
TEST_F(AXTreeSourceArcTest, ComplexTreeStructure) { TEST_F(AXTreeSourceArcTest, ComplexTreeStructure) {
int tree_size = 4; int tree_size = 4;
int num_trees = 3; int num_trees = 3;
......
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