1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file.
4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <string>
6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <vector>
7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/utf_string_conversions.h"
94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h"
11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/render_messages.h"
12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/test/in_process_browser_test.h"
13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/test/ui_test_utils.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_widget_host.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_widget_host_view.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h"
19bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
20bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(OS_WIN)
21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <atlbase.h>
22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <atlcom.h>
23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenusing webkit_glue::WebAccessibility;
26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace {
28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass RendererAccessibilityBrowserTest : public InProcessBrowserTest {
30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen public:
31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  RendererAccessibilityBrowserTest() {}
32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Tell the renderer to send an accessibility tree, then wait for the
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // notification that it's been received.
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const WebAccessibility& GetWebAccessibilityTree() {
36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    RenderWidgetHostView* host_view =
37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        browser()->GetSelectedTabContents()->GetRenderWidgetHostView();
38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    RenderWidgetHost* host = host_view->GetRenderWidgetHost();
39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    RenderViewHost* view_host = static_cast<RenderViewHost*>(host);
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    view_host->set_save_accessibility_tree_for_testing(true);
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    view_host->EnableRendererAccessibility();
42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ui_test_utils::WaitForNotification(
43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED);
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return view_host->accessibility_tree();
45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Make sure each node in the tree has an unique id.
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void RecursiveAssertUniqueIds(
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const WebAccessibility& node, base::hash_set<int>* ids) {
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ASSERT_TRUE(ids->find(node.id) == ids->end());
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ids->insert(node.id);
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (size_t i = 0; i < node.children.size(); i++)
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      RecursiveAssertUniqueIds(node.children[i], ids);
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
56bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // InProcessBrowserTest
57bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  void SetUpInProcessBrowserTestFixture();
58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  void TearDownInProcessBrowserTestFixture();
59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen protected:
61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::string GetAttr(const WebAccessibility& node,
62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                      const WebAccessibility::Attribute attr);
63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid RendererAccessibilityBrowserTest::SetUpInProcessBrowserTestFixture() {
66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(OS_WIN)
67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // ATL needs a pointer to a COM module.
68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  static CComModule module;
69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  _pAtlModule = &module;
70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Make sure COM is initialized for this thread; it's safe to call twice.
72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ::CoInitialize(NULL);
73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid RendererAccessibilityBrowserTest::TearDownInProcessBrowserTestFixture() {
77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(OS_WIN)
78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ::CoUninitialize();
79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
82bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Convenience method to get the value of a particular WebAccessibility
83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// node attribute as a UTF-8 const char*.
84bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenstd::string RendererAccessibilityBrowserTest::GetAttr(
85bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    const WebAccessibility& node, const WebAccessibility::Attribute attr) {
86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  std::map<int32, string16>::const_iterator iter = node.attributes.find(attr);
87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (iter != node.attributes.end())
88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return UTF16ToUTF8(iter->second);
89bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  else
90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return "";
91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenIN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                       CrossPlatformWebpageAccessibility) {
95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Create a data url and load it.
96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  const char url_str[] =
97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "data:text/html,"
98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "<!doctype html>"
99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "<html><head><title>Accessibility Test</title></head>"
100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "<body><input type='button' value='push' /><input type='checkbox' />"
101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "</body></html>";
102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  GURL url(url_str);
103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const WebAccessibility& tree = GetWebAccessibilityTree();
105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Check properties of the root element of the tree.
107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(url_str, GetAttr(tree, WebAccessibility::ATTR_DOC_URL).c_str());
108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "Accessibility Test",
110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      GetAttr(tree, WebAccessibility::ATTR_DOC_TITLE).c_str());
111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "html", GetAttr(tree, WebAccessibility::ATTR_DOC_DOCTYPE).c_str());
113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "text/html", GetAttr(tree, WebAccessibility::ATTR_DOC_MIMETYPE).c_str());
115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ("Accessibility Test", UTF16ToUTF8(tree.name).c_str());
116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_WEB_AREA, tree.role);
117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Check properites of the BODY element.
119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ASSERT_EQ(1U, tree.children.size());
120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  const WebAccessibility& body = tree.children[0];
121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_GROUP, body.role);
122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ("body", GetAttr(body, WebAccessibility::ATTR_HTML_TAG).c_str());
123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ("block", GetAttr(body, WebAccessibility::ATTR_DISPLAY).c_str());
124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Check properties of the two children of the BODY element.
126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ASSERT_EQ(2U, body.children.size());
127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  const WebAccessibility& button = body.children[0];
129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_BUTTON, button.role);
130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "input", GetAttr(button, WebAccessibility::ATTR_HTML_TAG).c_str());
132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ("push", UTF16ToUTF8(button.name).c_str());
133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "inline-block", GetAttr(button, WebAccessibility::ATTR_DISPLAY).c_str());
135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ASSERT_EQ(2U, button.html_attributes.size());
136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ("type", UTF16ToUTF8(button.html_attributes[0].first).c_str());
137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ("button", UTF16ToUTF8(button.html_attributes[0].second).c_str());
138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ("value", UTF16ToUTF8(button.html_attributes[1].first).c_str());
139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ("push", UTF16ToUTF8(button.html_attributes[1].second).c_str());
140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  const WebAccessibility& checkbox = body.children[1];
142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_CHECKBOX, checkbox.role);
143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "input", GetAttr(checkbox, WebAccessibility::ATTR_HTML_TAG).c_str());
145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "inline-block",
147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      GetAttr(checkbox, WebAccessibility::ATTR_DISPLAY).c_str());
148bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ASSERT_EQ(1U, checkbox.html_attributes.size());
149bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
150bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      "type", UTF16ToUTF8(checkbox.html_attributes[0].first).c_str());
151bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  EXPECT_STREQ(
152bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    "checkbox", UTF16ToUTF8(checkbox.html_attributes[0].second).c_str());
153bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
154bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
155731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickIN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                       CrossPlatformUnselectedEditableTextAccessibility) {
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Create a data url and load it.
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const char url_str[] =
159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "data:text/html,"
160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "<!doctype html>"
161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "<body>"
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "<input value=\"Hello, world.\"/>"
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "</body></html>";
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  GURL url(url_str);
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const WebAccessibility& tree = GetWebAccessibilityTree();
168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ASSERT_EQ(1U, tree.children.size());
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const WebAccessibility& body = tree.children[0];
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ASSERT_EQ(1U, body.children.size());
171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const WebAccessibility& text = body.children[0];
172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, text.role);
173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_STREQ(
174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "input", GetAttr(text, WebAccessibility::ATTR_HTML_TAG).c_str());
175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_STREQ(
176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "0", GetAttr(text, WebAccessibility::ATTR_TEXT_SEL_START).c_str());
177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_STREQ(
178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "0", GetAttr(text, WebAccessibility::ATTR_TEXT_SEL_END).c_str());
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str());
180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(dmazzoni): as soon as more accessibility code is cross-platform,
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // this code should test that the accessible info is dynamically updated
183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // if the selection or value changes.
184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
186731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickIN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                       CrossPlatformSelectedEditableTextAccessibility) {
188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Create a data url and load it.
189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const char url_str[] =
190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "data:text/html,"
191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "<!doctype html>"
192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "<body onload=\"document.body.children[0].select();\">"
193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "<input value=\"Hello, world.\"/>"
194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "</body></html>";
195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  GURL url(url_str);
196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const WebAccessibility& tree = GetWebAccessibilityTree();
199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ASSERT_EQ(1U, tree.children.size());
200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const WebAccessibility& body = tree.children[0];
201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ASSERT_EQ(1U, body.children.size());
202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const WebAccessibility& text = body.children[0];
203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, text.role);
204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_STREQ(
205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "input", GetAttr(text, WebAccessibility::ATTR_HTML_TAG).c_str());
206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_STREQ(
207731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "0", GetAttr(text, WebAccessibility::ATTR_TEXT_SEL_START).c_str());
208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_STREQ(
209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      "13", GetAttr(text, WebAccessibility::ATTR_TEXT_SEL_END).c_str());
210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str());
211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenIN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       CrossPlatformMultipleInheritanceAccessibility) {
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // In a WebKit accessibility render tree for a table, each cell is a
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // child of both a row and a column, so it appears to use multiple
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // inheritance. Make sure that the WebAccessibilityObject tree only
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // keeps one copy of each cell, and uses an indirect child id for the
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // additional reference to it.
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const char url_str[] =
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "data:text/html,"
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<!doctype html>"
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<table border=1><tr><td>1</td><td>2</td></tr></table>";
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL url(url_str);
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& tree = GetWebAccessibilityTree();
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_EQ(1U, tree.children.size());
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& table = tree.children[0];
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_TABLE, table.role);
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& row = table.children[0];
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_ROW, row.role);
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& cell1 = row.children[0];
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_CELL, cell1.role);
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& cell2 = row.children[1];
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_CELL, cell2.role);
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& column1 = table.children[1];
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_COLUMN, column1.role);
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(0U, column1.children.size());
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(1U, column1.indirect_child_ids.size());
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(cell1.id, column1.indirect_child_ids[0]);
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& column2 = table.children[2];
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_COLUMN, column2.role);
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(0U, column2.children.size());
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(1U, column2.indirect_child_ids.size());
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(cell2.id, column2.indirect_child_ids[0]);
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenIN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       CrossPlatformMultipleInheritanceAccessibility2) {
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Here's another html snippet where WebKit puts the same node as a child
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // of two different parents. Instead of checking the exact output, just
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // make sure that no id is reused in the resulting tree.
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const char url_str[] =
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "data:text/html,"
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<!doctype html>"
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<script>\n"
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "  document.writeln('<q><section></section></q><q><li>');\n"
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "  setTimeout(function() {\n"
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "    document.close();\n"
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "  }, 1);\n"
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "</script>";
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL url(url_str);
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& tree = GetWebAccessibilityTree();
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::hash_set<int> ids;
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RecursiveAssertUniqueIds(tree, &ids);
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenIN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       CrossPlatformIframeAccessibility) {
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Create a data url and load it.
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const char url_str[] =
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "data:text/html,"
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<!doctype html><html><body>"
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<button>Button 1</button>"
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<iframe src='data:text/html,"
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<!doctype html><html><body><button>Button 2</button></body></html>"
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "'></iframe>"
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<button>Button 3</button>"
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "</body></html>";
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL url(url_str);
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& tree = GetWebAccessibilityTree();
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_EQ(1U, tree.children.size());
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& body = tree.children[0];
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_EQ(3U, body.children.size());
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& button1 = body.children[0];
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_BUTTON, button1.role);
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_STREQ("Button 1", UTF16ToUTF8(button1.name).c_str());
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& iframe = body.children[1];
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_STREQ("iframe",
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               GetAttr(iframe, WebAccessibility::ATTR_HTML_TAG).c_str());
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_EQ(1U, iframe.children.size());
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& scroll_area = iframe.children[0];
301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_SCROLLAREA, scroll_area.role);
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_EQ(1U, scroll_area.children.size());
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& sub_document = scroll_area.children[0];
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_WEB_AREA, sub_document.role);
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_EQ(1U, sub_document.children.size());
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& sub_body = sub_document.children[0];
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ASSERT_EQ(1U, sub_body.children.size());
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& button2 = sub_body.children[0];
312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_BUTTON, button2.role);
313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_STREQ("Button 2", UTF16ToUTF8(button2.name).c_str());
314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& button3 = body.children[2];
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_EQ(WebAccessibility::ROLE_BUTTON, button3.role);
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_STREQ("Button 3", UTF16ToUTF8(button3.name).c_str());
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenIN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       CrossPlatformDuplicateChildrenAccessibility) {
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Here's another html snippet where WebKit has a parent node containing
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // two duplicate child nodes. Instead of checking the exact output, just
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // make sure that no id is reused in the resulting tree.
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const char url_str[] =
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "data:text/html,"
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<!doctype html>"
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "<em><code ><h4 ></em>";
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL url(url_str);
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const WebAccessibility& tree = GetWebAccessibilityTree();
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::hash_set<int> ids;
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RecursiveAssertUniqueIds(tree, &ids);
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
337bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}  // namespace
338