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 #import "content/browser/accessibility/browser_accessibility_cocoa.h" | 5 #import "content/browser/accessibility/browser_accessibility_cocoa.h" |
| 6 | 6 |
| 7 #include <execinfo.h> | 7 #include <execinfo.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 #include "content/app/strings/grit/content_strings.h" | 21 #include "content/app/strings/grit/content_strings.h" |
| 22 #include "content/browser/accessibility/ax_platform_position.h" | 22 #include "content/browser/accessibility/ax_platform_position.h" |
| 23 #include "content/browser/accessibility/browser_accessibility_mac.h" | 23 #include "content/browser/accessibility/browser_accessibility_mac.h" |
| 24 #include "content/browser/accessibility/browser_accessibility_manager.h" | 24 #include "content/browser/accessibility/browser_accessibility_manager.h" |
| 25 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" | 25 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" |
| 26 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h" | 26 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h" |
| 27 #include "content/public/common/content_client.h" | 27 #include "content/public/common/content_client.h" |
| 28 #include "third_party/skia/include/core/SkColor.h" | 28 #include "third_party/skia/include/core/SkColor.h" |
| 29 #include "ui/accessibility/ax_range.h" | 29 #include "ui/accessibility/ax_range.h" |
| 30 #import "ui/accessibility/platform/ax_platform_node_mac.h" | 30 #import "ui/accessibility/platform/ax_platform_node_mac.h" |
| 31 #import "ui/accessibility/platform/text_marker_helper_mac.h" | |
| 31 | 32 |
| 32 using AXAbstractPositionInstance = | |
| 33 content::AXPlatformPosition::AXPositionInstance; | |
| 34 using AXPlatformPositionInstance = | 33 using AXPlatformPositionInstance = |
| 35 content::AXPlatformPosition::ConcreteInstance; | 34 content::AXPlatformPosition::ConcreteInstance; |
| 36 using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>; | 35 using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>; |
| 37 using AXTextMarkerRangeRef = CFTypeRef; | |
| 38 using AXTextMarkerRef = CFTypeRef; | |
| 39 using StringAttribute = ui::AXStringAttribute; | 36 using StringAttribute = ui::AXStringAttribute; |
| 40 using content::AXPlatformPosition; | 37 using content::AXPlatformPosition; |
| 41 using content::AccessibilityMatchPredicate; | 38 using content::AccessibilityMatchPredicate; |
| 42 using content::BrowserAccessibility; | 39 using content::BrowserAccessibility; |
| 43 using content::BrowserAccessibilityDelegate; | 40 using content::BrowserAccessibilityDelegate; |
| 44 using content::BrowserAccessibilityManager; | 41 using content::BrowserAccessibilityManager; |
| 45 using content::BrowserAccessibilityManagerMac; | 42 using content::BrowserAccessibilityManagerMac; |
| 46 using content::ContentClient; | 43 using content::ContentClient; |
| 47 using content::OneShotAccessibilityTreeSearch; | 44 using content::OneShotAccessibilityTreeSearch; |
| 48 using ui::AXNodeData; | 45 using ui::AXNodeData; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 | 103 |
| 107 // Actions. | 104 // Actions. |
| 108 NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible"; | 105 NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible"; |
| 109 | 106 |
| 110 // A mapping from an accessibility attribute to its method name. | 107 // A mapping from an accessibility attribute to its method name. |
| 111 NSDictionary* attributeToMethodNameMap = nil; | 108 NSDictionary* attributeToMethodNameMap = nil; |
| 112 | 109 |
| 113 // VoiceOver uses -1 to mean "no limit" for AXResultsLimit. | 110 // VoiceOver uses -1 to mean "no limit" for AXResultsLimit. |
| 114 const int kAXResultsLimitNoLimit = -1; | 111 const int kAXResultsLimitNoLimit = -1; |
| 115 | 112 |
| 116 extern "C" { | |
| 117 | |
| 118 // The following are private accessibility APIs required for cursor navigation | |
| 119 // and text selection. VoiceOver started relying on them in Mac OS X 10.11. | |
| 120 #if !defined(MAC_OS_X_VERSION_10_11) || \ | |
| 121 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 | |
| 122 | |
| 123 AXTextMarkerRef AXTextMarkerCreate(CFAllocatorRef allocator, | |
| 124 const UInt8* bytes, | |
| 125 CFIndex length); | |
| 126 | |
| 127 const UInt8* AXTextMarkerGetBytePtr(AXTextMarkerRef text_marker); | |
| 128 | |
| 129 size_t AXTextMarkerGetLength(AXTextMarkerRef text_marker); | |
| 130 | |
| 131 AXTextMarkerRangeRef AXTextMarkerRangeCreate(CFAllocatorRef allocator, | |
| 132 AXTextMarkerRef start_marker, | |
| 133 AXTextMarkerRef end_marker); | |
| 134 | |
| 135 AXTextMarkerRef AXTextMarkerRangeCopyStartMarker( | |
| 136 AXTextMarkerRangeRef text_marker_range); | |
| 137 | |
| 138 AXTextMarkerRef AXTextMarkerRangeCopyEndMarker( | |
| 139 AXTextMarkerRangeRef text_marker_range); | |
| 140 | |
| 141 #endif // MAC_OS_X_VERSION_10_11 | |
| 142 | |
| 143 } // extern "C" | |
| 144 | |
| 145 static_assert(sizeof(AXPlatformPosition) == sizeof(ui::AXPositionBase), | 113 static_assert(sizeof(AXPlatformPosition) == sizeof(ui::AXPositionBase), |
| 146 "AXPosition size mismatch"); | 114 "AXPosition size mismatch"); |
| 147 constexpr size_t kAXPositionSize = sizeof(ui::AXPositionBase); | 115 constexpr size_t kAXPositionSize = sizeof(ui::AXPositionBase); |
| 148 | 116 |
| 149 // to call |release| on it to transfer ownership of the position to the text | 117 class BrowserPositionFactory : public ui::PositionFactory { |
| 150 // marker object. | 118 public: |
| 151 id CreateTextMarker(AXAbstractPositionInstance position) { | 119 explicit BrowserPositionFactory( |
| 152 AXTextMarkerRef text_marker = AXTextMarkerCreate( | 120 content::BrowserAccessibility* browser_accessibility) |
| 153 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(position.release()), | 121 : browser_accessibility_(browser_accessibility) {} |
| 154 kAXPositionSize); | |
| 155 return static_cast<id>( | |
| 156 base::mac::CFTypeRefToNSObjectAutorelease(text_marker)); | |
| 157 } | |
| 158 | 122 |
| 159 // |range| is destructed at the end of this method and ownership of its |anchor| | 123 std::unique_ptr<ui::AXPositionBase> GetRoot() const override; |
| 160 // and |focus| are transfered to the marker range object. | 124 std::unique_ptr<ui::AXAbstractRange> GetSelection() const override; |
| 161 id CreateTextMarkerRange(const ui::AXAbstractRange range) { | 125 std::unique_ptr<ui::AXPositionBase> ExtractFromMarker( |
| 162 AXTextMarkerRef start_marker = AXTextMarkerCreate( | 126 AXTextMarkerRef marker) const override; |
| 163 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.anchor()), | 127 |
| 164 kAXPositionSize); | 128 private: |
| 165 AXTextMarkerRef end_marker = AXTextMarkerCreate( | 129 bool IsActive() const { |
| 166 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.focus()), | 130 return browser_accessibility_ && browser_accessibility_->instance_active(); |
| 167 kAXPositionSize); | 131 } |
| 168 AXTextMarkerRangeRef marker_range = | 132 |
| 169 AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker); | 133 content::BrowserAccessibility* browser_accessibility_; |
| 170 return static_cast<id>( | 134 |
| 171 base::mac::CFTypeRefToNSObjectAutorelease(marker_range)); | 135 DISALLOW_COPY_AND_ASSIGN(BrowserPositionFactory); |
| 172 } | 136 }; |
| 173 | 137 |
| 174 AXPlatformPositionInstance CreateConcretePositionFromTextMarker( | 138 AXPlatformPositionInstance CreateConcretePositionFromTextMarker( |
| 175 AXTextMarkerRef text_marker) { | 139 AXTextMarkerRef text_marker) { |
| 176 DCHECK(text_marker); | 140 DCHECK(text_marker); |
| 177 if (AXTextMarkerGetLength(text_marker) != kAXPositionSize) | 141 if (AXTextMarkerGetLength(text_marker) != kAXPositionSize) |
| 178 return AXPlatformPosition::CreateConcreteNullPosition(); | 142 return AXPlatformPosition::CreateConcreteNullPosition(); |
| 179 const UInt8* source_buffer = AXTextMarkerGetBytePtr(text_marker); | 143 const UInt8* source_buffer = AXTextMarkerGetBytePtr(text_marker); |
| 180 if (!source_buffer) | 144 if (!source_buffer) |
| 181 return AXPlatformPosition::CreateConcreteNullPosition(); | 145 return AXPlatformPosition::CreateConcreteNullPosition(); |
| 182 UInt8* destination_buffer = new UInt8[kAXPositionSize]; | 146 UInt8* destination_buffer = new UInt8[kAXPositionSize]; |
| 183 std::memcpy(destination_buffer, source_buffer, kAXPositionSize); | 147 std::memcpy(destination_buffer, source_buffer, kAXPositionSize); |
| 184 AXPlatformPositionInstance position( | 148 AXPlatformPositionInstance position( |
| 185 reinterpret_cast<AXPlatformPositionInstance::pointer>( | 149 reinterpret_cast<AXPlatformPositionInstance::pointer>( |
| 186 destination_buffer)); | 150 destination_buffer)); |
| 187 if (!position) | 151 if (!position) |
| 188 return AXPlatformPosition::CreateConcreteNullPosition(); | 152 return AXPlatformPosition::CreateConcreteNullPosition(); |
| 189 return position; | 153 return position; |
| 190 } | 154 } |
| 191 | 155 |
| 192 AXAbstractPositionInstance CreatePositionFromTextMarker( | |
| 193 AXTextMarkerRef text_marker) { | |
| 194 return base::WrapUnique( | |
| 195 CreateConcretePositionFromTextMarker(text_marker).release()); | |
| 196 } | |
| 197 | |
| 198 AXPlatformRange CreateRangeFromTextMarkerRange( | 156 AXPlatformRange CreateRangeFromTextMarkerRange( |
| 199 AXTextMarkerRangeRef marker_range) { | 157 AXTextMarkerRangeRef marker_range) { |
| 200 DCHECK(marker_range); | 158 DCHECK(marker_range); |
| 201 base::ScopedCFTypeRef<AXTextMarkerRef> start_marker( | 159 base::ScopedCFTypeRef<AXTextMarkerRef> start_marker( |
| 202 AXTextMarkerRangeCopyStartMarker(marker_range)); | 160 AXTextMarkerRangeCopyStartMarker(marker_range)); |
| 203 base::ScopedCFTypeRef<AXTextMarkerRef> end_marker( | 161 base::ScopedCFTypeRef<AXTextMarkerRef> end_marker( |
| 204 AXTextMarkerRangeCopyEndMarker(marker_range)); | 162 AXTextMarkerRangeCopyEndMarker(marker_range)); |
| 205 if (!start_marker.get() || !end_marker.get()) | 163 if (!start_marker.get() || !end_marker.get()) |
| 206 return AXPlatformRange(); | 164 return AXPlatformRange(); |
| 207 | 165 |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 } // namespace | 487 } // namespace |
| 530 | 488 |
| 531 // The following private WebKit accessibility attribute became public in 10.12. | 489 // The following private WebKit accessibility attribute became public in 10.12. |
| 532 #if !defined(MAC_OS_X_VERSION_10_12) || \ | 490 #if !defined(MAC_OS_X_VERSION_10_12) || \ |
| 533 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 | 491 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 |
| 534 extern "C" { | 492 extern "C" { |
| 535 NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; | 493 NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
| 536 } | 494 } |
| 537 #endif // MAC_OS_X_VERSION_10_12 | 495 #endif // MAC_OS_X_VERSION_10_12 |
| 538 | 496 |
| 539 @implementation BrowserAccessibilityCocoa | 497 @interface BrowserAccessibilityCocoa () |
| 498 | |
| 499 // Lazily creates a TextMarkerHelper and returns it. | |
| 500 - (TextMarkerHelperMac*)textMarkerHelper; | |
| 501 | |
| 502 @end | |
| 503 | |
| 504 @implementation BrowserAccessibilityCocoa { | |
| 505 base::scoped_nsobject<TextMarkerHelperMac> textMarkerHelper_; | |
| 506 } | |
| 540 | 507 |
| 541 + (void)initialize { | 508 + (void)initialize { |
| 542 const struct { | 509 const struct { |
| 543 NSString* attribute; | 510 NSString* attribute; |
| 544 NSString* methodName; | 511 NSString* methodName; |
| 545 } attributeToMethodNameContainer[] = { | 512 } attributeToMethodNameContainer[] = { |
| 546 {NSAccessibilityARIAAtomicAttribute, @"ariaAtomic"}, | 513 {NSAccessibilityARIAAtomicAttribute, @"ariaAtomic"}, |
| 547 {NSAccessibilityARIABusyAttribute, @"ariaBusy"}, | 514 {NSAccessibilityARIABusyAttribute, @"ariaBusy"}, |
| 548 {NSAccessibilityARIAColumnCountAttribute, @"ariaColumnCount"}, | 515 {NSAccessibilityARIAColumnCountAttribute, @"ariaColumnCount"}, |
| 549 {NSAccessibilityARIAColumnIndexAttribute, @"ariaColumnIndex"}, | 516 {NSAccessibilityARIAColumnIndexAttribute, @"ariaColumnIndex"}, |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 972 return nil; | 939 return nil; |
| 973 } | 940 } |
| 974 | 941 |
| 975 - (NSNumber*)enabled { | 942 - (NSNumber*)enabled { |
| 976 if (![self instanceActive]) | 943 if (![self instanceActive]) |
| 977 return nil; | 944 return nil; |
| 978 return [NSNumber numberWithBool: | 945 return [NSNumber numberWithBool: |
| 979 !GetState(browserAccessibility_, ui::AX_STATE_DISABLED)]; | 946 !GetState(browserAccessibility_, ui::AX_STATE_DISABLED)]; |
| 980 } | 947 } |
| 981 | 948 |
| 982 // Returns a text marker that points to the last character in the document that | |
| 983 // can be selected with VoiceOver. | |
| 984 - (id)endTextMarker { | 949 - (id)endTextMarker { |
| 985 const BrowserAccessibility* root = | 950 return [[self textMarkerHelper] endTextMarker]; |
| 986 browserAccessibility_->manager()->GetRoot(); | 951 } |
| 987 if (!root) | |
| 988 return nil; | |
| 989 | 952 |
| 990 AXAbstractPositionInstance position = root->CreatePositionAt(0); | 953 - (id)startTextMarker { |
|
tapted
2017/06/19 11:44:30
(self review: swap order with endTextMarker)
| |
| 991 return CreateTextMarker(position->CreatePositionAtEndOfAnchor()); | 954 return [[self textMarkerHelper] startTextMarker]; |
| 992 } | 955 } |
| 993 | 956 |
| 994 - (NSNumber*)expanded { | 957 - (NSNumber*)expanded { |
| 995 if (![self instanceActive]) | 958 if (![self instanceActive]) |
| 996 return nil; | 959 return nil; |
| 997 return [NSNumber numberWithBool: | 960 return [NSNumber numberWithBool: |
| 998 GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)]; | 961 GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)]; |
| 999 } | 962 } |
| 1000 | 963 |
| 1001 - (NSNumber*)focused { | 964 - (NSNumber*)focused { |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1675 } | 1638 } |
| 1676 | 1639 |
| 1677 if (selStart > selEnd) | 1640 if (selStart > selEnd) |
| 1678 std::swap(selStart, selEnd); | 1641 std::swap(selStart, selEnd); |
| 1679 | 1642 |
| 1680 int selLength = selEnd - selStart; | 1643 int selLength = selEnd - selStart; |
| 1681 return [NSValue valueWithRange:NSMakeRange(selStart, selLength)]; | 1644 return [NSValue valueWithRange:NSMakeRange(selStart, selLength)]; |
| 1682 } | 1645 } |
| 1683 | 1646 |
| 1684 - (id)selectedTextMarkerRange { | 1647 - (id)selectedTextMarkerRange { |
| 1685 if (![self instanceActive]) | 1648 return [[self textMarkerHelper] selectedTextMarkerRange]; |
| 1686 return nil; | |
| 1687 | |
| 1688 BrowserAccessibilityManager* manager = browserAccessibility_->manager(); | |
| 1689 if (!manager) | |
| 1690 return nil; | |
| 1691 | |
| 1692 int32_t anchorId = manager->GetTreeData().sel_anchor_object_id; | |
| 1693 const BrowserAccessibility* anchorObject = manager->GetFromID(anchorId); | |
| 1694 if (!anchorObject) | |
| 1695 return nil; | |
| 1696 | |
| 1697 int32_t focusId = manager->GetTreeData().sel_focus_object_id; | |
| 1698 const BrowserAccessibility* focusObject = manager->GetFromID(focusId); | |
| 1699 if (!focusObject) | |
| 1700 return nil; | |
| 1701 | |
| 1702 int anchorOffset = manager->GetTreeData().sel_anchor_offset; | |
| 1703 int focusOffset = manager->GetTreeData().sel_focus_offset; | |
| 1704 if (anchorOffset < 0 || focusOffset < 0) | |
| 1705 return nil; | |
| 1706 | |
| 1707 ui::AXTextAffinity anchorAffinity = | |
| 1708 manager->GetTreeData().sel_anchor_affinity; | |
| 1709 ui::AXTextAffinity focusAffinity = manager->GetTreeData().sel_focus_affinity; | |
| 1710 | |
| 1711 return CreateTextMarkerRange(CreateTextRange(*anchorObject, anchorOffset, | |
| 1712 anchorAffinity, *focusObject, | |
| 1713 focusOffset, focusAffinity)); | |
| 1714 } | 1649 } |
| 1715 | 1650 |
| 1716 - (NSValue*)size { | 1651 - (NSValue*)size { |
| 1717 if (![self instanceActive]) | 1652 if (![self instanceActive]) |
| 1718 return nil; | 1653 return nil; |
| 1719 gfx::Rect bounds = browserAccessibility_->GetPageBoundsRect(); | 1654 gfx::Rect bounds = browserAccessibility_->GetPageBoundsRect(); |
| 1720 return [NSValue valueWithSize:NSMakeSize(bounds.width(), bounds.height())]; | 1655 return [NSValue valueWithSize:NSMakeSize(bounds.width(), bounds.height())]; |
| 1721 } | 1656 } |
| 1722 | 1657 |
| 1723 - (NSString*)sortDirection { | 1658 - (NSString*)sortDirection { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1737 return NSAccessibilityDescendingSortDirectionValue; | 1672 return NSAccessibilityDescendingSortDirectionValue; |
| 1738 case ui::AX_SORT_DIRECTION_OTHER: | 1673 case ui::AX_SORT_DIRECTION_OTHER: |
| 1739 return NSAccessibilityUnknownSortDirectionValue; | 1674 return NSAccessibilityUnknownSortDirectionValue; |
| 1740 default: | 1675 default: |
| 1741 NOTREACHED(); | 1676 NOTREACHED(); |
| 1742 } | 1677 } |
| 1743 | 1678 |
| 1744 return nil; | 1679 return nil; |
| 1745 } | 1680 } |
| 1746 | 1681 |
| 1747 // Returns a text marker that points to the first character in the document that | |
| 1748 // can be selected with VoiceOver. | |
| 1749 - (id)startTextMarker { | |
| 1750 const BrowserAccessibility* root = | |
| 1751 browserAccessibility_->manager()->GetRoot(); | |
| 1752 if (!root) | |
| 1753 return nil; | |
| 1754 | |
| 1755 AXAbstractPositionInstance position = root->CreatePositionAt(0); | |
| 1756 return CreateTextMarker(position->CreatePositionAtStartOfAnchor()); | |
| 1757 } | |
| 1758 | |
| 1759 // Returns a subrole based upon the role. | 1682 // Returns a subrole based upon the role. |
| 1760 - (NSString*) subrole { | 1683 - (NSString*) subrole { |
| 1761 if (![self instanceActive]) | 1684 if (![self instanceActive]) |
| 1762 return nil; | 1685 return nil; |
| 1763 ui::AXRole browserAccessibilityRole = [self internalRole]; | 1686 ui::AXRole browserAccessibilityRole = [self internalRole]; |
| 1764 if (browserAccessibilityRole == ui::AX_ROLE_TEXT_FIELD && | 1687 if (browserAccessibilityRole == ui::AX_ROLE_TEXT_FIELD && |
| 1765 GetState(browserAccessibility_, ui::AX_STATE_PROTECTED)) { | 1688 GetState(browserAccessibility_, ui::AX_STATE_PROTECTED)) { |
| 1766 return NSAccessibilitySecureTextFieldSubrole; | 1689 return NSAccessibilitySecureTextFieldSubrole; |
| 1767 } | 1690 } |
| 1768 | 1691 |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2019 NSString* value = base::SysUTF16ToNSString(browserAccessibility_->GetValue()); | 1942 NSString* value = base::SysUTF16ToNSString(browserAccessibility_->GetValue()); |
| 2020 NSMutableAttributedString* attributedValue = | 1943 NSMutableAttributedString* attributedValue = |
| 2021 [[[NSMutableAttributedString alloc] initWithString:value] autorelease]; | 1944 [[[NSMutableAttributedString alloc] initWithString:value] autorelease]; |
| 2022 std::vector<const BrowserAccessibility*> textOnlyObjects = | 1945 std::vector<const BrowserAccessibility*> textOnlyObjects = |
| 2023 BrowserAccessibilityManager::FindTextOnlyObjectsInRange( | 1946 BrowserAccessibilityManager::FindTextOnlyObjectsInRange( |
| 2024 *browserAccessibility_, *browserAccessibility_); | 1947 *browserAccessibility_, *browserAccessibility_); |
| 2025 AddMisspelledTextAttributes(textOnlyObjects, attributedValue); | 1948 AddMisspelledTextAttributes(textOnlyObjects, attributedValue); |
| 2026 return [attributedValue attributedSubstringFromRange:range]; | 1949 return [attributedValue attributedSubstringFromRange:range]; |
| 2027 } | 1950 } |
| 2028 | 1951 |
| 1952 - (TextMarkerHelperMac*)textMarkerHelper { | |
| 1953 if (!textMarkerHelper_) { | |
| 1954 textMarkerHelper_.reset([[TextMarkerHelperMac alloc] | |
| 1955 initWithFactory:base::MakeUnique<BrowserPositionFactory>( | |
| 1956 browserAccessibility_)]); | |
| 1957 } | |
| 1958 return textMarkerHelper_; | |
| 1959 } | |
| 1960 | |
| 2029 // Returns the accessibility value for the given attribute. If the value isn't | 1961 // Returns the accessibility value for the given attribute. If the value isn't |
| 2030 // supported this will return nil. | 1962 // supported this will return nil. |
| 2031 - (id)accessibilityAttributeValue:(NSString*)attribute { | 1963 - (id)accessibilityAttributeValue:(NSString*)attribute { |
| 2032 if (![self instanceActive]) | 1964 if (![self instanceActive]) |
| 2033 return nil; | 1965 return nil; |
| 2034 | 1966 |
| 2035 SEL selector = | 1967 SEL selector = |
| 2036 NSSelectorFromString([self methodNameForAttribute:attribute]); | 1968 NSSelectorFromString([self methodNameForAttribute:attribute]); |
| 2037 if (selector) | 1969 if (selector) |
| 2038 return [self performSelector:selector]; | 1970 return [self performSelector:selector]; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2135 } | 2067 } |
| 2136 if (colIndex == column) | 2068 if (colIndex == column) |
| 2137 return ToBrowserAccessibilityCocoa(cell); | 2069 return ToBrowserAccessibilityCocoa(cell); |
| 2138 if (colIndex > column) | 2070 if (colIndex > column) |
| 2139 break; | 2071 break; |
| 2140 } | 2072 } |
| 2141 } | 2073 } |
| 2142 return nil; | 2074 return nil; |
| 2143 } | 2075 } |
| 2144 | 2076 |
| 2077 SEL selector = NSSelectorFromString(attribute); | |
|
tapted
2017/06/19 11:44:30
(self review: this needs a colon appended to the s
| |
| 2078 DCHECK(selector); | |
| 2079 if ([TextMarkerHelperMac instancesRespondToSelector:selector]) { | |
| 2080 return | |
| 2081 [[self textMarkerHelper] performSelector:selector withObject:parameter]; | |
| 2082 } | |
| 2083 | |
| 2145 if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) { | 2084 if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) { |
| 2146 AXPlatformPositionInstance position = | 2085 AXPlatformPositionInstance position = CreateConcretePositionFromTextMarker( |
| 2147 CreateConcretePositionFromTextMarker(parameter); | 2086 base::mac::CFCastStrict<AXTextMarkerRef>(parameter)); |
| 2148 if (!position->IsNullPosition()) | 2087 if (!position->IsNullPosition()) |
| 2149 return ToBrowserAccessibilityCocoa(position->GetAnchor()); | 2088 return ToBrowserAccessibilityCocoa(position->GetAnchor()); |
| 2150 | 2089 |
| 2151 return nil; | 2090 return nil; |
| 2152 } | 2091 } |
| 2153 | 2092 |
| 2154 if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) { | 2093 if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) { |
| 2155 AXAbstractPositionInstance startPosition = | 2094 return GetTextForTextMarkerRange( |
| 2156 browserAccessibility_->CreatePositionAt(0); | 2095 base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter)); |
| 2157 AXAbstractPositionInstance endPosition = | |
| 2158 startPosition->CreatePositionAtEndOfAnchor(); | |
| 2159 ui::AXAbstractRange range = | |
| 2160 ui::AXAbstractRange(std::move(startPosition), std::move(endPosition)); | |
| 2161 return CreateTextMarkerRange(std::move(range)); | |
| 2162 } | 2096 } |
| 2163 | 2097 |
| 2164 if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) | 2098 if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) { |
| 2165 return GetTextForTextMarkerRange(parameter); | 2099 return GetAttributedTextForTextMarkerRange( |
| 2166 | 2100 base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter)); |
| 2167 if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) | |
| 2168 return GetAttributedTextForTextMarkerRange(parameter); | |
| 2169 | |
| 2170 if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) { | |
| 2171 AXAbstractPositionInstance position = | |
| 2172 CreatePositionFromTextMarker(parameter); | |
| 2173 if (position->IsNullPosition()) | |
| 2174 return nil; | |
| 2175 return CreateTextMarker(position->CreateNextCharacterPosition()); | |
| 2176 } | |
| 2177 | |
| 2178 if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) { | |
| 2179 AXAbstractPositionInstance position = | |
| 2180 CreatePositionFromTextMarker(parameter); | |
| 2181 if (position->IsNullPosition()) | |
| 2182 return nil; | |
| 2183 return CreateTextMarker(position->CreatePreviousCharacterPosition()); | |
| 2184 } | |
| 2185 | |
| 2186 if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) { | |
| 2187 AXAbstractPositionInstance endPosition = | |
| 2188 CreatePositionFromTextMarker(parameter); | |
| 2189 if (endPosition->IsNullPosition()) | |
| 2190 return nil; | |
| 2191 | |
| 2192 AXAbstractPositionInstance startWordPosition = | |
| 2193 endPosition->CreatePreviousWordStartPosition(); | |
| 2194 AXAbstractPositionInstance endWordPosition = | |
| 2195 endPosition->CreatePreviousWordEndPosition(); | |
| 2196 AXAbstractPositionInstance startPosition = | |
| 2197 *startWordPosition <= *endWordPosition ? std::move(endWordPosition) | |
| 2198 : std::move(startWordPosition); | |
| 2199 ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition)); | |
| 2200 return CreateTextMarkerRange(std::move(range)); | |
| 2201 } | |
| 2202 | |
| 2203 if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) { | |
| 2204 AXAbstractPositionInstance startPosition = | |
| 2205 CreatePositionFromTextMarker(parameter); | |
| 2206 if (startPosition->IsNullPosition()) | |
| 2207 return nil; | |
| 2208 | |
| 2209 AXAbstractPositionInstance endWordPosition = | |
| 2210 startPosition->CreateNextWordEndPosition(); | |
| 2211 AXAbstractPositionInstance startWordPosition = | |
| 2212 startPosition->CreateNextWordStartPosition(); | |
| 2213 AXAbstractPositionInstance endPosition = | |
| 2214 *startWordPosition <= *endWordPosition ? std::move(startWordPosition) | |
| 2215 : std::move(endWordPosition); | |
| 2216 ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition)); | |
| 2217 return CreateTextMarkerRange(std::move(range)); | |
| 2218 } | |
| 2219 | |
| 2220 if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) { | |
| 2221 AXAbstractPositionInstance position = | |
| 2222 CreatePositionFromTextMarker(parameter); | |
| 2223 if (position->IsNullPosition()) | |
| 2224 return nil; | |
| 2225 return CreateTextMarker(position->CreateNextWordEndPosition()); | |
| 2226 } | |
| 2227 | |
| 2228 if ([attribute | |
| 2229 isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) { | |
| 2230 AXAbstractPositionInstance position = | |
| 2231 CreatePositionFromTextMarker(parameter); | |
| 2232 if (position->IsNullPosition()) | |
| 2233 return nil; | |
| 2234 return CreateTextMarker(position->CreatePreviousWordStartPosition()); | |
| 2235 } | |
| 2236 | |
| 2237 if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) { | |
| 2238 AXAbstractPositionInstance position = | |
| 2239 CreatePositionFromTextMarker(parameter); | |
| 2240 if (position->IsNullPosition()) | |
| 2241 return nil; | |
| 2242 | |
| 2243 AXAbstractPositionInstance startPosition = | |
| 2244 position->CreatePreviousLineStartPosition(); | |
| 2245 AXAbstractPositionInstance endPosition = | |
| 2246 position->CreateNextLineEndPosition(); | |
| 2247 ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition)); | |
| 2248 return CreateTextMarkerRange(std::move(range)); | |
| 2249 } | |
| 2250 | |
| 2251 if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) { | |
| 2252 AXAbstractPositionInstance endPosition = | |
| 2253 CreatePositionFromTextMarker(parameter); | |
| 2254 if (endPosition->IsNullPosition()) | |
| 2255 return nil; | |
| 2256 | |
| 2257 AXAbstractPositionInstance startLinePosition = | |
| 2258 endPosition->CreatePreviousLineStartPosition(); | |
| 2259 AXAbstractPositionInstance endLinePosition = | |
| 2260 endPosition->CreatePreviousLineEndPosition(); | |
| 2261 AXAbstractPositionInstance startPosition = | |
| 2262 *startLinePosition <= *endLinePosition ? std::move(endLinePosition) | |
| 2263 : std::move(startLinePosition); | |
| 2264 ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition)); | |
| 2265 return CreateTextMarkerRange(std::move(range)); | |
| 2266 } | |
| 2267 | |
| 2268 if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) { | |
| 2269 AXAbstractPositionInstance startPosition = | |
| 2270 CreatePositionFromTextMarker(parameter); | |
| 2271 if (startPosition->IsNullPosition()) | |
| 2272 return nil; | |
| 2273 | |
| 2274 AXAbstractPositionInstance startLinePosition = | |
| 2275 startPosition->CreateNextLineStartPosition(); | |
| 2276 AXAbstractPositionInstance endLinePosition = | |
| 2277 startPosition->CreateNextLineEndPosition(); | |
| 2278 AXAbstractPositionInstance endPosition = | |
| 2279 *startLinePosition <= *endLinePosition ? std::move(startLinePosition) | |
| 2280 : std::move(endLinePosition); | |
| 2281 ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition)); | |
| 2282 return CreateTextMarkerRange(std::move(range)); | |
| 2283 } | |
| 2284 | |
| 2285 if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) { | |
| 2286 AXAbstractPositionInstance position = | |
| 2287 CreatePositionFromTextMarker(parameter); | |
| 2288 if (position->IsNullPosition()) | |
| 2289 return nil; | |
| 2290 return CreateTextMarker(position->CreateNextLineEndPosition()); | |
| 2291 } | |
| 2292 | |
| 2293 if ([attribute | |
| 2294 isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) { | |
| 2295 AXAbstractPositionInstance position = | |
| 2296 CreatePositionFromTextMarker(parameter); | |
| 2297 if (position->IsNullPosition()) | |
| 2298 return nil; | |
| 2299 return CreateTextMarker(position->CreatePreviousLineStartPosition()); | |
| 2300 } | 2101 } |
| 2301 | 2102 |
| 2302 if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) { | 2103 if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) { |
| 2303 NSString* text = GetTextForTextMarkerRange(parameter); | 2104 NSString* text = GetTextForTextMarkerRange( |
| 2105 base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter)); | |
| 2304 return [NSNumber numberWithInt:[text length]]; | 2106 return [NSNumber numberWithInt:[text length]]; |
| 2305 } | 2107 } |
| 2306 | 2108 |
| 2307 if ([attribute isEqualToString: | 2109 if ([attribute isEqualToString: |
| 2308 NSAccessibilityBoundsForRangeParameterizedAttribute]) { | 2110 NSAccessibilityBoundsForRangeParameterizedAttribute]) { |
| 2309 if ([self internalRole] != ui::AX_ROLE_STATIC_TEXT) | 2111 if ([self internalRole] != ui::AX_ROLE_STATIC_TEXT) |
| 2310 return nil; | 2112 return nil; |
| 2311 NSRange range = [(NSValue*)parameter rangeValue]; | 2113 NSRange range = [(NSValue*)parameter rangeValue]; |
| 2312 gfx::Rect rect = browserAccessibility_->GetScreenBoundsForRange( | 2114 gfx::Rect rect = browserAccessibility_->GetScreenBoundsForRange( |
| 2313 range.location, range.length); | 2115 range.location, range.length); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 2333 NSMutableArray* result = [NSMutableArray arrayWithCapacity:count]; | 2135 NSMutableArray* result = [NSMutableArray arrayWithCapacity:count]; |
| 2334 for (size_t i = 0; i < count; ++i) { | 2136 for (size_t i = 0; i < count; ++i) { |
| 2335 BrowserAccessibility* match = search.GetMatchAtIndex(i); | 2137 BrowserAccessibility* match = search.GetMatchAtIndex(i); |
| 2336 [result addObject:ToBrowserAccessibilityCocoa(match)]; | 2138 [result addObject:ToBrowserAccessibilityCocoa(match)]; |
| 2337 } | 2139 } |
| 2338 return result; | 2140 return result; |
| 2339 } | 2141 } |
| 2340 return nil; | 2142 return nil; |
| 2341 } | 2143 } |
| 2342 | 2144 |
| 2343 if ([attribute isEqualToString: | 2145 // TODO(tapted): Move this to TextMarkerHelper. |
| 2344 NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute ]) { | |
| 2345 AXAbstractPositionInstance position = | |
| 2346 CreatePositionFromTextMarker(parameter); | |
| 2347 if (position->IsNullPosition()) | |
| 2348 return nil; | |
| 2349 | |
| 2350 ui::AXAbstractRange range(position->CreatePreviousLineStartPosition(), | |
| 2351 position->CreateNextLineEndPosition()); | |
| 2352 return CreateTextMarkerRange(std::move(range)); | |
| 2353 } | |
| 2354 | |
| 2355 if ([attribute isEqualToString: | 2146 if ([attribute isEqualToString: |
| 2356 NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute]) { | 2147 NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute]) { |
| 2357 BrowserAccessibility* startObject; | 2148 BrowserAccessibility* startObject; |
| 2358 BrowserAccessibility* endObject; | 2149 BrowserAccessibility* endObject; |
| 2359 int startOffset, endOffset; | 2150 int startOffset, endOffset; |
| 2360 AXPlatformRange range = CreateRangeFromTextMarkerRange(parameter); | 2151 AXPlatformRange range = CreateRangeFromTextMarkerRange( |
| 2152 base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter)); | |
| 2361 if (range.IsNull()) | 2153 if (range.IsNull()) |
| 2362 return nil; | 2154 return nil; |
| 2363 | 2155 |
| 2364 startObject = range.GetAnchorNode(); | 2156 startObject = range.GetAnchorNode(); |
| 2365 endObject = range.GetFocusNode(); | 2157 endObject = range.GetFocusNode(); |
| 2366 startOffset = range.anchor()->text_offset(); | 2158 startOffset = range.anchor()->text_offset(); |
| 2367 endOffset = range.focus()->text_offset(); | 2159 endOffset = range.focus()->text_offset(); |
| 2368 DCHECK(startObject && endObject); | 2160 DCHECK(startObject && endObject); |
| 2369 DCHECK_GE(startOffset, 0); | 2161 DCHECK_GE(startOffset, 0); |
| 2370 DCHECK_GE(endOffset, 0); | 2162 DCHECK_GE(endOffset, 0); |
| 2371 | 2163 |
| 2372 gfx::Rect rect = BrowserAccessibilityManager::GetPageBoundsForRange( | 2164 gfx::Rect rect = BrowserAccessibilityManager::GetPageBoundsForRange( |
| 2373 *startObject, startOffset, *endObject, endOffset); | 2165 *startObject, startOffset, *endObject, endOffset); |
| 2374 NSPoint origin = NSMakePoint(rect.x(), rect.y()); | 2166 NSPoint origin = NSMakePoint(rect.x(), rect.y()); |
| 2375 NSSize size = NSMakeSize(rect.width(), rect.height()); | 2167 NSSize size = NSMakeSize(rect.width(), rect.height()); |
| 2376 NSPoint pointInScreen = [self pointInScreen:origin size:size]; | 2168 NSPoint pointInScreen = [self pointInScreen:origin size:size]; |
| 2377 NSRect nsrect = NSMakeRect( | 2169 NSRect nsrect = NSMakeRect( |
| 2378 pointInScreen.x, pointInScreen.y, rect.width(), rect.height()); | 2170 pointInScreen.x, pointInScreen.y, rect.width(), rect.height()); |
| 2379 return [NSValue valueWithRect:nsrect]; | 2171 return [NSValue valueWithRect:nsrect]; |
| 2380 } | 2172 } |
| 2381 | 2173 |
| 2382 if ([attribute isEqualToString: | 2174 if ([attribute isEqualToString: |
| 2383 NSAccessibilityTextMarkerRangeForUnorderedTextMarkersParameterizedAtt ribute]) { | |
| 2384 if (![parameter isKindOfClass:[NSArray class]]) | |
| 2385 return nil; | |
| 2386 | |
| 2387 NSArray* text_marker_array = parameter; | |
| 2388 if ([text_marker_array count] != 2) | |
| 2389 return nil; | |
| 2390 | |
| 2391 AXAbstractPositionInstance startPosition = | |
| 2392 CreatePositionFromTextMarker([text_marker_array objectAtIndex:0]); | |
| 2393 AXAbstractPositionInstance endPosition = | |
| 2394 CreatePositionFromTextMarker([text_marker_array objectAtIndex:1]); | |
| 2395 if (*startPosition <= *endPosition) { | |
| 2396 return CreateTextMarkerRange(ui::AXAbstractRange(std::move(startPosition), | |
| 2397 std::move(endPosition))); | |
| 2398 } else { | |
| 2399 return CreateTextMarkerRange(ui::AXAbstractRange( | |
| 2400 std::move(endPosition), std::move(startPosition))); | |
| 2401 } | |
| 2402 } | |
| 2403 | |
| 2404 if ([attribute isEqualToString: | |
| 2405 NSAccessibilityIndexForChildUIElementParameterizedAttribute]) { | 2175 NSAccessibilityIndexForChildUIElementParameterizedAttribute]) { |
| 2406 if (![parameter isKindOfClass:[BrowserAccessibilityCocoa class]]) | 2176 if (![parameter isKindOfClass:[BrowserAccessibilityCocoa class]]) |
| 2407 return nil; | 2177 return nil; |
| 2408 | 2178 |
| 2409 BrowserAccessibilityCocoa* childCocoaObj = | 2179 BrowserAccessibilityCocoa* childCocoaObj = |
| 2410 (BrowserAccessibilityCocoa*)parameter; | 2180 (BrowserAccessibilityCocoa*)parameter; |
| 2411 BrowserAccessibility* child = [childCocoaObj browserAccessibility]; | 2181 BrowserAccessibility* child = [childCocoaObj browserAccessibility]; |
| 2412 if (!child) | 2182 if (!child) |
| 2413 return nil; | 2183 return nil; |
| 2414 | 2184 |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2891 } | 2661 } |
| 2892 | 2662 |
| 2893 - (BOOL)accessibilityNotifiesWhenDestroyed { | 2663 - (BOOL)accessibilityNotifiesWhenDestroyed { |
| 2894 // Indicate that BrowserAccessibilityCocoa will post a notification when it's | 2664 // Indicate that BrowserAccessibilityCocoa will post a notification when it's |
| 2895 // destroyed (see -detach). This allows VoiceOver to do some internal things | 2665 // destroyed (see -detach). This allows VoiceOver to do some internal things |
| 2896 // more efficiently. | 2666 // more efficiently. |
| 2897 return YES; | 2667 return YES; |
| 2898 } | 2668 } |
| 2899 | 2669 |
| 2900 @end | 2670 @end |
| 2671 | |
| 2672 std::unique_ptr<ui::AXPositionBase> BrowserPositionFactory::GetRoot() const { | |
| 2673 const BrowserAccessibility* root = | |
| 2674 browser_accessibility_->manager()->GetRoot(); | |
| 2675 if (!root) | |
| 2676 return nullptr; | |
| 2677 | |
| 2678 return root->CreatePositionAt(0); | |
| 2679 } | |
| 2680 | |
| 2681 std::unique_ptr<ui::AXAbstractRange> BrowserPositionFactory::GetSelection() | |
| 2682 const { | |
| 2683 if (!IsActive()) | |
| 2684 return nullptr; | |
| 2685 | |
| 2686 BrowserAccessibilityManager* manager = browser_accessibility_->manager(); | |
| 2687 if (!manager) | |
| 2688 return nullptr; | |
| 2689 | |
| 2690 int32_t anchorId = manager->GetTreeData().sel_anchor_object_id; | |
|
tapted
2017/06/19 11:44:30
(self review: convert to hacker_case)
| |
| 2691 const BrowserAccessibility* anchorObject = manager->GetFromID(anchorId); | |
| 2692 if (!anchorObject) | |
| 2693 return nullptr; | |
| 2694 | |
| 2695 int32_t focusId = manager->GetTreeData().sel_focus_object_id; | |
| 2696 const BrowserAccessibility* focusObject = manager->GetFromID(focusId); | |
| 2697 if (!focusObject) | |
| 2698 return nullptr; | |
| 2699 | |
| 2700 int anchorOffset = manager->GetTreeData().sel_anchor_offset; | |
| 2701 int focusOffset = manager->GetTreeData().sel_focus_offset; | |
| 2702 if (anchorOffset < 0 || focusOffset < 0) | |
| 2703 return nullptr; | |
| 2704 | |
| 2705 ui::AXTextAffinity anchorAffinity = | |
| 2706 manager->GetTreeData().sel_anchor_affinity; | |
| 2707 ui::AXTextAffinity focusAffinity = manager->GetTreeData().sel_focus_affinity; | |
| 2708 | |
| 2709 return base::MakeUnique<ui::AXAbstractRange>( | |
| 2710 CreateTextRange(*anchorObject, anchorOffset, anchorAffinity, *focusObject, | |
| 2711 focusOffset, focusAffinity)); | |
| 2712 } | |
| 2713 | |
| 2714 std::unique_ptr<ui::AXPositionBase> BrowserPositionFactory::ExtractFromMarker( | |
| 2715 AXTextMarkerRef marker) const { | |
| 2716 return base::WrapUnique( | |
| 2717 CreateConcretePositionFromTextMarker(marker).release()); | |
| 2718 } | |
| OLD | NEW |