1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/pdf/renderer/pdf_ax_action_target.h"
6
7 #include "components/pdf/renderer/pdf_accessibility_tree.h"
8 #include "ui/accessibility/ax_enums.mojom.h"
9
10 namespace pdf {
11
12 namespace {
13
ConvertAXScrollToPdfScrollAlignment(ax::mojom::ScrollAlignment scroll_alignment)14 PP_PdfAccessibilityScrollAlignment ConvertAXScrollToPdfScrollAlignment(
15 ax::mojom::ScrollAlignment scroll_alignment) {
16 switch (scroll_alignment) {
17 case ax::mojom::ScrollAlignment::kScrollAlignmentCenter:
18 return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_CENTER;
19 case ax::mojom::ScrollAlignment::kScrollAlignmentTop:
20 return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_TOP;
21 case ax::mojom::ScrollAlignment::kScrollAlignmentBottom:
22 return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_BOTTOM;
23 case ax::mojom::ScrollAlignment::kScrollAlignmentLeft:
24 return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_LEFT;
25 case ax::mojom::ScrollAlignment::kScrollAlignmentRight:
26 return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_RIGHT;
27 case ax::mojom::ScrollAlignment::kScrollAlignmentClosestEdge:
28 return PP_PdfAccessibilityScrollAlignment::
29 PP_PDF_SCROLL_ALIGNMENT_CLOSEST_EDGE;
30 case ax::mojom::ScrollAlignment::kNone:
31 default:
32 return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_NONE;
33 }
34 }
35
36 } // namespace
37
38 // static
FromAXActionTarget(const ui::AXActionTarget * ax_action_target)39 const PdfAXActionTarget* PdfAXActionTarget::FromAXActionTarget(
40 const ui::AXActionTarget* ax_action_target) {
41 if (ax_action_target &&
42 ax_action_target->GetType() == ui::AXActionTarget::Type::kPdf) {
43 return static_cast<const PdfAXActionTarget*>(ax_action_target);
44 }
45
46 return nullptr;
47 }
48
PdfAXActionTarget(const ui::AXNode & plugin_node,PdfAccessibilityTree * pdf_tree_source)49 PdfAXActionTarget::PdfAXActionTarget(const ui::AXNode& plugin_node,
50 PdfAccessibilityTree* pdf_tree_source)
51 : target_plugin_node_(plugin_node),
52 pdf_accessibility_tree_source_(pdf_tree_source) {
53 DCHECK(pdf_accessibility_tree_source_);
54 }
55
56 PdfAXActionTarget::~PdfAXActionTarget() = default;
57
GetType() const58 ui::AXActionTarget::Type PdfAXActionTarget::GetType() const {
59 return ui::AXActionTarget::Type::kPdf;
60 }
61
ClearAccessibilityFocus() const62 bool PdfAXActionTarget::ClearAccessibilityFocus() const {
63 return false;
64 }
65
Click() const66 bool PdfAXActionTarget::Click() const {
67 PP_PdfAccessibilityActionData pdf_action_data = {};
68
69 if (target_plugin_node_.data().role != ax::mojom::Role::kLink)
70 return false;
71
72 base::Optional<PdfAccessibilityTree::AnnotationInfo> annotation_info_result =
73 pdf_accessibility_tree_source_->GetPdfAnnotationInfoFromAXNode(
74 target_plugin_node_.data().id);
75 if (!annotation_info_result.has_value())
76 return false;
77
78 const auto& annotation_info = annotation_info_result.value();
79 pdf_action_data.page_index = annotation_info.page_index;
80 pdf_action_data.annotation_index = annotation_info.annotation_index;
81 pdf_action_data.annotation_type =
82 PP_PdfAccessibilityAnnotationType::PP_PDF_LINK;
83 pdf_action_data.action = PP_PdfAccessibilityAction::PP_PDF_DO_DEFAULT_ACTION;
84 pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
85 return true;
86 }
87
Decrement() const88 bool PdfAXActionTarget::Decrement() const {
89 return false;
90 }
91
Increment() const92 bool PdfAXActionTarget::Increment() const {
93 return false;
94 }
95
Focus() const96 bool PdfAXActionTarget::Focus() const {
97 return false;
98 }
99
GetRelativeBounds() const100 gfx::Rect PdfAXActionTarget::GetRelativeBounds() const {
101 return gfx::Rect();
102 }
103
GetScrollOffset() const104 gfx::Point PdfAXActionTarget::GetScrollOffset() const {
105 return gfx::Point();
106 }
107
MinimumScrollOffset() const108 gfx::Point PdfAXActionTarget::MinimumScrollOffset() const {
109 return gfx::Point();
110 }
111
MaximumScrollOffset() const112 gfx::Point PdfAXActionTarget::MaximumScrollOffset() const {
113 return gfx::Point();
114 }
115
SetAccessibilityFocus() const116 bool PdfAXActionTarget::SetAccessibilityFocus() const {
117 return false;
118 }
119
SetScrollOffset(const gfx::Point & point) const120 void PdfAXActionTarget::SetScrollOffset(const gfx::Point& point) const {}
121
SetSelected(bool selected) const122 bool PdfAXActionTarget::SetSelected(bool selected) const {
123 return false;
124 }
125
SetSelection(const ui::AXActionTarget * anchor_object,int anchor_offset,const ui::AXActionTarget * focus_object,int focus_offset) const126 bool PdfAXActionTarget::SetSelection(const ui::AXActionTarget* anchor_object,
127 int anchor_offset,
128 const ui::AXActionTarget* focus_object,
129 int focus_offset) const {
130 const PdfAXActionTarget* pdf_anchor_object =
131 FromAXActionTarget(anchor_object);
132 const PdfAXActionTarget* pdf_focus_object = FromAXActionTarget(focus_object);
133 if (!pdf_anchor_object || !pdf_focus_object || anchor_offset < 0 ||
134 focus_offset < 0) {
135 return false;
136 }
137 PP_PdfAccessibilityActionData pdf_action_data = {};
138 if (!pdf_accessibility_tree_source_->FindCharacterOffset(
139 pdf_anchor_object->AXNode(), anchor_offset,
140 &pdf_action_data.selection_start_index) ||
141 !pdf_accessibility_tree_source_->FindCharacterOffset(
142 pdf_focus_object->AXNode(), focus_offset,
143 &pdf_action_data.selection_end_index)) {
144 return false;
145 }
146 pdf_action_data.action = PP_PdfAccessibilityAction::PP_PDF_SET_SELECTION;
147 pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
148 return true;
149 }
150
SetSequentialFocusNavigationStartingPoint() const151 bool PdfAXActionTarget::SetSequentialFocusNavigationStartingPoint() const {
152 return false;
153 }
154
SetValue(const std::string & value) const155 bool PdfAXActionTarget::SetValue(const std::string& value) const {
156 return false;
157 }
158
ShowContextMenu() const159 bool PdfAXActionTarget::ShowContextMenu() const {
160 return pdf_accessibility_tree_source_->ShowContextMenu();
161 }
162
ScrollToMakeVisible() const163 bool PdfAXActionTarget::ScrollToMakeVisible() const {
164 return false;
165 }
166
ScrollToMakeVisibleWithSubFocus(const gfx::Rect & rect,ax::mojom::ScrollAlignment horizontal_scroll_alignment,ax::mojom::ScrollAlignment vertical_scroll_alignment,ax::mojom::ScrollBehavior scroll_behavior) const167 bool PdfAXActionTarget::ScrollToMakeVisibleWithSubFocus(
168 const gfx::Rect& rect,
169 ax::mojom::ScrollAlignment horizontal_scroll_alignment,
170 ax::mojom::ScrollAlignment vertical_scroll_alignment,
171 ax::mojom::ScrollBehavior scroll_behavior) const {
172 PP_PdfAccessibilityActionData pdf_action_data = {};
173 pdf_action_data.action =
174 PP_PdfAccessibilityAction::PP_PDF_SCROLL_TO_MAKE_VISIBLE;
175 pdf_action_data.horizontal_scroll_alignment =
176 ConvertAXScrollToPdfScrollAlignment(horizontal_scroll_alignment);
177 pdf_action_data.vertical_scroll_alignment =
178 ConvertAXScrollToPdfScrollAlignment(vertical_scroll_alignment);
179 pdf_action_data.target_rect = {
180 {target_plugin_node_.data().relative_bounds.bounds.x(),
181 target_plugin_node_.data().relative_bounds.bounds.y()},
182 {target_plugin_node_.data().relative_bounds.bounds.width(),
183 target_plugin_node_.data().relative_bounds.bounds.height()}};
184 pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
185 return true;
186 }
187
ScrollToGlobalPoint(const gfx::Point & point) const188 bool PdfAXActionTarget::ScrollToGlobalPoint(const gfx::Point& point) const {
189 PP_PdfAccessibilityActionData pdf_action_data = {};
190 pdf_action_data.action =
191 PP_PdfAccessibilityAction::PP_PDF_SCROLL_TO_GLOBAL_POINT;
192 pdf_action_data.target_point = {point.x(), point.y()};
193 pdf_action_data.target_rect = {
194 {target_plugin_node_.data().relative_bounds.bounds.x(),
195 target_plugin_node_.data().relative_bounds.bounds.y()},
196 {target_plugin_node_.data().relative_bounds.bounds.width(),
197 target_plugin_node_.data().relative_bounds.bounds.height()}};
198 pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
199 return true;
200 }
201
202 } // namespace pdf
203