2 * Copyright (C) 2009 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #import "DumpRenderTree.h"
28 #import "AccessibilityUIElement.h"
30 #import "AccessibilityCommonMac.h"
31 #import <Foundation/Foundation.h>
32 #import <JavaScriptCore/JSRetainPtr.h>
33 #import <JavaScriptCore/JSStringRef.h>
34 #import <JavaScriptCore/JSStringRefCF.h>
35 #import <WebCore/TextGranularity.h>
36 #import <WebKit/WebFrame.h>
37 #import <WebKit/WebHTMLView.h>
38 #import <WebKit/WebTypesInternal.h>
39 #import <wtf/RetainPtr.h>
40 #import <wtf/Vector.h>
44 #import <UIKit/UIKit.h>
46 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
48 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
54 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
55 : m_element(other.m_element)
60 AccessibilityUIElement::~AccessibilityUIElement()
65 @interface NSObject (UIAccessibilityHidden)
66 - (id)accessibilityHitTest:(CGPoint)point;
67 - (id)accessibilityLinkedElement;
68 - (NSRange)accessibilityColumnRange;
69 - (NSRange)accessibilityRowRange;
70 - (id)accessibilityElementForRow:(NSInteger)row andColumn:(NSInteger)column;
71 - (NSURL *)accessibilityURL;
72 - (NSArray *)accessibilityHeaderElements;
73 - (NSString *)accessibilityPlaceholderValue;
74 - (NSString *)stringForRange:(NSRange)range;
75 - (NSArray *)elementsForRange:(NSRange)range;
76 - (NSString *)selectionRangeString;
77 - (CGPoint)accessibilityClickPoint;
78 - (void)accessibilityModifySelection:(WebCore::TextGranularity)granularity increase:(BOOL)increase;
79 - (void)accessibilitySetPostedNotificationCallback:(AXPostedNotificationCallback)function withContext:(void*)context;
82 @interface NSObject (WebAccessibilityObjectWrapperPrivate)
83 - (CGPathRef)_accessibilityPath;
86 static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
88 Vector<UniChar> buffer([attribute length]);
89 [attribute getCharacters:buffer.data()];
93 Vector<UniChar> valueBuffer([value length]);
94 [value getCharacters:valueBuffer.data()];
95 buffer.append(valueBuffer);
97 return JSStringCreateWithCharacters(buffer.data(), buffer.size());
100 #pragma mark iPhone Attributes
102 JSStringRef AccessibilityUIElement::iphoneLabel()
104 return concatenateAttributeAndValue(@"AXLabel", [m_element accessibilityLabel]);
107 JSStringRef AccessibilityUIElement::iphoneHint()
109 return concatenateAttributeAndValue(@"AXHint", [m_element accessibilityHint]);
112 JSStringRef AccessibilityUIElement::iphoneValue()
114 return concatenateAttributeAndValue(@"AXValue", [m_element accessibilityValue]);
117 JSStringRef AccessibilityUIElement::iphoneIdentifier()
119 return concatenateAttributeAndValue(@"AXIdentifier", [m_element accessibilityIdentifier]);
122 JSStringRef AccessibilityUIElement::iphoneTraits()
124 return concatenateAttributeAndValue(@"AXTraits", [NSString stringWithFormat:@"%qu", [m_element accessibilityTraits]]);
127 bool AccessibilityUIElement::iphoneIsElement()
129 return [m_element isAccessibilityElement];
132 int AccessibilityUIElement::iphoneElementTextPosition()
134 NSRange range = [[m_element valueForKey:@"elementTextRange"] rangeValue];
135 return range.location;
138 int AccessibilityUIElement::iphoneElementTextLength()
140 NSRange range = [[m_element valueForKey:@"elementTextRange"] rangeValue];
144 JSStringRef AccessibilityUIElement::url()
146 NSURL *url = [m_element accessibilityURL];
147 return [[url absoluteString] createJSStringRef];
150 double AccessibilityUIElement::x()
152 CGRect frame = [m_element accessibilityFrame];
153 return frame.origin.x;
156 double AccessibilityUIElement::y()
158 CGRect frame = [m_element accessibilityFrame];
159 return frame.origin.y;
162 double AccessibilityUIElement::width()
164 CGRect frame = [m_element accessibilityFrame];
165 return frame.size.width;
168 double AccessibilityUIElement::height()
170 CGRect frame = [m_element accessibilityFrame];
171 return frame.size.height;
174 double AccessibilityUIElement::clickPointX()
176 CGPoint centerPoint = [m_element accessibilityClickPoint];
177 return centerPoint.x;
180 double AccessibilityUIElement::clickPointY()
182 CGPoint centerPoint = [m_element accessibilityClickPoint];
183 return centerPoint.y;
186 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
188 NSInteger childCount = [m_element accessibilityElementCount];
189 for (NSInteger k = 0; k < childCount; ++k)
190 elementVector.append(AccessibilityUIElement([m_element accessibilityElementAtIndex:k]));
193 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
195 NSUInteger childCount = [m_element accessibilityElementCount];
196 for (NSUInteger k = location; k < childCount && k < (location+length); ++k)
197 elementVector.append(AccessibilityUIElement([m_element accessibilityElementAtIndex:k]));
200 int AccessibilityUIElement::childrenCount()
202 Vector<AccessibilityUIElement> children;
203 getChildren(children);
205 return children.size();
208 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
210 id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
214 return AccessibilityUIElement(element);
217 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
222 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
224 Vector<AccessibilityUIElement> children;
225 getChildrenWithRange(children, index, 1);
227 if (children.size() == 1)
232 AccessibilityUIElement AccessibilityUIElement::headerElementAtIndex(unsigned index)
234 NSArray *headers = [m_element accessibilityHeaderElements];
235 if (index < [headers count])
236 return [headers objectAtIndex:index];
241 AccessibilityUIElement AccessibilityUIElement::linkedElement()
243 id linkedElement = [m_element accessibilityLinkedElement];
245 return AccessibilityUIElement(linkedElement);
250 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
256 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
261 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
266 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
271 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
276 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
281 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
286 AccessibilityUIElement AccessibilityUIElement::parentElement()
288 id accessibilityObject = [m_element accessibilityContainer];
289 if (accessibilityObject)
290 return AccessibilityUIElement(accessibilityObject);
295 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
300 void AccessibilityUIElement::increaseTextSelection()
302 [m_element accessibilityModifySelection:WebCore::CharacterGranularity increase:YES];
305 void AccessibilityUIElement::decreaseTextSelection()
307 [m_element accessibilityModifySelection:WebCore::CharacterGranularity increase:NO];
310 JSStringRef AccessibilityUIElement::stringForSelection()
312 NSString *stringForRange = [m_element selectionRangeString];
316 return [stringForRange createJSStringRef];
319 JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
321 NSString *stringForRange = [m_element stringForRange:NSMakeRange(location, length)];
325 return [stringForRange createJSStringRef];
328 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
330 return JSStringCreateWithCharacters(0, 0);
333 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned)
339 void AccessibilityUIElement::elementsForRange(unsigned location, unsigned length, Vector<AccessibilityUIElement>& elements)
341 NSArray *elementsForRange = [m_element elementsForRange:NSMakeRange(location, length)];
342 for (id object in elementsForRange) {
343 AccessibilityUIElement element = AccessibilityUIElement(object);
344 elements.append(element);
348 static void _CGPathEnumerationIteration(void *info, const CGPathElement *element)
350 NSMutableString *result = (NSMutableString *)info;
351 switch (element->type) {
352 case kCGPathElementMoveToPoint:
353 [result appendString:@"\tMove to point\n"];
356 case kCGPathElementAddLineToPoint:
357 [result appendString:@"\tLine to\n"];
360 case kCGPathElementAddQuadCurveToPoint:
361 [result appendString:@"\tQuad curve to\n"];
364 case kCGPathElementAddCurveToPoint:
365 [result appendString:@"\tCurve to\n"];
368 case kCGPathElementCloseSubpath:
369 [result appendString:@"\tClose\n"];
374 JSStringRef AccessibilityUIElement::pathDescription() const
376 NSMutableString *result = [NSMutableString stringWithString:@"\nStart Path\n"];
377 CGPathRef pathRef = [m_element _accessibilityPath];
379 CGPathApply(pathRef, result, _CGPathEnumerationIteration);
381 return [result createJSStringRef];
386 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
390 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
394 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
396 return JSStringCreateWithCharacters(0, 0);
399 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
401 return JSStringCreateWithCharacters(0, 0);
404 JSStringRef AccessibilityUIElement::attributesOfChildren()
406 return JSStringCreateWithCharacters(0, 0);
409 JSStringRef AccessibilityUIElement::allAttributes()
411 return JSStringCreateWithCharacters(0, 0);
414 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
416 if (JSStringIsEqualToUTF8CString(attribute, "AXPlaceholderValue"))
417 return [[m_element accessibilityPlaceholderValue] createJSStringRef];
419 return JSStringCreateWithCharacters(0, 0);
422 bool AccessibilityUIElement::isPressActionSupported()
427 bool AccessibilityUIElement::isIncrementActionSupported()
432 bool AccessibilityUIElement::isDecrementActionSupported()
437 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
442 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
447 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
452 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
454 return JSStringCreateWithCharacters(0, 0);
457 JSStringRef AccessibilityUIElement::role()
459 return JSStringCreateWithCharacters(0, 0);
462 JSStringRef AccessibilityUIElement::subrole()
464 return JSStringCreateWithCharacters(0, 0);
467 JSStringRef AccessibilityUIElement::roleDescription()
469 return JSStringCreateWithCharacters(0, 0);
472 JSStringRef AccessibilityUIElement::title()
474 return JSStringCreateWithCharacters(0, 0);
477 JSStringRef AccessibilityUIElement::description()
479 return JSStringCreateWithCharacters(0, 0);
482 JSStringRef AccessibilityUIElement::orientation() const
484 return JSStringCreateWithCharacters(0, 0);
487 JSStringRef AccessibilityUIElement::stringValue()
489 return JSStringCreateWithCharacters(0, 0);
492 JSStringRef AccessibilityUIElement::language()
494 return JSStringCreateWithCharacters(0, 0);
497 JSStringRef AccessibilityUIElement::helpText() const
499 return JSStringCreateWithCharacters(0, 0);
502 double AccessibilityUIElement::intValue() const
507 double AccessibilityUIElement::minValue()
512 double AccessibilityUIElement::maxValue()
517 JSStringRef AccessibilityUIElement::valueDescription()
519 return JSStringCreateWithCharacters(0, 0);
522 int AccessibilityUIElement::insertionPointLineNumber()
527 bool AccessibilityUIElement::isEnabled()
532 bool AccessibilityUIElement::isRequired() const
537 bool AccessibilityUIElement::isFocused() const
543 bool AccessibilityUIElement::isSelected() const
545 UIAccessibilityTraits traits = [m_element accessibilityTraits];
546 return (traits & UIAccessibilityTraitSelected);
549 bool AccessibilityUIElement::isExpanded() const
554 bool AccessibilityUIElement::isChecked() const
559 int AccessibilityUIElement::hierarchicalLevel() const
564 bool AccessibilityUIElement::ariaIsGrabbed() const
569 JSStringRef AccessibilityUIElement::ariaDropEffects() const
571 return JSStringCreateWithCharacters(0, 0);
574 int AccessibilityUIElement::lineForIndex(int index)
579 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
581 return JSStringCreateWithCharacters(0, 0);
584 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
586 return JSStringCreateWithCharacters(0, 0);
589 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
591 return JSStringCreateWithCharacters(0, 0);
594 JSStringRef AccessibilityUIElement::attributesOfColumns()
596 return JSStringCreateWithCharacters(0, 0);
599 JSStringRef AccessibilityUIElement::attributesOfRows()
601 return JSStringCreateWithCharacters(0, 0);
604 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
606 return JSStringCreateWithCharacters(0, 0);
609 JSStringRef AccessibilityUIElement::attributesOfHeader()
611 return JSStringCreateWithCharacters(0, 0);
614 int AccessibilityUIElement::rowCount()
619 int AccessibilityUIElement::columnCount()
624 int AccessibilityUIElement::indexInTable()
629 JSStringRef AccessibilityUIElement::rowIndexRange()
631 NSRange range = [m_element accessibilityRowRange];
632 NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", (unsigned long)range.location, (unsigned long)range.length];
633 return [rangeDescription createJSStringRef];
636 JSStringRef AccessibilityUIElement::columnIndexRange()
638 NSRange range = [m_element accessibilityColumnRange];
639 NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", (unsigned long)range.location, (unsigned long)range.length];
640 return [rangeDescription createJSStringRef];
643 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
645 return AccessibilityUIElement([m_element accessibilityElementForRow:row andColumn:col]);
648 JSStringRef AccessibilityUIElement::selectedTextRange()
650 return JSStringCreateWithCharacters(0, 0);
653 void AccessibilityUIElement::assistiveTechnologySimulatedFocus()
655 [m_element accessibilityElementDidBecomeFocused];
658 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
662 void AccessibilityUIElement::increment()
664 [m_element accessibilityIncrement];
667 void AccessibilityUIElement::decrement()
669 [m_element accessibilityDecrement];
672 void AccessibilityUIElement::showMenu()
676 void AccessibilityUIElement::press()
680 JSStringRef AccessibilityUIElement::accessibilityValue() const
683 return JSStringCreateWithCharacters(0, 0);
686 JSStringRef AccessibilityUIElement::documentEncoding()
688 return JSStringCreateWithCharacters(0, 0);
691 JSStringRef AccessibilityUIElement::documentURI()
693 return JSStringCreateWithCharacters(0, 0);
696 static void _accessibilityNotificationCallback(id element, NSString* notification, void* context)
701 JSObjectRef functionCallback = static_cast<JSObjectRef>(context);
703 JSRetainPtr<JSStringRef> jsNotification(Adopt, [notification createJSStringRef]);
704 JSValueRef argument = JSValueMakeString([mainFrame globalContext], jsNotification.get());
705 JSObjectCallAsFunction([mainFrame globalContext], functionCallback, NULL, 1, &argument, NULL);
708 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
710 if (!functionCallback)
713 m_notificationFunctionCallback = functionCallback;
714 [platformUIElement() accessibilitySetPostedNotificationCallback:_accessibilityNotificationCallback withContext:reinterpret_cast<void*>(m_notificationFunctionCallback)];
718 void AccessibilityUIElement::removeNotificationListener()
720 m_notificationFunctionCallback = 0;
721 [platformUIElement() accessibilitySetPostedNotificationCallback:nil withContext:nil];
724 bool AccessibilityUIElement::isFocusable() const
730 bool AccessibilityUIElement::isSelectable() const
736 bool AccessibilityUIElement::isMultiSelectable() const
742 bool AccessibilityUIElement::isSelectedOptionActive() const
748 bool AccessibilityUIElement::isVisible() const
754 bool AccessibilityUIElement::isOffScreen() const
760 bool AccessibilityUIElement::isCollapsed() const
766 bool AccessibilityUIElement::isIgnored() const
772 bool AccessibilityUIElement::hasPopup() const
778 void AccessibilityUIElement::takeFocus()
783 void AccessibilityUIElement::takeSelection()
788 void AccessibilityUIElement::addSelection()
793 void AccessibilityUIElement::removeSelection()
798 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText)
804 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
809 #endif // PLATFORM(IOS)