blob: 21ea6232379a9ffeee5d8a869942009f3a11e38f [file] [log] [blame]
// Copyright 2017 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 CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_AX_TREE_SOURCE_ARC_H_
#define CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_AX_TREE_SOURCE_ARC_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h"
#include "components/arc/mojom/accessibility_helper.mojom-forward.h"
#include "extensions/browser/api/automation_internal/automation_event_router.h"
#include "ui/accessibility/ax_action_handler.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_data.h"
#include "ui/accessibility/ax_tree_serializer.h"
#include "ui/accessibility/ax_tree_source.h"
#include "ui/views/view.h"
namespace ui {
struct AXEvent;
}
namespace arc {
class AXTreeSourceArcTest;
using AXTreeArcSerializer = ui::AXTreeSerializer<AccessibilityInfoDataWrapper*,
ui::AXNodeData,
ui::AXTreeData>;
// This class represents the accessibility tree from the focused ARC window.
class AXTreeSourceArc : public ui::AXTreeSource<AccessibilityInfoDataWrapper*,
ui::AXNodeData,
ui::AXTreeData>,
public ui::AXActionHandler {
public:
class Delegate {
public:
virtual void OnAction(const ui::AXActionData& data) const = 0;
};
AXTreeSourceArc(Delegate* delegate, float device_scale_factor);
~AXTreeSourceArc() override;
// Notify automation of an accessibility event.
void NotifyAccessibilityEvent(mojom::AccessibilityEventData* event_data);
// Notify automation of a result to an action.
void NotifyActionResult(const ui::AXActionData& data, bool result);
// Notify automation of result to getTextLocation.
void NotifyGetTextLocationDataResult(const ui::AXActionData& data,
const base::Optional<gfx::Rect>& rect);
// Invalidates the tree serializer.
void InvalidateTree();
// Returns true if the node id is the root of the node tree (which can have a
// parent window).
bool IsRootOfNodeTree(int32_t id) const;
// AXTreeSource:
bool GetTreeData(ui::AXTreeData* data) const override;
AccessibilityInfoDataWrapper* GetRoot() const override;
AccessibilityInfoDataWrapper* GetFromId(int32_t id) const override;
AccessibilityInfoDataWrapper* GetParent(
AccessibilityInfoDataWrapper* info_data) const override;
void SerializeNode(AccessibilityInfoDataWrapper* info_data,
ui::AXNodeData* out_data) const override;
float device_scale_factor() const { return device_scale_factor_; }
void set_device_scale_factor(float dsf) { device_scale_factor_ = dsf; }
bool is_notification() { return is_notification_; }
bool is_input_method_window() { return is_input_method_window_; }
// The window id of this tree.
base::Optional<int32_t> window_id() const { return window_id_; }
private:
friend class arc::AXTreeSourceArcTest;
// virtual for testing.
virtual extensions::AutomationEventRouterInterface* GetAutomationEventRouter()
const;
// Computes the smallest rect that encloses all of the descendants of
// |info_data|.
gfx::Rect ComputeEnclosingBounds(
AccessibilityInfoDataWrapper* info_data) const;
// Helper to recursively compute bounds for |info_data|. Returns true if
// non-empty bounds were encountered.
void ComputeEnclosingBoundsInternal(AccessibilityInfoDataWrapper* info_data,
gfx::Rect& computed_bounds) const;
// Computes if the node is clickable and has no clickable descendants.
bool ComputeIsClickableLeaf(
const std::vector<mojom::AccessibilityNodeInfoDataPtr>& nodes,
int32_t node_index,
const std::map<int32_t, int32_t>& node_id_to_nodes_index) const;
// Builds a mapping from index in |nodes| to whether ignored state should be
// applied to the node in chrome accessibility.
void BuildImportanceTable(
mojom::AccessibilityEventData* event_data,
const std::map<int32_t, int32_t>& node_id_to_nodes_index,
std::vector<bool>& out_node) const;
bool BuildHasImportantProperty(
int32_t nodes_index,
const std::vector<mojom::AccessibilityNodeInfoDataPtr>& nodes,
const std::map<int32_t, int32_t>& node_id_to_nodes_index,
std::vector<bool>& has_important_prop_cache) const;
// Find the most top-left focusable node under the given node.
AccessibilityInfoDataWrapper* FindFirstFocusableNode(
AccessibilityInfoDataWrapper* info_data) const;
AccessibilityInfoDataWrapper* GetSelectedNodeInfoFromAdapterView(
mojom::AccessibilityEventData* event_data) const;
void UpdateAXNameCache(AccessibilityInfoDataWrapper* focused_node,
const std::vector<std::string>& event_text);
void ApplyCachedProperties();
// Compare previous live region and current live region, and add event to the
// given vector if there is any difference.
void HandleLiveRegions(std::vector<ui::AXEvent>* events);
// Resets tree state.
void Reset();
// AXTreeSource:
int32_t GetId(AccessibilityInfoDataWrapper* info_data) const override;
void GetChildren(
AccessibilityInfoDataWrapper* info_data,
std::vector<AccessibilityInfoDataWrapper*>* out_children) const override;
bool IsIgnored(AccessibilityInfoDataWrapper* info_data) const override;
bool IsValid(AccessibilityInfoDataWrapper* info_data) const override;
bool IsEqual(AccessibilityInfoDataWrapper* info_data1,
AccessibilityInfoDataWrapper* info_data2) const override;
AccessibilityInfoDataWrapper* GetNull() const override;
// AXActionHandler:
void PerformAction(const ui::AXActionData& data) override;
// Maps an AccessibilityInfoDataWrapper ID to its tree data.
std::map<int32_t, std::unique_ptr<AccessibilityInfoDataWrapper>> tree_map_;
// The device scale factor of the display which the window is on.
float device_scale_factor_;
// Maps an AccessibilityInfoDataWrapper ID to its parent.
std::map<int32_t, int32_t> parent_map_;
std::unique_ptr<AXTreeArcSerializer> current_tree_serializer_;
base::Optional<int32_t> root_id_;
base::Optional<int32_t> window_id_;
base::Optional<int32_t> android_focused_id_;
bool is_notification_;
bool is_input_method_window_;
std::map<int32_t, std::string> cached_names_;
std::map<int32_t, ax::mojom::Role> cached_roles_;
// Mapping from Chrome node ID to its cached computed bounds.
// This simplifies bounds calculations.
std::map<int32_t, gfx::Rect> computed_bounds_;
// Mapping from Chrome node ID to the previous computed name for live region.
std::map<int32_t, std::string> previous_live_region_name_;
// A delegate that handles accessibility actions on behalf of this tree. The
// delegate is valid during the lifetime of this tree.
const Delegate* const delegate_;
DISALLOW_COPY_AND_ASSIGN(AXTreeSourceArc);
};
} // namespace arc
#endif // CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_AX_TREE_SOURCE_ARC_H_