Skip to content

Commit

Permalink
[fuchsia][a11y] Populate list semantics when calling Fuchsia a11y API
Browse files Browse the repository at this point in the history
I generated the golden files with https://chromium-review.googlesource.com/c/chromium/src/+/3575495, and then manually verified that the changes look good.
(Some files have diffs that are just whitespace - this is because I recently changed the tool to strip trailing whitespace.)

AX-Relnotes: n/a.
Bug: fuchsia:95750
Tested: content_unittests and content_browsertests
Change-Id: Ie46a0d70cc1eae1b74ee34efc0950b9c4b8d9185
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3561851
Reviewed-by: David Tseng <dtseng@chromium.org>
Commit-Queue: Michael LoPiccolo <milopiccolo@google.com>
Cr-Commit-Position: refs/heads/main@{#990058}
  • Loading branch information
Michael LoPiccolo authored and Chromium LUCI CQ committed Apr 7, 2022
1 parent 9d90984 commit 504fbe9
Show file tree
Hide file tree
Showing 40 changed files with 274 additions and 162 deletions.
Expand Up @@ -30,8 +30,7 @@ constexpr const char* const kStringAttributes[] = {
constexpr const char* const kIntAttributes[] = {
"number_of_rows", "number_of_columns", "row_index",
"cell_row_index", "cell_column_index", "cell_row_span",
"cell_column_span",
};
"cell_column_span", "list_size", "list_element_index"};

constexpr const char* const kDoubleAttributes[] = {
"min_value",
Expand Down Expand Up @@ -59,6 +58,8 @@ std::string FuchsiaRoleToString(const FuchsiaRole role) {
return "LINK";
case FuchsiaRole::LIST:
return "LIST";
case FuchsiaRole::LIST_ELEMENT:
return "LIST_ELEMENT";
case FuchsiaRole::LIST_ELEMENT_MARKER:
return "LIST_ELEMENT_MARKER";
case FuchsiaRole::PARAGRAPH:
Expand Down Expand Up @@ -333,6 +334,15 @@ void AccessibilityTreeFormatterFuchsia::AddProperties(
}
}

if (attributes.has_list_attributes()) {
dict->SetIntKey("list_size", attributes.list_attributes().size());
}

if (attributes.has_list_element_attributes()) {
dict->SetIntKey("list_element_index",
attributes.list_element_attributes().index());
}

if (attributes.has_is_keyboard_key())
dict->SetBoolKey("is_keyboard_key", attributes.is_keyboard_key());
}
Expand Down
33 changes: 33 additions & 0 deletions content/browser/accessibility/browser_accessibility_fuchsia.cc
Expand Up @@ -149,6 +149,12 @@ BrowserAccessibilityFuchsia::GetFuchsiaRole() const {
return FuchsiaRole::IMAGE;
case AXRole::kLink:
return FuchsiaRole::LINK;
case AXRole::kList:
return FuchsiaRole::LIST;
case AXRole::kListItem:
return FuchsiaRole::LIST_ELEMENT;
case AXRole::kListMarker:
return FuchsiaRole::LIST_ELEMENT_MARKER;
case AXRole::kParagraph:
return FuchsiaRole::PARAGRAPH;
case AXRole::kRadioButton:
Expand Down Expand Up @@ -322,6 +328,25 @@ BrowserAccessibilityFuchsia::GetFuchsiaAttributes() const {
attributes.set_table_cell_attributes(std::move(table_cell_attributes));
}

if (IsList()) {
absl::optional<int> size = GetSetSize();
if (size) {
fuchsia::accessibility::semantics::SetAttributes list_attributes;
list_attributes.set_size(*size);
attributes.set_list_attributes(std::move(list_attributes));
}
}

if (IsListElement()) {
absl::optional<int> index = GetPosInSet();
if (index) {
fuchsia::accessibility::semantics::SetAttributes list_element_attributes;
list_element_attributes.set_index(*index);
attributes.set_list_element_attributes(
std::move(list_element_attributes));
}
}

return attributes;
}

Expand Down Expand Up @@ -387,6 +412,14 @@ void BrowserAccessibilityFuchsia::DeleteNode() {
GetAccessibilityBridge()->DeleteNode(GetFuchsiaNodeID());
}

bool BrowserAccessibilityFuchsia::IsList() const {
return GetRole() == AXRole::kList;
}

bool BrowserAccessibilityFuchsia::IsListElement() const {
return GetRole() == AXRole::kListItem;
}

bool BrowserAccessibilityFuchsia::AccessibilityPerformAction(
const ui::AXActionData& action_data) {
if (action_data.action == ax::mojom::Action::kHitTest) {
Expand Down
12 changes: 12 additions & 0 deletions content/browser/accessibility/browser_accessibility_fuchsia.h
Expand Up @@ -67,6 +67,18 @@ class CONTENT_EXPORT BrowserAccessibilityFuchsia : public BrowserAccessibility {
fuchsia::ui::gfx::mat4 GetFuchsiaTransform() const;
std::vector<uint32_t> GetFuchsiaChildIDs() const;

// Returns true if this AXNode has role AXRole::kList.
// This may need to be expanded later to include more roles, maybe using
// ui::IsList
// (https://source.chromium.org/chromium/chromium/src/+/main:ui/accessibility/ax_role_properties.cc;l=399;drc=2c712b0d61f0788c0ed1b05176ae7430e8c705e5;bpv=1;bpt=1).
bool IsList() const;

// Returns true if this AXNode has role AXRole::klistItem.
// This may need to be expanded later to include more roles, maybe using
// ui::IsListItem
// (https://source.chromium.org/chromium/chromium/src/+/main:ui/accessibility/ax_role_properties.cc;drc=2c712b0d61f0788c0ed1b05176ae7430e8c705e5;l=413).
bool IsListElement() const;

// Fuchsia-specific representation of this node.
ui::AXPlatformNodeFuchsia* platform_node_;
};
Expand Down
Expand Up @@ -26,66 +26,92 @@ constexpr int32_t kRootId = 182;
constexpr int32_t kRowNodeId1 = 2;
constexpr int32_t kRowNodeId2 = 3;
constexpr int32_t kCellNodeId = 7;
constexpr int32_t kListElementId1 = 111;
constexpr int32_t kListElementId2 = 222;

ui::AXTreeUpdate CreateTableUpdate() {
ui::AXTreeUpdate update;
update.root_id = kRootId;
update.nodes.resize(8);
auto& table = update.nodes[0];
table.id = kRootId;
table.role = ax::mojom::Role::kTable;
table.role = AXRole::kTable;
table.AddIntAttribute(ax::mojom::IntAttribute::kTableRowCount, 2);
table.AddIntAttribute(ax::mojom::IntAttribute::kTableColumnCount, 2);
table.child_ids = {888, kRowNodeId2};

auto& row_group = update.nodes[1];
row_group.id = 888;
row_group.role = ax::mojom::Role::kRowGroup;
row_group.role = AXRole::kRowGroup;
row_group.child_ids = {kRowNodeId1};

auto& row_1 = update.nodes[2];
row_1.id = kRowNodeId1;
row_1.role = ax::mojom::Role::kRow;
row_1.role = AXRole::kRow;
row_1.AddIntAttribute(ax::mojom::IntAttribute::kTableRowIndex, 0);
row_1.child_ids = {4, 5};

auto& row_2 = update.nodes[3];
row_2.id = kRowNodeId2;
row_2.role = ax::mojom::Role::kRow;
row_2.role = AXRole::kRow;
row_2.AddIntAttribute(ax::mojom::IntAttribute::kTableRowIndex, 1);
row_2.child_ids = {6, kCellNodeId};

auto& column_header_1 = update.nodes[4];
column_header_1.id = 4;
column_header_1.role = ax::mojom::Role::kColumnHeader;
column_header_1.role = AXRole::kColumnHeader;
column_header_1.AddIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex,
0);
column_header_1.AddIntAttribute(
ax::mojom::IntAttribute::kTableCellColumnIndex, 0);

auto& column_header_2 = update.nodes[5];
column_header_2.id = 5;
column_header_2.role = ax::mojom::Role::kColumnHeader;
column_header_2.role = AXRole::kColumnHeader;
column_header_2.AddIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex,
0);
column_header_2.AddIntAttribute(
ax::mojom::IntAttribute::kTableCellColumnIndex, 1);

auto& cell_1 = update.nodes[6];
cell_1.id = 6;
cell_1.role = ax::mojom::Role::kCell;
cell_1.role = AXRole::kCell;
cell_1.AddIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, 1);
cell_1.AddIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex, 0);

