1 // Copyright 2013 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 #include "content/test/accessibility_browser_test_utils.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "content/browser/frame_host/render_frame_host_impl.h" 12 #include "content/browser/renderer_host/render_widget_host_view_base.h" 13 #include "content/browser/web_contents/web_contents_impl.h" 14 #include "content/common/view_message_enums.h" 15 #include "content/public/browser/web_contents.h" 16 #include "content/public/common/url_constants.h" 17 #include "content/public/test/test_utils.h" 18 #include "content/shell/browser/shell.h" 19 #include "ui/accessibility/ax_node.h" 20 21 namespace content { 22 23 AccessibilityNotificationWaiter::AccessibilityNotificationWaiter(Shell* shell) 24 : event_to_wait_for_(ui::AX_EVENT_NONE), 25 loop_runner_(new MessageLoopRunner()), 26 event_target_id_(0), 27 weak_factory_(this) { 28 WebContents* web_contents = shell->web_contents(); 29 frame_host_ = static_cast<RenderFrameHostImpl*>( 30 web_contents->GetMainFrame()); 31 frame_host_->SetAccessibilityCallbackForTesting( 32 base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent, 33 weak_factory_.GetWeakPtr())); 34 } 35 36 AccessibilityNotificationWaiter::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 54 AccessibilityNotificationWaiter::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 67 AccessibilityNotificationWaiter::~AccessibilityNotificationWaiter() { 68 } 69 70 void 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 78 const ui::AXTree& AccessibilityNotificationWaiter::GetAXTree() const { 79 return *frame_host_->GetAXTreeForTesting(); 80 } 81 82 void 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 91 bool 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