|  | // Copyright 2013 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "content/test/accessibility_browser_test_utils.h" | 
|  |  | 
|  | #include "base/bind.h" | 
|  | #include "base/logging.h" | 
|  | #include "base/strings/string_util.h" | 
|  | #include "base/strings/utf_string_conversions.h" | 
|  | #include "content/browser/frame_host/render_frame_host_impl.h" | 
|  | #include "content/browser/renderer_host/render_widget_host_view_base.h" | 
|  | #include "content/browser/web_contents/web_contents_impl.h" | 
|  | #include "content/common/view_message_enums.h" | 
|  | #include "content/public/browser/web_contents.h" | 
|  | #include "content/public/common/url_constants.h" | 
|  | #include "content/public/test/test_utils.h" | 
|  | #include "ui/accessibility/ax_node.h" | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | AccessibilityNotificationWaiter::AccessibilityNotificationWaiter( | 
|  | WebContents* web_contents) | 
|  | : event_to_wait_for_(ui::AX_EVENT_NONE), | 
|  | loop_runner_(new MessageLoopRunner()), | 
|  | event_target_id_(0), | 
|  | event_render_frame_host_(nullptr), | 
|  | weak_factory_(this) { | 
|  | frame_host_ = static_cast<RenderFrameHostImpl*>( | 
|  | web_contents->GetMainFrame()); | 
|  | frame_host_->SetAccessibilityCallbackForTesting( | 
|  | base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent, | 
|  | weak_factory_.GetWeakPtr())); | 
|  | } | 
|  |  | 
|  | AccessibilityNotificationWaiter::AccessibilityNotificationWaiter( | 
|  | WebContents* web_contents, | 
|  | AccessibilityMode accessibility_mode, | 
|  | ui::AXEvent event_type) | 
|  | : event_to_wait_for_(event_type), | 
|  | loop_runner_(new MessageLoopRunner()), | 
|  | event_target_id_(0), | 
|  | weak_factory_(this) { | 
|  | WebContentsImpl* web_contents_impl = static_cast<WebContentsImpl*>( | 
|  | web_contents); | 
|  | frame_host_ = static_cast<RenderFrameHostImpl*>( | 
|  | web_contents_impl->GetMainFrame()); | 
|  | frame_host_->SetAccessibilityCallbackForTesting( | 
|  | base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent, | 
|  | weak_factory_.GetWeakPtr())); | 
|  | web_contents_impl->AddAccessibilityMode(accessibility_mode); | 
|  | } | 
|  |  | 
|  | AccessibilityNotificationWaiter::AccessibilityNotificationWaiter( | 
|  | RenderFrameHostImpl* frame_host, | 
|  | ui::AXEvent event_type) | 
|  | : frame_host_(frame_host), | 
|  | event_to_wait_for_(event_type), | 
|  | loop_runner_(new MessageLoopRunner()), | 
|  | event_target_id_(0), | 
|  | weak_factory_(this) { | 
|  | frame_host_->SetAccessibilityCallbackForTesting( | 
|  | base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent, | 
|  | weak_factory_.GetWeakPtr())); | 
|  | } | 
|  |  | 
|  | AccessibilityNotificationWaiter::~AccessibilityNotificationWaiter() { | 
|  | } | 
|  |  | 
|  | void AccessibilityNotificationWaiter::ListenToAdditionalFrame( | 
|  | RenderFrameHostImpl* frame_host) { | 
|  | frame_host->SetAccessibilityCallbackForTesting( | 
|  | base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent, | 
|  | weak_factory_.GetWeakPtr())); | 
|  | } | 
|  |  | 
|  | void AccessibilityNotificationWaiter::WaitForNotification() { | 
|  | loop_runner_->Run(); | 
|  |  | 
|  | // Each loop runner can only be called once. Create a new one in case | 
|  | // the caller wants to call this again to wait for the next notification. | 
|  | loop_runner_ = new MessageLoopRunner(); | 
|  | } | 
|  |  | 
|  | const ui::AXTree& AccessibilityNotificationWaiter::GetAXTree() const { | 
|  | CR_DEFINE_STATIC_LOCAL(ui::AXTree, empty_tree, ()); | 
|  | const ui::AXTree* tree = frame_host_->GetAXTreeForTesting(); | 
|  | if (tree) | 
|  | return *tree; | 
|  | return empty_tree; | 
|  | } | 
|  |  | 
|  | void AccessibilityNotificationWaiter::OnAccessibilityEvent( | 
|  | RenderFrameHostImpl* rfhi, | 
|  | ui::AXEvent event_type, | 
|  | int event_target_id) { | 
|  | if (!IsAboutBlank() && (event_to_wait_for_ == ui::AX_EVENT_NONE || | 
|  | event_to_wait_for_ == event_type)) { | 
|  | event_target_id_ = event_target_id; | 
|  | event_render_frame_host_ = rfhi; | 
|  | loop_runner_->Quit(); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool AccessibilityNotificationWaiter::IsAboutBlank() { | 
|  | // Skip any accessibility notifications related to "about:blank", | 
|  | // to avoid a possible race condition between the test beginning | 
|  | // listening for accessibility events and "about:blank" loading. | 
|  | return GetAXTree().data().url == url::kAboutBlankURL; | 
|  | } | 
|  |  | 
|  | }  // namespace content |