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