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 - (void)accessibilityModifySelection:(WebCore::TextGranularity)granularity increase:(BOOL)increase;
78 - (void)accessibilitySetPostedNotificationCallback:(AXPostedNotificationCallback)function withContext:(void*)context;
81 static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
83 Vector<UniChar> buffer([attribute length]);
84 [attribute getCharacters:buffer.data()];
88 Vector<UniChar> valueBuffer([value length]);
89 [value getCharacters:valueBuffer.data()];
90 buffer.append(valueBuffer);
92 return JSStringCreateWithCharacters(buffer.data(), buffer.size());
95 #pragma mark iPhone Attributes
97 JSStringRef AccessibilityUIElement::iphoneLabel()
99 return concatenateAttributeAndValue(@"AXLabel", [m_element accessibilityLabel]);
102 JSStringRef AccessibilityUIElement::iphoneHint()
104 return concatenateAttributeAndValue(@"AXHint", [m_element accessibilityHint]);
107 JSStringRef AccessibilityUIElement::iphoneValue()
109 return concatenateAttributeAndValue(@"AXValue", [m_element accessibilityValue]);
112 JSStringRef AccessibilityUIElement::iphoneIdentifier()
114 return concatenateAttributeAndValue(@"AXIdentifier", [m_element accessibilityIdentifier]);
117 JSStringRef AccessibilityUIElement::iphoneTraits()
119 return concatenateAttributeAndValue(@"AXTraits", [NSString stringWithFormat:@"%qu", [m_element accessibilityTraits]]);
122 bool AccessibilityUIElement::iphoneIsElement()
124 return [m_element isAccessibilityElement];
127 int AccessibilityUIElement::iphoneElementTextPosition()
129 NSRange range = [[m_element valueForKey:@"elementTextRange"] rangeValue];
130 return range.location;
133 int AccessibilityUIElement::iphoneElementTextLength()
135 NSRange range = [[m_element valueForKey:@"elementTextRange"] rangeValue];
139 JSStringRef AccessibilityUIElement::url()
141 NSURL *url = [m_element accessibilityURL];
142 return [[url absoluteString] createJSStringRef];
145 double AccessibilityUIElement::x()
147 CGRect frame = [m_element accessibilityFrame];
148 return frame.origin.x;
151 double AccessibilityUIElement::y()
153 CGRect frame = [m_element accessibilityFrame];
154 return frame.origin.y;
157 double AccessibilityUIElement::width()
159 CGRect frame = [m_element accessibilityFrame];
160 return frame.size.width;
163 double AccessibilityUIElement::height()
165 CGRect frame = [m_element accessibilityFrame];
166 return frame.size.height;
169 double AccessibilityUIElement::clickPointX()
171 CGPoint centerPoint = [m_element accessibilityActivationPoint];
172 return centerPoint.x;
175 double AccessibilityUIElement::clickPointY()
177 CGPoint centerPoint = [m_element accessibilityActivationPoint];
178 return centerPoint.y;
181 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
183 NSInteger childCount = [m_element accessibilityElementCount];
184 for (NSInteger k = 0; k < childCount; ++k)
185 elementVector.append(AccessibilityUIElement([m_element accessibilityElementAtIndex:k]));
188 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
190 NSUInteger childCount = [m_element accessibilityElementCount];
191 for (NSUInteger k = location; k < childCount && k < (location+length); ++k)
192 elementVector.append(AccessibilityUIElement([m_element accessibilityElementAtIndex:k]));
195 int AccessibilityUIElement::childrenCount()
197 Vector<AccessibilityUIElement> children;
198 getChildren(children);
200 return children.size();
203 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
205 id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
209 return AccessibilityUIElement(element);
212 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
217 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
219 Vector<AccessibilityUIElement> children;
220 getChildrenWithRange(children, index, 1);
222 if (children.size() == 1)
227 AccessibilityUIElement AccessibilityUIElement::headerElementAtIndex(unsigned index)
229 NSArray *headers = [m_element accessibilityHeaderElements];
230 if (index < [headers count])
231 return [headers objectAtIndex:index];
236 AccessibilityUIElement AccessibilityUIElement::linkedElement()
238 id linkedElement = [m_element accessibilityLinkedElement];
240 return AccessibilityUIElement(linkedElement);
245 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
251 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
256 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
261 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
266 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
271 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
276 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
281 AccessibilityUIElement AccessibilityUIElement::parentElement()
283 id accessibilityObject = [m_element accessibilityContainer];
284 if (accessibilityObject)
285 return AccessibilityUIElement(accessibilityObject);
290 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
295 void AccessibilityUIElement::increaseTextSelection()
297 [m_element accessibilityModifySelection:WebCore::CharacterGranularity increase:YES];
300 void AccessibilityUIElement::decreaseTextSelection()
302 [m_element accessibilityModifySelection:WebCore::CharacterGranularity increase:NO];
305 JSStringRef AccessibilityUIElement::stringForSelection()
307 NSString *stringForRange = [m_element selectionRangeString];
311 return [stringForRange createJSStringRef];
314 JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
316 NSString *stringForRange = [m_element stringForRange:NSMakeRange(location, length)];
320 return [stringForRange createJSStringRef];
323 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
325 return JSStringCreateWithCharacters(0, 0);
328 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned)
334 void AccessibilityUIElement::elementsForRange(unsigned location, unsigned length, Vector<AccessibilityUIElement>& elements)
336 NSArray *elementsForRange = [m_element elementsForRange:NSMakeRange(location, length)];
337 for (id object in elementsForRange) {
338 AccessibilityUIElement element = AccessibilityUIElement(object);
339 elements.append(element);
345 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
349 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
353 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
355 return JSStringCreateWithCharacters(0, 0);
358 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
360 return JSStringCreateWithCharacters(0, 0);
363 JSStringRef AccessibilityUIElement::attributesOfChildren()
365 return JSStringCreateWithCharacters(0, 0);
368 JSStringRef AccessibilityUIElement::allAttributes()
370 return JSStringCreateWithCharacters(0, 0);
373 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
375 if (JSStringIsEqualToUTF8CString(attribute, "AXPlaceholderValue"))
376 return [[m_element accessibilityPlaceholderValue] createJSStringRef];
378 return JSStringCreateWithCharacters(0, 0);
381 bool AccessibilityUIElement::isPressActionSupported()
386 bool AccessibilityUIElement::isIncrementActionSupported()
391 bool AccessibilityUIElement::isDecrementActionSupported()
396 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
401 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
406 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
411 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
413 return JSStringCreateWithCharacters(0, 0);
416 JSStringRef AccessibilityUIElement::role()
418 return JSStringCreateWithCharacters(0, 0);
421 JSStringRef AccessibilityUIElement::subrole()
423 return JSStringCreateWithCharacters(0, 0);
426 JSStringRef AccessibilityUIElement::roleDescription()
428 return JSStringCreateWithCharacters(0, 0);
431 JSStringRef AccessibilityUIElement::title()
433 return JSStringCreateWithCharacters(0, 0);
436 JSStringRef AccessibilityUIElement::description()
438 return JSStringCreateWithCharacters(0, 0);
441 JSStringRef AccessibilityUIElement::orientation() const
443 return JSStringCreateWithCharacters(0, 0);
446 JSStringRef AccessibilityUIElement::stringValue()
448 return JSStringCreateWithCharacters(0, 0);
451 JSStringRef AccessibilityUIElement::language()
453 return JSStringCreateWithCharacters(0, 0);
456 JSStringRef AccessibilityUIElement::helpText() const
458 return JSStringCreateWithCharacters(0, 0);
461 double AccessibilityUIElement::intValue() const
466 double AccessibilityUIElement::minValue()
471 double AccessibilityUIElement::maxValue()
476 JSStringRef AccessibilityUIElement::valueDescription()
478 return JSStringCreateWithCharacters(0, 0);
481 int AccessibilityUIElement::insertionPointLineNumber()
486 bool AccessibilityUIElement::isEnabled()
491 bool AccessibilityUIElement::isRequired() const
496 bool AccessibilityUIElement::isFocused() const
502 bool AccessibilityUIElement::isSelected() const
504 UIAccessibilityTraits traits = [m_element accessibilityTraits];
505 return (traits & UIAccessibilityTraitSelected);
508 bool AccessibilityUIElement::isExpanded() const
513 bool AccessibilityUIElement::isChecked() const
518 int AccessibilityUIElement::hierarchicalLevel() const
523 bool AccessibilityUIElement::ariaIsGrabbed() const
528 JSStringRef AccessibilityUIElement::ariaDropEffects() const
530 return JSStringCreateWithCharacters(0, 0);
533 int AccessibilityUIElement::lineForIndex(int index)
538 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
540 return JSStringCreateWithCharacters(0, 0);
543 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
545 return JSStringCreateWithCharacters(0, 0);
548 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
550 return JSStringCreateWithCharacters(0, 0);
553 JSStringRef AccessibilityUIElement::attributesOfColumns()
555 return JSStringCreateWithCharacters(0, 0);
558 JSStringRef AccessibilityUIElement::attributesOfRows()
560 return JSStringCreateWithCharacters(0, 0);
563 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
565 return JSStringCreateWithCharacters(0, 0);
568 JSStringRef AccessibilityUIElement::attributesOfHeader()
570 return JSStringCreateWithCharacters(0, 0);
573 int AccessibilityUIElement::rowCount()
578 int AccessibilityUIElement::columnCount()
583 int AccessibilityUIElement::indexInTable()
588 JSStringRef AccessibilityUIElement::rowIndexRange()
590 NSRange range = [m_element accessibilityRowRange];
591 NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", (unsigned long)range.location, (unsigned long)range.length];
592 return [rangeDescription createJSStringRef];
595 JSStringRef AccessibilityUIElement::columnIndexRange()
597 NSRange range = [m_element accessibilityColumnRange];
598 NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", (unsigned long)range.location, (unsigned long)range.length];
599 return [rangeDescription createJSStringRef];
602 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
604 return AccessibilityUIElement([m_element accessibilityElementForRow:row andColumn:col]);
607 JSStringRef AccessibilityUIElement::selectedTextRange()
609 return JSStringCreateWithCharacters(0, 0);
612 void AccessibilityUIElement::assistiveTechnologySimulatedFocus()
614 [m_element accessibilityElementDidBecomeFocused];
617 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
621 void AccessibilityUIElement::increment()
623 [m_element accessibilityIncrement];
626 void AccessibilityUIElement::decrement()
628 [m_element accessibilityDecrement];
631 void AccessibilityUIElement::showMenu()
635 void AccessibilityUIElement::press()
639 JSStringRef AccessibilityUIElement::accessibilityValue() const
642 return JSStringCreateWithCharacters(0, 0);
645 JSStringRef AccessibilityUIElement::documentEncoding()
647 return JSStringCreateWithCharacters(0, 0);
650 JSStringRef AccessibilityUIElement::documentURI()
652 return JSStringCreateWithCharacters(0, 0);
655 static void _accessibilityNotificationCallback(id element, NSString* notification, void* context)
660 JSObjectRef functionCallback = static_cast<JSObjectRef>(context);
662 JSRetainPtr<JSStringRef> jsNotification(Adopt, [notification createJSStringRef]);
663 JSValueRef argument = JSValueMakeString([mainFrame globalContext], jsNotification.get());
664 JSObjectCallAsFunction([mainFrame globalContext], functionCallback, NULL, 1, &argument, NULL);
667 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
669 if (!functionCallback)
672 m_notificationFunctionCallback = functionCallback;
673 [platformUIElement() accessibilitySetPostedNotificationCallback:_accessibilityNotificationCallback withContext:reinterpret_cast<void*>(m_notificationFunctionCallback)];
677 void AccessibilityUIElement::removeNotificationListener()
679 m_notificationFunctionCallback = 0;
680 [platformUIElement() accessibilitySetPostedNotificationCallback:nil withContext:nil];
683 bool AccessibilityUIElement::isFocusable() const
689 bool AccessibilityUIElement::isSelectable() const
695 bool AccessibilityUIElement::isMultiSelectable() const
701 bool AccessibilityUIElement::isSelectedOptionActive() const
707 bool AccessibilityUIElement::isVisible() const
713 bool AccessibilityUIElement::isOffScreen() const
719 bool AccessibilityUIElement::isCollapsed() const
725 bool AccessibilityUIElement::isIgnored() const
731 bool AccessibilityUIElement::hasPopup() const
737 void AccessibilityUIElement::takeFocus()
742 void AccessibilityUIElement::takeSelection()
747 void AccessibilityUIElement::addSelection()
752 void AccessibilityUIElement::removeSelection()
757 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
763 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
768 #endif // PLATFORM(IOS)