OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <atlbase.h> | 5 #include <atlbase.h> |
6 #include <vector> | 6 #include <vector> |
7 | 7 |
8 #include "base/scoped_comptr_win.h" | 8 #include "base/scoped_comptr_win.h" |
9 #include "chrome/browser/browser.h" | 9 #include "chrome/browser/browser.h" |
10 #include "chrome/browser/browser_window.h" | 10 #include "chrome/browser/browser_window.h" |
11 #include "chrome/browser/renderer_host/render_widget_host_view_win.h" | 11 #include "chrome/browser/renderer_host/render_widget_host_view_win.h" |
12 #include "chrome/browser/tab_contents/tab_contents.h" | 12 #include "chrome/browser/tab_contents/tab_contents.h" |
13 #include "chrome/common/chrome_switches.h" | 13 #include "chrome/common/chrome_switches.h" |
14 #include "chrome/common/notification_type.h" | 14 #include "chrome/common/notification_type.h" |
15 #include "chrome/test/in_process_browser_test.h" | 15 #include "chrome/test/in_process_browser_test.h" |
16 #include "chrome/test/ui_test_utils.h" | 16 #include "chrome/test/ui_test_utils.h" |
17 | 17 |
| 18 using std::auto_ptr; |
| 19 using std::vector; |
| 20 using std::wstring; |
| 21 |
18 namespace { | 22 namespace { |
19 | 23 |
20 class AccessibilityWinBrowserTest : public InProcessBrowserTest { | 24 class AccessibilityWinBrowserTest : public InProcessBrowserTest { |
21 public: | 25 public: |
22 AccessibilityWinBrowserTest() : screenreader_running_(FALSE) {} | 26 AccessibilityWinBrowserTest() : screenreader_running_(FALSE) {} |
23 | 27 |
24 // InProcessBrowserTest | 28 // InProcessBrowserTest |
25 void SetUpInProcessBrowserTestFixture(); | 29 void SetUpInProcessBrowserTestFixture(); |
26 void TearDownInProcessBrowserTestFixture(); | 30 void TearDownInProcessBrowserTestFixture(); |
27 | 31 |
(...skipping 22 matching lines...) Expand all Loading... |
50 // Restore the SPI_SETSCREENREADER flag and notify active applications about | 54 // Restore the SPI_SETSCREENREADER flag and notify active applications about |
51 // the setting change. | 55 // the setting change. |
52 ::SystemParametersInfo(SPI_SETSCREENREADER, TRUE, NULL, 0); | 56 ::SystemParametersInfo(SPI_SETSCREENREADER, TRUE, NULL, 0); |
53 ::SendNotifyMessage( | 57 ::SendNotifyMessage( |
54 HWND_BROADCAST, WM_SETTINGCHANGE, SPI_GETSCREENREADER, 0); | 58 HWND_BROADCAST, WM_SETTINGCHANGE, SPI_GETSCREENREADER, 0); |
55 } | 59 } |
56 } | 60 } |
57 | 61 |
58 class AccessibleChecker { | 62 class AccessibleChecker { |
59 public: | 63 public: |
60 AccessibleChecker(std::wstring expected_name, int32 expected_role); | 64 AccessibleChecker( |
61 AccessibleChecker(std::wstring expected_name, std::wstring expected_role); | 65 wstring expected_name, |
| 66 int32 expected_role, |
| 67 wstring expected_value); |
| 68 AccessibleChecker( |
| 69 wstring expected_name, |
| 70 wstring expected_role, |
| 71 wstring expected_value); |
62 | 72 |
63 // Append an AccessibleChecker that verifies accessibility information for | 73 // Append an AccessibleChecker that verifies accessibility information for |
64 // a child IAccessible. Order is important. | 74 // a child IAccessible. Order is important. |
65 void AppendExpectedChild(AccessibleChecker* expected_child); | 75 void AppendExpectedChild(AccessibleChecker* expected_child); |
66 | 76 |
67 // Check that the name and role of the given IAccessible instance and its | 77 // Check that the name and role of the given IAccessible instance and its |
68 // descendants match the expected names and roles that this object was | 78 // descendants match the expected names and roles that this object was |
69 // initialized with. | 79 // initialized with. |
70 void CheckAccessible(IAccessible* accessible); | 80 void CheckAccessible(IAccessible* accessible); |
71 | 81 |
72 typedef std::vector<AccessibleChecker*> AccessibleCheckerVector; | 82 // Set the expected value for this AccessibleChecker. |
| 83 void SetExpectedValue(wstring expected_value); |
73 | 84 |
74 private: | 85 private: |
75 void CheckAccessibleName(IAccessible* accessible); | 86 void CheckAccessibleName(IAccessible* accessible); |
76 void CheckAccessibleRole(IAccessible* accessible); | 87 void CheckAccessibleRole(IAccessible* accessible); |
| 88 void CheckAccessibleValue(IAccessible* accessible); |
77 void CheckAccessibleChildren(IAccessible* accessible); | 89 void CheckAccessibleChildren(IAccessible* accessible); |
78 | 90 |
79 private: | 91 private: |
| 92 typedef vector<AccessibleChecker*> AccessibleCheckerVector; |
| 93 |
80 // Expected accessible name. Checked against IAccessible::get_accName. | 94 // Expected accessible name. Checked against IAccessible::get_accName. |
81 std::wstring name_; | 95 wstring name_; |
82 | 96 |
83 // Expected accessible role. Checked against IAccessible::get_accRole. | 97 // Expected accessible role. Checked against IAccessible::get_accRole. |
84 CComVariant role_; | 98 CComVariant role_; |
85 | 99 |
| 100 // Expected accessible value. Checked against IAccessible::get_accValue. |
| 101 wstring value_; |
| 102 |
86 // Expected accessible children. Checked using IAccessible::get_accChildCount | 103 // Expected accessible children. Checked using IAccessible::get_accChildCount |
87 // and ::AccessibleChildren. | 104 // and ::AccessibleChildren. |
88 AccessibleCheckerVector children_; | 105 AccessibleCheckerVector children_; |
89 }; | 106 }; |
90 | 107 |
91 VARIANT CreateI4Variant(LONG value) { | 108 VARIANT CreateI4Variant(LONG value) { |
92 VARIANT variant = {0}; | 109 VARIANT variant = {0}; |
93 | 110 |
94 V_VT(&variant) = VT_I4; | 111 V_VT(&variant) = VT_I4; |
95 V_I4(&variant) = value; | 112 V_I4(&variant) = value; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 HRESULT hr = AccessibleObjectFromWindow( | 144 HRESULT hr = AccessibleObjectFromWindow( |
128 hwnd_render_widget_host_view, OBJID_CLIENT, | 145 hwnd_render_widget_host_view, OBJID_CLIENT, |
129 IID_IAccessible, reinterpret_cast<void**>(&accessible)); | 146 IID_IAccessible, reinterpret_cast<void**>(&accessible)); |
130 EXPECT_EQ(S_OK, hr); | 147 EXPECT_EQ(S_OK, hr); |
131 EXPECT_NE(accessible, reinterpret_cast<IAccessible*>(NULL)); | 148 EXPECT_NE(accessible, reinterpret_cast<IAccessible*>(NULL)); |
132 | 149 |
133 return accessible; | 150 return accessible; |
134 } | 151 } |
135 | 152 |
136 AccessibleChecker::AccessibleChecker( | 153 AccessibleChecker::AccessibleChecker( |
137 std::wstring expected_name, int32 expected_role) : | 154 wstring expected_name, int32 expected_role, wstring expected_value) : |
138 name_(expected_name), | 155 name_(expected_name), |
139 role_(expected_role) { | 156 role_(expected_role), |
| 157 value_(expected_value) { |
140 } | 158 } |
141 | 159 |
142 AccessibleChecker::AccessibleChecker( | 160 AccessibleChecker::AccessibleChecker( |
143 std::wstring expected_name, std::wstring expected_role) : | 161 wstring expected_name, wstring expected_role, wstring expected_value) : |
144 name_(expected_name), | 162 name_(expected_name), |
145 role_(expected_role.c_str()) { | 163 role_(expected_role.c_str()), |
| 164 value_(expected_value) { |
146 } | 165 } |
147 | 166 |
148 void AccessibleChecker::AppendExpectedChild( | 167 void AccessibleChecker::AppendExpectedChild( |
149 AccessibleChecker* expected_child) { | 168 AccessibleChecker* expected_child) { |
150 children_.push_back(expected_child); | 169 children_.push_back(expected_child); |
151 } | 170 } |
152 | 171 |
153 void AccessibleChecker::CheckAccessible(IAccessible* accessible) { | 172 void AccessibleChecker::CheckAccessible(IAccessible* accessible) { |
154 CheckAccessibleName(accessible); | 173 CheckAccessibleName(accessible); |
155 CheckAccessibleRole(accessible); | 174 CheckAccessibleRole(accessible); |
| 175 CheckAccessibleValue(accessible); |
156 CheckAccessibleChildren(accessible); | 176 CheckAccessibleChildren(accessible); |
157 } | 177 } |
158 | 178 |
| 179 void AccessibleChecker::SetExpectedValue(wstring expected_value) { |
| 180 value_ = expected_value; |
| 181 } |
| 182 |
159 void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) { | 183 void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) { |
160 CComBSTR name; | 184 CComBSTR name; |
161 HRESULT hr = | 185 HRESULT hr = |
162 accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name); | 186 accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name); |
163 | 187 |
164 if (name_.empty()) { | 188 if (name_.empty()) { |
165 // If the object doesn't have name S_FALSE should be returned. | 189 // If the object doesn't have name S_FALSE should be returned. |
166 EXPECT_EQ(hr, S_FALSE); | 190 EXPECT_EQ(hr, S_FALSE); |
167 } else { | 191 } else { |
168 // Test that the correct string was returned. | 192 // Test that the correct string was returned. |
169 EXPECT_EQ(hr, S_OK); | 193 EXPECT_EQ(hr, S_OK); |
170 EXPECT_EQ(CompareString(LOCALE_NEUTRAL, 0, name, SysStringLen(name), | 194 EXPECT_STREQ(name_.c_str(), |
171 name_.c_str(), name_.length()), | 195 wstring(name.m_str, SysStringLen(name)).c_str()); |
172 CSTR_EQUAL); | |
173 } | 196 } |
174 } | 197 } |
175 | 198 |
176 void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) { | 199 void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) { |
177 VARIANT var_role = {0}; | 200 VARIANT var_role = {0}; |
178 HRESULT hr = | 201 HRESULT hr = |
179 accessible->get_accRole(CreateI4Variant(CHILDID_SELF), &var_role); | 202 accessible->get_accRole(CreateI4Variant(CHILDID_SELF), &var_role); |
180 EXPECT_EQ(hr, S_OK); | 203 EXPECT_EQ(hr, S_OK); |
181 ASSERT_TRUE(role_ == var_role); | 204 ASSERT_TRUE(role_ == var_role); |
182 } | 205 } |
183 | 206 |
| 207 void AccessibleChecker::CheckAccessibleValue(IAccessible* accessible) { |
| 208 CComBSTR value; |
| 209 HRESULT hr = |
| 210 accessible->get_accValue(CreateI4Variant(CHILDID_SELF), &value); |
| 211 EXPECT_EQ(hr, S_OK); |
| 212 |
| 213 // Test that the correct string was returned. |
| 214 EXPECT_STREQ(value_.c_str(), |
| 215 wstring(value.m_str, SysStringLen(value)).c_str()); |
| 216 } |
| 217 |
184 void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) { | 218 void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) { |
185 LONG child_count = 0; | 219 LONG child_count = 0; |
186 HRESULT hr = parent->get_accChildCount(&child_count); | 220 HRESULT hr = parent->get_accChildCount(&child_count); |
187 EXPECT_EQ(hr, S_OK); | 221 EXPECT_EQ(hr, S_OK); |
188 ASSERT_EQ(child_count, children_.size()); | 222 ASSERT_EQ(child_count, children_.size()); |
189 | 223 |
190 std::auto_ptr<VARIANT> child_array(new VARIANT[child_count]); | 224 auto_ptr<VARIANT> child_array(new VARIANT[child_count]); |
191 LONG obtained_count = 0; | 225 LONG obtained_count = 0; |
192 hr = AccessibleChildren(parent, 0, child_count, | 226 hr = AccessibleChildren(parent, 0, child_count, |
193 child_array.get(), &obtained_count); | 227 child_array.get(), &obtained_count); |
194 ASSERT_EQ(hr, S_OK); | 228 ASSERT_EQ(hr, S_OK); |
195 ASSERT_EQ(child_count, obtained_count); | 229 ASSERT_EQ(child_count, obtained_count); |
196 | 230 |
197 VARIANT* child = child_array.get(); | 231 VARIANT* child = child_array.get(); |
198 for (AccessibleCheckerVector::iterator child_checker = children_.begin(); | 232 for (AccessibleCheckerVector::iterator child_checker = children_.begin(); |
199 child_checker != children_.end(); | 233 child_checker != children_.end(); |
200 ++child_checker, ++child) { | 234 ++child_checker, ++child) { |
(...skipping 27 matching lines...) Expand all Loading... |
228 "data:text/html,<html><head><title>Accessibility Win Test</title></head>" | 262 "data:text/html,<html><head><title>Accessibility Win Test</title></head>" |
229 "<body><input type='button' value='push' /><input type='checkbox' />" | 263 "<body><input type='button' value='push' /><input type='checkbox' />" |
230 "</body></html>"); | 264 "</body></html>"); |
231 browser()->OpenURL(tree_url, GURL(), CURRENT_TAB, PageTransition::TYPED); | 265 browser()->OpenURL(tree_url, GURL(), CURRENT_TAB, PageTransition::TYPED); |
232 ui_test_utils::WaitForNotification( | 266 ui_test_utils::WaitForNotification( |
233 NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED); | 267 NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED); |
234 | 268 |
235 document_accessible = GetRenderWidgetHostViewClientAccessible(); | 269 document_accessible = GetRenderWidgetHostViewClientAccessible(); |
236 ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL)); | 270 ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL)); |
237 | 271 |
238 AccessibleChecker button_checker(L"push", ROLE_SYSTEM_PUSHBUTTON); | 272 AccessibleChecker button_checker(L"push", ROLE_SYSTEM_PUSHBUTTON, L"push"); |
239 AccessibleChecker checkbox_checker(L"", ROLE_SYSTEM_CHECKBUTTON); | 273 AccessibleChecker checkbox_checker(L"", ROLE_SYSTEM_CHECKBUTTON, L""); |
240 | 274 |
241 AccessibleChecker grouping_checker(L"", L"div"); | 275 AccessibleChecker grouping_checker(L"", L"div", L""); |
242 grouping_checker.AppendExpectedChild(&button_checker); | 276 grouping_checker.AppendExpectedChild(&button_checker); |
243 grouping_checker.AppendExpectedChild(&checkbox_checker); | 277 grouping_checker.AppendExpectedChild(&checkbox_checker); |
244 | 278 |
245 AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT); | 279 AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L""); |
246 document_checker.AppendExpectedChild(&grouping_checker); | 280 document_checker.AppendExpectedChild(&grouping_checker); |
247 | 281 |
248 // Check the accessible tree of the renderer. | 282 // Check the accessible tree of the renderer. |
249 document_checker.CheckAccessible(document_accessible); | 283 document_checker.CheckAccessible(document_accessible); |
250 | 284 |
251 // Check that document accessible has a parent accessible. | 285 // Check that document accessible has a parent accessible. |
252 ScopedComPtr<IDispatch> parent_dispatch; | 286 ScopedComPtr<IDispatch> parent_dispatch; |
253 hr = document_accessible->get_accParent(parent_dispatch.Receive()); | 287 hr = document_accessible->get_accParent(parent_dispatch.Receive()); |
254 EXPECT_EQ(hr, S_OK); | 288 EXPECT_EQ(hr, S_OK); |
255 EXPECT_NE(parent_dispatch, reinterpret_cast<IDispatch*>(NULL)); | 289 EXPECT_NE(parent_dispatch, reinterpret_cast<IDispatch*>(NULL)); |
256 | 290 |
257 // Navigate to another page. | 291 // Navigate to another page. |
258 GURL about_url("about:"); | 292 GURL about_url("about:"); |
259 ui_test_utils::NavigateToURL(browser(), about_url); | 293 ui_test_utils::NavigateToURL(browser(), about_url); |
260 | 294 |
261 // Verify that the IAccessible reference still points to a valid object and | 295 // Verify that the IAccessible reference still points to a valid object and |
262 // that calls to its methods fail since the tree is no longer valid after | 296 // that calls to its methods fail since the tree is no longer valid after |
263 // the page navagation. | 297 // the page navagation. |
264 // Todo(ctguil): Currently this is giving a false positive because E_FAIL is | |
265 // returned when BrowserAccessibilityManager::RequestAccessibilityInfo fails | |
266 // since the previous render view host connection is lost. Verify that | |
267 // instances are actually marked as invalid once the browse side cache is | |
268 // checked in. | |
269 CComBSTR name; | 298 CComBSTR name; |
270 hr = document_accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name); | 299 hr = document_accessible->get_accName(CreateI4Variant(CHILDID_SELF), &name); |
271 ASSERT_EQ(E_FAIL, hr); | 300 ASSERT_EQ(E_FAIL, hr); |
272 } | 301 } |
| 302 |
| 303 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 304 TestDynamicAccessibilityTree) { |
| 305 // By requesting an accessible chrome will believe a screen reader has been |
| 306 // detected. Request and wait for the accessibility tree to be updated. |
| 307 GURL tree_url( |
| 308 "data:text/html,<html><body><div onclick=\"this.innerHTML='<b>new text" |
| 309 "</b>';\"><b>old text</b></div></body></html>"); |
| 310 ScopedComPtr<IAccessible> document_accessible( |
| 311 GetRenderWidgetHostViewClientAccessible()); |
| 312 browser()->OpenURL(tree_url, GURL(), CURRENT_TAB, PageTransition::TYPED); |
| 313 ui_test_utils::WaitForNotification( |
| 314 NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED); |
| 315 |
| 316 AccessibleChecker text_checker(L"", ROLE_SYSTEM_TEXT, L"old text"); |
| 317 AccessibleChecker checkbox_checker(L"", ROLE_SYSTEM_CHECKBUTTON, L""); |
| 318 |
| 319 AccessibleChecker div_checker(L"", L"div", L""); |
| 320 div_checker.AppendExpectedChild(&text_checker); |
| 321 |
| 322 AccessibleChecker document_checker(L"", ROLE_SYSTEM_DOCUMENT, L""); |
| 323 document_checker.AppendExpectedChild(&div_checker); |
| 324 |
| 325 // Check the accessible tree of the browser. |
| 326 document_accessible = GetRenderWidgetHostViewClientAccessible(); |
| 327 ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL)); |
| 328 document_checker.CheckAccessible(document_accessible); |
| 329 |
| 330 // Perform the default action on the div which executes the script that |
| 331 // updates text node within the div. |
| 332 CComPtr<IDispatch> div_dispatch; |
| 333 HRESULT hr = document_accessible->get_accChild(CreateI4Variant(1), |
| 334 &div_dispatch); |
| 335 EXPECT_EQ(hr, S_OK); |
| 336 CComQIPtr<IAccessible> div_accessible(div_dispatch); |
| 337 hr = div_accessible->accDoDefaultAction(CreateI4Variant(CHILDID_SELF)); |
| 338 EXPECT_EQ(hr, S_OK); |
| 339 ui_test_utils::WaitForNotification( |
| 340 NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED); |
| 341 |
| 342 // Check that the accessibility tree of the browser has been updated. |
| 343 text_checker.SetExpectedValue(L"new text"); |
| 344 document_checker.CheckAccessible(document_accessible); |
| 345 } |
273 } // namespace. | 346 } // namespace. |
OLD | NEW |