Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: content/browser/accessibility/browser_accessibility_cocoa.mm

Issue 2940923003: a11y: Move CreateTextMarker[Range] to TextMarkerHelperMac.
Patch Set: squish? Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/mac/foundation_util.mm ('k') | ui/accessibility/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
11 11
12 #include <map> 12 #include <map>
13 #include <memory> 13 #include <memory>
14 #include <utility> 14 #include <utility>
15 15
16 #include "base/mac/foundation_util.h" 16 #include "base/mac/foundation_util.h"
17 #include "base/mac/scoped_cftyperef.h" 17 #include "base/mac/scoped_cftyperef.h"
18 #include "base/memory/ptr_util.h"
18 #include "base/strings/string16.h" 19 #include "base/strings/string16.h"
19 #include "base/strings/sys_string_conversions.h" 20 #include "base/strings/sys_string_conversions.h"
20 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
21 #include "content/app/strings/grit/content_strings.h" 22 #include "content/app/strings/grit/content_strings.h"
22 #include "content/browser/accessibility/ax_platform_position.h" 23 #include "content/browser/accessibility/ax_platform_position.h"
23 #include "content/browser/accessibility/browser_accessibility_mac.h" 24 #include "content/browser/accessibility/browser_accessibility_mac.h"
24 #include "content/browser/accessibility/browser_accessibility_manager.h" 25 #include "content/browser/accessibility/browser_accessibility_manager.h"
25 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" 26 #include "content/browser/accessibility/browser_accessibility_manager_mac.h"
26 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h" 27 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
27 #include "content/public/common/content_client.h" 28 #include "content/public/common/content_client.h"
28 #include "third_party/skia/include/core/SkColor.h" 29 #include "third_party/skia/include/core/SkColor.h"
29 #include "ui/accessibility/ax_range.h" 30 #include "ui/accessibility/ax_range.h"
30 #import "ui/accessibility/platform/ax_platform_node_mac.h" 31 #import "ui/accessibility/platform/ax_platform_node_mac.h"
32 #import "ui/accessibility/platform/text_marker_helper_mac.h"
31 33
32 using AXPlatformPositionInstance = 34 using AXPlatformPositionInstance =
33 content::AXPlatformPosition::AXPositionInstance; 35 content::AXPlatformPosition::AXPositionInstance;
34 using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>; 36 using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>;
35 using AXTextMarkerRangeRef = CFTypeRef;
36 using AXTextMarkerRef = CFTypeRef;
37 using StringAttribute = ui::AXStringAttribute; 37 using StringAttribute = ui::AXStringAttribute;
38 using content::AXPlatformPosition; 38 using content::AXPlatformPosition;
39 using content::AccessibilityMatchPredicate; 39 using content::AccessibilityMatchPredicate;
40 using content::BrowserAccessibility; 40 using content::BrowserAccessibility;
41 using content::BrowserAccessibilityDelegate; 41 using content::BrowserAccessibilityDelegate;
42 using content::BrowserAccessibilityManager; 42 using content::BrowserAccessibilityManager;
43 using content::BrowserAccessibilityManagerMac; 43 using content::BrowserAccessibilityManagerMac;
44 using content::ContentClient; 44 using content::ContentClient;
45 using content::OneShotAccessibilityTreeSearch; 45 using content::OneShotAccessibilityTreeSearch;
46 using ui::AXNodeData; 46 using ui::AXNodeData;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 104
105 // Actions. 105 // Actions.
106 NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible"; 106 NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible";
107 107
108 // A mapping from an accessibility attribute to its method name. 108 // A mapping from an accessibility attribute to its method name.
109 NSDictionary* attributeToMethodNameMap = nil; 109 NSDictionary* attributeToMethodNameMap = nil;
110 110
111 // VoiceOver uses -1 to mean "no limit" for AXResultsLimit. 111 // VoiceOver uses -1 to mean "no limit" for AXResultsLimit.
112 const int kAXResultsLimitNoLimit = -1; 112 const int kAXResultsLimitNoLimit = -1;
113 113
114 extern "C" { 114 class BrowserPositionFactory : public ui::PositionFactory {
115 public:
116 explicit BrowserPositionFactory(
117 content::BrowserAccessibility* browser_accessibility)
118 : browser_accessibility_(browser_accessibility) {}
115 119
116 // The following are private accessibility APIs required for cursor navigation 120 ui::AXPositionPointer GetRoot() const override;
117 // and text selection. VoiceOver started relying on them in Mac OS X 10.11. 121 ui::AXRangePointer GetSelection() const override;
118 #if !defined(MAC_OS_X_VERSION_10_11) || \ 122 ui::AXPositionPointer GetFromData(
119 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 123 const ui::AXPositionData& data) const override;
124 id GetAccessibilityObject(const ui::AXPositionData& data) const override;
120 125
121 AXTextMarkerRef AXTextMarkerCreate(CFAllocatorRef allocator, 126 private:
122 const UInt8* bytes, 127 bool IsActive() const {
123 CFIndex length); 128 return browser_accessibility_ && browser_accessibility_->instance_active();
129 }
124 130
125 const UInt8* AXTextMarkerGetBytePtr(AXTextMarkerRef text_marker); 131 content::BrowserAccessibility* browser_accessibility_;
126 132
127 size_t AXTextMarkerGetLength(AXTextMarkerRef text_marker); 133 DISALLOW_COPY_AND_ASSIGN(BrowserPositionFactory);
134 };
128 135
129 AXTextMarkerRangeRef AXTextMarkerRangeCreate(CFAllocatorRef allocator, 136 AXPlatformRange CreateRangeFromTextMarkerRange(id marker_range) {
130 AXTextMarkerRef start_marker, 137 ui::AXPositionData start, end;
131 AXTextMarkerRef end_marker); 138 if (![TextMarkerHelperMac getRangeDataFromMarkerRange:marker_range
139 start:&start
140 end:&end]) {
141 return AXPlatformRange();
142 }
132 143
133 AXTextMarkerRef AXTextMarkerRangeCopyStartMarker( 144 return AXPlatformRange(AXPlatformPosition::CreateFromData(start),
134 AXTextMarkerRangeRef text_marker_range); 145 AXPlatformPosition::CreateFromData(end));
135
136 AXTextMarkerRef AXTextMarkerRangeCopyEndMarker(
137 AXTextMarkerRangeRef text_marker_range);
138
139 #endif // MAC_OS_X_VERSION_10_11
140
141 } // extern "C"
142
143 // AXTextMarkerCreate copies from data buffer given to it.
144 id CreateTextMarker(AXPlatformPositionInstance position) {
145 AXTextMarkerRef text_marker = AXTextMarkerCreate(
146 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(position.get()),
147 sizeof(AXPlatformPosition));
148 return static_cast<id>(
149 base::mac::CFTypeRefToNSObjectAutorelease(text_marker));
150 }
151
152 // |range| is destructed at the end of this method. |anchor| and |focus| are
153 // copied into the individual text markers.
154 id CreateTextMarkerRange(const AXPlatformRange range) {
155 base::ScopedCFTypeRef<AXTextMarkerRef> start_marker(AXTextMarkerCreate(
156 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.anchor()),
157 sizeof(AXPlatformPosition)));
158 base::ScopedCFTypeRef<AXTextMarkerRef> end_marker(AXTextMarkerCreate(
159 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.focus()),
160 sizeof(AXPlatformPosition)));
161 AXTextMarkerRangeRef marker_range =
162 AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker);
163 return static_cast<id>(
164 base::mac::CFTypeRefToNSObjectAutorelease(marker_range));
165 }
166
167 AXPlatformPositionInstance CreatePositionFromTextMarker(
168 AXTextMarkerRef text_marker) {
169 DCHECK(text_marker);
170 if (AXTextMarkerGetLength(text_marker) != sizeof(AXPlatformPosition))
171 return AXPlatformPosition::CreateNullPosition();
172 const UInt8* source_buffer = AXTextMarkerGetBytePtr(text_marker);
173 if (!source_buffer)
174 return AXPlatformPosition::CreateNullPosition();
175 UInt8* destination_buffer = new UInt8[sizeof(AXPlatformPosition)];
176 std::memcpy(destination_buffer, source_buffer, sizeof(AXPlatformPosition));
177 AXPlatformPosition::AXPositionInstance position(
178 reinterpret_cast<AXPlatformPosition::AXPositionInstance::pointer>(
179 destination_buffer));
180 if (!position)
181 return AXPlatformPosition::CreateNullPosition();
182 return position;
183 }
184
185 AXPlatformRange CreateRangeFromTextMarkerRange(
186 AXTextMarkerRangeRef marker_range) {
187 DCHECK(marker_range);
188 base::ScopedCFTypeRef<AXTextMarkerRef> start_marker(
189 AXTextMarkerRangeCopyStartMarker(marker_range));
190 base::ScopedCFTypeRef<AXTextMarkerRef> end_marker(
191 AXTextMarkerRangeCopyEndMarker(marker_range));
192 if (!start_marker.get() || !end_marker.get())
193 return AXPlatformRange();
194
195 AXPlatformPositionInstance anchor =
196 CreatePositionFromTextMarker(start_marker.get());
197 AXPlatformPositionInstance focus =
198 CreatePositionFromTextMarker(end_marker.get());
199 // |AXPlatformRange| takes ownership of its anchor and focus.
200 return AXPlatformRange(std::move(anchor), std::move(focus));
201 } 146 }
202 147
203 AXPlatformPositionInstance CreateTextPosition( 148 AXPlatformPositionInstance CreateTextPosition(
204 const BrowserAccessibility& object, 149 const BrowserAccessibility& object,
205 int offset, 150 int offset,
206 ui::AXTextAffinity affinity) { 151 ui::AXTextAffinity affinity) {
207 if (!object.instance_active()) 152 if (!object.instance_active())
208 return AXPlatformPosition::CreateNullPosition(); 153 return AXPlatformPosition::CreateNullPosition();
209 154
210 const BrowserAccessibilityManager* manager = object.manager(); 155 const BrowserAccessibilityManager* manager = object.manager();
211 DCHECK(manager); 156 DCHECK(manager);
212 return AXPlatformPosition::CreateTextPosition( 157 return AXPlatformPosition::CreateTextPosition(
213 manager->ax_tree_id(), object.GetId(), offset, affinity); 158 manager->ax_tree_id(), object.GetId(), offset, affinity);
214 } 159 }
215 160
216 AXPlatformRange CreateTextRange(const BrowserAccessibility& start_object, 161 ui::AXRangePointer CreateTextRange(const BrowserAccessibility& start_object,
217 int start_offset, 162 int start_offset,
218 ui::AXTextAffinity start_affinity, 163 ui::AXTextAffinity start_affinity,
219 const BrowserAccessibility& end_object, 164 const BrowserAccessibility& end_object,
220 int end_offset, 165 int end_offset,
221 ui::AXTextAffinity end_affinity) { 166 ui::AXTextAffinity end_affinity) {
222 AXPlatformPositionInstance anchor = 167 AXPlatformPositionInstance anchor =
223 CreateTextPosition(start_object, start_offset, start_affinity); 168 CreateTextPosition(start_object, start_offset, start_affinity);
224 AXPlatformPositionInstance focus = 169 AXPlatformPositionInstance focus =
225 CreateTextPosition(end_object, end_offset, end_affinity); 170 CreateTextPosition(end_object, end_offset, end_affinity);
226 // |AXPlatformRange| takes ownership of its anchor and focus. 171 // |AXRangePointer| takes ownership of its anchor and focus.
227 return AXPlatformRange(std::move(anchor), std::move(focus)); 172 return ui::AXRangePointer(std::move(anchor), std::move(focus));
228 } 173 }
229 174
230 void AddMisspelledTextAttributes( 175 void AddMisspelledTextAttributes(
231 const std::vector<const BrowserAccessibility*>& text_only_objects, 176 const std::vector<const BrowserAccessibility*>& text_only_objects,
232 NSMutableAttributedString* attributed_string) { 177 NSMutableAttributedString* attributed_string) {
233 [attributed_string beginEditing]; 178 [attributed_string beginEditing];
234 for (const BrowserAccessibility* text_object : text_only_objects) { 179 for (const BrowserAccessibility* text_object : text_only_objects) {
235 const std::vector<int32_t>& marker_types = 180 const std::vector<int32_t>& marker_types =
236 text_object->GetIntListAttribute(ui::AX_ATTR_MARKER_TYPES); 181 text_object->GetIntListAttribute(ui::AX_ATTR_MARKER_TYPES);
237 const std::vector<int>& marker_starts = 182 const std::vector<int>& marker_starts =
(...skipping 12 matching lines...) Expand all
250 DCHECK_GT(misspelling_length, 0); 195 DCHECK_GT(misspelling_length, 0);
251 [attributed_string 196 [attributed_string
252 addAttribute:NSAccessibilityMarkedMisspelledTextAttribute 197 addAttribute:NSAccessibilityMarkedMisspelledTextAttribute
253 value:@YES 198 value:@YES
254 range:NSMakeRange(misspelling_start, misspelling_length)]; 199 range:NSMakeRange(misspelling_start, misspelling_length)];
255 } 200 }
256 } 201 }
257 [attributed_string endEditing]; 202 [attributed_string endEditing];
258 } 203 }
259 204
260 NSString* GetTextForTextMarkerRange(AXTextMarkerRangeRef marker_range) { 205 NSString* GetTextForTextMarkerRange(id marker_range) {
261 AXPlatformRange range = CreateRangeFromTextMarkerRange(marker_range); 206 AXPlatformRange range = CreateRangeFromTextMarkerRange(marker_range);
262 if (range.IsNull()) 207 if (range.IsNull())
263 return nil; 208 return nil;
264 return base::SysUTF16ToNSString(range.GetText()); 209 return base::SysUTF16ToNSString(range.GetText());
265 } 210 }
266 211
267 NSAttributedString* GetAttributedTextForTextMarkerRange( 212 NSAttributedString* GetAttributedTextForTextMarkerRange(id marker_range) {
268 AXTextMarkerRangeRef marker_range) {
269 BrowserAccessibility* start_object; 213 BrowserAccessibility* start_object;
270 BrowserAccessibility* end_object; 214 BrowserAccessibility* end_object;
271 int start_offset, end_offset; 215 int start_offset, end_offset;
272 ui::AXTextAffinity start_affinity, end_affinity; 216 ui::AXTextAffinity start_affinity, end_affinity;
273 AXPlatformRange ax_range = CreateRangeFromTextMarkerRange(marker_range); 217 AXPlatformRange ax_range = CreateRangeFromTextMarkerRange(marker_range);
274 if (ax_range.IsNull()) 218 if (ax_range.IsNull())
275 return nil; 219 return nil;
276 start_object = ax_range.anchor()->GetAnchor(); 220 start_object = ax_range.anchor()->GetAnchor();
277 end_object = ax_range.focus()->GetAnchor(); 221 end_object = ax_range.focus()->GetAnchor();
278 start_offset = ax_range.anchor()->text_offset(); 222 start_offset = ax_range.anchor()->text_offset();
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 } // namespace 460 } // namespace
517 461
518 // The following private WebKit accessibility attribute became public in 10.12. 462 // The following private WebKit accessibility attribute became public in 10.12.
519 #if !defined(MAC_OS_X_VERSION_10_12) || \ 463 #if !defined(MAC_OS_X_VERSION_10_12) || \
520 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 464 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12
521 extern "C" { 465 extern "C" {
522 NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; 466 NSString* const NSAccessibilityRequiredAttribute = @"AXRequired";
523 } 467 }
524 #endif // MAC_OS_X_VERSION_10_12 468 #endif // MAC_OS_X_VERSION_10_12
525 469
526 @implementation BrowserAccessibilityCocoa 470 @interface BrowserAccessibilityCocoa ()
471
472 // Lazily creates a TextMarkerHelper and returns it.
473 - (TextMarkerHelperMac*)textMarkerHelper;
474
475 @end
476
477 @implementation BrowserAccessibilityCocoa {
478 base::scoped_nsobject<TextMarkerHelperMac> textMarkerHelper_;
479 }
527 480
528 + (void)initialize { 481 + (void)initialize {
529 const struct { 482 const struct {
530 NSString* attribute; 483 NSString* attribute;
531 NSString* methodName; 484 NSString* methodName;
532 } attributeToMethodNameContainer[] = { 485 } attributeToMethodNameContainer[] = {
533 {NSAccessibilityARIAAtomicAttribute, @"ariaAtomic"}, 486 {NSAccessibilityARIAAtomicAttribute, @"ariaAtomic"},
534 {NSAccessibilityARIABusyAttribute, @"ariaBusy"}, 487 {NSAccessibilityARIABusyAttribute, @"ariaBusy"},
535 {NSAccessibilityARIAColumnCountAttribute, @"ariaColumnCount"}, 488 {NSAccessibilityARIAColumnCountAttribute, @"ariaColumnCount"},
536 {NSAccessibilityARIAColumnIndexAttribute, @"ariaColumnIndex"}, 489 {NSAccessibilityARIAColumnIndexAttribute, @"ariaColumnIndex"},
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 return nil; 912 return nil;
960 } 913 }
961 914
962 - (NSNumber*)enabled { 915 - (NSNumber*)enabled {
963 if (![self instanceActive]) 916 if (![self instanceActive])
964 return nil; 917 return nil;
965 return [NSNumber numberWithBool: 918 return [NSNumber numberWithBool:
966 !GetState(browserAccessibility_, ui::AX_STATE_DISABLED)]; 919 !GetState(browserAccessibility_, ui::AX_STATE_DISABLED)];
967 } 920 }
968 921
969 // Returns a text marker that points to the last character in the document that 922 - (id)startTextMarker {
970 // can be selected with VoiceOver. 923 return [[self textMarkerHelper] startTextMarker];
924 }
925
971 - (id)endTextMarker { 926 - (id)endTextMarker {
972 const BrowserAccessibility* root = 927 return [[self textMarkerHelper] endTextMarker];
973 browserAccessibility_->manager()->GetRoot();
974 if (!root)
975 return nil;
976
977 AXPlatformPositionInstance position = root->CreatePositionAt(0);
978 return CreateTextMarker(position->CreatePositionAtEndOfAnchor());
979 } 928 }
980 929
981 - (NSNumber*)expanded { 930 - (NSNumber*)expanded {
982 if (![self instanceActive]) 931 if (![self instanceActive])
983 return nil; 932 return nil;
984 return [NSNumber numberWithBool: 933 return [NSNumber numberWithBool:
985 GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)]; 934 GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)];
986 } 935 }
987 936
988 - (NSNumber*)focused { 937 - (NSNumber*)focused {
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 } 1611 }
1663 1612
1664 if (selStart > selEnd) 1613 if (selStart > selEnd)
1665 std::swap(selStart, selEnd); 1614 std::swap(selStart, selEnd);
1666 1615
1667 int selLength = selEnd - selStart; 1616 int selLength = selEnd - selStart;
1668 return [NSValue valueWithRange:NSMakeRange(selStart, selLength)]; 1617 return [NSValue valueWithRange:NSMakeRange(selStart, selLength)];
1669 } 1618 }
1670 1619
1671 - (id)selectedTextMarkerRange { 1620 - (id)selectedTextMarkerRange {
1672 if (![self instanceActive]) 1621 return [[self textMarkerHelper] selectedTextMarkerRange];
1673 return nil;
1674
1675 BrowserAccessibilityManager* manager = browserAccessibility_->manager();
1676 if (!manager)
1677 return nil;
1678
1679 int32_t anchorId = manager->GetTreeData().sel_anchor_object_id;
1680 const BrowserAccessibility* anchorObject = manager->GetFromID(anchorId);
1681 if (!anchorObject)
1682 return nil;
1683
1684 int32_t focusId = manager->GetTreeData().sel_focus_object_id;
1685 const BrowserAccessibility* focusObject = manager->GetFromID(focusId);
1686 if (!focusObject)
1687 return nil;
1688
1689 int anchorOffset = manager->GetTreeData().sel_anchor_offset;
1690 int focusOffset = manager->GetTreeData().sel_focus_offset;
1691 if (anchorOffset < 0 || focusOffset < 0)
1692 return nil;
1693
1694 ui::AXTextAffinity anchorAffinity =
1695 manager->GetTreeData().sel_anchor_affinity;
1696 ui::AXTextAffinity focusAffinity = manager->GetTreeData().sel_focus_affinity;
1697
1698 return CreateTextMarkerRange(CreateTextRange(*anchorObject, anchorOffset,
1699 anchorAffinity, *focusObject,
1700 focusOffset, focusAffinity));
1701 } 1622 }
1702 1623
1703 - (NSValue*)size { 1624 - (NSValue*)size {
1704 if (![self instanceActive]) 1625 if (![self instanceActive])
1705 return nil; 1626 return nil;
1706 gfx::Rect bounds = browserAccessibility_->GetPageBoundsRect(); 1627 gfx::Rect bounds = browserAccessibility_->GetPageBoundsRect();
1707 return [NSValue valueWithSize:NSMakeSize(bounds.width(), bounds.height())]; 1628 return [NSValue valueWithSize:NSMakeSize(bounds.width(), bounds.height())];
1708 } 1629 }
1709 1630
1710 - (NSString*)sortDirection { 1631 - (NSString*)sortDirection {
(...skipping 13 matching lines...) Expand all
1724 return NSAccessibilityDescendingSortDirectionValue; 1645 return NSAccessibilityDescendingSortDirectionValue;
1725 case ui::AX_SORT_DIRECTION_OTHER: 1646 case ui::AX_SORT_DIRECTION_OTHER:
1726 return NSAccessibilityUnknownSortDirectionValue; 1647 return NSAccessibilityUnknownSortDirectionValue;
1727 default: 1648 default:
1728 NOTREACHED(); 1649 NOTREACHED();
1729 } 1650 }
1730 1651
1731 return nil; 1652 return nil;
1732 } 1653 }
1733 1654
1734 // Returns a text marker that points to the first character in the document that
1735 // can be selected with VoiceOver.
1736 - (id)startTextMarker {
1737 const BrowserAccessibility* root =
1738 browserAccessibility_->manager()->GetRoot();
1739 if (!root)
1740 return nil;
1741
1742 AXPlatformPositionInstance position = root->CreatePositionAt(0);
1743 return CreateTextMarker(position->CreatePositionAtStartOfAnchor());
1744 }
1745
1746 // Returns a subrole based upon the role. 1655 // Returns a subrole based upon the role.
1747 - (NSString*) subrole { 1656 - (NSString*) subrole {
1748 if (![self instanceActive]) 1657 if (![self instanceActive])
1749 return nil; 1658 return nil;
1750 ui::AXRole browserAccessibilityRole = [self internalRole]; 1659 ui::AXRole browserAccessibilityRole = [self internalRole];
1751 if (browserAccessibilityRole == ui::AX_ROLE_TEXT_FIELD && 1660 if (browserAccessibilityRole == ui::AX_ROLE_TEXT_FIELD &&
1752 GetState(browserAccessibility_, ui::AX_STATE_PROTECTED)) { 1661 GetState(browserAccessibility_, ui::AX_STATE_PROTECTED)) {
1753 return NSAccessibilitySecureTextFieldSubrole; 1662 return NSAccessibilitySecureTextFieldSubrole;
1754 } 1663 }
1755 1664
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
2006 NSString* value = base::SysUTF16ToNSString(browserAccessibility_->GetValue()); 1915 NSString* value = base::SysUTF16ToNSString(browserAccessibility_->GetValue());
2007 NSMutableAttributedString* attributedValue = 1916 NSMutableAttributedString* attributedValue =
2008 [[[NSMutableAttributedString alloc] initWithString:value] autorelease]; 1917 [[[NSMutableAttributedString alloc] initWithString:value] autorelease];
2009 std::vector<const BrowserAccessibility*> textOnlyObjects = 1918 std::vector<const BrowserAccessibility*> textOnlyObjects =
2010 BrowserAccessibilityManager::FindTextOnlyObjectsInRange( 1919 BrowserAccessibilityManager::FindTextOnlyObjectsInRange(
2011 *browserAccessibility_, *browserAccessibility_); 1920 *browserAccessibility_, *browserAccessibility_);
2012 AddMisspelledTextAttributes(textOnlyObjects, attributedValue); 1921 AddMisspelledTextAttributes(textOnlyObjects, attributedValue);
2013 return [attributedValue attributedSubstringFromRange:range]; 1922 return [attributedValue attributedSubstringFromRange:range];
2014 } 1923 }
2015 1924
1925 - (TextMarkerHelperMac*)textMarkerHelper {
1926 if (!textMarkerHelper_) {
1927 textMarkerHelper_.reset([[TextMarkerHelperMac alloc]
1928 initWithFactory:base::MakeUnique<BrowserPositionFactory>(
1929 browserAccessibility_)]);
1930 }
1931 return textMarkerHelper_;
1932 }
1933
2016 // Returns the accessibility value for the given attribute. If the value isn't 1934 // Returns the accessibility value for the given attribute. If the value isn't
2017 // supported this will return nil. 1935 // supported this will return nil.
2018 - (id)accessibilityAttributeValue:(NSString*)attribute { 1936 - (id)accessibilityAttributeValue:(NSString*)attribute {
2019 if (![self instanceActive]) 1937 if (![self instanceActive])
2020 return nil; 1938 return nil;
2021 1939
2022 SEL selector = 1940 SEL selector =
2023 NSSelectorFromString([self methodNameForAttribute:attribute]); 1941 NSSelectorFromString([self methodNameForAttribute:attribute]);
2024 if (selector) 1942 if (selector)
2025 return [self performSelector:selector]; 1943 return [self performSelector:selector];
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2122 } 2040 }
2123 if (colIndex == column) 2041 if (colIndex == column)
2124 return ToBrowserAccessibilityCocoa(cell); 2042 return ToBrowserAccessibilityCocoa(cell);
2125 if (colIndex > column) 2043 if (colIndex > column)
2126 break; 2044 break;
2127 } 2045 }
2128 } 2046 }
2129 return nil; 2047 return nil;
2130 } 2048 }
2131 2049
2132 if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) { 2050 SEL selector = NSSelectorFromString([attribute stringByAppendingString:@":"]);
2133 AXPlatformPositionInstance position = 2051 DCHECK(selector);
2134 CreatePositionFromTextMarker(parameter); 2052 if ([TextMarkerHelperMac instancesRespondToSelector:selector]) {
2135 if (!position->IsNullPosition()) 2053 return
2136 return ToBrowserAccessibilityCocoa(position->GetAnchor()); 2054 [[self textMarkerHelper] performSelector:selector withObject:parameter];
2137
2138 return nil;
2139 } 2055 }
2140 2056
2141 if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) { 2057 // TODO(tapted): Move the next three to TextMarkerHelper.
2142 AXPlatformPositionInstance startPosition =
2143 browserAccessibility_->CreatePositionAt(0);
2144 AXPlatformPositionInstance endPosition =
2145 startPosition->CreatePositionAtEndOfAnchor();
2146 AXPlatformRange range =
2147 AXPlatformRange(std::move(startPosition), std::move(endPosition));
2148 return CreateTextMarkerRange(std::move(range));
2149 }
2150
2151 if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) 2058 if ([attribute isEqualToString:@"AXStringForTextMarkerRange"])
2152 return GetTextForTextMarkerRange(parameter); 2059 return GetTextForTextMarkerRange(parameter);
2153 2060
2154 if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) 2061 if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
2155 return GetAttributedTextForTextMarkerRange(parameter); 2062 return GetAttributedTextForTextMarkerRange(parameter);
2156 2063
2157 if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
2158 AXPlatformPositionInstance position =
2159 CreatePositionFromTextMarker(parameter);
2160 if (position->IsNullPosition())
2161 return nil;
2162 return CreateTextMarker(position->CreateNextCharacterPosition());
2163 }
2164
2165 if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
2166 AXPlatformPositionInstance position =
2167 CreatePositionFromTextMarker(parameter);
2168 if (position->IsNullPosition())
2169 return nil;
2170 return CreateTextMarker(position->CreatePreviousCharacterPosition());
2171 }
2172
2173 if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
2174 AXPlatformPositionInstance endPosition =
2175 CreatePositionFromTextMarker(parameter);
2176 if (endPosition->IsNullPosition())
2177 return nil;
2178
2179 AXPlatformPositionInstance startWordPosition =
2180 endPosition->CreatePreviousWordStartPosition();
2181 AXPlatformPositionInstance endWordPosition =
2182 endPosition->CreatePreviousWordEndPosition();
2183 AXPlatformPositionInstance startPosition =
2184 *startWordPosition <= *endWordPosition ? std::move(endWordPosition)
2185 : std::move(startWordPosition);
2186 AXPlatformRange range(std::move(startPosition), std::move(endPosition));
2187 return CreateTextMarkerRange(std::move(range));
2188 }
2189
2190 if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
2191 AXPlatformPositionInstance startPosition =
2192 CreatePositionFromTextMarker(parameter);
2193 if (startPosition->IsNullPosition())
2194 return nil;
2195
2196 AXPlatformPositionInstance endWordPosition =
2197 startPosition->CreateNextWordEndPosition();
2198 AXPlatformPositionInstance startWordPosition =
2199 startPosition->CreateNextWordStartPosition();
2200 AXPlatformPositionInstance endPosition =
2201 *startWordPosition <= *endWordPosition ? std::move(startWordPosition)
2202 : std::move(endWordPosition);
2203 AXPlatformRange range(std::move(startPosition), std::move(endPosition));
2204 return CreateTextMarkerRange(std::move(range));
2205 }
2206
2207 if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
2208 AXPlatformPositionInstance position =
2209 CreatePositionFromTextMarker(parameter);
2210 if (position->IsNullPosition())
2211 return nil;
2212 return CreateTextMarker(position->CreateNextWordEndPosition());
2213 }
2214
2215 if ([attribute
2216 isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
2217 AXPlatformPositionInstance position =
2218 CreatePositionFromTextMarker(parameter);
2219 if (position->IsNullPosition())
2220 return nil;
2221 return CreateTextMarker(position->CreatePreviousWordStartPosition());
2222 }
2223
2224 if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
2225 AXPlatformPositionInstance position =
2226 CreatePositionFromTextMarker(parameter);
2227 if (position->IsNullPosition())
2228 return nil;
2229
2230 AXPlatformPositionInstance startPosition =
2231 position->CreatePreviousLineStartPosition();
2232 AXPlatformPositionInstance endPosition =
2233 position->CreateNextLineEndPosition();
2234 AXPlatformRange range(std::move(startPosition), std::move(endPosition));
2235 return CreateTextMarkerRange(std::move(range));
2236 }
2237
2238 if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
2239 AXPlatformPositionInstance endPosition =
2240 CreatePositionFromTextMarker(parameter);
2241 if (endPosition->IsNullPosition())
2242 return nil;
2243
2244 AXPlatformPositionInstance startLinePosition =
2245 endPosition->CreatePreviousLineStartPosition();
2246 AXPlatformPositionInstance endLinePosition =
2247 endPosition->CreatePreviousLineEndPosition();
2248 AXPlatformPositionInstance startPosition =
2249 *startLinePosition <= *endLinePosition ? std::move(endLinePosition)
2250 : std::move(startLinePosition);
2251 AXPlatformRange range(std::move(startPosition), std::move(endPosition));
2252 return CreateTextMarkerRange(std::move(range));
2253 }
2254
2255 if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
2256 AXPlatformPositionInstance startPosition =
2257 CreatePositionFromTextMarker(parameter);
2258 if (startPosition->IsNullPosition())
2259 return nil;
2260
2261 AXPlatformPositionInstance startLinePosition =
2262 startPosition->CreateNextLineStartPosition();
2263 AXPlatformPositionInstance endLinePosition =
2264 startPosition->CreateNextLineEndPosition();
2265 AXPlatformPositionInstance endPosition =
2266 *startLinePosition <= *endLinePosition ? std::move(startLinePosition)
2267 : std::move(endLinePosition);
2268 AXPlatformRange range(std::move(startPosition), std::move(endPosition));
2269 return CreateTextMarkerRange(std::move(range));
2270 }
2271
2272 if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
2273 AXPlatformPositionInstance position =
2274 CreatePositionFromTextMarker(parameter);
2275 if (position->IsNullPosition())
2276 return nil;
2277 return CreateTextMarker(position->CreateNextLineEndPosition());
2278 }
2279
2280 if ([attribute
2281 isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
2282 AXPlatformPositionInstance position =
2283 CreatePositionFromTextMarker(parameter);
2284 if (position->IsNullPosition())
2285 return nil;
2286 return CreateTextMarker(position->CreatePreviousLineStartPosition());
2287 }
2288
2289 if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) { 2064 if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
2290 NSString* text = GetTextForTextMarkerRange(parameter); 2065 NSString* text = GetTextForTextMarkerRange(parameter);
2291 return [NSNumber numberWithInt:[text length]]; 2066 return [NSNumber numberWithInt:[text length]];
2292 } 2067 }
2293 2068
2294 if ([attribute isEqualToString: 2069 if ([attribute isEqualToString:
2295 NSAccessibilityBoundsForRangeParameterizedAttribute]) { 2070 NSAccessibilityBoundsForRangeParameterizedAttribute]) {
2296 if ([self internalRole] != ui::AX_ROLE_STATIC_TEXT) 2071 if ([self internalRole] != ui::AX_ROLE_STATIC_TEXT)
2297 return nil; 2072 return nil;
2298 NSRange range = [(NSValue*)parameter rangeValue]; 2073 NSRange range = [(NSValue*)parameter rangeValue];
(...skipping 21 matching lines...) Expand all
2320 NSMutableArray* result = [NSMutableArray arrayWithCapacity:count]; 2095 NSMutableArray* result = [NSMutableArray arrayWithCapacity:count];
2321 for (size_t i = 0; i < count; ++i) { 2096 for (size_t i = 0; i < count; ++i) {
2322 BrowserAccessibility* match = search.GetMatchAtIndex(i); 2097 BrowserAccessibility* match = search.GetMatchAtIndex(i);
2323 [result addObject:ToBrowserAccessibilityCocoa(match)]; 2098 [result addObject:ToBrowserAccessibilityCocoa(match)];
2324 } 2099 }
2325 return result; 2100 return result;
2326 } 2101 }
2327 return nil; 2102 return nil;
2328 } 2103 }
2329 2104
2330 if ([attribute isEqualToString: 2105 // TODO(tapted): Move this to TextMarkerHelper.
2331 NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute ]) {
2332 AXPlatformPositionInstance position =
2333 CreatePositionFromTextMarker(parameter);
2334 if (position->IsNullPosition())
2335 return nil;
2336
2337 AXPlatformRange range(position->CreatePreviousLineStartPosition(),
2338 position->CreateNextLineEndPosition());
2339 return CreateTextMarkerRange(std::move(range));
2340 }
2341
2342 if ([attribute isEqualToString: 2106 if ([attribute isEqualToString:
2343 NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute]) { 2107 NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute]) {
2344 BrowserAccessibility* startObject; 2108 BrowserAccessibility* startObject;
2345 BrowserAccessibility* endObject; 2109 BrowserAccessibility* endObject;
2346 int startOffset, endOffset; 2110 int startOffset, endOffset;
2347 AXPlatformRange range = CreateRangeFromTextMarkerRange(parameter); 2111 AXPlatformRange range = CreateRangeFromTextMarkerRange(parameter);
2348 if (range.IsNull()) 2112 if (range.IsNull())
2349 return nil; 2113 return nil;
2350 2114
2351 startObject = range.anchor()->GetAnchor(); 2115 startObject = range.anchor()->GetAnchor();
2352 endObject = range.focus()->GetAnchor(); 2116 endObject = range.focus()->GetAnchor();
2353 startOffset = range.anchor()->text_offset(); 2117 startOffset = range.anchor()->text_offset();
2354 endOffset = range.focus()->text_offset(); 2118 endOffset = range.focus()->text_offset();
2355 DCHECK(startObject && endObject); 2119 DCHECK(startObject && endObject);
2356 DCHECK_GE(startOffset, 0); 2120 DCHECK_GE(startOffset, 0);
2357 DCHECK_GE(endOffset, 0); 2121 DCHECK_GE(endOffset, 0);
2358 2122
2359 gfx::Rect rect = BrowserAccessibilityManager::GetPageBoundsForRange( 2123 gfx::Rect rect = BrowserAccessibilityManager::GetPageBoundsForRange(
2360 *startObject, startOffset, *endObject, endOffset); 2124 *startObject, startOffset, *endObject, endOffset);
2361 NSPoint origin = NSMakePoint(rect.x(), rect.y()); 2125 NSPoint origin = NSMakePoint(rect.x(), rect.y());
2362 NSSize size = NSMakeSize(rect.width(), rect.height()); 2126 NSSize size = NSMakeSize(rect.width(), rect.height());
2363 NSPoint pointInScreen = [self pointInScreen:origin size:size]; 2127 NSPoint pointInScreen = [self pointInScreen:origin size:size];
2364 NSRect nsrect = NSMakeRect( 2128 NSRect nsrect = NSMakeRect(
2365 pointInScreen.x, pointInScreen.y, rect.width(), rect.height()); 2129 pointInScreen.x, pointInScreen.y, rect.width(), rect.height());
2366 return [NSValue valueWithRect:nsrect]; 2130 return [NSValue valueWithRect:nsrect];
2367 } 2131 }
2368 2132
2369 if ([attribute isEqualToString: 2133 if ([attribute isEqualToString:
2370 NSAccessibilityTextMarkerRangeForUnorderedTextMarkersParameterizedAtt ribute]) {
2371 if (![parameter isKindOfClass:[NSArray class]])
2372 return nil;
2373
2374 NSArray* text_marker_array = parameter;
2375 if ([text_marker_array count] != 2)
2376 return nil;
2377
2378 AXPlatformPositionInstance startPosition =
2379 CreatePositionFromTextMarker([text_marker_array objectAtIndex:0]);
2380 AXPlatformPositionInstance endPosition =
2381 CreatePositionFromTextMarker([text_marker_array objectAtIndex:1]);
2382 if (*startPosition <= *endPosition) {
2383 return CreateTextMarkerRange(
2384 AXPlatformRange(std::move(startPosition), std::move(endPosition)));
2385 } else {
2386 return CreateTextMarkerRange(
2387 AXPlatformRange(std::move(endPosition), std::move(startPosition)));
2388 }
2389 }
2390
2391 if ([attribute isEqualToString:
2392 NSAccessibilityIndexForChildUIElementParameterizedAttribute]) { 2134 NSAccessibilityIndexForChildUIElementParameterizedAttribute]) {
2393 if (![parameter isKindOfClass:[BrowserAccessibilityCocoa class]]) 2135 if (![parameter isKindOfClass:[BrowserAccessibilityCocoa class]])
2394 return nil; 2136 return nil;
2395 2137
2396 BrowserAccessibilityCocoa* childCocoaObj = 2138 BrowserAccessibilityCocoa* childCocoaObj =
2397 (BrowserAccessibilityCocoa*)parameter; 2139 (BrowserAccessibilityCocoa*)parameter;
2398 BrowserAccessibility* child = [childCocoaObj browserAccessibility]; 2140 BrowserAccessibility* child = [childCocoaObj browserAccessibility];
2399 if (!child) 2141 if (!child)
2400 return nil; 2142 return nil;
2401 2143
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
2878 } 2620 }
2879 2621
2880 - (BOOL)accessibilityNotifiesWhenDestroyed { 2622 - (BOOL)accessibilityNotifiesWhenDestroyed {
2881 // Indicate that BrowserAccessibilityCocoa will post a notification when it's 2623 // Indicate that BrowserAccessibilityCocoa will post a notification when it's
2882 // destroyed (see -detach). This allows VoiceOver to do some internal things 2624 // destroyed (see -detach). This allows VoiceOver to do some internal things
2883 // more efficiently. 2625 // more efficiently.
2884 return YES; 2626 return YES;
2885 } 2627 }
2886 2628
2887 @end 2629 @end
2630
2631 ui::AXPositionPointer BrowserPositionFactory::GetRoot() const {
2632 const BrowserAccessibility* root =
2633 browser_accessibility_->manager()->GetRoot();
2634 if (!root)
2635 return nullptr;
2636
2637 return root->CreatePositionAt(0);
2638 }
2639
2640 ui::AXRangePointer BrowserPositionFactory::GetSelection() const {
2641 if (!IsActive())
2642 return ui::AXRangePointer(nullptr, nullptr);
2643
2644 BrowserAccessibilityManager* manager = browser_accessibility_->manager();
2645 if (!manager)
2646 return ui::AXRangePointer(nullptr, nullptr);
2647
2648 int32_t anchor_id = manager->GetTreeData().sel_anchor_object_id;
2649 const BrowserAccessibility* anchor_object = manager->GetFromID(anchor_id);
2650 if (!anchor_object)
2651 return ui::AXRangePointer(nullptr, nullptr);
2652
2653 int32_t focus_id = manager->GetTreeData().sel_focus_object_id;
2654 const BrowserAccessibility* focusObject = manager->GetFromID(focus_id);
2655 if (!focusObject)
2656 return ui::AXRangePointer(nullptr, nullptr);
2657
2658 int anchor_offset = manager->GetTreeData().sel_anchor_offset;
2659 int focus_offset = manager->GetTreeData().sel_focus_offset;
2660 if (anchor_offset < 0 || focus_offset < 0)
2661 return ui::AXRangePointer(nullptr, nullptr);
2662
2663 ui::AXTextAffinity anchorAffinity =
2664 manager->GetTreeData().sel_anchor_affinity;
2665 ui::AXTextAffinity focusAffinity = manager->GetTreeData().sel_focus_affinity;
2666
2667 return CreateTextRange(*anchor_object, anchor_offset, anchorAffinity,
2668 *focusObject, focus_offset, focusAffinity);
2669 }
2670
2671 ui::AXPositionPointer BrowserPositionFactory::GetFromData(
2672 const ui::AXPositionData& data) const {
2673 return AXPlatformPosition::CreateFromData(data);
2674 }
2675
2676 id BrowserPositionFactory::GetAccessibilityObject(
2677 const ui::AXPositionData& data) const {
2678 AXPlatformPositionInstance position =
2679 AXPlatformPosition::CreateFromData(data);
2680 if (!position->IsNullPosition())
2681 return ToBrowserAccessibilityCocoa(position->GetAnchor());
2682
2683 return nil;
2684 }
OLDNEW
« no previous file with comments | « base/mac/foundation_util.mm ('k') | ui/accessibility/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698