Commit 8e411d07 authored by Alexander Surkov's avatar Alexander Surkov Committed by Commit Bot

Port ax_dump_tree tool on mac: seamless work with BrowserAccessibilityCocoa and AXUIElement objects

Bug: 1124366
Change-Id: I2dccf90e0de2ef06969630c0d6b890f5e619cf39
AX-Relnotes: n/a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2392848
Commit-Queue: Alexander Surkov <asurkov@igalia.com>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805380}
parent c917dcc1
......@@ -25,8 +25,9 @@ using base::SysNSStringToUTF8;
using base::SysNSStringToUTF16;
using base::SysUTF16ToNSString;
using content::a11y::AttributeInvoker;
using content::a11y::AXLineIndexer;
using content::a11y::CocoaLineIndexer;
using content::a11y::ChildrenOf;
using content::a11y::IsAXUIElement;
using content::a11y::IsBrowserAccessibilityCocoa;
using content::a11y::LineIndexer;
using content::a11y::OptionalNSObject;
using std::string;
......@@ -150,7 +151,7 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTree(
BrowserAccessibility* root) {
DCHECK(root);
BrowserAccessibilityCocoa* cocoa_root = ToBrowserAccessibilityCocoa(root);
CocoaLineIndexer line_indexer(cocoa_root);
LineIndexer line_indexer(cocoa_root);
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
RecursiveBuildAccessibilityTree(cocoa_root, &line_indexer, dict.get());
return dict;
......@@ -160,7 +161,7 @@ std::unique_ptr<base::DictionaryValue>
AccessibilityTreeFormatterMac::BuildAccessibilityTreeForWindow(
gfx::AcceleratedWidget widget) {
AXUIElementRef application = AXUIElementCreateApplication(widget);
AXLineIndexer line_indexer(application);
LineIndexer line_indexer(static_cast<id>(application));
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
RecursiveBuildAccessibilityTree(static_cast<id>(application), &line_indexer,
dict.get());
......@@ -178,31 +179,22 @@ void AccessibilityTreeFormatterMac::RecursiveBuildAccessibilityTree(
const id node,
const LineIndexer* line_indexer,
base::DictionaryValue* dict) const {
NSArray* children = nil;
if (CFGetTypeID(node) == AXUIElementGetTypeID()) {
if (IsAXUIElement(node)) {
AddProperties(static_cast<AXUIElementRef>(node), line_indexer, dict);
CFTypeRef children_ref;
if ((AXUIElementCopyAttributeValue(static_cast<AXUIElementRef>(node),
kAXChildrenAttribute, &children_ref)) ==
kAXErrorSuccess) {
children = static_cast<NSArray*>(children_ref);
}
} else if ([node isKindOfClass:[BrowserAccessibilityCocoa class]]) {
} else if (IsBrowserAccessibilityCocoa(node)) {
AddProperties(static_cast<BrowserAccessibilityCocoa*>(node), line_indexer,
dict);
children = [node children];
}
if (children) {
auto child_dict_list = std::make_unique<base::ListValue>();
for (id child in children) {
std::unique_ptr<base::DictionaryValue> child_dict(
new base::DictionaryValue);
RecursiveBuildAccessibilityTree(child, line_indexer, child_dict.get());
child_dict_list->Append(std::move(child_dict));
}
dict->Set(kChildrenDictAttr, std::move(child_dict_list));
NSArray* children = ChildrenOf(node);
auto child_dict_list = std::make_unique<base::ListValue>();
for (id child in children) {
std::unique_ptr<base::DictionaryValue> child_dict(
new base::DictionaryValue);
RecursiveBuildAccessibilityTree(child, line_indexer, child_dict.get());
child_dict_list->Append(std::move(child_dict));
}
dict->Set(kChildrenDictAttr, std::move(child_dict_list));
}
void AccessibilityTreeFormatterMac::AddProperties(
......
......@@ -11,48 +11,40 @@
namespace content {
namespace a11y {
/**
* Return true if the given object is internal BrowserAccessibilityCocoa.
*/
bool IsBrowserAccessibilityCocoa(const id node);
/**
* Returns true if the given object is AXUIElement.
*/
bool IsAXUIElement(const id node);
/**
* Returns children of an accessible object, either AXUIElement or
* BrowserAccessibilityCocoa.
*/
NSArray* ChildrenOf(const id node);
/**
* Converts accessible node object to a line index in the formatted
* accessibility tree, the node is placed at, and vice versa.
*/
class LineIndexer {
class LineIndexer final {
public:
LineIndexer();
LineIndexer(const gfx::NativeViewAccessible node);
virtual ~LineIndexer();
std::string IndexBy(const gfx::NativeViewAccessible node) const;
gfx::NativeViewAccessible NodeBy(const std::string& index) const;
protected:
virtual NSArray* Children(const gfx::NativeViewAccessible node) const = 0;
private:
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;
};
/**
* Line indexer for external AXUIElement trees.
*/
class AXLineIndexer final : public LineIndexer {
public:
AXLineIndexer(const AXUIElementRef 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.
......
......@@ -49,9 +49,40 @@ namespace {
} // namespace
bool IsBrowserAccessibilityCocoa(const id node) {
return [node isKindOfClass:[BrowserAccessibilityCocoa class]];
}
bool IsAXUIElement(const id node) {
return CFGetTypeID(node) == AXUIElementGetTypeID();
}
NSArray* ChildrenOf(const id node) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node children];
}
if (IsAXUIElement(node)) {
CFTypeRef children_ref;
if ((AXUIElementCopyAttributeValue(static_cast<AXUIElementRef>(node),
kAXChildrenAttribute, &children_ref)) ==
kAXErrorSuccess) {
return static_cast<NSArray*>(children_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
// Line indexers
LineIndexer::LineIndexer() {}
LineIndexer::LineIndexer(const gfx::NativeViewAccessible node) {
int counter = 0;
Build(node, &counter);
}
LineIndexer::~LineIndexer() {}
std::string LineIndexer::IndexBy(const gfx::NativeViewAccessible node) const {
......@@ -76,36 +107,12 @@ void LineIndexer::Build(const gfx::NativeViewAccessible node, int* counter) {
const std::string line_index =
std::string(1, ':') + base::NumberToString(++(*counter));
map.insert({node, line_index});
NSArray* children = Children(node);
NSArray* children = ChildrenOf(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];
}
AXLineIndexer::AXLineIndexer(const AXUIElementRef node) {
int counter = 0;
Build(static_cast<id>(node), &counter);
}
NSArray* AXLineIndexer::Children(gfx::NativeViewAccessible node) const {
CFTypeRef children_ref;
if ((AXUIElementCopyAttributeValue(static_cast<AXUIElementRef>(node),
kAXChildrenAttribute, &children_ref)) ==
kAXErrorSuccess) {
return static_cast<NSArray*>(children_ref);
}
return nil;
}
// AttributeInvoker
AttributeInvoker::AttributeInvoker(const BrowserAccessibilityCocoa* cocoa_node,
......
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