blob: 39a78f06037d52a538743ac769dab3c42046b3b2 [file] [log] [blame]
// 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.
#ifndef COMPONENTS_PDF_RENDERER_PDF_ACCESSIBILITY_TREE_H_
#define COMPONENTS_PDF_RENDERER_PDF_ACCESSIBILITY_TREE_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/optional.h"
#include "content/public/renderer/plugin_ax_tree_source.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/c/private/ppp_pdf.h"
#include "ppapi/shared_impl/pdf_accessibility_shared.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_source.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace content {
class RenderAccessibility;
class RendererPpapiHost;
}
namespace gfx {
class Transform;
}
namespace pdf {
class PdfAccessibilityTree : public content::PluginAXTreeSource {
public:
PdfAccessibilityTree(content::RendererPpapiHost* host,
PP_Instance instance);
~PdfAccessibilityTree() override;
static bool IsDataFromPluginValid(
const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs,
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
const ppapi::PdfAccessibilityPageObjects& page_objects);
// Stores the page index and annotation index in the page.
struct AnnotationInfo {
AnnotationInfo(uint32_t page_index, uint32_t annotation_index);
AnnotationInfo(const AnnotationInfo& other);
~AnnotationInfo();
uint32_t page_index;
uint32_t annotation_index;
};
void SetAccessibilityViewportInfo(
const PP_PrivateAccessibilityViewportInfo& viewport_info);
void SetAccessibilityDocInfo(
const PP_PrivateAccessibilityDocInfo& doc_info);
void SetAccessibilityPageInfo(
const PP_PrivateAccessibilityPageInfo& page_info,
const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs,
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
const ppapi::PdfAccessibilityPageObjects& page_objects);
void HandleAction(const PP_PdfAccessibilityActionData& action_data);
base::Optional<AnnotationInfo> GetPdfAnnotationInfoFromAXNode(
int32_t ax_node_id) const;
// Given the AXNode and the character offset within the AXNode, finds the
// respective page index and character index within the page. Returns
// false if the |node| is not a valid static text or inline text box
// AXNode. Used to find the character offsets of selection.
bool FindCharacterOffset(const ui::AXNode& node,
uint32_t char_offset_in_node,
PP_PdfPageCharacterIndex* page_char_index) const;
// PluginAXTreeSource implementation.
bool GetTreeData(ui::AXTreeData* tree_data) const override;
ui::AXNode* GetRoot() const override;
ui::AXNode* GetFromId(int32_t id) const override;
int32_t GetId(const ui::AXNode* node) const override;
void GetChildren(const ui::AXNode* node,
std::vector<const ui::AXNode*>* out_children) const override;
ui::AXNode* GetParent(const ui::AXNode* node) const override;
bool IsIgnored(const ui::AXNode* node) const override;
bool IsValid(const ui::AXNode* node) const override;
bool IsEqual(const ui::AXNode* node1, const ui::AXNode* node2) const override;
const ui::AXNode* GetNull() const override;
void SerializeNode(const ui::AXNode* node, ui::AXNodeData* out_data)
const override;
std::unique_ptr<ui::AXActionTarget> CreateActionTarget(
const ui::AXNode& target_node) override;
private:
// Update the AXTreeData when the selected range changed.
void UpdateAXTreeDataFromSelection();
// Given a 0-based page index and 0-based character index within a page,
// find the node ID of the associated static text AXNode, and the character
// index within that text node. Used to find the start and end of the
// selected text range.
void FindNodeOffset(uint32_t page_index,
uint32_t page_char_index,
int32_t* out_node_id,
int32_t* out_node_char_index);
// Called after the data for all pages in the PDF have been received.
// Finishes assembling a complete accessibility tree and grafts it
// onto the host tree.
void Finish();
void AddPageContent(
ui::AXNodeData* page_node,
const gfx::RectF& page_bounds,
uint32_t page_index,
const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs,
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
const ppapi::PdfAccessibilityPageObjects& page_objects);
void AddRemainingAnnotations(
ui::AXNodeData* page_node,
const gfx::RectF& page_bounds,
uint32_t page_index,
base::span<const ppapi::PdfAccessibilityLinkInfo> links,
base::span<const ppapi::PdfAccessibilityImageInfo> images,
ui::AXNodeData* para_node);
std::string GetTextRunCharsAsUTF8(
const ppapi::PdfAccessibilityTextRunInfo& text_run,
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
int char_index);
std::vector<int32_t> GetTextRunCharOffsets(
const ppapi::PdfAccessibilityTextRunInfo& text_run,
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
int char_index);
gfx::Vector2dF ToVector2dF(const PP_Point& p);
gfx::RectF ToRectF(const PP_Rect& r);
ui::AXNodeData* CreateNode(ax::mojom::Role role);
ui::AXNodeData* CreateParagraphNode(float font_size,
float heading_font_size_threshold);
ui::AXNodeData* CreateStaticTextNode(
const PP_PdfPageCharacterIndex& page_char_index);
ui::AXNodeData* CreateInlineTextBoxNode(
const ppapi::PdfAccessibilityTextRunInfo& text_run,
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
const PP_PdfPageCharacterIndex& page_char_index,
const gfx::RectF& page_bounds);
ui::AXNodeData* CreateLinkNode(const ppapi::PdfAccessibilityLinkInfo& link,
uint32_t page_index);
ui::AXNodeData* CreateImageNode(
const ppapi::PdfAccessibilityImageInfo& image);
ui::AXNodeData* CreateHighlightNode(
const ppapi::PdfAccessibilityHighlightInfo& highlight);
void AddTextToAXNode(
uint32_t start_text_run_index,
uint32_t end_text_run_index,
const std::vector<ppapi::PdfAccessibilityTextRunInfo>& text_runs,
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
const gfx::RectF& page_bounds,
uint32_t page_index,
const std::vector<uint32_t>& text_run_start_indices,
ui::AXNodeData* ax_node,
ui::AXNodeData** previous_on_line_node);
float GetDeviceScaleFactor() const;
content::RenderAccessibility* GetRenderAccessibility();
gfx::Transform* MakeTransformFromViewInfo();
void AddWordStartsAndEnds(ui::AXNodeData* inline_text_box);
ui::AXTreeData tree_data_;
ui::AXTree tree_;
content::RendererPpapiHost* host_;
PP_Instance instance_;
// |zoom_| signifies the zoom level set in for the browser content.
// |scale_| signifies the scale level set by user. Scale is applied
// by the OS while zoom is applied by the application. Higher scale
// values are usually set to increase the size of everything on screen.
// Preferred by people with blurry/low vision. |zoom_| and |scale_|
// both help us increase/descrease the size of content on screen.
// From PDF plugin we receive all the data in logical pixels. Which is
// without the zoom and scale factor applied. We apply the |zoom_| and
// |scale_| to generate the final bounding boxes of elements in accessibility
// tree.
double zoom_ = 1.0;
double scale_ = 1.0;
gfx::Vector2dF scroll_;
gfx::Vector2dF offset_;
uint32_t selection_start_page_index_ = 0;
uint32_t selection_start_char_index_ = 0;
uint32_t selection_end_page_index_ = 0;
uint32_t selection_end_char_index_ = 0;
PP_PrivateAccessibilityDocInfo doc_info_;
ui::AXNodeData* doc_node_;
std::vector<std::unique_ptr<ui::AXNodeData>> nodes_;
// Map from the id of each static text AXNode and inline text box
// AXNode to the page index and index of the character within its
// page. Used to find the node associated with the start or end of
// a selection and vice-versa.
std::map<int32_t, PP_PdfPageCharacterIndex> node_id_to_page_char_index_;
// Map between AXNode id to annotation object. Used to find the annotation
// object to which an action can be passed.
std::map<int32_t, AnnotationInfo> node_id_to_annotation_info_;
bool invalid_plugin_message_received_ = false;
};
} // namespace pdf
#endif // COMPONENTS_PDF_RENDERER_PDF_ACCESSIBILITY_TREE_H_