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