15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/test/accessibility_browser_test_utils.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string_util.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/utf_string_conversions.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/frame_host/render_frame_host_impl.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/renderer_host/render_widget_host_view_base.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/web_contents/web_contents_impl.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/view_message_enums.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/url_constants.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/test/test_utils.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/shell/browser/shell.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/accessibility/ax_node.h" 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content { 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochAccessibilityNotificationWaiter::AccessibilityNotificationWaiter(Shell* shell) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : event_to_wait_for_(ui::AX_EVENT_NONE), 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) loop_runner_(new MessageLoopRunner()), 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch event_target_id_(0), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_(this) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents = shell->web_contents(); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_host_ = static_cast<RenderFrameHostImpl*>( 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->GetMainFrame()); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_host_->SetAccessibilityCallbackForTesting( 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent, 33 weak_factory_.GetWeakPtr())); 34} 35 36AccessibilityNotificationWaiter::AccessibilityNotificationWaiter( 37 Shell* shell, 38 AccessibilityMode accessibility_mode, 39 ui::AXEvent event_type) 40 : event_to_wait_for_(event_type), 41 loop_runner_(new MessageLoopRunner()), 42 event_target_id_(0), 43 weak_factory_(this) { 44 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( 45 shell->web_contents()); 46 frame_host_ = static_cast<RenderFrameHostImpl*>( 47 web_contents->GetMainFrame()); 48 frame_host_->SetAccessibilityCallbackForTesting( 49 base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent, 50 weak_factory_.GetWeakPtr())); 51 web_contents->AddAccessibilityMode(accessibility_mode); 52} 53 54AccessibilityNotificationWaiter::AccessibilityNotificationWaiter( 55 RenderFrameHostImpl* frame_host, 56 ui::AXEvent event_type) 57 : frame_host_(frame_host), 58 event_to_wait_for_(event_type), 59 loop_runner_(new MessageLoopRunner()), 60 event_target_id_(0), 61 weak_factory_(this) { 62 frame_host_->SetAccessibilityCallbackForTesting( 63 base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent, 64 weak_factory_.GetWeakPtr())); 65} 66 67AccessibilityNotificationWaiter::~AccessibilityNotificationWaiter() { 68} 69 70void AccessibilityNotificationWaiter::WaitForNotification() { 71 loop_runner_->Run(); 72 73 // Each loop runner can only be called once. Create a new one in case 74 // the caller wants to call this again to wait for the next notification. 75 loop_runner_ = new MessageLoopRunner(); 76} 77 78const ui::AXTree& AccessibilityNotificationWaiter::GetAXTree() const { 79 return *frame_host_->GetAXTreeForTesting(); 80} 81 82void AccessibilityNotificationWaiter::OnAccessibilityEvent( 83 ui::AXEvent event_type, int event_target_id) { 84 if (!IsAboutBlank() && (event_to_wait_for_ == ui::AX_EVENT_NONE || 85 event_to_wait_for_ == event_type)) { 86 event_target_id_ = event_target_id; 87 loop_runner_->Quit(); 88 } 89} 90 91bool AccessibilityNotificationWaiter::IsAboutBlank() { 92 // Skip any accessibility notifications related to "about:blank", 93 // to avoid a possible race condition between the test beginning 94 // listening for accessibility events and "about:blank" loading. 95 const ui::AXNodeData& root = GetAXTree().GetRoot()->data(); 96 for (size_t i = 0; i < root.string_attributes.size(); ++i) { 97 if (root.string_attributes[i].first != ui::AX_ATTR_DOC_URL) 98 continue; 99 const std::string& doc_url = root.string_attributes[i].second; 100 return doc_url == url::kAboutBlankURL; 101 } 102 return false; 103} 104 105} // namespace content 106