Commit 8740e197 authored by Hiroki Sato's avatar Hiroki Sato Committed by Commit Bot

Do not ignore WebView and its child nodes for ARC++ a11y

crrev/c/1875853 wired Android's ImportantForAccessibility to chrome's
ignored state. This made all WebView nodes ignored as they don't have
importance.

This CL fixes it by checking whether it's a native web node and it's
focusable.

Bug: b:143435799
Test: unit_tests --gtest_filter="AXTreeSourceArcTest.*"
Change-Id: I01b52b2542d771749c50f44be361572bb30916da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1890407
Commit-Queue: Hiroki Sato <hirokisato@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Reviewed-by: default avatarSara Kato <sarakato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712414}
parent 8796f324
......@@ -9,6 +9,7 @@
#include "chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/platform/ax_android_constants.h"
namespace arc {
......@@ -261,7 +262,11 @@ void AccessibilityNodeInfoDataWrapper::PopulateAXState(
if (!GetProperty(AXBooleanProperty::VISIBLE_TO_USER))
out_data->AddState(ax::mojom::State::kInvisible);
if (!GetProperty(AXBooleanProperty::IMPORTANCE))
// WebView and its child nodes do not have accessibility importance set.
// IsFocusableNativeWeb can be removed once the change in crrev/c/1890402 is
// landed in all ARC containers.
if (!GetProperty(AXBooleanProperty::IMPORTANCE) &&
!IsFocusableNativeWeb(out_data->role))
out_data->AddState(ax::mojom::State::kIgnored);
}
......@@ -580,4 +585,45 @@ void AccessibilityNodeInfoDataWrapper::ComputeNameFromContents(
}
}
// Returns true if the node is (or is inside) WebView and it's accessibility
// focusable.
bool AccessibilityNodeInfoDataWrapper::IsFocusableNativeWeb(
ax::mojom::Role role) const {
std::vector<int32_t> standard_action_ids;
if (GetProperty(AXIntListProperty::STANDARD_ACTION_IDS,
&standard_action_ids)) {
bool is_native_web = false;
bool is_focusable = GetProperty(AXBooleanProperty::FOCUSABLE);
for (const int32_t id : standard_action_ids) {
switch (static_cast<AXActionType>(id)) {
case AXActionType::NEXT_HTML_ELEMENT:
case AXActionType::PREVIOUS_HTML_ELEMENT:
is_native_web = true;
break;
case AXActionType::CLICK:
case AXActionType::FOCUS:
case AXActionType::ACCESSIBILITY_FOCUS:
is_focusable = true;
break;
default:
// unused.
break;
}
}
return is_native_web &&
(is_focusable || ui::IsControl(role) || IsInterestingLeaf());
}
return false;
}
bool AccessibilityNodeInfoDataWrapper::IsInterestingLeaf() const {
bool has_text = HasProperty(AXStringProperty::CONTENT_DESCRIPTION) ||
HasProperty(AXStringProperty::TEXT);
std::vector<AccessibilityInfoDataWrapper*> children;
GetChildren(&children);
// TODO(hirokisato) Even if the node has children, they might be empty. In
// this case we should return true.
return has_text && children.empty();
}
} // namespace arc
......@@ -55,6 +55,10 @@ class AccessibilityNodeInfoDataWrapper : public AccessibilityInfoDataWrapper {
void ComputeNameFromContents(const AccessibilityNodeInfoDataWrapper* data,
std::vector<std::string>* names) const;
bool IsFocusableNativeWeb(ax::mojom::Role role) const;
bool IsInterestingLeaf() const;
mojom::AccessibilityNodeInfoData* node_ptr_ = nullptr;
bool is_clickable_leaf_;
......
......@@ -17,6 +17,7 @@
namespace arc {
using AXActionType = mojom::AccessibilityActionType;
using AXBooleanProperty = mojom::AccessibilityBooleanProperty;
using AXCollectionInfoData = mojom::AccessibilityCollectionInfoData;
using AXCollectionItemInfoData = mojom::AccessibilityCollectionItemInfoData;
......@@ -940,4 +941,48 @@ TEST_F(AXTreeSourceArcTest, SerializeAndUnserialize) {
EXPECT_EQ(1U, tree()->GetFromId(10)->GetUnignoredChildCount());
}
TEST_F(AXTreeSourceArcTest, SerializeWebView) {
auto event = AXEventData::New();
event->source_id = 10;
event->task_id = 1;
event->event_type = AXEventType::VIEW_FOCUSED;
event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>();
event->window_data->emplace_back(AXWindowInfoData::New());
AXWindowInfoData* root_window = event->window_data->back().get();
root_window->window_id = 100;
root_window->root_node_id = 10;
event->node_data.emplace_back(AXNodeInfoData::New());
AXNodeInfoData* root = event->node_data.back().get();
root->id = 10;
SetProperty(root, AXIntListProperty::CHILD_NODE_IDS, std::vector<int>({1}));
SetProperty(root, AXBooleanProperty::IMPORTANCE, true);
// node1 is a webView
event->node_data.emplace_back(AXNodeInfoData::New());
AXNodeInfoData* node1 = event->node_data.back().get();
node1->id = 1;
SetProperty(node1, AXIntListProperty::CHILD_NODE_IDS, std::vector<int>({2}));
SetProperty(node1, AXStringProperty::CHROME_ROLE, "rootWebArea");
event->node_data.emplace_back(AXNodeInfoData::New());
AXNodeInfoData* node2 = event->node_data.back().get();
node2->id = 2;
SetProperty(
node2, AXIntListProperty::STANDARD_ACTION_IDS,
std::vector<int>({static_cast<int>(AXActionType::NEXT_HTML_ELEMENT),
static_cast<int>(AXActionType::FOCUS)}));
CallNotifyAccessibilityEvent(event.get());
std::unique_ptr<ui::AXNodeData> data;
CallSerializeNode(node1, &data);
ASSERT_EQ(ax::mojom::Role::kGenericContainer, data->role);
// Node inside a WebView is not ignored even if it's not set importance.
CallSerializeNode(node2, &data);
ASSERT_FALSE(data->HasState(ax::mojom::State::kIgnored));
}
} // namespace arc
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