Commit 9b4cbe49 authored by Alexander Surkov's avatar Alexander Surkov Committed by Commit Bot

Port ax_dump_tree tool on mac: generalize LineIndexesMap to reuse it for...

Port ax_dump_tree tool on mac: generalize LineIndexesMap to reuse it for native mac accessible trees

Bug: 1124366
Change-Id: Id0071572ef54856fee9f6ecd1b5d379fdbb3a079
AX-Relnotes: n/a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2391468
Commit-Queue: Alexander Surkov <asurkov@igalia.com>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804455}
parent 8f6bd292
......@@ -25,7 +25,8 @@ using base::SysNSStringToUTF8;
using base::SysNSStringToUTF16;
using base::SysUTF16ToNSString;
using std::string;
using content::a11y::LineIndexesMap;
using content::a11y::LineIndexer;
using content::a11y::CocoaLineIndexer;
using content::a11y::OptionalNSObject;
using content::a11y::AttributeInvoker;
......@@ -69,7 +70,7 @@ class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase {
private:
void RecursiveBuildAccessibilityTree(const BrowserAccessibilityCocoa* node,
const LineIndexesMap& line_indexes_map,
const LineIndexer* line_indexer,
base::DictionaryValue* dict);
base::FilePath::StringType GetExpectedFileSuffix() override;
......@@ -80,27 +81,26 @@ class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase {
const std::string GetRunUntilEventString() override;
void AddProperties(const BrowserAccessibilityCocoa* node,
const LineIndexesMap& line_indexes_map,
const LineIndexer* line_indexer,
base::Value* dict);
// Invokes an attributes by a property node.
OptionalNSObject InvokeAttributeFor(
const BrowserAccessibilityCocoa* cocoa_node,
const PropertyNode& property_node,
const LineIndexesMap& line_indexes_map) const;
const LineIndexer* line_indexer) const;
base::Value PopulateSize(const BrowserAccessibilityCocoa*) const;
base::Value PopulatePosition(const BrowserAccessibilityCocoa*) const;
base::Value PopulateRange(NSRange) const;
base::Value PopulateTextPosition(
BrowserAccessibilityPosition::AXPositionInstance::pointer,
const LineIndexesMap&) const;
base::Value PopulateTextMarkerRange(id, const LineIndexesMap&) const;
base::Value PopulateObject(id, const LineIndexesMap& line_indexes_map) const;
base::Value PopulateArray(NSArray*,
const LineIndexesMap& line_indexes_map) const;
const LineIndexer*) const;
base::Value PopulateTextMarkerRange(id, const LineIndexer*) const;
base::Value PopulateObject(id, const LineIndexer* line_indexer) const;
base::Value PopulateArray(NSArray*, const LineIndexer* line_indexer) const;
std::string NodeToLineIndex(id, const LineIndexesMap&) const;
std::string NodeToLineIndex(id, const LineIndexer*) const;
std::string ProcessTreeForOutput(
const base::DictionaryValue& node,
......@@ -148,13 +148,10 @@ std::unique_ptr<base::DictionaryValue>
AccessibilityTreeFormatterMac::BuildAccessibilityTree(
BrowserAccessibility* root) {
DCHECK(root);
BrowserAccessibilityCocoa* cocoa_root = ToBrowserAccessibilityCocoa(root);
LineIndexesMap line_indexes_map(cocoa_root);
CocoaLineIndexer line_indexer(cocoa_root);
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
RecursiveBuildAccessibilityTree(cocoa_root, line_indexes_map, dict.get());
RecursiveBuildAccessibilityTree(cocoa_root, &line_indexer, dict.get());
return dict;
}
......@@ -181,15 +178,15 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTreeForPattern(
void AccessibilityTreeFormatterMac::RecursiveBuildAccessibilityTree(
const BrowserAccessibilityCocoa* cocoa_node,
const LineIndexesMap& line_indexes_map,
const LineIndexer* line_indexer,
base::DictionaryValue* dict) {
AddProperties(cocoa_node, line_indexes_map, dict);
AddProperties(cocoa_node, line_indexer, dict);
auto children = std::make_unique<base::ListValue>();
for (BrowserAccessibilityCocoa* cocoa_child in [cocoa_node children]) {
std::unique_ptr<base::DictionaryValue> child_dict(
new base::DictionaryValue);
RecursiveBuildAccessibilityTree(cocoa_child, line_indexes_map,
RecursiveBuildAccessibilityTree(cocoa_child, line_indexer,
child_dict.get());
children->Append(std::move(child_dict));
}
......@@ -198,7 +195,7 @@ void AccessibilityTreeFormatterMac::RecursiveBuildAccessibilityTree(
void AccessibilityTreeFormatterMac::AddProperties(
const BrowserAccessibilityCocoa* cocoa_node,
const LineIndexesMap& line_indexes_map,
const LineIndexer* line_indexer,
base::Value* dict) {
// DOM element id
BrowserAccessibility* node = [cocoa_node owner];
......@@ -210,15 +207,15 @@ void AccessibilityTreeFormatterMac::AddProperties(
dict->SetPath(
SysNSStringToUTF8(attribute),
PopulateObject([cocoa_node accessibilityAttributeValue:attribute],
line_indexes_map));
line_indexer));
}
return;
}
// Otherwise dump attributes matching allow filters only.
std::string line_index = line_indexes_map.IndexBy(cocoa_node);
std::string line_index = line_indexer->IndexBy(cocoa_node);
for (const PropertyNode& property_node : PropertyFilterNodesFor(line_index)) {
AttributeInvoker invoker(cocoa_node, line_indexes_map);
AttributeInvoker invoker(cocoa_node, line_indexer);
OptionalNSObject value = invoker.Invoke(property_node);
if (value.IsNotApplicable()) {
continue;
......@@ -229,7 +226,7 @@ void AccessibilityTreeFormatterMac::AddProperties(
continue;
}
dict->SetPath(property_node.original_property,
PopulateObject(*value, line_indexes_map));
PopulateObject(*value, line_indexer));
}
// Position and size
......@@ -277,14 +274,14 @@ base::Value AccessibilityTreeFormatterMac::PopulatePosition(
base::Value AccessibilityTreeFormatterMac::PopulateObject(
id value,
const LineIndexesMap& line_indexes_map) const {
const LineIndexer* line_indexer) const {
if (value == nil) {
return base::Value(kNULLValue);
}
// NSArray
if ([value isKindOfClass:[NSArray class]]) {
return PopulateArray((NSArray*)value, line_indexes_map);
return PopulateArray((NSArray*)value, line_indexer);
}
// NSNumber
......@@ -301,17 +298,17 @@ base::Value AccessibilityTreeFormatterMac::PopulateObject(
// AXTextMarker
if (content::IsAXTextMarker(value)) {
return PopulateTextPosition(content::AXTextMarkerToPosition(value).get(),
line_indexes_map);
line_indexer);
}
// AXTextMarkerRange
if (content::IsAXTextMarkerRange(value)) {
return PopulateTextMarkerRange(value, line_indexes_map);
return PopulateTextMarkerRange(value, line_indexer);
}
// Accessible object
if ([value isKindOfClass:[BrowserAccessibilityCocoa class]]) {
return base::Value(NodeToLineIndex(value, line_indexes_map));
return base::Value(NodeToLineIndex(value, line_indexer));
}
// Scalar value.
......@@ -329,7 +326,7 @@ base::Value AccessibilityTreeFormatterMac::PopulateRange(
base::Value AccessibilityTreeFormatterMac::PopulateTextPosition(
BrowserAccessibilityPosition::AXPositionInstance::pointer position,
const LineIndexesMap& line_indexes_map) const {
const LineIndexer* line_indexer) const {
if (position->IsNullPosition()) {
return base::Value(kNULLValue);
}
......@@ -353,7 +350,7 @@ base::Value AccessibilityTreeFormatterMac::PopulateTextPosition(
base::Value set(base::Value::Type::DICTIONARY);
const std::string setkey_prefix = kSetKeyPrefixDictAttr;
set.SetStringPath(setkey_prefix + "index1_anchor",
NodeToLineIndex(cocoa_anchor, line_indexes_map));
NodeToLineIndex(cocoa_anchor, line_indexer));
set.SetIntPath(setkey_prefix + "index2_offset", position->text_offset());
set.SetStringPath(setkey_prefix + "index3_affinity",
kConstValuePrefix + affinity);
......@@ -362,32 +359,31 @@ base::Value AccessibilityTreeFormatterMac::PopulateTextPosition(
base::Value AccessibilityTreeFormatterMac::PopulateTextMarkerRange(
id object,
const LineIndexesMap& line_indexes_map) const {
const LineIndexer* line_indexer) const {
auto range = content::AXTextMarkerRangeToRange(object);
if (range.IsNull()) {
return base::Value(kNULLValue);
}
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetPath("anchor",
PopulateTextPosition(range.anchor(), line_indexes_map));
dict.SetPath("focus", PopulateTextPosition(range.focus(), line_indexes_map));
dict.SetPath("anchor", PopulateTextPosition(range.anchor(), line_indexer));
dict.SetPath("focus", PopulateTextPosition(range.focus(), line_indexer));
return dict;
}
base::Value AccessibilityTreeFormatterMac::PopulateArray(
NSArray* node_array,
const LineIndexesMap& line_indexes_map) const {
const LineIndexer* line_indexer) const {
base::Value list(base::Value::Type::LIST);
for (NSUInteger i = 0; i < [node_array count]; i++)
list.Append(PopulateObject([node_array objectAtIndex:i], line_indexes_map));
list.Append(PopulateObject([node_array objectAtIndex:i], line_indexer));
return list;
}
std::string AccessibilityTreeFormatterMac::NodeToLineIndex(
id cocoa_node,
const LineIndexesMap& line_indexes_map) const {
return kConstValuePrefix + line_indexes_map.IndexBy(cocoa_node);
const LineIndexer* line_indexer) const {
return kConstValuePrefix + line_indexer->IndexBy(cocoa_node);
}
std::string AccessibilityTreeFormatterMac::ProcessTreeForOutput(
......
......@@ -12,23 +12,36 @@ namespace content {
namespace a11y {
/**
* Converts cocoa node object to a line index in the formatted accessibility
* tree, the node is placed at, and vice versa.
* Converts accessible node object to a line index in the formatted
* accessibility tree, the node is placed at, and vice versa.
*/
class LineIndexesMap {
class LineIndexer {
public:
LineIndexesMap(const BrowserAccessibilityCocoa* cocoa_node);
~LineIndexesMap();
LineIndexer();
virtual ~LineIndexer();
std::string IndexBy(const BrowserAccessibilityCocoa* cocoa_node) const;
std::string IndexBy(const gfx::NativeViewAccessible node) const;
gfx::NativeViewAccessible NodeBy(const std::string& index) const;
private:
void Build(const BrowserAccessibilityCocoa* cocoa_node, int* counter);
protected:
virtual NSArray* Children(const gfx::NativeViewAccessible node) const = 0;
void Build(const gfx::NativeViewAccessible node, int* counter);
private:
std::map<const gfx::NativeViewAccessible, std::string> map;
};
/**
* Line indexer for internal BrowserAccessibilityCocoa trees.
*/
class CocoaLineIndexer final : public LineIndexer {
public:
CocoaLineIndexer(const BrowserAccessibilityCocoa* node);
protected:
NSArray* Children(const gfx::NativeViewAccessible node) const override;
};
// Implements stateful id values. Can be either id or be in
// error or not applciable state. Similar to base::Optional, but tri-state
// allowing nullable values.
......@@ -64,7 +77,7 @@ class OptionalNSObject final {
class AttributeInvoker final {
public:
AttributeInvoker(const BrowserAccessibilityCocoa* cocoa_node,
const LineIndexesMap& line_indexes_map);
const LineIndexer* line_indexer);
// Invokes an attribute matching to a property filter.
OptionalNSObject Invoke(const PropertyNode& property_node) const;
......@@ -86,7 +99,7 @@ class AttributeInvoker final {
const base::string16 line_index) const;
const BrowserAccessibilityCocoa* cocoa_node;
const LineIndexesMap& line_indexes_map;
const LineIndexer* line_indexer;
const NSArray* attributes;
const NSArray* parameterized_attributes;
};
......
......@@ -49,23 +49,18 @@ namespace {
} // namespace
LineIndexesMap::LineIndexesMap(const BrowserAccessibilityCocoa* cocoa_node) {
int counter = 0;
Build(cocoa_node, &counter);
}
LineIndexer::LineIndexer() {}
LineIndexer::~LineIndexer() {}
LineIndexesMap::~LineIndexesMap() {}
std::string LineIndexesMap::IndexBy(
const BrowserAccessibilityCocoa* cocoa_node) const {
std::string LineIndexer::IndexBy(const gfx::NativeViewAccessible node) const {
std::string line_index = ":unknown";
if (map.find(cocoa_node) != map.end()) {
line_index = map.at(cocoa_node);
if (map.find(node) != map.end()) {
line_index = map.at(node);
}
return line_index;
}
gfx::NativeViewAccessible LineIndexesMap::NodeBy(
gfx::NativeViewAccessible LineIndexer::NodeBy(
const std::string& line_index) const {
for (std::pair<const gfx::NativeViewAccessible, std::string> item : map) {
if (item.second == line_index) {
......@@ -75,21 +70,30 @@ gfx::NativeViewAccessible LineIndexesMap::NodeBy(
return nil;
}
void LineIndexesMap::Build(const BrowserAccessibilityCocoa* cocoa_node,
int* counter) {
void LineIndexer::Build(const gfx::NativeViewAccessible node, int* counter) {
const std::string line_index =
std::string(1, ':') + base::NumberToString(++(*counter));
map.insert({cocoa_node, line_index});
for (BrowserAccessibilityCocoa* cocoa_child in [cocoa_node children]) {
Build(cocoa_child, counter);
map.insert({node, line_index});
NSArray* children = Children(node);
for (gfx::NativeViewAccessible child in children) {
Build(child, counter);
}
}
CocoaLineIndexer::CocoaLineIndexer(const BrowserAccessibilityCocoa* node) {
int counter = 0;
Build(node, &counter);
}
NSArray* CocoaLineIndexer::Children(gfx::NativeViewAccessible node) const {
return [node children];
}
// AttributeInvoker
AttributeInvoker::AttributeInvoker(const BrowserAccessibilityCocoa* cocoa_node,
const LineIndexesMap& line_indexes_map)
: cocoa_node(cocoa_node), line_indexes_map(line_indexes_map) {
const LineIndexer* line_indexer)
: cocoa_node(cocoa_node), line_indexer(line_indexer) {
attributes = [cocoa_node accessibilityAttributeNames];
parameterized_attributes =
[cocoa_node accessibilityParameterizedAttributeNames];
......@@ -216,7 +220,7 @@ NSValue* AttributeInvoker::PropertyNodeToRange(
gfx::NativeViewAccessible AttributeInvoker::PropertyNodeToUIElement(
const PropertyNode& uielement_node) const {
gfx::NativeViewAccessible uielement =
line_indexes_map.NodeBy(uielement_node.name_or_value);
line_indexer->NodeBy(uielement_node.name_or_value);
if (!uielement) {
UIELEMENT_FAIL(uielement_node,
"no corresponding UIElement was found in the tree")
......@@ -233,7 +237,7 @@ id AttributeInvoker::DictNodeToTextMarker(const PropertyNode& dictnode) const {
}
BrowserAccessibilityCocoa* anchor_cocoa =
line_indexes_map.NodeBy(dictnode.parameters[0].name_or_value);
line_indexer->NodeBy(dictnode.parameters[0].name_or_value);
if (!anchor_cocoa) {
TEXTMARKER_FAIL(dictnode, "1st argument: wrong anchor")
}
......
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