Chromium Code Reviews| 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 |