#ifndef UI_ACCESSIBILITY_PLATFORM_BROWSER_ACCESSIBILITY_H_
#define UI_ACCESSIBILITY_PLATFORM_BROWSER_ACCESSIBILITY_H_
#include <stdint.h>
#include <cstddef>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom-forward.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/platform/ax_platform_node_id.h"
#include "ui/accessibility/platform/child_iterator.h"
#include "ui/base/buildflags.h"
#if BUILDFLAG(IS_MAC) && __OBJC__
@class BrowserAccessibilityCocoa;
#endif
namespace content {
class DumpAccessibilityTestBase;
}
namespace ui {
class AXPlatformNode;
class BrowserAccessibilityManager;
class COMPONENT_EXPORT(AX_PLATFORM) BrowserAccessibility
: public AXPlatformNodeDelegate {
public:
static std::unique_ptr<BrowserAccessibility> Create(
BrowserAccessibilityManager* manager,
AXNode* node);
static BrowserAccessibility* FromAXPlatformNodeDelegate(
AXPlatformNodeDelegate* delegate);
~BrowserAccessibility() override;
BrowserAccessibility(const BrowserAccessibility&) = delete;
BrowserAccessibility& operator=(const BrowserAccessibility&) = delete;
virtual void OnDataChanged();
virtual void OnLocationChanged() {}
virtual void UpdatePlatformAttributes() {}
bool IsDescendantOf(const BrowserAccessibility* ancestor) const;
bool IsIgnoredForTextNavigation() const;
bool IsLineBreakObject() const;
bool HasDefaultAction() const;
virtual bool CanFireEvents() const;
virtual AXPlatformNode* GetAXPlatformNode() const;
virtual size_t PlatformChildCount() const;
virtual BrowserAccessibility* PlatformGetChild(size_t child_index) const;
BrowserAccessibility* PlatformGetParent() const;
virtual BrowserAccessibility* PlatformGetFirstChild() const;
virtual BrowserAccessibility* PlatformGetLastChild() const;
virtual BrowserAccessibility* PlatformGetNextSibling() const;
virtual BrowserAccessibility* PlatformGetPreviousSibling() const;
class COMPONENT_EXPORT(AX_PLATFORM) PlatformChildIterator
: public ChildIterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using difference_type = int;
using value_type = BrowserAccessibility;
using pointer = BrowserAccessibility*;
using reference = BrowserAccessibility&;
PlatformChildIterator(const BrowserAccessibility* parent,
BrowserAccessibility* child);
PlatformChildIterator(const PlatformChildIterator& it);
~PlatformChildIterator() override;
PlatformChildIterator& operator++() override;
PlatformChildIterator operator++(int);
PlatformChildIterator& operator--() override;
PlatformChildIterator operator--(int);
gfx::NativeViewAccessible GetNativeViewAccessible() const override;
BrowserAccessibility* get() const override;
std::optional<size_t> GetIndexInParent() const override;
BrowserAccessibility& operator*() const override;
BrowserAccessibility* operator->() const override;
private:
raw_ptr<const BrowserAccessibility> parent_;
AXNode::ChildIteratorBase<BrowserAccessibility,
&BrowserAccessibility::PlatformGetNextSibling,
&BrowserAccessibility::PlatformGetPreviousSibling,
&BrowserAccessibility::PlatformGetFirstChild,
&BrowserAccessibility::PlatformGetLastChild>
platform_iterator;
};
class PlatformChildrenRange {
public:
explicit PlatformChildrenRange(const BrowserAccessibility* parent)
: parent_(parent) {}
PlatformChildrenRange(const PlatformChildrenRange&) = default;
PlatformChildIterator begin() { return parent_->PlatformChildrenBegin(); }
PlatformChildIterator end() { return parent_->PlatformChildrenEnd(); }
std::reverse_iterator<PlatformChildIterator> rbegin() {
return std::reverse_iterator(parent_->PlatformChildrenEnd());
}
std::reverse_iterator<PlatformChildIterator> rend() {
return std::reverse_iterator(parent_->PlatformChildrenBegin());
}
private:
const raw_ptr<const BrowserAccessibility> parent_;
};
PlatformChildrenRange PlatformChildren() const {
return PlatformChildrenRange(this);
}
PlatformChildIterator PlatformChildrenBegin() const;
PlatformChildIterator PlatformChildrenEnd() const;
virtual BrowserAccessibility* PlatformGetLowestPlatformAncestor() const;
BrowserAccessibility* PlatformGetTextFieldAncestor() const;
BrowserAccessibility* PlatformGetSelectionContainer() const;
BrowserAccessibility* PlatformDeepestFirstChild() const;
BrowserAccessibility* PlatformDeepestLastChild() const;
BrowserAccessibility* InternalDeepestFirstChild() const;
BrowserAccessibility* InternalDeepestLastChild() const;
class AllChildrenRange final {
public:
explicit AllChildrenRange(const BrowserAccessibility* parent)
: parent_(parent),
child_tree_root_(parent->PlatformGetRootOfChildTree()) {}
AllChildrenRange(const AllChildrenRange&) = default;
class COMPONENT_EXPORT(AX_PLATFORM) Iterator final {
public:
using iterator_category = std::input_iterator_tag;
using value_type = BrowserAccessibility*;
using difference_type = std::ptrdiff_t;
using pointer = BrowserAccessibility**;
using reference = BrowserAccessibility*&;
Iterator(const BrowserAccessibility* parent,
const BrowserAccessibility* child_tree_root,
unsigned int index = 0U)
: parent_(parent), child_tree_root_(child_tree_root), index_(index) {}
Iterator(const Iterator&) = default;
~Iterator() = default;
Iterator& operator++() {
++index_;
return *this;
}
Iterator operator++(int) {
Iterator tmp(*this);
operator++();
return tmp;
}
bool operator==(const Iterator& rhs) const {
return parent_ == rhs.parent_ && index_ == rhs.index_;
}
const BrowserAccessibility* operator*();
private:
const raw_ptr<const BrowserAccessibility> parent_;
const raw_ptr<const BrowserAccessibility> child_tree_root_;
unsigned int index_;
};
Iterator begin() { return {parent_, child_tree_root_}; }
Iterator end() {
unsigned int count =
child_tree_root_
? 1U
: static_cast<unsigned int>(parent_->node()->children().size());
return {parent_, child_tree_root_, count};
}
private:
const raw_ptr<const BrowserAccessibility, DanglingUntriaged> parent_;
const raw_ptr<const BrowserAccessibility, DanglingUntriaged>
child_tree_root_;
};
AllChildrenRange AllChildren() const { return AllChildrenRange(this); }
gfx::Rect GetUnclippedRootFrameInnerTextRangeBoundsRect(
const int start_offset,
const int end_offset,
AXOffscreenResult* offscreen_result = nullptr) const;
gfx::Rect GetScreenHypertextRangeBoundsRect(
int start,
int len,
const AXClippingBehavior clipping_behavior,
AXOffscreenResult* offscreen_result = nullptr) const;
gfx::Rect GetRootFrameHypertextRangeBoundsRect(
int start,
int len,
const AXClippingBehavior clipping_behavior,
AXOffscreenResult* offscreen_result = nullptr) const;
BrowserAccessibility* ApproximateHitTest(
const gfx::Point& blink_screen_point);
BrowserAccessibilityManager* manager() const { return manager_; }
size_t InternalChildCount() const;
BrowserAccessibility* InternalGetChild(size_t child_index) const;
BrowserAccessibility* InternalGetParent() const;
BrowserAccessibility* InternalGetFirstChild() const;
BrowserAccessibility* InternalGetLastChild() const;
BrowserAccessibility* InternalGetNextSibling() const;
BrowserAccessibility* InternalGetPreviousSibling() const;
using InternalChildIterator = AXNode::ChildIteratorBase<
BrowserAccessibility,
&BrowserAccessibility::InternalGetNextSibling,
&BrowserAccessibility::InternalGetPreviousSibling,
&BrowserAccessibility::InternalGetFirstChild,
&BrowserAccessibility::InternalGetLastChild>;
InternalChildIterator InternalChildrenBegin() const;
InternalChildIterator InternalChildrenEnd() const;
gfx::RectF GetLocation() const;
virtual bool IsClickable() const;
bool IsTextField() const;
bool IsPasswordField() const;
bool IsAtomicTextField() const;
bool IsNonAtomicTextField() const;
bool HasExplicitlyEmptyName() const;
AXPosition CreatePositionForSelectionAt(int offset) const;
std::u16string GetNameAsString16() const;
gfx::NativeViewAccessible GetParent() const override;
size_t GetChildCount() const override;
gfx::NativeViewAccessible ChildAtIndex(size_t index) const override;
gfx::NativeViewAccessible GetFirstChild() const override;
gfx::NativeViewAccessible GetLastChild() const override;
gfx::NativeViewAccessible GetNextSibling() const override;
gfx::NativeViewAccessible GetPreviousSibling() const override;
bool IsPlatformDocument() const override;
bool IsLeaf() const override;
bool IsFocused() const override;
gfx::NativeViewAccessible GetLowestPlatformAncestor() const override;
gfx::NativeViewAccessible GetTextFieldAncestor() const override;
gfx::NativeViewAccessible GetSelectionContainer() const override;
gfx::NativeViewAccessible GetTableAncestor() const override;
std::unique_ptr<ChildIterator> ChildrenBegin() const override;
std::unique_ptr<ChildIterator> ChildrenEnd() const override;
bool SetHypertextSelection(int start_offset, int end_offset) override;
gfx::Rect GetBoundsRect(
const AXCoordinateSystem coordinate_system,
const AXClippingBehavior clipping_behavior,
AXOffscreenResult* offscreen_result = nullptr) const override;
gfx::Rect GetHypertextRangeBoundsRect(
const int start_offset,
const int end_offset,
const AXCoordinateSystem coordinate_system,
const AXClippingBehavior clipping_behavior,
AXOffscreenResult* offscreen_result = nullptr) const override;
gfx::Rect GetInnerTextRangeBoundsRect(
const int start_offset,
const int end_offset,
const AXCoordinateSystem coordinate_system,
const AXClippingBehavior clipping_behavior,
AXOffscreenResult* offscreen_result = nullptr) const override;
gfx::NativeViewAccessible HitTestSync(int physical_pixel_x,
int physical_pixel_y) const override;
gfx::NativeViewAccessible GetFocus() const override;
AXPlatformNode* GetFromNodeID(int32_t id) override;
AXPlatformNode* GetFromTreeIDAndNodeID(const AXTreeID& ax_tree_id,
int32_t id) override;
std::optional<size_t> GetIndexInParent() const override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
const std::vector<gfx::NativeViewAccessible> GetUIADirectChildrenInRange(
AXPlatformNodeDelegate* start,
AXPlatformNodeDelegate* end) override;
AXPlatformNode* GetTableCaption() const override;
bool AccessibilityPerformAction(const AXActionData& data) override;
#if !BUILDFLAG(IS_FUCHSIA)
virtual std::u16string GetLocalizedString(int message_id) const;
std::u16string GetLocalizedStringForImageAnnotationStatus(
ax::mojom::ImageAnnotationStatus status) const override;
std::u16string GetLocalizedRoleDescriptionForUnlabeledImage() const override;
std::u16string GetLocalizedStringForLandmarkType() const override;
std::u16string GetLocalizedStringForRoleDescription() const override;
std::u16string GetStyleNameAttributeAsLocalizedString() const override;
#endif
TextAttributeMap ComputeTextAttributeMap(
const TextAttributeList& default_attributes) const override;
bool ShouldIgnoreHoveredStateForTesting() override;
bool IsOffscreen() const override;
bool IsWebContent() const override;
bool HasVisibleCaretOrSelection() const override;
std::vector<AXPlatformNode*> GetSourceNodesForReverseRelations(
ax::mojom::IntAttribute attr) override;
std::vector<AXPlatformNode*> GetSourceNodesForReverseRelations(
ax::mojom::IntListAttribute attr) override;
std::optional<int> GetPosInSet() const override;
std::optional<int> GetSetSize() const override;
bool IsInListMarker() const;
BrowserAccessibility* GetCollapsedMenuListSelectAncestor() const;
BrowserAccessibility* GetExtraAnnouncementNode(
ax::mojom::AriaNotificationPriority priority_property) const;
bool IsHierarchicalList() const;
std::string ToString() const;
protected:
BrowserAccessibility(BrowserAccessibilityManager* manager, AXNode* node);
virtual TextAttributeList ComputeTextAttributes() const;
const raw_ptr<BrowserAccessibilityManager> manager_;
AXPlatformNodeId GetUniqueId() const override;
TextAttributeMap GetSpellingAndGrammarAttributes() const;
std::string SubtreeToStringHelper(size_t level) override;
friend class AccessibilityTreeFormatterUia;
friend class content::DumpAccessibilityTestBase;
private:
gfx::Rect RelativeToAbsoluteBounds(gfx::RectF bounds,
const AXCoordinateSystem coordinate_system,
const AXClippingBehavior clipping_behavior,
AXOffscreenResult* offscreen_result) const;
gfx::Rect GetRootFrameHypertextBoundsPastEndOfText(
const AXClippingBehavior clipping_behavior,
AXOffscreenResult* offscreen_result = nullptr) const;
gfx::RectF GetTextContentRangeBoundsUTF16(int start_offset,
int end_offset) const;
gfx::Rect GetInnerTextRangeBoundsRectInSubtree(
const int start_offset,
const int end_offset,
const AXCoordinateSystem coordinate_system,
const AXClippingBehavior clipping_behavior,
AXOffscreenResult* offscreen_result) const;
BrowserAccessibility* PlatformGetRootOfChildTree() const;
bool IsValid() const;
bool HasExtraAnnouncementNodes() const;
size_t PlatformChildCountWithoutAnnouncementNodes() const;
static void MergeSpellingAndGrammarIntoTextAttributes(
const TextAttributeMap& spelling_attributes,
int start_offset,
TextAttributeMap* text_attributes);
static bool HasInvalidAttribute(const TextAttributeList& attributes);
static bool ignore_hovered_state_for_testing_;
mutable AXPlatformNodeId unique_id_;
};
}
#endif