| OLD | NEW |
| 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2017 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 "content/browser/accessibility/browser_accessibility_com_win.h" | 5 #include "content/browser/accessibility/browser_accessibility_com_win.h" |
| 6 | 6 |
| 7 #include <UIAutomationClient.h> | 7 #include <UIAutomationClient.h> |
| 8 #include <UIAutomationCoreApi.h> | 8 #include <UIAutomationCoreApi.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 2261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2272 BSTR* text) { | 2272 BSTR* text) { |
| 2273 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_AT_OFFSET); | 2273 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_AT_OFFSET); |
| 2274 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes | | 2274 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes | |
| 2275 AccessibilityMode::kInlineTextBoxes); | 2275 AccessibilityMode::kInlineTextBoxes); |
| 2276 if (!owner()) | 2276 if (!owner()) |
| 2277 return E_FAIL; | 2277 return E_FAIL; |
| 2278 | 2278 |
| 2279 if (!start_offset || !end_offset || !text) | 2279 if (!start_offset || !end_offset || !text) |
| 2280 return E_INVALIDARG; | 2280 return E_INVALIDARG; |
| 2281 | 2281 |
| 2282 *start_offset = 0; |
| 2283 *end_offset = 0; |
| 2284 *text = nullptr; |
| 2285 |
| 2282 HandleSpecialTextOffset(&offset); | 2286 HandleSpecialTextOffset(&offset); |
| 2283 if (offset < 0) | 2287 if (offset < 0) |
| 2284 return E_INVALIDARG; | 2288 return E_INVALIDARG; |
| 2285 | 2289 |
| 2286 const base::string16& text_str = owner()->GetText(); | 2290 const base::string16& text_str = owner()->GetText(); |
| 2287 LONG text_len = text_str.length(); | 2291 LONG text_len = text_str.length(); |
| 2288 if (offset > text_len) | 2292 if (offset > text_len) |
| 2289 return E_INVALIDARG; | 2293 return E_INVALIDARG; |
| 2290 | 2294 |
| 2291 // The IAccessible2 spec says we don't have to implement the "sentence" | 2295 // The IAccessible2 spec says we don't have to implement the "sentence" |
| 2292 // boundary type, we can just let the screenreader handle it. | 2296 // boundary type, we can just let the screenreader handle it. |
| 2293 if (boundary_type == IA2_TEXT_BOUNDARY_SENTENCE) { | 2297 if (boundary_type == IA2_TEXT_BOUNDARY_SENTENCE) |
| 2294 *start_offset = 0; | |
| 2295 *end_offset = 0; | |
| 2296 *text = NULL; | |
| 2297 return S_FALSE; | 2298 return S_FALSE; |
| 2298 } | |
| 2299 | 2299 |
| 2300 // According to the IA2 Spec, only line boundaries should succeed when | 2300 // According to the IA2 Spec, only line boundaries should succeed when |
| 2301 // the offset is one past the end of the text. | 2301 // the offset is one past the end of the text. |
| 2302 if (offset == text_len) { | 2302 if (offset == text_len && boundary_type != IA2_TEXT_BOUNDARY_LINE) |
| 2303 if (boundary_type == IA2_TEXT_BOUNDARY_LINE) { | 2303 return S_FALSE; |
| 2304 --offset; | |
| 2305 } else { | |
| 2306 *start_offset = 0; | |
| 2307 *end_offset = 0; | |
| 2308 *text = nullptr; | |
| 2309 return S_FALSE; | |
| 2310 } | |
| 2311 } | |
| 2312 | 2304 |
| 2313 *start_offset = | 2305 LONG start = FindBoundary(boundary_type, offset, ui::BACKWARDS_DIRECTION); |
| 2314 FindBoundary(text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION); | 2306 LONG end = FindBoundary(boundary_type, start, ui::FORWARDS_DIRECTION); |
| 2315 *end_offset = | 2307 if (end < offset) |
| 2316 FindBoundary(text_str, boundary_type, offset, ui::FORWARDS_DIRECTION); | 2308 return S_FALSE; |
| 2317 return get_text(*start_offset, *end_offset, text); | 2309 |
| 2310 *start_offset = start; |
| 2311 *end_offset = end; |
| 2312 return get_text(start, end, text); |
| 2318 } | 2313 } |
| 2319 | 2314 |
| 2320 STDMETHODIMP BrowserAccessibilityComWin::get_textBeforeOffset( | 2315 STDMETHODIMP BrowserAccessibilityComWin::get_textBeforeOffset( |
| 2321 LONG offset, | 2316 LONG offset, |
| 2322 IA2TextBoundaryType boundary_type, | 2317 IA2TextBoundaryType boundary_type, |
| 2323 LONG* start_offset, | 2318 LONG* start_offset, |
| 2324 LONG* end_offset, | 2319 LONG* end_offset, |
| 2325 BSTR* text) { | 2320 BSTR* text) { |
| 2326 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_BEFORE_OFFSET); | 2321 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_BEFORE_OFFSET); |
| 2327 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes | | 2322 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes | |
| 2328 AccessibilityMode::kInlineTextBoxes); | 2323 AccessibilityMode::kInlineTextBoxes); |
| 2329 if (!owner()) | 2324 if (!owner()) |
| 2330 return E_FAIL; | 2325 return E_FAIL; |
| 2331 | 2326 |
| 2332 if (!start_offset || !end_offset || !text) | 2327 if (!start_offset || !end_offset || !text) |
| 2333 return E_INVALIDARG; | 2328 return E_INVALIDARG; |
| 2334 | 2329 |
| 2330 *start_offset = 0; |
| 2331 *end_offset = 0; |
| 2332 *text = NULL; |
| 2333 |
| 2334 const base::string16& text_str = owner()->GetText(); |
| 2335 LONG text_len = text_str.length(); |
| 2336 if (offset > text_len) |
| 2337 return E_INVALIDARG; |
| 2338 |
| 2335 // The IAccessible2 spec says we don't have to implement the "sentence" | 2339 // The IAccessible2 spec says we don't have to implement the "sentence" |
| 2336 // boundary type, we can just let the screenreader handle it. | 2340 // boundary type, we can just let the screenreader handle it. |
| 2337 if (boundary_type == IA2_TEXT_BOUNDARY_SENTENCE) { | 2341 if (boundary_type == IA2_TEXT_BOUNDARY_SENTENCE) |
| 2338 *start_offset = 0; | |
| 2339 *end_offset = 0; | |
| 2340 *text = NULL; | |
| 2341 return S_FALSE; | 2342 return S_FALSE; |
| 2342 } | |
| 2343 | 2343 |
| 2344 const base::string16& text_str = owner()->GetText(); | 2344 *start_offset = FindBoundary(boundary_type, offset, ui::BACKWARDS_DIRECTION); |
| 2345 | |
| 2346 *start_offset = | |
| 2347 FindBoundary(text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION); | |
| 2348 *end_offset = offset; | 2345 *end_offset = offset; |
| 2349 return get_text(*start_offset, *end_offset, text); | 2346 return get_text(*start_offset, *end_offset, text); |
| 2350 } | 2347 } |
| 2351 | 2348 |
| 2352 STDMETHODIMP BrowserAccessibilityComWin::get_textAfterOffset( | 2349 STDMETHODIMP BrowserAccessibilityComWin::get_textAfterOffset( |
| 2353 LONG offset, | 2350 LONG offset, |
| 2354 IA2TextBoundaryType boundary_type, | 2351 IA2TextBoundaryType boundary_type, |
| 2355 LONG* start_offset, | 2352 LONG* start_offset, |
| 2356 LONG* end_offset, | 2353 LONG* end_offset, |
| 2357 BSTR* text) { | 2354 BSTR* text) { |
| 2358 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_AFTER_OFFSET); | 2355 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_AFTER_OFFSET); |
| 2359 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes | | 2356 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes | |
| 2360 AccessibilityMode::kInlineTextBoxes); | 2357 AccessibilityMode::kInlineTextBoxes); |
| 2361 if (!owner()) | 2358 if (!owner()) |
| 2362 return E_FAIL; | 2359 return E_FAIL; |
| 2363 | 2360 |
| 2364 if (!start_offset || !end_offset || !text) | 2361 if (!start_offset || !end_offset || !text) |
| 2365 return E_INVALIDARG; | 2362 return E_INVALIDARG; |
| 2366 | 2363 |
| 2364 *start_offset = 0; |
| 2365 *end_offset = 0; |
| 2366 *text = NULL; |
| 2367 |
| 2368 const base::string16& text_str = owner()->GetText(); |
| 2369 LONG text_len = text_str.length(); |
| 2370 if (offset > text_len) |
| 2371 return E_INVALIDARG; |
| 2372 |
| 2367 // The IAccessible2 spec says we don't have to implement the "sentence" | 2373 // The IAccessible2 spec says we don't have to implement the "sentence" |
| 2368 // boundary type, we can just let the screenreader handle it. | 2374 // boundary type, we can just let the screenreader handle it. |
| 2369 if (boundary_type == IA2_TEXT_BOUNDARY_SENTENCE) { | 2375 if (boundary_type == IA2_TEXT_BOUNDARY_SENTENCE) |
| 2370 *start_offset = 0; | |
| 2371 *end_offset = 0; | |
| 2372 *text = NULL; | |
| 2373 return S_FALSE; | 2376 return S_FALSE; |
| 2374 } | |
| 2375 | |
| 2376 const base::string16& text_str = owner()->GetText(); | |
| 2377 | 2377 |
| 2378 *start_offset = offset; | 2378 *start_offset = offset; |
| 2379 *end_offset = | 2379 *end_offset = FindBoundary(boundary_type, offset, ui::FORWARDS_DIRECTION); |
| 2380 FindBoundary(text_str, boundary_type, offset, ui::FORWARDS_DIRECTION); | |
| 2381 return get_text(*start_offset, *end_offset, text); | 2380 return get_text(*start_offset, *end_offset, text); |
| 2382 } | 2381 } |
| 2383 | 2382 |
| 2384 STDMETHODIMP BrowserAccessibilityComWin::get_newText(IA2TextSegment* new_text) { | 2383 STDMETHODIMP BrowserAccessibilityComWin::get_newText(IA2TextSegment* new_text) { |
| 2385 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_NEW_TEXT); | 2384 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_NEW_TEXT); |
| 2386 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes); | 2385 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes); |
| 2387 if (!owner()) | 2386 if (!owner()) |
| 2388 return E_FAIL; | 2387 return E_FAIL; |
| 2389 | 2388 |
| 2390 if (!new_text) | 2389 if (!new_text) |
| (...skipping 2399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4790 case IA2_TEXT_BOUNDARY_PARAGRAPH: | 4789 case IA2_TEXT_BOUNDARY_PARAGRAPH: |
| 4791 return ui::PARAGRAPH_BOUNDARY; | 4790 return ui::PARAGRAPH_BOUNDARY; |
| 4792 case IA2_TEXT_BOUNDARY_ALL: | 4791 case IA2_TEXT_BOUNDARY_ALL: |
| 4793 return ui::ALL_BOUNDARY; | 4792 return ui::ALL_BOUNDARY; |
| 4794 } | 4793 } |
| 4795 NOTREACHED(); | 4794 NOTREACHED(); |
| 4796 return ui::CHAR_BOUNDARY; | 4795 return ui::CHAR_BOUNDARY; |
| 4797 } | 4796 } |
| 4798 | 4797 |
| 4799 LONG BrowserAccessibilityComWin::FindBoundary( | 4798 LONG BrowserAccessibilityComWin::FindBoundary( |
| 4800 const base::string16& text, | |
| 4801 IA2TextBoundaryType ia2_boundary, | 4799 IA2TextBoundaryType ia2_boundary, |
| 4802 LONG start_offset, | 4800 LONG start_offset, |
| 4803 ui::TextBoundaryDirection direction) { | 4801 ui::TextBoundaryDirection direction) { |
| 4804 // If the boundary is relative to the caret, use the selection | 4802 // If the boundary is relative to the caret, use the selection |
| 4805 // affinity, otherwise default to downstream affinity. | 4803 // affinity, otherwise default to downstream affinity. |
| 4806 ui::AXTextAffinity affinity = | 4804 ui::AXTextAffinity affinity = |
| 4807 start_offset == IA2_TEXT_OFFSET_CARET | 4805 start_offset == IA2_TEXT_OFFSET_CARET |
| 4808 ? Manager()->GetTreeData().sel_focus_affinity | 4806 ? Manager()->GetTreeData().sel_focus_affinity |
| 4809 : ui::AX_TEXT_AFFINITY_DOWNSTREAM; | 4807 : ui::AX_TEXT_AFFINITY_DOWNSTREAM; |
| 4810 | 4808 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4858 } else { | 4856 } else { |
| 4859 previous_line = std::move(position); | 4857 previous_line = std::move(position); |
| 4860 } | 4858 } |
| 4861 return previous_line->text_offset(); | 4859 return previous_line->text_offset(); |
| 4862 } | 4860 } |
| 4863 } | 4861 } |
| 4864 } | 4862 } |
| 4865 | 4863 |
| 4866 // TODO(nektar): |AXPosition| can handle other types of boundaries as well. | 4864 // TODO(nektar): |AXPosition| can handle other types of boundaries as well. |
| 4867 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); | 4865 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); |
| 4868 return ui::FindAccessibleTextBoundary(text, owner()->GetLineStartOffsets(), | 4866 return ui::FindAccessibleTextBoundary( |
| 4869 boundary, start_offset, direction, | 4867 owner()->GetText(), owner()->GetLineStartOffsets(), boundary, |
| 4870 affinity); | 4868 start_offset, direction, affinity); |
| 4871 } | 4869 } |
| 4872 | 4870 |
| 4873 LONG BrowserAccessibilityComWin::FindStartOfStyle( | 4871 LONG BrowserAccessibilityComWin::FindStartOfStyle( |
| 4874 LONG start_offset, | 4872 LONG start_offset, |
| 4875 ui::TextBoundaryDirection direction) const { | 4873 ui::TextBoundaryDirection direction) const { |
| 4876 LONG text_length = static_cast<LONG>(owner()->GetText().length()); | 4874 LONG text_length = static_cast<LONG>(owner()->GetText().length()); |
| 4877 DCHECK_GE(start_offset, 0); | 4875 DCHECK_GE(start_offset, 0); |
| 4878 DCHECK_LE(start_offset, text_length); | 4876 DCHECK_LE(start_offset, text_length); |
| 4879 | 4877 |
| 4880 switch (direction) { | 4878 switch (direction) { |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5717 | 5715 |
| 5718 BrowserAccessibilityComWin* ToBrowserAccessibilityComWin( | 5716 BrowserAccessibilityComWin* ToBrowserAccessibilityComWin( |
| 5719 BrowserAccessibility* obj) { | 5717 BrowserAccessibility* obj) { |
| 5720 if (!obj || !obj->IsNative()) | 5718 if (!obj || !obj->IsNative()) |
| 5721 return nullptr; | 5719 return nullptr; |
| 5722 auto* result = static_cast<BrowserAccessibilityWin*>(obj)->GetCOM(); | 5720 auto* result = static_cast<BrowserAccessibilityWin*>(obj)->GetCOM(); |
| 5723 return result; | 5721 return result; |
| 5724 } | 5722 } |
| 5725 | 5723 |
| 5726 } // namespace content | 5724 } // namespace content |
| OLD | NEW |