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 |