| 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 |