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 static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
84 Vector<UniChar> buffer([attribute length]);
85 [attribute getCharacters:buffer.data()];
89 Vector<UniChar> valueBuffer([value length]);
90 [value getCharacters:valueBuffer.data()];
91 buffer.append(valueBuffer);
93 return JSStringCreateWithCharacters(buffer.data(), buffer.size());
96 #pragma mark iPhone Attributes
98 JSStringRef AccessibilityUIElement::iphoneLabel()
100 return concatenateAttributeAndValue(@"AXLabel", [m_element accessibilityLabel]);
103 JSStringRef AccessibilityUIElement::iphoneHint()
105 return concatenateAttributeAndValue(@"AXHint", [m_element accessibilityHint]);
108 JSStringRef AccessibilityUIElement::iphoneValue()
110 return concatenateAttributeAndValue(@"AXValue", [m_element accessibilityValue]);
113 JSStringRef AccessibilityUIElement::iphoneIdentifier()
115 return concatenateAttributeAndValue(@"AXIdentifier", [m_element accessibilityIdentifier]);
118 JSStringRef AccessibilityUIElement::iphoneTraits()
120 return concatenateAttributeAndValue(@"AXTraits", [NSString stringWithFormat:@"%qu", [m_element accessibilityTraits]]);
123 bool AccessibilityUIElement::iphoneIsElement()
125 return [m_element isAccessibilityElement];
128 int AccessibilityUIElement::iphoneElementTextPosition()
130 NSRange range = [[m_element valueForKey:@"elementTextRange"] rangeValue];
131 return range.location;
134 int AccessibilityUIElement::iphoneElementTextLength()
136 NSRange range = [[m_element valueForKey:@"elementTextRange"] rangeValue];
140 JSStringRef AccessibilityUIElement::url()
142 NSURL *url = [m_element accessibilityURL];
143 return [[url absoluteString] createJSStringRef];
146 double AccessibilityUIElement::x()
148 CGRect frame = [m_element accessibilityFrame];
149 return frame.origin.x;
152 double AccessibilityUIElement::y()
154 CGRect frame = [m_element accessibilityFrame];
155 return frame.origin.y;
158 double AccessibilityUIElement::width()
160 CGRect frame = [m_element accessibilityFrame];
161 return frame.size.width;
164 double AccessibilityUIElement::height()
166 CGRect frame = [m_element accessibilityFrame];
167 return frame.size.height;
170 double AccessibilityUIElement::clickPointX()
172 CGPoint centerPoint = [m_element accessibilityClickPoint];
173 return centerPoint.x;
176 double AccessibilityUIElement::clickPointY()
178 CGPoint centerPoint = [m_element accessibilityClickPoint];
179 return centerPoint.y;
182 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
184 NSInteger childCount = [m_element accessibilityElementCount];
185 for (NSInteger k = 0; k < childCount; ++k)
186 elementVector.append(AccessibilityUIElement([m_element accessibilityElementAtIndex:k]));
189 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
191 NSUInteger childCount = [m_element accessibilityElementCount];
192 for (NSUInteger k = location; k < childCount && k < (location+length); ++k)
193 elementVector.append(AccessibilityUIElement([m_element accessibilityElementAtIndex:k]));
196 int AccessibilityUIElement::childrenCount()
198 Vector<AccessibilityUIElement> children;
199 getChildren(children);
201 return children.size();
204 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
206 id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
210 return AccessibilityUIElement(element);
213 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
218 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
220 Vector<AccessibilityUIElement> children;
221 getChildrenWithRange(children, index, 1);
223 if (children.size() == 1)
228 AccessibilityUIElement AccessibilityUIElement::headerElementAtIndex(unsigned index)
230 NSArray *headers = [m_element accessibilityHeaderElements];
231 if (index < [headers count])
232 return [headers objectAtIndex:index];
237 AccessibilityUIElement AccessibilityUIElement::linkedElement()
239 id linkedElement = [m_element accessibilityLinkedElement];
241 return AccessibilityUIElement(linkedElement);
246 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
252 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
257 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
262 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
267 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
272 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
277 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
282 AccessibilityUIElement AccessibilityUIElement::parentElement()
284 id accessibilityObject = [m_element accessibilityContainer];
285 if (accessibilityObject)
286 return AccessibilityUIElement(accessibilityObject);
291 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
296 void AccessibilityUIElement::increaseTextSelection()
298 [m_element accessibilityModifySelection:WebCore::CharacterGranularity increase:YES];
301 void AccessibilityUIElement::decreaseTextSelection()
303 [m_element accessibilityModifySelection:WebCore::CharacterGranularity increase:NO];
306 JSStringRef AccessibilityUIElement::stringForSelection()
308 NSString *stringForRange = [m_element selectionRangeString];
312 return [stringForRange createJSStringRef];
315 JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
317 NSString *stringForRange = [m_element stringForRange:NSMakeRange(location, length)];
321 return [stringForRange createJSStringRef];
324 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
326 return JSStringCreateWithCharacters(0, 0);
329 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned)
335 void AccessibilityUIElement::elementsForRange(unsigned location, unsigned length, Vector<AccessibilityUIElement>& elements)
337 NSArray *elementsForRange = [m_element elementsForRange:NSMakeRange(location, length)];
338 for (id object in elementsForRange) {
339 AccessibilityUIElement element = AccessibilityUIElement(object);
340 elements.append(element);
346 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
350 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
354 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
356 return JSStringCreateWithCharacters(0, 0);
359 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
361 return JSStringCreateWithCharacters(0, 0);
364 JSStringRef AccessibilityUIElement::attributesOfChildren()
366 return JSStringCreateWithCharacters(0, 0);
369 JSStringRef AccessibilityUIElement::allAttributes()
371 return JSStringCreateWithCharacters(0, 0);
374 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
376 if (JSStringIsEqualToUTF8CString(attribute, "AXPlaceholderValue"))
377 return [[m_element accessibilityPlaceholderValue] createJSStringRef];
379 return JSStringCreateWithCharacters(0, 0);
382 bool AccessibilityUIElement::isPressActionSupported()
387 bool AccessibilityUIElement::isIncrementActionSupported()
392 bool AccessibilityUIElement::isDecrementActionSupported()
397 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
402 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
407 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
412 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
414 return JSStringCreateWithCharacters(0, 0);
417 JSStringRef AccessibilityUIElement::role()
419 return JSStringCreateWithCharacters(0, 0);
422 JSStringRef AccessibilityUIElement::subrole()
424 return JSStringCreateWithCharacters(0, 0);
427 JSStringRef AccessibilityUIElement::roleDescription()
429 return JSStringCreateWithCharacters(0, 0);
432 JSStringRef AccessibilityUIElement::title()
434 return JSStringCreateWithCharacters(0, 0);
437 JSStringRef AccessibilityUIElement::description()
439 return JSStringCreateWithCharacters(0, 0);
442 JSStringRef AccessibilityUIElement::orientation() const
444 return JSStringCreateWithCharacters(0, 0);
447 JSStringRef AccessibilityUIElement::stringValue()
449 return JSStringCreateWithCharacters(0, 0);
452 JSStringRef AccessibilityUIElement::language()
454 return JSStringCreateWithCharacters(0, 0);
457 JSStringRef AccessibilityUIElement::helpText() const
459 return JSStringCreateWithCharacters(0, 0);
462 double AccessibilityUIElement::intValue() const
467 double AccessibilityUIElement::minValue()
472 double AccessibilityUIElement::maxValue()
477 JSStringRef AccessibilityUIElement::valueDescription()
479 return JSStringCreateWithCharacters(0, 0);
482 int AccessibilityUIElement::insertionPointLineNumber()
487 bool AccessibilityUIElement::isEnabled()
492 bool AccessibilityUIElement::isRequired() const
497 bool AccessibilityUIElement::isFocused() const
503 bool AccessibilityUIElement::isSelected() const
505 UIAccessibilityTraits traits = [m_element accessibilityTraits];
506 return (traits & UIAccessibilityTraitSelected);
509 bool AccessibilityUIElement::isExpanded() const
514 bool AccessibilityUIElement::isChecked() const
519 int AccessibilityUIElement::hierarchicalLevel() const
524 bool AccessibilityUIElement::ariaIsGrabbed() const
529 JSStringRef AccessibilityUIElement::ariaDropEffects() const
531 return JSStringCreateWithCharacters(0, 0);
534 int AccessibilityUIElement::lineForIndex(int index)
539 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
541 return JSStringCreateWithCharacters(0, 0);
544 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
546 return JSStringCreateWithCharacters(0, 0);
549 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
551 return JSStringCreateWithCharacters(0, 0);
554 JSStringRef AccessibilityUIElement::attributesOfColumns()
556 return JSStringCreateWithCharacters(0, 0);
559 JSStringRef AccessibilityUIElement::attributesOfRows()
561 return JSStringCreateWithCharacters(0, 0);
564 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
566 return JSStringCreateWithCharacters(0, 0);
569 JSStringRef AccessibilityUIElement::attributesOfHeader()
571 return JSStringCreateWithCharacters(0, 0);
574 int AccessibilityUIElement::rowCount()
579 int AccessibilityUIElement::columnCount()
584 int AccessibilityUIElement::indexInTable()
589 JSStringRef AccessibilityUIElement::rowIndexRange()
591 NSRange range = [m_element accessibilityRowRange];
592 NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", (unsigned long)range.location, (unsigned long)range.length];
593 return [rangeDescription createJSStringRef];
596 JSStringRef AccessibilityUIElement::columnIndexRange()
598 NSRange range = [m_element accessibilityColumnRange];
599 NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", (unsigned long)range.location, (unsigned long)range.length];
600 return [rangeDescription createJSStringRef];
603 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
605 return AccessibilityUIElement([m_element accessibilityElementForRow:row andColumn:col]);
608 JSStringRef AccessibilityUIElement::selectedTextRange()
610 return JSStringCreateWithCharacters(0, 0);
613 void AccessibilityUIElement::assistiveTechnologySimulatedFocus()
615 [m_element accessibilityElementDidBecomeFocused];
618 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
622 void AccessibilityUIElement::increment()
624 [m_element accessibilityIncrement];
627 void AccessibilityUIElement::decrement()
629 [m_element accessibilityDecrement];
632 void AccessibilityUIElement::showMenu()
636 void AccessibilityUIElement::press()
640 JSStringRef AccessibilityUIElement::accessibilityValue() const
643 return JSStringCreateWithCharacters(0, 0);
646 JSStringRef AccessibilityUIElement::documentEncoding()
648 return JSStringCreateWithCharacters(0, 0);
651 JSStringRef AccessibilityUIElement::documentURI()
653 return JSStringCreateWithCharacters(0, 0);
656 static void _accessibilityNotificationCallback(id element, NSString* notification, void* context)
661 JSObjectRef functionCallback = static_cast<JSObjectRef>(context);
663 JSRetainPtr<JSStringRef> jsNotification(Adopt, [notification createJSStringRef]);
664 JSValueRef argument = JSValueMakeString([mainFrame globalContext], jsNotification.get());
665 JSObjectCallAsFunction([mainFrame globalContext], functionCallback, NULL, 1, &argument, NULL);
668 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
670 if (!functionCallback)
673 m_notificationFunctionCallback = functionCallback;
674 [platformUIElement() accessibilitySetPostedNotificationCallback:_accessibilityNotificationCallback withContext:reinterpret_cast<void*>(m_notificationFunctionCallback)];
678 void AccessibilityUIElement::removeNotificationListener()
680 m_notificationFunctionCallback = 0;
681 [platformUIElement() accessibilitySetPostedNotificationCallback:nil withContext:nil];
684 bool AccessibilityUIElement::isFocusable() const
690 bool AccessibilityUIElement::isSelectable() const
696 bool AccessibilityUIElement::isMultiSelectable() const
702 bool AccessibilityUIElement::isSelectedOptionActive() const
708 bool AccessibilityUIElement::isVisible() const
714 bool AccessibilityUIElement::isOffScreen() const
720 bool AccessibilityUIElement::isCollapsed() const
726 bool AccessibilityUIElement::isIgnored() const
732 bool AccessibilityUIElement::hasPopup() const
738 void AccessibilityUIElement::takeFocus()
743 void AccessibilityUIElement::takeSelection()
748 void AccessibilityUIElement::addSelection()
753 void AccessibilityUIElement::removeSelection()
758 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText)
764 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
769 #endif // PLATFORM(IOS)