| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2014 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 <set> |
| 6 #include <string> |
| 7 #include <vector> |
| 8 |
| 9 #include "base/command_line.h" |
| 10 #include "base/files/file_util.h" |
| 11 #include "base/logging.h" |
| 12 #include "base/strings/string16.h" |
| 13 #include "base/strings/string_split.h" |
| 14 #include "base/strings/string_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "content/browser/accessibility/accessibility_tree_formatter.h" |
| 17 #include "content/browser/accessibility/browser_accessibility.h" |
| 18 #include "content/browser/accessibility/browser_accessibility_manager.h" |
| 19 #include "content/browser/web_contents/web_contents_impl.h" |
| 20 #include "content/public/browser/web_contents.h" |
| 21 #include "content/public/common/content_paths.h" |
| 22 #include "content/public/common/content_switches.h" |
| 23 #include "content/public/common/url_constants.h" |
| 24 #include "content/public/test/content_browser_test.h" |
| 25 #include "content/public/test/content_browser_test_utils.h" |
| 26 #include "content/shell/browser/shell.h" |
| 27 #include "content/test/accessibility_browser_test_utils.h" |
| 28 #include "net/dns/mock_host_resolver.h" |
| 29 #include "testing/gtest/include/gtest/gtest.h" |
| 30 |
| 31 namespace content { |
| 32 |
| 33 namespace { |
| 34 |
| 35 bool AXTreeContainsNodeWithName(BrowserAccessibility* node, |
| 36 const std::string& name) { |
| 37 if (node->GetStringAttribute(ui::AX_ATTR_NAME) == name) |
| 38 return true; |
| 39 |
| 40 for (unsigned i = 0; i < node->PlatformChildCount(); i++) { |
| 41 if (AXTreeContainsNodeWithName(node->PlatformGetChild(i), name)) |
| 42 return true; |
| 43 } |
| 44 |
| 45 return false; |
| 46 } |
| 47 |
| 48 } // namespace |
| 49 |
| 50 class AccessibilityHitTestingBrowserTest : public ContentBrowserTest { |
| 51 public: |
| 52 AccessibilityHitTestingBrowserTest() {} |
| 53 ~AccessibilityHitTestingBrowserTest() override {} |
| 54 |
| 55 protected: |
| 56 BrowserAccessibility* HitTestAndWaitForResult(const gfx::Point& point) { |
| 57 WebContentsImpl* web_contents = |
| 58 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 59 FrameTree* frame_tree = web_contents->GetFrameTree(); |
| 60 BrowserAccessibilityManager* manager = |
| 61 web_contents->GetRootBrowserAccessibilityManager(); |
| 62 |
| 63 AccessibilityNotificationWaiter hover_waiter( |
| 64 shell(), AccessibilityModeComplete, ui::AX_EVENT_HOVER); |
| 65 for (FrameTreeNode* node : frame_tree->Nodes()) |
| 66 hover_waiter.ListenToAdditionalFrame(node->current_frame_host()); |
| 67 manager->delegate()->AccessibilityHitTest(point); |
| 68 hover_waiter.WaitForNotification(); |
| 69 |
| 70 RenderFrameHostImpl* target_frame = hover_waiter.event_render_frame_host(); |
| 71 BrowserAccessibilityManager* target_manager = |
| 72 target_frame->browser_accessibility_manager(); |
| 73 int hover_target_id = hover_waiter.event_target_id(); |
| 74 BrowserAccessibility* hovered_node = |
| 75 target_manager->GetFromID(hover_target_id); |
| 76 return hovered_node; |
| 77 } |
| 78 }; |
| 79 |
| 80 IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest, |
| 81 HitTestOutsideDocumentBoundsReturnsRoot) { |
| 82 NavigateToURL(shell(), GURL(url::kAboutBlankURL)); |
| 83 |
| 84 // Load the page. |
| 85 AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete, |
| 86 ui::AX_EVENT_LOAD_COMPLETE); |
| 87 const char url_str[] = |
| 88 "data:text/html," |
| 89 "<!doctype html>" |
| 90 "<html><head><title>Accessibility Test</title></head>" |
| 91 "<body>" |
| 92 "<a href='#'>" |
| 93 "This is some text in a link" |
| 94 "</a>" |
| 95 "</body></html>"; |
| 96 GURL url(url_str); |
| 97 NavigateToURL(shell(), url); |
| 98 waiter.WaitForNotification(); |
| 99 |
| 100 BrowserAccessibility* hovered_node = |
| 101 HitTestAndWaitForResult(gfx::Point(-1, -1)); |
| 102 ASSERT_TRUE(hovered_node != NULL); |
| 103 ASSERT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, hovered_node->GetRole()); |
| 104 } |
| 105 |
| 106 IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest, |
| 107 HitTestingInIframes) { |
| 108 host_resolver()->AddRule("*", "127.0.0.1"); |
| 109 ASSERT_TRUE(embedded_test_server()->Start()); |
| 110 |
| 111 NavigateToURL(shell(), GURL(url::kAboutBlankURL)); |
| 112 |
| 113 AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete, |
| 114 ui::AX_EVENT_LOAD_COMPLETE); |
| 115 GURL url(embedded_test_server()->GetURL( |
| 116 "/accessibility/html/iframe-coordinates.html")); |
| 117 NavigateToURL(shell(), url); |
| 118 waiter.WaitForNotification(); |
| 119 |
| 120 WebContentsImpl* web_contents = |
| 121 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 122 FrameTree* frame_tree = web_contents->GetFrameTree(); |
| 123 BrowserAccessibilityManager* manager = |
| 124 web_contents->GetRootBrowserAccessibilityManager(); |
| 125 BrowserAccessibility* root = manager->GetRoot(); |
| 126 while (!AXTreeContainsNodeWithName(root, "Ordinary Button") || |
| 127 !AXTreeContainsNodeWithName(root, "Scrolled Button")) { |
| 128 AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete, |
| 129 ui::AX_EVENT_NONE); |
| 130 for (FrameTreeNode* node : frame_tree->Nodes()) |
| 131 waiter.ListenToAdditionalFrame(node->current_frame_host()); |
| 132 waiter.WaitForNotification(); |
| 133 } |
| 134 |
| 135 // Send a series of hit test requests, and for each one |
| 136 // wait for the hover event in response, verifying we hit the |
| 137 // correct object. |
| 138 |
| 139 // (50, 50) -> "Button" |
| 140 BrowserAccessibility* hovered_node; |
| 141 hovered_node = HitTestAndWaitForResult(gfx::Point(50, 50)); |
| 142 ASSERT_TRUE(hovered_node != NULL); |
| 143 ASSERT_EQ(ui::AX_ROLE_BUTTON, hovered_node->GetRole()); |
| 144 ASSERT_EQ("Button", hovered_node->GetStringAttribute(ui::AX_ATTR_NAME)); |
| 145 |
| 146 // (50, 305) -> div in first iframe |
| 147 hovered_node = HitTestAndWaitForResult(gfx::Point(50, 305)); |
| 148 ASSERT_TRUE(hovered_node != NULL); |
| 149 ASSERT_EQ(ui::AX_ROLE_DIV, hovered_node->GetRole()); |
| 150 |
| 151 // (50, 350) -> "Ordinary Button" |
| 152 hovered_node = HitTestAndWaitForResult(gfx::Point(50, 350)); |
| 153 ASSERT_TRUE(hovered_node != NULL); |
| 154 ASSERT_EQ(ui::AX_ROLE_BUTTON, hovered_node->GetRole()); |
| 155 ASSERT_EQ("Ordinary Button", |
| 156 hovered_node->GetStringAttribute(ui::AX_ATTR_NAME)); |
| 157 |
| 158 // (50, 455) -> "Scrolled Button" |
| 159 hovered_node = HitTestAndWaitForResult(gfx::Point(50, 455)); |
| 160 ASSERT_TRUE(hovered_node != NULL); |
| 161 ASSERT_EQ(ui::AX_ROLE_BUTTON, hovered_node->GetRole()); |
| 162 ASSERT_EQ("Scrolled Button", |
| 163 hovered_node->GetStringAttribute(ui::AX_ATTR_NAME)); |
| 164 |
| 165 // (50, 505) -> div in second iframe |
| 166 hovered_node = HitTestAndWaitForResult(gfx::Point(50, 505)); |
| 167 ASSERT_TRUE(hovered_node != NULL); |
| 168 ASSERT_EQ(ui::AX_ROLE_DIV, hovered_node->GetRole()); |
| 169 } |
| 170 |
| 171 } // namespace content |
| OLD | NEW |