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 "net/base/escape.h" | |
|
dmazzoni
2014/11/17 19:06:46
nit: sort this
| |
| 8 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 9 #include "base/win/scoped_bstr.h" | 10 #include "base/win/scoped_bstr.h" |
| 10 #include "base/win/scoped_comptr.h" | 11 #include "base/win/scoped_comptr.h" |
| 11 #include "base/win/scoped_variant.h" | 12 #include "base/win/scoped_variant.h" |
| 12 #include "content/browser/accessibility/accessibility_mode_helper.h" | 13 #include "content/browser/accessibility/accessibility_mode_helper.h" |
| 14 #include "content/browser/accessibility/accessibility_tree_formatter.h" | |
| 13 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h " | 15 #include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h " |
| 14 #include "content/browser/renderer_host/render_view_host_impl.h" | 16 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 15 #include "content/public/browser/notification_service.h" | 17 #include "content/public/browser/notification_service.h" |
| 16 #include "content/public/browser/notification_types.h" | 18 #include "content/public/browser/notification_types.h" |
| 17 #include "content/public/browser/render_frame_host.h" | 19 #include "content/public/browser/render_frame_host.h" |
| 18 #include "content/public/browser/render_widget_host_view.h" | 20 #include "content/public/browser/render_widget_host_view.h" |
| 19 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
| 20 #include "content/public/common/url_constants.h" | 22 #include "content/public/common/url_constants.h" |
| 21 #include "content/public/test/content_browser_test.h" | 23 #include "content/public/test/content_browser_test.h" |
| 22 #include "content/public/test/content_browser_test_utils.h" | 24 #include "content/public/test/content_browser_test_utils.h" |
| 23 #include "content/shell/browser/shell.h" | 25 #include "content/shell/browser/shell.h" |
| 24 #include "content/test/accessibility_browser_test_utils.h" | 26 #include "content/test/accessibility_browser_test_utils.h" |
| 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 SetUpTextFields( | |
| 58 base::win::ScopedComPtr<IAccessibleText>* input_text, | |
| 59 base::win::ScopedComPtr<IAccessibleText>* textarea_text); | |
| 60 | |
| 61 static base::win::ScopedComPtr<IAccessible> | |
| 62 AccessibilityWinBrowserTest::GetAccessibleFromVariant( | |
| 63 IAccessible* parent, | |
| 64 VARIANT* var); | |
| 65 static HRESULT QueryIAccessible2(IAccessible* accessible, | |
| 66 IAccessible2** accessible2); | |
| 67 static void FindNodeInAccessibilityTree(IAccessible* node, | |
| 68 int32 expected_role, | |
| 69 const std::wstring& expected_name, | |
| 70 int32 depth, | |
| 71 bool* found); | |
| 72 static void CheckTextAtOffset(IAccessibleText* element, | |
| 73 LONG offset, | |
| 74 IA2TextBoundaryType boundary_type, | |
| 75 LONG expected_start_offset, | |
| 76 LONG expected_end_offset, | |
| 77 const std::wstring& expected_text); | |
| 78 static std::vector<base::win::ScopedVariant> GetAllAccessibleChildren( | |
| 79 IAccessible* element); | |
| 80 | |
| 81 private: | |
| 82 DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest); | |
| 83 }; | |
| 84 | |
| 85 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() { | |
| 86 } | |
| 87 | |
| 88 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() { | |
| 89 } | |
| 90 | |
| 91 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml( | |
| 92 const std::string& html) { | |
| 93 AccessibilityNotificationWaiter waiter( | |
| 94 shell(), AccessibilityModeComplete, | |
| 95 ui::AX_EVENT_LOAD_COMPLETE); | |
| 96 GURL html_data_url("data:text/html," + html); | |
| 97 NavigateToURL(shell(), html_data_url); | |
| 98 waiter.WaitForNotification(); | |
| 99 } | |
| 100 | |
| 101 // Retrieve the MSAA client accessibility object for the Render Widget Host View | |
| 102 // of the selected tab. | |
| 103 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() { | |
| 104 content::WebContents* web_contents = shell()->web_contents(); | |
| 105 base::string16 contents; | |
| 106 AccessibilityTreeFormatter* atf = AccessibilityTreeFormatter::Create(web_conte nts); | |
|
dmazzoni
2014/11/17 19:06:46
Use a scoped_ptr rather than manually deleting a p
| |
| 107 atf->FormatAccessibilityTree(&contents); | |
| 108 DLOG(INFO) << contents; | |
| 109 delete atf; | |
| 110 return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible(); | |
| 111 } | |
| 112 | |
| 113 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) { | |
| 114 shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script); | |
| 115 } | |
| 116 | |
| 117 // Loads a page with two text fields, one using the input and one the textarea | |
| 118 // tags, and places the same sample text in both. Also, places the caret on the | |
| 119 // last character. | |
| 120 // Returns true if successful and false otherwise. | |
|
dmazzoni
2014/11/17 19:06:46
nit: no longer returns a bool
| |
| 121 void AccessibilityWinBrowserTest::SetUpTextFields( | |
| 122 base::win::ScopedComPtr<IAccessibleText>* input_text, | |
| 123 base::win::ScopedComPtr<IAccessibleText>* textarea_text) { | |
| 124 ASSERT_NE(nullptr, input_text); | |
| 125 ASSERT_NE(nullptr, textarea_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><textarea rows='3' cols='60'>") + | |
| 132 net::EscapeQueryParamValue(TEXTAREA_CONTENTS, false) + std::string( | |
| 133 "</textarea></body></html>")); | |
| 134 | |
| 135 // Retrieve the IAccessible interface for the web page. | |
| 136 base::win::ScopedComPtr<IAccessible> document(GetRendererAccessible()); | |
| 137 std::vector<base::win::ScopedVariant> document_children = | |
| 138 GetAllAccessibleChildren(document); | |
| 139 ASSERT_EQ(2, document_children.size()); | |
| 140 | |
| 141 base::win::ScopedComPtr<IAccessible2> form; | |
| 142 HRESULT hr = QueryIAccessible2(GetAccessibleFromVariant( | |
| 143 document, document_children[0].AsInput()), form.Receive()); | |
| 144 ASSERT_EQ(S_OK, hr); | |
| 145 std::vector<base::win::ScopedVariant> form_children = | |
| 146 GetAllAccessibleChildren(form); | |
| 147 ASSERT_EQ(2, form_children.size()); | |
| 148 base::win::ScopedComPtr<IAccessible2> div; | |
| 149 hr = QueryIAccessible2(GetAccessibleFromVariant( | |
| 150 document, document_children[1].AsInput()), div.Receive()); | |
| 151 ASSERT_EQ(S_OK, hr); | |
| 152 std::vector<base::win::ScopedVariant> div_children = | |
| 153 GetAllAccessibleChildren(div); | |
| 154 ASSERT_EQ(1, div_children.size()); | |
| 155 | |
| 156 // Find the two edit fields (simple and text area). | |
| 157 base::win::ScopedComPtr<IAccessible2> input; | |
| 158 hr = QueryIAccessible2(GetAccessibleFromVariant( | |
| 159 form, form_children[1].AsInput()), input.Receive()); | |
| 160 ASSERT_EQ(S_OK, hr); | |
| 161 LONG input_role = 0; | |
| 162 hr = input->role(&input_role); | |
| 163 ASSERT_EQ(S_OK, hr); | |
| 164 ASSERT_EQ(ROLE_SYSTEM_TEXT, input_role); | |
| 165 | |
| 166 base::win::ScopedComPtr<IAccessible2> textarea; | |
| 167 hr = QueryIAccessible2(GetAccessibleFromVariant( | |
| 168 div, div_children[0].AsInput()), textarea.Receive()); | |
| 169 ASSERT_EQ(S_OK, hr); | |
| 170 LONG textarea_role = 0; | |
| 171 hr = textarea->role(&textarea_role); | |
| 172 ASSERT_EQ(S_OK, hr); | |
| 173 ASSERT_EQ(ROLE_SYSTEM_TEXT, input_role); | |
| 174 | |
| 175 // Retrieve the IAccessibleText interface for both of the fields. | |
| 176 hr = input_text->QueryFrom(input); | |
| 177 ASSERT_EQ(S_OK, hr); | |
| 178 hr = textarea_text->QueryFrom(textarea); | |
| 179 ASSERT_EQ(S_OK, hr); | |
| 180 // Set the caret on the last character. | |
| 181 LONG caret_offset = CONTENTS_LENGTH - 1; | |
| 182 hr = (*input_text)->setCaretOffset(caret_offset); | |
| 183 ASSERT_EQ(S_OK, hr); | |
| 184 hr = (*textarea_text)->setCaretOffset(caret_offset); | |
| 185 ASSERT_EQ(S_OK, hr); | |
| 186 } | |
| 187 | |
| 188 // Static helpers ------------------------------------------------ | |
| 189 | |
| 190 base::win::ScopedComPtr<IAccessible> | |
| 191 AccessibilityWinBrowserTest::GetAccessibleFromVariant( | |
| 37 IAccessible* parent, | 192 IAccessible* parent, |
| 38 VARIANT* var) { | 193 VARIANT* var) { |
| 39 base::win::ScopedComPtr<IAccessible> ptr; | 194 base::win::ScopedComPtr<IAccessible> ptr; |
| 40 switch (V_VT(var)) { | 195 switch (V_VT(var)) { |
| 41 case VT_DISPATCH: { | 196 case VT_DISPATCH: { |
| 42 IDispatch* dispatch = V_DISPATCH(var); | 197 IDispatch* dispatch = V_DISPATCH(var); |
| 43 if (dispatch) | 198 if (dispatch) |
| 44 ptr.QueryFrom(dispatch); | 199 ptr.QueryFrom(dispatch); |
| 45 break; | 200 break; |
| 46 } | 201 } |
| 47 | 202 |
| 48 case VT_I4: { | 203 case VT_I4: { |
| 49 base::win::ScopedComPtr<IDispatch> dispatch; | 204 base::win::ScopedComPtr<IDispatch> dispatch; |
| 50 HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); | 205 HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); |
| 51 EXPECT_TRUE(SUCCEEDED(hr)); | 206 EXPECT_TRUE(SUCCEEDED(hr)); |
| 52 if (dispatch) | 207 if (dispatch) |
| 53 dispatch.QueryInterface(ptr.Receive()); | 208 dispatch.QueryInterface(ptr.Receive()); |
| 54 break; | 209 break; |
| 55 } | 210 } |
| 56 } | 211 } |
| 57 return ptr; | 212 return ptr; |
| 58 } | 213 } |
| 59 | 214 |
| 60 HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) { | 215 HRESULT AccessibilityWinBrowserTest::QueryIAccessible2( |
| 61 // TODO(ctguil): For some reason querying the IAccessible2 interface from | 216 IAccessible* accessible, |
| 62 // IAccessible fails. | 217 IAccessible2** accessible2) { |
| 218 // IA2 Spec dictates that IServiceProvider should be used instead of | |
| 219 // QueryInterface when retrieving IAccessible2. | |
| 63 base::win::ScopedComPtr<IServiceProvider> service_provider; | 220 base::win::ScopedComPtr<IServiceProvider> service_provider; |
| 64 HRESULT hr = accessible->QueryInterface(service_provider.Receive()); | 221 HRESULT hr = accessible->QueryInterface(service_provider.Receive()); |
| 65 return SUCCEEDED(hr) ? | 222 return SUCCEEDED(hr) ? |
| 66 service_provider->QueryService(IID_IAccessible2, accessible2) : hr; | 223 service_provider->QueryService(IID_IAccessible2, accessible2) : hr; |
| 67 } | 224 } |
| 68 | 225 |
| 69 // Recursively search through all of the descendants reachable from an | 226 // Recursively search through all of the descendants reachable from an |
| 70 // IAccessible node and return true if we find one with the given role | 227 // IAccessible node and return true if we find one with the given role |
| 71 // and name. | 228 // and name. |
| 72 void RecursiveFindNodeInAccessibilityTree(IAccessible* node, | 229 void AccessibilityWinBrowserTest::FindNodeInAccessibilityTree( |
| 73 int32 expected_role, | 230 IAccessible* node, |
| 74 const std::wstring& expected_name, | 231 int32 expected_role, |
| 75 int32 depth, | 232 const std::wstring& expected_name, |
| 76 bool* found) { | 233 int32 depth, |
| 234 bool* found) { | |
| 77 base::win::ScopedBstr name_bstr; | 235 base::win::ScopedBstr name_bstr; |
| 78 base::win::ScopedVariant childid_self(CHILDID_SELF); | 236 base::win::ScopedVariant childid_self(CHILDID_SELF); |
| 79 node->get_accName(childid_self, name_bstr.Receive()); | 237 node->get_accName(childid_self, name_bstr.Receive()); |
| 80 std::wstring name(name_bstr, name_bstr.Length()); | 238 std::wstring name(name_bstr, name_bstr.Length()); |
| 81 base::win::ScopedVariant role; | 239 base::win::ScopedVariant role; |
| 82 node->get_accRole(childid_self, role.Receive()); | 240 node->get_accRole(childid_self, role.Receive()); |
| 83 ASSERT_EQ(VT_I4, role.type()); | 241 ASSERT_EQ(VT_I4, role.type()); |
| 84 | 242 |
| 85 // Print the accessibility tree as we go, because if this test fails | 243 // Print the accessibility tree as we go, because if this test fails |
| 86 // on the bots, this is really helpful in figuring out why. | 244 // on the bots, this is really helpful in figuring out why. |
| 87 for (int i = 0; i < depth; i++) | 245 for (int i = 0; i < depth; i++) |
| 88 printf(" "); | 246 printf(" "); |
| 89 printf("role=%s name=%s\n", | 247 printf("role=%s name=%s\n", |
| 90 base::WideToUTF8(IAccessibleRoleToString(V_I4(&role))).c_str(), | 248 base::WideToUTF8(IAccessibleRoleToString(V_I4(&role))).c_str(), |
| 91 base::WideToUTF8(name).c_str()); | 249 base::WideToUTF8(name).c_str()); |
| 92 | 250 |
| 93 if (expected_role == V_I4(&role) && expected_name == name) { | 251 if (expected_role == V_I4(&role) && expected_name == name) { |
| 94 *found = true; | 252 *found = true; |
| 95 return; | 253 return; |
| 96 } | 254 } |
| 97 | 255 |
| 98 LONG child_count = 0; | 256 std::vector<base::win::ScopedVariant> children = GetAllAccessibleChildren( |
| 99 HRESULT hr = node->get_accChildCount(&child_count); | 257 node); |
| 100 ASSERT_EQ(S_OK, hr); | 258 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( | 259 base::win::ScopedComPtr<IAccessible> child_accessible( |
| 111 GetAccessibleFromResultVariant(node, &child_array.get()[index])); | 260 GetAccessibleFromVariant(node, children[i].AsInput())); |
| 112 if (child_accessible) { | 261 if (child_accessible) { |
| 113 RecursiveFindNodeInAccessibilityTree( | 262 FindNodeInAccessibilityTree( |
| 114 child_accessible.get(), expected_role, expected_name, depth + 1, | 263 child_accessible.get(), expected_role, expected_name, depth + 1, |
| 115 found); | 264 found); |
| 116 if (*found) | 265 if (*found) |
| 117 return; | 266 return; |
| 118 } | 267 } |
| 119 } | 268 } |
| 120 } | 269 } |
| 121 | 270 |
| 271 // Ensures that the text and the start and end offsets retrieved using | |
| 272 // get_textAtOffset match the expected values. | |
| 273 void AccessibilityWinBrowserTest::CheckTextAtOffset(IAccessibleText* element, | |
| 274 LONG offset, | |
| 275 IA2TextBoundaryType boundar y_type, | |
| 276 LONG expected_start_offset, | |
| 277 LONG expected_end_offset, | |
| 278 const std::wstring& expecte d_text) { | |
| 279 testing::Message message; | |
| 280 message << "While checking for \'" << expected_text << "\' at " << | |
| 281 expected_start_offset << '-' << expected_end_offset << '.'; | |
| 282 SCOPED_TRACE(message); | |
| 122 | 283 |
| 123 // AccessibilityWinBrowserTest ------------------------------------------------ | 284 LONG start_offset = 0; |
| 124 | 285 LONG end_offset = 0; |
| 125 class AccessibilityWinBrowserTest : public ContentBrowserTest { | 286 base::win::ScopedBstr text; |
| 126 public: | 287 HRESULT hr = element->get_textAtOffset( |
| 127 AccessibilityWinBrowserTest(); | 288 offset, boundary_type, |
| 128 virtual ~AccessibilityWinBrowserTest(); | 289 &start_offset, &end_offset, text.Receive()); |
| 129 | 290 EXPECT_EQ(S_OK, hr); |
| 130 protected: | 291 EXPECT_EQ(expected_start_offset, start_offset); |
| 131 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); | 292 EXPECT_EQ(expected_end_offset, end_offset); |
| 132 IAccessible* GetRendererAccessible(); | 293 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 } | 294 } |
| 141 | 295 |
| 142 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() { | 296 std::vector<base::win::ScopedVariant> |
| 143 } | 297 AccessibilityWinBrowserTest::GetAllAccessibleChildren( |
| 298 IAccessible* element) { | |
| 299 LONG child_count = 0; | |
| 300 HRESULT hr = element->get_accChildCount(&child_count); | |
| 301 EXPECT_EQ(S_OK, hr); | |
| 302 if (child_count <= 0) | |
| 303 return std::vector<base::win::ScopedVariant>(); | |
| 144 | 304 |
| 145 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml( | 305 scoped_ptr<VARIANT[]> children_array(new VARIANT[child_count]); |
| 146 const std::string& html) { | 306 LONG obtained_count = 0; |
| 147 AccessibilityNotificationWaiter waiter( | 307 hr = AccessibleChildren( |
| 148 shell(), AccessibilityModeComplete, | 308 element, 0, child_count, children_array.get(), &obtained_count); |
| 149 ui::AX_EVENT_LOAD_COMPLETE); | 309 EXPECT_EQ(S_OK, hr); |
| 150 GURL html_data_url("data:text/html," + html); | 310 EXPECT_EQ(child_count, obtained_count); |
| 151 NavigateToURL(shell(), html_data_url); | |
| 152 waiter.WaitForNotification(); | |
| 153 } | |
| 154 | 311 |
| 155 // Retrieve the MSAA client accessibility object for the Render Widget Host View | 312 std::vector<base::win::ScopedVariant> children( |
| 156 // of the selected tab. | 313 static_cast<size_t>(child_count)); |
| 157 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() { | 314 for (size_t i = 0; i < children.size(); i++) { |
| 158 content::WebContents* web_contents = shell()->web_contents(); | 315 children[i].Reset(children_array[i]); |
| 159 return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible(); | 316 } |
| 160 } | 317 return children; |
| 161 | |
| 162 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) { | |
| 163 shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script); | |
| 164 } | 318 } |
| 165 | 319 |
| 166 | 320 |
| 167 // AccessibleChecker ---------------------------------------------------------- | 321 // AccessibleChecker ---------------------------------------------------------- |
| 168 | 322 |
| 169 class AccessibleChecker { | 323 class AccessibilityWinBrowserTest::AccessibleChecker { |
| 170 public: | 324 public: |
| 171 // This constructor can be used if the IA2 role will be the same as the MSAA | 325 // This constructor can be used if the IA2 role will be the same as the MSAA |
| 172 // role. | 326 // role. |
| 173 AccessibleChecker(const std::wstring& expected_name, | 327 AccessibleChecker(const std::wstring& expected_name, |
| 174 int32 expected_role, | 328 int32 expected_role, |
| 175 const std::wstring& expected_value); | 329 const std::wstring& expected_value); |
| 176 AccessibleChecker(const std::wstring& expected_name, | 330 AccessibleChecker(const std::wstring& expected_name, |
| 177 int32 expected_role, | 331 int32 expected_role, |
| 178 int32 expected_ia2_role, | 332 int32 expected_ia2_role, |
| 179 const std::wstring& expected_value); | 333 const std::wstring& expected_value); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 std::wstring value_; | 375 std::wstring value_; |
| 222 | 376 |
| 223 // Expected accessible state. Checked against IAccessible::get_accState. | 377 // Expected accessible state. Checked against IAccessible::get_accState. |
| 224 LONG state_; | 378 LONG state_; |
| 225 | 379 |
| 226 // Expected accessible children. Checked using IAccessible::get_accChildCount | 380 // Expected accessible children. Checked using IAccessible::get_accChildCount |
| 227 // and ::AccessibleChildren. | 381 // and ::AccessibleChildren. |
| 228 AccessibleCheckerVector children_; | 382 AccessibleCheckerVector children_; |
| 229 }; | 383 }; |
| 230 | 384 |
| 231 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 385 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
| 232 int32 expected_role, | 386 const std::wstring& expected_name, |
| 233 const std::wstring& expected_value) | 387 int32 expected_role, |
| 388 const std::wstring& expected_value) | |
| 234 : name_(expected_name), | 389 : name_(expected_name), |
| 235 role_(expected_role), | 390 role_(expected_role), |
| 236 ia2_role_(expected_role), | 391 ia2_role_(expected_role), |
| 237 value_(expected_value), | 392 value_(expected_value), |
| 238 state_(-1) { | 393 state_(-1) { |
| 239 } | 394 } |
| 240 | 395 |
| 241 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 396 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
| 242 int32 expected_role, | 397 const std::wstring& expected_name, |
| 243 int32 expected_ia2_role, | 398 int32 expected_role, |
| 244 const std::wstring& expected_value) | 399 int32 expected_ia2_role, |
| 400 const std::wstring& expected_value) | |
| 245 : name_(expected_name), | 401 : name_(expected_name), |
| 246 role_(expected_role), | 402 role_(expected_role), |
| 247 ia2_role_(expected_ia2_role), | 403 ia2_role_(expected_ia2_role), |
| 248 value_(expected_value), | 404 value_(expected_value), |
| 249 state_(-1) { | 405 state_(-1) { |
| 250 } | 406 } |
| 251 | 407 |
| 252 AccessibleChecker::AccessibleChecker(const std::wstring& expected_name, | 408 AccessibilityWinBrowserTest::AccessibleChecker::AccessibleChecker( |
| 253 const std::wstring& expected_role, | 409 const std::wstring& expected_name, |
| 254 int32 expected_ia2_role, | 410 const std::wstring& expected_role, |
| 255 const std::wstring& expected_value) | 411 int32 expected_ia2_role, |
| 412 const std::wstring& expected_value) | |
| 256 : name_(expected_name), | 413 : name_(expected_name), |
| 257 role_(expected_role.c_str()), | 414 role_(expected_role.c_str()), |
| 258 ia2_role_(expected_ia2_role), | 415 ia2_role_(expected_ia2_role), |
| 259 value_(expected_value), | 416 value_(expected_value), |
| 260 state_(-1) { | 417 state_(-1) { |
| 261 } | 418 } |
| 262 | 419 |
| 263 void AccessibleChecker::AppendExpectedChild( | 420 void AccessibilityWinBrowserTest::AccessibleChecker::AppendExpectedChild( |
| 264 AccessibleChecker* expected_child) { | 421 AccessibleChecker* expected_child) { |
| 265 children_.push_back(expected_child); | 422 children_.push_back(expected_child); |
| 266 } | 423 } |
| 267 | 424 |
| 268 void AccessibleChecker::CheckAccessible(IAccessible* accessible) { | 425 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessible( |
| 269 SCOPED_TRACE("while checking " + | 426 IAccessible* accessible) { |
| 270 base::UTF16ToUTF8(RoleVariantToString(role_))); | 427 SCOPED_TRACE("While checking " |
| 428 + base::UTF16ToUTF8(RoleVariantToString(role_))); | |
| 271 CheckAccessibleName(accessible); | 429 CheckAccessibleName(accessible); |
| 272 CheckAccessibleRole(accessible); | 430 CheckAccessibleRole(accessible); |
| 273 CheckIA2Role(accessible); | 431 CheckIA2Role(accessible); |
| 274 CheckAccessibleValue(accessible); | 432 CheckAccessibleValue(accessible); |
| 275 CheckAccessibleState(accessible); | 433 CheckAccessibleState(accessible); |
| 276 CheckAccessibleChildren(accessible); | 434 CheckAccessibleChildren(accessible); |
| 277 } | 435 } |
| 278 | 436 |
| 279 void AccessibleChecker::SetExpectedValue(const std::wstring& expected_value) { | 437 void AccessibilityWinBrowserTest::AccessibleChecker::SetExpectedValue( |
| 438 const std::wstring& expected_value) { | |
| 280 value_ = expected_value; | 439 value_ = expected_value; |
| 281 } | 440 } |
| 282 | 441 |
| 283 void AccessibleChecker::SetExpectedState(LONG expected_state) { | 442 void AccessibilityWinBrowserTest::AccessibleChecker::SetExpectedState( |
| 443 LONG expected_state) { | |
| 284 state_ = expected_state; | 444 state_ = expected_state; |
| 285 } | 445 } |
| 286 | 446 |
| 287 void AccessibleChecker::CheckAccessibleName(IAccessible* accessible) { | 447 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleName( |
| 448 IAccessible* accessible) { | |
| 288 base::win::ScopedBstr name; | 449 base::win::ScopedBstr name; |
| 289 base::win::ScopedVariant childid_self(CHILDID_SELF); | 450 base::win::ScopedVariant childid_self(CHILDID_SELF); |
| 290 HRESULT hr = accessible->get_accName(childid_self, name.Receive()); | 451 HRESULT hr = accessible->get_accName(childid_self, name.Receive()); |
| 291 | 452 |
| 292 if (name_.empty()) { | 453 if (name_.empty()) { |
| 293 // If the object doesn't have name S_FALSE should be returned. | 454 // If the object doesn't have name S_FALSE should be returned. |
| 294 EXPECT_EQ(S_FALSE, hr); | 455 EXPECT_EQ(S_FALSE, hr); |
| 295 } else { | 456 } else { |
| 296 // Test that the correct string was returned. | 457 // Test that the correct string was returned. |
| 297 EXPECT_EQ(S_OK, hr); | 458 EXPECT_EQ(S_OK, hr); |
| 298 EXPECT_EQ(name_, std::wstring(name, name.Length())); | 459 EXPECT_EQ(name_, std::wstring(name, name.Length())); |
| 299 } | 460 } |
| 300 } | 461 } |
| 301 | 462 |
| 302 void AccessibleChecker::CheckAccessibleRole(IAccessible* accessible) { | 463 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleRole( |
| 464 IAccessible* accessible) { | |
| 303 base::win::ScopedVariant role; | 465 base::win::ScopedVariant role; |
| 304 base::win::ScopedVariant childid_self(CHILDID_SELF); | 466 base::win::ScopedVariant childid_self(CHILDID_SELF); |
| 305 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); | 467 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); |
| 306 ASSERT_EQ(S_OK, hr); | 468 ASSERT_EQ(S_OK, hr); |
| 307 EXPECT_EQ(0, role_.Compare(role)) | 469 EXPECT_EQ(0, role_.Compare(role)) |
| 308 << "Expected role: " << RoleVariantToString(role_) | 470 << "Expected role: " << RoleVariantToString(role_) |
| 309 << "\nGot role: " << RoleVariantToString(role); | 471 << "\nGot role: " << RoleVariantToString(role); |
| 310 } | 472 } |
| 311 | 473 |
| 312 void AccessibleChecker::CheckIA2Role(IAccessible* accessible) { | 474 void AccessibilityWinBrowserTest::AccessibleChecker::CheckIA2Role( |
| 475 IAccessible* accessible) { | |
| 313 base::win::ScopedComPtr<IAccessible2> accessible2; | 476 base::win::ScopedComPtr<IAccessible2> accessible2; |
| 314 HRESULT hr = QueryIAccessible2(accessible, accessible2.Receive()); | 477 HRESULT hr = QueryIAccessible2(accessible, accessible2.Receive()); |
| 315 ASSERT_EQ(S_OK, hr); | 478 ASSERT_EQ(S_OK, hr); |
| 316 long ia2_role = 0; | 479 long ia2_role = 0; |
| 317 hr = accessible2->role(&ia2_role); | 480 hr = accessible2->role(&ia2_role); |
| 318 ASSERT_EQ(S_OK, hr); | 481 ASSERT_EQ(S_OK, hr); |
| 319 EXPECT_EQ(ia2_role_, ia2_role) | 482 EXPECT_EQ(ia2_role_, ia2_role) |
| 320 << "Expected ia2 role: " << IAccessible2RoleToString(ia2_role_) | 483 << "Expected ia2 role: " << IAccessible2RoleToString(ia2_role_) |
| 321 << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role); | 484 << "\nGot ia2 role: " << IAccessible2RoleToString(ia2_role); |
| 322 } | 485 } |
| 323 | 486 |
| 324 void AccessibleChecker::CheckAccessibleValue(IAccessible* accessible) { | 487 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleValue( |
| 488 IAccessible* accessible) { | |
| 325 // Don't check the value if if's a DOCUMENT role, because the value | 489 // 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 | 490 // is supposed to be the url (and we don't keep track of that in the |
| 327 // test expectations). | 491 // test expectations). |
| 328 base::win::ScopedVariant role; | 492 base::win::ScopedVariant role; |
| 329 base::win::ScopedVariant childid_self(CHILDID_SELF); | 493 base::win::ScopedVariant childid_self(CHILDID_SELF); |
| 330 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); | 494 HRESULT hr = accessible->get_accRole(childid_self, role.Receive()); |
| 331 ASSERT_EQ(S_OK, hr); | 495 ASSERT_EQ(S_OK, hr); |
| 332 if (role.type() == VT_I4 && V_I4(&role) == ROLE_SYSTEM_DOCUMENT) | 496 if (role.type() == VT_I4 && V_I4(&role) == ROLE_SYSTEM_DOCUMENT) |
| 333 return; | 497 return; |
| 334 | 498 |
| 335 // Get the value. | 499 // Get the value. |
| 336 base::win::ScopedBstr value; | 500 base::win::ScopedBstr value; |
| 337 hr = accessible->get_accValue(childid_self, value.Receive()); | 501 hr = accessible->get_accValue(childid_self, value.Receive()); |
| 338 EXPECT_EQ(S_OK, hr); | 502 EXPECT_EQ(S_OK, hr); |
| 339 | 503 |
| 340 // Test that the correct string was returned. | 504 // Test that the correct string was returned. |
| 341 EXPECT_EQ(value_, std::wstring(value, value.Length())); | 505 EXPECT_EQ(value_, std::wstring(value, value.Length())); |
| 342 } | 506 } |
| 343 | 507 |
| 344 void AccessibleChecker::CheckAccessibleState(IAccessible* accessible) { | 508 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleState( |
| 509 IAccessible* accessible) { | |
| 345 if (state_ < 0) | 510 if (state_ < 0) |
| 346 return; | 511 return; |
| 347 | 512 |
| 348 base::win::ScopedVariant state; | 513 base::win::ScopedVariant state; |
| 349 base::win::ScopedVariant childid_self(CHILDID_SELF); | 514 base::win::ScopedVariant childid_self(CHILDID_SELF); |
| 350 HRESULT hr = accessible->get_accState(childid_self, state.Receive()); | 515 HRESULT hr = accessible->get_accState(childid_self, state.Receive()); |
| 351 EXPECT_EQ(S_OK, hr); | 516 EXPECT_EQ(S_OK, hr); |
| 352 ASSERT_EQ(VT_I4, state.type()); | 517 ASSERT_EQ(VT_I4, state.type()); |
| 353 LONG obj_state = V_I4(&state); | 518 LONG obj_state = V_I4(&state); |
| 354 // Avoid flakiness. The "offscreen" state depends on whether the browser | 519 // Avoid flakiness. The "offscreen" state depends on whether the browser |
| 355 // window is frontmost or not, and "hottracked" depends on whether the | 520 // window is frontmost or not, and "hottracked" depends on whether the |
| 356 // mouse cursor happens to be over the element. | 521 // mouse cursor happens to be over the element. |
| 357 obj_state &= ~(STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_HOTTRACKED); | 522 obj_state &= ~(STATE_SYSTEM_OFFSCREEN | STATE_SYSTEM_HOTTRACKED); |
| 358 EXPECT_EQ(state_, obj_state) | 523 EXPECT_EQ(state_, obj_state) |
| 359 << "Expected state: " << IAccessibleStateToString(state_) | 524 << "Expected state: " << IAccessibleStateToString(state_) |
| 360 << "\nGot state: " << IAccessibleStateToString(obj_state); | 525 << "\nGot state: " << IAccessibleStateToString(obj_state); |
| 361 } | 526 } |
| 362 | 527 |
| 363 void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) { | 528 void AccessibilityWinBrowserTest::AccessibleChecker::CheckAccessibleChildren( |
| 364 LONG child_count = 0; | 529 IAccessible* parent) { |
| 365 HRESULT hr = parent->get_accChildCount(&child_count); | 530 std::vector<base::win::ScopedVariant> obtained_children = |
| 366 EXPECT_EQ(S_OK, hr); | 531 GetAllAccessibleChildren(parent); |
| 532 size_t child_count = obtained_children.size(); | |
| 367 ASSERT_EQ(child_count, children_.size()); | 533 ASSERT_EQ(child_count, children_.size()); |
| 368 | 534 |
| 369 scoped_ptr<VARIANT[]> child_array(new VARIANT[child_count]); | 535 AccessibleCheckerVector::iterator child_checker; |
| 370 LONG obtained_count = 0; | 536 std::vector<base::win::ScopedVariant>::iterator child; |
| 371 hr = AccessibleChildren(parent, 0, child_count, | 537 for (child_checker = children_.begin(), |
| 372 child_array.get(), &obtained_count); | 538 child = obtained_children.begin(); |
| 373 ASSERT_EQ(S_OK, hr); | 539 child_checker != children_.end() |
| 374 ASSERT_EQ(child_count, obtained_count); | 540 && 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) { | 541 ++child_checker, ++child) { |
| 380 base::win::ScopedComPtr<IAccessible> child_accessible( | 542 base::win::ScopedComPtr<IAccessible> child_accessible( |
| 381 GetAccessibleFromResultVariant(parent, child)); | 543 GetAccessibleFromVariant(parent, child->AsInput())); |
| 382 ASSERT_TRUE(child_accessible.get()); | 544 ASSERT_TRUE(child_accessible.get()); |
| 383 (*child_checker)->CheckAccessible(child_accessible); | 545 (*child_checker)->CheckAccessible(child_accessible); |
| 384 } | 546 } |
| 385 } | 547 } |
| 386 | 548 |
| 387 base::string16 AccessibleChecker::RoleVariantToString( | 549 base::string16 |
| 550 AccessibilityWinBrowserTest::AccessibleChecker::RoleVariantToString( | |
| 388 const base::win::ScopedVariant& role) { | 551 const base::win::ScopedVariant& role) { |
| 389 if (role.type() == VT_I4) | 552 if (role.type() == VT_I4) |
| 390 return IAccessibleRoleToString(V_I4(&role)); | 553 return IAccessibleRoleToString(V_I4(&role)); |
| 391 if (role.type() == VT_BSTR) | 554 if (role.type() == VT_BSTR) |
| 392 return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role))); | 555 return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role))); |
| 393 return base::string16(); | 556 return base::string16(); |
| 394 } | 557 } |
| 395 | 558 |
| 396 } // namespace | 559 } // namespace |
| 397 | 560 |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 660 CHECK(hwnd); | 823 CHECK(hwnd); |
| 661 base::win::ScopedComPtr<IAccessible> browser_accessible; | 824 base::win::ScopedComPtr<IAccessible> browser_accessible; |
| 662 HRESULT hr = AccessibleObjectFromWindow( | 825 HRESULT hr = AccessibleObjectFromWindow( |
| 663 hwnd, | 826 hwnd, |
| 664 OBJID_WINDOW, | 827 OBJID_WINDOW, |
| 665 IID_IAccessible, | 828 IID_IAccessible, |
| 666 reinterpret_cast<void**>(browser_accessible.Receive())); | 829 reinterpret_cast<void**>(browser_accessible.Receive())); |
| 667 ASSERT_EQ(S_OK, hr); | 830 ASSERT_EQ(S_OK, hr); |
| 668 | 831 |
| 669 bool found = false; | 832 bool found = false; |
| 670 RecursiveFindNodeInAccessibilityTree( | 833 FindNodeInAccessibilityTree( |
| 671 browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found); | 834 browser_accessible.get(), ROLE_SYSTEM_DOCUMENT, L"MyDocument", 0, &found); |
| 672 ASSERT_EQ(found, true); | 835 ASSERT_EQ(found, true); |
| 673 } | 836 } |
| 674 | 837 |
| 675 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | 838 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, |
| 676 SupportsISimpleDOM) { | 839 SupportsISimpleDOM) { |
| 677 LoadInitialAccessibilityTreeFromHtml( | 840 LoadInitialAccessibilityTreeFromHtml( |
| 678 "<body><input type='checkbox' /></body>"); | 841 "<body><input type='checkbox' /></body>"); |
| 679 | 842 |
| 680 // Get the IAccessible object for the document. | 843 // Get the IAccessible object for the document. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 746 std::wstring()); | 909 std::wstring()); |
| 747 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, | 910 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, |
| 748 std::wstring()); | 911 std::wstring()); |
| 749 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, | 912 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, |
| 750 std::wstring()); | 913 std::wstring()); |
| 751 document_checker.AppendExpectedChild(&grouping1_checker); | 914 document_checker.AppendExpectedChild(&grouping1_checker); |
| 752 document_checker.AppendExpectedChild(&grouping2_checker); | 915 document_checker.AppendExpectedChild(&grouping2_checker); |
| 753 document_checker.CheckAccessible(GetRendererAccessible()); | 916 document_checker.CheckAccessible(GetRendererAccessible()); |
| 754 } | 917 } |
| 755 | 918 |
| 919 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
| 920 TestTextAtOffsetWithInvalidArgs) { | |
| 921 base::win::ScopedComPtr<IAccessibleText> input_text; | |
| 922 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
| 923 SetUpTextFields(&input_text, &textarea_text); | |
| 924 HRESULT hr = input_text->get_textAtOffset( | |
| 925 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); | |
| 926 EXPECT_EQ(E_INVALIDARG, hr); | |
| 927 hr = textarea_text->get_textAtOffset( | |
| 928 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); | |
| 929 EXPECT_EQ(E_INVALIDARG, hr); | |
| 930 | |
| 931 // Test invalid offset. | |
| 932 LONG start_offset = 0; | |
| 933 LONG end_offset = 0; | |
| 934 base::win::ScopedBstr text; | |
| 935 LONG invalid_offset = -5; | |
| 936 hr = input_text->get_textAtOffset( | |
| 937 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
| 938 &start_offset, &end_offset, text.Receive()); | |
| 939 EXPECT_EQ(E_INVALIDARG, hr); | |
| 940 hr = textarea_text->get_textAtOffset( | |
| 941 invalid_offset, IA2_TEXT_BOUNDARY_WORD, | |
| 942 &start_offset, &end_offset, text.Receive()); | |
| 943 EXPECT_EQ(E_INVALIDARG, hr); | |
| 944 | |
| 945 // According to the IA2 Spec, only line boundaries should succeed when | |
| 946 // the offset is one past the end of the text. | |
| 947 invalid_offset = CONTENTS_LENGTH; | |
| 948 hr = input_text->get_textAtOffset( | |
| 949 invalid_offset, IA2_TEXT_BOUNDARY_LINE, | |
| 950 &start_offset, &end_offset, text.Receive()); | |
| 951 EXPECT_EQ(S_OK, hr); | |
| 952 hr = textarea_text->get_textAtOffset( | |
| 953 invalid_offset, IA2_TEXT_BOUNDARY_LINE, | |
| 954 &start_offset, &end_offset, text.Receive()); | |
| 955 EXPECT_EQ(S_OK, hr); | |
| 956 | |
| 957 hr = input_text->get_textAtOffset( | |
| 958 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
| 959 &start_offset, &end_offset, text.Receive()); | |
| 960 EXPECT_EQ(S_FALSE, hr); | |
| 961 hr = input_text->get_textAtOffset( | |
| 962 invalid_offset, IA2_TEXT_BOUNDARY_WORD, | |
| 963 &start_offset, &end_offset, text.Receive()); | |
| 964 EXPECT_EQ(S_FALSE, hr); | |
| 965 hr = textarea_text->get_textAtOffset( | |
| 966 invalid_offset, IA2_TEXT_BOUNDARY_SENTENCE, | |
| 967 &start_offset, &end_offset, text.Receive()); | |
| 968 EXPECT_EQ(S_FALSE, hr); | |
| 969 hr = textarea_text->get_textAtOffset( | |
| 970 invalid_offset, IA2_TEXT_BOUNDARY_ALL, | |
| 971 &start_offset, &end_offset, text.Receive()); | |
| 972 EXPECT_EQ(S_FALSE, hr); | |
| 973 } | |
| 974 | |
| 975 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
| 976 TestTextAtOffsetWithBoundaryCharacter) { | |
| 977 base::win::ScopedComPtr<IAccessibleText> input_text; | |
| 978 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
| 979 SetUpTextFields(&input_text, &textarea_text); | |
| 980 for (LONG offset = 0; offset < CONTENTS_LENGTH; ++offset) { | |
| 981 std::wstring expected_text(1, INPUT_CONTENTS[offset]); | |
| 982 LONG expected_start_offset = offset; | |
| 983 LONG expected_end_offset = offset + 1; | |
| 984 CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR, | |
| 985 expected_start_offset, expected_end_offset, expected_text); | |
| 986 } | |
| 987 for (LONG offset = CONTENTS_LENGTH - 1; offset >= 0; --offset) { | |
| 988 std::wstring expected_text(1, TEXTAREA_CONTENTS[offset]); | |
| 989 LONG expected_start_offset = offset; | |
| 990 LONG expected_end_offset = offset + 1; | |
| 991 CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR, | |
| 992 expected_start_offset, expected_end_offset, expected_text); | |
| 993 } | |
| 994 // Test special offsets. | |
| 995 CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_LENGTH, | |
| 996 IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L"."); | |
| 997 CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, | |
| 998 IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L"."); | |
| 999 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_LENGTH, | |
| 1000 IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L"."); | |
| 1001 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET, | |
| 1002 IA2_TEXT_BOUNDARY_CHAR, CONTENTS_LENGTH - 1, CONTENTS_LENGTH, L"."); | |
| 1003 } | |
| 1004 | |
| 1005 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
| 1006 TestTextAtOffsetWithBoundaryWord) { | |
| 1007 base::win::ScopedComPtr<IAccessibleText> input_text; | |
| 1008 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
| 1009 SetUpTextFields(&input_text, &textarea_text); | |
| 1010 | |
| 1011 // Trailing punctuation should be included as part of the previous word. | |
| 1012 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, | |
| 1013 0, 4, L"Moz/"); | |
| 1014 CheckTextAtOffset(textarea_text, 2, IA2_TEXT_BOUNDARY_WORD, | |
| 1015 0, 4, L"Moz/"); | |
| 1016 | |
| 1017 // If the offset is at the punctuation, it should return | |
| 1018 // the previous word. | |
| 1019 CheckTextAtOffset(textarea_text, 3, IA2_TEXT_BOUNDARY_WORD, | |
| 1020 0, 4, L"Moz/"); | |
| 1021 | |
| 1022 // Numbers with a decimal point ("." for U.S), should be treated as one word. | |
| 1023 // Also, trailing punctuation that occurs after empty space should be part of | |
| 1024 // the word. ("5.0 (" and not "5.0 ".) | |
| 1025 CheckTextAtOffset(input_text, 4, IA2_TEXT_BOUNDARY_WORD, | |
| 1026 4, 9, L"5.0 ("); | |
| 1027 CheckTextAtOffset(textarea_text, 5, IA2_TEXT_BOUNDARY_WORD, | |
| 1028 4, 9, L"5.0 ("); | |
| 1029 CheckTextAtOffset(input_text, 6, IA2_TEXT_BOUNDARY_WORD, | |
| 1030 4, 9, L"5.0 ("); | |
| 1031 CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, | |
| 1032 4, 9, L"5.0 ("); | |
| 1033 | |
| 1034 // Leading punctuation should not be included with the word after it. | |
| 1035 CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, | |
| 1036 4, 9, L"5.0 ("); | |
| 1037 CheckTextAtOffset(textarea_text, 11, IA2_TEXT_BOUNDARY_WORD, | |
| 1038 9, 12, L"ST "); | |
| 1039 | |
| 1040 // Numbers separated from letters with trailing punctuation should | |
| 1041 // be split into two words. Same for abreviations like "i.e.". | |
| 1042 CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, | |
| 1043 12, 14, L"6."); | |
| 1044 CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, | |
| 1045 14, 17, L"x; "); | |
| 1046 | |
| 1047 // Words with numbers should be treated like ordinary words. | |
| 1048 CheckTextAtOffset(input_text, 17, IA2_TEXT_BOUNDARY_WORD, | |
| 1049 17, 24, L"WWW33) "); | |
| 1050 CheckTextAtOffset(textarea_text, 23, IA2_TEXT_BOUNDARY_WORD, | |
| 1051 17, 24, L"WWW33)\n"); | |
| 1052 // Multiple trailing empty spaces should be part of the word preceding it. | |
| 1053 CheckTextAtOffset(input_text, 28, IA2_TEXT_BOUNDARY_WORD, | |
| 1054 24, 33, L"WebKit \""); | |
| 1055 CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_WORD, | |
| 1056 24, 33, L"WebKit \n\""); | |
| 1057 // Leading punctuation such as quotation marks should not be part of the word. | |
| 1058 CheckTextAtOffset(input_text, 32, IA2_TEXT_BOUNDARY_WORD, | |
| 1059 24, 33, L"WebKit \""); | |
| 1060 CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_WORD, | |
| 1061 24, 33, L"WebKit \n\""); | |
| 1062 CheckTextAtOffset(input_text, 33, IA2_TEXT_BOUNDARY_WORD, | |
| 1063 33, 40, L"KHTML, "); | |
| 1064 CheckTextAtOffset(textarea_text, 38, IA2_TEXT_BOUNDARY_WORD, | |
| 1065 33, 40, L"KHTML, "); | |
| 1066 // Trailing final punctuation should be part of the last word. | |
| 1067 CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD, | |
| 1068 40, CONTENTS_LENGTH, L"like\"."); | |
| 1069 CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD, | |
| 1070 40, CONTENTS_LENGTH, L"like\"."); | |
| 1071 // Test special offsets. | |
| 1072 CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_LENGTH, | |
| 1073 IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\"."); | |
| 1074 CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, | |
| 1075 IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\"."); | |
| 1076 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_LENGTH, | |
| 1077 IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\"."); | |
| 1078 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET, | |
| 1079 IA2_TEXT_BOUNDARY_WORD, 40, CONTENTS_LENGTH, L"like\"."); | |
| 1080 } | |
| 1081 | |
| 1082 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
| 1083 TestTextAtOffsetWithBoundarySentence) { | |
| 1084 base::win::ScopedComPtr<IAccessibleText> input_text; | |
| 1085 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
| 1086 SetUpTextFields(&input_text, &textarea_text); | |
| 1087 | |
| 1088 // Sentence navigation is not currently implemented. | |
| 1089 LONG start_offset = 0; | |
| 1090 LONG end_offset = 0; | |
| 1091 base::win::ScopedBstr text; | |
| 1092 HRESULT hr = input_text->get_textAtOffset( | |
| 1093 5, IA2_TEXT_BOUNDARY_SENTENCE, | |
| 1094 &start_offset, &end_offset, text.Receive()); | |
| 1095 EXPECT_EQ(S_FALSE, hr); | |
| 1096 hr = textarea_text->get_textAtOffset( | |
| 1097 25, IA2_TEXT_BOUNDARY_SENTENCE, | |
| 1098 &start_offset, &end_offset, text.Receive()); | |
| 1099 EXPECT_EQ(S_FALSE, hr); | |
| 1100 } | |
| 1101 | |
| 1102 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
| 1103 TestTextAtOffsetWithBoundaryLine) { | |
| 1104 base::win::ScopedComPtr<IAccessibleText> input_text; | |
| 1105 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
| 1106 SetUpTextFields(&input_text, &textarea_text); | |
| 1107 | |
| 1108 // Single line text fields should return the whole text. | |
| 1109 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_LINE, | |
| 1110 0, CONTENTS_LENGTH, base::ASCIIToWide(INPUT_CONTENTS)); | |
| 1111 // Textarea is a multi-line text field. | |
| 1112 CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_LINE, | |
| 1113 0, 24, L"Moz/5.0 (ST 6.x; WWW33)\n"); | |
| 1114 // If the offset is at the newline, return the line preceding it. | |
| 1115 CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_LINE, | |
| 1116 24, 32, L"WebKit \n"); | |
| 1117 // Last line does not have a trailing newline. | |
| 1118 CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_LINE, | |
| 1119 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); | |
| 1120 // An offset one past the last character should return the last line. | |
| 1121 CheckTextAtOffset(textarea_text, CONTENTS_LENGTH, IA2_TEXT_BOUNDARY_LINE, | |
| 1122 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); | |
| 1123 // Test special offsets. | |
| 1124 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_LENGTH, | |
| 1125 IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); | |
| 1126 CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET, | |
| 1127 IA2_TEXT_BOUNDARY_LINE, 32, CONTENTS_LENGTH, L"\"KHTML, like\"."); | |
| 1128 } | |
| 1129 | |
| 1130 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, | |
| 1131 TestTextAtOffsetWithBoundaryAll) { | |
| 1132 base::win::ScopedComPtr<IAccessibleText> input_text; | |
| 1133 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
| 1134 SetUpTextFields(&input_text, &textarea_text); | |
| 1135 | |
| 1136 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL, | |
| 1137 0, CONTENTS_LENGTH, base::ASCIIToWide(INPUT_CONTENTS)); | |
| 1138 CheckTextAtOffset(textarea_text, CONTENTS_LENGTH - 1, IA2_TEXT_BOUNDARY_ALL, | |
| 1139 0, CONTENTS_LENGTH, base::ASCIIToWide(TEXTAREA_CONTENTS)); | |
| 1140 } | |
| 1141 | |
| 756 } // namespace content | 1142 } // namespace content |
| OLD | NEW |