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 <map>
9 #include <ostream>
10 #include <set>
11 #include <vector>
12 
13 #include "base/scoped_observer.h"
14 #include "ui/accessibility/ax_export.h"
15 #include "ui/accessibility/ax_tree.h"
16 #include "ui/accessibility/ax_tree_observer.h"
17 
18 namespace ui {
19 
20 // Subclass of AXTreeObserver that automatically generates AXEvents to fire
21 // based on changes to an accessibility tree.  Every platform
22 // tends to want different events, so this class lets each platform
23 // handle the events it wants and ignore the others.
24 class AX_EXPORT AXEventGenerator : public AXTreeObserver {
25  public:
26   enum class Event : int32_t {
27     ACCESS_KEY_CHANGED,
28     ACTIVE_DESCENDANT_CHANGED,
29     ALERT,
30     ATOMIC_CHANGED,
31     AUTO_COMPLETE_CHANGED,
32     BUSY_CHANGED,
33     CHECKED_STATE_CHANGED,
34     CHILDREN_CHANGED,
35     CLASS_NAME_CHANGED,
36     COLLAPSED,
37     CONTROLS_CHANGED,
38     DESCRIBED_BY_CHANGED,
39     DESCRIPTION_CHANGED,
40     DOCUMENT_SELECTION_CHANGED,
41     DOCUMENT_TITLE_CHANGED,
42     DROPEFFECT_CHANGED,
43     ENABLED_CHANGED,
44     EXPANDED,
45     FOCUS_CHANGED,
46     FLOW_FROM_CHANGED,
47     FLOW_TO_CHANGED,
48     GRABBED_CHANGED,
49     HASPOPUP_CHANGED,
50     HIERARCHICAL_LEVEL_CHANGED,
51     IGNORED_CHANGED,
52     IMAGE_ANNOTATION_CHANGED,
53     INVALID_STATUS_CHANGED,
54     KEY_SHORTCUTS_CHANGED,
55     LABELED_BY_CHANGED,
56     LANGUAGE_CHANGED,
57     LAYOUT_INVALIDATED,   // Fired when aria-busy goes false
58     LIVE_REGION_CHANGED,  // Fired on the root of a live region.
59     LIVE_REGION_CREATED,
60     LIVE_REGION_NODE_CHANGED,  // Fired on a node within a live region.
61     LIVE_RELEVANT_CHANGED,
62     LIVE_STATUS_CHANGED,
63     LOAD_COMPLETE,
64     LOAD_START,
65     MENU_ITEM_SELECTED,
66     MULTILINE_STATE_CHANGED,
67     MULTISELECTABLE_STATE_CHANGED,
68     NAME_CHANGED,
69     OTHER_ATTRIBUTE_CHANGED,
70     PLACEHOLDER_CHANGED,
71     PORTAL_ACTIVATED,
72     POSITION_IN_SET_CHANGED,
73     RELATED_NODE_CHANGED,
74     READONLY_CHANGED,
75     REQUIRED_STATE_CHANGED,
76     ROLE_CHANGED,
77     ROW_COUNT_CHANGED,
78     SCROLL_HORIZONTAL_POSITION_CHANGED,
79     SCROLL_VERTICAL_POSITION_CHANGED,
80     SELECTED_CHANGED,
81     SELECTED_CHILDREN_CHANGED,
82     SET_SIZE_CHANGED,
83     SORT_CHANGED,
84     STATE_CHANGED,
85     SUBTREE_CREATED,
86     VALUE_CHANGED,
87     VALUE_MAX_CHANGED,
88     VALUE_MIN_CHANGED,
89     VALUE_STEP_CHANGED,
90   };
91 
92   struct EventParams {
93     EventParams(Event event, ax::mojom::EventFrom event_from);
94     Event event;
95     ax::mojom::EventFrom event_from;
96 
97     bool operator==(const EventParams& rhs);
98     bool operator<(const EventParams& rhs) const;
99   };
100 
101   struct TargetedEvent {
102     // |node| must not be null
103     TargetedEvent(ui::AXNode* node, const EventParams& event_params);
104     ui::AXNode* node;
105     const EventParams& event_params;
106   };
107 
108   class AX_EXPORT Iterator
109       : public std::iterator<std::input_iterator_tag, TargetedEvent> {
110    public:
111     Iterator(
112         const std::map<AXNode*, std::set<EventParams>>& map,
113         const std::map<AXNode*, std::set<EventParams>>::const_iterator& head);
114     Iterator(const Iterator& other);
115     ~Iterator();
116 
117     bool operator!=(const Iterator& rhs) const;
118     Iterator& operator++();
119     TargetedEvent operator*() const;
120 
121    private:
122     const std::map<AXNode*, std::set<EventParams>>& map_;
123     std::map<AXNode*, std::set<EventParams>>::const_iterator map_iter_;
124     std::set<EventParams>::const_iterator set_iter_;
125   };
126 
127   using const_iterator = Iterator;
128   using iterator = Iterator;
129   using value_type = TargetedEvent;
130 
131   // If you use this constructor, you must call SetTree
132   // before using this class.
133   AXEventGenerator();
134 
135   // Automatically registers itself as the observer of |tree| and
136   // clears it on desctruction. |tree| must be valid for the lifetime
137   // of this object.
138   explicit AXEventGenerator(AXTree* tree);
139 
140   ~AXEventGenerator() override;
141 
142   // Clears this class as the observer of the previous tree that was
143   // being monitored, if any, and starts monitoring |new_tree|, if not
144   // nullptr. Note that |new_tree| must be valid for the lifetime of
145   // this object or until you call SetTree again.
146   void SetTree(AXTree* new_tree);
147 
148   // Null |tree_| without accessing it or destroying it.
149   void ReleaseTree();
150 
begin()151   Iterator begin() const {
152     return Iterator(tree_events_, tree_events_.begin());
153   }
end()154   Iterator end() const { return Iterator(tree_events_, tree_events_.end()); }
155 
156   // Clear any previously added events.
157   void ClearEvents();
158 
159   // This is called automatically based on changes to the tree observed
160   // by AXTreeObserver, but you can also call it directly to add events
161   // and retrieve them later.
162   //
163   // Note that events are organized by node and then by event id to
164   // efficiently remove duplicates, so events won't be retrieved in the
165   // same order they were added.
166   void AddEvent(ui::AXNode* node, Event event);
167 
168  protected:
169   // AXTreeObserver overrides.
170   void OnNodeDataChanged(AXTree* tree,
171                          const AXNodeData& old_node_data,
172                          const AXNodeData& new_node_data) override;
173   void OnRoleChanged(AXTree* tree,
174                      AXNode* node,
175                      ax::mojom::Role old_role,
176                      ax::mojom::Role new_role) override;
177   void OnStateChanged(AXTree* tree,
178                       AXNode* node,
179                       ax::mojom::State state,
180                       bool new_value) override;
181   void OnStringAttributeChanged(AXTree* tree,
182                                 AXNode* node,
183                                 ax::mojom::StringAttribute attr,
184                                 const std::string& old_value,
185                                 const std::string& new_value) override;
186   void OnIntAttributeChanged(AXTree* tree,
187                              AXNode* node,
188                              ax::mojom::IntAttribute attr,
189                              int32_t old_value,
190                              int32_t new_value) override;
191   void OnFloatAttributeChanged(AXTree* tree,
192                                AXNode* node,
193                                ax::mojom::FloatAttribute attr,
194                                float old_value,
195                                float new_value) override;
196   void OnBoolAttributeChanged(AXTree* tree,
197                               AXNode* node,
198                               ax::mojom::BoolAttribute attr,
199                               bool new_value) override;
200   void OnIntListAttributeChanged(
201       AXTree* tree,
202       AXNode* node,
203       ax::mojom::IntListAttribute attr,
204       const std::vector<int32_t>& old_value,
205       const std::vector<int32_t>& new_value) override;
206   void OnTreeDataChanged(AXTree* tree,
207                          const ui::AXTreeData& old_data,
208                          const ui::AXTreeData& new_data) override;
209   void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) override;
210   void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) override;
211   void OnNodeWillBeReparented(AXTree* tree, AXNode* node) override;
212   void OnSubtreeWillBeReparented(AXTree* tree, AXNode* node) override;
213   void OnAtomicUpdateFinished(AXTree* tree,
214                               bool root_changed,
215                               const std::vector<Change>& changes) override;
216 
217  private:
218   void FireLiveRegionEvents(AXNode* node);
219   void FireActiveDescendantEvents();
220   void FireRelationSourceEvents(AXTree* tree, AXNode* target_node);
221   bool ShouldFireLoadEvents(AXNode* node);
222   void PostprocessEvents();
223   static void GetRestrictionStates(ax::mojom::Restriction restriction,
224                                    bool* is_enabled,
225                                    bool* is_readonly);
226 
227   // Returns a vector of values unique to either |lhs| or |rhs|
228   static std::vector<int32_t> ComputeIntListDifference(
229       const std::vector<int32_t>& lhs,
230       const std::vector<int32_t>& rhs);
231 
232   AXTree* tree_ = nullptr;  // Not owned.
233   std::map<AXNode*, std::set<EventParams>> tree_events_;
234 
235   // Valid between the call to OnIntAttributeChanged and the call to
236   // OnAtomicUpdateFinished. List of nodes whose active descendant changed.
237   std::vector<AXNode*> active_descendant_changed_;
238 
239   // Please make sure that this ScopedObserver is always declared last in order
240   // to prevent any use-after-free.
241   ScopedObserver<AXTree, AXTreeObserver> tree_event_observer_{this};
242 };
243 
244 AX_EXPORT std::ostream& operator<<(std::ostream& os,
245                                    AXEventGenerator::Event event);
246 AX_EXPORT const char* ToString(AXEventGenerator::Event event);
247 
248 }  // namespace ui
249 
250 #endif  // UI_ACCESSIBILITY_AX_EVENT_GENERATOR_H_
251