AX: Support solution to handle invalid ax text marker
[WebKit-https.git] / Source / WebCore / accessibility / mac / WebAccessibilityObjectWrapper.mm
index 0b7dc4a88ac1541938a52ac8da7afb60c09f8320..c13ad392c2c324b73f64a67a187287e4dea9b567 100644 (file)
@@ -332,6 +332,9 @@ using namespace std;
 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
 #endif
 
+#define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
+#define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
+#define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
 
 @interface NSObject (WebKitAccessibilityArrayCategory)
 
@@ -2491,6 +2494,7 @@ static NSString* roleValueToNSString(AccessibilityRole value)
     static NSArray* paramAttrs = nil;
     static NSArray* textParamAttrs = nil;
     static NSArray* tableParamAttrs = nil;
+    static NSArray* webAreaParamAttrs = nil;
     if (paramAttrs == nil) {
         paramAttrs = [[NSArray alloc] initWithObjects:
                       @"AXUIElementForTextMarker",
@@ -2546,6 +2550,14 @@ static NSString* roleValueToNSString(AccessibilityRole value)
         tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
         [tempArray release];
     }
+    if (!webAreaParamAttrs) {
+        NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
+        [tempArray addObject:NSAccessibilityTextMarkerForIndexParameterizedAttribute];
+        [tempArray addObject:NSAccessibilityTextMarkerIsValidParameterizedAttribute];
+        [tempArray addObject:NSAccessibilityIndexForTextMarkerParameterizedAttribute];
+        webAreaParamAttrs = [[NSArray alloc] initWithArray:tempArray];
+        [tempArray release];
+    }
     
     if (m_object->isPasswordField())
         return [NSArray array];
@@ -2562,6 +2574,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
     if (m_object->isMenuRelated())
         return nil;
 
+    if (m_object->isWebArea())
+        return webAreaParamAttrs;
+    
     return paramAttrs;
 }
 
@@ -2753,6 +2768,42 @@ static RenderObject* rendererForView(NSView* view)
     return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];
 }
 
+- (NSRange)_convertToNSRange:(Range*)range
+{
+    NSRange result = NSMakeRange(NSNotFound, 0);
+    if (!range || !range->startContainer())
+        return result;
+    
+    Document* document = m_object->document();
+    if (!document)
+        return result;
+    
+    TextIterator::getLocationAndLengthFromRange(document->documentElement(), range, result.location, result.length);
+    
+    return result;
+}
+
+- (NSInteger)_indexForTextMarker:(id)marker
+{
+    if (!marker)
+        return NSNotFound;
+    
+    VisibleSelection selection([self visiblePositionForTextMarker:marker]);    
+    return [self _convertToNSRange:selection.toNormalizedRange().get()].location;
+}
+
+- (id)_textMarkerForIndex:(NSInteger)textIndex
+{
+    Document* document = m_object->document();
+    if (!document)
+        return nil;
+    
+    PassRefPtr<Range> textRange = TextIterator::rangeFromLocationAndLength(document->documentElement(), textIndex, 0);
+    
+    VisiblePosition position(textRange->startPosition());
+    return [self textMarkerForVisiblePosition:position];
+}
+
 // The RTF representation of the text associated with this accessibility object that is
 // specified by the given range.
 - (NSData*)doAXRTFForRange:(NSRange)range
@@ -2844,6 +2895,17 @@ static RenderObject* rendererForView(NSView* view)
         return convertToNSArray(results);
     }
 
+    if ([attribute isEqualToString:NSAccessibilityTextMarkerIsValidParameterizedAttribute]) {
+        VisiblePosition pos = [self visiblePositionForTextMarker:textMarker];
+        return [NSNumber numberWithBool:!pos.isNull()];
+    }
+    if ([attribute isEqualToString:NSAccessibilityIndexForTextMarkerParameterizedAttribute]) {
+        return [NSNumber numberWithInteger:[self _indexForTextMarker:textMarker]];
+    }
+    if ([attribute isEqualToString:NSAccessibilityTextMarkerForIndexParameterizedAttribute]) {
+        return [self _textMarkerForIndex:[number integerValue]];
+    }
+    
     if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         AccessibilityObject* axObject = m_object->accessibilityObjectForPosition(visiblePos);