| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_PUBLIC_TEST_ACCESSIBILITY_NOTIFICATION_WAITER_H_ |
| #define CONTENT_PUBLIC_TEST_ACCESSIBILITY_NOTIFICATION_WAITER_H_ |
| |
| #include <memory> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "ui/accessibility/ax_event_generator.h" |
| #include "ui/accessibility/ax_node_data.h" |
| #include "ui/accessibility/ax_node_id_forward.h" |
| #include "ui/accessibility/ax_tree.h" |
| |
| namespace base { |
| class RunLoop; |
| } |
| |
| namespace ui { |
| class BrowserAccessibilityManager; |
| } |
| |
| namespace content { |
| |
| class RenderFrameHost; |
| class RenderFrameHostImpl; |
| class WebContents; |
| |
| // Create an instance of this class *before* doing any operation that |
| // might generate an accessibility event (like a page navigation or |
| // clicking on a button). Then call WaitForNotification |
| // afterwards to block until the specified accessibility notification has been |
| // received. |
| class AccessibilityNotificationWaiter : public WebContentsObserver { |
| public: |
| // Will wait for any event across all ways including scroll or location |
| // changes as well normal and generated events. |
| explicit AccessibilityNotificationWaiter(WebContents* web_contents); |
| |
| // Wait for a specific Blink event. |
| AccessibilityNotificationWaiter(WebContents* web_contents, |
| ax::mojom::Event event); |
| |
| // Wait for a specific AXEventGenerator event. |
| AccessibilityNotificationWaiter(WebContents* web_contents, |
| ui::AXEventGenerator::Event event); |
| |
| AccessibilityNotificationWaiter(const AccessibilityNotificationWaiter&) = |
| delete; |
| AccessibilityNotificationWaiter& operator=( |
| const AccessibilityNotificationWaiter&) = delete; |
| |
| ~AccessibilityNotificationWaiter() override; |
| |
| // Blocks until the specific accessibility notification registered in |
| // AccessibilityNotificationWaiter is received. Returns true if an event was |
| // received, false if waiting ended for some other reason. |
| // Pass true for |all_frames| to wait for a notification on all frames |
| // before returning, rather than waiting for only a single notification |
| // from any frame. |
| [[nodiscard]] bool WaitForNotification(bool all_frames = false); |
| |
| // Blocks until the notification is received, or the given timeout passes. |
| // Returns true if an event was received, false if waiting ended for some |
| // other reason. |
| [[nodiscard]] bool WaitForNotificationWithTimeout(base::TimeDelta timeout); |
| |
| // After WaitForNotification has returned, this will retrieve |
| // the tree of accessibility nodes received from the renderer process for |
| // the observed WebContents (not including the trees of inner WebContents). |
| const ui::AXTree& GetAXTree() const; |
| |
| // After WaitForNotification returns, use this to retrieve the id of the |
| // node that was the target of the event. |
| int event_target_id() const { return event_target_id_; } |
| |
| bool notification_received() const { return notification_received_; } |
| |
| // After WaitForNotification returns, use this to retrieve the |
| // `BrowserAccessibilityManager` that was the target of the event. |
| ui::BrowserAccessibilityManager* event_browser_accessibility_manager() const { |
| return event_browser_accessibility_manager_; |
| } |
| |
| // WebContentsObserver override: |
| void RenderFrameHostChanged(RenderFrameHost* old_host, |
| RenderFrameHost* new_host) override; |
| |
| // Quits listening and unblocks WaitForNotification* calls. |
| void Quit(); |
| |
| private: |
| // Listen to all frames within the frame tree of this WebContents. |
| void ListenToAllFrames(WebContents* web_contents); |
| |
| // Bind either the OnAccessibilityEvent or OnGeneratedEvent callback |
| // for a given frame within the WebContent's frame tree. |
| void ListenToFrame(RenderFrameHostImpl* frame_host); |
| |
| // Helper to bind the OnAccessibilityEvent callback. |
| void BindOnAccessibilityEvent(RenderFrameHostImpl* frame_host); |
| |
| // Helper to bind the OnGeneratedEvent callback. |
| void BindOnGeneratedEvent(RenderFrameHostImpl* frame_host); |
| |
| // Helper to bind the OnLocationsChanged callback. |
| void BindOnLocationsChanged(RenderFrameHostImpl* frame_host); |
| |
| // Callback from RenderViewHostImpl. |
| void OnAccessibilityEvent(RenderFrameHostImpl* rfhi, |
| ax::mojom::Event event, |
| int event_target_id); |
| |
| // Callback from BrowserAccessibilityManager for all generated events. |
| void OnGeneratedEvent(ui::BrowserAccessibilityManager* manager, |
| ui::AXEventGenerator::Event event, |
| ui::AXNodeID event_target_id); |
| |
| // Callback from BrowserAccessibilityManager when locations / bounding |
| // boxes change. |
| void OnLocationsChanged(); |
| |
| // Callback from BrowserAccessibilityManager for the focus changed event. |
| // |
| // TODO(crbug.com/41470112): Remove this method once we migrate to using |
| // AXEventGenerator for focus changed events. |
| void OnFocusChanged(); |
| |
| // Returns the tree of accessibility nodes received from renderer processes |
| // for the WebContents that owns `render_frame`. This may not be the observed |
| // WebContents, but rather an inner WebContents (e.g., for a guest view). |
| const ui::AXTree& GetAXTreeForFrame(RenderFrameHostImpl* render_frame) const; |
| |
| std::optional<ax::mojom::Event> event_to_wait_for_; |
| std::optional<ui::AXEventGenerator::Event> generated_event_to_wait_for_; |
| std::unique_ptr<base::RunLoop> loop_runner_; |
| base::RepeatingClosure loop_runner_quit_closure_; |
| int event_target_id_ = 0; |
| raw_ptr<ui::BrowserAccessibilityManager, AcrossTasksDanglingUntriaged> |
| event_browser_accessibility_manager_ = nullptr; |
| bool notification_received_ = false; |
| int frame_count_ = 0; |
| int notification_count_ = 0; |
| bool wait_for_any_event_ = false; |
| |
| base::WeakPtrFactory<AccessibilityNotificationWaiter> weak_factory_{this}; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_PUBLIC_TEST_ACCESSIBILITY_NOTIFICATION_WAITER_H_ |