auto& cell_2 = update.nodes[7];
cell_2.id = kCellNodeId;
cell_2.role = ax::mojom::Role::kCell;
cell_2.role = AXRole::kCell;
cell_2.AddIntAttribute(ax::mojom::IntAttribute::kTableCellRowIndex, 1);
cell_2.AddIntAttribute(ax::mojom::IntAttribute::kTableCellColumnIndex, 1);

return update;
}

ui::AXTreeUpdate CreateListUpdate() {
ui::AXTreeUpdate update;
update.root_id = kRootId;
update.nodes.resize(3);

auto& list = update.nodes[0];
list.id = kRootId;
list.role = AXRole::kList;
list.AddIntAttribute(ax::mojom::IntAttribute::kSetSize, 2);
list.child_ids = {kListElementId1, kListElementId2};

auto& list_element_1 = update.nodes[1];
list_element_1.id = kListElementId1;
list_element_1.role = AXRole::kListItem;
list_element_1.AddIntAttribute(ax::mojom::IntAttribute::kPosInSet, 1);

auto& list_element_2 = update.nodes[2];
list_element_2.id = kListElementId2;
list_element_2.role = AXRole::kListItem;
list_element_2.AddIntAttribute(ax::mojom::IntAttribute::kPosInSet, 2);

return update;
}

} // namespace

