ax_event_generator.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // Copyright 2017 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 UI_ACCESSIBILITY_AX_EVENT_GENERATOR_H_
  5. #define UI_ACCESSIBILITY_AX_EVENT_GENERATOR_H_
  6. #include <bitset>
  7. #include <map>
  8. #include <memory>
  9. #include <ostream>
  10. #include <set>
  11. #include <string>
  12. #include <vector>
  13. #include "base/memory/raw_ptr.h"
  14. #include "base/scoped_observation.h"
  15. #include "ui/accessibility/ax_event_intent.h"
  16. #include "ui/accessibility/ax_export.h"
  17. #include "ui/accessibility/ax_tree.h"
  18. #include "ui/accessibility/ax_tree_observer.h"
  19. namespace ui {
  20. class AXLiveRegionTracker;
  21. // Subclass of AXTreeObserver that automatically generates AXEvents to fire
  22. // based on changes to an accessibility tree. Every platform
  23. // tends to want different events, so this class lets each platform
  24. // handle the events it wants and ignore the others.
  25. class AX_EXPORT AXEventGenerator : public AXTreeObserver {
  26. public:
  27. enum class Event : int32_t {
  28. ACCESS_KEY_CHANGED,
  29. ACTIVE_DESCENDANT_CHANGED,
  30. ALERT,
  31. ARIA_CURRENT_CHANGED,
  32. // ATK treats alignment, indentation, and other format-related attributes as
  33. // text attributes even when they are only applicable to the entire object.
  34. // And it lacks an event for use when object attributes have changed.
  35. ATK_TEXT_OBJECT_ATTRIBUTE_CHANGED,
  36. ATOMIC_CHANGED,
  37. AUTO_COMPLETE_CHANGED,
  38. BUSY_CHANGED,
  39. CARET_BOUNDS_CHANGED,
  40. CHECKED_STATE_CHANGED,
  41. CHECKED_STATE_DESCRIPTION_CHANGED,
  42. CHILDREN_CHANGED,
  43. CLASS_NAME_CHANGED,
  44. COLLAPSED,
  45. CONTROLS_CHANGED,
  46. DETAILS_CHANGED,
  47. DESCRIBED_BY_CHANGED,
  48. DESCRIPTION_CHANGED,
  49. DOCUMENT_SELECTION_CHANGED,
  50. DOCUMENT_TITLE_CHANGED,
  51. DROPEFFECT_CHANGED,
  52. // TODO(nektar): Deprecate this event and replace it with
  53. // "VALUE_IN_TEXT_FIELD_CHANGED".
  54. EDITABLE_TEXT_CHANGED,
  55. ENABLED_CHANGED,
  56. EXPANDED,
  57. FOCUS_CHANGED,
  58. FLOW_FROM_CHANGED,
  59. FLOW_TO_CHANGED,
  60. GRABBED_CHANGED,
  61. HASPOPUP_CHANGED,
  62. HIERARCHICAL_LEVEL_CHANGED,
  63. IGNORED_CHANGED,
  64. IMAGE_ANNOTATION_CHANGED,
  65. INVALID_STATUS_CHANGED,
  66. KEY_SHORTCUTS_CHANGED,
  67. LABELED_BY_CHANGED,
  68. LANGUAGE_CHANGED,
  69. LAYOUT_INVALIDATED, // Fired when aria-busy turns from true to false.
  70. // Fired only on the root of the ARIA live region.
  71. LIVE_REGION_CHANGED,
  72. // Fired only on the root of the ARIA live region.
  73. LIVE_REGION_CREATED,
  74. // Fired on all the nodes within the ARIA live region excluding its root.
  75. LIVE_REGION_NODE_CHANGED,
  76. // Fired only on the root of the ARIA live region.
  77. LIVE_RELEVANT_CHANGED,
  78. // Fired only on the root of the ARIA live region.
  79. LIVE_STATUS_CHANGED,
  80. MENU_ITEM_SELECTED,
  81. MENU_POPUP_END,
  82. MENU_POPUP_START,
  83. MULTILINE_STATE_CHANGED,
  84. MULTISELECTABLE_STATE_CHANGED,
  85. NAME_CHANGED,
  86. OBJECT_ATTRIBUTE_CHANGED,
  87. OTHER_ATTRIBUTE_CHANGED,
  88. PARENT_CHANGED,
  89. PLACEHOLDER_CHANGED,
  90. PORTAL_ACTIVATED,
  91. POSITION_IN_SET_CHANGED,
  92. RANGE_VALUE_CHANGED,
  93. RANGE_VALUE_MAX_CHANGED,
  94. RANGE_VALUE_MIN_CHANGED,
  95. RANGE_VALUE_STEP_CHANGED,
  96. READONLY_CHANGED,
  97. RELATED_NODE_CHANGED,
  98. REQUIRED_STATE_CHANGED,
  99. ROLE_CHANGED,
  100. ROW_COUNT_CHANGED,
  101. SCROLL_HORIZONTAL_POSITION_CHANGED,
  102. SCROLL_VERTICAL_POSITION_CHANGED,
  103. SELECTED_CHANGED,
  104. SELECTED_CHILDREN_CHANGED,
  105. SELECTED_VALUE_CHANGED,
  106. SET_SIZE_CHANGED,
  107. SORT_CHANGED,
  108. STATE_CHANGED,
  109. SUBTREE_CREATED,
  110. TEXT_ATTRIBUTE_CHANGED,
  111. TEXT_SELECTION_CHANGED,
  112. VALUE_IN_TEXT_FIELD_CHANGED,
  113. // This event is fired for the exact set of attributes that affect the
  114. // MSAA/IAccessible state on Windows. It is not needed on other platforms,
  115. // but it is very natural to compute in this class.
  116. WIN_IACCESSIBLE_STATE_CHANGED,
  117. MAX_VALUE = WIN_IACCESSIBLE_STATE_CHANGED,
  118. };
  119. // For distinguishing between show and hide state when a node has
  120. // an IGNORED_CHANGED event.
  121. enum class IgnoredChangedState : uint8_t { kShow, kHide, kCount = 2 };
  122. struct AX_EXPORT EventParams final {
  123. explicit EventParams(Event event);
  124. EventParams(Event event,
  125. ax::mojom::EventFrom event_from,
  126. ax::mojom::Action event_from_action,
  127. const std::vector<AXEventIntent>& event_intents);
  128. EventParams(const EventParams& other);
  129. ~EventParams();
  130. EventParams& operator=(const EventParams& other);
  131. bool operator==(const EventParams& rhs) const;
  132. bool operator<(const EventParams& rhs) const;
  133. Event event;
  134. ax::mojom::EventFrom event_from = ax::mojom::EventFrom::kNone;
  135. ax::mojom::Action event_from_action;
  136. std::vector<AXEventIntent> event_intents;
  137. };
  138. struct AX_EXPORT TargetedEvent final {
  139. TargetedEvent(AXNodeID node_id, const EventParams& event_params);
  140. ~TargetedEvent();
  141. const AXNodeID node_id;
  142. const EventParams& event_params;
  143. };
  144. class AX_EXPORT Iterator {
  145. public:
  146. using iterator_category = std::input_iterator_tag;
  147. using value_type = TargetedEvent;
  148. using difference_type = std::ptrdiff_t;
  149. using pointer = TargetedEvent*;
  150. using reference = TargetedEvent&;
  151. Iterator(
  152. std::map<AXNodeID, std::set<EventParams>>::const_iterator
  153. map_start_iter,
  154. std::map<AXNodeID, std::set<EventParams>>::const_iterator map_end_iter);
  155. Iterator(const Iterator& other);
  156. ~Iterator();
  157. Iterator& operator=(const Iterator& other);
  158. Iterator& operator++();
  159. Iterator operator++(int); // Postfix increment.
  160. value_type operator*() const;
  161. private:
  162. AX_EXPORT friend bool operator==(const Iterator& lhs, const Iterator& rhs);
  163. AX_EXPORT friend bool operator!=(const Iterator& lhs, const Iterator& rhs);
  164. AX_EXPORT friend void swap(Iterator& lhs, Iterator& rhs);
  165. std::map<AXNodeID, std::set<EventParams>>::const_iterator map_iter_;
  166. std::map<AXNodeID, std::set<EventParams>>::const_iterator map_end_iter_;
  167. std::set<EventParams>::const_iterator set_iter_;
  168. };
  169. // For storing ignored changed states for a particular node. We use bitset as
  170. // the underlying data structure to improve memory usage.
  171. // We use the index of AXEventGenerator::IgnoredChangedState enum
  172. // to access the bitset data.
  173. // e.g. AXEventGenerator::IgnoredChangedState::kShow has index 0 in the
  174. // IgnoredChangedState enum. If |IgnoredChangedStatesBitset[0]| is set, it
  175. // means IgnoredChangedState::kShow is present. Similarly, kHide has index 1
  176. // in the enum, and it corresponds to |IgnoredChangedStatesBitset[1]|.
  177. using IgnoredChangedStatesBitset =
  178. std::bitset<static_cast<size_t>(IgnoredChangedState::kCount)>;
  179. using const_iterator = Iterator;
  180. using iterator = Iterator;
  181. using value_type = TargetedEvent;
  182. // If you use this constructor, you must call SetTree
  183. // before using this class.
  184. AXEventGenerator();
  185. // Automatically registers itself as the observer of |tree| and
  186. // clears it on desctruction. |tree| must be valid for the lifetime
  187. // of this object.
  188. explicit AXEventGenerator(AXTree* tree);
  189. ~AXEventGenerator() override;
  190. // Clears this class as the observer of the previous tree that was
  191. // being monitored, if any, and starts monitoring |new_tree|, if not
  192. // nullptr. Note that |new_tree| must be valid for the lifetime of
  193. // this object or until you call SetTree again.
  194. void SetTree(AXTree* new_tree);
  195. // Nulls-out |tree_| without accessing it or destroying it.
  196. void ReleaseTree();
  197. //
  198. // Methods that make this class behave like an STL container, which simplifies
  199. // the process of iterating through generated events.
  200. //
  201. bool empty() const;
  202. size_t size() const;
  203. Iterator begin() const;
  204. Iterator end() const;
  205. // Clear any previously added events.
  206. void ClearEvents();
  207. // This is called automatically based on changes to the tree observed
  208. // by AXTreeObserver, but you can also call it directly to add events
  209. // and retrieve them later.
  210. //
  211. // Note that events are organized by node and then by event id to
  212. // efficiently remove duplicates, so events won't be retrieved in the
  213. // same order they were added.
  214. void AddEvent(ui::AXNode* node, Event event);
  215. void AddEventsForTesting(const AXNode& node,
  216. const std::set<EventParams>& events);
  217. protected:
  218. // AXTreeObserver overrides.
  219. void OnIgnoredWillChange(AXTree* tree,
  220. AXNode* node,
  221. bool is_ignored_new_value) override;
  222. void OnNodeDataChanged(AXTree* tree,
  223. const AXNodeData& old_node_data,
  224. const AXNodeData& new_node_data) override;
  225. void OnRoleChanged(AXTree* tree,
  226. AXNode* node,
  227. ax::mojom::Role old_role,
  228. ax::mojom::Role new_role) override;
  229. void OnIgnoredChanged(AXTree* tree,
  230. AXNode* node,
  231. bool is_ignored_new_value) override;
  232. void OnStateChanged(AXTree* tree,
  233. AXNode* node,
  234. ax::mojom::State state,
  235. bool new_value) override;
  236. void OnStringAttributeChanged(AXTree* tree,
  237. AXNode* node,
  238. ax::mojom::StringAttribute attr,
  239. const std::string& old_value,
  240. const std::string& new_value) override;
  241. void OnIntAttributeChanged(AXTree* tree,
  242. AXNode* node,
  243. ax::mojom::IntAttribute attr,
  244. int32_t old_value,
  245. int32_t new_value) override;
  246. void OnFloatAttributeChanged(AXTree* tree,
  247. AXNode* node,
  248. ax::mojom::FloatAttribute attr,
  249. float old_value,
  250. float new_value) override;
  251. void OnBoolAttributeChanged(AXTree* tree,
  252. AXNode* node,
  253. ax::mojom::BoolAttribute attr,
  254. bool new_value) override;
  255. void OnIntListAttributeChanged(
  256. AXTree* tree,
  257. AXNode* node,
  258. ax::mojom::IntListAttribute attr,
  259. const std::vector<int32_t>& old_value,
  260. const std::vector<int32_t>& new_value) override;
  261. void OnTreeDataChanged(AXTree* tree,
  262. const ui::AXTreeData& old_data,
  263. const ui::AXTreeData& new_data) override;
  264. void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) override;
  265. void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) override;
  266. void OnNodeWillBeReparented(AXTree* tree, AXNode* node) override;
  267. void OnSubtreeWillBeReparented(AXTree* tree, AXNode* node) override;
  268. void OnNodeDeleted(AXTree* tree, AXNodeID node_id) override;
  269. void OnNodeReparented(AXTree* tree, AXNode* node) override;
  270. void OnNodeCreated(AXTree* tree, AXNode* node) override;
  271. void OnAtomicUpdateFinished(AXTree* tree,
  272. bool root_changed,
  273. const std::vector<Change>& changes) override;
  274. private:
  275. static void GetRestrictionStates(ax::mojom::Restriction restriction,
  276. bool* is_enabled,
  277. bool* is_readonly);
  278. // Returns a vector of values unique to either |lhs| or |rhs|
  279. static std::vector<int32_t> ComputeIntListDifference(
  280. const std::vector<int32_t>& lhs,
  281. const std::vector<int32_t>& rhs);
  282. void FireLiveRegionEvents(AXNode* node);
  283. void FireActiveDescendantEvents();
  284. // If the given target node is inside a text field and the node's modification
  285. // could affect the field's value, generates an `VALUE_IN_TEXT_FIELD_CHANGED`
  286. // on the text field that contains the node.
  287. void FireValueInTextFieldChangedEventIfNecessary(AXTree* tree,
  288. AXNode* target_node);
  289. void FireRelationSourceEvents(AXTree* tree, AXNode* target_node);
  290. // Remove excessive events for a tree update containing node.
  291. // We remove certain events on a node when it flips its IGNORED state to
  292. // either show/hide and one of the node's ancestor has also flipped its
  293. // IGNORED state in the same way (show/hide) in the tree update.
  294. // |ancestor_has_ignored_map| contains if a node's ancestor has changed to
  295. // IGNORED state.
  296. // Map's key is an AXNode.
  297. // Map's value is a std::bitset containing IgnoredChangedStates(kShow/kHide).
  298. // - Map's value IgnoredChangedStatesBitset contains kShow if an ancestor
  299. // of node removed its IGNORED state.
  300. // - Map's value IgnoredChangedStatesBitset contains kHide if an ancestor
  301. // of node changed to IGNORED state.
  302. // - When IgnoredChangedStatesBitset is not set, it means neither the
  303. // node nor its ancestor has IGNORED_CHANGED.
  304. void TrimEventsDueToAncestorIgnoredChanged(
  305. AXNode* node,
  306. std::map<AXNode*, IgnoredChangedStatesBitset>&
  307. ancestor_ignored_changed_map);
  308. void PostprocessEvents();
  309. raw_ptr<AXTree> tree_ = nullptr; // Not owned.
  310. std::map<AXNodeID, std::set<EventParams>> tree_events_;
  311. // Valid between the call to OnIntAttributeChanged and the call to
  312. // OnAtomicUpdateFinished. List of nodes whose active descendant changed.
  313. std::vector<AXNode*> active_descendant_changed_;
  314. // Keeps track of nodes that have changed their state from ignored to
  315. // unignored, but which used to be in an invisible subtree. We should not fire
  316. // `Event::PARENT_CHANGED` on any of their children because they were
  317. // previously unknown to ATs.
  318. std::set<AXNodeID> nodes_to_suppress_parent_changed_on_;
  319. // Helper that tracks live regions.
  320. std::unique_ptr<AXLiveRegionTracker> live_region_tracker_;
  321. // Please make sure that this ScopedObserver is always declared last in order
  322. // to prevent any use-after-free.
  323. base::ScopedObservation<AXTree, AXTreeObserver> tree_event_observation_{this};
  324. };
  325. AX_EXPORT std::ostream& operator<<(std::ostream& os,
  326. AXEventGenerator::Event event);
  327. AX_EXPORT const char* ToString(AXEventGenerator::Event event);
  328. } // namespace ui
  329. #endif // UI_ACCESSIBILITY_AX_EVENT_GENERATOR_H_