Commit 0e1249fe authored by Alexander Surkov's avatar Alexander Surkov Committed by Commit Bot

DumpAccTree testing: implement nested attribute calls on mac

For example, AXIndexForTextMarker(AXTextMarkerForIndex(0)) which gets a text marker by index and converts it to the index back

Bug: 1100991
Change-Id: I961190dcb4e9aab3c0a6302b4f5ea3df8b5ca4a4
AX-Relnotes: n/a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2346744
Commit-Queue: Alexander Surkov <asurkov@igalia.com>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796683}
parent a5e69667
......@@ -70,6 +70,10 @@ TEST_F(AccessibilityTreeFormatterBaseTest, ParseProperty) {
ParseAndCheck("Text({dict: [1, 2]})", "Text({}(dict: [](1, 2)))");
ParseAndCheck("Text({dict: ValueFor(1)})", "Text({}(dict: ValueFor(1)))");
// Nested arguments
ParseAndCheck("AXIndexForTextMarker(AXTextMarkerForIndex(0))",
"AXIndexForTextMarker(AXTextMarkerForIndex(0))");
// Line indexes filter.
ParseAndCheck(":3,:5;AXDOMClassList", ":3,:5;AXDOMClassList");
......
......@@ -133,7 +133,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
}
IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
LineIndexFilter) {
Filters_LineIndex) {
TestAndCheck(R"~~(data:text/html,
<input class='input_at_3rd_line'>
<input class='input_at_4th_line'>
......@@ -328,4 +328,15 @@ IN_PROC_BROWSER_TEST_F(
)~~");
}
IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
NestedCalls_Attributes) {
TestAndCheck(R"~~(data:text/html,
<p>Text</p>)~~",
{":1;AXIndexForTextMarker(AXTextMarkerForIndex(0))"},
R"~~(AXWebArea AXIndexForTextMarker(AXTextMarkerForIndex(0))=0
++AXGroup
++++AXStaticText AXValue='Text'
)~~");
}
} // namespace content
......@@ -20,27 +20,27 @@ namespace a11y {
namespace {
#define INT_FAIL(property_node, msg) \
LOG(ERROR) << "Failed to parse " << property_node.original_property \
LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
<< " to Int: " << msg; \
return nil;
#define INTARRAY_FAIL(property_node, msg) \
LOG(ERROR) << "Failed to parse " << property_node.original_property \
LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
<< " to IntArray: " << msg; \
return nil;
#define NSRANGE_FAIL(property_node, msg) \
LOG(ERROR) << "Failed to parse " << property_node.original_property \
LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
<< " to NSRange: " << msg; \
return nil;
#define UIELEMENT_FAIL(property_node, msg) \
LOG(ERROR) << "Failed to parse " << property_node.original_property \
LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
<< " to UIElement: " << msg; \
return nil;
#define TEXTMARKER_FAIL(property_node, msg) \
LOG(ERROR) << "Failed to parse " << property_node.original_property \
LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
<< " to AXTextMarker: " << msg \
<< ". Expected format: {anchor, offset, affinity}, where anchor " \
"is :line_num, offset is integer, affinity is either down, " \
......@@ -123,29 +123,42 @@ OptionalNSObject AttributeInvoker::Invoke(
OptionalNSObject AttributeInvoker::ParamByPropertyNode(
const PropertyNode& property_node) const {
// NSAccessibility attributes always take a single parameter.
if (property_node.parameters.size() != 1) {
LOG(ERROR) << "Failed to parse " << property_node.original_property
<< ": single parameter is expected";
return OptionalNSObject::Error();
}
// Nested attribute case: attempt to invoke an attribute for an argument node.
const PropertyNode& arg_node = property_node.parameters[0];
OptionalNSObject subvalue = Invoke(arg_node);
if (!subvalue.IsNotApplicable()) {
return subvalue;
}
// Otherwise parse argument node value.
std::string property_name = base::UTF16ToASCII(property_node.name_or_value);
if (property_name == "AXLineForIndex") { // Int
return OptionalNSObject::NotNilOrError(PropertyNodeToInt(property_node));
if (property_name == "AXLineForIndex" ||
property_name == "AXTextMarkerForIndex") { // Int
return OptionalNSObject::NotNilOrError(PropertyNodeToInt(arg_node));
}
if (property_name == "AXCellForColumnAndRow") { // IntArray
return OptionalNSObject::NotNilOrError(
PropertyNodeToIntArray(property_node));
return OptionalNSObject::NotNilOrError(PropertyNodeToIntArray(arg_node));
}
if (property_name == "AXStringForRange") { // NSRange
return OptionalNSObject::NotNilOrError(PropertyNodeToRange(property_node));
return OptionalNSObject::NotNilOrError(PropertyNodeToRange(arg_node));
}
if (property_name == "AXIndexForChildUIElement") { // UIElement
return OptionalNSObject::NotNilOrError(
PropertyNodeToUIElement(property_node));
return OptionalNSObject::NotNilOrError(PropertyNodeToUIElement(arg_node));
}
if (property_name == "AXIndexForTextMarker") { // TextMarker
return OptionalNSObject::NotNilOrError(
PropertyNodeToTextMarker(property_node));
return OptionalNSObject::NotNilOrError(PropertyNodeToTextMarker(arg_node));
}
if (property_name == "AXStringForTextMarkerRange") { // TextMarkerRange
return OptionalNSObject::NotNilOrError(
PropertyNodeToTextMarkerRange(property_node));
PropertyNodeToTextMarkerRange(arg_node));
}
return OptionalNSObject::NotApplicable();
......@@ -153,29 +166,19 @@ OptionalNSObject AttributeInvoker::ParamByPropertyNode(
// NSNumber. Format: integer.
NSNumber* AttributeInvoker::PropertyNodeToInt(
const PropertyNode& property_node) const {
if (property_node.parameters.size() != 1) {
INT_FAIL(property_node, "single argument is expected")
}
const auto& intnode = property_node.parameters[0];
const PropertyNode& intnode) const {
base::Optional<int> param = intnode.AsInt();
if (!param) {
INT_FAIL(property_node, "not a number")
INT_FAIL(intnode, "not a number")
}
return [NSNumber numberWithInt:*param];
}
// NSArray of two NSNumber. Format: [integer, integer].
NSArray* AttributeInvoker::PropertyNodeToIntArray(
const PropertyNode& property_node) const {
if (property_node.parameters.size() != 1) {
INTARRAY_FAIL(property_node, "single argument is expected")
}
const auto& arraynode = property_node.parameters[0];
const PropertyNode& arraynode) const {
if (arraynode.name_or_value != base::ASCIIToUTF16("[]")) {
INTARRAY_FAIL(property_node, "not array")
INTARRAY_FAIL(arraynode, "not array")
}
NSMutableArray* array =
......@@ -183,7 +186,7 @@ NSArray* AttributeInvoker::PropertyNodeToIntArray(
for (const auto& paramnode : arraynode.parameters) {
base::Optional<int> param = paramnode.AsInt();
if (!param) {
INTARRAY_FAIL(property_node, paramnode.name_or_value +
INTARRAY_FAIL(arraynode, paramnode.name_or_value +
base::UTF8ToUTF16(" is not a number"))
}
[array addObject:@(*param)];
......@@ -193,24 +196,19 @@ NSArray* AttributeInvoker::PropertyNodeToIntArray(
// NSRange. Format: {loc: integer, len: integer}.
NSValue* AttributeInvoker::PropertyNodeToRange(
const PropertyNode& property_node) const {
if (property_node.parameters.size() != 1) {
NSRANGE_FAIL(property_node, "single argument is expected")
}
const auto& dictnode = property_node.parameters[0];
const PropertyNode& dictnode) const {
if (!dictnode.IsDict()) {
NSRANGE_FAIL(property_node, "dictionary is expected")
NSRANGE_FAIL(dictnode, "dictionary is expected")
}
base::Optional<int> loc = dictnode.FindIntKey("loc");
if (!loc) {
NSRANGE_FAIL(property_node, "no loc or loc is not a number")
NSRANGE_FAIL(dictnode, "no loc or loc is not a number")
}
base::Optional<int> len = dictnode.FindIntKey("len");
if (!len) {
NSRANGE_FAIL(property_node, "no len or len is not a number")
NSRANGE_FAIL(dictnode, "no len or len is not a number")
}
return [NSValue valueWithRange:NSMakeRange(*loc, *len)];
......@@ -218,15 +216,11 @@ NSValue* AttributeInvoker::PropertyNodeToRange(
// UIElement. Format: :line_num.
gfx::NativeViewAccessible AttributeInvoker::PropertyNodeToUIElement(
const PropertyNode& property_node) const {
if (property_node.parameters.size() != 1) {
UIELEMENT_FAIL(property_node, "single argument is expected")
}
gfx::NativeViewAccessible uielement = line_indexes_map.NodeBy(
base::UTF16ToUTF8(property_node.parameters[0].name_or_value));
const PropertyNode& uielement_node) const {
gfx::NativeViewAccessible uielement =
line_indexes_map.NodeBy(base::UTF16ToUTF8(uielement_node.name_or_value));
if (!uielement) {
UIELEMENT_FAIL(property_node,
UIELEMENT_FAIL(uielement_node,
"no corresponding UIElement was found in the tree")
}
return uielement;
......@@ -267,42 +261,34 @@ id AttributeInvoker::DictNodeToTextMarker(const PropertyNode& dictnode) const {
}
id AttributeInvoker::PropertyNodeToTextMarker(
const PropertyNode& property_node) const {
if (property_node.parameters.size() != 1) {
TEXTMARKER_FAIL(property_node, "single argument is expected")
}
return DictNodeToTextMarker(property_node.parameters[0]);
const PropertyNode& dictnode) const {
return DictNodeToTextMarker(dictnode);
}
id AttributeInvoker::PropertyNodeToTextMarkerRange(
const PropertyNode& property_node) const {
if (property_node.parameters.size() != 1) {
TEXTMARKER_FAIL(property_node, "single argument is expected")
}
const auto& rangenode = property_node.parameters[0];
const PropertyNode& rangenode) const {
if (!rangenode.IsDict()) {
TEXTMARKER_FAIL(property_node, "dictionary is expected")
TEXTMARKER_FAIL(rangenode, "dictionary is expected")
}
const PropertyNode* anchornode = rangenode.FindKey("anchor");
if (!anchornode) {
TEXTMARKER_FAIL(property_node, "no anchor")
TEXTMARKER_FAIL(rangenode, "no anchor")
}
id anchor_textmarker = DictNodeToTextMarker(*anchornode);
if (!anchor_textmarker) {
TEXTMARKER_FAIL(property_node, "failed to parse anchor")
TEXTMARKER_FAIL(rangenode, "failed to parse anchor")
}
const PropertyNode* focusnode = rangenode.FindKey("focus");
if (!focusnode) {
TEXTMARKER_FAIL(property_node, "no focus")
TEXTMARKER_FAIL(rangenode, "no focus")
}
id focus_textmarker = DictNodeToTextMarker(*focusnode);
if (!focus_textmarker) {
TEXTMARKER_FAIL(property_node, "failed to parse focus")
TEXTMARKER_FAIL(rangenode, "failed to parse focus")
}
return content::AXTextMarkerRangeFrom(anchor_textmarker, focus_textmarker);
......
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