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_H_
6 #define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <set>
13 #include <string>
14 #include <unordered_map>
15 #include <vector>
16 
17 #include "base/callback_forward.h"
18 #include "base/macros.h"
19 #include "base/scoped_observation.h"
20 #include "build/build_config.h"
21 #include "content/browser/accessibility/accessibility_buildflags.h"
22 #include "content/browser/accessibility/browser_accessibility_position.h"
23 #include "content/common/content_export.h"
24 #include "content/common/render_accessibility.mojom-forward.h"
25 #include "content/public/browser/ax_event_notification_details.h"
26 #include "content/public/browser/web_contents_observer.h"
27 #include "third_party/blink/public/web/web_ax_enums.h"
28 #include "ui/accessibility/ax_action_data.h"
29 #include "ui/accessibility/ax_event_generator.h"
30 #include "ui/accessibility/ax_node.h"
31 #include "ui/accessibility/ax_node_data.h"
32 #include "ui/accessibility/ax_range.h"
33 #include "ui/accessibility/ax_serializable_tree.h"
34 #include "ui/accessibility/ax_tree.h"
35 #include "ui/accessibility/ax_tree_id_registry.h"
36 #include "ui/accessibility/ax_tree_manager.h"
37 #include "ui/accessibility/ax_tree_observer.h"
38 #include "ui/accessibility/ax_tree_update.h"
39 #include "ui/accessibility/platform/ax_platform_node.h"
40 #include "ui/gfx/native_widget_types.h"
41 
42 namespace content {
43 class BrowserAccessibility;
44 class BrowserAccessibilityDelegate;
45 class BrowserAccessibilityManager;
46 #if defined(OS_ANDROID)
47 class BrowserAccessibilityManagerAndroid;
48 #elif defined(OS_WIN)
49 class BrowserAccessibilityManagerWin;
50 #elif BUILDFLAG(USE_ATK)
51 class BrowserAccessibilityManagerAuraLinux;
52 #elif defined(OS_MAC)
53 class BrowserAccessibilityManagerMac;
54 #endif
55 
56 // To be called when a BrowserAccessibilityManager fires a generated event.
57 // Provides the host, the event fired, and which node id the event was for.
58 typedef base::RepeatingCallback<
59     void(BrowserAccessibilityDelegate*, ui::AXEventGenerator::Event, int)>
60     GeneratedEventCallbackForTesting;
61 
62 // For testing.
63 CONTENT_EXPORT ui::AXTreeUpdate MakeAXTreeUpdate(
64     const ui::AXNodeData& node,
65     const ui::AXNodeData& node2 = ui::AXNodeData(),
66     const ui::AXNodeData& node3 = ui::AXNodeData(),
67     const ui::AXNodeData& node4 = ui::AXNodeData(),
68     const ui::AXNodeData& node5 = ui::AXNodeData(),
69     const ui::AXNodeData& node6 = ui::AXNodeData(),
70     const ui::AXNodeData& node7 = ui::AXNodeData(),
71     const ui::AXNodeData& node8 = ui::AXNodeData(),
72     const ui::AXNodeData& node9 = ui::AXNodeData(),
73     const ui::AXNodeData& node10 = ui::AXNodeData(),
74     const ui::AXNodeData& node11 = ui::AXNodeData(),
75     const ui::AXNodeData& node12 = ui::AXNodeData());
76 
77 // Class that can perform actions on behalf of the BrowserAccessibilityManager.
78 // Note: BrowserAccessibilityManager should never cache any of the return
79 // values from any of these interfaces, especially those that return pointers.
80 // They may only be valid within this call stack. That policy eliminates any
81 // concerns about ownership and lifecycle issues; none of these interfaces
82 // transfer ownership and no return values are guaranteed to be valid outside
83 // of the current call stack.
84 class CONTENT_EXPORT BrowserAccessibilityDelegate {
85  public:
~BrowserAccessibilityDelegate()86   virtual ~BrowserAccessibilityDelegate() {}
87 
88   virtual void AccessibilityPerformAction(const ui::AXActionData& data) = 0;
89   virtual bool AccessibilityViewHasFocus() = 0;
90   virtual void AccessibilityViewSetFocus() = 0;
91   virtual gfx::Rect AccessibilityGetViewBounds() = 0;
92   virtual float AccessibilityGetDeviceScaleFactor() = 0;
93   virtual void AccessibilityFatalError() = 0;
94   virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() = 0;
95   virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() = 0;
96   virtual gfx::NativeViewAccessible
97   AccessibilityGetNativeViewAccessibleForWindow() = 0;
98   virtual WebContents* AccessibilityWebContents() = 0;
99   virtual void AccessibilityHitTest(
100       const gfx::Point& point_in_frame_pixels,
101       ax::mojom::Event opt_event_to_fire,
102       int opt_request_id,
103       base::OnceCallback<void(BrowserAccessibilityManager* hit_manager,
104                               int hit_node_id)> opt_callback) = 0;
105 
106   // Returns true if this delegate represents the main (topmost) frame in a
107   // tree of frames.
108   virtual bool AccessibilityIsMainFrame() = 0;
109 };
110 
111 // This is all of the information about the current find in page result,
112 // so we can activate it if requested.
113 struct BrowserAccessibilityFindInPageInfo {
114   BrowserAccessibilityFindInPageInfo();
115 
116   // This data about find in text results is updated as the user types.
117   int request_id;
118   int match_index;
119   int start_id;
120   int start_offset;
121   int end_id;
122   int end_offset;
123 
124   // The active request id indicates that the user committed to a find query,
125   // e.g. by pressing enter or pressing the next or previous buttons. If
126   // |active_request_id| == |request_id|, we fire an accessibility event
127   // to move screen reader focus to that event.
128   int active_request_id;
129 };
130 
131 // Manages a tree of BrowserAccessibility objects.
132 class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
133                                                    public ui::AXTreeManager,
134                                                    public WebContentsObserver {
135  protected:
136   using BrowserAccessibilityPositionInstance =
137       BrowserAccessibilityPosition::AXPositionInstance;
138   using BrowserAccessibilityRange =
139       ui::AXRange<BrowserAccessibilityPositionInstance::element_type>;
140 
141  public:
142   // Creates the platform-specific BrowserAccessibilityManager, but
143   // with no parent window pointer. Only useful for unit tests.
144   static BrowserAccessibilityManager* Create(
145       const ui::AXTreeUpdate& initial_tree,
146       BrowserAccessibilityDelegate* delegate);
147 
148   static BrowserAccessibilityManager* FromID(ui::AXTreeID ax_tree_id);
149 
150   ~BrowserAccessibilityManager() override;
151 
152   void Initialize(const ui::AXTreeUpdate& initial_tree);
153 
154   static ui::AXTreeUpdate GetEmptyDocument();
155 
156   enum RetargetEventType {
157     RetargetEventTypeGenerated = 0,
158     RetargetEventTypeBlinkGeneral,
159     RetargetEventTypeBlinkHover,
160   };
161 
162   // Return |node| by default, but some platforms want to update the target node
163   // based on the event type.
164   virtual BrowserAccessibility* RetargetForEvents(BrowserAccessibility* node,
165                                                   RetargetEventType type) const;
166 
167   // Subclasses override these methods to send native event notifications.
168   virtual void FireFocusEvent(BrowserAccessibility* node);
FireBlinkEvent(ax::mojom::Event event_type,BrowserAccessibility * node)169   virtual void FireBlinkEvent(ax::mojom::Event event_type,
170                               BrowserAccessibility* node) {}
171   virtual void FireGeneratedEvent(ui::AXEventGenerator::Event event_type,
172                                   BrowserAccessibility* node);
173 
174   // Checks whether focus has changed since the last time it was checked,
175   // taking into account whether the window has focus and which frame within
176   // the frame tree has focus. If focus has changed, calls FireFocusEvent.
177   void FireFocusEventsIfNeeded();
178 
179   // Return whether or not we are currently able to fire events.
180   virtual bool CanFireEvents() const;
181 
182   // Return a pointer to the root of the tree.
183   BrowserAccessibility* GetRoot() const;
184 
185   // Returns a pointer to the BrowserAccessibility object for a given AXNode.
186   BrowserAccessibility* GetFromAXNode(const ui::AXNode* node) const;
187 
188   // Return a pointer to the object corresponding to the given id,
189   // does not make a new reference.
190   BrowserAccessibility* GetFromID(int32_t id) const;
191 
192   // If this tree has a parent tree, return the parent node in that tree.
193   BrowserAccessibility* GetParentNodeFromParentTree() const;
194 
195   // In general, there is only a single node with the role of kRootWebArea,
196   // but if a popup is opened, a second nested "root" is created in the same
197   // tree as the "true" root. This will keep track of the nested root node.
198   BrowserAccessibility* GetPopupRoot() const;
199 
200   // Get the AXTreeData for this frame.
201   const ui::AXTreeData& GetTreeData() const;
202 
203   // Called to notify the accessibility manager that its associated native
204   // view got focused.
205   virtual void OnWindowFocused();
206 
207   // Called to notify the accessibility manager that its associated native
208   // view lost focus.
209   virtual void OnWindowBlurred();
210 
211   // Notify the accessibility manager about page navigation.
212   // TODO(domfarolino, dmazzoni): Implement WebContentsObserver methods that
213   // correspond to the ones we provide today, so we can stop being manually
214   // notified of navigation events when they happen.
215   void UserIsNavigatingAway();
216   virtual void UserIsReloading();
217   void NavigationSucceeded();
218   void NavigationFailed();
219 
220   // WebContentsObserver overrides
221   void DidStopLoading() override;
222   void DidActivatePortal(WebContents* predecessor_contents,
223                          base::TimeTicks activation_time) override;
224 
225   // Keep track of if this page is hidden by an interstitial, in which case
226   // we need to suppress all events.
set_hidden_by_interstitial_page(bool hidden)227   void set_hidden_by_interstitial_page(bool hidden) {
228     hidden_by_interstitial_page_ = hidden;
229   }
hidden_by_interstitial_page()230   bool hidden_by_interstitial_page() const {
231     return hidden_by_interstitial_page_;
232   }
233 
234   // Pretend that the given node has focus, for testing only. Doesn't
235   // communicate with the renderer and doesn't fire any events.
236   void SetFocusLocallyForTesting(BrowserAccessibility* node);
237 
238   // For testing only, register a function to be called when focus changes
239   // in any BrowserAccessibilityManager.
240   static void SetFocusChangeCallbackForTesting(base::RepeatingClosure callback);
241 
242   // For testing only, register a function to be called when
243   // a generated event is fired from this BrowserAccessibilityManager.
244   void SetGeneratedEventCallbackForTesting(
245       const GeneratedEventCallbackForTesting& callback);
246 
247   // Normally we avoid firing accessibility focus events when the containing
248   // native window isn't focused, and we also delay some other events like
249   // live region events to improve screen reader compatibility.
250   // However, this can lead to test flakiness, so for testing, simplify
251   // this behavior and just fire all events with no delay as if the window
252   // had focus.
253   static void NeverSuppressOrDelayEventsForTesting();
254 
255   // Accessibility actions. All of these are implemented asynchronously
256   // by sending a message to the renderer to perform the respective action
257   // on the given node.  See the definition of |ui::AXActionData| for more
258   // information about each of these actions.
259   void ClearAccessibilityFocus(const BrowserAccessibility& node);
260   void Decrement(const BrowserAccessibility& node);
261   void DoDefaultAction(const BrowserAccessibility& node);
262   void GetImageData(const BrowserAccessibility& node,
263                     const gfx::Size& max_size);
264   // Per third_party/blink/renderer/core/layout/hit_test_location.h, Blink
265   // expects hit test points in page coordinates. However, WebAXObject::HitTest
266   // applies the visual viewport offset, so we want to pass that function a
267   // point in frame coordinates.
268   void HitTest(const gfx::Point& frame_point) const;
269   void Increment(const BrowserAccessibility& node);
270   void LoadInlineTextBoxes(const BrowserAccessibility& node);
271   void ScrollToMakeVisible(
272       const BrowserAccessibility& node,
273       gfx::Rect subfocus,
274       ax::mojom::ScrollAlignment horizontal_scroll_alignment =
275           ax::mojom::ScrollAlignment::kScrollAlignmentCenter,
276       ax::mojom::ScrollAlignment vertical_scroll_alignment =
277           ax::mojom::ScrollAlignment::kScrollAlignmentCenter,
278       ax::mojom::ScrollBehavior scroll_behavior =
279           ax::mojom::ScrollBehavior::kDoNotScrollIfVisible);
280   void ScrollToPoint(const BrowserAccessibility& node, gfx::Point point);
281   void SetAccessibilityFocus(const BrowserAccessibility& node);
282   void SetFocus(const BrowserAccessibility& node);
283   void SetSequentialFocusNavigationStartingPoint(
284       const BrowserAccessibility& node);
285   void SetScrollOffset(const BrowserAccessibility& node, gfx::Point offset);
286   void SetValue(const BrowserAccessibility& node, const std::string& value);
287   void SetSelection(const ui::AXActionData& action_data);
288   void SetSelection(const BrowserAccessibilityRange& range);
289   void ShowContextMenu(const BrowserAccessibility& node);
290   void SignalEndOfTest();
291 
292   // Retrieve the bounds of the parent View in screen coordinates.
293   virtual gfx::Rect GetViewBoundsInScreenCoordinates() const;
294 
295   // Fire an event telling native assistive technology to move focus to the
296   // given find in page result.
297   void ActivateFindInPageResult(int request_id, int match_index);
298 
299   // Called when the renderer process has notified us of tree changes. Returns
300   // false in fatal-error conditions, in which case the caller should destroy
301   // the manager.
302   virtual bool OnAccessibilityEvents(const AXEventNotificationDetails& details)
303       WARN_UNUSED_RESULT;
304 
305   // Allows derived classes to do event pre-processing
306   virtual void BeforeAccessibilityEvents();
307 
308   // Allows derived classes to do event post-processing.
309   virtual void FinalizeAccessibilityEvents();
310 
311   // Called when the renderer process updates the location of accessibility
312   // objects. Calls SendLocationChangeEvents(), which can be overridden.
313   void OnLocationChanges(const std::vector<mojom::LocationChangesPtr>& changes);
314 
315   // Called when a new find in page result is received. We hold on to this
316   // information and don't activate it until the user requests it.
317   virtual void OnFindInPageResult(int request_id,
318                                   int match_index,
319                                   int start_id,
320                                   int start_offset,
321                                   int end_id,
322                                   int end_offset);
323 
324   // This is called when the user has committed to a find in page query,
325   // e.g. by pressing enter or tapping on the next / previous result buttons.
326   // If a match has already been received for this request id,
327   // activate the result now by firing an accessibility event. If a match
328   // has not been received, we hold onto this request id and update it
329   // when OnFindInPageResult is called.
330   void ActivateFindInPageResult(int request_id);
331 
332   // This is called when the user finishes a find in page query and all
333   // highlighted matches are deactivated.
OnFindInPageTermination()334   virtual void OnFindInPageTermination() {}
335 
336 #if defined(OS_WIN)
337   BrowserAccessibilityManagerWin* ToBrowserAccessibilityManagerWin();
338 #endif
339 
340 #if defined(OS_ANDROID)
341   BrowserAccessibilityManagerAndroid* ToBrowserAccessibilityManagerAndroid();
342 #endif
343 
344 #if BUILDFLAG(USE_ATK)
345   BrowserAccessibilityManagerAuraLinux*
346   ToBrowserAccessibilityManagerAuraLinux();
347 #endif
348 
349 #if defined(OS_MAC)
350   BrowserAccessibilityManagerMac* ToBrowserAccessibilityManagerMac();
351 #endif
352 
353   // Returns the object that has focus, starting at the top of the frame tree,
354   // or returns nullptr if this manager doesn't have access to the top document.
355   virtual BrowserAccessibility* GetFocus() const;
356 
357   // Return the object that has focus, only considering this frame and
358   // descendants.
359   BrowserAccessibility* GetFocusFromThisOrDescendantFrame() const;
360 
361   // Given a focused node |focus|, returns a descendant of that node if it
362   // has an active descendant, otherwise returns |focus|.
363   BrowserAccessibility* GetActiveDescendant(BrowserAccessibility* focus) const;
364 
365   // Returns true if native focus is anywhere in this WebContents or not.
366   bool NativeViewHasFocus();
367 
368   // True by default, but some platforms want to treat the root
369   // scroll offsets separately.
370   bool UseRootScrollOffsetsWhenComputingBounds();
371   void SetUseRootScrollOffsetsWhenComputingBoundsForTesting(bool use);
372 
373   // Walk the tree using depth-first pre-order traversal.
374   static BrowserAccessibility* NextInTreeOrder(
375       const BrowserAccessibility* object);
376   static BrowserAccessibility* NextNonDescendantInTreeOrder(
377       const BrowserAccessibility* object);
378   static BrowserAccessibility* PreviousInTreeOrder(
379       const BrowserAccessibility* object,
380       bool can_wrap_to_last_element);
381   static BrowserAccessibility* NextTextOnlyObject(
382       const BrowserAccessibility* object);
383   static BrowserAccessibility* PreviousTextOnlyObject(
384       const BrowserAccessibility* object);
385 
386   // If the two objects provided have a common ancestor returns both the
387   // common ancestor and the child indices of the two subtrees in which the
388   // objects are located.
389   // Returns false if a common ancestor cannot be found.
390   static bool FindIndicesInCommonParent(const BrowserAccessibility& object1,
391                                         const BrowserAccessibility& object2,
392                                         BrowserAccessibility** common_parent,
393                                         int* child_index1,
394                                         int* child_index2);
395 
396   // Sets |out_is_before| to true if |object1| comes before |object2|
397   // in tree order (pre-order traversal), and false if the objects are the
398   // same or not in the same tree.
399   static ax::mojom::TreeOrder CompareNodes(const BrowserAccessibility& object1,
400                                            const BrowserAccessibility& object2);
401 
402   static std::vector<const BrowserAccessibility*> FindTextOnlyObjectsInRange(
403       const BrowserAccessibility& start_object,
404       const BrowserAccessibility& end_object);
405 
406   static base::string16 GetTextForRange(
407       const BrowserAccessibility& start_object,
408       const BrowserAccessibility& end_object);
409 
410   // If start and end offsets are greater than the text's length, returns all
411   // the text.
412   static base::string16 GetTextForRange(
413       const BrowserAccessibility& start_object,
414       int start_offset,
415       const BrowserAccessibility& end_object,
416       int end_offset);
417 
418   // DEPRECATED: Prefer using AXPlatformNodeDelegate bounds interfaces when
419   // writing new code.
420   static gfx::Rect GetRootFrameInnerTextRangeBoundsRect(
421       const BrowserAccessibility& start_object,
422       int start_offset,
423       const BrowserAccessibility& end_object,
424       int end_offset);
425 
426   // Accessors.
ax_tree_id()427   ui::AXTreeID ax_tree_id() const { return ax_tree_id_; }
device_scale_factor()428   float device_scale_factor() const { return device_scale_factor_; }
ax_tree()429   ui::AXTree* ax_tree() const { return tree_.get(); }
430 
431   // AXTreeObserver implementation.
432   void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
433   void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
434   void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override;
435   void OnNodeDeleted(ui::AXTree* tree, int32_t node_id) override;
436   void OnNodeReparented(ui::AXTree* tree, ui::AXNode* node) override;
437   void OnRoleChanged(ui::AXTree* tree,
438                      ui::AXNode* node,
439                      ax::mojom::Role old_role,
440                      ax::mojom::Role new_role) override;
441   void OnAtomicUpdateFinished(
442       ui::AXTree* tree,
443       bool root_changed,
444       const std::vector<ui::AXTreeObserver::Change>& changes) override;
445 
446   // AXTreeManager overrides.
447   ui::AXNode* GetNodeFromTree(ui::AXTreeID tree_id,
448                               ui::AXNode::AXID node_id) const override;
449   ui::AXNode* GetNodeFromTree(ui::AXNode::AXID node_id) const override;
450   void AddObserver(ui::AXTreeObserver* observer) override;
451   void RemoveObserver(ui::AXTreeObserver* observer) override;
452   AXTreeID GetTreeID() const override;
453   AXTreeID GetParentTreeID() const override;
454   ui::AXNode* GetRootAsAXNode() const override;
455   ui::AXNode* GetParentNodeFromParentTreeAsAXNode() const override;
456 
delegate()457   BrowserAccessibilityDelegate* delegate() const { return delegate_; }
458 
459   // If this BrowserAccessibilityManager is a child frame or guest frame,
460   // returns the BrowserAccessibilityManager from the top document in the frame
461   // tree. If the current frame is not connected to its parent frame yet, or if
462   // it got disconnected after being reparented, return nullptr to indicate that
463   // we don't have access to the root manager yet.
464   BrowserAccessibilityManager* GetRootManager() const;
465 
466   // Returns the BrowserAccessibilityDelegate from |GetRootManager| above, or
467   // returns nullptr in case we don't have access to the root manager yet.
468   BrowserAccessibilityDelegate* GetDelegateFromRootManager() const;
469 
470   // Returns whether this is the top document.
471   bool IsRootTree() const;
472 
473   // Get a snapshot of the current tree as an AXTreeUpdate.
474   ui::AXTreeUpdate SnapshotAXTreeForTesting();
475 
476   // Use a custom device scale factor for testing.
477   void UseCustomDeviceScaleFactorForTesting(float device_scale_factor);
478 
479   // Given a point in physical pixel coordinates, trigger an asynchronous hit
480   // test but return the best possible match instantly.
481   BrowserAccessibility* CachingAsyncHitTest(
482       const gfx::Point& physical_pixel_point) const;
483 
484   // Called in response to a hover event, caches the result for the next
485   // call to CachingAsyncHitTest().
486   void CacheHitTestResult(BrowserAccessibility* hit_test_result) const;
487 
488   // Updates the page scale factor for this frame.
489   void SetPageScaleFactor(float page_scale_factor);
490 
491   // Returns the current page scale factor for this frame.
492   float GetPageScaleFactor() const;
493 
494  protected:
495   FRIEND_TEST_ALL_PREFIXES(BrowserAccessibilityManagerTest,
496                            TestShouldFireEventForNode);
497   explicit BrowserAccessibilityManager(BrowserAccessibilityDelegate* delegate);
498 
499   BrowserAccessibilityManager(const ui::AXTreeUpdate& initial_tree,
500                               BrowserAccessibilityDelegate* delegate);
501 
502   // Send platform-specific notifications to each of these objects that
503   // their location has changed. This is called by OnLocationChanges
504   // after it's updated the internal data structure.
505   virtual void SendLocationChangeEvents(
506       const std::vector<mojom::LocationChangesPtr>& changes);
507 
508   // Given the data from an atomic update, collect the nodes that need updating
509   // assuming that this platform is one where plain text node content is
510   // directly included in parents' hypertext.
511   void CollectChangedNodesAndParentsForAtomicUpdate(
512       ui::AXTree* tree,
513       const std::vector<ui::AXTreeObserver::Change>& changes,
514       std::set<ui::AXPlatformNode*>* nodes_needing_update);
515 
516   bool ShouldFireEventForNode(BrowserAccessibility* node) const;
517 
518   static void SetLastFocusedNode(BrowserAccessibility* node);
519   static BrowserAccessibility* GetLastFocusedNode();
520 
521   // The object that can perform actions on our behalf.
522   BrowserAccessibilityDelegate* delegate_;
523 
524   // A mapping from a node id to its wrapper of type BrowserAccessibility.
525   std::map<int32_t, BrowserAccessibility*> id_wrapper_map_;
526 
527   // True if the user has initiated a navigation to another page.
528   bool user_is_navigating_away_;
529 
530   // Interstitial page, like an SSL warning.
531   // If so we need to suppress any events.
532   bool hidden_by_interstitial_page_ = false;
533 
534   BrowserAccessibilityFindInPageInfo find_in_page_info_;
535 
536   // These cache the AX tree ID, node ID, and global screen bounds of the
537   // last object found by an asynchronous hit test. Subsequent hit test
538   // requests that remain within this object's bounds will return the same
539   // object, but will also trigger a new asynchronous hit test request.
540   mutable ui::AXTreeID last_hover_ax_tree_id_;
541   mutable int last_hover_node_id_;
542   mutable gfx::Rect last_hover_bounds_;
543 
544   // True if the root's parent is in another accessibility tree and that
545   // parent's child is the root. Ensures that the parent node is notified
546   // once when this subtree is first connected.
547   bool connected_to_parent_tree_node_;
548 
549   // The global ID of this accessibility tree.
550   ui::AXTreeID ax_tree_id_;
551 
552   // The device scale factor for the view associated with this frame,
553   // cached each time there's any update to the accessibility tree.
554   float device_scale_factor_;
555 
556   // The page scale factor for the view associated with this frame,
557   // cached when we get an update via SetPageScaleFactor().
558   float page_scale_factor_ = 1.0f;
559 
560   // For testing only: If true, the manually-set device scale factor will be
561   // used and it won't be updated from the delegate.
562   bool use_custom_device_scale_factor_for_testing_;
563 
564   // Whether we should include or exclude the scroll offsets on the root
565   // scroller when computing bounding rectangles. Usually true, but on
566   // some platforms the root scroll offsets are handled separately.
567   bool use_root_scroll_offsets_when_computing_bounds_ = true;
568 
569   // For testing only: A function to call when a generated event is fired.
570   GeneratedEventCallbackForTesting generated_event_callback_for_testing_;
571 
572   // Keeps track of the nested popup root's id, if it exists. See GetPopupRoot()
573   // for details.
574   std::set<int32_t> popup_root_ids_;
575 
576   // Fire all events regardless of focus and with no delay, to avoid test
577   // flakiness. See NeverSuppressOrDelayEventsForTesting() for details.
578   static bool never_suppress_or_delay_events_for_testing_;
579 
event_generator()580   const ui::AXEventGenerator& event_generator() const {
581     return event_generator_;
582   }
event_generator()583   ui::AXEventGenerator& event_generator() { return event_generator_; }
584 
585   // Stores the id of the last focused node across all frames, as well as the id
586   // of the tree that contains it, so that when focus might have changed we can
587   // figure out whether we need to fire a focus event.
588   //
589   // NOTE: Don't use or modify these properties directly, use the
590   // SetLastFocusedNode and GetLastFocusedNode methods instead.
591   static base::Optional<int32_t> last_focused_node_id_;
592   static base::Optional<ui::AXTreeID> last_focused_node_tree_id_;
593 
594   // For debug only: True when handling OnAccessibilityEvents.
595 #if DCHECK_IS_ON()
596   bool in_on_accessibility_events_ = false;
597 #endif  // DCHECK_IS_ON()
598 
599  private:
600   // Helper that calls AXTree::Unserialize(). On failure it populates crash data
601   // with error information.
602   bool Unserialize(const ui::AXTreeUpdate& tree_update);
603 
604   // The underlying tree of accessibility objects.
605   std::unique_ptr<ui::AXSerializableTree> tree_;
606 
607   ui::AXEventGenerator event_generator_;
608 
609   // Automatically stops observing notifications from the AXTree when this class
610   // is destructed.
611   //
612   // This member needs to be destructed before any observed AXTrees. Since
613   // destructors for non-static member fields are called in the reverse order of
614   // declaration, do not move this member above other members.
615   base::ScopedObservation<ui::AXTree, ui::AXTreeObserver> tree_observation_{
616       this};
617 
618   DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManager);
619 };
620 
621 }  // namespace content
622 
623 #endif  // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_H_
624