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

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: Fixed word navigation on Windows and added browser tests. Created 5 years, 9 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
« no previous file with comments | « no previous file | content/browser/accessibility/browser_accessibility.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
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
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
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;
dmazzoni 2015/02/25 00:34:49 nit: indentation is wrong here, should be two spac
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
OLDNEW
« no previous file with comments | « no previous file | content/browser/accessibility/browser_accessibility.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698