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 "base/memory/scoped_ptr.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "base/win/scoped_bstr.h"
8 #include "base/win/scoped_comptr.h"
9 #include "base/win/scoped_variant.h"
10 #include "content/browser/accessibility/browser_accessibility_manager.h"
11 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
12 #include "content/browser/accessibility/browser_accessibility_win.h"
13 #include "content/common/accessibility_messages.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/base/win/atl_module.h"
21 // CountedBrowserAccessibility ------------------------------------------------
23 // Subclass of BrowserAccessibilityWin that counts the number of instances.
24 class CountedBrowserAccessibility : public BrowserAccessibilityWin {
26 CountedBrowserAccessibility();
27 virtual ~CountedBrowserAccessibility();
29 static void reset() { num_instances_ = 0; }
30 static int num_instances() { return num_instances_; }
33 static int num_instances_;
35 DISALLOW_COPY_AND_ASSIGN(CountedBrowserAccessibility);
39 int CountedBrowserAccessibility::num_instances_ = 0;
41 CountedBrowserAccessibility::CountedBrowserAccessibility() {
45 CountedBrowserAccessibility::~CountedBrowserAccessibility() {
50 // CountedBrowserAccessibilityFactory -----------------------------------------
52 // Factory that creates a CountedBrowserAccessibility.
53 class CountedBrowserAccessibilityFactory : public BrowserAccessibilityFactory {
55 CountedBrowserAccessibilityFactory();
58 virtual ~CountedBrowserAccessibilityFactory();
60 virtual BrowserAccessibility* Create() OVERRIDE;
62 DISALLOW_COPY_AND_ASSIGN(CountedBrowserAccessibilityFactory);
65 CountedBrowserAccessibilityFactory::CountedBrowserAccessibilityFactory() {
68 CountedBrowserAccessibilityFactory::~CountedBrowserAccessibilityFactory() {
71 BrowserAccessibility* CountedBrowserAccessibilityFactory::Create() {
72 CComObject<CountedBrowserAccessibility>* instance;
73 HRESULT hr = CComObject<CountedBrowserAccessibility>::CreateInstance(
75 DCHECK(SUCCEEDED(hr));
83 // BrowserAccessibilityTest ---------------------------------------------------
85 class BrowserAccessibilityTest : public testing::Test {
87 BrowserAccessibilityTest();
88 virtual ~BrowserAccessibilityTest();
91 virtual void SetUp() OVERRIDE;
93 DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityTest);
96 BrowserAccessibilityTest::BrowserAccessibilityTest() {
99 BrowserAccessibilityTest::~BrowserAccessibilityTest() {
102 void BrowserAccessibilityTest::SetUp() {
103 ui::win::CreateATLModuleIfNeeded();
107 // Actual tests ---------------------------------------------------------------
109 // Test that BrowserAccessibilityManager correctly releases the tree of
110 // BrowserAccessibility instances upon delete.
111 TEST_F(BrowserAccessibilityTest, TestNoLeaks) {
112 // Create AccessibilityNodeData objects for a simple document tree,
113 // representing the accessibility information used to initialize
114 // BrowserAccessibilityManager.
115 AccessibilityNodeData button;
117 button.SetName("Button");
118 button.role = WebKit::WebAXRoleButton;
121 AccessibilityNodeData checkbox;
123 checkbox.SetName("Checkbox");
124 checkbox.role = WebKit::WebAXRoleCheckBox;
127 AccessibilityNodeData root;
129 root.SetName("Document");
130 root.role = WebKit::WebAXRoleRootWebArea;
132 root.child_ids.push_back(2);
133 root.child_ids.push_back(3);
135 // Construct a BrowserAccessibilityManager with this
136 // AccessibilityNodeData tree and a factory for an instance-counting
137 // BrowserAccessibility, and ensure that exactly 3 instances were
138 // created. Note that the manager takes ownership of the factory.
139 CountedBrowserAccessibility::reset();
140 scoped_ptr<BrowserAccessibilityManager> manager(
141 BrowserAccessibilityManager::Create(
142 root, NULL, new CountedBrowserAccessibilityFactory()));
143 manager->UpdateNodesForTesting(button, checkbox);
144 ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
146 // Delete the manager and test that all 3 instances are deleted.
148 ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
150 // Construct a manager again, and this time use the IAccessible interface
151 // to get new references to two of the three nodes in the tree.
152 manager.reset(BrowserAccessibilityManager::Create(
153 root, NULL, new CountedBrowserAccessibilityFactory()));
154 manager->UpdateNodesForTesting(button, checkbox);
155 ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
156 IAccessible* root_accessible =
157 manager->GetRoot()->ToBrowserAccessibilityWin();
158 IDispatch* root_iaccessible = NULL;
159 IDispatch* child1_iaccessible = NULL;
160 base::win::ScopedVariant childid_self(CHILDID_SELF);
161 HRESULT hr = root_accessible->get_accChild(childid_self, &root_iaccessible);
163 base::win::ScopedVariant one(1);
164 hr = root_accessible->get_accChild(one, &child1_iaccessible);
167 // Now delete the manager, and only one of the three nodes in the tree
168 // should be released.
170 ASSERT_EQ(2, CountedBrowserAccessibility::num_instances());
172 // Release each of our references and make sure that each one results in
173 // the instance being deleted as its reference count hits zero.
174 root_iaccessible->Release();
175 ASSERT_EQ(1, CountedBrowserAccessibility::num_instances());
176 child1_iaccessible->Release();
177 ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
180 TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
181 // Create AccessibilityNodeData objects for a simple document tree,
182 // representing the accessibility information used to initialize
183 // BrowserAccessibilityManager.
184 AccessibilityNodeData text;
186 text.role = WebKit::WebAXRoleStaticText;
187 text.SetName("old text");
190 AccessibilityNodeData root;
192 root.SetName("Document");
193 root.role = WebKit::WebAXRoleRootWebArea;
195 root.child_ids.push_back(2);
197 // Construct a BrowserAccessibilityManager with this
198 // AccessibilityNodeData tree and a factory for an instance-counting
199 // BrowserAccessibility.
200 CountedBrowserAccessibility::reset();
201 scoped_ptr<BrowserAccessibilityManager> manager(
202 BrowserAccessibilityManager::Create(
203 root, NULL, new CountedBrowserAccessibilityFactory()));
204 manager->UpdateNodesForTesting(text);
206 // Query for the text IAccessible and verify that it returns "old text" as its
208 base::win::ScopedVariant one(1);
209 base::win::ScopedComPtr<IDispatch> text_dispatch;
210 HRESULT hr = manager->GetRoot()->ToBrowserAccessibilityWin()->get_accChild(
211 one, text_dispatch.Receive());
214 base::win::ScopedComPtr<IAccessible> text_accessible;
215 hr = text_dispatch.QueryInterface(text_accessible.Receive());
218 base::win::ScopedVariant childid_self(CHILDID_SELF);
219 base::win::ScopedBstr name;
220 hr = text_accessible->get_accName(childid_self, name.Receive());
222 EXPECT_EQ(L"old text", string16(name));
225 text_dispatch.Release();
226 text_accessible.Release();
228 // Notify the BrowserAccessibilityManager that the text child has changed.
229 AccessibilityNodeData text2;
231 text2.role = WebKit::WebAXRoleStaticText;
232 text2.SetName("new text");
233 text2.SetName("old text");
234 AccessibilityHostMsg_EventParams param;
235 param.event_type = WebKit::WebAXEventChildrenChanged;
236 param.nodes.push_back(text2);
238 std::vector<AccessibilityHostMsg_EventParams> events;
239 events.push_back(param);
240 manager->OnAccessibilityEvents(events);
242 // Query for the text IAccessible and verify that it now returns "new text"
244 hr = manager->GetRoot()->ToBrowserAccessibilityWin()->get_accChild(
245 one, text_dispatch.Receive());
248 hr = text_dispatch.QueryInterface(text_accessible.Receive());
251 hr = text_accessible->get_accName(childid_self, name.Receive());
253 EXPECT_EQ(L"new text", string16(name));
255 text_dispatch.Release();
256 text_accessible.Release();
258 // Delete the manager and test that all BrowserAccessibility instances are
261 ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
264 TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) {
265 // Create AccessibilityNodeData objects for a simple document tree,
266 // representing the accessibility information used to initialize
267 // BrowserAccessibilityManager.
268 AccessibilityNodeData div;
270 div.role = WebKit::WebAXRoleGroup;
273 AccessibilityNodeData text3;
275 text3.role = WebKit::WebAXRoleStaticText;
278 AccessibilityNodeData text4;
280 text4.role = WebKit::WebAXRoleStaticText;
283 div.child_ids.push_back(3);
284 div.child_ids.push_back(4);
286 AccessibilityNodeData root;
288 root.role = WebKit::WebAXRoleRootWebArea;
290 root.child_ids.push_back(2);
292 // Construct a BrowserAccessibilityManager with this
293 // AccessibilityNodeData tree and a factory for an instance-counting
294 // BrowserAccessibility and ensure that exactly 4 instances were
295 // created. Note that the manager takes ownership of the factory.
296 CountedBrowserAccessibility::reset();
297 scoped_ptr<BrowserAccessibilityManager> manager(
298 BrowserAccessibilityManager::Create(
299 root, NULL, new CountedBrowserAccessibilityFactory()));
300 manager->UpdateNodesForTesting(div, text3, text4);
301 ASSERT_EQ(4, CountedBrowserAccessibility::num_instances());
303 // Notify the BrowserAccessibilityManager that the div node and its children
304 // were removed and ensure that only one BrowserAccessibility instance exists.
305 root.child_ids.clear();
306 AccessibilityHostMsg_EventParams param;
307 param.event_type = WebKit::WebAXEventChildrenChanged;
308 param.nodes.push_back(root);
310 std::vector<AccessibilityHostMsg_EventParams> events;
311 events.push_back(param);
312 manager->OnAccessibilityEvents(events);
313 ASSERT_EQ(1, CountedBrowserAccessibility::num_instances());
315 // Delete the manager and test that all BrowserAccessibility instances are
318 ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
321 TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
322 std::string text1_value = "One two three.\nFour five six.";
324 AccessibilityNodeData text1;
326 text1.role = WebKit::WebAXRoleTextField;
328 text1.AddStringAttribute(AccessibilityNodeData::ATTR_VALUE, text1_value);
329 std::vector<int32> line_breaks;
330 line_breaks.push_back(15);
331 text1.AddIntListAttribute(
332 AccessibilityNodeData::ATTR_LINE_BREAKS, line_breaks);
334 AccessibilityNodeData root;
336 root.role = WebKit::WebAXRoleRootWebArea;
338 root.child_ids.push_back(11);
340 CountedBrowserAccessibility::reset();
341 scoped_ptr<BrowserAccessibilityManager> manager(
342 BrowserAccessibilityManager::Create(
343 root, NULL, new CountedBrowserAccessibilityFactory()));
344 manager->UpdateNodesForTesting(text1);
345 ASSERT_EQ(2, CountedBrowserAccessibility::num_instances());
347 BrowserAccessibilityWin* root_obj =
348 manager->GetRoot()->ToBrowserAccessibilityWin();
349 BrowserAccessibilityWin* text1_obj =
350 root_obj->PlatformGetChild(0)->ToBrowserAccessibilityWin();
353 ASSERT_EQ(S_OK, text1_obj->get_nCharacters(&text1_len));
355 base::win::ScopedBstr text;
356 ASSERT_EQ(S_OK, text1_obj->get_text(0, text1_len, text.Receive()));
357 ASSERT_EQ(text1_value, base::UTF16ToUTF8(string16(text)));
360 ASSERT_EQ(S_OK, text1_obj->get_text(0, 4, text.Receive()));
361 ASSERT_STREQ(L"One ", text);
366 ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
367 1, IA2_TEXT_BOUNDARY_CHAR, &start, &end, text.Receive()));
370 ASSERT_STREQ(L"n", text);
373 ASSERT_EQ(S_FALSE, text1_obj->get_textAtOffset(
374 text1_len, IA2_TEXT_BOUNDARY_CHAR, &start, &end, text.Receive()));
375 ASSERT_EQ(text1_len, start);
376 ASSERT_EQ(text1_len, end);
379 ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
380 1, IA2_TEXT_BOUNDARY_WORD, &start, &end, text.Receive()));
383 ASSERT_STREQ(L"One", text);
386 ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
387 6, IA2_TEXT_BOUNDARY_WORD, &start, &end, text.Receive()));
390 ASSERT_STREQ(L"two", text);
393 ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
394 text1_len, IA2_TEXT_BOUNDARY_WORD, &start, &end, text.Receive()));
395 ASSERT_EQ(25, start);
397 ASSERT_STREQ(L"six.", text);
400 ASSERT_EQ(S_OK, text1_obj->get_textAtOffset(
401 1, IA2_TEXT_BOUNDARY_LINE, &start, &end, text.Receive()));
404 ASSERT_STREQ(L"One two three.\n", text);
408 text1_obj->get_text(0, IA2_TEXT_OFFSET_LENGTH, text.Receive()));
409 ASSERT_STREQ(L"One two three.\nFour five six.", text);
411 // Delete the manager and test that all BrowserAccessibility instances are
414 ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
417 TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
418 const std::string text1_name = "One two three.";
419 const std::string text2_name = " Four five six.";
421 AccessibilityNodeData text1;
423 text1.role = WebKit::WebAXRoleStaticText;
424 text1.state = 1 << WebKit::WebAXStateReadonly;
425 text1.SetName(text1_name);
427 AccessibilityNodeData text2;
429 text2.role = WebKit::WebAXRoleStaticText;
430 text2.state = 1 << WebKit::WebAXStateReadonly;
431 text2.SetName(text2_name);
433 AccessibilityNodeData root;
435 root.role = WebKit::WebAXRoleRootWebArea;
436 root.state = 1 << WebKit::WebAXStateReadonly;
437 root.child_ids.push_back(11);
438 root.child_ids.push_back(12);
440 CountedBrowserAccessibility::reset();
441 scoped_ptr<BrowserAccessibilityManager> manager(
442 BrowserAccessibilityManager::Create(
443 root, NULL, new CountedBrowserAccessibilityFactory()));
444 manager->UpdateNodesForTesting(root, text1, text2);
445 ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
447 BrowserAccessibilityWin* root_obj =
448 manager->GetRoot()->ToBrowserAccessibilityWin();
451 ASSERT_EQ(S_OK, root_obj->get_nCharacters(&text_len));
453 base::win::ScopedBstr text;
454 ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive()));
455 EXPECT_EQ(text1_name + text2_name, base::UTF16ToUTF8(string16(text)));
457 long hyperlink_count;
458 ASSERT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count));
459 EXPECT_EQ(0, hyperlink_count);
461 base::win::ScopedComPtr<IAccessibleHyperlink> hyperlink;
462 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(-1, hyperlink.Receive()));
463 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(0, hyperlink.Receive()));
464 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(28, hyperlink.Receive()));
465 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(29, hyperlink.Receive()));
467 long hyperlink_index;
468 EXPECT_EQ(E_FAIL, root_obj->get_hyperlinkIndex(0, &hyperlink_index));
469 EXPECT_EQ(-1, hyperlink_index);
470 EXPECT_EQ(E_FAIL, root_obj->get_hyperlinkIndex(28, &hyperlink_index));
471 EXPECT_EQ(-1, hyperlink_index);
472 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlinkIndex(-1, &hyperlink_index));
473 EXPECT_EQ(-1, hyperlink_index);
474 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlinkIndex(29, &hyperlink_index));
475 EXPECT_EQ(-1, hyperlink_index);
477 // Delete the manager and test that all BrowserAccessibility instances are
480 ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
483 TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
484 const std::string text1_name = "One two three.";
485 const std::string text2_name = " Four five six.";
486 const std::string button1_text_name = "red";
487 const std::string link1_text_name = "blue";
489 AccessibilityNodeData text1;
491 text1.role = WebKit::WebAXRoleStaticText;
492 text1.state = 1 << WebKit::WebAXStateReadonly;
493 text1.SetName(text1_name);
495 AccessibilityNodeData text2;
497 text2.role = WebKit::WebAXRoleStaticText;
498 text2.state = 1 << WebKit::WebAXStateReadonly;
499 text2.SetName(text2_name);
501 AccessibilityNodeData button1, button1_text;
503 button1_text.id = 15;
504 button1_text.SetName(button1_text_name);
505 button1.role = WebKit::WebAXRoleButton;
506 button1_text.role = WebKit::WebAXRoleStaticText;
507 button1.state = 1 << WebKit::WebAXStateReadonly;
508 button1_text.state = 1 << WebKit::WebAXStateReadonly;
509 button1.child_ids.push_back(15);
511 AccessibilityNodeData link1, link1_text;
514 link1_text.SetName(link1_text_name);
515 link1.role = WebKit::WebAXRoleLink;
516 link1_text.role = WebKit::WebAXRoleStaticText;
517 link1.state = 1 << WebKit::WebAXStateReadonly;
518 link1_text.state = 1 << WebKit::WebAXStateReadonly;
519 link1.child_ids.push_back(16);
521 AccessibilityNodeData root;
523 root.role = WebKit::WebAXRoleRootWebArea;
524 root.state = 1 << WebKit::WebAXStateReadonly;
525 root.child_ids.push_back(11);
526 root.child_ids.push_back(13);
527 root.child_ids.push_back(12);
528 root.child_ids.push_back(14);
530 CountedBrowserAccessibility::reset();
531 scoped_ptr<BrowserAccessibilityManager> manager(
532 BrowserAccessibilityManager::Create(
533 root, NULL, new CountedBrowserAccessibilityFactory()));
534 manager->UpdateNodesForTesting(root,
535 text1, button1, button1_text,
536 text2, link1, link1_text);
538 ASSERT_EQ(7, CountedBrowserAccessibility::num_instances());
540 BrowserAccessibilityWin* root_obj =
541 manager->GetRoot()->ToBrowserAccessibilityWin();
544 ASSERT_EQ(S_OK, root_obj->get_nCharacters(&text_len));
546 base::win::ScopedBstr text;
547 ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive()));
548 const std::string embed = base::UTF16ToUTF8(
549 BrowserAccessibilityWin::kEmbeddedCharacter);
550 EXPECT_EQ(text1_name + embed + text2_name + embed,
551 UTF16ToUTF8(string16(text)));
554 long hyperlink_count;
555 ASSERT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count));
556 EXPECT_EQ(2, hyperlink_count);
558 base::win::ScopedComPtr<IAccessibleHyperlink> hyperlink;
559 base::win::ScopedComPtr<IAccessibleText> hypertext;
560 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(-1, hyperlink.Receive()));
561 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(2, hyperlink.Receive()));
562 EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(28, hyperlink.Receive()));
564 EXPECT_EQ(S_OK, root_obj->get_hyperlink(0, hyperlink.Receive()));
566 hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive()));
567 EXPECT_EQ(S_OK, hypertext->get_text(0, 3, text.Receive()));
568 EXPECT_STREQ(button1_text_name.c_str(),
569 base::UTF16ToUTF8(string16(text)).c_str());
574 EXPECT_EQ(S_OK, root_obj->get_hyperlink(1, hyperlink.Receive()));
576 hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive()));
577 EXPECT_EQ(S_OK, hypertext->get_text(0, 4, text.Receive()));
578 EXPECT_STREQ(link1_text_name.c_str(),
579 base::UTF16ToUTF8(string16(text)).c_str());
584 long hyperlink_index;
585 EXPECT_EQ(E_FAIL, root_obj->get_hyperlinkIndex(0, &hyperlink_index));
586 EXPECT_EQ(-1, hyperlink_index);
587 EXPECT_EQ(E_FAIL, root_obj->get_hyperlinkIndex(28, &hyperlink_index));
588 EXPECT_EQ(-1, hyperlink_index);
589 EXPECT_EQ(S_OK, root_obj->get_hyperlinkIndex(14, &hyperlink_index));
590 EXPECT_EQ(0, hyperlink_index);
591 EXPECT_EQ(S_OK, root_obj->get_hyperlinkIndex(30, &hyperlink_index));
592 EXPECT_EQ(1, hyperlink_index);
594 // Delete the manager and test that all BrowserAccessibility instances are
597 ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
600 TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
601 // Try creating an empty document with busy state. Readonly is
602 // set automatically.
603 CountedBrowserAccessibility::reset();
604 const int32 busy_state = 1 << WebKit::WebAXStateBusy;
605 const int32 readonly_state = 1 << WebKit::WebAXStateReadonly;
606 const int32 enabled_state = 1 << WebKit::WebAXStateEnabled;
607 scoped_ptr<BrowserAccessibilityManager> manager(
608 new BrowserAccessibilityManagerWin(
611 BrowserAccessibilityManagerWin::GetEmptyDocument(),
613 new CountedBrowserAccessibilityFactory()));
615 // Verify the root is as we expect by default.
616 BrowserAccessibility* root = manager->GetRoot();
617 EXPECT_EQ(0, root->renderer_id());
618 EXPECT_EQ(WebKit::WebAXRoleRootWebArea, root->role());
619 EXPECT_EQ(busy_state | readonly_state | enabled_state, root->state());
621 // Tree with a child textfield.
622 AccessibilityNodeData tree1_1;
624 tree1_1.role = WebKit::WebAXRoleRootWebArea;
625 tree1_1.child_ids.push_back(2);
627 AccessibilityNodeData tree1_2;
629 tree1_2.role = WebKit::WebAXRoleTextField;
631 // Process a load complete.
632 std::vector<AccessibilityHostMsg_EventParams> params;
633 params.push_back(AccessibilityHostMsg_EventParams());
634 AccessibilityHostMsg_EventParams* msg = ¶ms[0];
635 msg->event_type = WebKit::WebAXEventLoadComplete;
636 msg->nodes.push_back(tree1_1);
637 msg->nodes.push_back(tree1_2);
638 msg->id = tree1_1.id;
639 manager->OnAccessibilityEvents(params);
641 // Save for later comparison.
642 BrowserAccessibility* acc1_2 = manager->GetFromRendererID(2);
644 // Verify the root has changed.
645 EXPECT_NE(root, manager->GetRoot());
647 // And the proper child remains.
648 EXPECT_EQ(WebKit::WebAXRoleTextField, acc1_2->role());
649 EXPECT_EQ(2, acc1_2->renderer_id());
651 // Tree with a child button.
652 AccessibilityNodeData tree2_1;
654 tree2_1.role = WebKit::WebAXRoleRootWebArea;
655 tree2_1.child_ids.push_back(3);
657 AccessibilityNodeData tree2_2;
659 tree2_2.role = WebKit::WebAXRoleButton;
662 msg->nodes.push_back(tree2_1);
663 msg->nodes.push_back(tree2_2);
664 msg->id = tree2_1.id;
666 // Fire another load complete.
667 manager->OnAccessibilityEvents(params);
669 BrowserAccessibility* acc2_2 = manager->GetFromRendererID(3);
671 // Verify the root has changed.
672 EXPECT_NE(root, manager->GetRoot());
674 // And the new child exists.
675 EXPECT_EQ(WebKit::WebAXRoleButton, acc2_2->role());
676 EXPECT_EQ(3, acc2_2->renderer_id());
678 // Ensure we properly cleaned up.
680 ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
683 } // namespace content