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