class BrowserAccessibilityFuchsiaTest : public testing::Test {
Expand Down Expand Up @@ -122,6 +148,9 @@ TEST_F(BrowserAccessibilityFuchsiaTest, ToFuchsiaNodeDataTranslatesRoles) {
{AXRole::kHeader, Role::HEADER},
{AXRole::kImage, Role::IMAGE},
{AXRole::kLink, Role::LINK},
{AXRole::kList, Role::LIST},
{AXRole::kListItem, Role::LIST_ELEMENT},
{AXRole::kListMarker, Role::LIST_ELEMENT_MARKER},
{AXRole::kRadioButton, Role::RADIO_BUTTON},
{AXRole::kSlider, Role::SLIDER},
{AXRole::kTextField, Role::TEXT_FIELD},
Expand Down Expand Up @@ -313,6 +342,42 @@ TEST_F(BrowserAccessibilityFuchsiaTest,
}
}

TEST_F(BrowserAccessibilityFuchsiaTest,
ToFuchsiaNodeDataTranslatesListAttributes) {
std::unique_ptr<BrowserAccessibilityManager> manager(
BrowserAccessibilityManager::Create(
CreateListUpdate(), test_browser_accessibility_delegate_.get()));

// Verify that the list root was translated.
{
BrowserAccessibilityFuchsia* browser_accessibility_fuchsia =
ToBrowserAccessibilityFuchsia(manager->GetRoot());
ASSERT_TRUE(browser_accessibility_fuchsia);
auto fuchsia_node_data = browser_accessibility_fuchsia->ToFuchsiaNodeData();
EXPECT_EQ(fuchsia_node_data.role(),
fuchsia::accessibility::semantics::Role::LIST);
ASSERT_TRUE(fuchsia_node_data.has_attributes());
ASSERT_TRUE(fuchsia_node_data.attributes().has_list_attributes());
ASSERT_FALSE(fuchsia_node_data.attributes().has_list_element_attributes());
EXPECT_EQ(fuchsia_node_data.attributes().list_attributes().size(), 2u);
}

// Verify that the list elements were translated.
{
BrowserAccessibilityFuchsia* browser_accessibility_fuchsia =
ToBrowserAccessibilityFuchsia(manager->GetFromID(kListElementId2));
ASSERT_TRUE(browser_accessibility_fuchsia);
auto fuchsia_node_data = browser_accessibility_fuchsia->ToFuchsiaNodeData();
EXPECT_EQ(fuchsia_node_data.role(),
fuchsia::accessibility::semantics::Role::LIST_ELEMENT);
ASSERT_TRUE(fuchsia_node_data.has_attributes());
ASSERT_FALSE(fuchsia_node_data.attributes().has_list_attributes());
ASSERT_TRUE(fuchsia_node_data.attributes().has_list_element_attributes());
EXPECT_EQ(fuchsia_node_data.attributes().list_element_attributes().index(),
2u);
}
}

TEST_F(BrowserAccessibilityFuchsiaTest,
ToFuchsiaNodeDataTranslatesCheckedState) {
std::map<ax::mojom::CheckedState,
Expand Down
Expand Up @@ -26,4 +26,4 @@ UNKNOWN focusable has_input_focus
++++++LINK focusable label='Link with image at the end' actions='{DEFAULT}'
++++++++STATIC_TEXT label='Link with image at the '
++++++++++UNKNOWN label='Link with image at the '
++++++++IMAGE label='end' actions='{DEFAULT}'
++++++++IMAGE label='end' actions='{DEFAULT}'
Expand Up @@ -29,7 +29,7 @@ UNKNOWN focusable has_input_focus label='Action verbs'
++++++UNKNOWN
++++++++UNKNOWN hidden
++++++++++UNKNOWN focusable label='Summary' actions='{DEFAULT}'
++++++++++++UNKNOWN hidden
++++++++++++LIST_ELEMENT_MARKER hidden
++++++++++++++STATIC_TEXT hidden label='%E2%96%B8 '
++++++++++++STATIC_TEXT label='Summary'
++++++++++++++UNKNOWN label='Summary'
Expand Down
Expand Up @@ -10,4 +10,4 @@ UNKNOWN focusable has_input_focus
++++++++++++UNKNOWN label='Aside tag'
++++++++PARAGRAPH
++++++++++STATIC_TEXT label='The aside content should be related to the surrounding content.'
++++++++++++UNKNOWN label='The aside content should be related to the surrounding content.'
++++++++++++UNKNOWN label='The aside content should be related to the surrounding content.'
Expand Up @@ -24,9 +24,9 @@ UNKNOWN focusable has_input_focus
++++++++++++++CELL label='Always expose editable tables as tables.' actions='{DEFAULT}' cell_row_span=1 cell_column_span=1
++++++++++++++++STATIC_TEXT label='Always expose editable tables as tables.'
++++++++++++++++++UNKNOWN label='Always expose editable tables as tables.'
++++++++UNKNOWN actions='{DEFAULT}'
++++++++++UNKNOWN actions='{DEFAULT}'
++++++++++++UNKNOWN label='1. ' actions='{DEFAULT}'
++++++++LIST actions='{DEFAULT}' list_size=1
++++++++++LIST_ELEMENT actions='{DEFAULT}' list_element_index=1
++++++++++++LIST_ELEMENT_MARKER label='1. ' actions='{DEFAULT}'
++++++++++++++STATIC_TEXT hidden label='1. '
++++++++++++STATIC_TEXT label='Editable list item.'
++++++++++++++UNKNOWN label='Editable list item.'
Expand All @@ -35,4 +35,4 @@ UNKNOWN focusable has_input_focus
++++++++++UNKNOWN label='Non-editable paragraph.'
++++++PARAGRAPH focusable actions='{DEFAULT}' value='Should keep the role but change the state.'
++++++++STATIC_TEXT label='Should keep the role but change the state.'
++++++++++UNKNOWN label='Should keep the role but change the state.'
++++++++++UNKNOWN label='Should keep the role but change the state.'
Expand Up @@ -24,9 +24,9 @@ UNKNOWN focusable
++++++++++++++CELL label='Always expose editable tables as tables.' actions='{DEFAULT}' cell_row_span=1 cell_column_span=1
++++++++++++++++STATIC_TEXT label='Always expose editable tables as tables.'
++++++++++++++++++UNKNOWN label='Always expose editable tables as tables.'
++++++++UNKNOWN actions='{DEFAULT}'
++++++++++UNKNOWN actions='{DEFAULT}'
++++++++++++UNKNOWN label='1. ' actions='{DEFAULT}'
++++++++LIST actions='{DEFAULT}' list_size=1
++++++++++LIST_ELEMENT actions='{DEFAULT}' list_element_index=1
++++++++++++LIST_ELEMENT_MARKER label='1. ' actions='{DEFAULT}'
++++++++++++++STATIC_TEXT hidden label='1. '
++++++++++++STATIC_TEXT label='Editable list item.'
++++++++++++++UNKNOWN label='Editable list item.'
++++++++++++++UNKNOWN label='Editable list item.'
Expand Up @@ -15,4 +15,4 @@ UNKNOWN focusable has_input_focus
++++++++++++++UNKNOWN label='But this one is.'
++++++++PARAGRAPH actions='{DEFAULT}' value='So is this one.'
++++++++++STATIC_TEXT label='So is this one.'
++++++++++++UNKNOWN label='So is this one.'
++++++++++++UNKNOWN label='So is this one.'
Expand Up @@ -4,7 +4,7 @@ UNKNOWN focusable has_input_focus
++++++UNKNOWN
++++++++UNKNOWN hidden
++++++++++UNKNOWN focusable label='details tag' actions='{DEFAULT}'
++++++++++++UNKNOWN hidden
++++++++++++LIST_ELEMENT_MARKER hidden
++++++++++++++STATIC_TEXT hidden label='%E2%96%B8 '
++++++++++++STATIC_TEXT label='details tag'
++++++++++++++UNKNOWN label='details tag'
Expand All @@ -17,7 +17,7 @@ UNKNOWN focusable has_input_focus
++++++UNKNOWN
++++++++UNKNOWN hidden
++++++++++UNKNOWN focusable label='details tag open' actions='{DEFAULT}'
++++++++++++UNKNOWN hidden
++++++++++++LIST_ELEMENT_MARKER hidden
++++++++++++++STATIC_TEXT hidden label='%E2%96%BE '
++++++++++++STATIC_TEXT label='details tag open'
++++++++++++++UNKNOWN label='details tag open'
Expand Down
@@ -1,8 +0,0 @@
UNKNOWN focusable has_input_focus
++UNKNOWN hidden
++++UNKNOWN hidden
++++++UNKNOWN
++++++++IMAGE label='This is a green box.'
++++++++UNKNOWN
++++++++++STATIC_TEXT label='Fig.1 - A green Box'
++++++++++++UNKNOWN label='Fig.1 - A green Box'
Expand Up @@ -8,4 +8,4 @@ UNKNOWN focusable has_input_focus
++++++UNKNOWN focusable
++++++++UNKNOWN focusable
++++++++++UNKNOWN hidden
++++++++++++UNKNOWN hidden
++++++++++++UNKNOWN hidden
Expand Up @@ -8,4 +8,4 @@ UNKNOWN focusable has_input_focus
++++++TEXT_FIELD focusable label='Launch' actions='{DEFAULT, SET_VALUE}' value='1/1/2015 1:00AM'
++++++++UNKNOWN
++++++++++STATIC_TEXT label='1/1/2015 1:00AM'
++++++++++++UNKNOWN label='1/1/2015 1:00AM'
++++++++++++UNKNOWN label='1/1/2015 1:00AM'
Expand Up @@ -8,6 +8,6 @@ UNKNOWN focusable has_input_focus
++++++++++UNKNOWN hidden
++++++++++++UNKNOWN hidden
++++++++++++++UNKNOWN
++++++++++++UNKNOWN hidden
++++++++++++++UNKNOWN hidden
++++++++++++LIST_ELEMENT hidden
++++++++++++++LIST_ELEMENT_MARKER hidden
++++++++++++++++STATIC_TEXT hidden label='%E2%96%BE'
Expand Up @@ -12,4 +12,4 @@ UNKNOWN focusable has_input_focus
++++++++++++UNKNOWN focusable label='Year' actions='{SET_VALUE}'
++++++++++++++STATIC_TEXT label='----'
++++++++++++++++UNKNOWN label='----'
++++++++UNKNOWN focusable label='Show month picker'
++++++++UNKNOWN focusable label='Show month picker'
Expand Up @@ -12,4 +12,4 @@ UNKNOWN focusable has_input_focus
++++++++UNKNOWN
++++++++++RADIO_BUTTON focusable label='Dark' actions='{DEFAULT}' checked_state='UNCHECKED'
++++++++++STATIC_TEXT label='Dark'
++++++++++++UNKNOWN label='Dark'
++++++++++++UNKNOWN label='Dark'

0 comments on commit 504fbe9

Please sign in to comment.