1 // Copyright (c) 2012 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 CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_WIN_H_ 6 #define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_WIN_H_ 7 8 #include <oleacc.h> 9 10 #include <map> 11 #include <memory> 12 #include <set> 13 #include <vector> 14 15 #include "base/macros.h" 16 #include "content/browser/accessibility/browser_accessibility_manager.h" 17 #include "ui/accessibility/platform/ax_platform_node_win.h" 18 19 namespace content { 20 class BrowserAccessibilityWin; 21 22 // Manages a tree of BrowserAccessibilityWin objects. 23 class CONTENT_EXPORT BrowserAccessibilityManagerWin 24 : public BrowserAccessibilityManager { 25 public: 26 BrowserAccessibilityManagerWin(const ui::AXTreeUpdate& initial_tree, 27 BrowserAccessibilityDelegate* delegate); 28 29 ~BrowserAccessibilityManagerWin() override; 30 31 static ui::AXTreeUpdate GetEmptyDocument(); 32 33 // Get the closest containing HWND. 34 HWND GetParentHWND(); 35 36 // BrowserAccessibilityManager methods 37 void UserIsReloading() override; 38 BrowserAccessibility* GetFocus() const override; 39 bool CanFireEvents() const override; 40 gfx::Rect GetViewBoundsInScreenCoordinates() const override; 41 42 void FireFocusEvent(BrowserAccessibility* node) override; 43 void FireBlinkEvent(ax::mojom::Event event_type, 44 BrowserAccessibility* node) override; 45 void FireGeneratedEvent(ui::AXEventGenerator::Event event_type, 46 BrowserAccessibility* node) override; 47 48 void FireWinAccessibilityEvent(LONG win_event, BrowserAccessibility* node); 49 void FireUiaAccessibilityEvent(LONG uia_event, BrowserAccessibility* node); 50 void FireUiaPropertyChangedEvent(LONG uia_property, 51 BrowserAccessibility* node); 52 void FireUiaStructureChangedEvent(StructureChangeType change_type, 53 BrowserAccessibility* node); 54 55 // Do event pre-processing 56 void BeforeAccessibilityEvents() override; 57 58 // Do event post-processing 59 void FinalizeAccessibilityEvents() override; 60 61 // Track this object and post a VISIBLE_DATA_CHANGED notification when 62 // its container scrolls. 63 // TODO(dmazzoni): remove once http://crbug.com/113483 is fixed. 64 void TrackScrollingObject(BrowserAccessibilityWin* node); 65 66 // Called when |accessible_hwnd_| is deleted by its parent. 67 void OnAccessibleHwndDeleted(); 68 69 protected: 70 // AXTreeObserver methods. 71 void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override; 72 void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override; 73 void OnAtomicUpdateFinished( 74 ui::AXTree* tree, 75 bool root_changed, 76 const std::vector<ui::AXTreeObserver::Change>& changes) override; 77 78 private: 79 struct SelectionEvents { 80 std::vector<BrowserAccessibility*> added; 81 std::vector<BrowserAccessibility*> removed; 82 SelectionEvents(); 83 ~SelectionEvents(); 84 }; 85 86 using SelectionEventsMap = std::map<BrowserAccessibility*, SelectionEvents>; 87 using IsSelectedPredicate = 88 base::RepeatingCallback<bool(BrowserAccessibility*)>; 89 using FirePlatformSelectionEventsCallback = 90 base::RepeatingCallback<void(BrowserAccessibility*, 91 BrowserAccessibility*, 92 const SelectionEvents&)>; 93 94 static bool IsIA2NodeSelected(BrowserAccessibility* node); 95 static bool IsUIANodeSelected(BrowserAccessibility* node); 96 97 void FireIA2SelectionEvents(BrowserAccessibility* container, 98 BrowserAccessibility* only_selected_child, 99 const SelectionEvents& changes); 100 void FireUIASelectionEvents(BrowserAccessibility* container, 101 BrowserAccessibility* only_selected_child, 102 const SelectionEvents& changes); 103 104 static void HandleSelectedStateChanged( 105 SelectionEventsMap& selection_events_map, 106 BrowserAccessibility* node, 107 bool is_selected); 108 109 static void FinalizeSelectionEvents( 110 SelectionEventsMap& selection_events_map, 111 IsSelectedPredicate is_selected_predicate, 112 FirePlatformSelectionEventsCallback fire_platform_events_callback); 113 114 void HandleAriaPropertiesChangedEvent(BrowserAccessibility& node); 115 void HandleTextChangedEvent(BrowserAccessibility& node); 116 void HandleTextSelectionChangedEvent(BrowserAccessibility& node); 117 118 // Give BrowserAccessibilityManager::Create access to our constructor. 119 friend class BrowserAccessibilityManager; 120 121 // Keep track of if we got a "load complete" event but were unable to fire 122 // it because of no HWND, because otherwise JAWS can get very confused. 123 // TODO(dmazzoni): a better fix would be to always have an HWND. 124 // http://crbug.com/521877 125 bool load_complete_pending_; 126 127 // Since there could be multiple aria property changes on a node and we only 128 // want to fire UIA_AriaPropertiesPropertyId once for that node, we use the 129 // set here to keep track of the unique nodes that had aria property changes, 130 // so we only fire the event once for every node. 131 std::set<BrowserAccessibility*> aria_properties_events_; 132 133 // Since there could be duplicate text selection changed events on a node 134 // raised from both FireBlinkEvent and FireGeneratedEvent, we use the set here 135 // to keep track of the unique nodes that had 136 // UIA_Text_TextSelectionChangedEventId, so we only fire the event once for 137 // every node. 138 std::set<BrowserAccessibility*> text_selection_changed_events_; 139 140 // Since there could be duplicate text changed events on a node raised from 141 // both FireBlinkEvent and FireGeneratedEvent, we use the set here to keep 142 // track of the unique nodes that had UIA_Text_TextChangedEventId, so we only 143 // fire the event once for every node. 144 std::set<BrowserAccessibility*> text_changed_events_; 145 146 // When the ignored state changes for a node, we only want to fire the 147 // events relevant to the ignored state change (e.g. show / hide). 148 // This set keeps track of what nodes should suppress superfluous events. 149 std::set<BrowserAccessibility*> ignored_changed_nodes_; 150 151 // Keep track of selection changes so we can optimize UIA event firing. 152 // Pointers are only stored for the duration of |OnAccessibilityEvents|, and 153 // the map is cleared in |FinalizeAccessibilityEvents|. 154 SelectionEventsMap ia2_selection_events_; 155 SelectionEventsMap uia_selection_events_; 156 157 DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerWin); 158 }; 159 160 } // namespace content 161 162 #endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_WIN_H_ 163