| // Copyright 2016 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/browser_accessibility_position.h" |
| |
| #include "build/build_config.h" |
| #include "content/browser/accessibility/accessibility_flags.h" |
| #include "content/browser/accessibility/browser_accessibility.h" |
| #include "content/browser/accessibility/browser_accessibility_manager.h" |
| #include "ui/accessibility/ax_enums.h" |
| |
| namespace content { |
| |
| BrowserAccessibilityPosition::BrowserAccessibilityPosition() {} |
| |
| BrowserAccessibilityPosition::~BrowserAccessibilityPosition() {} |
| |
| BrowserAccessibilityPosition::AXPositionInstance |
| BrowserAccessibilityPosition::Clone() const { |
| return AXPositionInstance(new BrowserAccessibilityPosition(*this)); |
| } |
| |
| base::string16 BrowserAccessibilityPosition::GetInnerText() const { |
| if (IsNullPosition()) |
| return base::string16(); |
| DCHECK(GetAnchor()); |
| return GetAnchor()->GetText(); |
| } |
| |
| void BrowserAccessibilityPosition::AnchorChild(int child_index, |
| AXTreeID* tree_id, |
| int32_t* child_id) const { |
| DCHECK(tree_id); |
| DCHECK(child_id); |
| |
| if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) { |
| *tree_id = INVALID_TREE_ID; |
| *child_id = INVALID_ANCHOR_ID; |
| return; |
| } |
| |
| BrowserAccessibility* child = nullptr; |
| if (GetAnchor()->PlatformIsLeaf()) { |
| child = GetAnchor()->InternalGetChild(child_index); |
| } else { |
| child = GetAnchor()->PlatformGetChild(child_index); |
| } |
| DCHECK(child); |
| *tree_id = child->manager()->ax_tree_id(); |
| *child_id = child->GetId(); |
| } |
| |
| int BrowserAccessibilityPosition::AnchorChildCount() const { |
| if (!GetAnchor()) |
| return 0; |
| |
| if (GetAnchor()->PlatformIsLeaf()) { |
| return static_cast<int>(GetAnchor()->InternalChildCount()); |
| } else { |
| return static_cast<int>(GetAnchor()->PlatformChildCount()); |
| } |
| } |
| |
| int BrowserAccessibilityPosition::AnchorIndexInParent() const { |
| return GetAnchor() ? static_cast<int>(GetAnchor()->GetIndexInParent()) |
| : AXPosition::INVALID_INDEX; |
| } |
| |
| void BrowserAccessibilityPosition::AnchorParent(AXTreeID* tree_id, |
| int32_t* parent_id) const { |
| DCHECK(tree_id); |
| DCHECK(parent_id); |
| |
| if (!GetAnchor() || !GetAnchor()->PlatformGetParent()) { |
| *tree_id = AXPosition::INVALID_TREE_ID; |
| *parent_id = AXPosition::INVALID_ANCHOR_ID; |
| return; |
| } |
| |
| BrowserAccessibility* parent = GetAnchor()->PlatformGetParent(); |
| *tree_id = parent->manager()->ax_tree_id(); |
| *parent_id = parent->GetId(); |
| } |
| |
| BrowserAccessibility* BrowserAccessibilityPosition::GetNodeInTree( |
| AXTreeID tree_id, |
| int32_t node_id) const { |
| if (tree_id == AXPosition::INVALID_TREE_ID || |
| node_id == AXPosition::INVALID_ANCHOR_ID) { |
| return nullptr; |
| } |
| |
| auto* manager = BrowserAccessibilityManager::FromID(tree_id); |
| if (!manager) |
| return nullptr; |
| return manager->GetFromID(node_id); |
| } |
| |
| int BrowserAccessibilityPosition::MaxTextOffset() const { |
| if (IsNullPosition()) |
| return INVALID_OFFSET; |
| return static_cast<int>(GetInnerText().length()); |
| } |
| |
| // On some platforms, most objects are represented in the text of their parents |
| // with a special (embedded object) character and not with their actual text |
| // contents. |
| int BrowserAccessibilityPosition::MaxTextOffsetInParent() const { |
| #if defined(OS_WIN) || BUILDFLAG(USE_ATK) |
| if (IsNullPosition()) |
| return INVALID_OFFSET; |
| if (GetAnchor()->IsTextOnlyObject()) |
| return MaxTextOffset(); |
| // Not all objects in the internal accessibility tree are exposed to platform |
| // APIs. |
| if (GetAnchor()->PlatformIsChildOfLeaf()) |
| return MaxTextOffset(); |
| return 1; |
| #else |
| return MaxTextOffset(); |
| #endif |
| } |
| |
| bool BrowserAccessibilityPosition::IsInLineBreak() const { |
| if (IsNullPosition()) |
| return false; |
| |
| DCHECK(GetAnchor()); |
| return GetAnchor()->IsLineBreakObject(); |
| } |
| |
| std::vector<int32_t> BrowserAccessibilityPosition::GetWordStartOffsets() const { |
| if (IsNullPosition()) |
| return std::vector<int32_t>(); |
| DCHECK(GetAnchor()); |
| return GetAnchor()->GetIntListAttribute(ui::AX_ATTR_WORD_STARTS); |
| } |
| |
| std::vector<int32_t> BrowserAccessibilityPosition::GetWordEndOffsets() const { |
| if (IsNullPosition()) |
| return std::vector<int32_t>(); |
| DCHECK(GetAnchor()); |
| return GetAnchor()->GetIntListAttribute(ui::AX_ATTR_WORD_ENDS); |
| } |
| |
| int32_t BrowserAccessibilityPosition::GetNextOnLineID(int32_t node_id) const { |
| if (IsNullPosition()) |
| return INVALID_ANCHOR_ID; |
| BrowserAccessibility* node = GetNodeInTree(tree_id(), node_id); |
| int next_on_line_id; |
| if (!node || |
| !node->GetIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID, &next_on_line_id)) { |
| return INVALID_ANCHOR_ID; |
| } |
| return static_cast<int32_t>(next_on_line_id); |
| } |
| |
| int32_t BrowserAccessibilityPosition::GetPreviousOnLineID( |
| int32_t node_id) const { |
| if (IsNullPosition()) |
| return INVALID_ANCHOR_ID; |
| BrowserAccessibility* node = GetNodeInTree(tree_id(), node_id); |
| int previous_on_line_id; |
| if (!node || !node->GetIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID, |
| &previous_on_line_id)) { |
| return INVALID_ANCHOR_ID; |
| } |
| return static_cast<int32_t>(previous_on_line_id); |
| } |
| |
| } // namespace content |