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 "content/browser/accessibility/browser_accessibility_win.h" | 5 #include "content/browser/accessibility/browser_accessibility_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> |
| 11 |
10 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
12 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
13 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
14 #include "base/win/enum_variant.h" | 16 #include "base/win/enum_variant.h" |
15 #include "base/win/scoped_comptr.h" | 17 #include "base/win/scoped_comptr.h" |
16 #include "base/win/windows_version.h" | 18 #include "base/win/windows_version.h" |
17 #include "content/browser/accessibility/browser_accessibility_manager_win.h" | 19 #include "content/browser/accessibility/browser_accessibility_manager_win.h" |
18 #include "content/browser/accessibility/browser_accessibility_state_impl.h" | 20 #include "content/browser/accessibility/browser_accessibility_state_impl.h" |
19 #include "content/common/accessibility_messages.h" | 21 #include "content/common/accessibility_messages.h" |
(...skipping 1977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1997 return S_OK; | 1999 return S_OK; |
1998 } | 2000 } |
1999 | 2001 |
2000 STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) { | 2002 STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) { |
2001 if (!instance_active()) | 2003 if (!instance_active()) |
2002 return E_FAIL; | 2004 return E_FAIL; |
2003 | 2005 |
2004 if (!offset) | 2006 if (!offset) |
2005 return E_INVALIDARG; | 2007 return E_INVALIDARG; |
2006 | 2008 |
2007 // IA2 spec says that caret offset should be -1 if the object is not focused. | 2009 int selection_start, selection_end; |
2008 if (manager()->GetFocus(this) != this) { | 2010 GetSelectionOffsets(&selection_start, &selection_end); |
2009 *offset = -1; | 2011 *offset = selection_start; |
| 2012 if (selection_start < 0) |
2010 return S_FALSE; | 2013 return S_FALSE; |
2011 } | |
2012 | |
2013 *offset = 0; | |
2014 if (IsEditableText()) { | |
2015 int sel_start = 0; | |
2016 if (GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, | |
2017 &sel_start)) | |
2018 *offset = sel_start; | |
2019 } | |
2020 | 2014 |
2021 return S_OK; | 2015 return S_OK; |
2022 } | 2016 } |
2023 | 2017 |
2024 STDMETHODIMP BrowserAccessibilityWin::get_characterExtents( | 2018 STDMETHODIMP BrowserAccessibilityWin::get_characterExtents( |
2025 LONG offset, | 2019 LONG offset, |
2026 enum IA2CoordinateType coordinate_type, | 2020 enum IA2CoordinateType coordinate_type, |
2027 LONG* out_x, | 2021 LONG* out_x, |
2028 LONG* out_y, | 2022 LONG* out_y, |
2029 LONG* out_width, | 2023 LONG* out_width, |
(...skipping 29 matching lines...) Expand all Loading... |
2059 } | 2053 } |
2060 | 2054 |
2061 STDMETHODIMP BrowserAccessibilityWin::get_nSelections(LONG* n_selections) { | 2055 STDMETHODIMP BrowserAccessibilityWin::get_nSelections(LONG* n_selections) { |
2062 if (!instance_active()) | 2056 if (!instance_active()) |
2063 return E_FAIL; | 2057 return E_FAIL; |
2064 | 2058 |
2065 if (!n_selections) | 2059 if (!n_selections) |
2066 return E_INVALIDARG; | 2060 return E_INVALIDARG; |
2067 | 2061 |
2068 *n_selections = 0; | 2062 *n_selections = 0; |
2069 if (IsEditableText()) { | 2063 int selection_start, selection_end; |
2070 int sel_start = 0; | 2064 GetSelectionOffsets(&selection_start, &selection_end); |
2071 int sel_end = 0; | 2065 if (selection_start >= 0 && selection_end >= 0 && |
2072 if (GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, | 2066 selection_start != selection_end) |
2073 &sel_start) && | 2067 *n_selections = 1; |
2074 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &sel_end) && | |
2075 sel_start != sel_end) | |
2076 *n_selections = 1; | |
2077 } | |
2078 | 2068 |
2079 return S_OK; | 2069 return S_OK; |
2080 } | 2070 } |
2081 | 2071 |
2082 STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index, | 2072 STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index, |
2083 LONG* start_offset, | 2073 LONG* start_offset, |
2084 LONG* end_offset) { | 2074 LONG* end_offset) { |
2085 if (!instance_active()) | 2075 if (!instance_active()) |
2086 return E_FAIL; | 2076 return E_FAIL; |
2087 | 2077 |
2088 if (!start_offset || !end_offset || selection_index != 0) | 2078 if (!start_offset || !end_offset || selection_index != 0) |
2089 return E_INVALIDARG; | 2079 return E_INVALIDARG; |
2090 | 2080 |
2091 LONG n_selections = 0; | 2081 LONG n_selections = 0; |
2092 if (FAILED(get_nSelections(&n_selections)) || n_selections < 1) | 2082 if (FAILED(get_nSelections(&n_selections)) || n_selections < 1) |
2093 return E_INVALIDARG; | 2083 return E_INVALIDARG; |
2094 | 2084 |
2095 *start_offset = 0; | 2085 *start_offset = 0; |
2096 *end_offset = 0; | 2086 *end_offset = 0; |
2097 if (IsEditableText()) { | 2087 int selection_start, selection_end; |
2098 int sel_start = 0; | 2088 GetSelectionOffsets(&selection_start, &selection_end); |
2099 int sel_end = 0; | 2089 if (selection_start >= 0 && selection_end >= 0) { |
2100 if (GetIntAttribute( | 2090 *start_offset = selection_start; |
2101 ui::AX_ATTR_TEXT_SEL_START, &sel_start) && | 2091 *end_offset = selection_end; |
2102 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &sel_end)) { | |
2103 *start_offset = sel_start; | |
2104 *end_offset = sel_end; | |
2105 } | |
2106 } | 2092 } |
2107 | 2093 |
2108 return S_OK; | 2094 return S_OK; |
2109 } | 2095 } |
2110 | 2096 |
2111 STDMETHODIMP BrowserAccessibilityWin::get_text(LONG start_offset, | 2097 STDMETHODIMP BrowserAccessibilityWin::get_text(LONG start_offset, |
2112 LONG end_offset, | 2098 LONG end_offset, |
2113 BSTR* text) { | 2099 BSTR* text) { |
2114 if (!instance_active()) | 2100 if (!instance_active()) |
2115 return E_FAIL; | 2101 return E_FAIL; |
(...skipping 1530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3646 ui::AXIntAttribute attribute, | 3632 ui::AXIntAttribute attribute, |
3647 const char* ia2_attr) { | 3633 const char* ia2_attr) { |
3648 int value; | 3634 int value; |
3649 if (GetIntAttribute(attribute, &value)) { | 3635 if (GetIntAttribute(attribute, &value)) { |
3650 win_attributes_->ia2_attributes.push_back( | 3636 win_attributes_->ia2_attributes.push_back( |
3651 base::ASCIIToUTF16(ia2_attr) + L":" + | 3637 base::ASCIIToUTF16(ia2_attr) + L":" + |
3652 base::IntToString16(value)); | 3638 base::IntToString16(value)); |
3653 } | 3639 } |
3654 } | 3640 } |
3655 | 3641 |
| 3642 int32 BrowserAccessibilityWin::GetHyperlinkIndexFromChild( |
| 3643 const BrowserAccessibilityWin& child) const { |
| 3644 auto iterator = std::find( |
| 3645 hyperlinks().begin(), hyperlinks().end(), child.GetId()); |
| 3646 if (iterator == hyperlinks().end()) |
| 3647 return -1; |
| 3648 |
| 3649 return static_cast<int32>(iterator - hyperlinks().begin()); |
| 3650 } |
| 3651 |
| 3652 int32 BrowserAccessibilityWin::GetHypertextOffsetFromHyperlinkIndex( |
| 3653 int32 hyperlink_index) const { |
| 3654 auto& offsets_map = hyperlink_offset_to_index(); |
| 3655 for (auto& offset_index : offsets_map) { |
| 3656 if (offset_index.second == hyperlink_index) |
| 3657 return offset_index.first; |
| 3658 } |
| 3659 |
| 3660 return -1; |
| 3661 } |
| 3662 |
| 3663 int32 BrowserAccessibilityWin::GetHypertextOffsetFromChild( |
| 3664 const BrowserAccessibilityWin& child) const { |
| 3665 int32 hyperlink_index = GetHyperlinkIndexFromChild(child); |
| 3666 if (hyperlink_index < 0) |
| 3667 return -1; |
| 3668 |
| 3669 return GetHypertextOffsetFromHyperlinkIndex(hyperlink_index); |
| 3670 } |
| 3671 |
| 3672 int32 BrowserAccessibilityWin::GetHypertextOffsetFromDescendant( |
| 3673 const BrowserAccessibilityWin& descendant) const { |
| 3674 auto parent_object = descendant.GetParent()->ToBrowserAccessibilityWin(); |
| 3675 auto current_object = const_cast<BrowserAccessibilityWin*>(&descendant); |
| 3676 while (parent_object && parent_object != this) { |
| 3677 current_object = parent_object; |
| 3678 parent_object = current_object->GetParent()->ToBrowserAccessibilityWin(); |
| 3679 } |
| 3680 if (!parent_object) |
| 3681 return -1; |
| 3682 |
| 3683 return parent_object->GetHypertextOffsetFromChild(*current_object); |
| 3684 } |
| 3685 |
| 3686 int BrowserAccessibilityWin::GetSelectionAnchor() const { |
| 3687 BrowserAccessibility* root = manager()->GetRoot(); |
| 3688 int32 anchor_id; |
| 3689 if (!root || !root->GetIntAttribute(ui::AX_ATTR_ANCHOR_OBJECT_ID, &anchor_id)) |
| 3690 return -1; |
| 3691 |
| 3692 BrowserAccessibilityWin* anchor_object = manager()->GetFromID( |
| 3693 anchor_id)->ToBrowserAccessibilityWin(); |
| 3694 if (!anchor_object) |
| 3695 return -1; |
| 3696 |
| 3697 if (anchor_object->IsDescendantOf(this)) |
| 3698 return GetHypertextOffsetFromDescendant(*anchor_object); |
| 3699 |
| 3700 if (IsDescendantOf(anchor_object)) { |
| 3701 int anchor_offset; |
| 3702 if (!root->GetIntAttribute(ui::AX_ATTR_ANCHOR_OFFSET, &anchor_offset)) |
| 3703 return -1; |
| 3704 |
| 3705 return anchor_offset; |
| 3706 } |
| 3707 |
| 3708 return -1; |
| 3709 } |
| 3710 |
| 3711 int BrowserAccessibilityWin::GetSelectionFocus() const { |
| 3712 BrowserAccessibility* root = manager()->GetRoot(); |
| 3713 int32 focus_id; |
| 3714 if (!root || !root->GetIntAttribute(ui::AX_ATTR_FOCUS_OBJECT_ID, &focus_id)) |
| 3715 return -1; |
| 3716 |
| 3717 BrowserAccessibilityWin* focus_object = manager()->GetFromID( |
| 3718 focus_id)->ToBrowserAccessibilityWin(); |
| 3719 if (!focus_object) |
| 3720 return -1; |
| 3721 |
| 3722 if (focus_object->IsDescendantOf(this)) |
| 3723 return GetHypertextOffsetFromDescendant(*focus_object); |
| 3724 |
| 3725 if (IsDescendantOf(focus_object)) { |
| 3726 int focus_offset; |
| 3727 if (!root->GetIntAttribute(ui::AX_ATTR_FOCUS_OFFSET, &focus_offset)) |
| 3728 return -1; |
| 3729 |
| 3730 return focus_offset; |
| 3731 } |
| 3732 |
| 3733 return -1; |
| 3734 } |
| 3735 |
| 3736 void BrowserAccessibilityWin::GetSelectionOffsets( |
| 3737 int* selection_start, int* selection_end) const { |
| 3738 DCHECK(selection_start && selection_end); |
| 3739 |
| 3740 if (GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, selection_start) && |
| 3741 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, selection_end)) { |
| 3742 return; |
| 3743 } |
| 3744 |
| 3745 *selection_start = GetSelectionAnchor(); |
| 3746 *selection_end = GetSelectionFocus(); |
| 3747 if (*selection_start < 0 || *selection_end < 0) |
| 3748 return; |
| 3749 |
| 3750 if (*selection_end < *selection_start) |
| 3751 std::swap(*selection_start, *selection_end); |
| 3752 |
| 3753 // IA2 Spec says that the end of the selection should be after the last |
| 3754 // embedded object character that is part of the selection. |
| 3755 ++(*selection_end); |
| 3756 } |
| 3757 |
3656 base::string16 BrowserAccessibilityWin::GetNameRecursive() const { | 3758 base::string16 BrowserAccessibilityWin::GetNameRecursive() const { |
3657 if (!name().empty()) { | 3759 if (!name().empty()) { |
3658 return name(); | 3760 return name(); |
3659 } | 3761 } |
3660 | 3762 |
3661 base::string16 result; | 3763 base::string16 result; |
3662 for (uint32 i = 0; i < PlatformChildCount(); ++i) { | 3764 for (uint32 i = 0; i < PlatformChildCount(); ++i) { |
3663 result += PlatformGetChild(i)->ToBrowserAccessibilityWin()-> | 3765 result += PlatformGetChild(i)->ToBrowserAccessibilityWin()-> |
3664 GetNameRecursive(); | 3766 GetNameRecursive(); |
3665 } | 3767 } |
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4377 ia2_role = ia_role; | 4479 ia2_role = ia_role; |
4378 | 4480 |
4379 win_attributes_->ia_role = ia_role; | 4481 win_attributes_->ia_role = ia_role; |
4380 win_attributes_->ia_state = ia_state; | 4482 win_attributes_->ia_state = ia_state; |
4381 win_attributes_->role_name = role_name; | 4483 win_attributes_->role_name = role_name; |
4382 win_attributes_->ia2_role = ia2_role; | 4484 win_attributes_->ia2_role = ia2_role; |
4383 win_attributes_->ia2_state = ia2_state; | 4485 win_attributes_->ia2_state = ia2_state; |
4384 } | 4486 } |
4385 | 4487 |
4386 } // namespace content | 4488 } // namespace content |
OLD | NEW |