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

Unified Diff: content/browser/accessibility/browser_accessibility_cocoa.mm

Issue 2940923003: a11y: Move CreateTextMarker[Range] to TextMarkerHelperMac.
Patch Set: self review 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 side-by-side diff with in-line comments
Download patch
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 bf5b5e2821bf9caeba7286cfb6972a1b00ea3d41..6ac825d1b12dfa5000e0fa1efac5d464272ff728 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -28,14 +28,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 AXAbstractPositionInstance =
- content::AXPlatformPosition::AXPositionInstance;
using AXPlatformPositionInstance =
content::AXPlatformPosition::ConcreteInstance;
using AXPlatformRange = ui::AXRange<AXPlatformPositionInstance::element_type>;
-using AXTextMarkerRangeRef = CFTypeRef;
-using AXTextMarkerRef = CFTypeRef;
using StringAttribute = ui::AXStringAttribute;
using content::AXPlatformPosition;
using content::AccessibilityMatchPredicate;
@@ -113,63 +110,30 @@ 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);
+static_assert(sizeof(AXPlatformPosition) == sizeof(ui::AXPositionBase),
+ "AXPosition size mismatch");
+constexpr size_t kAXPositionSize = sizeof(ui::AXPositionBase);
-AXTextMarkerRef AXTextMarkerRangeCopyEndMarker(
- AXTextMarkerRangeRef text_marker_range);
+class BrowserPositionFactory : public ui::PositionFactory {
+ public:
+ explicit BrowserPositionFactory(
+ content::BrowserAccessibility* browser_accessibility)
+ : browser_accessibility_(browser_accessibility) {}
-#endif // MAC_OS_X_VERSION_10_11
+ std::unique_ptr<ui::AXPositionBase> GetRoot() const override;
+ std::unique_ptr<ui::AXAbstractRange> GetSelection() const override;
+ std::unique_ptr<ui::AXPositionBase> ExtractFromMarker(
+ AXTextMarkerRef marker) const override;
-} // extern "C"
+ private:
+ bool IsActive() const {
+ return browser_accessibility_ && browser_accessibility_->instance_active();
+ }
-static_assert(sizeof(AXPlatformPosition) == sizeof(ui::AXPositionBase),
- "AXPosition size mismatch");
-constexpr size_t kAXPositionSize = sizeof(ui::AXPositionBase);
+ content::BrowserAccessibility* browser_accessibility_;
-// to call |release| on it to transfer ownership of the position to the text
-// marker object.
-id CreateTextMarker(AXAbstractPositionInstance position) {
- AXTextMarkerRef text_marker = AXTextMarkerCreate(
- kCFAllocatorDefault, reinterpret_cast<const UInt8*>(position.release()),
- kAXPositionSize);
- return static_cast<id>(
- base::mac::CFTypeRefToNSObjectAutorelease(text_marker));
-}
-
-// |range| is destructed at the end of this method and ownership of its |anchor|
-// and |focus| are transfered to the marker range object.
-id CreateTextMarkerRange(const ui::AXAbstractRange range) {
- AXTextMarkerRef start_marker = AXTextMarkerCreate(
- kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.anchor()),
- kAXPositionSize);
- AXTextMarkerRef end_marker = AXTextMarkerCreate(
- kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.focus()),
- kAXPositionSize);
- AXTextMarkerRangeRef marker_range =
- AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker);
- return static_cast<id>(
- base::mac::CFTypeRefToNSObjectAutorelease(marker_range));
-}
+ DISALLOW_COPY_AND_ASSIGN(BrowserPositionFactory);
+};
AXPlatformPositionInstance CreateConcretePositionFromTextMarker(
AXTextMarkerRef text_marker) {
@@ -189,12 +153,6 @@ AXPlatformPositionInstance CreateConcretePositionFromTextMarker(
return position;
}
-AXAbstractPositionInstance CreatePositionFromTextMarker(
- AXTextMarkerRef text_marker) {
- return base::WrapUnique(
- CreateConcretePositionFromTextMarker(text_marker).release());
-}
-
AXPlatformRange CreateRangeFromTextMarkerRange(
AXTextMarkerRangeRef marker_range) {
DCHECK(marker_range);
@@ -536,7 +494,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 {
@@ -979,16 +946,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;
+ return [[self textMarkerHelper] endTextMarker];
+}
- AXAbstractPositionInstance position = root->CreatePositionAt(0);
- return CreateTextMarker(position->CreatePositionAtEndOfAnchor());
+- (id)startTextMarker {
tapted 2017/06/19 11:44:30 (self review: swap order with endTextMarker)
+ return [[self textMarkerHelper] startTextMarker];
}
- (NSNumber*)expanded {
@@ -1682,35 +1645,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 {
@@ -1744,18 +1679,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;
-
- AXAbstractPositionInstance position = root->CreatePositionAt(0);
- return CreateTextMarker(position->CreatePositionAtStartOfAnchor());
-}
-
// Returns a subrole based upon the role.
- (NSString*) subrole {
if (![self instanceActive])
@@ -2026,6 +1949,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 {
@@ -2142,165 +2074,35 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired";
return nil;
}
+ SEL selector = NSSelectorFromString(attribute);
tapted 2017/06/19 11:44:30 (self review: this needs a colon appended to the s
+ DCHECK(selector);
+ if ([TextMarkerHelperMac instancesRespondToSelector:selector]) {
+ return
+ [[self textMarkerHelper] performSelector:selector withObject:parameter];
+ }
+
if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
- AXPlatformPositionInstance position =
- CreateConcretePositionFromTextMarker(parameter);
+ AXPlatformPositionInstance position = CreateConcretePositionFromTextMarker(
+ base::mac::CFCastStrict<AXTextMarkerRef>(parameter));
if (!position->IsNullPosition())
return ToBrowserAccessibilityCocoa(position->GetAnchor());
return nil;
}
- if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
- AXAbstractPositionInstance startPosition =
- browserAccessibility_->CreatePositionAt(0);
- AXAbstractPositionInstance endPosition =
- startPosition->CreatePositionAtEndOfAnchor();
- ui::AXAbstractRange range =
- ui::AXAbstractRange(std::move(startPosition), std::move(endPosition));
- return CreateTextMarkerRange(std::move(range));
+ if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) {
+ return GetTextForTextMarkerRange(
+ base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter));
}
- if ([attribute isEqualToString:@"AXStringForTextMarkerRange"])
- return GetTextForTextMarkerRange(parameter);
-
- if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
- return GetAttributedTextForTextMarkerRange(parameter);
-
- if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
- AXAbstractPositionInstance position =
- CreatePositionFromTextMarker(parameter);
- if (position->IsNullPosition())
- return nil;
- return CreateTextMarker(position->CreateNextCharacterPosition());
- }
-
- if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
- AXAbstractPositionInstance position =
- CreatePositionFromTextMarker(parameter);
- if (position->IsNullPosition())
- return nil;
- return CreateTextMarker(position->CreatePreviousCharacterPosition());
- }
-
- if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
- AXAbstractPositionInstance endPosition =
- CreatePositionFromTextMarker(parameter);
- if (endPosition->IsNullPosition())
- return nil;
-
- AXAbstractPositionInstance startWordPosition =
- endPosition->CreatePreviousWordStartPosition();
- AXAbstractPositionInstance endWordPosition =
- endPosition->CreatePreviousWordEndPosition();
- AXAbstractPositionInstance startPosition =
- *startWordPosition <= *endWordPosition ? std::move(endWordPosition)
- : std::move(startWordPosition);
- ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
- return CreateTextMarkerRange(std::move(range));
- }
-
- if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
- AXAbstractPositionInstance startPosition =
- CreatePositionFromTextMarker(parameter);
- if (startPosition->IsNullPosition())
- return nil;
-
- AXAbstractPositionInstance endWordPosition =
- startPosition->CreateNextWordEndPosition();
- AXAbstractPositionInstance startWordPosition =
- startPosition->CreateNextWordStartPosition();
- AXAbstractPositionInstance endPosition =
- *startWordPosition <= *endWordPosition ? std::move(startWordPosition)
- : std::move(endWordPosition);
- ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
- return CreateTextMarkerRange(std::move(range));
- }
-
- if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
- AXAbstractPositionInstance position =
- CreatePositionFromTextMarker(parameter);
- if (position->IsNullPosition())
- return nil;
- return CreateTextMarker(position->CreateNextWordEndPosition());
- }
-
- if ([attribute
- isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
- AXAbstractPositionInstance position =
- CreatePositionFromTextMarker(parameter);
- if (position->IsNullPosition())
- return nil;
- return CreateTextMarker(position->CreatePreviousWordStartPosition());
- }
-
- if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
- AXAbstractPositionInstance position =
- CreatePositionFromTextMarker(parameter);
- if (position->IsNullPosition())
- return nil;
-
- AXAbstractPositionInstance startPosition =
- position->CreatePreviousLineStartPosition();
- AXAbstractPositionInstance endPosition =
- position->CreateNextLineEndPosition();
- ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
- return CreateTextMarkerRange(std::move(range));
- }
-
- if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
- AXAbstractPositionInstance endPosition =
- CreatePositionFromTextMarker(parameter);
- if (endPosition->IsNullPosition())
- return nil;
-
- AXAbstractPositionInstance startLinePosition =
- endPosition->CreatePreviousLineStartPosition();
- AXAbstractPositionInstance endLinePosition =
- endPosition->CreatePreviousLineEndPosition();
- AXAbstractPositionInstance startPosition =
- *startLinePosition <= *endLinePosition ? std::move(endLinePosition)
- : std::move(startLinePosition);
- ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
- return CreateTextMarkerRange(std::move(range));
- }
-
- if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
- AXAbstractPositionInstance startPosition =
- CreatePositionFromTextMarker(parameter);
- if (startPosition->IsNullPosition())
- return nil;
-
- AXAbstractPositionInstance startLinePosition =
- startPosition->CreateNextLineStartPosition();
- AXAbstractPositionInstance endLinePosition =
- startPosition->CreateNextLineEndPosition();
- AXAbstractPositionInstance endPosition =
- *startLinePosition <= *endLinePosition ? std::move(startLinePosition)
- : std::move(endLinePosition);
- ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
- return CreateTextMarkerRange(std::move(range));
- }
-
- if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
- AXAbstractPositionInstance position =
- CreatePositionFromTextMarker(parameter);
- if (position->IsNullPosition())
- return nil;
- return CreateTextMarker(position->CreateNextLineEndPosition());
- }
-
- if ([attribute
- isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
- AXAbstractPositionInstance position =
- CreatePositionFromTextMarker(parameter);
- if (position->IsNullPosition())
- return nil;
- return CreateTextMarker(position->CreatePreviousLineStartPosition());
+ if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) {
+ return GetAttributedTextForTextMarkerRange(
+ base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter));
}
if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
- NSString* text = GetTextForTextMarkerRange(parameter);
+ NSString* text = GetTextForTextMarkerRange(
+ base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter));
return [NSNumber numberWithInt:[text length]];
}
@@ -2340,24 +2142,14 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired";
return nil;
}
- if ([attribute isEqualToString:
- NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute]) {
- AXAbstractPositionInstance position =
- CreatePositionFromTextMarker(parameter);
- if (position->IsNullPosition())
- return nil;
-
- ui::AXAbstractRange range(position->CreatePreviousLineStartPosition(),
- position->CreateNextLineEndPosition());
- return CreateTextMarkerRange(std::move(range));
- }
-
+ // TODO(tapted): Move this to TextMarkerHelper.
if ([attribute isEqualToString:
NSAccessibilityBoundsForTextMarkerRangeParameterizedAttribute]) {
BrowserAccessibility* startObject;
BrowserAccessibility* endObject;
int startOffset, endOffset;
- AXPlatformRange range = CreateRangeFromTextMarkerRange(parameter);
+ AXPlatformRange range = CreateRangeFromTextMarkerRange(
+ base::mac::CFCastStrict<AXTextMarkerRangeRef>(parameter));
if (range.IsNull())
return nil;
@@ -2380,28 +2172,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;
-
- AXAbstractPositionInstance startPosition =
- CreatePositionFromTextMarker([text_marker_array objectAtIndex:0]);
- AXAbstractPositionInstance endPosition =
- CreatePositionFromTextMarker([text_marker_array objectAtIndex:1]);
- if (*startPosition <= *endPosition) {
- return CreateTextMarkerRange(ui::AXAbstractRange(std::move(startPosition),
- std::move(endPosition)));
- } else {
- return CreateTextMarkerRange(ui::AXAbstractRange(
- std::move(endPosition), std::move(startPosition)));
- }
- }
-
- if ([attribute isEqualToString:
NSAccessibilityIndexForChildUIElementParameterizedAttribute]) {
if (![parameter isKindOfClass:[BrowserAccessibilityCocoa class]])
return nil;
@@ -2898,3 +2668,51 @@ NSString* const NSAccessibilityRequiredAttribute = @"AXRequired";
}
@end
+
+std::unique_ptr<ui::AXPositionBase> BrowserPositionFactory::GetRoot() const {
+ const BrowserAccessibility* root =
+ browser_accessibility_->manager()->GetRoot();
+ if (!root)
+ return nullptr;
+
+ return root->CreatePositionAt(0);
+}
+
+std::unique_ptr<ui::AXAbstractRange> BrowserPositionFactory::GetSelection()
+ const {
+ if (!IsActive())
+ return nullptr;
+
+ BrowserAccessibilityManager* manager = browser_accessibility_->manager();
+ if (!manager)
+ return nullptr;
+
+ int32_t anchorId = manager->GetTreeData().sel_anchor_object_id;
tapted 2017/06/19 11:44:30 (self review: convert to hacker_case)
+ const BrowserAccessibility* anchorObject = manager->GetFromID(anchorId);
+ if (!anchorObject)
+ return nullptr;
+
+ int32_t focusId = manager->GetTreeData().sel_focus_object_id;
+ const BrowserAccessibility* focusObject = manager->GetFromID(focusId);
+ if (!focusObject)
+ return nullptr;
+
+ int anchorOffset = manager->GetTreeData().sel_anchor_offset;
+ int focusOffset = manager->GetTreeData().sel_focus_offset;
+ if (anchorOffset < 0 || focusOffset < 0)
+ return nullptr;
+
+ ui::AXTextAffinity anchorAffinity =
+ manager->GetTreeData().sel_anchor_affinity;
+ ui::AXTextAffinity focusAffinity = manager->GetTreeData().sel_focus_affinity;
+
+ return base::MakeUnique<ui::AXAbstractRange>(
+ CreateTextRange(*anchorObject, anchorOffset, anchorAffinity, *focusObject,
+ focusOffset, focusAffinity));
+}
+
+std::unique_ptr<ui::AXPositionBase> BrowserPositionFactory::ExtractFromMarker(
+ AXTextMarkerRef marker) const {
+ return base::WrapUnique(
+ CreateConcretePositionFromTextMarker(marker).release());
+}

Powered by Google App Engine
This is Rietveld 408576698