| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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 "base/string16.h" | |
| 6 #include "base/utf_string_conversions.h" | |
| 7 #include "content/browser/accessibility/browser_accessibility.h" | |
| 8 #include "content/browser/accessibility/browser_accessibility_manager.h" | |
| 9 #include "content/common/view_messages.h" | |
| 10 #include "testing/gtest/include/gtest/gtest.h" | |
| 11 #include "webkit/glue/webaccessibility.h" | |
| 12 | |
| 13 using webkit_glue::WebAccessibility; | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 // Subclass of BrowserAccessibility that counts the number of instances. | |
| 18 class CountedBrowserAccessibility : public BrowserAccessibility { | |
| 19 public: | |
| 20 CountedBrowserAccessibility() { | |
| 21 global_obj_count_++; | |
| 22 native_ref_count_ = 1; | |
| 23 } | |
| 24 virtual ~CountedBrowserAccessibility() { | |
| 25 global_obj_count_--; | |
| 26 } | |
| 27 | |
| 28 virtual void NativeAddReference() OVERRIDE { | |
| 29 native_ref_count_++; | |
| 30 } | |
| 31 | |
| 32 virtual void NativeReleaseReference() OVERRIDE { | |
| 33 native_ref_count_--; | |
| 34 if (native_ref_count_ == 0) | |
| 35 delete this; | |
| 36 } | |
| 37 | |
| 38 int native_ref_count_; | |
| 39 static int global_obj_count_; | |
| 40 }; | |
| 41 | |
| 42 int CountedBrowserAccessibility::global_obj_count_ = 0; | |
| 43 | |
| 44 // Factory that creates a CountedBrowserAccessibility. | |
| 45 class CountedBrowserAccessibilityFactory | |
| 46 : public BrowserAccessibilityFactory { | |
| 47 public: | |
| 48 virtual ~CountedBrowserAccessibilityFactory() {} | |
| 49 virtual BrowserAccessibility* Create() { | |
| 50 return new CountedBrowserAccessibility(); | |
| 51 } | |
| 52 }; | |
| 53 | |
| 54 } // anonymous namespace | |
| 55 | |
| 56 TEST(BrowserAccessibilityManagerTest, TestNoLeaks) { | |
| 57 // Create WebAccessibility objects for a simple document tree, | |
| 58 // representing the accessibility information used to initialize | |
| 59 // BrowserAccessibilityManager. | |
| 60 WebAccessibility button; | |
| 61 button.id = 2; | |
| 62 button.name = UTF8ToUTF16("Button"); | |
| 63 button.role = WebAccessibility::ROLE_BUTTON; | |
| 64 button.state = 0; | |
| 65 | |
| 66 WebAccessibility checkbox; | |
| 67 checkbox.id = 3; | |
| 68 checkbox.name = UTF8ToUTF16("Checkbox"); | |
| 69 checkbox.role = WebAccessibility::ROLE_CHECKBOX; | |
| 70 checkbox.state = 0; | |
| 71 | |
| 72 WebAccessibility root; | |
| 73 root.id = 1; | |
| 74 root.name = UTF8ToUTF16("Document"); | |
| 75 root.role = WebAccessibility::ROLE_DOCUMENT; | |
| 76 root.state = 0; | |
| 77 root.children.push_back(button); | |
| 78 root.children.push_back(checkbox); | |
| 79 | |
| 80 // Construct a BrowserAccessibilityManager with this WebAccessibility tree | |
| 81 // and a factory for an instance-counting BrowserAccessibility, and ensure | |
| 82 // that exactly 3 instances were created. Note that the manager takes | |
| 83 // ownership of the factory. | |
| 84 CountedBrowserAccessibility::global_obj_count_ = 0; | |
| 85 BrowserAccessibilityManager* manager = | |
| 86 BrowserAccessibilityManager::Create( | |
| 87 NULL, | |
| 88 root, | |
| 89 NULL, | |
| 90 new CountedBrowserAccessibilityFactory()); | |
| 91 | |
| 92 ASSERT_EQ(3, CountedBrowserAccessibility::global_obj_count_); | |
| 93 | |
| 94 // Delete the manager and test that all 3 instances are deleted. | |
| 95 delete manager; | |
| 96 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); | |
| 97 | |
| 98 // Construct a manager again, and this time save references to two of | |
| 99 // the three nodes in the tree. | |
| 100 manager = | |
| 101 BrowserAccessibilityManager::Create( | |
| 102 NULL, | |
| 103 root, | |
| 104 NULL, | |
| 105 new CountedBrowserAccessibilityFactory()); | |
| 106 ASSERT_EQ(3, CountedBrowserAccessibility::global_obj_count_); | |
| 107 | |
| 108 CountedBrowserAccessibility* root_accessible = | |
| 109 static_cast<CountedBrowserAccessibility*>(manager->GetRoot()); | |
| 110 root_accessible->NativeAddReference(); | |
| 111 CountedBrowserAccessibility* child1_accessible = | |
| 112 static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(1)); | |
| 113 child1_accessible->NativeAddReference(); | |
| 114 | |
| 115 // Now delete the manager, and only one of the three nodes in the tree | |
| 116 // should be released. | |
| 117 delete manager; | |
| 118 ASSERT_EQ(2, CountedBrowserAccessibility::global_obj_count_); | |
| 119 | |
| 120 // Release each of our references and make sure that each one results in | |
| 121 // the instance being deleted as its reference count hits zero. | |
| 122 root_accessible->NativeReleaseReference(); | |
| 123 ASSERT_EQ(1, CountedBrowserAccessibility::global_obj_count_); | |
| 124 child1_accessible->NativeReleaseReference(); | |
| 125 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); | |
| 126 } | |
| 127 | |
| 128 TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects) { | |
| 129 // Make sure that changes to a subtree reuse as many objects as possible. | |
| 130 | |
| 131 // Tree 1: | |
| 132 // | |
| 133 // root | |
| 134 // child1 | |
| 135 // child2 | |
| 136 // child3 | |
| 137 | |
| 138 WebAccessibility tree1_child1; | |
| 139 tree1_child1.id = 2; | |
| 140 tree1_child1.name = UTF8ToUTF16("Child1"); | |
| 141 tree1_child1.role = WebAccessibility::ROLE_BUTTON; | |
| 142 tree1_child1.state = 0; | |
| 143 | |
| 144 WebAccessibility tree1_child2; | |
| 145 tree1_child2.id = 3; | |
| 146 tree1_child2.name = UTF8ToUTF16("Child2"); | |
| 147 tree1_child2.role = WebAccessibility::ROLE_BUTTON; | |
| 148 tree1_child2.state = 0; | |
| 149 | |
| 150 WebAccessibility tree1_child3; | |
| 151 tree1_child3.id = 4; | |
| 152 tree1_child3.name = UTF8ToUTF16("Child3"); | |
| 153 tree1_child3.role = WebAccessibility::ROLE_BUTTON; | |
| 154 tree1_child3.state = 0; | |
| 155 | |
| 156 WebAccessibility tree1_root; | |
| 157 tree1_root.id = 1; | |
| 158 tree1_root.name = UTF8ToUTF16("Document"); | |
| 159 tree1_root.role = WebAccessibility::ROLE_DOCUMENT; | |
| 160 tree1_root.state = 0; | |
| 161 tree1_root.children.push_back(tree1_child1); | |
| 162 tree1_root.children.push_back(tree1_child2); | |
| 163 tree1_root.children.push_back(tree1_child3); | |
| 164 | |
| 165 // Tree 2: | |
| 166 // | |
| 167 // root | |
| 168 // child0 <-- inserted | |
| 169 // child1 | |
| 170 // child2 | |
| 171 // <-- child3 deleted | |
| 172 | |
| 173 WebAccessibility tree2_child0; | |
| 174 tree2_child0.id = 5; | |
| 175 tree2_child0.name = UTF8ToUTF16("Child0"); | |
| 176 tree2_child0.role = WebAccessibility::ROLE_BUTTON; | |
| 177 tree2_child0.state = 0; | |
| 178 | |
| 179 WebAccessibility tree2_child1; | |
| 180 tree2_child1.id = 2; | |
| 181 tree2_child1.name = UTF8ToUTF16("Child1"); | |
| 182 tree2_child1.role = WebAccessibility::ROLE_BUTTON; | |
| 183 tree2_child1.state = 0; | |
| 184 | |
| 185 WebAccessibility tree2_child2; | |
| 186 tree2_child2.id = 3; | |
| 187 tree2_child2.name = UTF8ToUTF16("Child2"); | |
| 188 tree2_child2.role = WebAccessibility::ROLE_BUTTON; | |
| 189 tree2_child2.state = 0; | |
| 190 | |
| 191 WebAccessibility tree2_root; | |
| 192 tree2_root.id = 1; | |
| 193 tree2_root.name = UTF8ToUTF16("DocumentChanged"); | |
| 194 tree2_root.role = WebAccessibility::ROLE_DOCUMENT; | |
| 195 tree2_root.state = 0; | |
| 196 tree2_root.children.push_back(tree2_child0); | |
| 197 tree2_root.children.push_back(tree2_child1); | |
| 198 tree2_root.children.push_back(tree2_child2); | |
| 199 | |
| 200 // Construct a BrowserAccessibilityManager with tree1. | |
| 201 CountedBrowserAccessibility::global_obj_count_ = 0; | |
| 202 BrowserAccessibilityManager* manager = | |
| 203 BrowserAccessibilityManager::Create( | |
| 204 NULL, | |
| 205 tree1_root, | |
| 206 NULL, | |
| 207 new CountedBrowserAccessibilityFactory()); | |
| 208 ASSERT_EQ(4, CountedBrowserAccessibility::global_obj_count_); | |
| 209 | |
| 210 // Save references to all of the objects. | |
| 211 CountedBrowserAccessibility* root_accessible = | |
| 212 static_cast<CountedBrowserAccessibility*>(manager->GetRoot()); | |
| 213 root_accessible->NativeAddReference(); | |
| 214 CountedBrowserAccessibility* child1_accessible = | |
| 215 static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(0)); | |
| 216 child1_accessible->NativeAddReference(); | |
| 217 CountedBrowserAccessibility* child2_accessible = | |
| 218 static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(1)); | |
| 219 child2_accessible->NativeAddReference(); | |
| 220 CountedBrowserAccessibility* child3_accessible = | |
| 221 static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(2)); | |
| 222 child3_accessible->NativeAddReference(); | |
| 223 | |
| 224 // Check the index in parent. | |
| 225 EXPECT_EQ(0, child1_accessible->index_in_parent()); | |
| 226 EXPECT_EQ(1, child2_accessible->index_in_parent()); | |
| 227 EXPECT_EQ(2, child3_accessible->index_in_parent()); | |
| 228 | |
| 229 // Process a notification containing the changed subtree. | |
| 230 std::vector<ViewHostMsg_AccessibilityNotification_Params> params; | |
| 231 params.push_back(ViewHostMsg_AccessibilityNotification_Params()); | |
| 232 ViewHostMsg_AccessibilityNotification_Params* msg = ¶ms[0]; | |
| 233 msg->notification_type = ViewHostMsg_AccEvent::CHILDREN_CHANGED; | |
| 234 msg->acc_tree = tree2_root; | |
| 235 msg->includes_children = true; | |
| 236 msg->id = tree2_root.id; | |
| 237 manager->OnAccessibilityNotifications(params); | |
| 238 | |
| 239 // There should be 5 objects now: the 4 from the new tree, plus the | |
| 240 // reference to child3 we kept. | |
| 241 EXPECT_EQ(5, CountedBrowserAccessibility::global_obj_count_); | |
| 242 | |
| 243 // Check that our references to the root, child1, and child2 are still valid, | |
| 244 // but that the reference to child3 is now invalid. | |
| 245 EXPECT_TRUE(root_accessible->instance_active()); | |
| 246 EXPECT_TRUE(child1_accessible->instance_active()); | |
| 247 EXPECT_TRUE(child2_accessible->instance_active()); | |
| 248 EXPECT_FALSE(child3_accessible->instance_active()); | |
| 249 | |
| 250 // Check that the index in parent has been updated. | |
| 251 EXPECT_EQ(1, child1_accessible->index_in_parent()); | |
| 252 EXPECT_EQ(2, child2_accessible->index_in_parent()); | |
| 253 | |
| 254 // Release our references. The object count should only decrease by 1 | |
| 255 // for child3. | |
| 256 root_accessible->NativeReleaseReference(); | |
| 257 child1_accessible->NativeReleaseReference(); | |
| 258 child2_accessible->NativeReleaseReference(); | |
| 259 child3_accessible->NativeReleaseReference(); | |
| 260 | |
| 261 EXPECT_EQ(4, CountedBrowserAccessibility::global_obj_count_); | |
| 262 | |
| 263 // Delete the manager and make sure all memory is cleaned up. | |
| 264 delete manager; | |
| 265 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); | |
| 266 } | |
| 267 | |
| 268 TEST(BrowserAccessibilityManagerTest, TestReuseBrowserAccessibilityObjects2) { | |
| 269 // Similar to the test above, but with a more complicated tree. | |
| 270 | |
| 271 // Tree 1: | |
| 272 // | |
| 273 // root | |
| 274 // container | |
| 275 // child1 | |
| 276 // grandchild1 | |
| 277 // child2 | |
| 278 // grandchild2 | |
| 279 // child3 | |
| 280 // grandchild3 | |
| 281 | |
| 282 WebAccessibility tree1_grandchild1; | |
| 283 tree1_grandchild1.id = 4; | |
| 284 tree1_grandchild1.name = UTF8ToUTF16("GrandChild1"); | |
| 285 tree1_grandchild1.role = WebAccessibility::ROLE_BUTTON; | |
| 286 tree1_grandchild1.state = 0; | |
| 287 | |
| 288 WebAccessibility tree1_child1; | |
| 289 tree1_child1.id = 3; | |
| 290 tree1_child1.name = UTF8ToUTF16("Child1"); | |
| 291 tree1_child1.role = WebAccessibility::ROLE_BUTTON; | |
| 292 tree1_child1.state = 0; | |
| 293 tree1_child1.children.push_back(tree1_grandchild1); | |
| 294 | |
| 295 WebAccessibility tree1_grandchild2; | |
| 296 tree1_grandchild2.id = 6; | |
| 297 tree1_grandchild2.name = UTF8ToUTF16("GrandChild1"); | |
| 298 tree1_grandchild2.role = WebAccessibility::ROLE_BUTTON; | |
| 299 tree1_grandchild2.state = 0; | |
| 300 | |
| 301 WebAccessibility tree1_child2; | |
| 302 tree1_child2.id = 5; | |
| 303 tree1_child2.name = UTF8ToUTF16("Child2"); | |
| 304 tree1_child2.role = WebAccessibility::ROLE_BUTTON; | |
| 305 tree1_child2.state = 0; | |
| 306 tree1_child2.children.push_back(tree1_grandchild2); | |
| 307 | |
| 308 WebAccessibility tree1_grandchild3; | |
| 309 tree1_grandchild3.id = 8; | |
| 310 tree1_grandchild3.name = UTF8ToUTF16("GrandChild3"); | |
| 311 tree1_grandchild3.role = WebAccessibility::ROLE_BUTTON; | |
| 312 tree1_grandchild3.state = 0; | |
| 313 | |
| 314 WebAccessibility tree1_child3; | |
| 315 tree1_child3.id = 7; | |
| 316 tree1_child3.name = UTF8ToUTF16("Child3"); | |
| 317 tree1_child3.role = WebAccessibility::ROLE_BUTTON; | |
| 318 tree1_child3.state = 0; | |
| 319 tree1_child3.children.push_back(tree1_grandchild3); | |
| 320 | |
| 321 WebAccessibility tree1_container; | |
| 322 tree1_container.id = 2; | |
| 323 tree1_container.name = UTF8ToUTF16("Container"); | |
| 324 tree1_container.role = WebAccessibility::ROLE_GROUP; | |
| 325 tree1_container.state = 0; | |
| 326 tree1_container.children.push_back(tree1_child1); | |
| 327 tree1_container.children.push_back(tree1_child2); | |
| 328 tree1_container.children.push_back(tree1_child3); | |
| 329 | |
| 330 WebAccessibility tree1_root; | |
| 331 tree1_root.id = 1; | |
| 332 tree1_root.name = UTF8ToUTF16("Document"); | |
| 333 tree1_root.role = WebAccessibility::ROLE_DOCUMENT; | |
| 334 tree1_root.state = 0; | |
| 335 tree1_root.children.push_back(tree1_container); | |
| 336 | |
| 337 // Tree 2: | |
| 338 // | |
| 339 // root | |
| 340 // container | |
| 341 // child0 <-- inserted | |
| 342 // grandchild0 <-- | |
| 343 // child1 | |
| 344 // grandchild1 | |
| 345 // child2 | |
| 346 // grandchild2 | |
| 347 // <-- child3 (and grandchild3) deleted | |
| 348 | |
| 349 WebAccessibility tree2_grandchild0; | |
| 350 tree2_grandchild0.id = 9; | |
| 351 tree2_grandchild0.name = UTF8ToUTF16("GrandChild0"); | |
| 352 tree2_grandchild0.role = WebAccessibility::ROLE_BUTTON; | |
| 353 tree2_grandchild0.state = 0; | |
| 354 | |
| 355 WebAccessibility tree2_child0; | |
| 356 tree2_child0.id = 10; | |
| 357 tree2_child0.name = UTF8ToUTF16("Child0"); | |
| 358 tree2_child0.role = WebAccessibility::ROLE_BUTTON; | |
| 359 tree2_child0.state = 0; | |
| 360 tree2_child0.children.push_back(tree2_grandchild0); | |
| 361 | |
| 362 WebAccessibility tree2_grandchild1; | |
| 363 tree2_grandchild1.id = 4; | |
| 364 tree2_grandchild1.name = UTF8ToUTF16("GrandChild1"); | |
| 365 tree2_grandchild1.role = WebAccessibility::ROLE_BUTTON; | |
| 366 tree2_grandchild1.state = 0; | |
| 367 | |
| 368 WebAccessibility tree2_child1; | |
| 369 tree2_child1.id = 3; | |
| 370 tree2_child1.name = UTF8ToUTF16("Child1"); | |
| 371 tree2_child1.role = WebAccessibility::ROLE_BUTTON; | |
| 372 tree2_child1.state = 0; | |
| 373 tree2_child1.children.push_back(tree2_grandchild1); | |
| 374 | |
| 375 WebAccessibility tree2_grandchild2; | |
| 376 tree2_grandchild2.id = 6; | |
| 377 tree2_grandchild2.name = UTF8ToUTF16("GrandChild1"); | |
| 378 tree2_grandchild2.role = WebAccessibility::ROLE_BUTTON; | |
| 379 tree2_grandchild2.state = 0; | |
| 380 | |
| 381 WebAccessibility tree2_child2; | |
| 382 tree2_child2.id = 5; | |
| 383 tree2_child2.name = UTF8ToUTF16("Child2"); | |
| 384 tree2_child2.role = WebAccessibility::ROLE_BUTTON; | |
| 385 tree2_child2.state = 0; | |
| 386 tree2_child2.children.push_back(tree2_grandchild2); | |
| 387 | |
| 388 WebAccessibility tree2_container; | |
| 389 tree2_container.id = 2; | |
| 390 tree2_container.name = UTF8ToUTF16("Container"); | |
| 391 tree2_container.role = WebAccessibility::ROLE_GROUP; | |
| 392 tree2_container.state = 0; | |
| 393 tree2_container.children.push_back(tree2_child0); | |
| 394 tree2_container.children.push_back(tree2_child1); | |
| 395 tree2_container.children.push_back(tree2_child2); | |
| 396 | |
| 397 WebAccessibility tree2_root; | |
| 398 tree2_root.id = 1; | |
| 399 tree2_root.name = UTF8ToUTF16("Document"); | |
| 400 tree2_root.role = WebAccessibility::ROLE_DOCUMENT; | |
| 401 tree2_root.state = 0; | |
| 402 tree2_root.children.push_back(tree2_container); | |
| 403 | |
| 404 // Construct a BrowserAccessibilityManager with tree1. | |
| 405 CountedBrowserAccessibility::global_obj_count_ = 0; | |
| 406 BrowserAccessibilityManager* manager = | |
| 407 BrowserAccessibilityManager::Create( | |
| 408 NULL, | |
| 409 tree1_root, | |
| 410 NULL, | |
| 411 new CountedBrowserAccessibilityFactory()); | |
| 412 ASSERT_EQ(8, CountedBrowserAccessibility::global_obj_count_); | |
| 413 | |
| 414 // Save references to some objects. | |
| 415 CountedBrowserAccessibility* root_accessible = | |
| 416 static_cast<CountedBrowserAccessibility*>(manager->GetRoot()); | |
| 417 root_accessible->NativeAddReference(); | |
| 418 CountedBrowserAccessibility* container_accessible = | |
| 419 static_cast<CountedBrowserAccessibility*>(root_accessible->GetChild(0)); | |
| 420 container_accessible->NativeAddReference(); | |
| 421 CountedBrowserAccessibility* child2_accessible = | |
| 422 static_cast<CountedBrowserAccessibility*>( | |
| 423 container_accessible->GetChild(1)); | |
| 424 child2_accessible->NativeAddReference(); | |
| 425 CountedBrowserAccessibility* child3_accessible = | |
| 426 static_cast<CountedBrowserAccessibility*>( | |
| 427 container_accessible->GetChild(2)); | |
| 428 child3_accessible->NativeAddReference(); | |
| 429 | |
| 430 // Check the index in parent. | |
| 431 EXPECT_EQ(1, child2_accessible->index_in_parent()); | |
| 432 EXPECT_EQ(2, child3_accessible->index_in_parent()); | |
| 433 | |
| 434 // Process a notification containing the changed subtree rooted at | |
| 435 // the container. | |
| 436 std::vector<ViewHostMsg_AccessibilityNotification_Params> params; | |
| 437 params.push_back(ViewHostMsg_AccessibilityNotification_Params()); | |
| 438 ViewHostMsg_AccessibilityNotification_Params* msg = ¶ms[0]; | |
| 439 msg->notification_type = ViewHostMsg_AccEvent::CHILDREN_CHANGED; | |
| 440 msg->acc_tree = tree2_container; | |
| 441 msg->includes_children = true; | |
| 442 msg->id = tree2_container.id; | |
| 443 manager->OnAccessibilityNotifications(params); | |
| 444 | |
| 445 // There should be 9 objects now: the 8 from the new tree, plus the | |
| 446 // reference to child3 we kept. | |
| 447 EXPECT_EQ(9, CountedBrowserAccessibility::global_obj_count_); | |
| 448 | |
| 449 // Check that our references to the root and container and child2 are | |
| 450 // still valid, but that the reference to child3 is now invalid. | |
| 451 EXPECT_TRUE(root_accessible->instance_active()); | |
| 452 EXPECT_TRUE(container_accessible->instance_active()); | |
| 453 EXPECT_TRUE(child2_accessible->instance_active()); | |
| 454 EXPECT_FALSE(child3_accessible->instance_active()); | |
| 455 | |
| 456 // Ensure that we retain the parent of the detached subtree. | |
| 457 EXPECT_EQ(root_accessible, container_accessible->parent()); | |
| 458 EXPECT_EQ(0, container_accessible->index_in_parent()); | |
| 459 | |
| 460 // Check that the index in parent has been updated. | |
| 461 EXPECT_EQ(2, child2_accessible->index_in_parent()); | |
| 462 | |
| 463 // Release our references. The object count should only decrease by 1 | |
| 464 // for child3. | |
| 465 root_accessible->NativeReleaseReference(); | |
| 466 container_accessible->NativeReleaseReference(); | |
| 467 child2_accessible->NativeReleaseReference(); | |
| 468 child3_accessible->NativeReleaseReference(); | |
| 469 | |
| 470 EXPECT_EQ(8, CountedBrowserAccessibility::global_obj_count_); | |
| 471 | |
| 472 // Delete the manager and make sure all memory is cleaned up. | |
| 473 delete manager; | |
| 474 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); | |
| 475 } | |
| 476 | |
| 477 TEST(BrowserAccessibilityManagerTest, TestMoveChildUp) { | |
| 478 // Tree 1: | |
| 479 // | |
| 480 // 1 | |
| 481 // 2 | |
| 482 // 3 | |
| 483 // 4 | |
| 484 | |
| 485 WebAccessibility tree1_4; | |
| 486 tree1_4.id = 4; | |
| 487 tree1_4.state = 0; | |
| 488 | |
| 489 WebAccessibility tree1_3; | |
| 490 tree1_3.id = 3; | |
| 491 tree1_3.state = 0; | |
| 492 tree1_3.children.push_back(tree1_4); | |
| 493 | |
| 494 WebAccessibility tree1_2; | |
| 495 tree1_2.id = 2; | |
| 496 tree1_2.state = 0; | |
| 497 | |
| 498 WebAccessibility tree1_1; | |
| 499 tree1_1.id = 1; | |
| 500 tree1_1.state = 0; | |
| 501 tree1_1.children.push_back(tree1_2); | |
| 502 tree1_1.children.push_back(tree1_3); | |
| 503 | |
| 504 // Tree 2: | |
| 505 // | |
| 506 // 1 | |
| 507 // 4 <-- moves up a level and gains child | |
| 508 // 6 <-- new | |
| 509 // 5 <-- new | |
| 510 | |
| 511 WebAccessibility tree2_6; | |
| 512 tree2_6.id = 6; | |
| 513 tree2_6.state = 0; | |
| 514 | |
| 515 WebAccessibility tree2_5; | |
| 516 tree2_5.id = 5; | |
| 517 tree2_5.state = 0; | |
| 518 | |
| 519 WebAccessibility tree2_4; | |
| 520 tree2_4.id = 4; | |
| 521 tree2_4.state = 0; | |
| 522 tree2_4.children.push_back(tree2_6); | |
| 523 | |
| 524 WebAccessibility tree2_1; | |
| 525 tree2_1.id = 1; | |
| 526 tree2_1.state = 0; | |
| 527 tree2_1.children.push_back(tree2_4); | |
| 528 tree2_1.children.push_back(tree2_5); | |
| 529 | |
| 530 // Construct a BrowserAccessibilityManager with tree1. | |
| 531 CountedBrowserAccessibility::global_obj_count_ = 0; | |
| 532 BrowserAccessibilityManager* manager = | |
| 533 BrowserAccessibilityManager::Create( | |
| 534 NULL, | |
| 535 tree1_1, | |
| 536 NULL, | |
| 537 new CountedBrowserAccessibilityFactory()); | |
| 538 ASSERT_EQ(4, CountedBrowserAccessibility::global_obj_count_); | |
| 539 | |
| 540 // Process a notification containing the changed subtree. | |
| 541 std::vector<ViewHostMsg_AccessibilityNotification_Params> params; | |
| 542 params.push_back(ViewHostMsg_AccessibilityNotification_Params()); | |
| 543 ViewHostMsg_AccessibilityNotification_Params* msg = ¶ms[0]; | |
| 544 msg->notification_type = ViewHostMsg_AccEvent::CHILDREN_CHANGED; | |
| 545 msg->acc_tree = tree2_1; | |
| 546 msg->includes_children = true; | |
| 547 msg->id = tree2_1.id; | |
| 548 manager->OnAccessibilityNotifications(params); | |
| 549 | |
| 550 // There should be 4 objects now. | |
| 551 EXPECT_EQ(4, CountedBrowserAccessibility::global_obj_count_); | |
| 552 | |
| 553 // Delete the manager and make sure all memory is cleaned up. | |
| 554 delete manager; | |
| 555 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); | |
| 556 } | |
| 557 | |
| 558 TEST(BrowserAccessibilityManagerTest, TestCreateEmptyDocument) { | |
| 559 // Try creating an empty document with busy state. | |
| 560 scoped_ptr<BrowserAccessibilityManager> manager; | |
| 561 manager.reset(BrowserAccessibilityManager::CreateEmptyDocument( | |
| 562 NULL, | |
| 563 WebAccessibility::STATE_BUSY, | |
| 564 NULL, | |
| 565 new CountedBrowserAccessibilityFactory())); | |
| 566 | |
| 567 // Verify the root is as we expect by default. | |
| 568 BrowserAccessibility* root = manager->GetRoot(); | |
| 569 EXPECT_EQ(0, root->renderer_id()); | |
| 570 EXPECT_EQ(WebAccessibility::ROLE_ROOT_WEB_AREA, root->role()); | |
| 571 EXPECT_EQ(WebAccessibility::STATE_BUSY, root->state()); | |
| 572 | |
| 573 // Tree with a child textfield. | |
| 574 WebAccessibility tree1_1; | |
| 575 tree1_1.id = 1; | |
| 576 tree1_1.role = WebAccessibility::ROLE_ROOT_WEB_AREA; | |
| 577 | |
| 578 WebAccessibility tree1_2; | |
| 579 tree1_2.id = 2; | |
| 580 tree1_2.role = WebAccessibility::ROLE_TEXT_FIELD; | |
| 581 | |
| 582 tree1_1.children.push_back(tree1_2); | |
| 583 | |
| 584 // Process a load complete. | |
| 585 std::vector<ViewHostMsg_AccessibilityNotification_Params> params; | |
| 586 params.push_back(ViewHostMsg_AccessibilityNotification_Params()); | |
| 587 ViewHostMsg_AccessibilityNotification_Params* msg = ¶ms[0]; | |
| 588 msg->notification_type = ViewHostMsg_AccEvent::LOAD_COMPLETE; | |
| 589 msg->acc_tree = tree1_1; | |
| 590 msg->includes_children = true; | |
| 591 msg->id = tree1_1.id; | |
| 592 manager->OnAccessibilityNotifications(params); | |
| 593 | |
| 594 // Save for later comparison. | |
| 595 BrowserAccessibility* acc1_2 = manager->GetFromRendererID(2); | |
| 596 | |
| 597 // Verify the root has changed. | |
| 598 EXPECT_NE(root, manager->GetRoot()); | |
| 599 | |
| 600 // And the proper child remains. | |
| 601 EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, acc1_2->role()); | |
| 602 EXPECT_EQ(2, acc1_2->renderer_id()); | |
| 603 | |
| 604 // Tree with a child button. | |
| 605 WebAccessibility tree2_1; | |
| 606 tree2_1.id = 1; | |
| 607 tree2_1.role = WebAccessibility::ROLE_ROOT_WEB_AREA; | |
| 608 | |
| 609 WebAccessibility tree2_2; | |
| 610 tree2_2.id = 3; | |
| 611 tree2_2.role = WebAccessibility::ROLE_BUTTON; | |
| 612 | |
| 613 tree2_1.children.push_back(tree2_2); | |
| 614 | |
| 615 msg->acc_tree = tree2_1; | |
| 616 msg->includes_children = true; | |
| 617 msg->id = tree2_1.id; | |
| 618 | |
| 619 // Fire another load complete. | |
| 620 manager->OnAccessibilityNotifications(params); | |
| 621 | |
| 622 BrowserAccessibility* acc2_2 = manager->GetFromRendererID(3); | |
| 623 | |
| 624 // Verify the root has changed. | |
| 625 EXPECT_NE(root, manager->GetRoot()); | |
| 626 | |
| 627 // And the new child exists. | |
| 628 EXPECT_EQ(WebAccessibility::ROLE_BUTTON, acc2_2->role()); | |
| 629 EXPECT_EQ(3, acc2_2->renderer_id()); | |
| 630 | |
| 631 // Ensure we properly cleaned up. | |
| 632 manager.reset(); | |
| 633 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); | |
| 634 } | |
| OLD | NEW |