Index: content/browser/accessibility/browser_accessibility_cocoa.mm |
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm |
index 2698d30c785d5b46b8259a9346cfe8147a84e49c..5e96f632217c176e2aba374dc7943076f7452ac5 100644 |
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm |
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm |
@@ -15,6 +15,7 @@ |
#include "base/mac/foundation_util.h" |
#include "base/mac/scoped_cftyperef.h" |
+#include "base/memory/ptr_util.h" |
#include "base/strings/string16.h" |
#include "base/strings/sys_string_conversions.h" |
#include "base/strings/utf_string_conversions.h" |
@@ -28,12 +29,11 @@ |
#include "third_party/skia/include/core/SkColor.h" |
#include "ui/accessibility/ax_range.h" |
#import "ui/accessibility/platform/ax_platform_node_mac.h" |
+#import "ui/accessibility/platform/text_marker_helper_mac.h" |
using AXPlatformPositionInstance = |
content::AXPlatformPosition::AXPositionInstance; |
using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>; |
-using AXTextMarkerRangeRef = CFTypeRef; |
-using AXTextMarkerRef = CFTypeRef; |
using StringAttribute = ui::AXStringAttribute; |
using content::AXPlatformPosition; |
using content::AccessibilityMatchPredicate; |
@@ -111,93 +111,38 @@ NSDictionary* attributeToMethodNameMap = nil; |
// VoiceOver uses -1 to mean "no limit" for AXResultsLimit. |
const int kAXResultsLimitNoLimit = -1; |
-extern "C" { |
- |
-// The following are private accessibility APIs required for cursor navigation |
-// and text selection. VoiceOver started relying on them in Mac OS X 10.11. |
-#if !defined(MAC_OS_X_VERSION_10_11) || \ |
- MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 |
- |
-AXTextMarkerRef AXTextMarkerCreate(CFAllocatorRef allocator, |
- const UInt8* bytes, |
- CFIndex length); |
- |
-const UInt8* AXTextMarkerGetBytePtr(AXTextMarkerRef text_marker); |
- |
-size_t AXTextMarkerGetLength(AXTextMarkerRef text_marker); |
- |
-AXTextMarkerRangeRef AXTextMarkerRangeCreate(CFAllocatorRef allocator, |
- AXTextMarkerRef start_marker, |
- AXTextMarkerRef end_marker); |
- |
-AXTextMarkerRef AXTextMarkerRangeCopyStartMarker( |
- AXTextMarkerRangeRef text_marker_range); |
- |
-AXTextMarkerRef AXTextMarkerRangeCopyEndMarker( |
- AXTextMarkerRangeRef text_marker_range); |
- |
-#endif // MAC_OS_X_VERSION_10_11 |
+class BrowserPositionFactory : public ui::PositionFactory { |
+ public: |
+ explicit BrowserPositionFactory( |
+ content::BrowserAccessibility* browser_accessibility) |
+ : browser_accessibility_(browser_accessibility) {} |
-} // extern "C" |
+ ui::AXPositionPointer GetRoot() const override; |
+ ui::AXRangePointer GetSelection() const override; |
+ ui::AXPositionPointer GetFromData( |
+ const ui::AXPositionData& data) const override; |
+ id GetAccessibilityObject(const ui::AXPositionData& data) const override; |
-// AXTextMarkerCreate copies from data buffer given to it. |
-id CreateTextMarker(AXPlatformPositionInstance position) { |
- AXTextMarkerRef text_marker = AXTextMarkerCreate( |
- kCFAllocatorDefault, reinterpret_cast<const UInt8*>(position.get()), |
- sizeof(AXPlatformPosition)); |
- return static_cast<id>( |
- base::mac::CFTypeRefToNSObjectAutorelease(text_marker)); |
-} |
+ private: |
+ bool IsActive() const { |
+ return browser_accessibility_ && browser_accessibility_->instance_active(); |
+ } |
-// |range| is destructed at the end of this method. |anchor| and |focus| are |
-// copied into the individual text markers. |
-id CreateTextMarkerRange(const AXPlatformRange range) { |
- base::ScopedCFTypeRef<AXTextMarkerRef> start_marker(AXTextMarkerCreate( |
- kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.anchor()), |
- sizeof(AXPlatformPosition))); |
- base::ScopedCFTypeRef<AXTextMarkerRef> end_marker(AXTextMarkerCreate( |
- kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.focus()), |
- sizeof(AXPlatformPosition))); |
- AXTextMarkerRangeRef marker_range = |
- AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker); |
- return static_cast<id>( |
- base::mac::CFTypeRefToNSObjectAutorelease(marker_range)); |
-} |
+ content::BrowserAccessibility* browser_accessibility_; |
-AXPlatformPositionInstance CreatePositionFromTextMarker( |
- AXTextMarkerRef text_marker) { |
- DCHECK(text_marker); |
- if (AXTextMarkerGetLength(text_marker) != sizeof(AXPlatformPosition)) |
- return AXPlatformPosition::CreateNullPosition(); |
- const UInt8* source_buffer = AXTextMarkerGetBytePtr(text_marker); |
- if (!source_buffer) |
- return AXPlatformPosition::CreateNullPosition(); |
- UInt8* destination_buffer = new UInt8[sizeof(AXPlatformPosition)]; |
- std::memcpy(destination_buffer, source_buffer, sizeof(AXPlatformPosition)); |
- AXPlatformPosition::AXPositionInstance position( |
- reinterpret_cast<AXPlatformPosition::AXPositionInstance::pointer>( |
- destination_buffer)); |
- if (!position) |
- return AXPlatformPosition::CreateNullPosition(); |
- return position; |
-} |
+ DISALLOW_COPY_AND_ASSIGN(BrowserPositionFactory); |
+}; |
-AXPlatformRange CreateRangeFromTextMarkerRange( |
- AXTextMarkerRangeRef marker_range) { |
- DCHECK(marker_range); |
- base::ScopedCFTypeRef<AXTextMarkerRef> start_marker( |
- AXTextMarkerRangeCopyStartMarker(marker_range)); |
- base::ScopedCFTypeRef<AXTextMarkerRef> end_marker( |
- AXTextMarkerRangeCopyEndMarker(marker_range)); |
- if (!start_marker.get() || !end_marker.get()) |
+AXPlatformRange CreateRangeFromTextMarkerRange(id marker_range) { |
+ ui::AXPositionData start, end; |
+ if (![TextMarkerHelperMac getRangeDataFromMarkerRange:marker_range |
+ start:&start |
+ end:&end]) { |
return AXPlatformRange(); |
+ } |
- AXPlatformPositionInstance anchor = |
- CreatePositionFromTextMarker(start_marker.get()); |
- AXPlatformPositionInstance focus = |
- CreatePositionFromTextMarker(end_marker.get()); |
- // |AXPlatformRange| takes ownership of its anchor and focus. |
- return AXPlatformRange(std::move(anchor), std::move(focus)); |
+ return AXPlatformRange(AXPlatformPosition::CreateFromData(start), |
+ AXPlatformPosition::CreateFromData(end)); |
} |
AXPlatformPositionInstance CreateTextPosition( |
@@ -213,18 +158,18 @@ AXPlatformPositionInstance CreateTextPosition( |
manager->ax_tree_id(), object.GetId(), offset, affinity); |
} |
-AXPlatformRange CreateTextRange(const BrowserAccessibility& start_object, |
- int start_offset, |
- ui::AXTextAffinity start_affinity, |
- const BrowserAccessibility& end_object, |
- int end_offset, |
- ui::AXTextAffinity end_affinity) { |
+ui::AXRangePointer CreateTextRange(const BrowserAccessibility& start_object, |
+ int start_offset, |
+ ui::AXTextAffinity start_affinity, |
+ const BrowserAccessibility& end_object, |
+ int end_offset, |
+ ui::AXTextAffinity end_affinity) { |
AXPlatformPositionInstance anchor = |
CreateTextPosition(start_object, start_offset, start_affinity); |
AXPlatformPositionInstance focus = |
CreateTextPosition(end_object, end_offset, end_affinity); |
- // |AXPlatformRange| takes ownership of its anchor and focus. |
- return AXPlatformRange(std::move(anchor), std::move(focus)); |
+ // |AXRangePointer| takes ownership of its anchor and focus. |
+ return ui::AXRangePointer(std::move(anchor), std::move(focus)); |
} |
void AddMisspelledTextAttributes( |
@@ -257,15 +202,14 @@ void AddMisspelledTextAttributes( |
[attributed_string endEditing]; |
} |
-NSString* GetTextForTextMarkerRange(AXTextMarkerRangeRef marker_range) { |
+NSString* GetTextForTextMarkerRange(id marker_range) { |
AXPlatformRange range = CreateRangeFromTextMarkerRange(marker_range); |
if (range.IsNull()) |
return nil; |
return base::SysUTF16ToNSString(range.GetText()); |
} |
-NSAttributedString* GetAttributedTextForTextMarkerRange( |
- AXTextMarkerRangeRef marker_range) { |
+NSAttributedString* GetAttributedTextForTextMarkerRange(id marker_range) { |
BrowserAccessibility* start_object; |
BrowserAccessibility* end_object; |
int start_offset, end_offset; |
@@ -523,7 +467,16 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
} |
#endif // MAC_OS_X_VERSION_10_12 |
-@implementation BrowserAccessibilityCocoa |
+@interface BrowserAccessibilityCocoa () |
+ |
+// Lazily creates a TextMarkerHelper and returns it. |
+- (TextMarkerHelperMac*)textMarkerHelper; |
+ |
+@end |
+ |
+@implementation BrowserAccessibilityCocoa { |
+ base::scoped_nsobject<TextMarkerHelperMac> textMarkerHelper_; |
+} |
+ (void)initialize { |
const struct { |
@@ -966,16 +919,12 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
!GetState(browserAccessibility_, ui::AX_STATE_DISABLED)]; |
} |
-// Returns a text marker that points to the last character in the document that |
-// can be selected with VoiceOver. |
-- (id)endTextMarker { |
- const BrowserAccessibility* root = |
- browserAccessibility_->manager()->GetRoot(); |
- if (!root) |
- return nil; |
+- (id)startTextMarker { |
+ return [[self textMarkerHelper] startTextMarker]; |
+} |
- AXPlatformPositionInstance position = root->CreatePositionAt(0); |
- return CreateTextMarker(position->CreatePositionAtEndOfAnchor()); |
+- (id)endTextMarker { |
+ return [[self textMarkerHelper] endTextMarker]; |
} |
- (NSNumber*)expanded { |
@@ -1669,35 +1618,7 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
} |
- (id)selectedTextMarkerRange { |
- if (![self instanceActive]) |
- return nil; |
- |
- BrowserAccessibilityManager* manager = browserAccessibility_->manager(); |
- if (!manager) |
- return nil; |
- |
- int32_t anchorId = manager->GetTreeData().sel_anchor_object_id; |
- const BrowserAccessibility* anchorObject = manager->GetFromID(anchorId); |
- if (!anchorObject) |
- return nil; |
- |
- int32_t focusId = manager->GetTreeData().sel_focus_object_id; |
- const BrowserAccessibility* focusObject = manager->GetFromID(focusId); |
- if (!focusObject) |
- return nil; |
- |
- int anchorOffset = manager->GetTreeData().sel_anchor_offset; |
- int focusOffset = manager->GetTreeData().sel_focus_offset; |
- if (anchorOffset < 0 || focusOffset < 0) |
- return nil; |
- |
- ui::AXTextAffinity anchorAffinity = |
- manager->GetTreeData().sel_anchor_affinity; |
- ui::AXTextAffinity focusAffinity = manager->GetTreeData().sel_focus_affinity; |
- |
- return CreateTextMarkerRange(CreateTextRange(*anchorObject, anchorOffset, |
- anchorAffinity, *focusObject, |
- focusOffset, focusAffinity)); |
+ return [[self textMarkerHelper] selectedTextMarkerRange]; |
} |
- (NSValue*)size { |
@@ -1731,18 +1652,6 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
return nil; |
} |
-// Returns a text marker that points to the first character in the document that |
-// can be selected with VoiceOver. |
-- (id)startTextMarker { |
- const BrowserAccessibility* root = |
- browserAccessibility_->manager()->GetRoot(); |
- if (!root) |
- return nil; |
- |
- AXPlatformPositionInstance position = root->CreatePositionAt(0); |
- return CreateTextMarker(position->CreatePositionAtStartOfAnchor()); |
-} |
- |
// Returns a subrole based upon the role. |
- (NSString*) subrole { |
if (![self instanceActive]) |
@@ -2013,6 +1922,15 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
return [attributedValue attributedSubstringFromRange:range]; |
} |
+- (TextMarkerHelperMac*)textMarkerHelper { |
+ if (!textMarkerHelper_) { |
+ textMarkerHelper_.reset([[TextMarkerHelperMac alloc] |
+ initWithFactory:base::MakeUnique<BrowserPositionFactory>( |
+ browserAccessibility_)]); |
+ } |
+ return textMarkerHelper_; |
+} |
+ |
// Returns the accessibility value for the given attribute. If the value isn't |
// supported this will return nil. |
- (id)accessibilityAttributeValue:(NSString*)attribute { |
@@ -2129,163 +2047,20 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
return nil; |
} |
- if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (!position->IsNullPosition()) |
- return ToBrowserAccessibilityCocoa(position->GetAnchor()); |
- |
- return nil; |
- } |
- |
- if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) { |
- AXPlatformPositionInstance startPosition = |
- browserAccessibility_->CreatePositionAt(0); |
- AXPlatformPositionInstance endPosition = |
- startPosition->CreatePositionAtEndOfAnchor(); |
- AXPlatformRange range = |
- AXPlatformRange(std::move(startPosition), std::move(endPosition)); |
- return CreateTextMarkerRange(std::move(range)); |
+ SEL selector = NSSelectorFromString([attribute stringByAppendingString:@":"]); |
+ DCHECK(selector); |
+ if ([TextMarkerHelperMac instancesRespondToSelector:selector]) { |
+ return |
+ [[self textMarkerHelper] performSelector:selector withObject:parameter]; |
} |
+ // TODO(tapted): Move the next three to TextMarkerHelper. |
if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) |
return GetTextForTextMarkerRange(parameter); |
if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) |
return GetAttributedTextForTextMarkerRange(parameter); |
- if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (position->IsNullPosition()) |
- return nil; |
- return CreateTextMarker(position->CreateNextCharacterPosition()); |
- } |
- |
- if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (position->IsNullPosition()) |
- return nil; |
- return CreateTextMarker(position->CreatePreviousCharacterPosition()); |
- } |
- |
- if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) { |
- AXPlatformPositionInstance endPosition = |
- CreatePositionFromTextMarker(parameter); |
- if (endPosition->IsNullPosition()) |
- return nil; |
- |
- AXPlatformPositionInstance startWordPosition = |
- endPosition->CreatePreviousWordStartPosition(); |
- AXPlatformPositionInstance endWordPosition = |
- endPosition->CreatePreviousWordEndPosition(); |
- AXPlatformPositionInstance startPosition = |
- *startWordPosition <= *endWordPosition ? std::move(endWordPosition) |
- : std::move(startWordPosition); |
- AXPlatformRange range(std::move(startPosition), std::move(endPosition)); |
- return CreateTextMarkerRange(std::move(range)); |
- } |
- |
- if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) { |
- AXPlatformPositionInstance startPosition = |
- CreatePositionFromTextMarker(parameter); |
- if (startPosition->IsNullPosition()) |
- return nil; |
- |
- AXPlatformPositionInstance endWordPosition = |
- startPosition->CreateNextWordEndPosition(); |
- AXPlatformPositionInstance startWordPosition = |
- startPosition->CreateNextWordStartPosition(); |
- AXPlatformPositionInstance endPosition = |
- *startWordPosition <= *endWordPosition ? std::move(startWordPosition) |
- : std::move(endWordPosition); |
- AXPlatformRange range(std::move(startPosition), std::move(endPosition)); |
- return CreateTextMarkerRange(std::move(range)); |
- } |
- |
- if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (position->IsNullPosition()) |
- return nil; |
- return CreateTextMarker(position->CreateNextWordEndPosition()); |
- } |
- |
- if ([attribute |
- isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (position->IsNullPosition()) |
- return nil; |
- return CreateTextMarker(position->CreatePreviousWordStartPosition()); |
- } |
- |
- if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (position->IsNullPosition()) |
- return nil; |
- |
- AXPlatformPositionInstance startPosition = |
- position->CreatePreviousLineStartPosition(); |
- AXPlatformPositionInstance endPosition = |
- position->CreateNextLineEndPosition(); |
- AXPlatformRange range(std::move(startPosition), std::move(endPosition)); |
- return CreateTextMarkerRange(std::move(range)); |
- } |
- |
- if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) { |
- AXPlatformPositionInstance endPosition = |
- CreatePositionFromTextMarker(parameter); |
- if (endPosition->IsNullPosition()) |
- return nil; |
- |
- AXPlatformPositionInstance startLinePosition = |
- endPosition->CreatePreviousLineStartPosition(); |
- AXPlatformPositionInstance endLinePosition = |
- endPosition->CreatePreviousLineEndPosition(); |
- AXPlatformPositionInstance startPosition = |
- *startLinePosition <= *endLinePosition ? std::move(endLinePosition) |
- : std::move(startLinePosition); |
- AXPlatformRange range(std::move(startPosition), std::move(endPosition)); |
- return CreateTextMarkerRange(std::move(range)); |
- } |
- |
- if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) { |
- AXPlatformPositionInstance startPosition = |
- CreatePositionFromTextMarker(parameter); |
- if (startPosition->IsNullPosition()) |
- return nil; |
- |
- AXPlatformPositionInstance startLinePosition = |
- startPosition->CreateNextLineStartPosition(); |
- AXPlatformPositionInstance endLinePosition = |
- startPosition->CreateNextLineEndPosition(); |
- AXPlatformPositionInstance endPosition = |
- *startLinePosition <= *endLinePosition ? std::move(startLinePosition) |
- : std::move(endLinePosition); |
- AXPlatformRange range(std::move(startPosition), std::move(endPosition)); |
- return CreateTextMarkerRange(std::move(range)); |
- } |
- |
- if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (position->IsNullPosition()) |
- return nil; |
- return CreateTextMarker(position->CreateNextLineEndPosition()); |
- } |
- |
- if ([attribute |
- isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (position->IsNullPosition()) |
- return nil; |
- return CreateTextMarker(position->CreatePreviousLineStartPosition()); |
- } |
- |
if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) { |
NSString* text = GetTextForTextMarkerRange(parameter); |
return [NSNumber numberWithInt:[text length]]; |
@@ -2327,18 +2102,7 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
return nil; |
} |
- if ([attribute isEqualToString: |
- NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute]) { |
- AXPlatformPositionInstance position = |
- CreatePositionFromTextMarker(parameter); |
- if (position->IsNullPosition()) |
- return nil; |
- |
- AXPlatformRange range(position->CreatePreviousLineStartPosition(), |
- position->CreateNextLineEndPosition()); |
- return CreateTextMarkerRange(std::move(range)); |
- } |
- |
+ // TODO(tapted): Move this to TextMarkerHelper. |
if ([attribute isEqualToString: |
NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute]) { |
BrowserAccessibility* startObject; |
@@ -2367,28 +2131,6 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
} |
if ([attribute isEqualToString: |
- NSAccessibilityTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute]) { |
- if (![parameter isKindOfClass:[NSArray class]]) |
- return nil; |
- |
- NSArray* text_marker_array = parameter; |
- if ([text_marker_array count] != 2) |
- return nil; |
- |
- AXPlatformPositionInstance startPosition = |
- CreatePositionFromTextMarker([text_marker_array objectAtIndex:0]); |
- AXPlatformPositionInstance endPosition = |
- CreatePositionFromTextMarker([text_marker_array objectAtIndex:1]); |
- if (*startPosition <= *endPosition) { |
- return CreateTextMarkerRange( |
- AXPlatformRange(std::move(startPosition), std::move(endPosition))); |
- } else { |
- return CreateTextMarkerRange( |
- AXPlatformRange(std::move(endPosition), std::move(startPosition))); |
- } |
- } |
- |
- if ([attribute isEqualToString: |
NSAccessibilityIndexForChildUIElementParameterizedAttribute]) { |
if (![parameter isKindOfClass:[BrowserAccessibilityCocoa class]]) |
return nil; |
@@ -2885,3 +2627,58 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired"; |
} |
@end |
+ |
+ui::AXPositionPointer BrowserPositionFactory::GetRoot() const { |
+ const BrowserAccessibility* root = |
+ browser_accessibility_->manager()->GetRoot(); |
+ if (!root) |
+ return nullptr; |
+ |
+ return root->CreatePositionAt(0); |
+} |
+ |
+ui::AXRangePointer BrowserPositionFactory::GetSelection() const { |
+ if (!IsActive()) |
+ return ui::AXRangePointer(nullptr, nullptr); |
+ |
+ BrowserAccessibilityManager* manager = browser_accessibility_->manager(); |
+ if (!manager) |
+ return ui::AXRangePointer(nullptr, nullptr); |
+ |
+ int32_t anchor_id = manager->GetTreeData().sel_anchor_object_id; |
+ const BrowserAccessibility* anchor_object = manager->GetFromID(anchor_id); |
+ if (!anchor_object) |
+ return ui::AXRangePointer(nullptr, nullptr); |
+ |
+ int32_t focus_id = manager->GetTreeData().sel_focus_object_id; |
+ const BrowserAccessibility* focusObject = manager->GetFromID(focus_id); |
+ if (!focusObject) |
+ return ui::AXRangePointer(nullptr, nullptr); |
+ |
+ int anchor_offset = manager->GetTreeData().sel_anchor_offset; |
+ int focus_offset = manager->GetTreeData().sel_focus_offset; |
+ if (anchor_offset < 0 || focus_offset < 0) |
+ return ui::AXRangePointer(nullptr, nullptr); |
+ |
+ ui::AXTextAffinity anchorAffinity = |
+ manager->GetTreeData().sel_anchor_affinity; |
+ ui::AXTextAffinity focusAffinity = manager->GetTreeData().sel_focus_affinity; |
+ |
+ return CreateTextRange(*anchor_object, anchor_offset, anchorAffinity, |
+ *focusObject, focus_offset, focusAffinity); |
+} |
+ |
+ui::AXPositionPointer BrowserPositionFactory::GetFromData( |
+ const ui::AXPositionData& data) const { |
+ return AXPlatformPosition::CreateFromData(data); |
+} |
+ |
+id BrowserPositionFactory::GetAccessibilityObject( |
+ const ui::AXPositionData& data) const { |
+ AXPlatformPositionInstance position = |
+ AXPlatformPosition::CreateFromData(data); |
+ if (!position->IsNullPosition()) |
+ return ToBrowserAccessibilityCocoa(position->GetAnchor()); |
+ |
+ return nil; |
+} |