Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / accessibility / accessibility_win_browsertest.cc
blob6e8ba536de059d315d9afd9a423ac5c4da7dd905
1 // Copyright (c) 2012 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.
5 #include <vector>
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/win/scoped_bstr.h"
10 #include "base/win/scoped_comptr.h"
11 #include "base/win/scoped_variant.h"
12 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/public/browser/notification_service.h"
15 #include "content/public/browser/notification_types.h"
16 #include "content/public/browser/render_frame_host.h"
17 #include "content/public/browser/render_widget_host_view.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/url_constants.h"
20 #include "content/public/test/content_browser_test.h"
21 #include "content/public/test/content_browser_test_utils.h"
22 #include "content/shell/browser/shell.h"
23 #include "content/test/accessibility_browser_test_utils.h"
24 #include "third_party/iaccessible2/ia2_api_all.h"
25 #include "third_party/isimpledom/ISimpleDOMNode.h"
26 #include "ui/aura/window.h"
27 #include "ui/aura/window_tree_host.h"
29 namespace content {
31 namespace {
33 // Helpers --------------------------------------------------------------------
35 base::win::ScopedComPtr<IAccessible> GetAccessibleFromResultVariant(
36 IAccessible* parent,
37 VARIANT* var) {
38 base::win::ScopedComPtr<IAccessible> ptr;
39 switch (V_VT(var)) {
40 case VT_DISPATCH: {
41 IDispatch* dispatch = V_DISPATCH(var);
42 if (dispatch)
43 ptr.QueryFrom(dispatch);
44 break;
47 case VT_I4: {
48 base::win::ScopedComPtr<IDispatch> dispatch;
49 HRESULT hr = parent->get_accChild(*var, dispatch.Receive());
50 EXPECT_TRUE(SUCCEEDED(hr));
51 if (dispatch)
52 dispatch.QueryInterface(ptr.Receive());
53 break;
56 return ptr;
59 HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) {
60 // TODO(ctguil): For some reason querying the IAccessible2 interface from
61 // IAccessible fails.
62 base::win::ScopedComPtr<IServiceProvider> service_provider;
63 HRESULT hr = accessible->QueryInterface(service_provider.Receive());
64 return SUCCEEDED(hr) ?
65 service_provider->QueryService(IID_IAccessible2, accessible2) : hr;
68 // Recursively search through all of the descendants reachable from an
69 // IAccessible node and return true if we find one with the given role
70 // and name.
71 void RecursiveFindNodeInAccessibilityTree(IAccessible* node,
72 int32 expected_role,
73 const std::wstring& expected_name,
74 int32 depth,
75 bool* found) {
76 base::win::ScopedBstr name_bstr;
77 base::win::ScopedVariant childid_self(CHILDID_SELF);
78 node->get_accName(childid_self, name_bstr.Receive());
79 std::wstring name(name_bstr, name_bstr.Length());
80 base::win::ScopedVariant role;
81 node->get_accRole(childid_self, role.Receive());
82 ASSERT_EQ(VT_I4, role.type());
84 // Print the accessibility tree as we go, because if this test fails
85 // on the bots, this is really helpful in figuring out why.
86 for (int i = 0; i < depth; i++)
87 printf(" ");
88 printf("role=%s name=%s\n",
89 base::WideToUTF8(IAccessibleRoleToString(V_I4(&role))).c_str(),
90 base::WideToUTF8(name).c_str());
92 if (expected_role == V_I4(&role) && expected_name == name) {
93 *found = true;
94 return;
97 LONG child_count = 0;
98 HRESULT hr = node->get_accChildCount(&child_count);
99 ASSERT_EQ(S_OK, hr);
101 scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]);
102 LONG obtained_count = 0;
103 hr = AccessibleChildren(
104 node, 0, child_count, child_array.get(), &obtained_count);
105 ASSERT_EQ(S_OK, hr);
106 ASSERT_EQ(child_count, obtained_count);
108 for (int index = 0; index < obtained_count; index++) {
109 base::win::ScopedComPtr<IAccessible> child_accessible(
110 GetAccessibleFromResultVariant(node, &child_array.get()[index]));
111 if (child_accessible) {
112 RecursiveFindNodeInAccessibilityTree(
113 child_accessible.get(), expected_role, expected_name, depth + 1,
114 found);
115 if (*found)
116 return;
122 // AccessibilityWinBrowserTest ------------------------------------------------
124 class AccessibilityWinBrowserTest : public ContentBrowserTest {
125 public:
126 AccessibilityWinBrowserTest();
127 virtual ~AccessibilityWinBrowserTest();
129 protected:
130 void LoadInitialAccessibilityTreeFromHtml(const std::string& html);
131 IAccessible* GetRendererAccessible();
132 void ExecuteScript(const std::wstring& script);
134 private:
135 DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest);
138 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() {
141 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() {
144 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml(
145 const std::string& html) {
146 AccessibilityNotificationWaiter waiter(
147 shell(), AccessibilityModeComplete,
148 ui::AX_EVENT_LOAD_COMPLETE);
149 GURL html_data_url("data:text/html," + html);
150 NavigateToURL(shell(), html_data_url);
151 waiter.WaitForNotification();
154 // Retrieve the MSAA client accessibility object for the Render Widget Host View
155 // of the selected tab.
156 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() {
157 content::WebContents* web_contents = shell()->web_contents();
158 return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible();
161 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) {
162 shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script);
166 // AccessibleChecker ----------------------------------------------------------
168 class AccessibleChecker {
169 public:
170 // This constructor can be used if the IA2 role will be the same as the MSAA
171 // role.
172 AccessibleChecker(const std::wstring& expected_name,
173 int32 expected_role,
174 const std::wstring& expected_value);
175 AccessibleChecker(const std::wstring& expected_name,
176 int32 expected_role,
177 int32 expected_ia2_role,
178 const std::wstring& expected_value);
179 AccessibleChecker(const std::wstring& expected_name,
180 const std::wstring& expected_role,
181 int32 expected_ia2_role,
182 const std::wstring& expected_value);
184 // Append an AccessibleChecker that verifies accessibility information for
185 // a child IAccessible. Order is important.
186 void AppendExpectedChild(AccessibleChecker* expected_child);
188 // Check that the name and role of the given IAccessible instance and its
189 // descendants match the expected names and roles that this object was
190 // initialized with.
191 void CheckAccessible(IAccessible* accessible);
193 // Set the expected value for this AccessibleChecker.
194 void SetExpectedValue(const std::wstring& expected_value);
196 // Set the expected state for this AccessibleChecker.
197 void SetExpectedState(LONG expected_state);
199 private:
200 typedef std::vector<AccessibleChecker*> AccessibleCheckerVector;
202 void CheckAccessibleName(IAccessible* accessible);
203 void CheckAccessibleRole(IAccessible* accessible);
204 void CheckIA2Role(IAccessible* accessible);
205 void CheckAccessibleValue(IAccessible* accessible);
206 void CheckAccessibleState(IAccessible* accessible);
207 void CheckAccessibleChildren(IAccessible* accessible);
208 base::string16 RoleVariantToString(const base::win::ScopedVariant& role);
210 // Expected accessible name. Checked against IAccessible::get_accName.
211 std::wstring name_;
213 // Expected accessible role. Checked against IAccessible::get_accRole.
214 base::win::ScopedVariant role_;
216 // Expected IAccessible2 role. Checked against IAccessible2::role.
217 int32 ia2_role_;
219 // Expected accessible value. Checked against IAccessible::get_accValue.
220 std::wstring value_;
222 // Expected accessible state. Checked against IAccessible::get_accState.
223 LONG state_;
225 // Expected accessible children. Checked using IAccessible::get_accChildCount
226 // and ::AccessibleChildren.
227 AccessibleCheckerVector children_;
230 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
231 int32 expected_role,
232 const std::wstring& expected_value)
233 : name_(expected_name),
234 role_(expected_role),
235 ia2_role_(expected_role),
236 value_(expected_value),
237 state_(-1) {
240 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
241 int32 expected_role,
242 int32 expected_ia2_role,
243 const std::wstring& expected_value)
244 : name_(expected_name),
245 role_(expected_role),
246 ia2_role_(expected_ia2_role),
247 value_(expected_value),
248 state_(-1) {
251 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name,
252 const std::wstring& expected_role,
253 int32 expected_ia2_role,
254 const std::wstring& expected_value)
255 : name_(expected_name),
256 role_(expected_role.c_str()),
257 ia2_role_(expected_ia2_role),
258 value_(expected_value),
259 state_(-1) {
262 void AccessibleChecker::AppendExpectedChild(
263 AccessibleChecker* expected_child) {
264 children_.push_back(expected_child);
267 void AccessibleChecker::CheckAccessible(IAccessible* accessible) {
268 SCOPED_TRACE("while checking " +
269 base::UTF16ToUTF8(RoleVariantToString(role_)));
270 CheckAccessibleName(accessible);
271 CheckAccessibleRole(accessible);
272 CheckIA2Role(accessible);
273 CheckAccessibleValue(accessible);
274 CheckAccessibleState(accessible);
275 CheckAccessibleChildren(accessible);
278 void AccessibleChecker::SetExpectedValue(const std::wstring& expected_value) {
279 value_ = expected_value;
282 void AccessibleChecker::SetExpectedState(LONG expected_state) {
283 state_ = expected_state;
286 void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) {
287 base::win::ScopedBstr name;
288 base::win::ScopedVariant childid_self(CHILDID_SELF);
289 HRESULT hr = accessible->get_accName(childid_self, name.Receive());
291 if (name_.empty()) {
292 // If the object doesn't have name S_FALSE should be returned.
293 EXPECT_EQ(S_FALSE, hr);
294 } else {
295 // Test that the correct string was returned.
296 EXPECT_EQ(S_OK, hr);
297 EXPECT_EQ(name_, std::wstring(name, name.Length()));
301 void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) {
302 base::win::ScopedVariant role;
303 base::win::ScopedVariant childid_self(CHILDID_SELF);
304 HRESULT hr = accessible->get_accRole(childid_self, role.Receive());
305 ASSERT_EQ(S_OK, hr);
306 EXPECT_EQ(0, role_.Compare(role))
307 << "Expected role: " << RoleVariantToString(role_)
308 << "\nGot role: " << RoleVariantToString(role);
311 void AccessibleChecker::CheckIA2Role(IAccessible* accessible) {
312 base::win::ScopedComPtr<IAccessible2> accessible2;
313 HRESULT hr = QueryIAccessible2(accessible, accessible2.Receive());
314 ASSERT_EQ(S_OK, hr);
315 long ia2_role = 0;
316 hr = accessible2->role(&ia2_role);
317 ASSERT_EQ(S_OK, hr);
318 EXPECT_EQ(ia2_role_, ia2_role)
319 << "Expected ia2 role: " << IAccessible2RoleToString(ia2_role_)
320 << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role);
323 void AccessibleChecker::CheckAccessibleValue(IAccessible* accessible) {
324 // Don't check the value if if's a DOCUMENT role, because the value
325 // is supposed to be the url (and we don't keep track of that in the
326 // test expectations).
327 base::win::ScopedVariant role;
328 base::win::ScopedVariant childid_self(CHILDID_SELF);
329 HRESULT hr = accessible->get_accRole(childid_self, role.Receive());
330 ASSERT_EQ(S_OK, hr);
331 if (role.type() == VT_I4 && V_I4(&role) == ROLE_SYSTEM_DOCUMENT)
332 return;
334 // Get the value.
335 base::win::ScopedBstr value;
336 hr = accessible->get_accValue(childid_self, value.Receive());
337 EXPECT_EQ(S_OK, hr);
339 // Test that the correct string was returned.
340 EXPECT_EQ(value_, std::wstring(value, value.Length()));
343 void AccessibleChecker::CheckAccessibleState(IAccessible* accessible) {
344 if (state_ < 0)
345 return;
347 base::win::ScopedVariant state;
348 base::win::ScopedVariant childid_self(CHILDID_SELF);
349 HRESULT hr = accessible->get_accState(childid_self, state.Receive());
350 EXPECT_EQ(S_OK, hr);
351 ASSERT_EQ(VT_I4, state.type());
352 LONG obj_state = V_I4(&state);
353 // Avoid flakiness. The "offscreen" state depends on whether the browser
354 // window is frontmost or not, and "hottracked" depends on whether the
355 // mouse cursor happens to be over the element.
356 obj_state &= ~(STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_HOTTRACKED);
357 EXPECT_EQ(state_, obj_state)
358 << "Expected state: " << IAccessibleStateToString(state_)
359 << "\nGot state: " << IAccessibleStateToString(obj_state);
362 void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) {
363 LONG child_count = 0;
364 HRESULT hr = parent->get_accChildCount(&child_count);
365 EXPECT_EQ(S_OK, hr);
366 ASSERT_EQ(child_count, children_.size());
368 scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]);
369 LONG obtained_count = 0;
370 hr = AccessibleChildren(parent, 0, child_count,
371 child_array.get(), &obtained_count);
372 ASSERT_EQ(S_OK, hr);
373 ASSERT_EQ(child_count, obtained_count);
375 VARIANT* child = child_array.get();
376 for (AccessibleCheckerVector::iterator child_checker = children_.begin();
377 child_checker != children_.end();
378 ++child_checker, ++child) {
379 base::win::ScopedComPtr<IAccessible> child_accessible(
380 GetAccessibleFromResultVariant(parent, child));
381 ASSERT_TRUE(child_accessible.get());
382 (*child_checker)->CheckAccessible(child_accessible);
386 base::string16 AccessibleChecker::RoleVariantToString(
387 const base::win::ScopedVariant& role) {
388 if (role.type() == VT_I4)
389 return IAccessibleRoleToString(V_I4(&role));
390 if (role.type() == VT_BSTR)
391 return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role)));
392 return base::string16();
395 } // namespace
398 // Tests ----------------------------------------------------------------------
400 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
401 TestBusyAccessibilityTree) {
402 NavigateToURL(shell(), GURL(url::kAboutBlankURL));
404 // The initial accessible returned should have state STATE_SYSTEM_BUSY while
405 // the accessibility tree is being requested from the renderer.
406 AccessibleChecker document1_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
407 std::wstring());
408 document1_checker.SetExpectedState(
409 STATE_SYSTEM_READONLY | STATE_SYSTEM_FOCUSABLE | STATE_SYSTEM_FOCUSED |
410 STATE_SYSTEM_BUSY);
411 document1_checker.CheckAccessible(GetRendererAccessible());
414 // Periodically failing. See crbug.com/145537
415 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
416 DISABLED_TestNotificationActiveDescendantChanged) {
417 LoadInitialAccessibilityTreeFromHtml(
418 "<ul tabindex='-1' role='radiogroup' aria-label='ul'>"
419 "<li id='li'>li</li></ul>");
421 // Check the browser's copy of the renderer accessibility tree.
422 AccessibleChecker list_marker_checker(L"\x2022", ROLE_SYSTEM_TEXT,
423 std::wstring());
424 AccessibleChecker static_text_checker(L"li", ROLE_SYSTEM_TEXT,
425 std::wstring());
426 AccessibleChecker list_item_checker(std::wstring(), ROLE_SYSTEM_LISTITEM,
427 std::wstring());
428 list_item_checker.SetExpectedState(STATE_SYSTEM_READONLY);
429 AccessibleChecker radio_group_checker(L"ul", ROLE_SYSTEM_GROUPING,
430 IA2_ROLE_SECTION, std::wstring());
431 radio_group_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
432 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
433 std::wstring());
434 list_item_checker.AppendExpectedChild(&list_marker_checker);
435 list_item_checker.AppendExpectedChild(&static_text_checker);
436 radio_group_checker.AppendExpectedChild(&list_item_checker);
437 document_checker.AppendExpectedChild(&radio_group_checker);
438 document_checker.CheckAccessible(GetRendererAccessible());
440 // Set focus to the radio group.
441 scoped_ptr<AccessibilityNotificationWaiter> waiter(
442 new AccessibilityNotificationWaiter(
443 shell(), AccessibilityModeComplete,
444 ui::AX_EVENT_FOCUS));
445 ExecuteScript(L"document.body.children[0].focus()");
446 waiter->WaitForNotification();
448 // Check that the accessibility tree of the browser has been updated.
449 radio_group_checker.SetExpectedState(
450 STATE_SYSTEM_FOCUSABLE | STATE_SYSTEM_FOCUSED);
451 document_checker.CheckAccessible(GetRendererAccessible());
453 // Set the active descendant of the radio group
454 waiter.reset(new AccessibilityNotificationWaiter(
455 shell(), AccessibilityModeComplete,
456 ui::AX_EVENT_FOCUS));
457 ExecuteScript(
458 L"document.body.children[0].setAttribute('aria-activedescendant', 'li')");
459 waiter->WaitForNotification();
461 // Check that the accessibility tree of the browser has been updated.
462 list_item_checker.SetExpectedState(
463 STATE_SYSTEM_READONLY | STATE_SYSTEM_FOCUSED);
464 radio_group_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
465 document_checker.CheckAccessible(GetRendererAccessible());
468 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
469 TestNotificationCheckedStateChanged) {
470 LoadInitialAccessibilityTreeFromHtml(
471 "<body><input type='checkbox' /></body>");
473 // Check the browser's copy of the renderer accessibility tree.
474 AccessibleChecker checkbox_checker(std::wstring(), ROLE_SYSTEM_CHECKBUTTON,
475 std::wstring());
476 checkbox_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
477 AccessibleChecker body_checker(std::wstring(), L"body", IA2_ROLE_SECTION,
478 std::wstring());
479 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
480 std::wstring());
481 body_checker.AppendExpectedChild(&checkbox_checker);
482 document_checker.AppendExpectedChild(&body_checker);
483 document_checker.CheckAccessible(GetRendererAccessible());
485 // Check the checkbox.
486 scoped_ptr<AccessibilityNotificationWaiter> waiter(
487 new AccessibilityNotificationWaiter(
488 shell(), AccessibilityModeComplete,
489 ui::AX_EVENT_CHECKED_STATE_CHANGED));
490 ExecuteScript(L"document.body.children[0].checked=true");
491 waiter->WaitForNotification();
493 // Check that the accessibility tree of the browser has been updated.
494 checkbox_checker.SetExpectedState(
495 STATE_SYSTEM_CHECKED | STATE_SYSTEM_FOCUSABLE);
496 document_checker.CheckAccessible(GetRendererAccessible());
499 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
500 TestNotificationChildrenChanged) {
501 // The role attribute causes the node to be in the accessibility tree.
502 LoadInitialAccessibilityTreeFromHtml("<body role=group></body>");
504 // Check the browser's copy of the renderer accessibility tree.
505 AccessibleChecker group_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
506 std::wstring());
507 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
508 std::wstring());
509 document_checker.AppendExpectedChild(&group_checker);
510 document_checker.CheckAccessible(GetRendererAccessible());
512 // Change the children of the document body.
513 scoped_ptr<AccessibilityNotificationWaiter> waiter(
514 new AccessibilityNotificationWaiter(
515 shell(),
516 AccessibilityModeComplete,
517 ui::AX_EVENT_CHILDREN_CHANGED));
518 ExecuteScript(L"document.body.innerHTML='<b>new text</b>'");
519 waiter->WaitForNotification();
521 // Check that the accessibility tree of the browser has been updated.
522 AccessibleChecker text_checker(
523 L"new text", ROLE_SYSTEM_STATICTEXT, std::wstring());
524 group_checker.AppendExpectedChild(&text_checker);
525 document_checker.CheckAccessible(GetRendererAccessible());
528 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
529 TestNotificationChildrenChanged2) {
530 // The role attribute causes the node to be in the accessibility tree.
531 LoadInitialAccessibilityTreeFromHtml(
532 "<div role=group style='visibility: hidden'>text</div>");
534 // Check the accessible tree of the browser.
535 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
536 std::wstring());
537 document_checker.CheckAccessible(GetRendererAccessible());
539 // Change the children of the document body.
540 scoped_ptr<AccessibilityNotificationWaiter> waiter(
541 new AccessibilityNotificationWaiter(
542 shell(), AccessibilityModeComplete,
543 ui::AX_EVENT_CHILDREN_CHANGED));
544 ExecuteScript(L"document.body.children[0].style.visibility='visible'");
545 waiter->WaitForNotification();
547 // Check that the accessibility tree of the browser has been updated.
548 AccessibleChecker static_text_checker(L"text", ROLE_SYSTEM_STATICTEXT,
549 std::wstring());
550 AccessibleChecker group_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
551 std::wstring());
552 document_checker.AppendExpectedChild(&group_checker);
553 group_checker.AppendExpectedChild(&static_text_checker);
554 document_checker.CheckAccessible(GetRendererAccessible());
557 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
558 TestNotificationFocusChanged) {
559 // The role attribute causes the node to be in the accessibility tree.
560 LoadInitialAccessibilityTreeFromHtml("<div role=group tabindex='-1'></div>");
562 // Check the browser's copy of the renderer accessibility tree.
563 SCOPED_TRACE("Check initial tree");
564 AccessibleChecker group_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
565 std::wstring());
566 group_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
567 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
568 std::wstring());
569 document_checker.AppendExpectedChild(&group_checker);
570 document_checker.CheckAccessible(GetRendererAccessible());
572 // Focus the div in the document
573 scoped_ptr<AccessibilityNotificationWaiter> waiter(
574 new AccessibilityNotificationWaiter(
575 shell(), AccessibilityModeComplete,
576 ui::AX_EVENT_FOCUS));
577 ExecuteScript(L"document.body.children[0].focus()");
578 waiter->WaitForNotification();
580 // Check that the accessibility tree of the browser has been updated.
581 SCOPED_TRACE("Check updated tree after focusing div");
582 group_checker.SetExpectedState(
583 STATE_SYSTEM_FOCUSABLE | STATE_SYSTEM_FOCUSED);
584 document_checker.CheckAccessible(GetRendererAccessible());
586 // Focus the document accessible. This will un-focus the current node.
587 waiter.reset(
588 new AccessibilityNotificationWaiter(
589 shell(), AccessibilityModeComplete,
590 ui::AX_EVENT_BLUR));
591 base::win::ScopedComPtr<IAccessible> document_accessible(
592 GetRendererAccessible());
593 ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL));
594 base::win::ScopedVariant childid_self(CHILDID_SELF);
595 HRESULT hr = document_accessible->accSelect(SELFLAG_TAKEFOCUS, childid_self);
596 ASSERT_EQ(S_OK, hr);
597 waiter->WaitForNotification();
599 // Check that the accessibility tree of the browser has been updated.
600 SCOPED_TRACE("Check updated tree after focusing document again");
601 group_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
602 document_checker.CheckAccessible(GetRendererAccessible());
605 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
606 TestNotificationValueChanged) {
607 LoadInitialAccessibilityTreeFromHtml(
608 "<body><input type='text' value='old value'/></body>");
610 // Check the browser's copy of the renderer accessibility tree.
611 AccessibleChecker text_field_checker(std::wstring(), ROLE_SYSTEM_TEXT,
612 L"old value");
613 text_field_checker.SetExpectedState(STATE_SYSTEM_FOCUSABLE);
614 AccessibleChecker body_checker(std::wstring(), L"body", IA2_ROLE_SECTION,
615 std::wstring());
616 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
617 std::wstring());
618 body_checker.AppendExpectedChild(&text_field_checker);
619 document_checker.AppendExpectedChild(&body_checker);
620 document_checker.CheckAccessible(GetRendererAccessible());
622 // Set the value of the text control
623 scoped_ptr<AccessibilityNotificationWaiter> waiter(
624 new AccessibilityNotificationWaiter(
625 shell(), AccessibilityModeComplete,
626 ui::AX_EVENT_VALUE_CHANGED));
627 ExecuteScript(L"document.body.children[0].value='new value'");
628 waiter->WaitForNotification();
630 // Check that the accessibility tree of the browser has been updated.
631 text_field_checker.SetExpectedValue(L"new value");
632 document_checker.CheckAccessible(GetRendererAccessible());
635 // This test verifies that the web content's accessibility tree is a
636 // descendant of the main browser window's accessibility tree, so that
637 // tools like AccExplorer32 or AccProbe can be used to examine Chrome's
638 // accessibility support.
640 // If you made a change and this test now fails, check that the NativeViewHost
641 // that wraps the tab contents returns the IAccessible implementation
642 // provided by RenderWidgetHostViewWin in GetNativeViewAccessible().
643 // flaky: http://crbug.com/402190
644 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
645 DISABLED_ContainsRendererAccessibilityTree) {
646 LoadInitialAccessibilityTreeFromHtml(
647 "<html><head><title>MyDocument</title></head>"
648 "<body>Content</body></html>");
650 // Get the accessibility object for the window tree host.
651 aura::Window* window = shell()->window();
652 CHECK(window);
653 aura::WindowTreeHost* window_tree_host = window->GetHost();
654 CHECK(window_tree_host);
655 HWND hwnd = window_tree_host->GetAcceleratedWidget();
656 CHECK(hwnd);
657 base::win::ScopedComPtr<IAccessible> browser_accessible;
658 HRESULT hr = AccessibleObjectFromWindow(
659 hwnd,
660 OBJID_WINDOW,
661 IID_IAccessible,
662 reinterpret_cast<void**>(browser_accessible.Receive()));
663 ASSERT_EQ(S_OK, hr);
665 bool found = false;
666 RecursiveFindNodeInAccessibilityTree(
667 browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found);
668 ASSERT_EQ(found, true);
671 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
672 SupportsISimpleDOM) {
673 LoadInitialAccessibilityTreeFromHtml(
674 "<body><input type='checkbox' /></body>");
676 // Get the IAccessible object for the document.
677 base::win::ScopedComPtr<IAccessible> document_accessible(
678 GetRendererAccessible());
679 ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL));
681 // Get the ISimpleDOM object for the document.
682 base::win::ScopedComPtr<IServiceProvider> service_provider;
683 HRESULT hr = static_cast<IAccessible*>(document_accessible)->QueryInterface(
684 service_provider.Receive());
685 ASSERT_EQ(S_OK, hr);
686 const GUID refguid = {0x0c539790, 0x12e4, 0x11cf,
687 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8};
688 base::win::ScopedComPtr<ISimpleDOMNode> document_isimpledomnode;
689 hr = static_cast<IServiceProvider *>(service_provider)->QueryService(
690 refguid, IID_ISimpleDOMNode,
691 reinterpret_cast<void**>(document_isimpledomnode.Receive()));
692 ASSERT_EQ(S_OK, hr);
694 base::win::ScopedBstr node_name;
695 short name_space_id; // NOLINT
696 base::win::ScopedBstr node_value;
697 unsigned int num_children;
698 unsigned int unique_id;
699 unsigned short node_type; // NOLINT
700 hr = document_isimpledomnode->get_nodeInfo(
701 node_name.Receive(), &name_space_id, node_value.Receive(), &num_children,
702 &unique_id, &node_type);
703 ASSERT_EQ(S_OK, hr);
704 EXPECT_EQ(NODETYPE_DOCUMENT, node_type);
705 EXPECT_EQ(1, num_children);
706 node_name.Reset();
707 node_value.Reset();
709 base::win::ScopedComPtr<ISimpleDOMNode> body_isimpledomnode;
710 hr = document_isimpledomnode->get_firstChild(
711 body_isimpledomnode.Receive());
712 ASSERT_EQ(S_OK, hr);
713 hr = body_isimpledomnode->get_nodeInfo(
714 node_name.Receive(), &name_space_id, node_value.Receive(), &num_children,
715 &unique_id, &node_type);
716 ASSERT_EQ(S_OK, hr);
717 EXPECT_EQ(L"body", std::wstring(node_name, node_name.Length()));
718 EXPECT_EQ(NODETYPE_ELEMENT, node_type);
719 EXPECT_EQ(1, num_children);
720 node_name.Reset();
721 node_value.Reset();
723 base::win::ScopedComPtr<ISimpleDOMNode> checkbox_isimpledomnode;
724 hr = body_isimpledomnode->get_firstChild(
725 checkbox_isimpledomnode.Receive());
726 ASSERT_EQ(S_OK, hr);
727 hr = checkbox_isimpledomnode->get_nodeInfo(
728 node_name.Receive(), &name_space_id, node_value.Receive(), &num_children,
729 &unique_id, &node_type);
730 ASSERT_EQ(S_OK, hr);
731 EXPECT_EQ(L"input", std::wstring(node_name, node_name.Length()));
732 EXPECT_EQ(NODETYPE_ELEMENT, node_type);
733 EXPECT_EQ(0, num_children);
736 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestRoleGroup) {
737 LoadInitialAccessibilityTreeFromHtml(
738 "<fieldset></fieldset><div role=group></div>");
740 // Check the browser's copy of the renderer accessibility tree.
741 AccessibleChecker grouping1_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
742 std::wstring());
743 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
744 std::wstring());
745 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
746 std::wstring());
747 document_checker.AppendExpectedChild(&grouping1_checker);
748 document_checker.AppendExpectedChild(&grouping2_checker);
749 document_checker.CheckAccessible(GetRendererAccessible());
752 } // namespace content