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