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> | 10 #include <algorithm> |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 | 200 |
201 // static | 201 // static |
202 BrowserAccessibility* BrowserAccessibility::Create() { | 202 BrowserAccessibility* BrowserAccessibility::Create() { |
203 ui::win::CreateATLModuleIfNeeded(); | 203 ui::win::CreateATLModuleIfNeeded(); |
204 CComObject<BrowserAccessibilityWin>* instance; | 204 CComObject<BrowserAccessibilityWin>* instance; |
205 HRESULT hr = CComObject<BrowserAccessibilityWin>::CreateInstance(&instance); | 205 HRESULT hr = CComObject<BrowserAccessibilityWin>::CreateInstance(&instance); |
206 DCHECK(SUCCEEDED(hr)); | 206 DCHECK(SUCCEEDED(hr)); |
207 return instance->NewReference(); | 207 return instance->NewReference(); |
208 } | 208 } |
209 | 209 |
| 210 const BrowserAccessibilityWin* BrowserAccessibility::ToBrowserAccessibilityWin() |
| 211 const { |
| 212 return static_cast<const BrowserAccessibilityWin*>(this); |
| 213 } |
| 214 |
210 BrowserAccessibilityWin* BrowserAccessibility::ToBrowserAccessibilityWin() { | 215 BrowserAccessibilityWin* BrowserAccessibility::ToBrowserAccessibilityWin() { |
211 return static_cast<BrowserAccessibilityWin*>(this); | 216 return static_cast<BrowserAccessibilityWin*>(this); |
212 } | 217 } |
213 | 218 |
214 BrowserAccessibilityWin::BrowserAccessibilityWin() | 219 BrowserAccessibilityWin::BrowserAccessibilityWin() |
215 : win_attributes_(new WinAttributes()), | 220 : win_attributes_(new WinAttributes()), |
216 previous_scroll_x_(0), | 221 previous_scroll_x_(0), |
217 previous_scroll_y_(0) { | 222 previous_scroll_y_(0) { |
218 // Start unique IDs at -1 and decrement each time, because get_accChild | 223 // Start unique IDs at -1 and decrement each time, because get_accChild |
219 // uses positive IDs to enumerate children, so we use negative IDs to | 224 // uses positive IDs to enumerate children, so we use negative IDs to |
(...skipping 1783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2003 | 2008 |
2004 STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) { | 2009 STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) { |
2005 if (!instance_active()) | 2010 if (!instance_active()) |
2006 return E_FAIL; | 2011 return E_FAIL; |
2007 | 2012 |
2008 if (!offset) | 2013 if (!offset) |
2009 return E_INVALIDARG; | 2014 return E_INVALIDARG; |
2010 | 2015 |
2011 int selection_start, selection_end; | 2016 int selection_start, selection_end; |
2012 GetSelectionOffsets(&selection_start, &selection_end); | 2017 GetSelectionOffsets(&selection_start, &selection_end); |
2013 *offset = selection_start; | 2018 // The caret is always at the end of the selection, if a selection exists. |
2014 if (selection_start < 0) | 2019 *offset = selection_end; |
| 2020 if (*offset < 0) |
2015 return S_FALSE; | 2021 return S_FALSE; |
2016 | 2022 |
2017 return S_OK; | 2023 return S_OK; |
2018 } | 2024 } |
2019 | 2025 |
2020 STDMETHODIMP BrowserAccessibilityWin::get_characterExtents( | 2026 STDMETHODIMP BrowserAccessibilityWin::get_characterExtents( |
2021 LONG offset, | 2027 LONG offset, |
2022 enum IA2CoordinateType coordinate_type, | 2028 enum IA2CoordinateType coordinate_type, |
2023 LONG* out_x, | 2029 LONG* out_x, |
2024 LONG* out_y, | 2030 LONG* out_y, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2058 if (!instance_active()) | 2064 if (!instance_active()) |
2059 return E_FAIL; | 2065 return E_FAIL; |
2060 | 2066 |
2061 if (!n_selections) | 2067 if (!n_selections) |
2062 return E_INVALIDARG; | 2068 return E_INVALIDARG; |
2063 | 2069 |
2064 *n_selections = 0; | 2070 *n_selections = 0; |
2065 int selection_start, selection_end; | 2071 int selection_start, selection_end; |
2066 GetSelectionOffsets(&selection_start, &selection_end); | 2072 GetSelectionOffsets(&selection_start, &selection_end); |
2067 if (selection_start >= 0 && selection_end >= 0 && | 2073 if (selection_start >= 0 && selection_end >= 0 && |
2068 selection_start != selection_end) | 2074 selection_start != selection_end) { |
2069 *n_selections = 1; | 2075 *n_selections = 1; |
| 2076 } |
2070 | 2077 |
2071 return S_OK; | 2078 return S_OK; |
2072 } | 2079 } |
2073 | 2080 |
2074 STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index, | 2081 STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index, |
2075 LONG* start_offset, | 2082 LONG* start_offset, |
2076 LONG* end_offset) { | 2083 LONG* end_offset) { |
2077 if (!instance_active()) | 2084 if (!instance_active()) |
2078 return E_FAIL; | 2085 return E_FAIL; |
2079 | 2086 |
2080 if (!start_offset || !end_offset || selection_index != 0) | 2087 if (!start_offset || !end_offset || selection_index != 0) |
2081 return E_INVALIDARG; | 2088 return E_INVALIDARG; |
2082 | 2089 |
2083 LONG n_selections = 0; | 2090 LONG n_selections = 0; |
2084 if (FAILED(get_nSelections(&n_selections)) || n_selections < 1) | 2091 if (FAILED(get_nSelections(&n_selections)) || n_selections < 1) |
2085 return E_INVALIDARG; | 2092 return E_INVALIDARG; |
2086 | 2093 |
2087 *start_offset = 0; | 2094 *start_offset = 0; |
2088 *end_offset = 0; | 2095 *end_offset = 0; |
2089 int selection_start, selection_end; | 2096 int selection_start, selection_end; |
2090 GetSelectionOffsets(&selection_start, &selection_end); | 2097 GetSelectionOffsets(&selection_start, &selection_end); |
2091 if (selection_start >= 0 && selection_end >= 0) { | 2098 if (selection_start >= 0 && selection_end >= 0) { |
| 2099 // We should ignore the direction of the selection when exposing start and |
| 2100 // end offsets. According to the IA2 Spec the end offset is always increased |
| 2101 // by one past the end of the selection. This wouldn't make sense if |
| 2102 // end < start. |
| 2103 if (selection_end < selection_start) |
| 2104 std::swap(selection_start, selection_end); |
| 2105 |
2092 *start_offset = selection_start; | 2106 *start_offset = selection_start; |
2093 *end_offset = selection_end; | 2107 *end_offset = selection_end; |
2094 } | 2108 } |
2095 | 2109 |
2096 return S_OK; | 2110 return S_OK; |
2097 } | 2111 } |
2098 | 2112 |
2099 STDMETHODIMP BrowserAccessibilityWin::get_text(LONG start_offset, | 2113 STDMETHODIMP BrowserAccessibilityWin::get_text(LONG start_offset, |
2100 LONG end_offset, | 2114 LONG end_offset, |
2101 BSTR* text) { | 2115 BSTR* text) { |
(...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3641 int value; | 3655 int value; |
3642 if (GetIntAttribute(attribute, &value)) { | 3656 if (GetIntAttribute(attribute, &value)) { |
3643 win_attributes_->ia2_attributes.push_back( | 3657 win_attributes_->ia2_attributes.push_back( |
3644 base::ASCIIToUTF16(ia2_attr) + L":" + | 3658 base::ASCIIToUTF16(ia2_attr) + L":" + |
3645 base::IntToString16(value)); | 3659 base::IntToString16(value)); |
3646 } | 3660 } |
3647 } | 3661 } |
3648 | 3662 |
3649 int32 BrowserAccessibilityWin::GetHyperlinkIndexFromChild( | 3663 int32 BrowserAccessibilityWin::GetHyperlinkIndexFromChild( |
3650 const BrowserAccessibilityWin& child) const { | 3664 const BrowserAccessibilityWin& child) const { |
| 3665 if (hyperlinks().empty()) |
| 3666 return -1; |
| 3667 |
3651 auto iterator = std::find( | 3668 auto iterator = std::find( |
3652 hyperlinks().begin(), hyperlinks().end(), child.GetId()); | 3669 hyperlinks().begin(), hyperlinks().end(), child.GetId()); |
3653 if (iterator == hyperlinks().end()) | 3670 if (iterator == hyperlinks().end()) |
3654 return -1; | 3671 return -1; |
3655 | 3672 |
3656 return static_cast<int32>(iterator - hyperlinks().begin()); | 3673 return static_cast<int32>(iterator - hyperlinks().begin()); |
3657 } | 3674 } |
3658 | 3675 |
3659 int32 BrowserAccessibilityWin::GetHypertextOffsetFromHyperlinkIndex( | 3676 int32 BrowserAccessibilityWin::GetHypertextOffsetFromHyperlinkIndex( |
3660 int32 hyperlink_index) const { | 3677 int32 hyperlink_index) const { |
3661 auto& offsets_map = hyperlink_offset_to_index(); | 3678 for (auto& offset_index : hyperlink_offset_to_index()) { |
3662 for (auto& offset_index : offsets_map) { | |
3663 if (offset_index.second == hyperlink_index) | 3679 if (offset_index.second == hyperlink_index) |
3664 return offset_index.first; | 3680 return offset_index.first; |
3665 } | 3681 } |
3666 | 3682 |
3667 return -1; | 3683 return -1; |
3668 } | 3684 } |
3669 | 3685 |
3670 int32 BrowserAccessibilityWin::GetHypertextOffsetFromChild( | 3686 int32 BrowserAccessibilityWin::GetHypertextOffsetFromChild( |
3671 const BrowserAccessibilityWin& child) const { | 3687 const BrowserAccessibilityWin& child) const { |
3672 int32 hyperlink_index = GetHyperlinkIndexFromChild(child); | 3688 int32 hyperlink_index = GetHyperlinkIndexFromChild(child); |
(...skipping 10 matching lines...) Expand all Loading... |
3683 while (parent_object && parent_object != this) { | 3699 while (parent_object && parent_object != this) { |
3684 current_object = parent_object; | 3700 current_object = parent_object; |
3685 parent_object = current_object->GetParent()->ToBrowserAccessibilityWin(); | 3701 parent_object = current_object->GetParent()->ToBrowserAccessibilityWin(); |
3686 } | 3702 } |
3687 if (!parent_object) | 3703 if (!parent_object) |
3688 return -1; | 3704 return -1; |
3689 | 3705 |
3690 return parent_object->GetHypertextOffsetFromChild(*current_object); | 3706 return parent_object->GetHypertextOffsetFromChild(*current_object); |
3691 } | 3707 } |
3692 | 3708 |
| 3709 int BrowserAccessibilityWin::GetHypertextOffsetFromEndpoint( |
| 3710 const BrowserAccessibilityWin& endpoint_object, |
| 3711 int endpoint_offset) const { |
| 3712 // There are three cases: |
| 3713 // 1. Either the selection endpoint is inside this object or is an ancestor of |
| 3714 // of this object. endpoint_offset should be returned. |
| 3715 // 2. The selection endpoint is a pure descendant of this object. The offset |
| 3716 // of the embedded object character corresponding to the subtree in which |
| 3717 // the endpoint is located should be returned. |
| 3718 // 3. The selection endpoint is in a completely different part of the tree. |
| 3719 // Either 0 or text_length should be returned depending on the direction that |
| 3720 // one needs to travel to find the endpoint. |
| 3721 |
| 3722 // Case 1. |
| 3723 // |
| 3724 // IsDescendantOf includes the case when endpoint_object == this. |
| 3725 if (IsDescendantOf(&endpoint_object) || |
| 3726 // Handle the case when the endpoint is a direct text-only child. |
| 3727 // The selection offset should still be valid on the parent. |
| 3728 (endpoint_object.IsTextOnlyObject() && |
| 3729 endpoint_object.GetParent() == this)) { |
| 3730 return endpoint_offset; |
| 3731 } |
| 3732 |
| 3733 const BrowserAccessibility* common_parent = this; |
| 3734 int32 index_in_common_parent = 0; |
| 3735 while (common_parent && !endpoint_object.IsDescendantOf(common_parent)) { |
| 3736 index_in_common_parent = common_parent->GetIndexInParent(); |
| 3737 common_parent = common_parent->GetParent(); |
| 3738 } |
| 3739 if (!common_parent) |
| 3740 return -1; |
| 3741 |
| 3742 auto common_parent_win = common_parent->ToBrowserAccessibilityWin(); |
| 3743 DCHECK_GE(index_in_common_parent, 0); |
| 3744 DCHECK(!(common_parent_win->IsTextOnlyObject())); |
| 3745 |
| 3746 // Case 2. |
| 3747 // |
| 3748 // We already checked in case 1 if our endpoint is inside this object. |
| 3749 // We can safely assume that it is a descendant or in a completely different |
| 3750 // part of the tree. |
| 3751 if (common_parent_win == this) { |
| 3752 // Text only objects must have a parent. |
| 3753 DCHECK(!endpoint_object.IsTextOnlyObject() || endpoint_object.GetParent()); |
| 3754 // Text only objects that are direct descendants should behave as if they |
| 3755 // are part of their parent when computing hyperlink offsets. |
| 3756 const BrowserAccessibilityWin& nearest_non_text_endpoint = |
| 3757 endpoint_object.IsTextOnlyObject() |
| 3758 ? *(endpoint_object.GetParent()->ToBrowserAccessibilityWin()) |
| 3759 : endpoint_object; |
| 3760 |
| 3761 return GetHypertextOffsetFromDescendant(nearest_non_text_endpoint); |
| 3762 } |
| 3763 |
| 3764 // Case 3. |
| 3765 // |
| 3766 // We can safely assume that the endpoint is in another part of the tree or |
| 3767 // at common parent, and that this object is a descendant of common parent. |
| 3768 int32 endpoint_index_in_common_parent = 0; |
| 3769 for (size_t i = 0; i < common_parent->PlatformChildCount(); ++i) { |
| 3770 BrowserAccessibility* child = common_parent->PlatformGetChild(i); |
| 3771 DCHECK(child); |
| 3772 if (endpoint_object.IsDescendantOf(child)) { |
| 3773 endpoint_index_in_common_parent = child->GetIndexInParent(); |
| 3774 break; |
| 3775 } |
| 3776 } |
| 3777 DCHECK_GE(endpoint_index_in_common_parent, 0); |
| 3778 |
| 3779 if (endpoint_index_in_common_parent < index_in_common_parent) |
| 3780 return 0; |
| 3781 if (endpoint_index_in_common_parent > index_in_common_parent) |
| 3782 return TextForIAccessibleText().length(); |
| 3783 |
| 3784 NOTREACHED(); |
| 3785 return -1; |
| 3786 } |
| 3787 |
3693 int BrowserAccessibilityWin::GetSelectionAnchor() const { | 3788 int BrowserAccessibilityWin::GetSelectionAnchor() const { |
3694 BrowserAccessibility* root = manager()->GetRoot(); | 3789 BrowserAccessibility* root = manager()->GetRoot(); |
3695 int32 anchor_id; | 3790 int32 anchor_id; |
3696 if (!root || !root->GetIntAttribute(ui::AX_ATTR_ANCHOR_OBJECT_ID, &anchor_id)) | 3791 if (!root || !root->GetIntAttribute(ui::AX_ATTR_ANCHOR_OBJECT_ID, &anchor_id)) |
3697 return -1; | 3792 return -1; |
3698 | 3793 |
3699 BrowserAccessibilityWin* anchor_object = manager()->GetFromID( | 3794 BrowserAccessibilityWin* anchor_object = manager()->GetFromID( |
3700 anchor_id)->ToBrowserAccessibilityWin(); | 3795 anchor_id)->ToBrowserAccessibilityWin(); |
3701 if (!anchor_object) | 3796 if (!anchor_object) |
3702 return -1; | 3797 return -1; |
3703 | 3798 |
3704 // Includes the case when anchor_object == this. | 3799 int anchor_offset; |
3705 if (IsDescendantOf(anchor_object) || | 3800 if (!root->GetIntAttribute(ui::AX_ATTR_ANCHOR_OFFSET, &anchor_offset)) |
3706 // Text only objects that are direct descendants should behave as if they | 3801 return -1; |
3707 // are part of this object when computing hypertext. | |
3708 (anchor_object->GetParent() == this && | |
3709 anchor_object->IsTextOnlyObject())) { | |
3710 int anchor_offset; | |
3711 if (!root->GetIntAttribute(ui::AX_ATTR_ANCHOR_OFFSET, &anchor_offset)) | |
3712 return -1; | |
3713 | 3802 |
3714 return anchor_offset; | 3803 return GetHypertextOffsetFromEndpoint(*anchor_object, anchor_offset); |
3715 } | |
3716 | |
3717 if (anchor_object->IsDescendantOf(this)) | |
3718 return GetHypertextOffsetFromDescendant(*anchor_object); | |
3719 | |
3720 return -1; | |
3721 } | 3804 } |
3722 | 3805 |
3723 int BrowserAccessibilityWin::GetSelectionFocus() const { | 3806 int BrowserAccessibilityWin::GetSelectionFocus() const { |
3724 BrowserAccessibility* root = manager()->GetRoot(); | 3807 BrowserAccessibility* root = manager()->GetRoot(); |
3725 int32 focus_id; | 3808 int32 focus_id; |
3726 if (!root || !root->GetIntAttribute(ui::AX_ATTR_FOCUS_OBJECT_ID, &focus_id)) | 3809 if (!root || !root->GetIntAttribute(ui::AX_ATTR_FOCUS_OBJECT_ID, &focus_id)) |
3727 return -1; | 3810 return -1; |
3728 | 3811 |
3729 BrowserAccessibilityWin* focus_object = manager()->GetFromID( | 3812 BrowserAccessibilityWin* focus_object = manager()->GetFromID( |
3730 focus_id)->ToBrowserAccessibilityWin(); | 3813 focus_id)->ToBrowserAccessibilityWin(); |
3731 if (!focus_object) | 3814 if (!focus_object) |
3732 return -1; | 3815 return -1; |
3733 | 3816 |
3734 // Includes the case when focus_object == this. | 3817 int focus_offset; |
3735 if (IsDescendantOf(focus_object) || | 3818 if (!root->GetIntAttribute(ui::AX_ATTR_FOCUS_OFFSET, &focus_offset)) |
3736 // Text only objects that are direct descendants should behave as if they | 3819 return -1; |
3737 // are part of this object when computing hypertext. | |
3738 (focus_object->GetParent() == this && focus_object->IsTextOnlyObject())) { | |
3739 int focus_offset; | |
3740 if (!root->GetIntAttribute(ui::AX_ATTR_FOCUS_OFFSET, &focus_offset)) | |
3741 return -1; | |
3742 | 3820 |
3743 return focus_offset; | 3821 return GetHypertextOffsetFromEndpoint(*focus_object, focus_offset); |
3744 } | |
3745 | |
3746 if (focus_object->IsDescendantOf(this)) | |
3747 return GetHypertextOffsetFromDescendant(*focus_object); | |
3748 | |
3749 return -1; | |
3750 } | 3822 } |
3751 | 3823 |
3752 void BrowserAccessibilityWin::GetSelectionOffsets( | 3824 void BrowserAccessibilityWin::GetSelectionOffsets( |
3753 int* selection_start, int* selection_end) const { | 3825 int* selection_start, int* selection_end) const { |
3754 DCHECK(selection_start && selection_end); | 3826 DCHECK(selection_start && selection_end); |
3755 | 3827 |
3756 if (IsEditableText() && !HasState(ui::AX_STATE_RICHLY_EDITABLE) && | 3828 if (IsEditableText() && !HasState(ui::AX_STATE_RICHLY_EDITABLE) && |
3757 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, selection_start) && | 3829 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, selection_start) && |
3758 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, selection_end)) { | 3830 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, selection_end)) { |
3759 return; | 3831 return; |
3760 } | 3832 } |
3761 | 3833 |
3762 *selection_start = GetSelectionAnchor(); | 3834 *selection_start = GetSelectionAnchor(); |
3763 *selection_end = GetSelectionFocus(); | 3835 *selection_end = GetSelectionFocus(); |
3764 if (*selection_start < 0 || *selection_end < 0) | 3836 if (*selection_start < 0 || *selection_end < 0) |
3765 return; | 3837 return; |
3766 | 3838 |
3767 if (*selection_end < *selection_start) | 3839 // If the selection is collapsed or if it only spans one character, return the |
3768 std::swap(*selection_start, *selection_end); | 3840 // selection offsets only if the caret is active on this object or any of its |
| 3841 // children. |
| 3842 // The focus object indicates the caret position. |
| 3843 if (*selection_start == *selection_end) { |
| 3844 BrowserAccessibility* root = manager()->GetRoot(); |
| 3845 int32 focus_id; |
| 3846 if (!root || !root->GetIntAttribute(ui::AX_ATTR_FOCUS_OBJECT_ID, &focus_id)) |
| 3847 return; |
3769 | 3848 |
3770 // IA2 Spec says that the end of the selection should be after the last | 3849 BrowserAccessibilityWin* focus_object = |
3771 // embedded object character that is part of the selection, if there is one. | 3850 manager()->GetFromID(focus_id)->ToBrowserAccessibilityWin(); |
3772 if (hyperlink_offset_to_index().find(*selection_end) != | 3851 if (!focus_object) |
3773 hyperlink_offset_to_index().end()) { | 3852 return; |
3774 ++(*selection_end); | 3853 |
| 3854 if (!focus_object->IsDescendantOf(this) && |
| 3855 !(IsTextOnlyObject() && GetParent() == focus_object)) { |
| 3856 *selection_start = -1; |
| 3857 *selection_end = -1; |
| 3858 return; |
| 3859 } |
3775 } | 3860 } |
| 3861 |
| 3862 // The IA2 Spec says that if the largest of the two offsets falls on an |
| 3863 // embedded object character and if there is a selection in that embedded |
| 3864 // object, it should be incremented by one so that it points after the |
| 3865 // embedded object character. |
| 3866 // This is a signal to AT software that the embedded object is also part of |
| 3867 // the selection. |
| 3868 int* largest_offset = |
| 3869 (*selection_start <= *selection_end) ? selection_end : selection_start; |
| 3870 auto current_object = const_cast<BrowserAccessibilityWin*>(this); |
| 3871 LONG hyperlink_index; |
| 3872 HRESULT hr = |
| 3873 current_object->get_hyperlinkIndex(*largest_offset, &hyperlink_index); |
| 3874 if (hr != S_OK) |
| 3875 return; |
| 3876 |
| 3877 DCHECK_GE(hyperlink_index, 0); |
| 3878 base::win::ScopedComPtr<IAccessibleHyperlink> hyperlink; |
| 3879 hr = current_object->get_hyperlink(hyperlink_index, hyperlink.Receive()); |
| 3880 DCHECK(SUCCEEDED(hr)); |
| 3881 base::win::ScopedComPtr<IAccessibleText> hyperlink_text; |
| 3882 hr = hyperlink.QueryInterface(hyperlink_text.Receive()); |
| 3883 DCHECK(SUCCEEDED(hr)); |
| 3884 LONG n_selections = 0; |
| 3885 hr = hyperlink_text->get_nSelections(&n_selections); |
| 3886 DCHECK(SUCCEEDED(hr)); |
| 3887 if (n_selections > 0) |
| 3888 ++(*largest_offset); |
3776 } | 3889 } |
3777 | 3890 |
3778 base::string16 BrowserAccessibilityWin::GetNameRecursive() const { | 3891 base::string16 BrowserAccessibilityWin::GetNameRecursive() const { |
3779 if (!name().empty()) { | 3892 if (!name().empty()) { |
3780 return name(); | 3893 return name(); |
3781 } | 3894 } |
3782 | 3895 |
3783 base::string16 result; | 3896 base::string16 result; |
3784 for (uint32 i = 0; i < PlatformChildCount(); ++i) { | 3897 for (uint32 i = 0; i < PlatformChildCount(); ++i) { |
3785 result += PlatformGetChild(i)->ToBrowserAccessibilityWin()-> | 3898 result += PlatformGetChild(i)->ToBrowserAccessibilityWin()-> |
3786 GetNameRecursive(); | 3899 GetNameRecursive(); |
3787 } | 3900 } |
3788 return result; | 3901 return result; |
3789 } | 3902 } |
3790 | 3903 |
3791 base::string16 BrowserAccessibilityWin::GetValueText() { | 3904 base::string16 BrowserAccessibilityWin::GetValueText() { |
3792 float fval; | 3905 float fval; |
3793 base::string16 value = this->value(); | 3906 base::string16 value = this->value(); |
3794 | 3907 |
3795 if (value.empty() && | 3908 if (value.empty() && |
3796 GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) { | 3909 GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) { |
3797 value = base::UTF8ToUTF16(base::DoubleToString(fval)); | 3910 value = base::UTF8ToUTF16(base::DoubleToString(fval)); |
3798 } | 3911 } |
3799 return value; | 3912 return value; |
3800 } | 3913 } |
3801 | 3914 |
3802 base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { | 3915 base::string16 BrowserAccessibilityWin::TextForIAccessibleText() const { |
3803 switch (GetRole()) { | 3916 switch (GetRole()) { |
3804 case ui::AX_ROLE_TEXT_FIELD: | 3917 case ui::AX_ROLE_TEXT_FIELD: |
3805 case ui::AX_ROLE_MENU_LIST_OPTION: | 3918 case ui::AX_ROLE_MENU_LIST_OPTION: |
3806 return value(); | 3919 return value(); |
3807 default: | 3920 default: |
3808 return hypertext(); | 3921 return hypertext(); |
3809 } | 3922 } |
3810 } | 3923 } |
3811 | 3924 |
3812 bool BrowserAccessibilityWin::IsSameHypertextCharacter(size_t old_char_index, | 3925 bool BrowserAccessibilityWin::IsSameHypertextCharacter(size_t old_char_index, |
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4499 ia2_role = ia_role; | 4612 ia2_role = ia_role; |
4500 | 4613 |
4501 win_attributes_->ia_role = ia_role; | 4614 win_attributes_->ia_role = ia_role; |
4502 win_attributes_->ia_state = ia_state; | 4615 win_attributes_->ia_state = ia_state; |
4503 win_attributes_->role_name = role_name; | 4616 win_attributes_->role_name = role_name; |
4504 win_attributes_->ia2_role = ia2_role; | 4617 win_attributes_->ia2_role = ia2_role; |
4505 win_attributes_->ia2_state = ia2_state; | 4618 win_attributes_->ia2_state = ia2_state; |
4506 } | 4619 } |
4507 | 4620 |
4508 } // namespace content | 4621 } // namespace content |
OLD | NEW |