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 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 // | 692 // |
693 | 693 |
694 STDMETHODIMP BrowserAccessibilityWin::role(LONG* role) { | 694 STDMETHODIMP BrowserAccessibilityWin::role(LONG* role) { |
695 if (!instance_active()) | 695 if (!instance_active()) |
696 return E_FAIL; | 696 return E_FAIL; |
697 | 697 |
698 if (!role) | 698 if (!role) |
699 return E_INVALIDARG; | 699 return E_INVALIDARG; |
700 | 700 |
701 *role = ia2_role(); | 701 *role = ia2_role(); |
702 | |
703 return S_OK; | 702 return S_OK; |
704 } | 703 } |
705 | 704 |
706 STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) { | 705 STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) { |
707 if (!attributes) | 706 if (!attributes) |
708 return E_INVALIDARG; | 707 return E_INVALIDARG; |
709 *attributes = nullptr; | 708 *attributes = nullptr; |
710 | 709 |
711 if (!instance_active()) | 710 if (!instance_active()) |
712 return E_FAIL; | 711 return E_FAIL; |
(...skipping 2606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3319 | 3318 |
3320 return CComObjectRootBase::InternalQueryInterface( | 3319 return CComObjectRootBase::InternalQueryInterface( |
3321 this_ptr, entries, iid, object); | 3320 this_ptr, entries, iid, object); |
3322 } | 3321 } |
3323 | 3322 |
3324 void BrowserAccessibilityWin::ComputeStylesIfNeeded() { | 3323 void BrowserAccessibilityWin::ComputeStylesIfNeeded() { |
3325 if (!offset_to_text_attributes().empty()) | 3324 if (!offset_to_text_attributes().empty()) |
3326 return; | 3325 return; |
3327 | 3326 |
3328 std::map<int, std::vector<base::string16>> attributes_map; | 3327 std::map<int, std::vector<base::string16>> attributes_map; |
3329 if (PlatformIsLeaf()) { | 3328 if (PlatformIsLeaf() || IsSimpleTextControl()) { |
3330 attributes_map[0] = ComputeTextAttributes(); | 3329 attributes_map[0] = ComputeTextAttributes(); |
3331 std::map<int, std::vector<base::string16>> spelling_attributes = | 3330 std::map<int, std::vector<base::string16>> spelling_attributes = |
3332 GetSpellingAttributes(); | 3331 GetSpellingAttributes(); |
3333 for (auto& spelling_attribute : spelling_attributes) { | 3332 for (auto& spelling_attribute : spelling_attributes) { |
3334 auto attributes_iterator = attributes_map.find(spelling_attribute.first); | 3333 auto attributes_iterator = attributes_map.find(spelling_attribute.first); |
3335 if (attributes_iterator == attributes_map.end()) { | 3334 if (attributes_iterator == attributes_map.end()) { |
3336 attributes_map[spelling_attribute.first] = | 3335 attributes_map[spelling_attribute.first] = |
3337 std::move(spelling_attribute.second); | 3336 std::move(spelling_attribute.second); |
3338 } else { | 3337 } else { |
3339 std::vector<base::string16>& existing_attributes = | 3338 std::vector<base::string16>& existing_attributes = |
3340 attributes_iterator->second; | 3339 attributes_iterator->second; |
| 3340 |
| 3341 // There might be a spelling attribute already in the list of text |
| 3342 // attributes, originating from "aria-invalid". |
3341 auto existing_spelling_attribute = | 3343 auto existing_spelling_attribute = |
3342 std::find(existing_attributes.begin(), existing_attributes.end(), | 3344 std::find(existing_attributes.begin(), existing_attributes.end(), |
3343 L"invalid:false"); | 3345 L"invalid:false"); |
3344 if (existing_spelling_attribute != existing_attributes.end()) | 3346 if (existing_spelling_attribute != existing_attributes.end()) |
3345 existing_attributes.erase(existing_spelling_attribute); | 3347 existing_attributes.erase(existing_spelling_attribute); |
| 3348 |
3346 existing_attributes.insert(existing_attributes.end(), | 3349 existing_attributes.insert(existing_attributes.end(), |
3347 spelling_attribute.second.begin(), | 3350 spelling_attribute.second.begin(), |
3348 spelling_attribute.second.end()); | 3351 spelling_attribute.second.end()); |
3349 } | 3352 } |
3350 } | 3353 } |
3351 win_attributes_->offset_to_text_attributes.swap(attributes_map); | 3354 win_attributes_->offset_to_text_attributes.swap(attributes_map); |
3352 return; | 3355 return; |
3353 } | 3356 } |
3354 | 3357 |
3355 int start_offset = 0; | 3358 int start_offset = 0; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3552 // If this is a web area for a presentational iframe, give it a role of | 3555 // If this is a web area for a presentational iframe, give it a role of |
3553 // something other than DOCUMENT so that the fact that it's a separate doc | 3556 // something other than DOCUMENT so that the fact that it's a separate doc |
3554 // is not exposed to AT. | 3557 // is not exposed to AT. |
3555 if (IsWebAreaForPresentationalIframe()) { | 3558 if (IsWebAreaForPresentationalIframe()) { |
3556 win_attributes_->ia_role = ROLE_SYSTEM_GROUPING; | 3559 win_attributes_->ia_role = ROLE_SYSTEM_GROUPING; |
3557 win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING; | 3560 win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING; |
3558 } | 3561 } |
3559 } | 3562 } |
3560 | 3563 |
3561 void BrowserAccessibilityWin::UpdateStep2ComputeHypertext() { | 3564 void BrowserAccessibilityWin::UpdateStep2ComputeHypertext() { |
3562 if (!PlatformChildCount()) { | 3565 if (IsSimpleTextControl()) { |
3563 if (IsSimpleTextControl()) { | 3566 win_attributes_->hypertext = value(); |
3564 win_attributes_->hypertext = value(); | |
3565 } else if (IsRichTextControl()) { | |
3566 // We don't want to expose any associated label in IA2 Hypertext. | |
3567 return; | |
3568 } else { | |
3569 win_attributes_->hypertext = name(); | |
3570 } | |
3571 | |
3572 return; | 3567 return; |
3573 } | 3568 } |
3574 | 3569 |
| 3570 if (!PlatformChildCount()) { |
| 3571 if (IsRichTextControl()) { |
| 3572 // We don't want to expose any associated label in IA2 Hypertext. |
| 3573 return; |
| 3574 } |
| 3575 win_attributes_->hypertext = name(); |
| 3576 return; |
| 3577 } |
| 3578 |
3575 // Construct the hypertext for this node, which contains the concatenation | 3579 // Construct the hypertext for this node, which contains the concatenation |
3576 // of all of the static text and widespace of this node's children and an | 3580 // of all of the static text and widespace of this node's children and an |
3577 // embedded object character for all the other children. Build up a map from | 3581 // embedded object character for all the other children. Build up a map from |
3578 // the character index of each embedded object character to the id of the | 3582 // the character index of each embedded object character to the id of the |
3579 // child object it points to. | 3583 // child object it points to. |
3580 for (unsigned int i = 0; i < PlatformChildCount(); ++i) { | 3584 for (unsigned int i = 0; i < PlatformChildCount(); ++i) { |
3581 const auto child = ToBrowserAccessibilityWin(PlatformGetChild(i)); | 3585 const auto child = ToBrowserAccessibilityWin(PlatformGetChild(i)); |
3582 DCHECK(child); | 3586 DCHECK(child); |
3583 // Similar to Firefox, we don't expose text-only objects in IA2 hypertext. | 3587 // Similar to Firefox, we don't expose text-only objects in IA2 hypertext. |
3584 if (child->IsTextOnlyObject()) { | 3588 if (child->IsTextOnlyObject()) { |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3882 } | 3886 } |
3883 | 3887 |
3884 BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() { | 3888 BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() { |
3885 AddRef(); | 3889 AddRef(); |
3886 return this; | 3890 return this; |
3887 } | 3891 } |
3888 | 3892 |
3889 std::map<int, std::vector<base::string16>> | 3893 std::map<int, std::vector<base::string16>> |
3890 BrowserAccessibilityWin::GetSpellingAttributes() const { | 3894 BrowserAccessibilityWin::GetSpellingAttributes() const { |
3891 std::map<int, std::vector<base::string16>> spelling_attributes; | 3895 std::map<int, std::vector<base::string16>> spelling_attributes; |
3892 | |
3893 // It doesn't make sense to expose spelling error information on anything | |
3894 // other than a leaf object, because non-leaf objects do not expose text | |
3895 // directly. | |
3896 if (!PlatformIsLeaf()) | |
3897 return spelling_attributes; | |
3898 | |
3899 if (IsTextOnlyObject()) { | 3896 if (IsTextOnlyObject()) { |
3900 const std::vector<int32_t>& marker_types = | 3897 const std::vector<int32_t>& marker_types = |
3901 GetIntListAttribute(ui::AX_ATTR_MARKER_TYPES); | 3898 GetIntListAttribute(ui::AX_ATTR_MARKER_TYPES); |
3902 const std::vector<int>& marker_starts = | 3899 const std::vector<int>& marker_starts = |
3903 GetIntListAttribute(ui::AX_ATTR_MARKER_STARTS); | 3900 GetIntListAttribute(ui::AX_ATTR_MARKER_STARTS); |
3904 const std::vector<int>& marker_ends = | 3901 const std::vector<int>& marker_ends = |
3905 GetIntListAttribute(ui::AX_ATTR_MARKER_ENDS); | 3902 GetIntListAttribute(ui::AX_ATTR_MARKER_ENDS); |
3906 for (size_t i = 0; i < marker_types.size(); ++i) { | 3903 for (size_t i = 0; i < marker_types.size(); ++i) { |
3907 if (!(static_cast<ui::AXMarkerType>(marker_types[i]) & | 3904 if (!(static_cast<ui::AXMarkerType>(marker_types[i]) & |
3908 ui::AX_MARKER_TYPE_SPELLING)) | 3905 ui::AX_MARKER_TYPE_SPELLING)) |
3909 continue; | 3906 continue; |
3910 int start_offset = marker_starts[i]; | 3907 int start_offset = marker_starts[i]; |
3911 int end_offset = marker_ends[i]; | 3908 int end_offset = marker_ends[i]; |
3912 std::vector<base::string16> start_attributes; | 3909 std::vector<base::string16> start_attributes; |
3913 start_attributes.push_back(L"invalid:spelling"); | 3910 start_attributes.push_back(L"invalid:spelling"); |
3914 std::vector<base::string16> end_attributes; | 3911 std::vector<base::string16> end_attributes; |
3915 end_attributes.push_back(L"invalid:false"); | 3912 end_attributes.push_back(L"invalid:false"); |
3916 spelling_attributes[start_offset] = start_attributes; | 3913 spelling_attributes[start_offset] = start_attributes; |
3917 spelling_attributes[end_offset] = end_attributes; | 3914 spelling_attributes[end_offset] = end_attributes; |
3918 } | 3915 } |
3919 } | 3916 } |
3920 | |
3921 if (IsSimpleTextControl()) { | 3917 if (IsSimpleTextControl()) { |
3922 int start_offset = 0; | 3918 int start_offset = 0; |
3923 for (const BrowserAccessibility* static_text = | 3919 for (const BrowserAccessibility* static_text = |
3924 BrowserAccessibilityManager::NextTextOnlyObject( | 3920 BrowserAccessibilityManager::NextTextOnlyObject( |
3925 InternalGetChild(0)); | 3921 InternalGetChild(0)); |
3926 static_text; static_text = static_text->GetNextSibling()) { | 3922 static_text; static_text = static_text->GetNextSibling()) { |
3927 auto text_win = ToBrowserAccessibilityWin(static_text); | 3923 auto text_win = ToBrowserAccessibilityWin(static_text); |
3928 if (text_win) { | 3924 if (text_win) { |
3929 std::map<int, std::vector<base::string16>> text_spelling_attributes = | 3925 std::map<int, std::vector<base::string16>> text_spelling_attributes = |
3930 text_win->GetSpellingAttributes(); | 3926 text_win->GetSpellingAttributes(); |
3931 for (auto& attribute : text_spelling_attributes) { | 3927 for (auto& attribute : text_spelling_attributes) { |
3932 spelling_attributes[start_offset + attribute.first] = | 3928 spelling_attributes[start_offset + attribute.first] = |
3933 std::move(attribute.second); | 3929 std::move(attribute.second); |
3934 } | 3930 } |
3935 start_offset += static_cast<int>(text_win->GetText().length()); | 3931 start_offset += static_cast<int>(text_win->GetText().length()); |
3936 } | 3932 } |
3937 } | 3933 } |
3938 } | 3934 } |
3939 | |
3940 return spelling_attributes; | 3935 return spelling_attributes; |
3941 } | 3936 } |
3942 | 3937 |
3943 BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID( | 3938 BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID( |
3944 const VARIANT& var_id) { | 3939 const VARIANT& var_id) { |
3945 if (var_id.vt != VT_I4) | 3940 if (var_id.vt != VT_I4) |
3946 return nullptr; | 3941 return nullptr; |
3947 | 3942 |
3948 LONG child_id = var_id.lVal; | 3943 LONG child_id = var_id.lVal; |
3949 if (child_id == CHILDID_SELF) | 3944 if (child_id == CHILDID_SELF) |
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5204 return static_cast<BrowserAccessibilityWin*>(obj); | 5199 return static_cast<BrowserAccessibilityWin*>(obj); |
5205 } | 5200 } |
5206 | 5201 |
5207 const BrowserAccessibilityWin* | 5202 const BrowserAccessibilityWin* |
5208 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) { | 5203 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) { |
5209 DCHECK(!obj || obj->IsNative()); | 5204 DCHECK(!obj || obj->IsNative()); |
5210 return static_cast<const BrowserAccessibilityWin*>(obj); | 5205 return static_cast<const BrowserAccessibilityWin*>(obj); |
5211 } | 5206 } |
5212 | 5207 |
5213 } // namespace content | 5208 } // namespace content |
OLD | NEW |