OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 <vector> | 5 #include <vector> |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/sys_string_conversions.h" |
9 #include "base/win/scoped_bstr.h" | 9 #include "base/win/scoped_bstr.h" |
10 #include "base/win/scoped_comptr.h" | 10 #include "base/win/scoped_comptr.h" |
11 #include "base/win/scoped_variant.h" | 11 #include "base/win/scoped_variant.h" |
12 #include "content/browser/accessibility/accessibility_mode_helper.h" | 12 #include "content/browser/accessibility/accessibility_mode_helper.h" |
| 13 #include "content/browser/accessibility/accessibility_tree_formatter.h" |
13 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h
" | 14 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h
" |
14 #include "content/browser/renderer_host/render_view_host_impl.h" | 15 #include "content/browser/renderer_host/render_view_host_impl.h" |
15 #include "content/public/browser/notification_service.h" | 16 #include "content/public/browser/notification_service.h" |
16 #include "content/public/browser/notification_types.h" | 17 #include "content/public/browser/notification_types.h" |
17 #include "content/public/browser/render_frame_host.h" | 18 #include "content/public/browser/render_frame_host.h" |
18 #include "content/public/browser/render_widget_host_view.h" | 19 #include "content/public/browser/render_widget_host_view.h" |
19 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
20 #include "content/public/common/url_constants.h" | 21 #include "content/public/common/url_constants.h" |
21 #include "content/public/test/content_browser_test.h" | 22 #include "content/public/test/content_browser_test.h" |
22 #include "content/public/test/content_browser_test_utils.h" | 23 #include "content/public/test/content_browser_test_utils.h" |
23 #include "content/shell/browser/shell.h" | 24 #include "content/shell/browser/shell.h" |
24 #include "content/test/accessibility_browser_test_utils.h" | 25 #include "content/test/accessibility_browser_test_utils.h" |
| 26 #include "net/base/escape.h" |
25 #include "third_party/iaccessible2/ia2_api_all.h" | 27 #include "third_party/iaccessible2/ia2_api_all.h" |
26 #include "third_party/isimpledom/ISimpleDOMNode.h" | 28 #include "third_party/isimpledom/ISimpleDOMNode.h" |
27 #include "ui/aura/window.h" | 29 #include "ui/aura/window.h" |
28 #include "ui/aura/window_tree_host.h" | 30 #include "ui/aura/window_tree_host.h" |
29 | 31 |
30 namespace content { | 32 namespace content { |
31 | 33 |
32 namespace { | 34 namespace { |
33 | 35 |
34 // Helpers -------------------------------------------------------------------- | |
35 | 36 |
36 base::win::ScopedComPtr<IAccessible> GetAccessibleFromResultVariant( | 37 const char INPUT_CONTENTS[] = "Moz/5.0 (ST 6.x; WWW33) " |
| 38 "WebKit \"KHTML, like\"."; |
| 39 const char TEXTAREA_CONTENTS[] = "Moz/5.0 (ST 6.x; WWW33)\n" |
| 40 "WebKit \n\"KHTML, like\"."; |
| 41 const LONG CONTENTS_LENGTH = static_cast<LONG>( |
| 42 (sizeof(INPUT_CONTENTS) - 1) / sizeof(char)); |
| 43 |
| 44 |
| 45 // AccessibilityWinBrowserTest ------------------------------------------------ |
| 46 |
| 47 class AccessibilityWinBrowserTest : public ContentBrowserTest { |
| 48 public: |
| 49 AccessibilityWinBrowserTest(); |
| 50 virtual ~AccessibilityWinBrowserTest(); |
| 51 |
| 52 protected: |
| 53 class AccessibleChecker; |
| 54 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); |
| 55 IAccessible* GetRendererAccessible(); |
| 56 void ExecuteScript(const std::wstring& script); |
| 57 void SetUpInputField( |
| 58 base::win::ScopedComPtr<IAccessibleText>* input_text); |
| 59 void SetUpTextareaField( |
| 60 base::win::ScopedComPtr<IAccessibleText>* textarea_text); |
| 61 |
| 62 |
| 63 static base::win::ScopedComPtr<IAccessible> |
| 64 AccessibilityWinBrowserTest::GetAccessibleFromVariant( |
| 65 IAccessible* parent, |
| 66 VARIANT* var); |
| 67 static HRESULT QueryIAccessible2(IAccessible* accessible, |
| 68 IAccessible2** accessible2); |
| 69 static void FindNodeInAccessibilityTree(IAccessible* node, |
| 70 int32 expected_role, |
| 71 const std::wstring& expected_name, |
| 72 int32 depth, |
| 73 bool* found); |
| 74 static void CheckTextAtOffset( |
| 75 base::win::ScopedComPtr<IAccessibleText>& element, |
| 76 LONG offset, |
| 77 IA2TextBoundaryType boundary_type, |
| 78 LONG expected_start_offset, |
| 79 LONG expected_end_offset, |
| 80 const std::wstring& expected_text); |
| 81 static std::vector<base::win::ScopedVariant> GetAllAccessibleChildren( |
| 82 IAccessible* element); |
| 83 |
| 84 private: |
| 85 DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest); |
| 86 }; |
| 87 |
| 88 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() { |
| 89 } |
| 90 |
| 91 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() { |
| 92 } |
| 93 |
| 94 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml( |
| 95 const std::string& html) { |
| 96 AccessibilityNotificationWaiter waiter( |
| 97 shell(), AccessibilityModeComplete, |
| 98 ui::AX_EVENT_LOAD_COMPLETE); |
| 99 GURL html_data_url("data:text/html," + html); |
| 100 NavigateToURL(shell(), html_data_url); |
| 101 waiter.WaitForNotification(); |
| 102 } |
| 103 |
| 104 // Retrieve the MSAA client accessibility object for the Render Widget Host View |
| 105 // of the selected tab. |
| 106 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() { |
| 107 content::WebContents* web_contents = shell()->web_contents(); |
| 108 base::string16 contents; |
| 109 AccessibilityTreeFormatter* atf = AccessibilityTreeFormatter::Create( |
| 110 web_contents); |
| 111 atf->FormatAccessibilityTree(&contents); |
| 112 DLOG(INFO) << contents; |
| 113 delete atf; |
| 114 return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible(); |
| 115 } |
| 116 |
| 117 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) { |
| 118 shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script); |
| 119 } |
| 120 |
| 121 // Loads a page with an input text field and places sample text in it. Also, |
| 122 // places the caret on the last character. |
| 123 void AccessibilityWinBrowserTest::SetUpInputField( |
| 124 base::win::ScopedComPtr<IAccessibleText>* input_text) { |
| 125 ASSERT_NE(nullptr, input_text); |
| 126 LoadInitialAccessibilityTreeFromHtml(std::string("<!DOCTYPE html>" |
| 127 "<html><body><form>" |
| 128 "<label for='name'>Browser name:</label>" |
| 129 "<input type='text' id='name' name='name' value='") + |
| 130 net::EscapeQueryParamValue(INPUT_CONTENTS, false) + std::string( |
| 131 "'></form></body></html>")); |
| 132 |
| 133 // Retrieve the IAccessible interface for the web page. |
| 134 base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible()); |
| 135 std::vector<base::win::ScopedVariant> document_children = |
| 136 GetAllAccessibleChildren(document.get()); |
| 137 ASSERT_EQ(1, document_children.size()); |
| 138 |
| 139 base::win::ScopedComPtr<IAccessible2> form; |
| 140 HRESULT hr = QueryIAccessible2(GetAccessibleFromVariant( |
| 141 document.get(), document_children[0].AsInput()).get(), form.Receive()); |
| 142 ASSERT_EQ(S_OK, hr); |
| 143 std::vector<base::win::ScopedVariant> form_children = |
| 144 GetAllAccessibleChildren(form.get()); |
| 145 ASSERT_EQ(2, form_children.size()); |
| 146 |
| 147 // Find the input text field. |
| 148 base::win::ScopedComPtr<IAccessible2> input; |
| 149 hr = QueryIAccessible2(GetAccessibleFromVariant( |
| 150 form.get(), form_children[1].AsInput()).get(), input.Receive()); |
| 151 ASSERT_EQ(S_OK, hr); |
| 152 LONG input_role = 0; |
| 153 hr = input->role(&input_role); |
| 154 ASSERT_EQ(S_OK, hr); |
| 155 ASSERT_EQ(ROLE_SYSTEM_TEXT, input_role); |
| 156 |
| 157 // Retrieve the IAccessibleText interface for the field. |
| 158 hr = input.QueryInterface(input_text->Receive()); |
| 159 ASSERT_EQ(S_OK, hr); |
| 160 |
| 161 // Set the caret on the last character. |
| 162 LONG caret_offset = CONTENTS_LENGTH - 1; |
| 163 hr = (*input_text)->setCaretOffset(caret_offset); |
| 164 ASSERT_EQ(S_OK, hr); |
| 165 } |
| 166 |
| 167 // Loads a page with a textarea text field and places sample text in it. Also, |
| 168 // places the caret on the last character. |
| 169 void AccessibilityWinBrowserTest::SetUpTextareaField( |
| 170 base::win::ScopedComPtr<IAccessibleText>* textarea_text) { |
| 171 ASSERT_NE(nullptr, textarea_text); |
| 172 LoadInitialAccessibilityTreeFromHtml(std::string("<!DOCTYPE html>" |
| 173 "<textarea rows='3' cols='60'>") + |
| 174 net::EscapeQueryParamValue(TEXTAREA_CONTENTS, false) + std::string( |
| 175 "</textarea></body></html>")); |
| 176 |
| 177 // Retrieve the IAccessible interface for the web page. |
| 178 base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible()); |
| 179 std::vector<base::win::ScopedVariant> document_children = |
| 180 GetAllAccessibleChildren(document.get()); |
| 181 ASSERT_EQ(1, document_children.size()); |
| 182 |
| 183 base::win::ScopedComPtr<IAccessible2> section; |
| 184 hr = QueryIAccessible2(GetAccessibleFromVariant( |
| 185 document.get(), document_children[1].AsInput()).get(), section.Receive()); |
| 186 ASSERT_EQ(S_OK, hr); |
| 187 std::vector<base::win::ScopedVariant> section_children = |
| 188 GetAllAccessibleChildren(section.get()); |
| 189 ASSERT_EQ(1, section_children.size()); |
| 190 |
| 191 // Find the textarea text field. |
| 192 base::win::ScopedComPtr<IAccessible2> textarea; |
| 193 hr = QueryIAccessible2(GetAccessibleFromVariant( |
| 194 section.get(), section_children[0].AsInput()).get(), textarea.Receive()); |
| 195 ASSERT_EQ(S_OK, hr); |
| 196 LONG textarea_role = 0; |
| 197 hr = textarea->role(&textarea_role); |
| 198 ASSERT_EQ(S_OK, hr); |
| 199 ASSERT_EQ(ROLE_SYSTEM_TEXT, input_role); |
| 200 |
| 201 // Retrieve the IAccessibleText interface for the field. |
| 202 hr = textarea.QueryInterface(textarea_text->Receive()); |
| 203 ASSERT_EQ(S_OK, hr); |
| 204 |
| 205 // Set the caret on the last character. |
| 206 LONG caret_offset = CONTENTS_LENGTH - 1; |
| 207 hr = (*textarea_text)->setCaretOffset(caret_offset); |
| 208 ASSERT_EQ(S_OK, hr); |
| 209 } |
| 210 |
| 211 |
| 212 // Static helpers ------------------------------------------------ |
| 213 |
| 214 base::win::ScopedComPtr<IAccessible> |
| 215 AccessibilityWinBrowserTest::GetAccessibleFromVariant( |
37 IAccessible* parent, | 216 IAccessible* parent, |
38 VARIANT* var) { | 217 VARIANT* var) { |
39 base::win::ScopedComPtr<IAccessible> ptr; | 218 base::win::ScopedComPtr<IAccessible> ptr; |
40 switch (V_VT(var)) { | 219 switch (V_VT(var)) { |
41 case VT_DISPATCH: { | 220 case VT_DISPATCH: { |
42 IDispatch* dispatch = V_DISPATCH(var); | 221 IDispatch* dispatch = V_DISPATCH(var); |
43 if (dispatch) | 222 if (dispatch) |
44 ptr.QueryFrom(dispatch); | 223 dispatch->QueryInterface(ptr.Receive()); |
45 break; | 224 break; |
46 } | 225 } |
47 | 226 |
48 case VT_I4: { | 227 case VT_I4: { |
49 base::win::ScopedComPtr<IDispatch> dispatch; | 228 base::win::ScopedComPtr<IDispatch> dispatch; |
50 HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); | 229 HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); |
51 EXPECT_TRUE(SUCCEEDED(hr)); | 230 EXPECT_TRUE(SUCCEEDED(hr)); |
52 if (dispatch.get()) | 231 if (dispatch.get()) |
53 dispatch.QueryInterface(ptr.Receive()); | 232 dispatch.QueryInterface(ptr.Receive()); |
54 break; | 233 break; |
55 } | 234 } |
56 } | 235 } |
57 return ptr; | 236 return ptr; |
58 } | 237 } |
59 | 238 |
60 HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) { | 239 HRESULT AccessibilityWinBrowserTest::QueryIAccessible2( |
61 // TODO(ctguil): For some reason querying the IAccessible2 interface from | 240 IAccessible* accessible, |
62 // IAccessible fails. | 241 IAccessible2** accessible2) { |
| 242 // IA2 Spec dictates that IServiceProvider should be used instead of |
| 243 // QueryInterface when retrieving IAccessible2. |
63 base::win::ScopedComPtr<IServiceProvider> service_provider; | 244 base::win::ScopedComPtr<IServiceProvider> service_provider; |
64 HRESULT hr = accessible->QueryInterface(service_provider.Receive()); | 245 HRESULT hr = accessible->QueryInterface(service_provider.Receive()); |
65 return SUCCEEDED(hr) ? | 246 return SUCCEEDED(hr) ? |
66 service_provider->QueryService(IID_IAccessible2, accessible2) : hr; | 247 service_provider->QueryService(IID_IAccessible2, accessible2) : hr; |
67 } | 248 } |
68 | 249 |
69 // Recursively search through all of the descendants reachable from an | 250 // Recursively search through all of the descendants reachable from an |
70 // IAccessible node and return true if we find one with the given role | 251 // IAccessible node and return true if we find one with the given role |
71 // and name. | 252 // and name. |
72 void RecursiveFindNodeInAccessibilityTree(IAccessible* node, | 253 void AccessibilityWinBrowserTest::FindNodeInAccessibilityTree( |
73 int32 expected_role, | 254 IAccessible* node, |
74 const std::wstring& expected_name, | 255 int32 expected_role, |
75 int32 depth, | 256 const std::wstring& expected_name, |
76 bool* found) { | 257 int32 depth, |
| 258 bool* found) { |
77 base::win::ScopedBstr name_bstr; | 259 base::win::ScopedBstr name_bstr; |
78 base::win::ScopedVariant childid_self(CHILDID_SELF); | 260 base::win::ScopedVariant childid_self(CHILDID_SELF); |
79 node->get_accName(childid_self, name_bstr.Receive()); | 261 node->get_accName(childid_self, name_bstr.Receive()); |
80 std::wstring name(name_bstr, name_bstr.Length()); | 262 std::wstring name(name_bstr, name_bstr.Length()); |
81 base::win::ScopedVariant role; | 263 base::win::ScopedVariant role; |
82 node->get_accRole(childid_self, role.Receive()); | 264 node->get_accRole(childid_self, role.Receive()); |
83 ASSERT_EQ(VT_I4, role.type()); | 265 ASSERT_EQ(VT_I4, role.type()); |
84 | 266 |
85 // Print the accessibility tree as we go, because if this test fails | 267 // Print the accessibility tree as we go, because if this test fails |
86 // on the bots, this is really helpful in figuring out why. | 268 // on the bots, this is really helpful in figuring out why. |
87 for (int i = 0; i < depth; i++) | 269 for (int i = 0; i < depth; i++) |
88 printf(" "); | 270 printf(" "); |
89 printf("role=%s name=%s\n", | 271 printf("role=%s name=%s\n", |
90 base::WideToUTF8(IAccessibleRoleToString(V_I4(&role))).c_str(), | 272 base::WideToUTF8(IAccessibleRoleToString(V_I4(&role))).c_str(), |
91 base::WideToUTF8(name).c_str()); | 273 base::WideToUTF8(name).c_str()); |
92 | 274 |
93 if (expected_role == V_I4(&role) && expected_name == name) { | 275 if (expected_role == V_I4(&role) && expected_name == name) { |
94 *found = true; | 276 *found = true; |
95 return; | 277 return; |
96 } | 278 } |
97 | 279 |
98 LONG child_count = 0; | 280 std::vector<base::win::ScopedVariant> children = GetAllAccessibleChildren( |
99 HRESULT hr = node->get_accChildCount(&child_count); | 281 node); |
100 ASSERT_EQ(S_OK, hr); | 282 for (size_t i = 0; i < children.size(); ++i) { |
101 | |
102 scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]); | |
103 LONG obtained_count = 0; | |
104 hr = AccessibleChildren( | |
105 node, 0, child_count, child_array.get(), &obtained_count); | |
106 ASSERT_EQ(S_OK, hr); | |
107 ASSERT_EQ(child_count, obtained_count); | |
108 | |
109 for (int index = 0; index < obtained_count; index++) { | |
110 base::win::ScopedComPtr<IAccessible> child_accessible( | 283 base::win::ScopedComPtr<IAccessible> child_accessible( |
111 GetAccessibleFromResultVariant(node, &child_array.get()[index])); | 284 GetAccessibleFromVariant(node, children[i].AsInput())); |
112 if (child_accessible.get()) { | 285 if (child_accessible) { |
113 RecursiveFindNodeInAccessibilityTree( | 286 FindNodeInAccessibilityTree( |
114 child_accessible.get(), expected_role, expected_name, depth + 1, | 287 child_accessible.get(), expected_role, expected_name, depth + 1, |
115 found); | 288 found); |
116 if (*found) | 289 if (*found) |
117 return; | 290 return; |
118 } | 291 } |
119 } | 292 } |
120 } | 293 } |
121 | 294 |
| 295 // Ensures that the text and the start and end offsets retrieved using |
| 296 // get_textAtOffset match the expected values. |
| 297 void AccessibilityWinBrowserTest::CheckTextAtOffset( |
| 298 base::win::ScopedComPtr<IAccessibleText>& element, |
| 299 LONG offset, |
| 300 IA2TextBoundaryType boundary_type, |
| 301 LONG expected_start_offset, |
| 302 LONG expected_end_offset, |
| 303 const std::wstring& expected_text) { |
| 304 testing::Message message; |
| 305 message << "While checking for \'" << expected_text << "\' at " << |
| 306 expected_start_offset << '-' << expected_end_offset << '.'; |
| 307 SCOPED_TRACE(message); |
122 | 308 |
123 // AccessibilityWinBrowserTest ------------------------------------------------ | 309 LONG start_offset = 0; |
124 | 310 LONG end_offset = 0; |
125 class AccessibilityWinBrowserTest : public ContentBrowserTest { | 311 base::win::ScopedBstr text; |
126 public: | 312 HRESULT hr = element->get_textAtOffset( |
127 AccessibilityWinBrowserTest(); | 313 offset, boundary_type, |
128 virtual ~AccessibilityWinBrowserTest(); | 314 &start_offset, &end_offset, text.Receive()); |
129 | 315 EXPECT_EQ(S_OK, hr); |
130 protected: | 316 EXPECT_EQ(expected_start_offset, start_offset); |
131 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); | 317 EXPECT_EQ(expected_end_offset, end_offset); |
132 IAccessible* GetRendererAccessible(); | 318 EXPECT_EQ(expected_text, std::wstring(text, text.Length())); |
133 void ExecuteScript(const std::wstring& script); | |
134 | |
135 private: | |
136 DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest); | |
137 }; | |
138 | |
139 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() { | |
140 } | 319 } |
141 | 320 |
142 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() { | 321 std::vector<base::win::ScopedVariant> |
143 } | 322 AccessibilityWinBrowserTest::GetAllAccessibleChildren( |
| 323 IAccessible* element) { |
| 324 LONG child_count = 0; |
| 325 HRESULT hr = element->get_accChildCount(&child_count); |
| 326 EXPECT_EQ(S_OK, hr); |
| 327 if (child_count <= 0) |
| 328 return std::vector<base::win::ScopedVariant>(); |
144 | 329 |
145 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml( | 330 scoped_ptr<VARIANT[]> children_array(new VARIANT[child_count]); |
146 const std::string& html) { | 331 LONG obtained_count = 0; |
147 AccessibilityNotificationWaiter waiter( | 332 hr = AccessibleChildren( |
148 shell(), AccessibilityModeComplete, | 333 element, 0, child_count, children_array.get(), &obtained_count); |
149 ui::AX_EVENT_LOAD_COMPLETE); | 334 EXPECT_EQ(S_OK, hr); |
150 GURL html_data_url("data:text/html," + html); | 335 EXPECT_EQ(child_count, obtained_count); |
151 NavigateToURL(shell(), html_data_url); | |
152 waiter.WaitForNotification(); | |
153 } | |
154 | 336 |
155 // Retrieve the MSAA client accessibility object for the Render Widget Host View | 337 std::vector<base::win::ScopedVariant> children( |
156 // of the selected tab. | 338 static_cast<size_t>(child_count)); |
157 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() { | 339 for (size_t i = 0; i < children.size(); i++) { |
158 content::WebContents* web_contents = shell()->web_contents(); | 340 children[i].Reset(children_array[i]); |
159 return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible(); | 341 } |
160 } | 342 return children; |
161 | |
162 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) { | |
163 shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script); | |
164 } | 343 } |
165 | 344 |
166 | 345 |
167 // AccessibleChecker ---------------------------------------------------------- | 346 // AccessibleChecker ---------------------------------------------------------- |
168 | 347 |
169 class AccessibleChecker { | 348 class AccessibilityWinBrowserTest::AccessibleChecker { |
170 public: | 349 public: |
171 // This constructor can be used if the IA2 role will be the same as the MSAA | 350 // This constructor can be used if the IA2 role will be the same as the MSAA |
172 // role. | 351 // role. |
173 AccessibleChecker(const std::wstring& expected_name, | 352 AccessibleChecker(const std::wstring& expected_name, |
174 int32 expected_role, | 353 int32 expected_role, |
175 const std::wstring& expected_value); | 354 const std::wstring& expected_value); |
176 AccessibleChecker(const std::wstring& expected_name, | 355 AccessibleChecker(const std::wstring& expected_name, |
177 int32 expected_role, | 356 int32 expected_role, |
178 int32 expected_ia2_role, | 357 int32 expected_ia2_role, |
179 const std::wstring& expected_value); | 358 const std::wstring& expected_value); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 std::wstring value_; | 400 std::wstring value_; |
222 | 401 |
223 // Expected accessible state. Checked against IAccessible::get_accState. | 402 // Expected accessible state. Checked against IAccessible::get_accState. |
224 LONG state_; | 403 LONG state_; |
225 | 404 |
226 // Expected accessible children. Checked using IAccessible::get_accChildCount | 405 // Expected accessible children. Checked using IAccessible::get_accChildCount |
227 // and ::AccessibleChildren. | 406 // and ::AccessibleChildren. |
228 AccessibleCheckerVector children_; | 407 AccessibleCheckerVector children_; |
229 }; | 408 }; |
230 | 409 |
231 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 410 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
232 int32 expected_role, | 411 const std::wstring& expected_name, |
233 const std::wstring& expected_value) | 412 int32 expected_role, |
| 413 const std::wstring& expected_value) |
234 : name_(expected_name), | 414 : name_(expected_name), |
235 role_(expected_role), | 415 role_(expected_role), |
236 ia2_role_(expected_role), | 416 ia2_role_(expected_role), |
237 value_(expected_value), | 417 value_(expected_value), |
238 state_(-1) { | 418 state_(-1) { |
239 } | 419 } |
240 | 420 |
241 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 421 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
242 int32 expected_role, | 422 const std::wstring& expected_name, |
243 int32 expected_ia2_role, | 423 int32 expected_role, |
244 const std::wstring& expected_value) | 424 int32 expected_ia2_role, |
| 425 const std::wstring& expected_value) |
245 : name_(expected_name), | 426 : name_(expected_name), |
246 role_(expected_role), | 427 role_(expected_role), |
247 ia2_role_(expected_ia2_role), | 428 ia2_role_(expected_ia2_role), |
248 value_(expected_value), | 429 value_(expected_value), |
249 state_(-1) { | 430 state_(-1) { |
250 } | 431 } |
251 | 432 |
252 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 433 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
253 const std::wstring& expected_role, | 434 const std::wstring& expected_name, |
254 int32 expected_ia2_role, | 435 const std::wstring& expected_role, |
255 const std::wstring& expected_value) | 436 int32 expected_ia2_role, |
| 437 const std::wstring& expected_value) |
256 : name_(expected_name), | 438 : name_(expected_name), |
257 role_(expected_role.c_str()), | 439 role_(expected_role.c_str()), |
258 ia2_role_(expected_ia2_role), | 440 ia2_role_(expected_ia2_role), |
259 value_(expected_value), | 441 value_(expected_value), |
260 state_(-1) { | 442 state_(-1) { |
261 } | 443 } |
262 | 444 |
263 void AccessibleChecker::AppendExpectedChild( | 445 void AccessibilityWinBrowserTest::AccessibleChecker::AppendExpectedChild( |
264 AccessibleChecker* expected_child) { | 446 AccessibleChecker* expected_child) { |
265 children_.push_back(expected_child); | 447 children_.push_back(expected_child); |
266 } | 448 } |
267 | 449 |
268 void AccessibleChecker::CheckAccessible(IAccessible* accessible) { | 450 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessible( |
269 SCOPED_TRACE("while checking " + | 451 IAccessible* accessible) { |
270 base::UTF16ToUTF8(RoleVariantToString(role_))); | 452 SCOPED_TRACE("While checking " |
| 453 + base::UTF16ToUTF8(RoleVariantToString(role_))); |
271 CheckAccessibleName(accessible); | 454 CheckAccessibleName(accessible); |
272 CheckAccessibleRole(accessible); | 455 CheckAccessibleRole(accessible); |
273 CheckIA2Role(accessible); | 456 CheckIA2Role(accessible); |
274 CheckAccessibleValue(accessible); | 457 CheckAccessibleValue(accessible); |
275 CheckAccessibleState(accessible); | 458 CheckAccessibleState(accessible); |
276 CheckAccessibleChildren(accessible); | 459 CheckAccessibleChildren(accessible); |
277 } | 460 } |
278 | 461 |
279 void AccessibleChecker::SetExpectedValue(const std::wstring& expected_value) { | 462 void AccessibilityWinBrowserTest::AccessibleChecker::SetExpectedValue( |
| 463 const std::wstring& expected_value) { |
280 value_ = expected_value; | 464 value_ = expected_value; |
281 } | 465 } |
282 | 466 |
283 void AccessibleChecker::SetExpectedState(LONG expected_state) { | 467 void AccessibilityWinBrowserTest::AccessibleChecker::SetExpectedState( |
| 468 LONG expected_state) { |
284 state_ = expected_state; | 469 state_ = expected_state; |
285 } | 470 } |
286 | 471 |
287 void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) { | 472 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleName( |
| 473 IAccessible* accessible) { |
288 base::win::ScopedBstr name; | 474 base::win::ScopedBstr name; |
289 base::win::ScopedVariant childid_self(CHILDID_SELF); | 475 base::win::ScopedVariant childid_self(CHILDID_SELF); |
290 HRESULT hr = accessible->get_accName(childid_self, name.Receive()); | 476 HRESULT hr = accessible->get_accName(childid_self, name.Receive()); |
291 | 477 |
292 if (name_.empty()) { | 478 if (name_.empty()) { |
293 // If the object doesn't have name S_FALSE should be returned. | 479 // If the object doesn't have name S_FALSE should be returned. |
294 EXPECT_EQ(S_FALSE, hr); | 480 EXPECT_EQ(S_FALSE, hr); |
295 } else { | 481 } else { |
296 // Test that the correct string was returned. | 482 // Test that the correct string was returned. |
297 EXPECT_EQ(S_OK, hr); | 483 EXPECT_EQ(S_OK, hr); |
298 EXPECT_EQ(name_, std::wstring(name, name.Length())); | 484 EXPECT_EQ(name_, std::wstring(name, name.Length())); |
299 } | 485 } |
300 } | 486 } |
301 | 487 |
302 void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) { | 488 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleRole( |
| 489 IAccessible* accessible) { |
303 base::win::ScopedVariant role; | 490 base::win::ScopedVariant role; |
304 base::win::ScopedVariant childid_self(CHILDID_SELF); | 491 base::win::ScopedVariant childid_self(CHILDID_SELF); |
305 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); | 492 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); |
306 ASSERT_EQ(S_OK, hr); | 493 ASSERT_EQ(S_OK, hr); |
307 EXPECT_EQ(0, role_.Compare(role)) | 494 EXPECT_EQ(0, role_.Compare(role)) |
308 << "Expected role: " << RoleVariantToString(role_) | 495 << "Expected role: " << RoleVariantToString(role_) |
309 << "\nGot role: " << RoleVariantToString(role); | 496 << "\nGot role: " << RoleVariantToString(role); |
310 } | 497 } |
311 | 498 |
312 void AccessibleChecker::CheckIA2Role(IAccessible* accessible) { | 499 void AccessibilityWinBrowserTest::AccessibleChecker::CheckIA2Role( |
| 500 IAccessible* accessible) { |
313 base::win::ScopedComPtr<IAccessible2> accessible2; | 501 base::win::ScopedComPtr<IAccessible2> accessible2; |
314 HRESULT hr = QueryIAccessible2(accessible, accessible2.Receive()); | 502 HRESULT hr = QueryIAccessible2(accessible, accessible2.Receive()); |
315 ASSERT_EQ(S_OK, hr); | 503 ASSERT_EQ(S_OK, hr); |
316 long ia2_role = 0; | 504 long ia2_role = 0; |
317 hr = accessible2->role(&ia2_role); | 505 hr = accessible2->role(&ia2_role); |
318 ASSERT_EQ(S_OK, hr); | 506 ASSERT_EQ(S_OK, hr); |
319 EXPECT_EQ(ia2_role_, ia2_role) | 507 EXPECT_EQ(ia2_role_, ia2_role) |
320 << "Expected ia2 role: " << IAccessible2RoleToString(ia2_role_) | 508 << "Expected ia2 role: " << IAccessible2RoleToString(ia2_role_) |
321 << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role); | 509 << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role); |
322 } | 510 } |
323 | 511 |
324 void AccessibleChecker::CheckAccessibleValue(IAccessible* accessible) { | 512 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleValue( |
| 513 IAccessible* accessible) { |
325 // Don't check the value if if's a DOCUMENT role, because the value | 514 // Don't check the value if if's a DOCUMENT role, because the value |
326 // is supposed to be the url (and we don't keep track of that in the | 515 // is supposed to be the url (and we don't keep track of that in the |
327 // test expectations). | 516 // test expectations). |
328 base::win::ScopedVariant role; | 517 base::win::ScopedVariant role; |
329 base::win::ScopedVariant childid_self(CHILDID_SELF); | 518 base::win::ScopedVariant childid_self(CHILDID_SELF); |
330 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); | 519 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); |
331 ASSERT_EQ(S_OK, hr); | 520 ASSERT_EQ(S_OK, hr); |
332 if (role.type() == VT_I4 && V_I4(&role) == ROLE_SYSTEM_DOCUMENT) | 521 if (role.type() == VT_I4 && V_I4(&role) == ROLE_SYSTEM_DOCUMENT) |
333 return; | 522 return; |
334 | 523 |
335 // Get the value. | 524 // Get the value. |
336 base::win::ScopedBstr value; | 525 base::win::ScopedBstr value; |
337 hr = accessible->get_accValue(childid_self, value.Receive()); | 526 hr = accessible->get_accValue(childid_self, value.Receive()); |
338 EXPECT_EQ(S_OK, hr); | 527 EXPECT_EQ(S_OK, hr); |
339 | 528 |
340 // Test that the correct string was returned. | 529 // Test that the correct string was returned. |
341 EXPECT_EQ(value_, std::wstring(value, value.Length())); | 530 EXPECT_EQ(value_, std::wstring(value, value.Length())); |
342 } | 531 } |
343 | 532 |
344 void AccessibleChecker::CheckAccessibleState(IAccessible* accessible) { | 533 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleState( |
| 534 IAccessible* accessible) { |
345 if (state_ < 0) | 535 if (state_ < 0) |
346 return; | 536 return; |
347 | 537 |
348 base::win::ScopedVariant state; | 538 base::win::ScopedVariant state; |
349 base::win::ScopedVariant childid_self(CHILDID_SELF); | 539 base::win::ScopedVariant childid_self(CHILDID_SELF); |
350 HRESULT hr = accessible->get_accState(childid_self, state.Receive()); | 540 HRESULT hr = accessible->get_accState(childid_self, state.Receive()); |
351 EXPECT_EQ(S_OK, hr); | 541 EXPECT_EQ(S_OK, hr); |
352 ASSERT_EQ(VT_I4, state.type()); | 542 ASSERT_EQ(VT_I4, state.type()); |
353 LONG obj_state = V_I4(&state); | 543 LONG obj_state = V_I4(&state); |
354 // Avoid flakiness. The "offscreen" state depends on whether the browser | 544 // Avoid flakiness. The "offscreen" state depends on whether the browser |
355 // window is frontmost or not, and "hottracked" depends on whether the | 545 // window is frontmost or not, and "hottracked" depends on whether the |
356 // mouse cursor happens to be over the element. | 546 // mouse cursor happens to be over the element. |
357 obj_state &= ~(STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_HOTTRACKED); | 547 obj_state &= ~(STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_HOTTRACKED); |
358 EXPECT_EQ(state_, obj_state) | 548 EXPECT_EQ(state_, obj_state) |
359 << "Expected state: " << IAccessibleStateToString(state_) | 549 << "Expected state: " << IAccessibleStateToString(state_) |
360 << "\nGot state: " << IAccessibleStateToString(obj_state); | 550 << "\nGot state: " << IAccessibleStateToString(obj_state); |
361 } | 551 } |
362 | 552 |
363 void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) { | 553 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleChildren( |
364 LONG child_count = 0; | 554 IAccessible* parent) { |
365 HRESULT hr = parent->get_accChildCount(&child_count); | 555 std::vector<base::win::ScopedVariant> obtained_children = |
366 EXPECT_EQ(S_OK, hr); | 556 GetAllAccessibleChildren(parent); |
| 557 size_t child_count = obtained_children.size(); |
367 ASSERT_EQ(child_count, children_.size()); | 558 ASSERT_EQ(child_count, children_.size()); |
368 | 559 |
369 scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]); | 560 AccessibleCheckerVector::iterator child_checker; |
370 LONG obtained_count = 0; | 561 std::vector<base::win::ScopedVariant>::iterator child; |
371 hr = AccessibleChildren(parent, 0, child_count, | 562 for (child_checker = children_.begin(), |
372 child_array.get(), &obtained_count); | 563 child = obtained_children.begin(); |
373 ASSERT_EQ(S_OK, hr); | 564 child_checker != children_.end() |
374 ASSERT_EQ(child_count, obtained_count); | 565 && child != obtained_children.end(); |
375 | |
376 VARIANT* child = child_array.get(); | |
377 for (AccessibleCheckerVector::iterator child_checker = children_.begin(); | |
378 child_checker != children_.end(); | |
379 ++child_checker, ++child) { | 566 ++child_checker, ++child) { |
380 base::win::ScopedComPtr<IAccessible> child_accessible( | 567 base::win::ScopedComPtr<IAccessible> child_accessible( |
381 GetAccessibleFromResultVariant(parent, child)); | 568 GetAccessibleFromVariant(parent, child->AsInput())); |
382 ASSERT_TRUE(child_accessible.get()); | 569 ASSERT_TRUE(child_accessible.get()); |
383 (*child_checker)->CheckAccessible(child_accessible.get()); | 570 (*child_checker)->CheckAccessible(child_accessible.get()); |
384 } | 571 } |
385 } | 572 } |
386 | 573 |
387 base::string16 AccessibleChecker::RoleVariantToString( | 574 base::string16 |
| 575 AccessibilityWinBrowserTest::AccessibleChecker::RoleVariantToString( |
388 const base::win::ScopedVariant& role) { | 576 const base::win::ScopedVariant& role) { |
389 if (role.type() == VT_I4) | 577 if (role.type() == VT_I4) |
390 return IAccessibleRoleToString(V_I4(&role)); | 578 return IAccessibleRoleToString(V_I4(&role)); |
391 if (role.type() == VT_BSTR) | 579 if (role.type() == VT_BSTR) |
392 return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role))); | 580 return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role))); |
393 return base::string16(); | 581 return base::string16(); |
394 } | 582 } |
395 | 583 |
396 } // namespace | 584 } // namespace |
397 | 585 |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 CHECK(hwnd); | 848 CHECK(hwnd); |
661 base::win::ScopedComPtr<IAccessible> browser_accessible; | 849 base::win::ScopedComPtr<IAccessible> browser_accessible; |
662 HRESULT hr = AccessibleObjectFromWindow( | 850 HRESULT hr = AccessibleObjectFromWindow( |
663 hwnd, | 851 hwnd, |
664 OBJID_WINDOW, | 852 OBJID_WINDOW, |
665 IID_IAccessible, | 853 IID_IAccessible, |
666 reinterpret_cast<void**>(browser_accessible.Receive())); | 854 reinterpret_cast<void**>(browser_accessible.Receive())); |
667 ASSERT_EQ(S_OK, hr); | 855 ASSERT_EQ(S_OK, hr); |
668 | 856 |
669 bool found = false; | 857 bool found = false; |
670 RecursiveFindNodeInAccessibilityTree( | 858 FindNodeInAccessibilityTree( |
671 browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found); | 859 browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found); |
672 ASSERT_EQ(found, true); | 860 ASSERT_EQ(found, true); |
673 } | 861 } |
674 | 862 |
675 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | 863 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
676 SupportsISimpleDOM) { | 864 SupportsISimpleDOM) { |
677 LoadInitialAccessibilityTreeFromHtml( | 865 LoadInitialAccessibilityTreeFromHtml( |
678 "<body><input type='checkbox' /></body>"); | 866 "<body><input type='checkbox' /></body>"); |
679 | 867 |
680 // Get the IAccessible object for the document. | 868 // Get the IAccessible object for the document. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 std::wstring()); | 935 std::wstring()); |
748 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, | 936 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, |
749 std::wstring()); | 937 std::wstring()); |
750 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, | 938 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, |
751 std::wstring()); | 939 std::wstring()); |
752 document_checker.AppendExpectedChild(&grouping1_checker); | 940 document_checker.AppendExpectedChild(&grouping1_checker); |
753 document_checker.AppendExpectedChild(&grouping2_checker); | 941 document_checker.AppendExpectedChild(&grouping2_checker); |
754 document_checker.CheckAccessible(GetRendererAccessible()); | 942 document_checker.CheckAccessible(GetRendererAccessible()); |
755 } | 943 } |
756 | 944 |
| 945 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 946 TestTextAtOffsetWithInvalidArgs) { |
| 947 base::win::ScopedComPtr<IAccessibleText> input_text; |
| 948 SetUpInputField(&input_text); |
| 949 HRESULT hr = input_text->get_textAtOffset( |
| 950 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); |
| 951 EXPECT_EQ(E_INVALIDARG, hr); |
| 952 |
| 953 // Test invalid offset. |
| 954 LONG start_offset = 0; |
| 955 LONG end_offset = 0; |
| 956 base::win::ScopedBstr text; |
| 957 LONG invalid_offset = -5; |
| 958 hr = input_text->get_textAtOffset( |
| 959 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, |
| 960 &start_offset, &end_offset, text.Receive()); |
| 961 EXPECT_EQ(E_INVALIDARG, hr); |
| 962 EXPECT_EQ(0, start_offset); |
| 963 EXPECT_EQ(0, end_offset); |
| 964 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 965 invalid_offset = CONTENTS_LENGTH + 1; |
| 966 hr = input_text->get_textAtOffset( |
| 967 invalid_offset, IA2_TEXT_BOUNDARY_WORD, |
| 968 &start_offset, &end_offset, text.Receive()); |
| 969 EXPECT_EQ(E_INVALIDARG, hr); |
| 970 EXPECT_EQ(0, start_offset); |
| 971 EXPECT_EQ(0, end_offset); |
| 972 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 973 |
| 974 // According to the IA2 Spec, only line boundaries should succeed when |
| 975 // the offset is one past the end of the text. |
| 976 invalid_offset = CONTENTS_LENGTH; |
| 977 hr = input_text->get_textAtOffset( |
| 978 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, |
| 979 &start_offset, &end_offset, text.Receive()); |
| 980 EXPECT_EQ(S_FALSE, hr); |
| 981 EXPECT_EQ(0, start_offset); |
| 982 EXPECT_EQ(0, end_offset); |
| 983 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 984 hr = input_text->get_textAtOffset( |
| 985 invalid_offset, IA2_TEXT_BOUNDARY_WORD, |
| 986 &start_offset, &end_offset, text.Receive()); |
| 987 EXPECT_EQ(S_FALSE, hr); |
| 988 EXPECT_EQ(0, start_offset); |
| 989 EXPECT_EQ(0, end_offset); |
| 990 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 991 hr = input_text->get_textAtOffset( |
| 992 invalid_offset, IA2_TEXT_BOUNDARY_SENTENCE, |
| 993 &start_offset, &end_offset, text.Receive()); |
| 994 EXPECT_EQ(S_FALSE, hr); |
| 995 EXPECT_EQ(0, start_offset); |
| 996 EXPECT_EQ(0, end_offset); |
| 997 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 998 hr = input_text->get_textAtOffset( |
| 999 invalid_offset, IA2_TEXT_BOUNDARY_ALL, |
| 1000 &start_offset, &end_offset, text.Receive()); |
| 1001 EXPECT_EQ(S_FALSE, hr); |
| 1002 EXPECT_EQ(0, start_offset); |
| 1003 EXPECT_EQ(0, end_offset); |
| 1004 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1005 |
| 1006 // The same behavior should be observed when the special offset |
| 1007 // IA2_TEXT_OFFSET_LENGTH is used. |
| 1008 hr = input_text->get_textAtOffset( |
| 1009 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_CHAR, |
| 1010 &start_offset, &end_offset, text.Receive()); |
| 1011 EXPECT_EQ(S_FALSE, hr); |
| 1012 EXPECT_EQ(0, start_offset); |
| 1013 EXPECT_EQ(0, end_offset); |
| 1014 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1015 hr = input_text->get_textAtOffset( |
| 1016 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_WORD, |
| 1017 &start_offset, &end_offset, text.Receive()); |
| 1018 EXPECT_EQ(S_FALSE, hr); |
| 1019 EXPECT_EQ(0, start_offset); |
| 1020 EXPECT_EQ(0, end_offset); |
| 1021 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1022 hr = input_text->get_textAtOffset( |
| 1023 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_SENTENCE, |
| 1024 &start_offset, &end_offset, text.Receive()); |
| 1025 EXPECT_EQ(S_FALSE, hr); |
| 1026 EXPECT_EQ(0, start_offset); |
| 1027 EXPECT_EQ(0, end_offset); |
| 1028 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1029 hr = input_text->get_textAtOffset( |
| 1030 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_ALL, |
| 1031 &start_offset, &end_offset, text.Receive()); |
| 1032 EXPECT_EQ(S_FALSE, hr); |
| 1033 EXPECT_EQ(0, start_offset); |
| 1034 EXPECT_EQ(0, end_offset); |
| 1035 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1036 } |
| 1037 |
| 1038 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1039 TestMultiLineTextAtOffsetWithInvalidArgs) { |
| 1040 base::win::ScopedComPtr<IAccessibleText> textarea_text; |
| 1041 SetUpTextareaField(&textarea_text); |
| 1042 HRESULT hr = textarea_text->get_textAtOffset( |
| 1043 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); |
| 1044 EXPECT_EQ(E_INVALIDARG, hr); |
| 1045 |
| 1046 // Test invalid offset. |
| 1047 LONG start_offset = 0; |
| 1048 LONG end_offset = 0; |
| 1049 base::win::ScopedBstr text; |
| 1050 LONG invalid_offset = -5; |
| 1051 hr = textarea_text->get_textAtOffset( |
| 1052 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, |
| 1053 &start_offset, &end_offset, text.Receive()); |
| 1054 EXPECT_EQ(E_INVALIDARG, hr); |
| 1055 EXPECT_EQ(0, start_offset); |
| 1056 EXPECT_EQ(0, end_offset); |
| 1057 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1058 invalid_offset = CONTENTS_LENGTH + 1; |
| 1059 hr = textarea_text->get_textAtOffset( |
| 1060 invalid_offset, IA2_TEXT_BOUNDARY_WORD, |
| 1061 &start_offset, &end_offset, text.Receive()); |
| 1062 EXPECT_EQ(E_INVALIDARG, hr); |
| 1063 EXPECT_EQ(0, start_offset); |
| 1064 EXPECT_EQ(0, end_offset); |
| 1065 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1066 |
| 1067 // According to the IA2 Spec, only line boundaries should succeed when |
| 1068 // the offset is one past the end of the text. |
| 1069 invalid_offset = CONTENTS_LENGTH; |
| 1070 hr = textarea_text->get_textAtOffset( |
| 1071 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, |
| 1072 &start_offset, &end_offset, text.Receive()); |
| 1073 EXPECT_EQ(S_FALSE, hr); |
| 1074 EXPECT_EQ(0, start_offset); |
| 1075 EXPECT_EQ(0, end_offset); |
| 1076 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1077 hr = textarea_text->get_textAtOffset( |
| 1078 invalid_offset, IA2_TEXT_BOUNDARY_WORD, |
| 1079 &start_offset, &end_offset, text.Receive()); |
| 1080 EXPECT_EQ(S_FALSE, hr); |
| 1081 EXPECT_EQ(0, start_offset); |
| 1082 EXPECT_EQ(0, end_offset); |
| 1083 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1084 hr = textarea_text->get_textAtOffset( |
| 1085 invalid_offset, IA2_TEXT_BOUNDARY_SENTENCE, |
| 1086 &start_offset, &end_offset, text.Receive()); |
| 1087 EXPECT_EQ(S_FALSE, hr); |
| 1088 EXPECT_EQ(0, start_offset); |
| 1089 EXPECT_EQ(0, end_offset); |
| 1090 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1091 hr = textarea_text->get_textAtOffset( |
| 1092 invalid_offset, IA2_TEXT_BOUNDARY_ALL, |
| 1093 &start_offset, &end_offset, text.Receive()); |
| 1094 EXPECT_EQ(S_FALSE, hr); |
| 1095 EXPECT_EQ(0, start_offset); |
| 1096 EXPECT_EQ(0, end_offset); |
| 1097 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1098 |
| 1099 // The same behavior should be observed when the special offset |
| 1100 // IA2_TEXT_OFFSET_LENGTH is used. |
| 1101 hr = textarea_text->get_textAtOffset( |
| 1102 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_CHAR, |
| 1103 &start_offset, &end_offset, text.Receive()); |
| 1104 EXPECT_EQ(S_FALSE, hr); |
| 1105 EXPECT_EQ(0, start_offset); |
| 1106 EXPECT_EQ(0, end_offset); |
| 1107 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1108 hr = textarea_text->get_textAtOffset( |
| 1109 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_WORD, |
| 1110 &start_offset, &end_offset, text.Receive()); |
| 1111 EXPECT_EQ(S_FALSE, hr); |
| 1112 EXPECT_EQ(0, start_offset); |
| 1113 EXPECT_EQ(0, end_offset); |
| 1114 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1115 hr = textarea_text->get_textAtOffset( |
| 1116 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_SENTENCE, |
| 1117 &start_offset, &end_offset, text.Receive()); |
| 1118 EXPECT_EQ(S_FALSE, hr); |
| 1119 EXPECT_EQ(0, start_offset); |
| 1120 EXPECT_EQ(0, end_offset); |
| 1121 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1122 hr = textarea_text->get_textAtOffset( |
| 1123 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_ALL, |
| 1124 &start_offset, &end_offset, text.Receive()); |
| 1125 EXPECT_EQ(S_FALSE, hr); |
| 1126 EXPECT_EQ(0, start_offset); |
| 1127 EXPECT_EQ(0, end_offset); |
| 1128 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); |
| 1129 } |
| 1130 |
| 1131 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1132 TestTextAtOffsetWithBoundaryCharacter) { |
| 1133 base::win::ScopedComPtr<IAccessibleText> input_text; |
| 1134 SetUpInputField(&input_text); |
| 1135 for (LONG offset = 0; offset < CONTENTS_LENGTH; ++offset) { |
| 1136 std::wstring expected_text(1, INPUT_CONTENTS[offset]); |
| 1137 LONG expected_start_offset = offset; |
| 1138 LONG expected_end_offset = offset + 1; |
| 1139 CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR, |
| 1140 expected_start_offset, expected_end_offset, expected_text); |
| 1141 } |
| 1142 |
| 1143 for (LONG offset = CONTENTS_LENGTH - 1; offset >= 0; --offset) { |
| 1144 std::wstring expected_text(1, INPUT_CONTENTS[offset]); |
| 1145 LONG expected_start_offset = offset; |
| 1146 LONG expected_end_offset = offset + 1; |
| 1147 CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR, |
| 1148 expected_start_offset, expected_end_offset, expected_text); |
| 1149 } |
| 1150 |
| 1151 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET, |
| 1152 IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L"."); |
| 1153 } |
| 1154 |
| 1155 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1156 TestMultiLineTextAtOffsetWithBoundaryCharacter) { |
| 1157 base::win::ScopedComPtr<IAccessibleText> textarea_text; |
| 1158 SetUpTextareaField(&textarea_text); |
| 1159 for (LONG offset = 0; offset < CONTENTS_LENGTH; ++offset) { |
| 1160 std::wstring expected_text(1, TEXTAREA_CONTENTS[offset]); |
| 1161 LONG expected_start_offset = offset; |
| 1162 LONG expected_end_offset = offset + 1; |
| 1163 CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR, |
| 1164 expected_start_offset, expected_end_offset, expected_text); |
| 1165 } |
| 1166 |
| 1167 for (LONG offset = CONTENTS_LENGTH - 1; offset >= 0; --offset) { |
| 1168 std::wstring expected_text(1, TEXTAREA_CONTENTS[offset]); |
| 1169 LONG expected_start_offset = offset; |
| 1170 LONG expected_end_offset = offset + 1; |
| 1171 CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR, |
| 1172 expected_start_offset, expected_end_offset, expected_text); |
| 1173 } |
| 1174 |
| 1175 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET, |
| 1176 IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L"."); |
| 1177 } |
| 1178 |
| 1179 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1180 TestTextAtOffsetWithBoundaryWord) { |
| 1181 base::win::ScopedComPtr<IAccessibleText> input_text; |
| 1182 SetUpInputField(&input_text); |
| 1183 |
| 1184 // Trailing punctuation should be included as part of the previous word. |
| 1185 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, |
| 1186 0, 4, L"Moz/"); |
| 1187 CheckTextAtOffset(input_text, 2, IA2_TEXT_BOUNDARY_WORD, |
| 1188 0, 4, L"Moz/"); |
| 1189 |
| 1190 // If the offset is at the punctuation, it should return |
| 1191 // the previous word. |
| 1192 CheckTextAtOffset(input_text, 3, IA2_TEXT_BOUNDARY_WORD, |
| 1193 0, 4, L"Moz/"); |
| 1194 |
| 1195 // Numbers with a decimal point ("." for U.S), should be treated as one word. |
| 1196 // Also, trailing punctuation that occurs after empty space should be part of |
| 1197 // the word. ("5.0 (" and not "5.0 ".) |
| 1198 CheckTextAtOffset(input_text, 4, IA2_TEXT_BOUNDARY_WORD, |
| 1199 4, 9, L"5.0 ("); |
| 1200 CheckTextAtOffset(input_text, 5, IA2_TEXT_BOUNDARY_WORD, |
| 1201 4, 9, L"5.0 ("); |
| 1202 CheckTextAtOffset(input_text, 6, IA2_TEXT_BOUNDARY_WORD, |
| 1203 4, 9, L"5.0 ("); |
| 1204 CheckTextAtOffset(input_text, 7, IA2_TEXT_BOUNDARY_WORD, |
| 1205 4, 9, L"5.0 ("); |
| 1206 |
| 1207 // Leading punctuation should not be included with the word after it. |
| 1208 CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, |
| 1209 4, 9, L"5.0 ("); |
| 1210 CheckTextAtOffset(input_text, 11, IA2_TEXT_BOUNDARY_WORD, |
| 1211 9, 12, L"ST "); |
| 1212 |
| 1213 // Numbers separated from letters with trailing punctuation should |
| 1214 // be split into two words. Same for abreviations like "i.e.". |
| 1215 CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, |
| 1216 12, 14, L"6."); |
| 1217 CheckTextAtOffset(input_text, 15, IA2_TEXT_BOUNDARY_WORD, |
| 1218 14, 17, L"x; "); |
| 1219 |
| 1220 // Words with numbers should be treated like ordinary words. |
| 1221 CheckTextAtOffset(input_text, 17, IA2_TEXT_BOUNDARY_WORD, |
| 1222 17, 24, L"WWW33) "); |
| 1223 CheckTextAtOffset(input_text, 23, IA2_TEXT_BOUNDARY_WORD, |
| 1224 17, 24, L"WWW33) "); |
| 1225 |
| 1226 // Multiple trailing empty spaces should be part of the word preceding it. |
| 1227 CheckTextAtOffset(input_text, 28, IA2_TEXT_BOUNDARY_WORD, |
| 1228 24, 33, L"WebKit \""); |
| 1229 CheckTextAtOffset(input_text, 31, IA2_TEXT_BOUNDARY_WORD, |
| 1230 24, 33, L"WebKit \""); |
| 1231 CheckTextAtOffset(input_text, 32, IA2_TEXT_BOUNDARY_WORD, |
| 1232 24, 33, L"WebKit \""); |
| 1233 |
| 1234 // Leading punctuation such as quotation marks should not be part of the word. |
| 1235 CheckTextAtOffset(input_text, 33, IA2_TEXT_BOUNDARY_WORD, |
| 1236 33, 40, L"KHTML, "); |
| 1237 CheckTextAtOffset(input_text, 38, IA2_TEXT_BOUNDARY_WORD, |
| 1238 33, 40, L"KHTML, "); |
| 1239 |
| 1240 // Trailing final punctuation should be part of the last word. |
| 1241 CheckTextAtOffset(input_text, 41, IA2_TEXT_BOUNDARY_WORD, |
| 1242 40, CONTENTS_LENGTH, L"like\"."); |
| 1243 CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD, |
| 1244 40, CONTENTS_LENGTH, L"like\"."); |
| 1245 |
| 1246 // Test special offsets. |
| 1247 CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, |
| 1248 IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\"."); |
| 1249 } |
| 1250 |
| 1251 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1252 TestMultiLineTextAtOffsetWithBoundaryWord) { |
| 1253 base::win::ScopedComPtr<IAccessibleText> textarea_text; |
| 1254 SetUpTextareaField(&textarea_text); |
| 1255 |
| 1256 // Trailing punctuation should be included as part of the previous word. |
| 1257 CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_WORD, |
| 1258 0, 4, L"Moz/"); |
| 1259 CheckTextAtOffset(textarea_text, 2, IA2_TEXT_BOUNDARY_WORD, |
| 1260 0, 4, L"Moz/"); |
| 1261 |
| 1262 // If the offset is at the punctuation, it should return |
| 1263 // the previous word. |
| 1264 CheckTextAtOffset(textarea_text, 3, IA2_TEXT_BOUNDARY_WORD, |
| 1265 0, 4, L"Moz/"); |
| 1266 |
| 1267 // Numbers with a decimal point ("." for U.S), should be treated as one word. |
| 1268 // Also, trailing punctuation that occurs after empty space should be part of |
| 1269 // the word. ("5.0 (" and not "5.0 ".) |
| 1270 CheckTextAtOffset(textarea_text, 4, IA2_TEXT_BOUNDARY_WORD, |
| 1271 4, 9, L"5.0 ("); |
| 1272 CheckTextAtOffset(textarea_text, 5, IA2_TEXT_BOUNDARY_WORD, |
| 1273 4, 9, L"5.0 ("); |
| 1274 CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD, |
| 1275 4, 9, L"5.0 ("); |
| 1276 CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, |
| 1277 4, 9, L"5.0 ("); |
| 1278 |
| 1279 // Leading punctuation should not be included with the word after it. |
| 1280 CheckTextAtOffset(textarea_text, 8, IA2_TEXT_BOUNDARY_WORD, |
| 1281 4, 9, L"5.0 ("); |
| 1282 CheckTextAtOffset(textarea_text, 11, IA2_TEXT_BOUNDARY_WORD, |
| 1283 9, 12, L"ST "); |
| 1284 |
| 1285 // Numbers separated from letters with trailing punctuation should |
| 1286 // be split into two words. Same for abreviations like "i.e.". |
| 1287 CheckTextAtOffset(textarea_text, 12, IA2_TEXT_BOUNDARY_WORD, |
| 1288 12, 14, L"6."); |
| 1289 CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, |
| 1290 14, 17, L"x; "); |
| 1291 |
| 1292 // Words with numbers should be treated like ordinary words. |
| 1293 CheckTextAtOffset(textarea_text, 17, IA2_TEXT_BOUNDARY_WORD, |
| 1294 17, 24, L"WWW33)\n"); |
| 1295 CheckTextAtOffset(textarea_text, 23, IA2_TEXT_BOUNDARY_WORD, |
| 1296 17, 24, L"WWW33)\n"); |
| 1297 |
| 1298 // Multiple trailing empty spaces should be part of the word preceding it. |
| 1299 CheckTextAtOffset(textarea_text, 28, IA2_TEXT_BOUNDARY_WORD, |
| 1300 24, 33, L"WebKit \n\""); |
| 1301 CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_WORD, |
| 1302 24, 33, L"WebKit \n\""); |
| 1303 CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_WORD, |
| 1304 24, 33, L"WebKit \n\""); |
| 1305 |
| 1306 // Leading punctuation such as quotation marks should not be part of the word. |
| 1307 CheckTextAtOffset(textarea_text, 33, IA2_TEXT_BOUNDARY_WORD, |
| 1308 33, 40, L"KHTML, "); |
| 1309 CheckTextAtOffset(textarea_text, 38, IA2_TEXT_BOUNDARY_WORD, |
| 1310 33, 40, L"KHTML, "); |
| 1311 |
| 1312 // Trailing final punctuation should be part of the last word. |
| 1313 CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD, |
| 1314 40, CONTENTS_LENGTH, L"like\"."); |
| 1315 CheckTextAtOffset(textarea_text, 45, IA2_TEXT_BOUNDARY_WORD, |
| 1316 40, CONTENTS_LENGTH, L"like\"."); |
| 1317 |
| 1318 // Test special offsets. |
| 1319 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET, |
| 1320 IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\"."); |
| 1321 } |
| 1322 |
| 1323 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1324 TestTextAtOffsetWithBoundarySentence) { |
| 1325 base::win::ScopedComPtr<IAccessibleText> input_text; |
| 1326 SetUpInputField(&input_text); |
| 1327 |
| 1328 // Sentence navigation is not currently implemented. |
| 1329 LONG start_offset = 0; |
| 1330 LONG end_offset = 0; |
| 1331 base::win::ScopedBstr text; |
| 1332 HRESULT hr = input_text->get_textAtOffset( |
| 1333 5, IA2_TEXT_BOUNDARY_SENTENCE, |
| 1334 &start_offset, &end_offset, text.Receive()); |
| 1335 EXPECT_EQ(S_FALSE, hr); |
| 1336 } |
| 1337 |
| 1338 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1339 TestMultiLineTextAtOffsetWithBoundarySentence) { |
| 1340 base::win::ScopedComPtr<IAccessibleText> textarea_text; |
| 1341 SetUpTextareaField(&textarea_text); |
| 1342 |
| 1343 // Sentence navigation is not currently implemented. |
| 1344 LONG start_offset = 0; |
| 1345 LONG end_offset = 0; |
| 1346 base::win::ScopedBstr text; |
| 1347 HRESULT hr = textarea_text->get_textAtOffset( |
| 1348 25, IA2_TEXT_BOUNDARY_SENTENCE, |
| 1349 &start_offset, &end_offset, text.Receive()); |
| 1350 EXPECT_EQ(S_FALSE, hr); |
| 1351 } |
| 1352 |
| 1353 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1354 TestTextAtOffsetWithBoundaryLine) { |
| 1355 base::win::ScopedComPtr<IAccessibleText> input_text; |
| 1356 SetUpInputField(&input_text); |
| 1357 |
| 1358 // Single line text fields should return the whole text. |
| 1359 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_LINE, |
| 1360 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS)); |
| 1361 |
| 1362 // Test special offsets. |
| 1363 CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_LINE, |
| 1364 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS)); |
| 1365 CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_OFFSET_CARET, |
| 1366 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS)); |
| 1367 } |
| 1368 |
| 1369 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1370 TestMultiLineTextAtOffsetWithBoundaryLine) { |
| 1371 base::win::ScopedComPtr<IAccessibleText> textarea_text; |
| 1372 SetUpInputField(&input_text); |
| 1373 |
| 1374 CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_LINE, |
| 1375 0, 24, L"Moz/5.0 (ST 6.x; WWW33)\n"); |
| 1376 |
| 1377 // If the offset is at the newline, return the line preceding it. |
| 1378 CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_LINE, |
| 1379 24, 32, L"WebKit \n"); |
| 1380 |
| 1381 // Last line does not have a trailing newline. |
| 1382 CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_LINE, |
| 1383 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); |
| 1384 |
| 1385 // An offset one past the last character should return the last line. |
| 1386 CheckTextAtOffset(textarea_text, CONTENTS_LENGTH, IA2_TEXT_BOUNDARY_LINE, |
| 1387 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); |
| 1388 |
| 1389 // Test special offsets. |
| 1390 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_LENGTH, |
| 1391 IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); |
| 1392 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET, |
| 1393 IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); |
| 1394 } |
| 1395 |
| 1396 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1397 TestTextAtOffsetWithBoundaryAll) { |
| 1398 base::win::ScopedComPtr<IAccessibleText> input_text; |
| 1399 SetUpInputField(&input_text); |
| 1400 |
| 1401 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL, |
| 1402 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS)); |
| 1403 } |
| 1404 |
| 1405 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 1406 TestMultiLineTextAtOffsetWithBoundaryAll) { |
| 1407 base::win::ScopedComPtr<IAccessibleText> textarea_text; |
| 1408 SetUpTextAreaField(&textarea_text); |
| 1409 |
| 1410 CheckTextAtOffset(textarea_text, CONTENTS_LENGTH - 1, IA2_TEXT_BOUNDARY_ALL, |
| 1411 0, CONTENTS_LENGTH, base::SysUTF8ToWide(TEXTAREA_CONTENTS)); |
| 1412 } |
| 1413 |
757 } // namespace content | 1414 } // namespace content |
OLD | NEW |