https://bugs.webkit.org/show_bug.cgi?id=82023
Reviewed by Oliver Hunt.
Source/WebCore:
This provides methods to better use text markers so that assistive technologies
can know when they are valid, and can convert them to and from absolute positions.
Test: platform/mac/accessibility/textmarker-routines.html
* accessibility/mac/WebAccessibilityObjectWrapper.mm:
(-[WebAccessibilityObjectWrapper accessibilityParameterizedAttributeNames]):
(-[WebAccessibilityObjectWrapper _convertToNSRange:]):
(-[WebAccessibilityObjectWrapper _indexForTextMarker:]):
(-[WebAccessibilityObjectWrapper _textMarkerForIndex:]):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
Tools:
* DumpRenderTree/AccessibilityUIElement.cpp:
(indexForTextMarkerCallback):
(isTextMarkerValidCallback):
(textMarkerForIndexCallback):
(AccessibilityUIElement::indexForTextMarker):
(AccessibilityUIElement::isTextMarkerValid):
(AccessibilityUIElement::textMarkerForIndex):
(AccessibilityUIElement::getJSClass):
* DumpRenderTree/AccessibilityUIElement.h:
(AccessibilityUIElement):
* DumpRenderTree/mac/AccessibilityUIElementMac.mm:
(AccessibilityUIElement::indexForTextMarker):
(AccessibilityUIElement::textMarkerForIndex):
(AccessibilityUIElement::isTextMarkerValid):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
(WTR::AccessibilityUIElement::indexForTextMarker):
(WTR::AccessibilityUIElement::isTextMarkerValid):
(WTR::AccessibilityUIElement::textMarkerForIndex):
(WTR):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
(AccessibilityUIElement):
* WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR):
(WTR::AccessibilityUIElement::indexForTextMarker):
(WTR::AccessibilityUIElement::isTextMarkerValid):
(WTR::AccessibilityUIElement::textMarkerForIndex):
LayoutTests:
* platform/mac/accessibility/textmarker-routines-expected.txt: Added.
* platform/mac/accessibility/textmarker-routines.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@112021
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-03-24 Chris Fleizach <cfleizach@apple.com>
+
+ AX: Support solution to handle invalid ax text marker
+ https://bugs.webkit.org/show_bug.cgi?id=82023
+
+ Reviewed by Oliver Hunt.
+
+ * platform/mac/accessibility/textmarker-routines-expected.txt: Added.
+ * platform/mac/accessibility/textmarker-routines.html: Added.
+
2012-03-24 Abhishek Arya <inferno@chromium.org>
Crash in ApplyStyleCommand::applyInlineStyleToNodeRange.
--- /dev/null
+text
+text
+This verifies usage of isTextMarkerValid, indexForTextMarker and textMarkerForIndex.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS item1.isTextMarkerValid(firstTextMarker) is true
+PASS item1.indexForTextMarker(firstTextMarker) is 0
+PASS item1.textMarkerForIndex(0).isEqual(firstTextMarker) is true
+PASS item1.isTextMarkerValid(firstTextMarker) is false
+PASS item2.isTextMarkerValid(secondTextMarker) is true
+PASS item2.indexForTextMarker(secondTextMarker) is 5
+PASS item2.textMarkerForIndex(item2.indexForTextMarker(secondTextMarker)).isEqual(secondTextMarker) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<script src="../../../fast/js/resources/js-test-pre.js"></script>
+<body id="body" tabindex="0">
+
+<div tabindex="0" id="text1">text</div>
+
+text
+
+<div tabindex="0" id="text2">text</div>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+ description("This verifies usage of isTextMarkerValid, indexForTextMarker and textMarkerForIndex.");
+
+ if (window.accessibilityController) {
+ document.getElementById("text1").focus();
+ var item1 = accessibilityController.focusedElement;
+ var markerRange = item1.textMarkerRangeForElement(item1);
+ var firstTextMarker = item1.startTextMarkerForTextMarkerRange(markerRange);
+
+ shouldBeTrue("item1.isTextMarkerValid(firstTextMarker)");
+ shouldBe("item1.indexForTextMarker(firstTextMarker)", "0");
+ shouldBeTrue("item1.textMarkerForIndex(0).isEqual(firstTextMarker)");
+
+ document.getElementById("body").removeChild(document.getElementById("text1"));
+
+ shouldBeFalse("item1.isTextMarkerValid(firstTextMarker)");
+
+ document.getElementById("text2").focus();
+ var item2 = accessibilityController.focusedElement;
+ markerRange = item2.textMarkerRangeForElement(item2);
+ var secondTextMarker = item2.startTextMarkerForTextMarkerRange(markerRange);
+
+ shouldBeTrue("item2.isTextMarkerValid(secondTextMarker)");
+ shouldBe("item2.indexForTextMarker(secondTextMarker)", "5");
+ shouldBeTrue("item2.textMarkerForIndex(item2.indexForTextMarker(secondTextMarker)).isEqual(secondTextMarker)");
+ }
+
+</script>
+
+<script src="../../../fast/js/resources/js-test-post.js"></script>
+
+</body>
+</html>
+
+2012-03-24 Chris Fleizach <cfleizach@apple.com>
+
+ AX: Support solution to handle invalid ax text marker
+ https://bugs.webkit.org/show_bug.cgi?id=82023
+
+ Reviewed by Oliver Hunt.
+
+ This provides methods to better use text markers so that assistive technologies
+ can know when they are valid, and can convert them to and from absolute positions.
+
+ Test: platform/mac/accessibility/textmarker-routines.html
+
+ * accessibility/mac/WebAccessibilityObjectWrapper.mm:
+ (-[WebAccessibilityObjectWrapper accessibilityParameterizedAttributeNames]):
+ (-[WebAccessibilityObjectWrapper _convertToNSRange:]):
+ (-[WebAccessibilityObjectWrapper _indexForTextMarker:]):
+ (-[WebAccessibilityObjectWrapper _textMarkerForIndex:]):
+ (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+
2012-03-24 Victor Carbune <vcarbune@adobe.com>
Quick fix for rendering controls regression.
#define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
#endif
+#define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
+#define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
+#define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
@interface NSObject (WebKitAccessibilityArrayCategory)
static NSArray* paramAttrs = nil;
static NSArray* textParamAttrs = nil;
static NSArray* tableParamAttrs = nil;
+ static NSArray* webAreaParamAttrs = nil;
if (paramAttrs == nil) {
paramAttrs = [[NSArray alloc] initWithObjects:
@"AXUIElementForTextMarker",
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];
if (m_object->isMenuRelated())
return nil;
+ if (m_object->isWebArea())
+ return webAreaParamAttrs;
+
return paramAttrs;
}
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
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);
+2012-03-24 Chris Fleizach <cfleizach@apple.com>
+
+ AX: Support solution to handle invalid ax text marker
+ https://bugs.webkit.org/show_bug.cgi?id=82023
+
+ Reviewed by Oliver Hunt.
+
+ * DumpRenderTree/AccessibilityUIElement.cpp:
+ (indexForTextMarkerCallback):
+ (isTextMarkerValidCallback):
+ (textMarkerForIndexCallback):
+ (AccessibilityUIElement::indexForTextMarker):
+ (AccessibilityUIElement::isTextMarkerValid):
+ (AccessibilityUIElement::textMarkerForIndex):
+ (AccessibilityUIElement::getJSClass):
+ * DumpRenderTree/AccessibilityUIElement.h:
+ (AccessibilityUIElement):
+ * DumpRenderTree/mac/AccessibilityUIElementMac.mm:
+ (AccessibilityUIElement::indexForTextMarker):
+ (AccessibilityUIElement::textMarkerForIndex):
+ (AccessibilityUIElement::isTextMarkerValid):
+ * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
+ (WTR::AccessibilityUIElement::indexForTextMarker):
+ (WTR::AccessibilityUIElement::isTextMarkerValid):
+ (WTR::AccessibilityUIElement::textMarkerForIndex):
+ (WTR):
+ * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
+ (AccessibilityUIElement):
+ * WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
+ * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
+ (WTR):
+ (WTR::AccessibilityUIElement::indexForTextMarker):
+ (WTR::AccessibilityUIElement::isTextMarkerValid):
+ (WTR::AccessibilityUIElement::textMarkerForIndex):
+
2012-03-24 Sheriff Bot <webkit.review.bot@gmail.com>
Unreviewed, rolling out r112014.
return result;
}
+static JSValueRef indexForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = 0;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return JSValueMakeNumber(context, toAXElement(thisObject)->indexForTextMarker(marker));
+}
+
+static JSValueRef isTextMarkerValidCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = 0;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->isTextMarkerValid(marker));
+}
+
+static JSValueRef textMarkerForIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ int textIndex = 0;
+ if (argumentCount == 1)
+ textIndex = JSValueToNumber(context, arguments[0], exception);
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->textMarkerForIndex(textIndex));
+}
+
static JSValueRef textMarkerRangeLengthCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
AccessibilityTextMarkerRange* range = 0;
return false;
}
+int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker*)
+{
+ return -1;
+}
+
+bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker*)
+{
+ return false;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::textMarkerForIndex(int)
+{
+ return 0;
+}
+
#endif
// Destruction
{ "removeSelection", removeSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "textMarkerRangeForElement", textMarkerRangeForElementCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "attributedStringForTextMarkerRangeContainsAttribute", attributedStringForTextMarkerRangeContainsAttributeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "indexForTextMarker", indexForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "isTextMarkerValid", isTextMarkerValidCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "textMarkerRangeForMarkers", textMarkerRangeForMarkersCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "textMarkerForIndex", textMarkerForIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "startTextMarkerForTextMarkerRange", startTextMarkerForTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "endTextMarkerForTextMarkerRange", endTextMarkerForTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "accessibilityElementForTextMarker", accessibilityElementForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
JSStringRef stringForTextMarkerRange(AccessibilityTextMarkerRange*);
int textMarkerRangeLength(AccessibilityTextMarkerRange*);
bool attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*);
-
+ int indexForTextMarker(AccessibilityTextMarker*);
+ bool isTextMarkerValid(AccessibilityTextMarker*);
+ AccessibilityTextMarker textMarkerForIndex(int);
+
void scrollToMakeVisible();
void scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height);
void scrollToGlobalPoint(int x, int y);
return false;
}
+int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ NSNumber* indexNumber = [m_element accessibilityAttributeValue:@"AXIndexForTextMarker" forParameter:(id)marker->platformTextMarker()];
+ return [indexNumber intValue];
+ END_AX_OBJC_EXCEPTIONS
+
+ return -1;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::textMarkerForIndex(int textIndex)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForIndex" forParameter:[NSNumber numberWithInteger:textIndex]];
+ return AccessibilityTextMarker(textMarker);
+ END_AX_OBJC_EXCEPTIONS
+
+ return 0;
+}
+
+bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ NSNumber* validNumber = [m_element accessibilityAttributeValue:@"AXTextMarkerIsValid" forParameter:(id)textMarker->platformTextMarker()];
+ return [validNumber boolValue];
+ END_AX_OBJC_EXCEPTIONS
+
+ return false;
+}
+
AccessibilityTextMarker AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
{
BEGIN_AX_OBJC_EXCEPTIONS
PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker*) { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange*) { return 0; }
bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*) { return false; }
+int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker*) { return -1; }
+bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker*) { return false; }
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int) { return 0; }
+
#endif
} // namespace WTR
JSRetainPtr<JSStringRef> stringForTextMarkerRange(AccessibilityTextMarkerRange*);
int textMarkerRangeLength(AccessibilityTextMarkerRange*);
bool attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*);
+ int indexForTextMarker(AccessibilityTextMarker*);
+ bool isTextMarkerValid(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> textMarkerForIndex(int);
// Notifications
// Function callback should take one argument, the name of the notification.
DOMString stringForTextMarkerRange(in AccessibilityTextMarkerRange range);
int textMarkerRangeLength(in AccessibilityTextMarkerRange range);
boolean attributedStringForTextMarkerRangeContainsAttribute(in DOMString attr, in AccessibilityTextMarkerRange range);
-
+ int indexForTextMarker(in AccessibilityTextMarker marker);
+ boolean isTextMarkerValid(in AccessibilityTextMarker marker);
+ AccessibilityTextMarker textMarkerForIndex(in int textIndex);
+
// Notification support.
boolean addNotificationListener(in object callbackFunction);
boolean removeNotificationListener();
return false;
}
+
+int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ NSNumber* indexNumber = [m_element accessibilityAttributeValue:@"AXIndexForTextMarker" forParameter:(id)marker->platformTextMarker()];
+ return [indexNumber intValue];
+ END_AX_OBJC_EXCEPTIONS
+
+ return -1;
+}
+
+bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ NSNumber* validNumber = [m_element accessibilityAttributeValue:@"AXTextMarkerIsValid" forParameter:(id)textMarker->platformTextMarker()];
+ return [validNumber boolValue];
+ END_AX_OBJC_EXCEPTIONS
+
+ return false;
+}
+
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int textIndex)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForIndex" forParameter:[NSNumber numberWithInteger:textIndex]];
+ return AccessibilityTextMarker::create(textMarker);
+ END_AX_OBJC_EXCEPTIONS
+
+ return 0;
+}
+
} // namespace WTR