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