accessibility_bridge.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. #ifndef FUCHSIA_WEB_WEBENGINE_BROWSER_ACCESSIBILITY_BRIDGE_H_
  5. #define FUCHSIA_WEB_WEBENGINE_BROWSER_ACCESSIBILITY_BRIDGE_H_
  6. #include <fuchsia/accessibility/semantics/cpp/fidl.h>
  7. #include <fuchsia/math/cpp/fidl.h>
  8. #include <fuchsia/ui/views/cpp/fidl.h>
  9. #include <lib/fidl/cpp/binding.h>
  10. #include <lib/inspect/cpp/vmo/types.h>
  11. #include "base/callback.h"
  12. #include "base/containers/flat_map.h"
  13. #include "base/containers/flat_set.h"
  14. #include "base/gtest_prod_util.h"
  15. #include "content/public/browser/ax_event_notification_details.h"
  16. #include "content/public/browser/web_contents_delegate.h"
  17. #include "content/public/browser/web_contents_observer.h"
  18. #include "fuchsia_web/webengine/browser/ax_tree_converter.h"
  19. #include "fuchsia_web/webengine/web_engine_export.h"
  20. #include "third_party/abseil-cpp/absl/types/optional.h"
  21. #include "ui/accessibility/ax_serializable_tree.h"
  22. #include "ui/accessibility/ax_tree_id.h"
  23. #include "ui/accessibility/ax_tree_observer.h"
  24. namespace content {
  25. class WebContents;
  26. } // namespace content
  27. class FrameWindowTreeHost;
  28. // This class is the intermediate for accessibility between Chrome and Fuchsia.
  29. // It handles registration to the Fuchsia Semantics Manager, translating events
  30. // and data structures between the two services, and forwarding actions and
  31. // events.
  32. // The lifetime of an instance of AccessibilityBridge is the same as that of a
  33. // View created by FrameImpl. This class refers to the View via the
  34. // caller-supplied ViewRef.
  35. // If |semantic_tree_| gets disconnected, it will cause the FrameImpl that owns
  36. // |this| to close, which will also destroy |this|.
  37. class WEB_ENGINE_EXPORT AccessibilityBridge final
  38. : public content::WebContentsObserver,
  39. public fuchsia::accessibility::semantics::SemanticListener,
  40. public ui::AXTreeObserver {
  41. public:
  42. using AXNodeID = std::pair<ui::AXTreeID, int32_t>;
  43. // |semantics_manager| is used during construction to register the instance.
  44. // |web_contents| is required to exist for the duration of |this|.
  45. AccessibilityBridge(
  46. fuchsia::accessibility::semantics::SemanticsManager* semantics_manager,
  47. FrameWindowTreeHost* window_tree_host,
  48. content::WebContents* web_contents,
  49. base::OnceCallback<bool(zx_status_t)> on_error_callback,
  50. inspect::Node inspect_node);
  51. ~AccessibilityBridge() override;
  52. AccessibilityBridge(const AccessibilityBridge&) = delete;
  53. AccessibilityBridge& operator=(const AccessibilityBridge&) = delete;
  54. ui::AXSerializableTree* ax_tree_for_test();
  55. void set_event_received_callback_for_test(base::OnceClosure callback) {
  56. event_received_callback_for_test_ = std::move(callback);
  57. }
  58. void set_device_scale_factor_for_test(float device_scale_factor) {
  59. device_scale_factor_override_for_test_ = device_scale_factor;
  60. }
  61. NodeIDMapper* node_id_mapper_for_test() { return id_mapper_.get(); }
  62. private:
  63. FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest, OnSemanticsModeChanged);
  64. FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest,
  65. TreeModificationsAreForwarded);
  66. FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest,
  67. TransformAccountsForOffsetContainerBounds);
  68. FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest,
  69. UpdateTransformWhenContainerBoundsChange);
  70. FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest,
  71. OffsetContainerBookkeepingIsUpdated);
  72. FRIEND_TEST_ALL_PREFIXES(AccessibilityBridgeTest, OneUpdatePerNode);
  73. // Represents a connection between two AXTrees that are in different frames.
  74. struct TreeConnection {
  75. // ID of the node in the parent tree that points to this tree.
  76. int32_t parent_node_id = 0;
  77. // ID of the parent tree.
  78. ui::AXTreeID parent_tree_id = ui::AXTreeIDUnknown();
  79. // Whether the trees are connected.
  80. bool is_connected = false;
  81. };
  82. // Populates inspect data with the AXTrees. Updates must be enabled.
  83. inspect::Inspector FillInspectData();
  84. // Processes pending data and commits it to the Semantic Tree.
  85. void TryCommit();
  86. // Connects trees if they are present or deletes the connection if both are
  87. // gone.
  88. void UpdateTreeConnections();
  89. // Updates the node in focus and clears the focus from the old node. The nodes
  90. // are added to |to_update_|, and will be sent to Fuchsia the next time the
  91. // update is committed.
  92. void UpdateFocus();
  93. // Returns true if the main frame AXTree is not present or if trees are not
  94. // connected.
  95. bool ShouldHoldCommit();
  96. // The AXTreeID of a tree can change. Updates all internal references of an
  97. // AXTreeID by fetching the RenderFrameHost associated with |tree_id| and
  98. // updates the value if it is different from the previously used AXTreeID.
  99. // Returns false if the frame does not exist anymore, true otherwise.
  100. bool UpdateAXTreeID(const ui::AXTreeID& tree_id);
  101. // If |tree| is connected to another tree as its child, mark them as
  102. // disconnected.
  103. void MaybeDisconnectTreeFromParentTree(ui::AXTree* tree);
  104. // Callback for SemanticTree::CommitUpdates.
  105. void OnCommitComplete();
  106. // Interrupts actions that are waiting for a response. This is invoked during
  107. // destruction time or when semantic updates have been disabled.
  108. void InterruptPendingActions();
  109. // Accessor for the device scale factor that allows for overriding the value
  110. // in tests.
  111. float GetDeviceScaleFactor();
  112. // Helper method to add a node to its offset container's offset children
  113. // mapping.
  114. void AddNodeToOffsetMapping(const ui::AXTree* tree,
  115. const ui::AXNodeData& node_data);
  116. // Helper method to remove a node id from its offset container's offset
  117. // children mapping.
  118. void RemoveNodeFromOffsetMapping(const ui::AXTree* tree,
  119. const ui::AXNodeData& node_data);
  120. // Helper method to return the node in focus. Returns nullptr if the main
  121. // frame is not ready yet. If no focus information is present, returns the
  122. // root node of the frame in focus.
  123. absl::optional<AXNodeID> GetFocusedNodeId() const;
  124. // Helper method to return the fuchsia representation of the node if it is
  125. // being changed in this update. Returns nullptr if the node is not part of
  126. // the current update.
  127. fuchsia::accessibility::semantics::Node* GetNodeIfChangingInUpdate(
  128. const ui::AXTreeID& tree_id,
  129. ui::AXNodeID node_id);
  130. // Helper method to get the most recently updated fuchsia representation of
  131. // the node. Note that it differs from |GetNodeIfChangingInUpdate| because
  132. // here a node will be created to be part of the update if it is not. If
  133. // |replace_existing| is set to true, then this method will overwrite the
  134. // existing update for the node (if one exists).
  135. //
  136. // Returns nullptr if the node does not exist.
  137. fuchsia::accessibility::semantics::Node* EnsureAndGetUpdatedNode(
  138. const ui::AXTreeID& tree_id,
  139. ui::AXNodeID node_id,
  140. bool replace_existing);
  141. // Returns the node in focus in this frame or in one of its descendants if the
  142. // node in focus points to a child frame.
  143. absl::optional<AXNodeID> GetFocusFromThisOrDescendantFrame(
  144. const ui::AXSerializableTree* tree) const;
  145. // Enqueues |node_id| for deletion in the subsequent tree update.
  146. void AppendToDeleteList(uint32_t node_id);
  147. // Enqueues changes to |node| in the subsequent tree update.
  148. void AppendToUpdateList(fuchsia::accessibility::semantics::Node node);
  149. // content::WebContentsObserver implementation.
  150. void AccessibilityEventReceived(
  151. const content::AXEventNotificationDetails& details) override;
  152. void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
  153. // fuchsia::accessibility::semantics::SemanticListener implementation.
  154. void OnAccessibilityActionRequested(
  155. uint32_t node_id,
  156. fuchsia::accessibility::semantics::Action action,
  157. OnAccessibilityActionRequestedCallback callback) override;
  158. void HitTest(fuchsia::math::PointF local_point,
  159. HitTestCallback callback) override;
  160. void OnSemanticsModeChanged(bool updates_enabled,
  161. OnSemanticsModeChangedCallback callback) override;
  162. // ui::AXTreeObserver implementation.
  163. void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override;
  164. void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
  165. void OnNodeDeleted(ui::AXTree* tree, int32_t node_id) override;
  166. void OnAtomicUpdateFinished(
  167. ui::AXTree* tree,
  168. bool root_changed,
  169. const std::vector<ui::AXTreeObserver::Change>& changes) override;
  170. void OnNodeDataChanged(ui::AXTree* tree,
  171. const ui::AXNodeData& old_node_data,
  172. const ui::AXNodeData& new_node_data) override;
  173. fuchsia::accessibility::semantics::SemanticTreePtr semantic_tree_;
  174. fidl::Binding<fuchsia::accessibility::semantics::SemanticListener> binding_;
  175. FrameWindowTreeHost* const window_tree_host_;
  176. content::WebContents* const web_contents_;
  177. // Holds one semantic tree per iframe.
  178. base::flat_map<ui::AXTreeID, std::unique_ptr<ui::AXSerializableTree>>
  179. ax_trees_;
  180. // Maps frames to AXTrees.
  181. base::flat_map<content::GlobalRenderFrameHostId, ui::AXTreeID>
  182. frame_id_to_tree_id_;
  183. // Keeps track of semantic trees connections.
  184. // The key is the AXTreeID of the semantic tree that is connected to another
  185. // tree.
  186. base::flat_map<ui::AXTreeID, TreeConnection> tree_connections_;
  187. // Last focused node. If nullptr, no node is in focus.
  188. absl::optional<AXNodeID> last_focused_node_id_;
  189. // Maintain a map of callbacks as multiple hit test events can happen at
  190. // once. These are keyed by the request_id field of ui::AXActionData.
  191. base::flat_map<int, HitTestCallback> pending_hit_test_callbacks_;
  192. // Whether semantic updates are enabled.
  193. bool enable_semantic_updates_ = false;
  194. // Buffer for pending data to be sent to the Semantic Tree between commits.
  195. std::vector<std::vector<uint32_t>> to_delete_;
  196. std::vector<std::vector<fuchsia::accessibility::semantics::Node>> to_update_;
  197. bool commit_inflight_ = false;
  198. // Maintain a map from AXNode IDs to a list of the AXNode IDs of descendant
  199. // nodes that have the key node ID as their offset containers.
  200. std::map<AXNodeID, base::flat_set<AXNodeID>> offset_container_children_;
  201. // Run in the case of an internal error that cannot be recovered from. This
  202. // will cause the frame |this| is owned by to be torn down.
  203. base::OnceCallback<bool(zx_status_t)> on_error_callback_;
  204. // The root id of the AXTree of the main frame.
  205. int32_t root_id_ = 0;
  206. // Maps node IDs from one platform to another.
  207. std::unique_ptr<NodeIDMapper> id_mapper_;
  208. base::OnceClosure event_received_callback_for_test_;
  209. // If set, the scale factor for this device for use in tests.
  210. absl::optional<float> device_scale_factor_override_for_test_;
  211. // Inspect node for the accessibility bridge.
  212. inspect::Node inspect_node_;
  213. // Inspect node to store a dump of the semantic tree.
  214. inspect::LazyNode inspect_node_tree_dump_;
  215. };
  216. #endif // FUCHSIA_WEB_WEBENGINE_BROWSER_ACCESSIBILITY_BRIDGE_H_