1 // Copyright 2016 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 #ifndef COMPONENTS_PDF_RENDERER_PDF_ACCESSIBILITY_TREE_H_ 6 #define COMPONENTS_PDF_RENDERER_PDF_ACCESSIBILITY_TREE_H_ 7 8 #include <map> 9 #include <memory> 10 #include <string> 11 #include <vector> 12 13 #include "base/optional.h" 14 #include "content/public/renderer/plugin_ax_tree_source.h" 15 #include "ppapi/c/pp_instance.h" 16 #include "ppapi/c/private/ppb_pdf.h" 17 #include "ppapi/c/private/ppp_pdf.h" 18 #include "ppapi/shared_impl/pdf_accessibility_shared.h" 19 #include "ui/accessibility/ax_node.h" 20 #include "ui/accessibility/ax_tree.h" 21 #include "ui/accessibility/ax_tree_source.h" 22 #include "ui/gfx/geometry/rect_f.h" 23 #include "ui/gfx/geometry/vector2d_f.h" 24 25 namespace content { 26 class RenderAccessibility; 27 class RendererPpapiHost; 28 } 29 30 namespace gfx { 31 class Transform; 32 } 33 34 namespace pdf { 35 36 class PdfAccessibilityTree : public content::PluginAXTreeSource { 37 public: 38 PdfAccessibilityTree(content::RendererPpapiHost* host, 39 PP_Instance instance); 40 ~PdfAccessibilityTree() override; 41 42 static bool IsDataFromPluginValid( 43 const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs, 44 const std::vector<PP_PrivateAccessibilityCharInfo>& chars, 45 const ppapi::PdfAccessibilityPageObjects& page_objects); 46 47 // Stores the page index and annotation index in the page. 48 struct AnnotationInfo { 49 AnnotationInfo(uint32_t page_index, uint32_t annotation_index); 50 AnnotationInfo(const AnnotationInfo& other); 51 ~AnnotationInfo(); 52 53 uint32_t page_index; 54 uint32_t annotation_index; 55 }; 56 57 void SetAccessibilityViewportInfo( 58 const PP_PrivateAccessibilityViewportInfo& viewport_info); 59 void SetAccessibilityDocInfo( 60 const PP_PrivateAccessibilityDocInfo& doc_info); 61 void SetAccessibilityPageInfo( 62 const PP_PrivateAccessibilityPageInfo& page_info, 63 const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs, 64 const std::vector<PP_PrivateAccessibilityCharInfo>& chars, 65 const ppapi::PdfAccessibilityPageObjects& page_objects); 66 void HandleAction(const PP_PdfAccessibilityActionData& action_data); 67 base::Optional<AnnotationInfo> GetPdfAnnotationInfoFromAXNode( 68 int32_t ax_node_id) const; 69 70 // Given the AXNode and the character offset within the AXNode, finds the 71 // respective page index and character index within the page. Returns 72 // false if the |node| is not a valid static text or inline text box 73 // AXNode. Used to find the character offsets of selection. 74 bool FindCharacterOffset(const ui::AXNode& node, 75 uint32_t char_offset_in_node, 76 PP_PdfPageCharacterIndex* page_char_index) const; 77 78 // PluginAXTreeSource implementation. 79 bool GetTreeData(ui::AXTreeData* tree_data) const override; 80 ui::AXNode* GetRoot() const override; 81 ui::AXNode* GetFromId(int32_t id) const override; 82 int32_t GetId(const ui::AXNode* node) const override; 83 void GetChildren(const ui::AXNode* node, 84 std::vector<const ui::AXNode*>* out_children) const override; 85 ui::AXNode* GetParent(const ui::AXNode* node) const override; 86 bool IsIgnored(const ui::AXNode* node) const override; 87 bool IsValid(const ui::AXNode* node) const override; 88 bool IsEqual(const ui::AXNode* node1, const ui::AXNode* node2) const override; 89 const ui::AXNode* GetNull() const override; 90 void SerializeNode(const ui::AXNode* node, ui::AXNodeData* out_data) 91 const override; 92 std::unique_ptr<ui::AXActionTarget> CreateActionTarget( 93 const ui::AXNode& target_node) override; 94 95 private: 96 // Update the AXTreeData when the selected range changed. 97 void UpdateAXTreeDataFromSelection(); 98 99 // Given a 0-based page index and 0-based character index within a page, 100 // find the node ID of the associated static text AXNode, and the character 101 // index within that text node. Used to find the start and end of the 102 // selected text range. 103 void FindNodeOffset(uint32_t page_index, 104 uint32_t page_char_index, 105 int32_t* out_node_id, 106 int32_t* out_node_char_index) const; 107 108 // Called after the data for all pages in the PDF have been received. 109 // Finishes assembling a complete accessibility tree and grafts it 110 // onto the host tree. 111 void Finish(); 112 113 void AddPageContent( 114 ui::AXNodeData* page_node, 115 const gfx::RectF& page_bounds, 116 uint32_t page_index, 117 const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs, 118 const std::vector<PP_PrivateAccessibilityCharInfo>& chars, 119 const ppapi::PdfAccessibilityPageObjects& page_objects); 120 void AddRemainingAnnotations( 121 ui::AXNodeData* page_node, 122 const gfx::RectF& page_bounds, 123 uint32_t page_index, 124 base::span<const ppapi::PdfAccessibilityLinkInfo> links, 125 base::span<const ppapi::PdfAccessibilityImageInfo> images, 126 base::span<const ppapi::PdfAccessibilityTextFieldInfo> text_fields, 127 ui::AXNodeData* para_node); 128 129 ui::AXNodeData* CreateNode(ax::mojom::Role role, 130 ax::mojom::Restriction restriction); 131 ui::AXNodeData* CreateParagraphNode(float font_size, 132 float heading_font_size_threshold); 133 ui::AXNodeData* CreateStaticTextNode( 134 const PP_PdfPageCharacterIndex& page_char_index); 135 ui::AXNodeData* CreateInlineTextBoxNode( 136 const ppapi::PdfAccessibilityTextRunInfo& text_run, 137 const std::vector<PP_PrivateAccessibilityCharInfo>& chars, 138 const PP_PdfPageCharacterIndex& page_char_index, 139 const gfx::RectF& page_bounds); 140 ui::AXNodeData* CreateLinkNode(const ppapi::PdfAccessibilityLinkInfo& link, 141 uint32_t page_index); 142 ui::AXNodeData* CreateImageNode( 143 const ppapi::PdfAccessibilityImageInfo& image); 144 ui::AXNodeData* CreateHighlightNode( 145 const ppapi::PdfAccessibilityHighlightInfo& highlight); 146 ui::AXNodeData* CreateTextFieldNode( 147 const ppapi::PdfAccessibilityTextFieldInfo& text_field); 148 void AddTextToAXNode( 149 uint32_t start_text_run_index, 150 uint32_t end_text_run_index, 151 const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs, 152 const std::vector<PP_PrivateAccessibilityCharInfo>& chars, 153 const gfx::RectF& page_bounds, 154 uint32_t page_index, 155 const std::vector<uint32_t>& text_run_start_indices, 156 ui::AXNodeData* ax_node, 157 ui::AXNodeData** previous_on_line_node); 158 content::RenderAccessibility* GetRenderAccessibility(); 159 std::unique_ptr<gfx::Transform> MakeTransformFromViewInfo() const; 160 void AddWordStartsAndEnds(ui::AXNodeData* inline_text_box); 161 162 ui::AXTreeData tree_data_; 163 ui::AXTree tree_; 164 165 // Unowned. Must outlive |this|. 166 content::RendererPpapiHost* const host_; 167 168 const PP_Instance instance_; 169 // |zoom_| signifies the zoom level set in for the browser content. 170 // |scale_| signifies the scale level set by user. Scale is applied 171 // by the OS while zoom is applied by the application. Higher scale 172 // values are usually set to increase the size of everything on screen. 173 // Preferred by people with blurry/low vision. |zoom_| and |scale_| 174 // both help us increase/descrease the size of content on screen. 175 // From PDF plugin we receive all the data in logical pixels. Which is 176 // without the zoom and scale factor applied. We apply the |zoom_| and 177 // |scale_| to generate the final bounding boxes of elements in accessibility 178 // tree. 179 double zoom_ = 1.0; 180 double scale_ = 1.0; 181 gfx::Vector2dF scroll_; 182 gfx::Vector2dF offset_; 183 uint32_t selection_start_page_index_ = 0; 184 uint32_t selection_start_char_index_ = 0; 185 uint32_t selection_end_page_index_ = 0; 186 uint32_t selection_end_char_index_ = 0; 187 PP_PrivateAccessibilityDocInfo doc_info_; 188 ui::AXNodeData* doc_node_; 189 std::vector<std::unique_ptr<ui::AXNodeData>> nodes_; 190 191 // Map from the id of each static text AXNode and inline text box 192 // AXNode to the page index and index of the character within its 193 // page. Used to find the node associated with the start or end of 194 // a selection and vice-versa. 195 std::map<int32_t, PP_PdfPageCharacterIndex> node_id_to_page_char_index_; 196 197 // Map between AXNode id to annotation object. Used to find the annotation 198 // object to which an action can be passed. 199 std::map<int32_t, AnnotationInfo> node_id_to_annotation_info_; 200 bool invalid_plugin_message_received_ = false; 201 }; 202 203 } // namespace pdf 204 205 #endif // COMPONENTS_PDF_RENDERER_PDF_ACCESSIBILITY_TREE_H_ 206