Commit 6ac9b1c6 authored by Alexander Surkov's avatar Alexander Surkov Committed by Commit Bot

ax_dump_tools: share mac utils between tree formatter and event recorder

Bug: 1131921
Change-Id: I6fb257c7521e6a85ca734b6606e6ea499e696492
AX-Relnotes: n/a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2435818Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Alexander Surkov <asurkov@igalia.com>
Cr-Commit-Position: refs/heads/master@{#812070}
parent 535eff1d
...@@ -334,6 +334,8 @@ source_set("browser") { ...@@ -334,6 +334,8 @@ source_set("browser") {
"accessibility/accessibility_event_recorder_uia_win.cc", "accessibility/accessibility_event_recorder_uia_win.cc",
"accessibility/accessibility_event_recorder_uia_win.h", "accessibility/accessibility_event_recorder_uia_win.h",
"accessibility/accessibility_event_recorder_win.cc", "accessibility/accessibility_event_recorder_win.cc",
"accessibility/accessibility_tools_utils_mac.h",
"accessibility/accessibility_tools_utils_mac.mm",
"accessibility/accessibility_tree_formatter_base.cc", "accessibility/accessibility_tree_formatter_base.cc",
"accessibility/accessibility_tree_formatter_base.h", "accessibility/accessibility_tree_formatter_base.h",
"accessibility/accessibility_tree_formatter_blink.cc", "accessibility/accessibility_tree_formatter_blink.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TOOLS_UTILS_MAC_H_
#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TOOLS_UTILS_MAC_H_
#import <Cocoa/Cocoa.h>
#include "base/callback.h"
#include "content/public/browser/accessibility_tree_formatter.h"
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);
/**
* Returns (parameterized) attributes of an accessible object, (either
* AXUIElement or BrowserAccessibilityCocoa).
*/
NSArray* AttributeNamesOf(const id node);
NSArray* ParameterizedAttributeNamesOf(const id node);
/**
* Returns (parameterized) attribute value on a given node (either AXUIElement
* or BrowserAccessibilityCocoa)
*/
id AttributeValueOf(const id node, NSString* attribute);
id ParameterizedAttributeValueOf(const id node,
NSString* attribute,
id parameter);
/**
* Return AXElement in a tree by a given criteria.
*/
using FindCriteria = base::RepeatingCallback<bool(const AXUIElementRef)>;
AXUIElementRef FindAXUIElement(const AXUIElementRef node,
const FindCriteria& criteria);
/**
* Returns AXUIElement by a given tree selector.
*/
AXUIElementRef FindAXUIElement(const AccessibilityTreeFormatter::TreeSelector&);
} // namespace a11y
} // namespace content
#endif // CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TOOLS_UTILS_MAC_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/accessibility/accessibility_tools_utils_mac.h"
#include "base/strings/sys_string_conversions.h"
#include "content/browser/accessibility/browser_accessibility_cocoa.h"
// error: 'accessibilityAttributeNames' is deprecated: first deprecated in
// macOS 10.10 - Use the NSAccessibility protocol methods instead (see
// NSAccessibilityProtocols.h
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
namespace content {
namespace a11y {
using TreeSelector = AccessibilityTreeFormatter::TreeSelector;
using base::SysNSStringToUTF8;
const char kChromeTitle[] = "Google Chrome";
const char kChromiumTitle[] = "Chromium";
const char kFirefoxTitle[] = "Firefox";
const char kSafariTitle[] = "Safari";
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;
}
NSArray* AttributeNamesOf(const id node) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node accessibilityAttributeNames];
}
if (IsAXUIElement(node)) {
CFArrayRef attributes_ref;
if (AXUIElementCopyAttributeNames(static_cast<AXUIElementRef>(node),
&attributes_ref) == kAXErrorSuccess) {
return static_cast<NSArray*>(attributes_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
NSArray* ParameterizedAttributeNamesOf(const id node) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node accessibilityParameterizedAttributeNames];
}
if (IsAXUIElement(node)) {
CFArrayRef attributes_ref;
if (AXUIElementCopyParameterizedAttributeNames(
static_cast<AXUIElementRef>(node), &attributes_ref) ==
kAXErrorSuccess) {
return static_cast<NSArray*>(attributes_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
id AttributeValueOf(const id node, NSString* attribute) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node accessibilityAttributeValue:attribute];
}
if (IsAXUIElement(node)) {
CFTypeRef value_ref;
if ((AXUIElementCopyAttributeValue(static_cast<AXUIElementRef>(node),
static_cast<CFStringRef>(attribute),
&value_ref)) == kAXErrorSuccess) {
return static_cast<id>(value_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
id ParameterizedAttributeValueOf(const id node,
NSString* attribute,
id parameter) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node accessibilityAttributeValue:attribute forParameter:parameter];
}
if (IsAXUIElement(node)) {
CFTypeRef value_ref;
if ((AXUIElementCopyParameterizedAttributeValue(
static_cast<AXUIElementRef>(node),
static_cast<CFStringRef>(attribute),
static_cast<CFTypeRef>(parameter), &value_ref)) ==
kAXErrorSuccess) {
return static_cast<id>(value_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
AXUIElementRef FindAXUIElement(const AXUIElementRef node,
const FindCriteria& criteria) {
if (criteria.Run(node)) {
return node;
}
NSArray* children = ChildrenOf(static_cast<id>(node));
for (id child in children) {
AXUIElementRef found =
FindAXUIElement(static_cast<AXUIElementRef>(child), criteria);
if (found != nil) {
return found;
}
}
return nil;
}
AXUIElementRef FindAXUIElement(
const AccessibilityTreeFormatter::TreeSelector& selector) {
NSArray* windows = static_cast<NSArray*>(CGWindowListCopyWindowInfo(
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
kCGNullWindowID));
std::string title;
if (selector.types & TreeSelector::Chrome) {
title = kChromeTitle;
} else if (selector.types & TreeSelector::Chromium) {
title = kChromiumTitle;
} else if (selector.types & TreeSelector::Firefox) {
title = kFirefoxTitle;
} else if (selector.types & TreeSelector::Safari) {
title = kSafariTitle;
}
for (NSDictionary* window_info in windows) {
NSNumber* pid =
static_cast<NSNumber*>([window_info objectForKey:@"kCGWindowOwnerPID"]);
std::string window_name = SysNSStringToUTF8(static_cast<NSString*>(
[window_info objectForKey:@"kCGWindowOwnerName"]));
if (window_name == selector.pattern) {
return AXUIElementCreateApplication([pid intValue]);
}
if (window_name == title) {
AXUIElementRef node = AXUIElementCreateApplication([pid intValue]);
if (selector.types & TreeSelector::ActiveTab) {
node = FindAXUIElement(
node, base::BindRepeating([](const AXUIElementRef node) {
// Only active tab in exposed in browsers, thus find first
// AXWebArea role.
NSString* role = AttributeValueOf(static_cast<id>(node),
NSAccessibilityRoleAttribute);
return SysNSStringToUTF8(role) == "AXWebArea";
}));
}
if (node) {
return node;
}
}
}
return nil;
}
} // namespace a11y
} // namespace content
#pragma clang diagnostic pop
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/values.h" #include "base/values.h"
#include "content/browser/accessibility/accessibility_tools_utils_mac.h"
#include "content/browser/accessibility/accessibility_tree_formatter_blink.h" #include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
#include "content/browser/accessibility/accessibility_tree_formatter_utils_mac.h" #include "content/browser/accessibility/accessibility_tree_formatter_utils_mac.h"
#include "content/browser/accessibility/browser_accessibility_mac.h" #include "content/browser/accessibility/browser_accessibility_mac.h"
...@@ -51,11 +52,6 @@ const char kConstValuePrefix[] = "_const_"; ...@@ -51,11 +52,6 @@ const char kConstValuePrefix[] = "_const_";
const char kNULLValue[] = "_const_NULL"; const char kNULLValue[] = "_const_NULL";
const char kFailedToParseArgsError[] = "_const_ERROR:FAILED_TO_PARSE_ARGS"; const char kFailedToParseArgsError[] = "_const_ERROR:FAILED_TO_PARSE_ARGS";
const char kChromeTitle[] = "Google Chrome";
const char kChromiumTitle[] = "Chromium";
const char kFirefoxTitle[] = "Firefox";
const char kSafariTitle[] = "Safari";
} // namespace } // namespace
class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase { class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase {
...@@ -77,10 +73,6 @@ class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase { ...@@ -77,10 +73,6 @@ class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase {
std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForAXUIElement( std::unique_ptr<base::DictionaryValue> BuildAccessibilityTreeForAXUIElement(
AXUIElementRef node) const; AXUIElementRef node) const;
// Return AXElement in a tree by a given criteria
using FindCriteria = base::RepeatingCallback<bool(id)>;
id FindAXUIElement(const id node, const FindCriteria& criteria) const;
void RecursiveBuildAccessibilityTree(const id node, void RecursiveBuildAccessibilityTree(const id node,
const LineIndexer* line_indexer, const LineIndexer* line_indexer,
base::DictionaryValue* dict) const; base::DictionaryValue* dict) const;
...@@ -180,50 +172,8 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTreeForWindow( ...@@ -180,50 +172,8 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTreeForWindow(
std::unique_ptr<base::DictionaryValue> std::unique_ptr<base::DictionaryValue>
AccessibilityTreeFormatterMac::BuildAccessibilityTreeForSelector( AccessibilityTreeFormatterMac::BuildAccessibilityTreeForSelector(
const TreeSelector& selector) { const TreeSelector& selector) {
NSArray* windows = (NSArray*)CGWindowListCopyWindowInfo( AXUIElementRef node = a11y::FindAXUIElement(selector);
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, return node != nil ? BuildAccessibilityTreeForAXUIElement(node) : nil;
kCGNullWindowID);
std::string title;
if (selector.types & TreeSelector::Chrome) {
title = kChromeTitle;
} else if (selector.types & TreeSelector::Chromium) {
title = kChromiumTitle;
} else if (selector.types & TreeSelector::Firefox) {
title = kFirefoxTitle;
} else if (selector.types & TreeSelector::Safari) {
title = kSafariTitle;
}
for (NSDictionary* window_info in windows) {
NSNumber* pid =
static_cast<NSNumber*>([window_info objectForKey:@"kCGWindowOwnerPID"]);
std::string window_name = SysNSStringToUTF8(static_cast<NSString*>(
[window_info objectForKey:@"kCGWindowOwnerName"]));
if (window_name == selector.pattern) {
return BuildAccessibilityTreeForWindow([pid intValue]);
}
if (window_name == title) {
AXUIElementRef node = AXUIElementCreateApplication([pid intValue]);
if (selector.types & TreeSelector::ActiveTab) {
node = static_cast<AXUIElementRef>(FindAXUIElement(
static_cast<id>(node), base::BindRepeating([](const id node) {
// Only active tab in exposed in browsers, thus find first
// AXWebArea role.
NSString* role =
AttributeValueOf(node, NSAccessibilityRoleAttribute);
return SysNSStringToUTF8(role) == "AXWebArea";
})));
}
if (node) {
return BuildAccessibilityTreeForAXUIElement(node);
}
}
}
return nullptr;
} }
std::unique_ptr<base::DictionaryValue> std::unique_ptr<base::DictionaryValue>
...@@ -236,24 +186,6 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTreeForAXUIElement( ...@@ -236,24 +186,6 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTreeForAXUIElement(
return dict; return dict;
} }
id AccessibilityTreeFormatterMac::FindAXUIElement(
const id node,
const FindCriteria& criteria) const {
if (criteria.Run(node)) {
return node;
}
NSArray* children = ChildrenOf(node);
for (id child in children) {
id found = FindAXUIElement(child, criteria);
if (found != nil) {
return found;
}
}
return nil;
}
void AccessibilityTreeFormatterMac::RecursiveBuildAccessibilityTree( void AccessibilityTreeFormatterMac::RecursiveBuildAccessibilityTree(
const id node, const id node,
const LineIndexer* line_indexer, const LineIndexer* line_indexer,
......
...@@ -11,38 +11,6 @@ ...@@ -11,38 +11,6 @@
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);
/**
* Returns (parameterized) attributes of an accessible object, (either
* AXUIElement or BrowserAccessibilityCocoa).
*/
NSArray* AttributeNamesOf(const id node);
NSArray* ParameterizedAttributeNamesOf(const id node);
/**
* Returns (parameterized) attribute value on a given node (either AXUIElement
* or BrowserAccessibilityCocoa)
*/
id AttributeValueOf(const id node, NSString* attribute);
id ParameterizedAttributeValueOf(const id node,
NSString* attribute,
id parameter);
/** /**
* 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.
......
...@@ -5,12 +5,7 @@ ...@@ -5,12 +5,7 @@
#include "content/browser/accessibility/accessibility_tree_formatter_utils_mac.h" #include "content/browser/accessibility/accessibility_tree_formatter_utils_mac.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "content/browser/accessibility/accessibility_tools_utils_mac.h"
// error: 'accessibilityAttributeNames' is deprecated: first deprecated in
// macOS 10.10 - Use the NSAccessibility protocol methods instead (see
// NSAccessibilityProtocols.h
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
using base::SysNSStringToUTF8; using base::SysNSStringToUTF8;
...@@ -49,112 +44,6 @@ namespace { ...@@ -49,112 +44,6 @@ 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;
}
NSArray* AttributeNamesOf(const id node) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node accessibilityAttributeNames];
}
if (IsAXUIElement(node)) {
CFArrayRef attributes_ref;
if (AXUIElementCopyAttributeNames(static_cast<AXUIElementRef>(node),
&attributes_ref) == kAXErrorSuccess) {
return static_cast<NSArray*>(attributes_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
NSArray* ParameterizedAttributeNamesOf(const id node) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node accessibilityParameterizedAttributeNames];
}
if (IsAXUIElement(node)) {
CFArrayRef attributes_ref;
if (AXUIElementCopyParameterizedAttributeNames(
static_cast<AXUIElementRef>(node), &attributes_ref) ==
kAXErrorSuccess) {
return static_cast<NSArray*>(attributes_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
id AttributeValueOf(const id node, NSString* attribute) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node accessibilityAttributeValue:attribute];
}
if (IsAXUIElement(node)) {
CFTypeRef value_ref;
if ((AXUIElementCopyAttributeValue(static_cast<AXUIElementRef>(node),
static_cast<CFStringRef>(attribute),
&value_ref)) == kAXErrorSuccess) {
return static_cast<id>(value_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
id ParameterizedAttributeValueOf(const id node,
NSString* attribute,
id parameter) {
if (IsBrowserAccessibilityCocoa(node)) {
return [node accessibilityAttributeValue:attribute forParameter:parameter];
}
if (IsAXUIElement(node)) {
CFTypeRef value_ref;
if ((AXUIElementCopyParameterizedAttributeValue(
static_cast<AXUIElementRef>(node),
static_cast<CFStringRef>(attribute),
static_cast<CFTypeRef>(parameter), &value_ref)) ==
kAXErrorSuccess) {
return static_cast<id>(value_ref);
}
return nil;
}
NOTREACHED();
return nil;
}
// Line indexers // Line indexers
LineIndexer::LineIndexer(const gfx::NativeViewAccessible node) { LineIndexer::LineIndexer(const gfx::NativeViewAccessible node) {
...@@ -409,5 +298,3 @@ id AttributeInvoker::PropertyNodeToTextMarkerRange( ...@@ -409,5 +298,3 @@ id AttributeInvoker::PropertyNodeToTextMarkerRange(
} // namespace a11y } // namespace a11y
} // namespace content } // namespace content
#pragma clang diagnostic pop
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