Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: content/browser/accessibility/accessibility_win_browsertest.cc

Issue 660633002: Fixed IAccessibleText::TextAtOffset with IA2_TEXT_BOUNDARY_WORD to return text that spans from the … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moved manual test changes to another branch. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698