Streamline JSRetainPtr, fix leaks of JSString and JSGlobalContext
[WebKit-https.git] / Tools / DumpRenderTree / ios / AccessibilityUIElementIOS.mm
1 /*
2  * Copyright (C) 2009 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #import "config.h"
27 #import "DumpRenderTree.h"
28 #import "AccessibilityUIElement.h"
29
30 #import "AccessibilityCommonMac.h"
31 #import "AccessibilityNotificationHandler.h"
32 #import <Foundation/Foundation.h>
33 #import <JavaScriptCore/JSStringRefCF.h>
34 #import <WebCore/TextGranularity.h>
35 #import <WebKit/WebFrame.h>
36 #import <WebKit/WebHTMLView.h>
37 #import <wtf/RetainPtr.h>
38 #import <wtf/Vector.h>
39
40 #import <UIKit/UIKit.h>
41
42 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
43
44 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
45     : m_element(element)
46     , m_notificationHandler(0)
47 {
48     [m_element retain];
49 }
50
51 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
52     : m_element(other.m_element)
53     , m_notificationHandler(0)
54
55 {
56     [m_element retain];
57 }
58
59 AccessibilityUIElement::~AccessibilityUIElement()
60 {
61     [m_element release];
62 }
63
64 @interface NSObject (UIAccessibilityHidden)
65 - (id)accessibilityHitTest:(CGPoint)point;
66 - (id)accessibilityLinkedElement;
67 - (NSRange)accessibilityColumnRange;
68 - (NSRange)accessibilityRowRange;
69 - (id)accessibilityElementForRow:(NSInteger)row andColumn:(NSInteger)column;
70 - (NSURL *)accessibilityURL;
71 - (NSArray *)accessibilityHeaderElements;
72 - (NSString *)accessibilityPlaceholderValue;
73 - (NSString *)stringForRange:(NSRange)range;
74 - (NSAttributedString *)attributedStringForRange:(NSRange)range;
75 - (NSAttributedString *)attributedStringForElement;
76 - (NSArray *)elementsForRange:(NSRange)range;
77 - (NSString *)selectionRangeString;
78 - (CGPoint)accessibilityClickPoint;
79 - (void)accessibilityModifySelection:(WebCore::TextGranularity)granularity increase:(BOOL)increase;
80 - (void)accessibilitySetPostedNotificationCallback:(AXPostedNotificationCallback)function withContext:(void*)context;
81 - (CGFloat)_accessibilityMinValue;
82 - (CGFloat)_accessibilityMaxValue;
83 - (void)_accessibilitySetValue:(NSString *)value;
84 - (void)_accessibilityActivate;
85 - (UIAccessibilityTraits)_axSelectedTrait;
86 - (UIAccessibilityTraits)_axTextAreaTrait;
87 - (UIAccessibilityTraits)_axSearchFieldTrait;
88 - (NSString *)accessibilityARIACurrentStatus;
89 - (NSUInteger)accessibilityRowCount;
90 - (NSUInteger)accessibilityColumnCount;
91 - (NSUInteger)accessibilityARIARowCount;
92 - (NSUInteger)accessibilityARIAColumnCount;
93 - (NSUInteger)accessibilityARIARowIndex;
94 - (NSUInteger)accessibilityARIAColumnIndex;
95 - (UIAccessibilityTraits)_axContainedByFieldsetTrait;
96 - (id)_accessibilityFieldsetAncestor;
97 - (BOOL)_accessibilityHasTouchEventListener;
98 - (NSString *)accessibilityExpandedTextValue;
99 - (NSString *)accessibilitySortDirection;
100 - (BOOL)accessibilityIsExpanded;
101 - (NSUInteger)accessibilityBlockquoteLevel;
102 - (NSArray *)accessibilityFindMatchingObjects:(NSDictionary *)parameters;
103 - (NSArray *)accessibilitySpeechHint;
104 - (BOOL)_accessibilityIsStrongPasswordField;
105
106 // TextMarker related
107 - (NSArray *)textMarkerRange;
108 - (NSInteger)lengthForTextMarkers:(NSArray *)textMarkers;
109 - (NSString *)stringForTextMarkers:(NSArray *)markers;
110 - (id)startOrEndTextMarkerForTextMarkers:(NSArray*)textMarkers isStart:(BOOL)isStart;
111 - (NSArray *)textMarkerRangeForMarkers:(NSArray *)textMarkers;
112 - (id)nextMarkerForMarker:(id)marker;
113 - (id)previousMarkerForMarker:(id)marker;
114 - (id)accessibilityObjectForTextMarker:(id)marker;
115 - (id)lineStartMarkerForMarker:(id)marker;
116 - (id)lineEndMarkerForMarker:(id)marker;
117 - (NSArray *)textMarkerRangeFromMarkers:(NSArray *)markers withText:(NSString *)text;
118 @end
119
120 @interface NSObject (WebAccessibilityObjectWrapperPrivate)
121 - (CGPathRef)_accessibilityPath;
122 @end
123
124 static JSRetainPtr<JSStringRef> createEmptyJSString()
125 {
126     return adopt(JSStringCreateWithCharacters(nullptr, 0));
127 }
128
129 static JSRetainPtr<JSStringRef> concatenateAttributeAndValue(NSString *attribute, NSString *value)
130 {
131     Vector<UniChar> buffer([attribute length]);
132     [attribute getCharacters:buffer.data()];
133     buffer.append(':');
134     buffer.append(' ');
135     
136     Vector<UniChar> valueBuffer([value length]);
137     [value getCharacters:valueBuffer.data()];
138     buffer.appendVector(valueBuffer);
139
140     return adopt(JSStringCreateWithCharacters(buffer.data(), buffer.size()));
141 }
142
143 #pragma mark iPhone Attributes
144
145 JSRetainPtr<JSStringRef> AccessibilityUIElement::identifier()
146 {
147     return concatenateAttributeAndValue(@"AXIdentifier", [m_element accessibilityIdentifier]);
148 }
149
150 bool AccessibilityUIElement::isTextArea() const
151 {
152     return ([m_element accessibilityTraits] & [m_element _axTextAreaTrait]) == [m_element _axTextAreaTrait];
153 }
154
155 bool AccessibilityUIElement::isSearchField() const
156 {
157     return ([m_element accessibilityTraits] & [m_element _axSearchFieldTrait]) == [m_element _axSearchFieldTrait];
158 }
159
160 JSRetainPtr<JSStringRef> AccessibilityUIElement::traits()
161 {
162     return concatenateAttributeAndValue(@"AXTraits", [NSString stringWithFormat:@"%qu", [m_element accessibilityTraits]]);
163 }
164
165 int AccessibilityUIElement::elementTextPosition()
166 {
167     NSRange range = [[m_element valueForKey:@"elementTextRange"] rangeValue];
168     return range.location;
169 }
170
171 int AccessibilityUIElement::elementTextLength()
172 {
173     NSRange range = [[m_element valueForKey:@"elementTextRange"] rangeValue];
174     return range.length;    
175 }
176
177 bool AccessibilityUIElement::hasContainedByFieldsetTrait()
178 {
179     UIAccessibilityTraits traits = [m_element accessibilityTraits];
180     return (traits & [m_element _axContainedByFieldsetTrait]) == [m_element _axContainedByFieldsetTrait];
181 }
182
183 AccessibilityUIElement AccessibilityUIElement::fieldsetAncestorElement()
184 {
185     id ancestorElement = [m_element _accessibilityFieldsetAncestor];
186     if (ancestorElement)
187         return AccessibilityUIElement(ancestorElement);
188     
189     return nullptr;
190 }
191
192
193 JSRetainPtr<JSStringRef> AccessibilityUIElement::url()
194 {
195     NSURL *url = [m_element accessibilityURL];
196     return [[url absoluteString] createJSStringRef];
197 }
198
199 double AccessibilityUIElement::x()
200 {
201     CGRect frame = [m_element accessibilityFrame];
202     return frame.origin.x;
203 }
204
205 double AccessibilityUIElement::y()
206 {
207     CGRect frame = [m_element accessibilityFrame];
208     return frame.origin.y;
209 }
210
211 double AccessibilityUIElement::width()
212 {
213     CGRect frame = [m_element accessibilityFrame];
214     return frame.size.width;
215 }
216
217 double AccessibilityUIElement::height()
218 {
219     CGRect frame = [m_element accessibilityFrame];
220     return frame.size.height;
221 }
222
223 double AccessibilityUIElement::clickPointX()
224 {
225     CGPoint centerPoint = [m_element accessibilityClickPoint];
226     return centerPoint.x;
227 }
228
229 double AccessibilityUIElement::clickPointY()
230 {
231     CGPoint centerPoint = [m_element accessibilityClickPoint];
232     return centerPoint.y;
233 }
234
235 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
236 {
237     NSInteger childCount = [m_element accessibilityElementCount];
238     for (NSInteger k = 0; k < childCount; ++k)
239         elementVector.append(AccessibilityUIElement([m_element accessibilityElementAtIndex:k]));
240 }
241
242 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
243 {
244     // accessibilityElementAtIndex: takes an NSInteger.
245     // We want to preserve that in order to test against invalid indexes being input.
246     NSInteger maxValue = static_cast<NSInteger>(location + length);
247     for (NSInteger k = location; k < maxValue; ++k)
248         elementVector.append(AccessibilityUIElement([m_element accessibilityElementAtIndex:k]));    
249 }
250
251 int AccessibilityUIElement::childrenCount()
252 {
253     Vector<AccessibilityUIElement> children;
254     getChildren(children);
255     
256     return children.size();
257 }
258
259 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
260 {
261     id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
262     if (!element)
263         return nil;
264     
265     return AccessibilityUIElement(element); 
266 }
267
268 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
269 {
270     return 0;
271 }
272
273 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
274 {
275     Vector<AccessibilityUIElement> children;
276     getChildrenWithRange(children, index, 1);
277     
278     if (children.size() == 1)
279         return children[0];
280     return nil;
281 }
282
283 AccessibilityUIElement AccessibilityUIElement::headerElementAtIndex(unsigned index)
284 {
285     NSArray *headers = [m_element accessibilityHeaderElements];
286     if (index < [headers count])
287         return [headers objectAtIndex:index];
288     
289     return 0;
290 }
291
292 AccessibilityUIElement AccessibilityUIElement::linkedElement()
293 {
294     id linkedElement = [m_element accessibilityLinkedElement];
295     if (linkedElement)
296         return AccessibilityUIElement(linkedElement);
297     
298     return 0;
299 }
300
301 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
302 {
303     // FIXME: implement
304     return 0;
305 }
306
307 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
308 {
309     return 0;
310 }
311
312 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
313 {
314     return 0;
315 }
316
317 AccessibilityUIElement AccessibilityUIElement::ariaControlsElementAtIndex(unsigned index)
318 {
319     return 0;
320 }
321
322 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
323 {
324     return 0;
325 }
326
327 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
328 {
329     return 0;
330 }
331
332 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
333 {
334     return 0;
335 }
336
337 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
338 {
339     return 0;
340 }
341
342 AccessibilityUIElement AccessibilityUIElement::parentElement()
343 {
344     id accessibilityObject = [m_element accessibilityContainer];
345     if (accessibilityObject)
346         return AccessibilityUIElement(accessibilityObject);
347     
348     return nil;
349 }
350
351 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
352 {
353     return 0;
354 }
355
356 void AccessibilityUIElement::increaseTextSelection()
357 {
358     [m_element accessibilityModifySelection:WebCore::CharacterGranularity increase:YES];
359 }
360
361 void AccessibilityUIElement::decreaseTextSelection()
362 {
363     [m_element accessibilityModifySelection:WebCore::CharacterGranularity increase:NO];    
364 }
365
366 JSRetainPtr<JSStringRef> AccessibilityUIElement::speakAs()
367 {
368     return [[[m_element accessibilitySpeechHint] componentsJoinedByString:@", "] createJSStringRef];
369 }
370
371 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForSelection()
372
373     NSString *stringForRange = [m_element selectionRangeString];
374     return [stringForRange createJSStringRef];
375 }
376
377 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
378
379     NSString *stringForRange = [m_element stringForRange:NSMakeRange(location, length)];
380     return [stringForRange createJSStringRef];
381 }
382
383 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
384 {
385     NSRange range = NSMakeRange(location, length);
386     NSAttributedString* string = [m_element attributedStringForRange:range];
387     if (![string isKindOfClass:[NSAttributedString class]])
388         return 0;
389     
390     NSString* stringWithAttrs = [string description];
391     return [stringWithAttrs createJSStringRef];
392 }
393
394 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForElement()
395 {
396     NSAttributedString *string = [m_element attributedStringForElement];
397     if (![string isKindOfClass:[NSAttributedString class]])
398         return nullptr;
399     
400     return [[string description] createJSStringRef];
401 }
402
403 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned)
404 {
405     return false;
406 }
407
408
409 void AccessibilityUIElement::elementsForRange(unsigned location, unsigned length, Vector<AccessibilityUIElement>& elements)
410
411     NSArray *elementsForRange = [m_element elementsForRange:NSMakeRange(location, length)];
412     for (id object in elementsForRange) {
413         AccessibilityUIElement element = AccessibilityUIElement(object);
414         elements.append(element);
415     }
416 }
417
418 static void _CGPathEnumerationIteration(void *info, const CGPathElement *element)
419 {
420     NSMutableString *result = (NSMutableString *)info;
421     switch (element->type) {
422     case kCGPathElementMoveToPoint:
423         [result appendString:@"\tMove to point\n"];
424         break;
425         
426     case kCGPathElementAddLineToPoint:
427         [result appendString:@"\tLine to\n"];
428         break;
429         
430     case kCGPathElementAddQuadCurveToPoint:
431         [result appendString:@"\tQuad curve to\n"];
432         break;
433         
434     case kCGPathElementAddCurveToPoint:
435         [result appendString:@"\tCurve to\n"];
436         break;
437         
438     case kCGPathElementCloseSubpath:
439         [result appendString:@"\tClose\n"];
440         break;
441     }
442 }
443
444 JSRetainPtr<JSStringRef> AccessibilityUIElement::pathDescription() const
445 {
446     NSMutableString *result = [NSMutableString stringWithString:@"\nStart Path\n"];
447     CGPathRef pathRef = [m_element _accessibilityPath];
448     
449     CGPathApply(pathRef, result, _CGPathEnumerationIteration);
450     
451     return [result createJSStringRef];
452 }
453
454 #if SUPPORTS_AX_TEXTMARKERS && PLATFORM(IOS)
455
456 // Text markers
457
458 AccessibilityTextMarkerRange AccessibilityUIElement::lineTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
459 {
460     id startTextMarker = [m_element lineStartMarkerForMarker:(id)textMarker->platformTextMarker()];
461     id endTextMarker = [m_element lineEndMarkerForMarker:(id)textMarker->platformTextMarker()];
462     NSArray *textMarkers = [NSArray arrayWithObjects:startTextMarker, endTextMarker, nil];
463     
464     id textMarkerRange = [m_element textMarkerRangeForMarkers:textMarkers];
465     return AccessibilityTextMarkerRange(textMarkerRange);
466 }
467
468 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
469 {
470     id textMarkerRange = [element->platformUIElement() textMarkerRange];
471     return AccessibilityTextMarkerRange(textMarkerRange);
472 }
473
474 AccessibilityTextMarkerRange AccessibilityUIElement::selectedTextMarkerRange()
475 {
476     return nullptr;
477 }
478
479 void AccessibilityUIElement::resetSelectedTextMarkerRange()
480 {
481 }
482
483 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
484 {
485     id textMarkers = (id)range->platformTextMarkerRange();
486     return [m_element lengthForTextMarkers:textMarkers];
487 }
488
489 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
490 {
491     NSArray *textMarkers = [NSArray arrayWithObjects:(id)startMarker->platformTextMarker(), (id)endMarker->platformTextMarker(), nil];
492     id textMarkerRange = [m_element textMarkerRangeForMarkers:textMarkers];
493     return AccessibilityTextMarkerRange(textMarkerRange);
494 }
495
496 AccessibilityTextMarker AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
497 {
498     id textMarkers = (id)range->platformTextMarkerRange();
499     id textMarker = [m_element startOrEndTextMarkerForTextMarkers:textMarkers isStart:YES];
500     return AccessibilityTextMarker(textMarker);
501 }
502
503 AccessibilityTextMarker AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
504 {
505     id textMarkers = (id)range->platformTextMarkerRange();
506     id textMarker = [m_element startOrEndTextMarkerForTextMarkers:textMarkers isStart:NO];
507     return AccessibilityTextMarker(textMarker);
508 }
509
510 AccessibilityUIElement AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
511 {
512     id obj = [m_element accessibilityObjectForTextMarker:(id)marker->platformTextMarker()];
513     if (obj)
514         return AccessibilityUIElement(obj);
515     return nullptr;
516 }
517
518 AccessibilityTextMarker AccessibilityUIElement::endTextMarkerForBounds(int x, int y, int width, int height)
519 {
520     return nullptr;
521 }
522
523 AccessibilityTextMarker AccessibilityUIElement::startTextMarkerForBounds(int x, int y, int width, int height)
524 {
525     return nullptr;
526 }
527
528 AccessibilityTextMarker AccessibilityUIElement::textMarkerForPoint(int x, int y)
529 {
530     return nullptr;
531 }
532
533 AccessibilityTextMarker AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
534 {
535     id previousMarker = [m_element previousMarkerForMarker:(id)textMarker->platformTextMarker()];
536     return AccessibilityTextMarker(previousMarker);
537 }
538
539 AccessibilityTextMarker AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
540 {
541     id nextMarker = [m_element nextMarkerForMarker:(id)textMarker->platformTextMarker()];
542     return AccessibilityTextMarker(nextMarker);
543 }
544
545 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
546 {
547     id textMarkers = (id)markerRange->platformTextMarkerRange();
548     if (!textMarkers || ![textMarkers isKindOfClass:[NSArray class]])
549         return createEmptyJSString();
550     return [[m_element stringForTextMarkers:textMarkers] createJSStringRef];
551 }
552
553 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRange(AccessibilityTextMarkerRange*)
554 {
555     return nullptr;
556 }
557
558 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange*, bool)
559 {
560     return nullptr;
561 }
562
563 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*)
564 {
565     return false;
566 }
567
568 int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker*)
569 {
570     return -1;
571 }
572
573 bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker*)
574 {
575     return false;
576 }
577
578 AccessibilityTextMarker AccessibilityUIElement::textMarkerForIndex(int)
579 {
580     return nullptr;
581 }
582
583 AccessibilityTextMarker AccessibilityUIElement::startTextMarker()
584 {
585     return nullptr;
586 }
587
588 AccessibilityTextMarker AccessibilityUIElement::endTextMarker()
589 {
590     return nullptr;
591 }
592
593 bool AccessibilityUIElement::setSelectedVisibleTextRange(AccessibilityTextMarkerRange*)
594 {
595     return false;
596 }
597
598 AccessibilityTextMarkerRange AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
599 {
600     return nullptr;
601 }
602
603 AccessibilityTextMarkerRange AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
604 {
605     return nullptr;
606 }
607
608 AccessibilityTextMarker AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*)
609 {
610     return nullptr;
611 }
612
613 AccessibilityTextMarker AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*)
614 {
615     return nullptr;
616 }
617
618 AccessibilityTextMarkerRange AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
619 {
620     return nullptr;
621 }
622
623 AccessibilityTextMarker AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*)
624 {
625     return nullptr;
626 }
627
628 AccessibilityTextMarker AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*)
629 {
630     return nullptr;
631 }
632
633 AccessibilityTextMarkerRange AccessibilityUIElement::sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
634 {
635     return nullptr;
636 }
637
638 AccessibilityTextMarker AccessibilityUIElement::previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker*)
639 {
640     return nullptr;
641 }
642
643 AccessibilityTextMarker AccessibilityUIElement::nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*)
644 {
645     return nullptr;
646 }
647
648 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeMatchesTextNearMarkers(JSStringRef text, AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
649 {
650     NSArray *textMarkers = nil;
651     if (startMarker->platformTextMarker() && endMarker->platformTextMarker())
652         textMarkers = [NSArray arrayWithObjects:(id)startMarker->platformTextMarker(), (id)endMarker->platformTextMarker(), nil];
653     id textMarkerRange = [m_element textMarkerRangeFromMarkers:textMarkers withText:[NSString stringWithJSStringRef:text]];
654     return AccessibilityTextMarkerRange(textMarkerRange);
655 }
656
657
658 #endif // SUPPORTS_AX_TEXTMARKERS && PLATFORM(IOS)
659
660 #pragma mark Unused
661
662 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
663 {
664 }
665
666 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
667 {
668 }
669
670 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfLinkedUIElements()
671 {
672     return createEmptyJSString();
673 }
674
675 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfDocumentLinks()
676 {
677     return createEmptyJSString();
678 }
679
680 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfChildren()
681 {
682     return createEmptyJSString();
683 }
684
685 JSRetainPtr<JSStringRef> AccessibilityUIElement::allAttributes()
686 {
687     return createEmptyJSString();
688 }
689
690 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
691 {
692     if (JSStringIsEqualToUTF8CString(attribute, "AXPlaceholderValue"))
693         return [[m_element accessibilityPlaceholderValue] createJSStringRef];
694     
695     if (JSStringIsEqualToUTF8CString(attribute, "AXARIACurrent"))
696         return [[m_element accessibilityARIACurrentStatus] createJSStringRef];
697
698     if (JSStringIsEqualToUTF8CString(attribute, "AXExpandedTextValue"))
699         return [[m_element accessibilityExpandedTextValue] createJSStringRef];
700     
701     if (JSStringIsEqualToUTF8CString(attribute, "AXSortDirection"))
702         return [[m_element accessibilitySortDirection] createJSStringRef];
703     
704     return createEmptyJSString();
705 }
706
707 bool AccessibilityUIElement::isPressActionSupported()
708 {
709     return false;
710 }
711
712 bool AccessibilityUIElement::isIncrementActionSupported()
713 {
714     return false;
715 }
716
717 bool AccessibilityUIElement::isDecrementActionSupported()
718 {
719     return false;
720 }
721
722 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
723 {
724     if (JSStringIsEqualToUTF8CString(attribute, "AXHasTouchEventListener"))
725         return [m_element _accessibilityHasTouchEventListener];
726     if (JSStringIsEqualToUTF8CString(attribute, "AXIsStrongPasswordField"))
727         return [m_element _accessibilityIsStrongPasswordField];
728     return false;
729 }
730
731 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
732 {
733     return false;
734 }
735
736 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
737 {
738     return false;
739 }
740
741 JSRetainPtr<JSStringRef> AccessibilityUIElement::parameterizedAttributeNames()
742 {
743     return createEmptyJSString();
744 }
745
746 JSRetainPtr<JSStringRef> AccessibilityUIElement::role()
747 {
748     return createEmptyJSString();
749 }
750
751 JSRetainPtr<JSStringRef> AccessibilityUIElement::subrole()
752 {
753     return createEmptyJSString();
754 }
755
756 bool AccessibilityUIElement::scrollPageUp()
757 {
758     return [m_element accessibilityScroll:UIAccessibilityScrollDirectionUp];
759 }
760
761 bool AccessibilityUIElement::scrollPageDown()
762 {
763     return [m_element accessibilityScroll:UIAccessibilityScrollDirectionDown];
764 }
765 bool AccessibilityUIElement::scrollPageLeft()
766 {
767     return [m_element accessibilityScroll:UIAccessibilityScrollDirectionLeft];
768 }
769
770 bool AccessibilityUIElement::scrollPageRight()
771 {
772     return [m_element accessibilityScroll:UIAccessibilityScrollDirectionRight];
773 }
774
775 JSRetainPtr<JSStringRef> AccessibilityUIElement::roleDescription()
776 {
777     return createEmptyJSString();
778 }
779
780 JSRetainPtr<JSStringRef> AccessibilityUIElement::computedRoleString()
781 {
782     return createEmptyJSString();
783 }
784
785 JSRetainPtr<JSStringRef> AccessibilityUIElement::title()
786 {
787     return createEmptyJSString();
788 }
789
790 JSRetainPtr<JSStringRef> AccessibilityUIElement::description()
791 {
792     return concatenateAttributeAndValue(@"AXLabel", [m_element accessibilityLabel]);
793 }
794
795 JSRetainPtr<JSStringRef> AccessibilityUIElement::orientation() const
796 {
797     return createEmptyJSString();
798 }
799
800 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringValue()
801 {
802     return concatenateAttributeAndValue(@"AXValue", [m_element accessibilityValue]);
803 }
804
805 JSRetainPtr<JSStringRef> AccessibilityUIElement::language()
806 {
807     return createEmptyJSString();
808 }
809
810 JSRetainPtr<JSStringRef> AccessibilityUIElement::helpText() const
811 {
812     return concatenateAttributeAndValue(@"AXHint", [m_element accessibilityHint]);
813 }
814
815 double AccessibilityUIElement::intValue() const
816 {
817     return 0.0f;
818 }
819
820 double AccessibilityUIElement::minValue()
821 {
822     return [m_element _accessibilityMinValue];
823 }
824
825 double AccessibilityUIElement::maxValue()
826 {
827     return [m_element _accessibilityMaxValue];
828 }
829
830 void AccessibilityUIElement::setValue(JSStringRef valueText)
831 {
832     [m_element _accessibilitySetValue:[NSString stringWithJSStringRef:valueText]];
833 }
834
835 JSRetainPtr<JSStringRef> AccessibilityUIElement::valueDescription()
836 {
837     return createEmptyJSString();
838 }
839
840 int AccessibilityUIElement::insertionPointLineNumber()
841 {
842     return -1;
843 }
844
845 bool AccessibilityUIElement::isEnabled()
846 {
847     return false;
848 }
849
850 bool AccessibilityUIElement::isRequired() const
851 {
852     return false;
853 }
854
855 bool AccessibilityUIElement::isFocused() const
856 {
857     // FIXME: implement
858     return false;
859 }
860
861 bool AccessibilityUIElement::isSelected() const
862 {
863     UIAccessibilityTraits traits = [m_element accessibilityTraits];
864     bool result = (traits & [m_element _axSelectedTrait]) == [m_element _axSelectedTrait];
865     return result;
866 }
867
868 bool AccessibilityUIElement::isExpanded() const
869 {
870     return [m_element accessibilityIsExpanded];
871 }
872
873 bool AccessibilityUIElement::isChecked() const
874 {
875     return false;
876 }
877
878 bool AccessibilityUIElement::isIndeterminate() const
879 {
880     // FIXME: implement
881     return false;
882 }
883
884 int AccessibilityUIElement::hierarchicalLevel() const
885 {
886     return 0;
887 }
888
889 bool AccessibilityUIElement::ariaIsGrabbed() const
890 {
891     return false;
892 }
893
894 JSRetainPtr<JSStringRef> AccessibilityUIElement::ariaDropEffects() const
895 {
896     return createEmptyJSString();
897 }
898
899 int AccessibilityUIElement::lineForIndex(int index)
900 {
901     return -1;
902 }
903
904 JSRetainPtr<JSStringRef> AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
905 {
906     return createEmptyJSString();
907 }
908
909 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
910 {
911     return createEmptyJSString();
912 }
913
914 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRowHeaders()
915 {
916     return createEmptyJSString();
917 }
918
919 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumns()
920 {
921     return createEmptyJSString();
922 }
923
924 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRows()
925 {
926     return createEmptyJSString();
927 }
928
929 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfVisibleCells()
930 {
931     return createEmptyJSString();
932 }
933
934 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfHeader()
935 {
936     return createEmptyJSString();
937 }
938
939 int AccessibilityUIElement::rowCount()
940 {
941     return [m_element accessibilityRowCount];
942 }
943
944 int AccessibilityUIElement::columnCount()
945 {
946     return [m_element accessibilityColumnCount];
947 }
948
949 int AccessibilityUIElement::indexInTable()
950 {
951     return -1;
952 }
953
954 JSRetainPtr<JSStringRef> AccessibilityUIElement::rowIndexRange()
955 {
956     NSRange range = [m_element accessibilityRowRange];
957     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", (unsigned long)range.location, (unsigned long)range.length];
958     return [rangeDescription createJSStringRef];
959 }
960
961 JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange()
962 {
963     NSRange range = [m_element accessibilityColumnRange];
964     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", (unsigned long)range.location, (unsigned long)range.length];
965     return [rangeDescription createJSStringRef];
966 }
967
968 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
969 {
970     return AccessibilityUIElement([m_element accessibilityElementForRow:row andColumn:col]);
971 }
972
973 void AccessibilityUIElement::scrollToMakeVisible()
974 {
975     // FIXME: implement
976 }
977
978 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
979 {
980     // FIXME: implement
981 }
982
983 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
984 {
985     // FIXME: implement
986 }
987
988 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectedTextRange()
989 {
990     return createEmptyJSString();
991 }
992
993 void AccessibilityUIElement::assistiveTechnologySimulatedFocus()
994 {
995     [m_element accessibilityElementDidBecomeFocused];
996 }
997
998 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
999 {
1000 }
1001
1002 void AccessibilityUIElement::increment()
1003 {
1004     [m_element accessibilityIncrement];
1005 }
1006
1007 void AccessibilityUIElement::decrement()
1008 {
1009     [m_element accessibilityDecrement];
1010 }
1011
1012 void AccessibilityUIElement::showMenu()
1013 {
1014 }
1015
1016 void AccessibilityUIElement::press()
1017 {
1018     [m_element _accessibilityActivate];
1019 }
1020
1021 JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const
1022 {
1023     // FIXME: implement
1024     return createEmptyJSString();
1025 }
1026
1027 void AccessibilityUIElement::clearSelectedChildren() const
1028 {
1029     // FIXME: implement
1030 }
1031
1032 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentEncoding()
1033 {
1034     return createEmptyJSString();
1035 }
1036
1037 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentURI()
1038 {
1039     return createEmptyJSString();
1040 }
1041
1042 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
1043 {
1044     if (!functionCallback)
1045         return false;
1046     
1047     // iOS programmers should not be adding more than one notification listener per element.
1048     // Other platforms may be different.
1049     if (m_notificationHandler)
1050         return false;
1051     m_notificationHandler = [[AccessibilityNotificationHandler alloc] init];
1052     [m_notificationHandler setPlatformElement:platformUIElement()];
1053     [m_notificationHandler setCallback:functionCallback];
1054     [m_notificationHandler startObserving];
1055     
1056     return true;
1057 }
1058
1059 void AccessibilityUIElement::removeNotificationListener()
1060 {
1061     // iOS programmers should not be trying to remove a listener that's already removed.
1062     ASSERT(m_notificationHandler);
1063     
1064     [m_notificationHandler stopObserving];
1065     [m_notificationHandler release];
1066     m_notificationHandler = nil;
1067 }
1068
1069 bool AccessibilityUIElement::isFocusable() const
1070 {
1071     // FIXME: implement
1072     return false;
1073 }
1074
1075 bool AccessibilityUIElement::isSelectable() const
1076 {
1077     // FIXME: implement
1078     return false;
1079 }
1080
1081 bool AccessibilityUIElement::isMultiSelectable() const
1082 {
1083     // FIXME: implement
1084     return false;
1085 }
1086
1087 bool AccessibilityUIElement::isSelectedOptionActive() const
1088 {
1089     // FIXME: implement
1090     return false;
1091 }
1092
1093 bool AccessibilityUIElement::isVisible() const
1094 {
1095     // FIXME: implement
1096     return false;
1097 }
1098
1099 bool AccessibilityUIElement::isOffScreen() const
1100 {
1101     // FIXME: implement
1102     return false;
1103 }
1104
1105 bool AccessibilityUIElement::isCollapsed() const
1106 {
1107     // FIXME: implement
1108     return false;
1109 }
1110
1111 bool AccessibilityUIElement::isIgnored() const
1112 {
1113     return ![m_element isAccessibilityElement];
1114 }
1115
1116 bool AccessibilityUIElement::isSingleLine() const
1117 {
1118     // FIXME: implement
1119     return false;
1120 }
1121
1122 bool AccessibilityUIElement::isMultiLine() const
1123 {
1124     // FIXME: implement
1125     return false;
1126 }
1127
1128 bool AccessibilityUIElement::hasPopup() const
1129 {
1130     // FIXME: implement
1131     return false;
1132 }
1133
1134 void AccessibilityUIElement::takeFocus()
1135 {
1136     // FIXME: implement
1137 }
1138
1139 void AccessibilityUIElement::takeSelection()
1140 {
1141     // FIXME: implement
1142 }
1143
1144 void AccessibilityUIElement::addSelection()
1145 {
1146     // FIXME: implement
1147 }
1148
1149 void AccessibilityUIElement::removeSelection()
1150 {
1151     // FIXME: implement
1152 }
1153
1154 unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
1155 {
1156     // FIXME: implement
1157     return 0;
1158 }
1159
1160 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement *startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
1161 {
1162     NSDictionary *parameterizedAttribute = searchPredicateParameterizedAttributeForSearchCriteria(context, startElement, isDirectionNext, 5, searchKey, searchText, visibleOnly, immediateDescendantsOnly);
1163     id value = [m_element accessibilityFindMatchingObjects:parameterizedAttribute];
1164     if (![value isKindOfClass:[NSArray class]])
1165         return nullptr;
1166     for (id element in value) {
1167         if ([element isAccessibilityElement])
1168             return AccessibilityUIElement(element);
1169     }
1170     return AccessibilityUIElement([value firstObject]);
1171 }
1172
1173 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectTextWithCriteria(JSContextRef context, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity)
1174 {
1175     // FIXME: Implement.
1176     return nullptr;
1177 }
1178
1179 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
1180 {
1181     // Support test for table related attributes.
1182     if (JSStringIsEqualToUTF8CString(attribute, "AXARIAColumnCount"))
1183         return [m_element accessibilityARIAColumnCount];
1184     if (JSStringIsEqualToUTF8CString(attribute, "AXARIARowCount"))
1185         return [m_element accessibilityARIARowCount];
1186     if (JSStringIsEqualToUTF8CString(attribute, "AXARIAColumnIndex"))
1187         return [m_element accessibilityARIAColumnIndex];
1188     if (JSStringIsEqualToUTF8CString(attribute, "AXARIARowIndex"))
1189         return [m_element accessibilityARIARowIndex];
1190     if (JSStringIsEqualToUTF8CString(attribute, "AXBlockquoteLevel"))
1191         return [m_element accessibilityBlockquoteLevel];
1192     
1193     return 0;
1194 }
1195
1196 JSRetainPtr<JSStringRef> AccessibilityUIElement::classList() const
1197 {
1198     // FIXME: implement
1199     return nullptr;
1200 }
1201
1202 void AccessibilityUIElement::uiElementArrayAttributeValue(JSStringRef, Vector<AccessibilityUIElement>&) const
1203 {
1204     // FIXME: implement
1205 }
1206
1207 void AccessibilityUIElement::columnHeaders(Vector<AccessibilityUIElement>&) const
1208 {
1209     // FIXME: implement
1210 }
1211
1212 void AccessibilityUIElement::rowHeaders(Vector<AccessibilityUIElement>&) const
1213 {
1214     // FIXME: implement
1215 }
1216
1217 unsigned AccessibilityUIElement::selectedChildrenCount() const
1218 {
1219     return 0;
1220 }
1221
1222 AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned) const
1223 {
1224     return 0;
1225 }