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