OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <vector> | 5 #include <vector> |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/sys_string_conversions.h" |
9 #include "base/win/scoped_bstr.h" | 9 #include "base/win/scoped_bstr.h" |
10 #include "base/win/scoped_comptr.h" | 10 #include "base/win/scoped_comptr.h" |
11 #include "base/win/scoped_variant.h" | 11 #include "base/win/scoped_variant.h" |
12 #include "content/browser/accessibility/accessibility_mode_helper.h" | 12 #include "content/browser/accessibility/accessibility_mode_helper.h" |
13 #include "content/browser/accessibility/accessibility_tree_formatter.h" | |
13 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h " | 14 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h " |
14 #include "content/browser/renderer_host/render_view_host_impl.h" | 15 #include "content/browser/renderer_host/render_view_host_impl.h" |
15 #include "content/public/browser/notification_service.h" | 16 #include "content/public/browser/notification_service.h" |
16 #include "content/public/browser/notification_types.h" | 17 #include "content/public/browser/notification_types.h" |
17 #include "content/public/browser/render_frame_host.h" | 18 #include "content/public/browser/render_frame_host.h" |
18 #include "content/public/browser/render_widget_host_view.h" | 19 #include "content/public/browser/render_widget_host_view.h" |
19 #include "content/public/browser/web_contents.h" | 20 #include "content/public/browser/web_contents.h" |
20 #include "content/public/common/url_constants.h" | 21 #include "content/public/common/url_constants.h" |
21 #include "content/public/test/content_browser_test.h" | 22 #include "content/public/test/content_browser_test.h" |
22 #include "content/public/test/content_browser_test_utils.h" | 23 #include "content/public/test/content_browser_test_utils.h" |
23 #include "content/shell/browser/shell.h" | 24 #include "content/shell/browser/shell.h" |
24 #include "content/test/accessibility_browser_test_utils.h" | 25 #include "content/test/accessibility_browser_test_utils.h" |
26 #include "net/base/escape.h" | |
25 #include "third_party/iaccessible2/ia2_api_all.h" | 27 #include "third_party/iaccessible2/ia2_api_all.h" |
26 #include "third_party/isimpledom/ISimpleDOMNode.h" | 28 #include "third_party/isimpledom/ISimpleDOMNode.h" |
27 #include "ui/aura/window.h" | 29 #include "ui/aura/window.h" |
28 #include "ui/aura/window_tree_host.h" | 30 #include "ui/aura/window_tree_host.h" |
29 | 31 |
30 namespace content { | 32 namespace content { |
31 | 33 |
32 namespace { | 34 namespace { |
33 | 35 |
34 // Helpers -------------------------------------------------------------------- | |
35 | 36 |
36 base::win::ScopedComPtr<IAccessible> GetAccessibleFromResultVariant( | 37 const char INPUT_CONTENTS[] = "Moz/5.0 (ST 6.x; WWW33) " |
38 "WebKit \"KHTML, like\"."; | |
39 const char TEXTAREA_CONTENTS[] = "Moz/5.0 (ST 6.x; WWW33)\n" | |
40 "WebKit \n\"KHTML, like\"."; | |
41 const LONG CONTENTS_LENGTH = static_cast<LONG>( | |
42 (sizeof(INPUT_CONTENTS) - 1) / sizeof(char)); | |
43 | |
44 | |
45 // AccessibilityWinBrowserTest ------------------------------------------------ | |
46 | |
47 class AccessibilityWinBrowserTest : public ContentBrowserTest { | |
48 public: | |
49 AccessibilityWinBrowserTest(); | |
50 virtual ~AccessibilityWinBrowserTest(); | |
51 | |
52 protected: | |
53 class AccessibleChecker; | |
54 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); | |
55 IAccessible* GetRendererAccessible(); | |
56 void ExecuteScript(const std::wstring& script); | |
57 void SetUpInputField( | |
58 base::win::ScopedComPtr<IAccessibleText>* input_text); | |
59 void SetUpTextareaField( | |
60 base::win::ScopedComPtr<IAccessibleText>* textarea_text); | |
61 | |
62 | |
63 static base::win::ScopedComPtr<IAccessible> | |
64 AccessibilityWinBrowserTest::GetAccessibleFromVariant( | |
65 IAccessible* parent, | |
66 VARIANT* var); | |
67 static HRESULT QueryIAccessible2(IAccessible* accessible, | |
68 IAccessible2** accessible2); | |
69 static void FindNodeInAccessibilityTree(IAccessible* node, | |
70 int32 expected_role, | |
71 const std::wstring& expected_name, | |
72 int32 depth, | |
73 bool* found); | |
74 static void CheckTextAtOffset( | |
75 base::win::ScopedComPtr<IAccessibleText>& element, | |
76 LONG offset, | |
77 IA2TextBoundaryType boundary_type, | |
78 LONG expected_start_offset, | |
79 LONG expected_end_offset, | |
80 const std::wstring& expected_text); | |
81 static std::vector<base::win::ScopedVariant> GetAllAccessibleChildren( | |
82 IAccessible* element); | |
83 | |
84 private: | |
85 DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest); | |
86 }; | |
87 | |
88 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() { | |
89 } | |
90 | |
91 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() { | |
92 } | |
93 | |
94 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml( | |
95 const std::string& html) { | |
96 AccessibilityNotificationWaiter waiter( | |
97 shell(), AccessibilityModeComplete, | |
98 ui::AX_EVENT_LOAD_COMPLETE); | |
99 GURL html_data_url("data:text/html," + html); | |
100 NavigateToURL(shell(), html_data_url); | |
101 waiter.WaitForNotification(); | |
102 } | |
103 | |
104 // Retrieve the MSAA client accessibility object for the Render Widget Host View | |
105 // of the selected tab. | |
106 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() { | |
107 content::WebContents* web_contents = shell()->web_contents(); | |
108 base::string16 contents; | |
109 AccessibilityTreeFormatter* atf = AccessibilityTreeFormatter::Create( | |
dmazzoni
2015/02/20 22:43:06
Can you remove this logging when done?
If you wan
| |
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 HRESULT hr = QueryIAccessible2(GetAccessibleFromVariant( | |
185 document.get(), document_children[0].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, textarea_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); | |
dmazzoni
2015/02/20 22:43:06
This is asynchronous
| |
208 ASSERT_EQ(S_OK, hr); | |
209 } | |
210 | |
211 | |
212 // Static helpers ------------------------------------------------ | |
213 | |
214 base::win::ScopedComPtr<IAccessible> | |
215 AccessibilityWinBrowserTest::GetAccessibleFromVariant( | |
37 IAccessible* parent, | 216 IAccessible* parent, |
38 VARIANT* var) { | 217 VARIANT* var) { |
39 base::win::ScopedComPtr<IAccessible> ptr; | 218 base::win::ScopedComPtr<IAccessible> ptr; |
40 switch (V_VT(var)) { | 219 switch (V_VT(var)) { |
41 case VT_DISPATCH: { | 220 case VT_DISPATCH: { |
42 IDispatch* dispatch = V_DISPATCH(var); | 221 IDispatch* dispatch = V_DISPATCH(var); |
43 if (dispatch) | 222 if (dispatch) |
44 ptr.QueryFrom(dispatch); | 223 dispatch->QueryInterface(ptr.Receive()); |
45 break; | 224 break; |
46 } | 225 } |
47 | 226 |
48 case VT_I4: { | 227 case VT_I4: { |
49 base::win::ScopedComPtr<IDispatch> dispatch; | 228 base::win::ScopedComPtr<IDispatch> dispatch; |
50 HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); | 229 HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); |
51 EXPECT_TRUE(SUCCEEDED(hr)); | 230 EXPECT_TRUE(SUCCEEDED(hr)); |
52 if (dispatch.get()) | 231 if (dispatch.get()) |
53 dispatch.QueryInterface(ptr.Receive()); | 232 dispatch.QueryInterface(ptr.Receive()); |
54 break; | 233 break; |
55 } | 234 } |
56 } | 235 } |
57 return ptr; | 236 return ptr; |
58 } | 237 } |
59 | 238 |
60 HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) { | 239 HRESULT AccessibilityWinBrowserTest::QueryIAccessible2( |
61 // TODO(ctguil): For some reason querying the IAccessible2 interface from | 240 IAccessible* accessible, |
62 // IAccessible fails. | 241 IAccessible2** accessible2) { |
242 // IA2 Spec dictates that IServiceProvider should be used instead of | |
243 // QueryInterface when retrieving IAccessible2. | |
63 base::win::ScopedComPtr<IServiceProvider> service_provider; | 244 base::win::ScopedComPtr<IServiceProvider> service_provider; |
64 HRESULT hr = accessible->QueryInterface(service_provider.Receive()); | 245 HRESULT hr = accessible->QueryInterface(service_provider.Receive()); |
65 return SUCCEEDED(hr) ? | 246 return SUCCEEDED(hr) ? |
66 service_provider->QueryService(IID_IAccessible2, accessible2) : hr; | 247 service_provider->QueryService(IID_IAccessible2, accessible2) : hr; |
67 } | 248 } |
68 | 249 |
69 // Recursively search through all of the descendants reachable from an | 250 // Recursively search through all of the descendants reachable from an |
70 // IAccessible node and return true if we find one with the given role | 251 // IAccessible node and return true if we find one with the given role |
71 // and name. | 252 // and name. |
72 void RecursiveFindNodeInAccessibilityTree(IAccessible* node, | 253 void AccessibilityWinBrowserTest::FindNodeInAccessibilityTree( |
73 int32 expected_role, | 254 IAccessible* node, |
74 const std::wstring& expected_name, | 255 int32 expected_role, |
75 int32 depth, | 256 const std::wstring& expected_name, |
76 bool* found) { | 257 int32 depth, |
258 bool* found) { | |
77 base::win::ScopedBstr name_bstr; | 259 base::win::ScopedBstr name_bstr; |
78 base::win::ScopedVariant childid_self(CHILDID_SELF); | 260 base::win::ScopedVariant childid_self(CHILDID_SELF); |
79 node->get_accName(childid_self, name_bstr.Receive()); | 261 node->get_accName(childid_self, name_bstr.Receive()); |
80 std::wstring name(name_bstr, name_bstr.Length()); | 262 std::wstring name(name_bstr, name_bstr.Length()); |
81 base::win::ScopedVariant role; | 263 base::win::ScopedVariant role; |
82 node->get_accRole(childid_self, role.Receive()); | 264 node->get_accRole(childid_self, role.Receive()); |
83 ASSERT_EQ(VT_I4, role.type()); | 265 ASSERT_EQ(VT_I4, role.type()); |
84 | 266 |
85 // Print the accessibility tree as we go, because if this test fails | 267 // Print the accessibility tree as we go, because if this test fails |
86 // on the bots, this is really helpful in figuring out why. | 268 // on the bots, this is really helpful in figuring out why. |
87 for (int i = 0; i < depth; i++) | 269 for (int i = 0; i < depth; i++) |
88 printf(" "); | 270 printf(" "); |
89 printf("role=%s name=%s\n", | 271 printf("role=%s name=%s\n", |
90 base::WideToUTF8(IAccessibleRoleToString(V_I4(&role))).c_str(), | 272 base::WideToUTF8(IAccessibleRoleToString(V_I4(&role))).c_str(), |
91 base::WideToUTF8(name).c_str()); | 273 base::WideToUTF8(name).c_str()); |
92 | 274 |
93 if (expected_role == V_I4(&role) && expected_name == name) { | 275 if (expected_role == V_I4(&role) && expected_name == name) { |
94 *found = true; | 276 *found = true; |
95 return; | 277 return; |
96 } | 278 } |
97 | 279 |
98 LONG child_count = 0; | 280 std::vector<base::win::ScopedVariant> children = GetAllAccessibleChildren( |
99 HRESULT hr = node->get_accChildCount(&child_count); | 281 node); |
100 ASSERT_EQ(S_OK, hr); | 282 for (size_t i = 0; i < children.size(); ++i) { |
101 | |
102 scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]); | |
103 LONG obtained_count = 0; | |
104 hr = AccessibleChildren( | |
105 node, 0, child_count, child_array.get(), &obtained_count); | |
106 ASSERT_EQ(S_OK, hr); | |
107 ASSERT_EQ(child_count, obtained_count); | |
108 | |
109 for (int index = 0; index < obtained_count; index++) { | |
110 base::win::ScopedComPtr<IAccessible> child_accessible( | 283 base::win::ScopedComPtr<IAccessible> child_accessible( |
111 GetAccessibleFromResultVariant(node, &child_array.get()[index])); | 284 GetAccessibleFromVariant(node, children[i].AsInput())); |
112 if (child_accessible.get()) { | 285 if (child_accessible) { |
113 RecursiveFindNodeInAccessibilityTree( | 286 FindNodeInAccessibilityTree( |
114 child_accessible.get(), expected_role, expected_name, depth + 1, | 287 child_accessible.get(), expected_role, expected_name, depth + 1, |
115 found); | 288 found); |
116 if (*found) | 289 if (*found) |
117 return; | 290 return; |
118 } | 291 } |
119 } | 292 } |
120 } | 293 } |
121 | 294 |
295 // Ensures that the text and the start and end offsets retrieved using | |
296 // get_textAtOffset match the expected values. | |
297 void AccessibilityWinBrowserTest::CheckTextAtOffset( | |
298 base::win::ScopedComPtr<IAccessibleText>& element, | |
299 LONG offset, | |
300 IA2TextBoundaryType boundary_type, | |
301 LONG expected_start_offset, | |
302 LONG expected_end_offset, | |
303 const std::wstring& expected_text) { | |
304 testing::Message message; | |
305 message << "While checking for \'" << expected_text << "\' at " << | |
306 expected_start_offset << '-' << expected_end_offset << '.'; | |
307 SCOPED_TRACE(message); | |
122 | 308 |
123 // AccessibilityWinBrowserTest ------------------------------------------------ | 309 LONG start_offset = 0; |
124 | 310 LONG end_offset = 0; |
125 class AccessibilityWinBrowserTest : public ContentBrowserTest { | 311 base::win::ScopedBstr text; |
126 public: | 312 HRESULT hr = element->get_textAtOffset( |
127 AccessibilityWinBrowserTest(); | 313 offset, boundary_type, |
128 virtual ~AccessibilityWinBrowserTest(); | 314 &start_offset, &end_offset, text.Receive()); |
129 | 315 EXPECT_EQ(S_OK, hr); |
130 protected: | 316 EXPECT_EQ(expected_start_offset, start_offset); |
131 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); | 317 EXPECT_EQ(expected_end_offset, end_offset); |
132 IAccessible* GetRendererAccessible(); | 318 EXPECT_EQ(expected_text, std::wstring(text, text.Length())); |
133 void ExecuteScript(const std::wstring& script); | |
134 | |
135 private: | |
136 DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest); | |
137 }; | |
138 | |
139 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() { | |
140 } | 319 } |
141 | 320 |
142 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() { | 321 std::vector<base::win::ScopedVariant> |
143 } | 322 AccessibilityWinBrowserTest::GetAllAccessibleChildren( |
323 IAccessible* element) { | |
324 LONG child_count = 0; | |
325 HRESULT hr = element->get_accChildCount(&child_count); | |
326 EXPECT_EQ(S_OK, hr); | |
327 if (child_count <= 0) | |
328 return std::vector<base::win::ScopedVariant>(); | |
144 | 329 |
145 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml( | 330 scoped_ptr<VARIANT[]> children_array(new VARIANT[child_count]); |
146 const std::string& html) { | 331 LONG obtained_count = 0; |
147 AccessibilityNotificationWaiter waiter( | 332 hr = AccessibleChildren( |
148 shell(), AccessibilityModeComplete, | 333 element, 0, child_count, children_array.get(), &obtained_count); |
149 ui::AX_EVENT_LOAD_COMPLETE); | 334 EXPECT_EQ(S_OK, hr); |
150 GURL html_data_url("data:text/html," + html); | 335 EXPECT_EQ(child_count, obtained_count); |
151 NavigateToURL(shell(), html_data_url); | |
152 waiter.WaitForNotification(); | |
153 } | |
154 | 336 |
155 // Retrieve the MSAA client accessibility object for the Render Widget Host View | 337 std::vector<base::win::ScopedVariant> children( |
156 // of the selected tab. | 338 static_cast<size_t>(child_count)); |
157 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() { | 339 for (size_t i = 0; i < children.size(); i++) { |
158 content::WebContents* web_contents = shell()->web_contents(); | 340 children[i].Reset(children_array[i]); |
159 return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible(); | 341 } |
160 } | 342 return children; |
161 | |
162 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) { | |
163 shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script); | |
164 } | 343 } |
165 | 344 |
166 | 345 |
167 // AccessibleChecker ---------------------------------------------------------- | 346 // AccessibleChecker ---------------------------------------------------------- |
168 | 347 |
169 class AccessibleChecker { | 348 class AccessibilityWinBrowserTest::AccessibleChecker { |
170 public: | 349 public: |
171 // This constructor can be used if the IA2 role will be the same as the MSAA | 350 // This constructor can be used if the IA2 role will be the same as the MSAA |
172 // role. | 351 // role. |
173 AccessibleChecker(const std::wstring& expected_name, | 352 AccessibleChecker(const std::wstring& expected_name, |
174 int32 expected_role, | 353 int32 expected_role, |
175 const std::wstring& expected_value); | 354 const std::wstring& expected_value); |
176 AccessibleChecker(const std::wstring& expected_name, | 355 AccessibleChecker(const std::wstring& expected_name, |
177 int32 expected_role, | 356 int32 expected_role, |
178 int32 expected_ia2_role, | 357 int32 expected_ia2_role, |
179 const std::wstring& expected_value); | 358 const std::wstring& expected_value); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 std::wstring value_; | 400 std::wstring value_; |
222 | 401 |
223 // Expected accessible state. Checked against IAccessible::get_accState. | 402 // Expected accessible state. Checked against IAccessible::get_accState. |
224 LONG state_; | 403 LONG state_; |
225 | 404 |
226 // Expected accessible children. Checked using IAccessible::get_accChildCount | 405 // Expected accessible children. Checked using IAccessible::get_accChildCount |
227 // and ::AccessibleChildren. | 406 // and ::AccessibleChildren. |
228 AccessibleCheckerVector children_; | 407 AccessibleCheckerVector children_; |
229 }; | 408 }; |
230 | 409 |
231 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 410 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
232 int32 expected_role, | 411 const std::wstring& expected_name, |
233 const std::wstring& expected_value) | 412 int32 expected_role, |
413 const std::wstring& expected_value) | |
234 : name_(expected_name), | 414 : name_(expected_name), |
235 role_(expected_role), | 415 role_(expected_role), |
236 ia2_role_(expected_role), | 416 ia2_role_(expected_role), |
237 value_(expected_value), | 417 value_(expected_value), |
238 state_(-1) { | 418 state_(-1) { |
239 } | 419 } |
240 | 420 |
241 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 421 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
242 int32 expected_role, | 422 const std::wstring& expected_name, |
243 int32 expected_ia2_role, | 423 int32 expected_role, |
244 const std::wstring& expected_value) | 424 int32 expected_ia2_role, |
425 const std::wstring& expected_value) | |
245 : name_(expected_name), | 426 : name_(expected_name), |
246 role_(expected_role), | 427 role_(expected_role), |
247 ia2_role_(expected_ia2_role), | 428 ia2_role_(expected_ia2_role), |
248 value_(expected_value), | 429 value_(expected_value), |
249 state_(-1) { | 430 state_(-1) { |
250 } | 431 } |
251 | 432 |
252 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 433 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
253 const std::wstring& expected_role, | 434 const std::wstring& expected_name, |
254 int32 expected_ia2_role, | 435 const std::wstring& expected_role, |
255 const std::wstring& expected_value) | 436 int32 expected_ia2_role, |
437 const std::wstring& expected_value) | |
256 : name_(expected_name), | 438 : name_(expected_name), |
257 role_(expected_role.c_str()), | 439 role_(expected_role.c_str()), |
258 ia2_role_(expected_ia2_role), | 440 ia2_role_(expected_ia2_role), |
259 value_(expected_value), | 441 value_(expected_value), |
260 state_(-1) { | 442 state_(-1) { |
261 } | 443 } |
262 | 444 |
263 void AccessibleChecker::AppendExpectedChild( | 445 void AccessibilityWinBrowserTest::AccessibleChecker::AppendExpectedChild( |
264 AccessibleChecker* expected_child) { | 446 AccessibleChecker* expected_child) { |
265 children_.push_back(expected_child); | 447 children_.push_back(expected_child); |
266 } | 448 } |
267 | 449 |
268 void AccessibleChecker::CheckAccessible(IAccessible* accessible) { | 450 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessible( |
269 SCOPED_TRACE("while checking " + | 451 IAccessible* accessible) { |
270 base::UTF16ToUTF8(RoleVariantToString(role_))); | 452 SCOPED_TRACE("While checking " |
453 + base::UTF16ToUTF8(RoleVariantToString(role_))); | |
271 CheckAccessibleName(accessible); | 454 CheckAccessibleName(accessible); |
272 CheckAccessibleRole(accessible); | 455 CheckAccessibleRole(accessible); |
273 CheckIA2Role(accessible); | 456 CheckIA2Role(accessible); |
274 CheckAccessibleValue(accessible); | 457 CheckAccessibleValue(accessible); |
275 CheckAccessibleState(accessible); | 458 CheckAccessibleState(accessible); |
276 CheckAccessibleChildren(accessible); | 459 CheckAccessibleChildren(accessible); |
277 } | 460 } |
278 | 461 |
279 void AccessibleChecker::SetExpectedValue(const std::wstring& expected_value) { | 462 void AccessibilityWinBrowserTest::AccessibleChecker::SetExpectedValue( |
463 const std::wstring& expected_value) { | |
280 value_ = expected_value; | 464 value_ = expected_value; |
281 } | 465 } |
282 | 466 |
283 void AccessibleChecker::SetExpectedState(LONG expected_state) { | 467 void AccessibilityWinBrowserTest::AccessibleChecker::SetExpectedState( |
468 LONG expected_state) { | |
284 state_ = expected_state; | 469 state_ = expected_state; |
285 } | 470 } |
286 | 471 |
287 void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) { | 472 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleName( |
473 IAccessible* accessible) { | |
288 base::win::ScopedBstr name; | 474 base::win::ScopedBstr name; |
289 base::win::ScopedVariant childid_self(CHILDID_SELF); | 475 base::win::ScopedVariant childid_self(CHILDID_SELF); |
290 HRESULT hr = accessible->get_accName(childid_self, name.Receive()); | 476 HRESULT hr = accessible->get_accName(childid_self, name.Receive()); |
291 | 477 |
292 if (name_.empty()) { | 478 if (name_.empty()) { |
293 // If the object doesn't have name S_FALSE should be returned. | 479 // If the object doesn't have name S_FALSE should be returned. |
294 EXPECT_EQ(S_FALSE, hr); | 480 EXPECT_EQ(S_FALSE, hr); |
295 } else { | 481 } else { |
296 // Test that the correct string was returned. | 482 // Test that the correct string was returned. |
297 EXPECT_EQ(S_OK, hr); | 483 EXPECT_EQ(S_OK, hr); |
298 EXPECT_EQ(name_, std::wstring(name, name.Length())); | 484 EXPECT_EQ(name_, std::wstring(name, name.Length())); |
299 } | 485 } |
300 } | 486 } |
301 | 487 |
302 void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) { | 488 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleRole( |
489 IAccessible* accessible) { | |
303 base::win::ScopedVariant role; | 490 base::win::ScopedVariant role; |
304 base::win::ScopedVariant childid_self(CHILDID_SELF); | 491 base::win::ScopedVariant childid_self(CHILDID_SELF); |
305 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); | 492 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); |
306 ASSERT_EQ(S_OK, hr); | 493 ASSERT_EQ(S_OK, hr); |
307 EXPECT_EQ(0, role_.Compare(role)) | 494 EXPECT_EQ(0, role_.Compare(role)) |
308 << "Expected role: " << RoleVariantToString(role_) | 495 << "Expected role: " << RoleVariantToString(role_) |
309 << "\nGot role: " << RoleVariantToString(role); | 496 << "\nGot role: " << RoleVariantToString(role); |
310 } | 497 } |
311 | 498 |
312 void AccessibleChecker::CheckIA2Role(IAccessible* accessible) { | 499 void AccessibilityWinBrowserTest::AccessibleChecker::CheckIA2Role( |
500 IAccessible* accessible) { | |
313 base::win::ScopedComPtr<IAccessible2> accessible2; | 501 base::win::ScopedComPtr<IAccessible2> accessible2; |
314 HRESULT hr = QueryIAccessible2(accessible, accessible2.Receive()); | 502 HRESULT hr = QueryIAccessible2(accessible, accessible2.Receive()); |
315 ASSERT_EQ(S_OK, hr); | 503 ASSERT_EQ(S_OK, hr); |
316 long ia2_role = 0; | 504 long ia2_role = 0; |
317 hr = accessible2->role(&ia2_role); | 505 hr = accessible2->role(&ia2_role); |
318 ASSERT_EQ(S_OK, hr); | 506 ASSERT_EQ(S_OK, hr); |
319 EXPECT_EQ(ia2_role_, ia2_role) | 507 EXPECT_EQ(ia2_role_, ia2_role) |
320 << "Expected ia2 role: " << IAccessible2RoleToString(ia2_role_) | 508 << "Expected ia2 role: " << IAccessible2RoleToString(ia2_role_) |
321 << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role); | 509 << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role); |
322 } | 510 } |
323 | 511 |
324 void AccessibleChecker::CheckAccessibleValue(IAccessible* accessible) { | 512 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleValue( |
513 IAccessible* accessible) { | |
325 // Don't check the value if if's a DOCUMENT role, because the value | 514 // Don't check the value if if's a DOCUMENT role, because the value |
326 // is supposed to be the url (and we don't keep track of that in the | 515 // is supposed to be the url (and we don't keep track of that in the |
327 // test expectations). | 516 // test expectations). |
328 base::win::ScopedVariant role; | 517 base::win::ScopedVariant role; |
329 base::win::ScopedVariant childid_self(CHILDID_SELF); | 518 base::win::ScopedVariant childid_self(CHILDID_SELF); |
330 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); | 519 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); |
331 ASSERT_EQ(S_OK, hr); | 520 ASSERT_EQ(S_OK, hr); |
332 if (role.type() == VT_I4 && V_I4(&role) == ROLE_SYSTEM_DOCUMENT) | 521 if (role.type() == VT_I4 && V_I4(&role) == ROLE_SYSTEM_DOCUMENT) |
333 return; | 522 return; |
334 | 523 |
335 // Get the value. | 524 // Get the value. |
336 base::win::ScopedBstr value; | 525 base::win::ScopedBstr value; |
337 hr = accessible->get_accValue(childid_self, value.Receive()); | 526 hr = accessible->get_accValue(childid_self, value.Receive()); |
338 EXPECT_EQ(S_OK, hr); | 527 EXPECT_EQ(S_OK, hr); |
339 | 528 |
340 // Test that the correct string was returned. | 529 // Test that the correct string was returned. |
341 EXPECT_EQ(value_, std::wstring(value, value.Length())); | 530 EXPECT_EQ(value_, std::wstring(value, value.Length())); |
342 } | 531 } |
343 | 532 |
344 void AccessibleChecker::CheckAccessibleState(IAccessible* accessible) { | 533 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleState( |
534 IAccessible* accessible) { | |
345 if (state_ < 0) | 535 if (state_ < 0) |
346 return; | 536 return; |
347 | 537 |
348 base::win::ScopedVariant state; | 538 base::win::ScopedVariant state; |
349 base::win::ScopedVariant childid_self(CHILDID_SELF); | 539 base::win::ScopedVariant childid_self(CHILDID_SELF); |
350 HRESULT hr = accessible->get_accState(childid_self, state.Receive()); | 540 HRESULT hr = accessible->get_accState(childid_self, state.Receive()); |
351 EXPECT_EQ(S_OK, hr); | 541 EXPECT_EQ(S_OK, hr); |
352 ASSERT_EQ(VT_I4, state.type()); | 542 ASSERT_EQ(VT_I4, state.type()); |
353 LONG obj_state = V_I4(&state); | 543 LONG obj_state = V_I4(&state); |
354 // Avoid flakiness. The "offscreen" state depends on whether the browser | 544 // Avoid flakiness. The "offscreen" state depends on whether the browser |
355 // window is frontmost or not, and "hottracked" depends on whether the | 545 // window is frontmost or not, and "hottracked" depends on whether the |
356 // mouse cursor happens to be over the element. | 546 // mouse cursor happens to be over the element. |
357 obj_state &= ~(STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_HOTTRACKED); | 547 obj_state &= ~(STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_HOTTRACKED); |
358 EXPECT_EQ(state_, obj_state) | 548 EXPECT_EQ(state_, obj_state) |
359 << "Expected state: " << IAccessibleStateToString(state_) | 549 << "Expected state: " << IAccessibleStateToString(state_) |
360 << "\nGot state: " << IAccessibleStateToString(obj_state); | 550 << "\nGot state: " << IAccessibleStateToString(obj_state); |
361 } | 551 } |
362 | 552 |
363 void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) { | 553 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleChildren( |
364 LONG child_count = 0; | 554 IAccessible* parent) { |
365 HRESULT hr = parent->get_accChildCount(&child_count); | 555 std::vector<base::win::ScopedVariant> obtained_children = |
366 EXPECT_EQ(S_OK, hr); | 556 GetAllAccessibleChildren(parent); |
557 size_t child_count = obtained_children.size(); | |
367 ASSERT_EQ(child_count, children_.size()); | 558 ASSERT_EQ(child_count, children_.size()); |
368 | 559 |
369 scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]); | 560 AccessibleCheckerVector::iterator child_checker; |
370 LONG obtained_count = 0; | 561 std::vector<base::win::ScopedVariant>::iterator child; |
371 hr = AccessibleChildren(parent, 0, child_count, | 562 for (child_checker = children_.begin(), |
372 child_array.get(), &obtained_count); | 563 child = obtained_children.begin(); |
373 ASSERT_EQ(S_OK, hr); | 564 child_checker != children_.end() |
374 ASSERT_EQ(child_count, obtained_count); | 565 && child != obtained_children.end(); |
375 | |
376 VARIANT* child = child_array.get(); | |
377 for (AccessibleCheckerVector::iterator child_checker = children_.begin(); | |
378 child_checker != children_.end(); | |
379 ++child_checker, ++child) { | 566 ++child_checker, ++child) { |
380 base::win::ScopedComPtr<IAccessible> child_accessible( | 567 base::win::ScopedComPtr<IAccessible> child_accessible( |
381 GetAccessibleFromResultVariant(parent, child)); | 568 GetAccessibleFromVariant(parent, child->AsInput())); |
382 ASSERT_TRUE(child_accessible.get()); | 569 ASSERT_TRUE(child_accessible.get()); |
383 (*child_checker)->CheckAccessible(child_accessible.get()); | 570 (*child_checker)->CheckAccessible(child_accessible.get()); |
384 } | 571 } |
385 } | 572 } |
386 | 573 |
387 base::string16 AccessibleChecker::RoleVariantToString( | 574 base::string16 |
575 AccessibilityWinBrowserTest::AccessibleChecker::RoleVariantToString( | |
388 const base::win::ScopedVariant& role) { | 576 const base::win::ScopedVariant& role) { |
389 if (role.type() == VT_I4) | 577 if (role.type() == VT_I4) |
390 return IAccessibleRoleToString(V_I4(&role)); | 578 return IAccessibleRoleToString(V_I4(&role)); |
391 if (role.type() == VT_BSTR) | 579 if (role.type() == VT_BSTR) |
392 return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role))); | 580 return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role))); |
393 return base::string16(); | 581 return base::string16(); |
394 } | 582 } |
395 | 583 |
396 } // namespace | 584 } // namespace |
397 | 585 |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
660 CHECK(hwnd); | 848 CHECK(hwnd); |
661 base::win::ScopedComPtr<IAccessible> browser_accessible; | 849 base::win::ScopedComPtr<IAccessible> browser_accessible; |
662 HRESULT hr = AccessibleObjectFromWindow( | 850 HRESULT hr = AccessibleObjectFromWindow( |
663 hwnd, | 851 hwnd, |
664 OBJID_WINDOW, | 852 OBJID_WINDOW, |
665 IID_IAccessible, | 853 IID_IAccessible, |
666 reinterpret_cast<void**>(browser_accessible.Receive())); | 854 reinterpret_cast<void**>(browser_accessible.Receive())); |
667 ASSERT_EQ(S_OK, hr); | 855 ASSERT_EQ(S_OK, hr); |
668 | 856 |
669 bool found = false; | 857 bool found = false; |
670 RecursiveFindNodeInAccessibilityTree( | 858 FindNodeInAccessibilityTree( |
671 browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found); | 859 browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found); |
672 ASSERT_EQ(found, true); | 860 ASSERT_EQ(found, true); |
673 } | 861 } |
674 | 862 |
675 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | 863 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
676 SupportsISimpleDOM) { | 864 SupportsISimpleDOM) { |
677 LoadInitialAccessibilityTreeFromHtml( | 865 LoadInitialAccessibilityTreeFromHtml( |
678 "<body><input type='checkbox' /></body>"); | 866 "<body><input type='checkbox' /></body>"); |
679 | 867 |
680 // Get the IAccessible object for the document. | 868 // Get the IAccessible object for the document. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
747 std::wstring()); | 935 std::wstring()); |
748 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, | 936 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, |
749 std::wstring()); | 937 std::wstring()); |
750 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, | 938 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, |
751 std::wstring()); | 939 std::wstring()); |
752 document_checker.AppendExpectedChild(&grouping1_checker); | 940 document_checker.AppendExpectedChild(&grouping1_checker); |
753 document_checker.AppendExpectedChild(&grouping2_checker); | 941 document_checker.AppendExpectedChild(&grouping2_checker); |
754 document_checker.CheckAccessible(GetRendererAccessible()); | 942 document_checker.CheckAccessible(GetRendererAccessible()); |
755 } | 943 } |
756 | 944 |
945 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
946 TestTextAtOffsetWithInvalidArgs) { | |
947 base::win::ScopedComPtr<IAccessibleText> input_text; | |
948 SetUpInputField(&input_text); | |
949 HRESULT hr = input_text->get_textAtOffset( | |
950 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); | |
951 EXPECT_EQ(E_INVALIDARG, hr); | |
952 | |
953 // Test invalid offset. | |
954 LONG start_offset = 0; | |
955 LONG end_offset = 0; | |
956 base::win::ScopedBstr text; | |
957 LONG invalid_offset = -5; | |
958 hr = input_text->get_textAtOffset( | |
959 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
960 &start_offset, &end_offset, text.Receive()); | |
961 EXPECT_EQ(E_INVALIDARG, hr); | |
962 EXPECT_EQ(0, start_offset); | |
963 EXPECT_EQ(0, end_offset); | |
964 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
965 invalid_offset = CONTENTS_LENGTH + 1; | |
966 hr = input_text->get_textAtOffset( | |
967 invalid_offset, IA2_TEXT_BOUNDARY_WORD, | |
968 &start_offset, &end_offset, text.Receive()); | |
969 EXPECT_EQ(E_INVALIDARG, hr); | |
970 EXPECT_EQ(0, start_offset); | |
971 EXPECT_EQ(0, end_offset); | |
972 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
973 | |
974 // According to the IA2 Spec, only line boundaries should succeed when | |
975 // the offset is one past the end of the text. | |
976 invalid_offset = CONTENTS_LENGTH; | |
977 hr = input_text->get_textAtOffset( | |
978 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
979 &start_offset, &end_offset, text.Receive()); | |
980 EXPECT_EQ(S_FALSE, hr); | |
981 EXPECT_EQ(0, start_offset); | |
982 EXPECT_EQ(0, end_offset); | |
983 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
984 hr = input_text->get_textAtOffset( | |
985 invalid_offset, IA2_TEXT_BOUNDARY_WORD, | |
986 &start_offset, &end_offset, text.Receive()); | |
987 EXPECT_EQ(S_FALSE, hr); | |
988 EXPECT_EQ(0, start_offset); | |
989 EXPECT_EQ(0, end_offset); | |
990 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
991 hr = input_text->get_textAtOffset( | |
992 invalid_offset, IA2_TEXT_BOUNDARY_SENTENCE, | |
993 &start_offset, &end_offset, text.Receive()); | |
994 EXPECT_EQ(S_FALSE, hr); | |
995 EXPECT_EQ(0, start_offset); | |
996 EXPECT_EQ(0, end_offset); | |
997 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
998 hr = input_text->get_textAtOffset( | |
999 invalid_offset, IA2_TEXT_BOUNDARY_ALL, | |
1000 &start_offset, &end_offset, text.Receive()); | |
1001 EXPECT_EQ(S_FALSE, hr); | |
1002 EXPECT_EQ(0, start_offset); | |
1003 EXPECT_EQ(0, end_offset); | |
1004 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1005 | |
1006 // The same behavior should be observed when the special offset | |
1007 // IA2_TEXT_OFFSET_LENGTH is used. | |
1008 hr = input_text->get_textAtOffset( | |
1009 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_CHAR, | |
1010 &start_offset, &end_offset, text.Receive()); | |
1011 EXPECT_EQ(S_FALSE, hr); | |
1012 EXPECT_EQ(0, start_offset); | |
1013 EXPECT_EQ(0, end_offset); | |
1014 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1015 hr = input_text->get_textAtOffset( | |
1016 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_WORD, | |
1017 &start_offset, &end_offset, text.Receive()); | |
1018 EXPECT_EQ(S_FALSE, hr); | |
1019 EXPECT_EQ(0, start_offset); | |
1020 EXPECT_EQ(0, end_offset); | |
1021 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1022 hr = input_text->get_textAtOffset( | |
1023 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_SENTENCE, | |
1024 &start_offset, &end_offset, text.Receive()); | |
1025 EXPECT_EQ(S_FALSE, hr); | |
1026 EXPECT_EQ(0, start_offset); | |
1027 EXPECT_EQ(0, end_offset); | |
1028 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1029 hr = input_text->get_textAtOffset( | |
1030 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_ALL, | |
1031 &start_offset, &end_offset, text.Receive()); | |
1032 EXPECT_EQ(S_FALSE, hr); | |
1033 EXPECT_EQ(0, start_offset); | |
1034 EXPECT_EQ(0, end_offset); | |
1035 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1036 } | |
1037 | |
1038 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
1039 TestMultiLineTextAtOffsetWithInvalidArgs) { | |
1040 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
1041 SetUpTextareaField(&textarea_text); | |
1042 HRESULT hr = textarea_text->get_textAtOffset( | |
1043 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); | |
1044 EXPECT_EQ(E_INVALIDARG, hr); | |
1045 | |
1046 // Test invalid offset. | |
1047 LONG start_offset = 0; | |
1048 LONG end_offset = 0; | |
1049 base::win::ScopedBstr text; | |
1050 LONG invalid_offset = -5; | |
1051 hr = textarea_text->get_textAtOffset( | |
1052 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
1053 &start_offset, &end_offset, text.Receive()); | |
1054 EXPECT_EQ(E_INVALIDARG, hr); | |
1055 EXPECT_EQ(0, start_offset); | |
1056 EXPECT_EQ(0, end_offset); | |
1057 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1058 invalid_offset = CONTENTS_LENGTH + 1; | |
1059 hr = textarea_text->get_textAtOffset( | |
1060 invalid_offset, IA2_TEXT_BOUNDARY_WORD, | |
1061 &start_offset, &end_offset, text.Receive()); | |
1062 EXPECT_EQ(E_INVALIDARG, hr); | |
1063 EXPECT_EQ(0, start_offset); | |
1064 EXPECT_EQ(0, end_offset); | |
1065 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1066 | |
1067 // According to the IA2 Spec, only line boundaries should succeed when | |
1068 // the offset is one past the end of the text. | |
1069 invalid_offset = CONTENTS_LENGTH; | |
1070 hr = textarea_text->get_textAtOffset( | |
1071 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
1072 &start_offset, &end_offset, text.Receive()); | |
1073 EXPECT_EQ(S_FALSE, hr); | |
1074 EXPECT_EQ(0, start_offset); | |
1075 EXPECT_EQ(0, end_offset); | |
1076 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1077 hr = textarea_text->get_textAtOffset( | |
1078 invalid_offset, IA2_TEXT_BOUNDARY_WORD, | |
1079 &start_offset, &end_offset, text.Receive()); | |
1080 EXPECT_EQ(S_FALSE, hr); | |
1081 EXPECT_EQ(0, start_offset); | |
1082 EXPECT_EQ(0, end_offset); | |
1083 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1084 hr = textarea_text->get_textAtOffset( | |
1085 invalid_offset, IA2_TEXT_BOUNDARY_SENTENCE, | |
1086 &start_offset, &end_offset, text.Receive()); | |
1087 EXPECT_EQ(S_FALSE, hr); | |
1088 EXPECT_EQ(0, start_offset); | |
1089 EXPECT_EQ(0, end_offset); | |
1090 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1091 hr = textarea_text->get_textAtOffset( | |
1092 invalid_offset, IA2_TEXT_BOUNDARY_ALL, | |
1093 &start_offset, &end_offset, text.Receive()); | |
1094 EXPECT_EQ(S_FALSE, hr); | |
1095 EXPECT_EQ(0, start_offset); | |
1096 EXPECT_EQ(0, end_offset); | |
1097 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1098 | |
1099 // The same behavior should be observed when the special offset | |
1100 // IA2_TEXT_OFFSET_LENGTH is used. | |
1101 hr = textarea_text->get_textAtOffset( | |
1102 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_CHAR, | |
1103 &start_offset, &end_offset, text.Receive()); | |
1104 EXPECT_EQ(S_FALSE, hr); | |
1105 EXPECT_EQ(0, start_offset); | |
1106 EXPECT_EQ(0, end_offset); | |
1107 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1108 hr = textarea_text->get_textAtOffset( | |
1109 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_WORD, | |
1110 &start_offset, &end_offset, text.Receive()); | |
1111 EXPECT_EQ(S_FALSE, hr); | |
1112 EXPECT_EQ(0, start_offset); | |
1113 EXPECT_EQ(0, end_offset); | |
1114 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1115 hr = textarea_text->get_textAtOffset( | |
1116 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_SENTENCE, | |
1117 &start_offset, &end_offset, text.Receive()); | |
1118 EXPECT_EQ(S_FALSE, hr); | |
1119 EXPECT_EQ(0, start_offset); | |
1120 EXPECT_EQ(0, end_offset); | |
1121 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1122 hr = textarea_text->get_textAtOffset( | |
1123 IA2_TEXT_OFFSET_LENGTH, IA2_TEXT_BOUNDARY_ALL, | |
1124 &start_offset, &end_offset, text.Receive()); | |
1125 EXPECT_EQ(S_FALSE, hr); | |
1126 EXPECT_EQ(0, start_offset); | |
1127 EXPECT_EQ(0, end_offset); | |
1128 EXPECT_EQ(nullptr, static_cast<BSTR>(text)); | |
1129 } | |
1130 | |
1131 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
1132 TestTextAtOffsetWithBoundaryCharacter) { | |
1133 base::win::ScopedComPtr<IAccessibleText> input_text; | |
1134 SetUpInputField(&input_text); | |
1135 for (LONG offset = 0; offset < CONTENTS_LENGTH; ++offset) { | |
1136 std::wstring expected_text(1, INPUT_CONTENTS[offset]); | |
1137 LONG expected_start_offset = offset; | |
1138 LONG expected_end_offset = offset + 1; | |
1139 CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR, | |
1140 expected_start_offset, expected_end_offset, expected_text); | |
1141 } | |
1142 | |
1143 for (LONG offset = CONTENTS_LENGTH - 1; offset >= 0; --offset) { | |
1144 std::wstring expected_text(1, INPUT_CONTENTS[offset]); | |
1145 LONG expected_start_offset = offset; | |
1146 LONG expected_end_offset = offset + 1; | |
1147 CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR, | |
1148 expected_start_offset, expected_end_offset, expected_text); | |
1149 } | |
1150 | |
1151 CheckTextAtOffset(input_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_CARET, IA2_TEXT_BOUNDARY_LINE, | |
1366 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS)); | |
1367 } | |
1368 | |
1369 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
1370 TestMultiLineTextAtOffsetWithBoundaryLine) { | |
dmazzoni
2015/02/20 22:43:06
Are you going to delete this test?
| |
1371 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
1372 SetUpTextareaField(&textarea_text); | |
1373 | |
1374 CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_LINE, | |
1375 0, 24, L"Moz/5.0 (ST 6.x; WWW33)\n"); | |
1376 | |
1377 // If the offset is at the newline, return the line preceding it. | |
1378 CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_LINE, | |
1379 24, 32, L"WebKit \n"); | |
1380 | |
1381 // Last line does not have a trailing newline. | |
1382 CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_LINE, | |
1383 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); | |
1384 | |
1385 // An offset one past the last character should return the last line. | |
1386 CheckTextAtOffset(textarea_text, CONTENTS_LENGTH, IA2_TEXT_BOUNDARY_LINE, | |
1387 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); | |
1388 | |
1389 // Test special offsets. | |
1390 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_LENGTH, | |
1391 IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); | |
1392 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET, | |
1393 IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); | |
1394 } | |
1395 | |
1396 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
1397 TestTextAtOffsetWithBoundaryAll) { | |
1398 base::win::ScopedComPtr<IAccessibleText> input_text; | |
1399 SetUpInputField(&input_text); | |
1400 | |
1401 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL, | |
1402 0, CONTENTS_LENGTH, base::SysUTF8ToWide(INPUT_CONTENTS)); | |
1403 } | |
1404 | |
1405 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
1406 TestMultiLineTextAtOffsetWithBoundaryAll) { | |
1407 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
1408 SetUpTextareaField(&textarea_text); | |
1409 | |
1410 CheckTextAtOffset(textarea_text, CONTENTS_LENGTH - 1, IA2_TEXT_BOUNDARY_ALL, | |
1411 0, CONTENTS_LENGTH, base::SysUTF8ToWide(TEXTAREA_CONTENTS)); | |
1412 } | |
1413 | |
757 } // namespace content | 1414 } // namespace content |
OLD | NEW |