OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/scoped_ptr.h" | 5 #include "base/scoped_ptr.h" |
| 6 #include "base/scoped_comptr_win.h" |
6 #include "chrome/browser/browser_accessibility_manager_win.h" | 7 #include "chrome/browser/browser_accessibility_manager_win.h" |
7 #include "chrome/browser/browser_accessibility_win.h" | 8 #include "chrome/browser/browser_accessibility_win.h" |
8 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
9 | 10 |
10 using webkit_glue::WebAccessibility; | 11 using webkit_glue::WebAccessibility; |
11 | 12 |
12 // Subclass of BrowserAccessibility that counts the number of instances. | 13 // Subclass of BrowserAccessibility that counts the number of instances. |
13 class CountedBrowserAccessibility : public BrowserAccessibility { | 14 class CountedBrowserAccessibility : public BrowserAccessibility { |
14 public: | 15 public: |
15 CountedBrowserAccessibility() { global_obj_count_++; } | 16 CountedBrowserAccessibility() { global_obj_count_++; } |
16 virtual ~CountedBrowserAccessibility() { global_obj_count_--; } | 17 virtual ~CountedBrowserAccessibility() { global_obj_count_--; } |
17 static int global_obj_count_; | 18 static int global_obj_count_; |
18 }; | 19 }; |
19 | 20 |
20 int CountedBrowserAccessibility::global_obj_count_ = 0; | 21 int CountedBrowserAccessibility::global_obj_count_ = 0; |
21 | 22 |
22 // Factory that creates a CountedBrowserAccessibility. | 23 // Factory that creates a CountedBrowserAccessibility. |
23 class CountedBrowserAccessibilityFactory : public BrowserAccessibilityFactory { | 24 class CountedBrowserAccessibilityFactory : public BrowserAccessibilityFactory { |
24 public: | 25 public: |
25 virtual ~CountedBrowserAccessibilityFactory() {} | 26 virtual ~CountedBrowserAccessibilityFactory() {} |
26 virtual BrowserAccessibility* Create() { | 27 virtual BrowserAccessibility* Create() { |
27 CComObject<CountedBrowserAccessibility>* instance; | 28 CComObject<CountedBrowserAccessibility>* instance; |
28 HRESULT hr = CComObject<CountedBrowserAccessibility>::CreateInstance( | 29 HRESULT hr = CComObject<CountedBrowserAccessibility>::CreateInstance( |
29 &instance); | 30 &instance); |
30 DCHECK(SUCCEEDED(hr)); | 31 DCHECK(SUCCEEDED(hr)); |
31 return instance->NewReference(); | 32 return instance->NewReference(); |
32 } | 33 } |
33 }; | 34 }; |
34 | 35 |
| 36 VARIANT CreateI4Variant(LONG value) { |
| 37 VARIANT variant = {0}; |
| 38 |
| 39 V_VT(&variant) = VT_I4; |
| 40 V_I4(&variant) = value; |
| 41 |
| 42 return variant; |
| 43 } |
| 44 |
| 45 class BrowserAccessibilityTest : public testing::Test { |
| 46 protected: |
| 47 virtual void SetUp() { |
| 48 // ATL needs a pointer to a COM module. |
| 49 static CComModule module; |
| 50 _pAtlModule = &module; |
| 51 |
| 52 // Make sure COM is initialized for this thread; it's safe to call twice. |
| 53 ::CoInitialize(NULL); |
| 54 } |
| 55 |
| 56 virtual void TearDown() |
| 57 { |
| 58 ::CoUninitialize(); |
| 59 } |
| 60 }; |
| 61 |
35 // Test that BrowserAccessibilityManager correctly releases the tree of | 62 // Test that BrowserAccessibilityManager correctly releases the tree of |
36 // BrowserAccessibility instances upon delete. | 63 // BrowserAccessibility instances upon delete. |
37 TEST(BrowserAccessibilityTest, TestNoLeaks) { | 64 TEST_F(BrowserAccessibilityTest, TestNoLeaks) { |
38 // ATL needs a pointer to a COM module. | |
39 CComModule module; | |
40 _pAtlModule = &module; | |
41 // Make sure COM is initialized for this thread; it's safe to call twice. | |
42 ::CoInitialize(NULL); | |
43 | |
44 // Create WebAccessibility objects for a simple document tree, | 65 // Create WebAccessibility objects for a simple document tree, |
45 // representing the accessibility information used to initialize | 66 // representing the accessibility information used to initialize |
46 // BrowserAccessibilityManager. | 67 // BrowserAccessibilityManager. |
47 WebAccessibility button; | 68 WebAccessibility button; |
48 button.id = 2; | 69 button.id = 2; |
49 button.name = L"Button"; | 70 button.name = L"Button"; |
50 button.role = WebAccessibility::ROLE_BUTTON; | 71 button.role = WebAccessibility::ROLE_BUTTON; |
51 button.state = 0; | 72 button.state = 0; |
52 | 73 |
53 WebAccessibility checkbox; | 74 WebAccessibility checkbox; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 delete manager; | 123 delete manager; |
103 ASSERT_EQ(2, CountedBrowserAccessibility::global_obj_count_); | 124 ASSERT_EQ(2, CountedBrowserAccessibility::global_obj_count_); |
104 | 125 |
105 // Release each of our references and make sure that each one results in | 126 // Release each of our references and make sure that each one results in |
106 // the instance being deleted as its reference count hits zero. | 127 // the instance being deleted as its reference count hits zero. |
107 root_iaccessible->Release(); | 128 root_iaccessible->Release(); |
108 ASSERT_EQ(1, CountedBrowserAccessibility::global_obj_count_); | 129 ASSERT_EQ(1, CountedBrowserAccessibility::global_obj_count_); |
109 child1_iaccessible->Release(); | 130 child1_iaccessible->Release(); |
110 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); | 131 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); |
111 } | 132 } |
| 133 |
| 134 TEST_F(BrowserAccessibilityTest, TestChildrenChange) { |
| 135 // Create WebAccessibility objects for a simple document tree, |
| 136 // representing the accessibility information used to initialize |
| 137 // BrowserAccessibilityManager. |
| 138 WebAccessibility text; |
| 139 text.id = 2; |
| 140 text.role = WebAccessibility::ROLE_STATIC_TEXT; |
| 141 text.value = L"old text"; |
| 142 text.state = 0; |
| 143 |
| 144 WebAccessibility root; |
| 145 root.id = 1; |
| 146 root.name = L"Document"; |
| 147 root.role = WebAccessibility::ROLE_DOCUMENT; |
| 148 root.state = 0; |
| 149 root.children.push_back(text); |
| 150 |
| 151 // Construct a BrowserAccessibilityManager with this WebAccessibility tree |
| 152 // and a factory for an instance-counting BrowserAccessibility. |
| 153 CountedBrowserAccessibility::global_obj_count_ = 0; |
| 154 BrowserAccessibilityManager* manager = |
| 155 new BrowserAccessibilityManager( |
| 156 GetDesktopWindow(), root, NULL, |
| 157 new CountedBrowserAccessibilityFactory()); |
| 158 |
| 159 // Query for the text IAccessible and verify that it returns "old text" as its |
| 160 // value. |
| 161 ScopedComPtr<IDispatch> text_dispatch; |
| 162 HRESULT hr = manager->GetRoot()->get_accChild(CreateI4Variant(1), |
| 163 text_dispatch.Receive()); |
| 164 ASSERT_EQ(S_OK, hr); |
| 165 |
| 166 ScopedComPtr<IAccessible> text_accessible; |
| 167 hr = text_dispatch.QueryInterface(text_accessible.Receive()); |
| 168 ASSERT_EQ(S_OK, hr); |
| 169 |
| 170 CComBSTR value; |
| 171 hr = text_accessible->get_accValue(CreateI4Variant(CHILDID_SELF), &value); |
| 172 ASSERT_EQ(S_OK, hr); |
| 173 EXPECT_STREQ(L"old text", value.m_str); |
| 174 |
| 175 text_dispatch.Release(); |
| 176 text_accessible.Release(); |
| 177 |
| 178 // Notify the BrowserAccessibilityManager that the text child has changed. |
| 179 text.value = L"new text"; |
| 180 std::vector<WebAccessibility> acc_changes; |
| 181 acc_changes.push_back(text); |
| 182 manager->OnAccessibilityObjectChildrenChange(acc_changes); |
| 183 |
| 184 // Query for the text IAccessible and verify that it now returns "new text" |
| 185 // as its value. |
| 186 hr = manager->GetRoot()->get_accChild( |
| 187 CreateI4Variant(1), |
| 188 text_dispatch.Receive()); |
| 189 ASSERT_EQ(S_OK, hr); |
| 190 |
| 191 hr = text_dispatch.QueryInterface(text_accessible.Receive()); |
| 192 ASSERT_EQ(S_OK, hr); |
| 193 |
| 194 hr = text_accessible->get_accValue(CreateI4Variant(CHILDID_SELF), &value); |
| 195 ASSERT_EQ(S_OK, hr); |
| 196 EXPECT_STREQ(L"new text", value.m_str); |
| 197 |
| 198 text_dispatch.Release(); |
| 199 text_accessible.Release(); |
| 200 |
| 201 // Delete the manager and test that all BrowserAccessibility instances are |
| 202 // deleted. |
| 203 delete manager; |
| 204 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); |
| 205 } |
| 206 |
| 207 TEST_F(BrowserAccessibilityTest, TestChildrenChangeNoLeaks) { |
| 208 // Create WebAccessibility objects for a simple document tree, |
| 209 // representing the accessibility information used to initialize |
| 210 // BrowserAccessibilityManager. |
| 211 WebAccessibility text; |
| 212 text.id = 3; |
| 213 text.role = WebAccessibility::ROLE_STATIC_TEXT; |
| 214 text.state = 0; |
| 215 |
| 216 WebAccessibility div; |
| 217 div.id = 2; |
| 218 div.role = WebAccessibility::ROLE_GROUP; |
| 219 div.state = 0; |
| 220 |
| 221 div.children.push_back(text); |
| 222 text.id = 4; |
| 223 div.children.push_back(text); |
| 224 |
| 225 WebAccessibility root; |
| 226 root.id = 1; |
| 227 root.role = WebAccessibility::ROLE_DOCUMENT; |
| 228 root.state = 0; |
| 229 root.children.push_back(div); |
| 230 |
| 231 // Construct a BrowserAccessibilityManager with this WebAccessibility tree |
| 232 // and a factory for an instance-counting BrowserAccessibility and ensure |
| 233 // that exactly 4 instances were created. Note that the manager takes |
| 234 // ownership of the factory. |
| 235 CountedBrowserAccessibility::global_obj_count_ = 0; |
| 236 BrowserAccessibilityManager* manager = |
| 237 new BrowserAccessibilityManager( |
| 238 GetDesktopWindow(), root, NULL, |
| 239 new CountedBrowserAccessibilityFactory()); |
| 240 ASSERT_EQ(4, CountedBrowserAccessibility::global_obj_count_); |
| 241 |
| 242 // Notify the BrowserAccessibilityManager that the div node and its children |
| 243 // were removed and ensure that only one BrowserAccessibility instance exists. |
| 244 root.children.clear(); |
| 245 std::vector<WebAccessibility> acc_changes; |
| 246 acc_changes.push_back(root); |
| 247 manager->OnAccessibilityObjectChildrenChange(acc_changes); |
| 248 ASSERT_EQ(1, CountedBrowserAccessibility::global_obj_count_); |
| 249 |
| 250 // Delete the manager and test that all BrowserAccessibility instances are |
| 251 // deleted. |
| 252 delete manager; |
| 253 ASSERT_EQ(0, CountedBrowserAccessibility::global_obj_count_); |
| 254 } |
OLD | NEW |