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.
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"
33 // Helpers --------------------------------------------------------------------
35 base::win::ScopedComPtr
<IAccessible
> GetAccessibleFromResultVariant(
38 base::win::ScopedComPtr
<IAccessible
> ptr
;
41 IDispatch
* dispatch
= V_DISPATCH(var
);
43 ptr
.QueryFrom(dispatch
);
48 base::win::ScopedComPtr
<IDispatch
> dispatch
;
49 HRESULT hr
= parent
->get_accChild(*var
, dispatch
.Receive());
50 EXPECT_TRUE(SUCCEEDED(hr
));
52 dispatch
.QueryInterface(ptr
.Receive());
59 HRESULT
QueryIAccessible2(IAccessible
* accessible
, IAccessible2
** accessible2
) {
60 // TODO(ctguil): For some reason querying the IAccessible2 interface from
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
71 void RecursiveFindNodeInAccessibilityTree(IAccessible
* node
,
73 const std::wstring
& expected_name
,
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
++)
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
) {
98 HRESULT hr
= node
->get_accChildCount(&child_count
);
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
);
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,
122 // AccessibilityWinBrowserTest ------------------------------------------------
124 class AccessibilityWinBrowserTest
: public ContentBrowserTest
{
126 AccessibilityWinBrowserTest();
127 virtual ~AccessibilityWinBrowserTest();
130 void LoadInitialAccessibilityTreeFromHtml(const std::string
& html
);
131 IAccessible
* GetRendererAccessible();
132 void ExecuteScript(const std::wstring
& script
);
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
{
170 // This constructor can be used if the IA2 role will be the same as the MSAA
172 AccessibleChecker(const std::wstring
& expected_name
,
174 const std::wstring
& expected_value
);
175 AccessibleChecker(const std::wstring
& expected_name
,
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
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
);
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.
213 // Expected accessible role. Checked against IAccessible::get_accRole.
214 base::win::ScopedVariant role_
;
216 // Expected IAccessible2 role. Checked against IAccessible2::role.
219 // Expected accessible value. Checked against IAccessible::get_accValue.
222 // Expected accessible state. Checked against IAccessible::get_accState.
225 // Expected accessible children. Checked using IAccessible::get_accChildCount
226 // and ::AccessibleChildren.
227 AccessibleCheckerVector children_
;
230 AccessibleChecker::AccessibleChecker(const std::wstring
& expected_name
,
232 const std::wstring
& expected_value
)
233 : name_(expected_name
),
234 role_(expected_role
),
235 ia2_role_(expected_role
),
236 value_(expected_value
),
240 AccessibleChecker::AccessibleChecker(const std::wstring
& expected_name
,
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
),
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
),
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());
292 // If the object doesn't have name S_FALSE should be returned.
293 EXPECT_EQ(S_FALSE
, hr
);
295 // Test that the correct string was returned.
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());
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());
316 hr
= accessible2
->role(&ia2_role
);
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());
331 if (role
.type() == VT_I4
&& V_I4(&role
) == ROLE_SYSTEM_DOCUMENT
)
335 base::win::ScopedBstr value
;
336 hr
= accessible
->get_accValue(childid_self
, value
.Receive());
339 // Test that the correct string was returned.
340 EXPECT_EQ(value_
, std::wstring(value
, value
.Length()));
343 void AccessibleChecker::CheckAccessibleState(IAccessible
* accessible
) {
347 base::win::ScopedVariant state
;
348 base::win::ScopedVariant
childid_self(CHILDID_SELF
);
349 HRESULT hr
= accessible
->get_accState(childid_self
, state
.Receive());
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
);
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
);
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();
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
,
408 document1_checker
.SetExpectedState(
409 STATE_SYSTEM_READONLY
| STATE_SYSTEM_FOCUSABLE
| STATE_SYSTEM_FOCUSED
|
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
,
424 AccessibleChecker
static_text_checker(L
"li", ROLE_SYSTEM_TEXT
,
426 AccessibleChecker
list_item_checker(std::wstring(), ROLE_SYSTEM_LISTITEM
,
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
,
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
));
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
,
476 checkbox_checker
.SetExpectedState(STATE_SYSTEM_FOCUSABLE
);
477 AccessibleChecker
body_checker(std::wstring(), L
"body", IA2_ROLE_SECTION
,
479 AccessibleChecker
document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT
,
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
,
507 AccessibleChecker
document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT
,
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(
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
,
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
,
550 AccessibleChecker
group_checker(std::wstring(), ROLE_SYSTEM_GROUPING
,
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
,
566 group_checker
.SetExpectedState(STATE_SYSTEM_FOCUSABLE
);
567 AccessibleChecker
document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT
,
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.
588 new AccessibilityNotificationWaiter(
589 shell(), AccessibilityModeComplete
,
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
);
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
,
613 text_field_checker
.SetExpectedState(STATE_SYSTEM_FOCUSABLE
);
614 AccessibleChecker
body_checker(std::wstring(), L
"body", IA2_ROLE_SECTION
,
616 AccessibleChecker
document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT
,
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();
653 aura::WindowTreeHost
* window_tree_host
= window
->GetHost();
654 CHECK(window_tree_host
);
655 HWND hwnd
= window_tree_host
->GetAcceleratedWidget();
657 base::win::ScopedComPtr
<IAccessible
> browser_accessible
;
658 HRESULT hr
= AccessibleObjectFromWindow(
662 reinterpret_cast<void**>(browser_accessible
.Receive()));
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());
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()));
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
);
704 EXPECT_EQ(NODETYPE_DOCUMENT
, node_type
);
705 EXPECT_EQ(1, num_children
);
709 base::win::ScopedComPtr
<ISimpleDOMNode
> body_isimpledomnode
;
710 hr
= document_isimpledomnode
->get_firstChild(
711 body_isimpledomnode
.Receive());
713 hr
= body_isimpledomnode
->get_nodeInfo(
714 node_name
.Receive(), &name_space_id
, node_value
.Receive(), &num_children
,
715 &unique_id
, &node_type
);
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
);
723 base::win::ScopedComPtr
<ISimpleDOMNode
> checkbox_isimpledomnode
;
724 hr
= body_isimpledomnode
->get_firstChild(
725 checkbox_isimpledomnode
.Receive());
727 hr
= checkbox_isimpledomnode
->get_nodeInfo(
728 node_name
.Receive(), &name_space_id
, node_value
.Receive(), &num_children
,
729 &unique_id
, &node_type
);
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
,
743 AccessibleChecker
grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING
,
745 AccessibleChecker
document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT
,
747 document_checker
.AppendExpectedChild(&grouping1_checker
);
748 document_checker
.AppendExpectedChild(&grouping2_checker
);
749 document_checker
.CheckAccessible(GetRendererAccessible());
752 } // namespace content