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; ...@@ -25,8 +25,9 @@ using base::SysNSStringToUTF8;
using base::SysNSStringToUTF16; using base::SysNSStringToUTF16;
using base::SysUTF16ToNSString; using base::SysUTF16ToNSString;
using content::a11y::AttributeInvoker; using content::a11y::AttributeInvoker;
using content::a11y::AXLineIndexer; using content::a11y::ChildrenOf;
using content::a11y::CocoaLineIndexer; using content::a11y::IsAXUIElement;
using content::a11y::IsBrowserAccessibilityCocoa;
using content::a11y::LineIndexer; using content::a11y::LineIndexer;
using content::a11y::OptionalNSObject; using content::a11y::OptionalNSObject;
using std::string; using std::string;
...@@ -150,7 +151,7 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTree( ...@@ -150,7 +151,7 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTree(
BrowserAccessibility* root) { BrowserAccessibility* root) {
DCHECK(root); DCHECK(root);
BrowserAccessibilityCocoa* cocoa_root = ToBrowserAccessibilityCocoa(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); std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
RecursiveBuildAccessibilityTree(cocoa_root, &line_indexer, dict.get()); RecursiveBuildAccessibilityTree(cocoa_root, &line_indexer, dict.get());
return dict; return dict;
...@@ -160,7 +161,7 @@ std::unique_ptr<base::DictionaryValue> ...@@ -160,7 +161,7 @@ std::unique_ptr<base::DictionaryValue>
AccessibilityTreeFormatterMac::BuildAccessibilityTreeForWindow( AccessibilityTreeFormatterMac::BuildAccessibilityTreeForWindow(
gfx::AcceleratedWidget widget) { gfx::AcceleratedWidget widget) {
AXUIElementRef application = AXUIElementCreateApplication(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); std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
RecursiveBuildAccessibilityTree(static_cast<id>(application), &line_indexer, RecursiveBuildAccessibilityTree(static_cast<id>(application), &line_indexer,
dict.get()); dict.get());
...@@ -178,31 +179,22 @@ void AccessibilityTreeFormatterMac::RecursiveBuildAccessibilityTree( ...@@ -178,31 +179,22 @@ void AccessibilityTreeFormatterMac::RecursiveBuildAccessibilityTree(
const id node, const id node,
const LineIndexer* line_indexer, const LineIndexer* line_indexer,
base::DictionaryValue* dict) const { base::DictionaryValue* dict) const {
NSArray* children = nil; if (IsAXUIElement(node)) {
if (CFGetTypeID(node) == AXUIElementGetTypeID()) {
AddProperties(static_cast<AXUIElementRef>(node), line_indexer, dict); AddProperties(static_cast<AXUIElementRef>(node), line_indexer, dict);
CFTypeRef children_ref; } else if (IsBrowserAccessibilityCocoa(node)) {
if ((AXUIElementCopyAttributeValue(static_cast<AXUIElementRef>(node),
kAXChildrenAttribute, &children_ref)) ==
kAXErrorSuccess) {
children = static_cast<NSArray*>(children_ref);
}
} else if ([node isKindOfClass:[BrowserAccessibilityCocoa class]]) {
AddProperties(static_cast<BrowserAccessibilityCocoa*>(node), line_indexer, AddProperties(static_cast<BrowserAccessibilityCocoa*>(node), line_indexer,
dict); dict);
children = [node children];
} }
if (children) { NSArray* children = ChildrenOf(node);
auto child_dict_list = std::make_unique<base::ListValue>(); auto child_dict_list = std::make_unique<base::ListValue>();
for (id child in children) { for (id child in children) {
std::unique_ptr<base::DictionaryValue> child_dict( std::unique_ptr<base::DictionaryValue> child_dict(
new base::DictionaryValue); new base::DictionaryValue);
RecursiveBuildAccessibilityTree(child, line_indexer, child_dict.get()); RecursiveBuildAccessibilityTree(child, line_indexer, child_dict.get());
child_dict_list->Append(std::move(child_dict)); child_dict_list->Append(std::move(child_dict));
}
dict->Set(kChildrenDictAttr, std::move(child_dict_list));
} }
dict->Set(kChildrenDictAttr, std::move(child_dict_list));
} }
void AccessibilityTreeFormatterMac::AddProperties( void AccessibilityTreeFormatterMac::AddProperties(
......
...@@ -11,48 +11,40 @@ ...@@ -11,48 +11,40 @@
namespace content { namespace content {
namespace a11y { 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 * Converts accessible node object to a line index in the formatted
* accessibility tree, the node is placed at, and vice versa. * accessibility tree, the node is placed at, and vice versa.
*/ */
class LineIndexer { class LineIndexer final {
public: public:
LineIndexer(); LineIndexer(const gfx::NativeViewAccessible node);
virtual ~LineIndexer(); virtual ~LineIndexer();
std::string IndexBy(const gfx::NativeViewAccessible node) const; std::string IndexBy(const gfx::NativeViewAccessible node) const;
gfx::NativeViewAccessible NodeBy(const std::string& index) const; gfx::NativeViewAccessible NodeBy(const std::string& index) const;
protected: private:
virtual NSArray* Children(const gfx::NativeViewAccessible node) const = 0;
void Build(const gfx::NativeViewAccessible node, int* counter); void Build(const gfx::NativeViewAccessible node, int* counter);
private:
std::map<const gfx::NativeViewAccessible, std::string> map; 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 // Implements stateful id values. Can be either id or be in
// error or not applciable state. Similar to base::Optional, but tri-state // error or not applciable state. Similar to base::Optional, but tri-state
// allowing nullable values. // allowing nullable values.
......
...@@ -49,9 +49,40 @@ namespace { ...@@ -49,9 +49,40 @@ namespace {
} // 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 // Line indexers
LineIndexer::LineIndexer() {} LineIndexer::LineIndexer(const gfx::NativeViewAccessible node) {
int counter = 0;
Build(node, &counter);
}
LineIndexer::~LineIndexer() {} LineIndexer::~LineIndexer() {}
std::string LineIndexer::IndexBy(const gfx::NativeViewAccessible node) const { std::string LineIndexer::IndexBy(const gfx::NativeViewAccessible node) const {
...@@ -76,36 +107,12 @@ void LineIndexer::Build(const gfx::NativeViewAccessible node, int* counter) { ...@@ -76,36 +107,12 @@ void LineIndexer::Build(const gfx::NativeViewAccessible node, int* counter) {
const std::string line_index = const std::string line_index =
std::string(1, ':') + base::NumberToString(++(*counter)); std::string(1, ':') + base::NumberToString(++(*counter));
map.insert({node, line_index}); map.insert({node, line_index});
NSArray* children = Children(node); NSArray* children = ChildrenOf(node);
for (gfx::NativeViewAccessible child in children) { for (gfx::NativeViewAccessible child in children) {
Build(child, counter); 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::AttributeInvoker(const BrowserAccessibilityCocoa* cocoa_node, 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