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