Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / content / browser / accessibility / accessibility_win_browsertest.cc
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.
4
5 #include <vector>
6
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"
28
29 namespace content {
30
31 namespace {
32
33 // Helpers --------------------------------------------------------------------
34
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;
45     }
46
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;
54     }
55   }
56   return ptr;
57 }
58
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;
66 }
67
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());
83
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());
91
92   if (expected_role == V_I4(&role) && expected_name == name) {
93     *found = true;
94     return;
95   }
96
97   LONG child_count = 0;
98   HRESULT hr = node->get_accChildCount(&child_count);
99   ASSERT_EQ(S_OK, hr);
100
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);
107
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;
117     }
118   }
119 }
120
121
122 // AccessibilityWinBrowserTest ------------------------------------------------
123
124 class AccessibilityWinBrowserTest : public ContentBrowserTest {
125  public:
126   AccessibilityWinBrowserTest();
127   virtual ~AccessibilityWinBrowserTest();
128
129  protected:
130   void LoadInitialAccessibilityTreeFromHtml(const std::string& html);
131   IAccessible* GetRendererAccessible();
132   void ExecuteScript(const std::wstring& script);
133
134  private:
135   DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest);
136 };
137
138 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() {
139 }
140
141 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() {
142 }
143
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();
152 }
153
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();
159 }
160
161 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) {
162   shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script);
163 }
164
165
166 // AccessibleChecker ----------------------------------------------------------
167
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);
183
184   // Append an AccessibleChecker that verifies accessibility information for
185   // a child IAccessible. Order is important.
186   void AppendExpectedChild(AccessibleChecker* expected_child);
187
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);
192
193   // Set the expected value for this AccessibleChecker.
194   void SetExpectedValue(const std::wstring& expected_value);
195
196   // Set the expected state for this AccessibleChecker.
197   void SetExpectedState(LONG expected_state);
198
199  private:
200   typedef std::vector<AccessibleChecker*> AccessibleCheckerVector;
201
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);
209
210   // Expected accessible name. Checked against IAccessible::get_accName.
211   std::wstring name_;
212
213   // Expected accessible role. Checked against IAccessible::get_accRole.
214   base::win::ScopedVariant role_;
215
216   // Expected IAccessible2 role. Checked against IAccessible2::role.
217   int32 ia2_role_;
218
219   // Expected accessible value. Checked against IAccessible::get_accValue.
220   std::wstring value_;
221
222   // Expected accessible state. Checked against IAccessible::get_accState.
223   LONG state_;
224
225   // Expected accessible children. Checked using IAccessible::get_accChildCount
226   // and ::AccessibleChildren.
227   AccessibleCheckerVector children_;
228 };
229
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) {
238 }
239
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) {
249 }
250
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) {
260 }
261
262 void AccessibleChecker::AppendExpectedChild(
263     AccessibleChecker* expected_child) {
264   children_.push_back(expected_child);
265 }
266
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);
276 }
277
278 void AccessibleChecker::SetExpectedValue(const std::wstring& expected_value) {
279   value_ = expected_value;
280 }
281
282 void AccessibleChecker::SetExpectedState(LONG expected_state) {
283   state_ = expected_state;
284 }
285
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());
290
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()));
298   }
299 }
300
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);
309 }
310
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);
321 }
322
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;
333
334   // Get the value.
335   base::win::ScopedBstr value;
336   hr = accessible->get_accValue(childid_self, value.Receive());
337   EXPECT_EQ(S_OK, hr);
338
339   // Test that the correct string was returned.
340   EXPECT_EQ(value_, std::wstring(value, value.Length()));
341 }
342
343 void AccessibleChecker::CheckAccessibleState(IAccessible* accessible) {
344   if (state_ < 0)
345     return;
346
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);
360 }
361
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());
367
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);
374
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);
383   }
384 }
385
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();
393 }
394
395 }  // namespace
396
397
398 // Tests ----------------------------------------------------------------------
399
400 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
401                        TestBusyAccessibilityTree) {
402   NavigateToURL(shell(), GURL(url::kAboutBlankURL));
403
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());
412 }
413
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>");
420
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());
439
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();
447
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());
452
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();
460
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());
466 }
467
468 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
469                        TestNotificationCheckedStateChanged) {
470   LoadInitialAccessibilityTreeFromHtml(
471       "<body><input type='checkbox' /></body>");
472
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());
484
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();
492
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());
497 }
498
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>");
503
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());
511
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();
520
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());
526 }
527
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>");
533
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());
538
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();
546
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());
555 }
556
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>");
561
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());
571
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();
579
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());
585
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();
598
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());
603 }
604
605 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
606                        TestNotificationValueChanged) {
607   LoadInitialAccessibilityTreeFromHtml(
608       "<body><input type='text' value='old value'/></body>");
609
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());
621
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();
629
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());
633 }
634
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.
639 //
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 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
644                        ContainsRendererAccessibilityTree) {
645   LoadInitialAccessibilityTreeFromHtml(
646       "<html><head><title>MyDocument</title></head>"
647       "<body>Content</body></html>");
648
649   // Get the accessibility object for the window tree host.
650   aura::Window* window = shell()->window();
651   CHECK(window);
652   aura::WindowTreeHost* window_tree_host = window->GetHost();
653   CHECK(window_tree_host);
654   HWND hwnd = window_tree_host->GetAcceleratedWidget();
655   CHECK(hwnd);
656   base::win::ScopedComPtr<IAccessible> browser_accessible;
657   HRESULT hr = AccessibleObjectFromWindow(
658       hwnd,
659       OBJID_WINDOW,
660       IID_IAccessible,
661       reinterpret_cast<void**>(browser_accessible.Receive()));
662   ASSERT_EQ(S_OK, hr);
663
664   bool found = false;
665   RecursiveFindNodeInAccessibilityTree(
666       browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found);
667   ASSERT_EQ(found, true);
668 }
669
670 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
671                        SupportsISimpleDOM) {
672   LoadInitialAccessibilityTreeFromHtml(
673       "<body><input type='checkbox' /></body>");
674
675   // Get the IAccessible object for the document.
676   base::win::ScopedComPtr<IAccessible> document_accessible(
677       GetRendererAccessible());
678   ASSERT_NE(document_accessible.get(), reinterpret_cast<IAccessible*>(NULL));
679
680   // Get the ISimpleDOM object for the document.
681   base::win::ScopedComPtr<IServiceProvider> service_provider;
682   HRESULT hr = static_cast<IAccessible*>(document_accessible)->QueryInterface(
683       service_provider.Receive());
684   ASSERT_EQ(S_OK, hr);
685   const GUID refguid = {0x0c539790, 0x12e4, 0x11cf,
686                         0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8};
687   base::win::ScopedComPtr<ISimpleDOMNode> document_isimpledomnode;
688   hr = static_cast<IServiceProvider *>(service_provider)->QueryService(
689       refguid, IID_ISimpleDOMNode,
690       reinterpret_cast<void**>(document_isimpledomnode.Receive()));
691   ASSERT_EQ(S_OK, hr);
692
693   base::win::ScopedBstr node_name;
694   short name_space_id;  // NOLINT
695   base::win::ScopedBstr node_value;
696   unsigned int num_children;
697   unsigned int unique_id;
698   unsigned short node_type;  // NOLINT
699   hr = document_isimpledomnode->get_nodeInfo(
700       node_name.Receive(), &name_space_id, node_value.Receive(), &num_children,
701       &unique_id, &node_type);
702   ASSERT_EQ(S_OK, hr);
703   EXPECT_EQ(NODETYPE_DOCUMENT, node_type);
704   EXPECT_EQ(1, num_children);
705   node_name.Reset();
706   node_value.Reset();
707
708   base::win::ScopedComPtr<ISimpleDOMNode> body_isimpledomnode;
709   hr = document_isimpledomnode->get_firstChild(
710       body_isimpledomnode.Receive());
711   ASSERT_EQ(S_OK, hr);
712   hr = body_isimpledomnode->get_nodeInfo(
713       node_name.Receive(), &name_space_id, node_value.Receive(), &num_children,
714       &unique_id, &node_type);
715   ASSERT_EQ(S_OK, hr);
716   EXPECT_EQ(L"body", std::wstring(node_name, node_name.Length()));
717   EXPECT_EQ(NODETYPE_ELEMENT, node_type);
718   EXPECT_EQ(1, num_children);
719   node_name.Reset();
720   node_value.Reset();
721
722   base::win::ScopedComPtr<ISimpleDOMNode> checkbox_isimpledomnode;
723   hr = body_isimpledomnode->get_firstChild(
724       checkbox_isimpledomnode.Receive());
725   ASSERT_EQ(S_OK, hr);
726   hr = checkbox_isimpledomnode->get_nodeInfo(
727       node_name.Receive(), &name_space_id, node_value.Receive(), &num_children,
728       &unique_id, &node_type);
729   ASSERT_EQ(S_OK, hr);
730   EXPECT_EQ(L"input", std::wstring(node_name, node_name.Length()));
731   EXPECT_EQ(NODETYPE_ELEMENT, node_type);
732   EXPECT_EQ(0, num_children);
733 }
734
735 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestRoleGroup) {
736   LoadInitialAccessibilityTreeFromHtml(
737       "<fieldset></fieldset><div role=group></div>");
738
739   // Check the browser's copy of the renderer accessibility tree.
740   AccessibleChecker grouping1_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
741                                       std::wstring());
742   AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING,
743                                       std::wstring());
744   AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT,
745                                      std::wstring());
746   document_checker.AppendExpectedChild(&grouping1_checker);
747   document_checker.AppendExpectedChild(&grouping2_checker);
748   document_checker.CheckAccessible(GetRendererAccessible());
749 }
750
751 }  // namespace content