blob: 6162f67da6d6e01888c71f582159eede53e05e10 [file] [log] [blame]
// Copyright 2019 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 "components/pdf/renderer/pdf_ax_action_target.h"
#include "components/pdf/renderer/pdf_accessibility_tree.h"
#include "pdf/accessibility_structs.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/gfx/geometry/rect_conversions.h"
namespace pdf {
namespace {
chrome_pdf::AccessibilityScrollAlignment ConvertAXScrollToPdfScrollAlignment(
ax::mojom::ScrollAlignment scroll_alignment) {
switch (scroll_alignment) {
case ax::mojom::ScrollAlignment::kScrollAlignmentCenter:
return chrome_pdf::AccessibilityScrollAlignment::kCenter;
case ax::mojom::ScrollAlignment::kScrollAlignmentTop:
return chrome_pdf::AccessibilityScrollAlignment::kTop;
case ax::mojom::ScrollAlignment::kScrollAlignmentBottom:
return chrome_pdf::AccessibilityScrollAlignment::kBottom;
case ax::mojom::ScrollAlignment::kScrollAlignmentLeft:
return chrome_pdf::AccessibilityScrollAlignment::kLeft;
case ax::mojom::ScrollAlignment::kScrollAlignmentRight:
return chrome_pdf::AccessibilityScrollAlignment::kRight;
case ax::mojom::ScrollAlignment::kScrollAlignmentClosestEdge:
return chrome_pdf::AccessibilityScrollAlignment::kClosestToEdge;
case ax::mojom::ScrollAlignment::kNone:
return chrome_pdf::AccessibilityScrollAlignment::kNone;
}
}
} // namespace
// static
const PdfAXActionTarget* PdfAXActionTarget::FromAXActionTarget(
const ui::AXActionTarget* ax_action_target) {
if (ax_action_target &&
ax_action_target->GetType() == ui::AXActionTarget::Type::kPdf) {
return static_cast<const PdfAXActionTarget*>(ax_action_target);
}
return nullptr;
}
PdfAXActionTarget::PdfAXActionTarget(const ui::AXNode& plugin_node,
PdfAccessibilityTree* pdf_tree_source)
: target_plugin_node_(plugin_node),
pdf_accessibility_tree_source_(pdf_tree_source) {
DCHECK(pdf_accessibility_tree_source_);
}
PdfAXActionTarget::~PdfAXActionTarget() = default;
ui::AXActionTarget::Type PdfAXActionTarget::GetType() const {
return ui::AXActionTarget::Type::kPdf;
}
bool PdfAXActionTarget::PerformAction(
const ui::AXActionData& action_data) const {
switch (action_data.action) {
case ax::mojom::Action::kDoDefault:
return Click();
case ax::mojom::Action::kShowContextMenu:
return ShowContextMenu();
case ax::mojom::Action::kScrollToPoint:
return ScrollToGlobalPoint(action_data.target_point);
default:
return false;
}
}
bool PdfAXActionTarget::Click() const {
if (target_plugin_node_.GetRole() != ax::mojom::Role::kLink)
return false;
absl::optional<PdfAccessibilityTree::AnnotationInfo> annotation_info_result =
pdf_accessibility_tree_source_->GetPdfAnnotationInfoFromAXNode(
target_plugin_node_.data().id);
if (!annotation_info_result.has_value())
return false;
const auto& annotation_info = annotation_info_result.value();
chrome_pdf::AccessibilityActionData pdf_action_data;
pdf_action_data.page_index = annotation_info.page_index;
pdf_action_data.annotation_index = annotation_info.annotation_index;
pdf_action_data.annotation_type =
chrome_pdf::AccessibilityAnnotationType::kLink;
pdf_action_data.action = chrome_pdf::AccessibilityAction::kDoDefaultAction;
pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
return true;
}
gfx::Rect PdfAXActionTarget::GetRelativeBounds() const {
return gfx::Rect();
}
gfx::Point PdfAXActionTarget::GetScrollOffset() const {
return gfx::Point();
}
gfx::Point PdfAXActionTarget::MinimumScrollOffset() const {
return gfx::Point();
}
gfx::Point PdfAXActionTarget::MaximumScrollOffset() const {
return gfx::Point();
}
void PdfAXActionTarget::SetScrollOffset(const gfx::Point& point) const {}
bool PdfAXActionTarget::SetSelected(bool selected) const {
return false;
}
bool PdfAXActionTarget::SetSelection(const ui::AXActionTarget* anchor_object,
int anchor_offset,
const ui::AXActionTarget* focus_object,
int focus_offset) const {
const PdfAXActionTarget* pdf_anchor_object =
FromAXActionTarget(anchor_object);
const PdfAXActionTarget* pdf_focus_object = FromAXActionTarget(focus_object);
if (!pdf_anchor_object || !pdf_focus_object || anchor_offset < 0 ||
focus_offset < 0) {
return false;
}
chrome_pdf::AccessibilityActionData pdf_action_data;
if (!pdf_accessibility_tree_source_->FindCharacterOffset(
pdf_anchor_object->AXNode(), anchor_offset,
pdf_action_data.selection_start_index) ||
!pdf_accessibility_tree_source_->FindCharacterOffset(
pdf_focus_object->AXNode(), focus_offset,
pdf_action_data.selection_end_index)) {
return false;
}
pdf_action_data.action = chrome_pdf::AccessibilityAction::kSetSelection;
pdf_action_data.target_rect =
gfx::ToEnclosingRect(target_plugin_node_.data().relative_bounds.bounds);
pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
return true;
}
bool PdfAXActionTarget::ShowContextMenu() const {
return pdf_accessibility_tree_source_->ShowContextMenu();
}
bool PdfAXActionTarget::ScrollToMakeVisible() const {
return false;
}
bool PdfAXActionTarget::ScrollToMakeVisibleWithSubFocus(
const gfx::Rect& rect,
ax::mojom::ScrollAlignment horizontal_scroll_alignment,
ax::mojom::ScrollAlignment vertical_scroll_alignment,
ax::mojom::ScrollBehavior scroll_behavior) const {
chrome_pdf::AccessibilityActionData pdf_action_data;
pdf_action_data.action =
chrome_pdf::AccessibilityAction::kScrollToMakeVisible;
pdf_action_data.horizontal_scroll_alignment =
ConvertAXScrollToPdfScrollAlignment(horizontal_scroll_alignment);
pdf_action_data.vertical_scroll_alignment =
ConvertAXScrollToPdfScrollAlignment(vertical_scroll_alignment);
pdf_action_data.target_rect =
gfx::ToEnclosingRect(target_plugin_node_.data().relative_bounds.bounds);
pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
return true;
}
bool PdfAXActionTarget::ScrollToGlobalPoint(const gfx::Point& point) const {
chrome_pdf::AccessibilityActionData pdf_action_data;
pdf_action_data.action =
chrome_pdf::AccessibilityAction::kScrollToGlobalPoint;
pdf_action_data.target_point = point;
pdf_action_data.target_rect =
gfx::ToEnclosingRect(target_plugin_node_.data().relative_bounds.bounds);
pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
return true;
}
} // namespace pdf