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