AX: Implement paragraph related text marker functions using TextIterator
[WebKit-https.git] / Tools / WebKitTestRunner / InjectedBundle / mac / AccessibilityUIElementMac.mm
1 /*
2  * Copyright (C) 2011 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "config.h"
27 #import "AccessibilityCommonMac.h"
28
29 #if HAVE(ACCESSIBILITY)
30
31 #import "AccessibilityNotificationHandler.h"
32 #import "AccessibilityUIElement.h"
33 #import "InjectedBundle.h"
34 #import "InjectedBundlePage.h"
35
36 #import <AppKit/NSAccessibility.h>
37 #import <Foundation/Foundation.h>
38 #import <JavaScriptCore/JSRetainPtr.h>
39 #import <JavaScriptCore/JSStringRef.h>
40 #import <JavaScriptCore/JSStringRefCF.h>
41 #import <JavaScriptCore/JSObjectRef.h>
42 #import <WebKit/WKBundleFrame.h>
43 #import <wtf/RetainPtr.h>
44 #import <wtf/Vector.h>
45
46
47 #ifndef NSAccessibilityOwnsAttribute
48 #define NSAccessibilityOwnsAttribute @"AXOwns"
49 #endif
50
51 #ifndef NSAccessibilityGrabbedAttribute
52 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
53 #endif
54
55 #ifndef NSAccessibilityDropEffectsAttribute
56 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
57 #endif
58
59 #ifndef NSAccessibilityPathAttribute
60 #define NSAccessibilityPathAttribute @"AXPath"
61 #endif
62
63 // Text
64 #ifndef NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute
65 #define NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute @"AXEndTextMarkerForBounds"
66 #endif
67
68 #ifndef NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute
69 #define NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute @"AXStartTextMarkerForBounds"
70 #endif
71
72 #ifndef NSAccessibilitySelectedTextMarkerRangeAttribute
73 #define NSAccessibilitySelectedTextMarkerRangeAttribute @"AXSelectedTextMarkerRange"
74 #endif
75
76 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
77
78 @interface NSObject (WebKitAccessibilityAdditions)
79 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
80 - (NSUInteger)accessibilityIndexOfChild:(id)child;
81 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
82 - (void)_accessibilitySetTestValue:(id)value forAttribute:(NSString*)attributeName;
83 - (void)_accessibilityScrollToMakeVisibleWithSubFocus:(NSRect)rect;
84 - (void)_accessibilityScrollToGlobalPoint:(NSPoint)point;
85 - (void)_accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName;
86 @end
87
88 namespace WTR {
89
90 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
91     : m_element(element)
92     , m_notificationHandler(0)
93 {
94     // FIXME: ap@webkit.org says ObjC objects need to be CFRetained/CFRelease to be GC-compliant on the mac.
95     [m_element retain];
96 }
97
98 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
99     : JSWrappable()
100     , m_element(other.m_element)
101     , m_notificationHandler(0)
102 {
103     [m_element retain];
104 }
105
106 AccessibilityUIElement::~AccessibilityUIElement()
107 {
108     // The notification handler should be nil because removeNotificationListener() should have been called in the test.
109     ASSERT(!m_notificationHandler);
110     [m_element release];
111 }
112
113 bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement)
114 {
115     if (!otherElement)
116         return false;
117     return platformUIElement() == otherElement->platformUIElement();
118 }
119     
120 static NSString* descriptionOfValue(id valueObject, id focusedAccessibilityObject)
121 {
122     if (!valueObject)
123         return NULL;
124
125     if ([valueObject isKindOfClass:[NSArray class]])
126         return [NSString stringWithFormat:@"<array of size %lu>", static_cast<unsigned long>([(NSArray*)valueObject count])];
127
128     if ([valueObject isKindOfClass:[NSNumber class]])
129         return [(NSNumber*)valueObject stringValue];
130
131     if ([valueObject isKindOfClass:[NSValue class]]) {
132         NSString* type = [NSString stringWithCString:[valueObject objCType] encoding:NSASCIIStringEncoding];
133         NSValue* value = (NSValue*)valueObject;
134         if ([type rangeOfString:@"NSRect"].length > 0)
135             return [NSString stringWithFormat:@"NSRect: %@", NSStringFromRect([value rectValue])];
136         if ([type rangeOfString:@"NSPoint"].length > 0)
137             return [NSString stringWithFormat:@"NSPoint: %@", NSStringFromPoint([value pointValue])];
138         if ([type rangeOfString:@"NSSize"].length > 0)
139             return [NSString stringWithFormat:@"NSSize: %@", NSStringFromSize([value sizeValue])];
140         if ([type rangeOfString:@"NSRange"].length > 0)
141             return [NSString stringWithFormat:@"NSRange: %@", NSStringFromRange([value rangeValue])];
142     }
143
144     // Strip absolute URL paths
145     NSString* description = [valueObject description];
146     NSRange range = [description rangeOfString:@"LayoutTests"];
147     if (range.length)
148         return [description substringFromIndex:range.location];
149
150     // Strip pointer locations
151     if ([description rangeOfString:@"0x"].length) {
152         NSString* role = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityRoleAttribute];
153         NSString* title = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityTitleAttribute];
154         if ([title length])
155             return [NSString stringWithFormat:@"<%@: '%@'>", role, title];
156         return [NSString stringWithFormat:@"<%@>", role];
157     }
158     
159     return [valueObject description];
160 }
161
162 static NSString* attributesOfElement(id accessibilityObject)
163 {
164     NSArray* supportedAttributes = [accessibilityObject accessibilityAttributeNames];
165
166     NSMutableString* attributesString = [NSMutableString string];
167     for (NSUInteger i = 0; i < [supportedAttributes count]; ++i) {
168         NSString* attribute = [supportedAttributes objectAtIndex:i];
169         
170         // Right now, position provides useless and screen-specific information, so we do not
171         // want to include it for the sake of universally passing tests.
172         if ([attribute isEqualToString:@"AXPosition"])
173             continue;
174         
175         // accessibilityAttributeValue: can throw an if an attribute is not returned.
176         // For DumpRenderTree's purpose, we should ignore those exceptions
177         BEGIN_AX_OBJC_EXCEPTIONS
178         id valueObject = [accessibilityObject accessibilityAttributeValue:attribute];
179         NSString* value = descriptionOfValue(valueObject, accessibilityObject);
180         [attributesString appendFormat:@"%@: %@\n", attribute, value];
181         END_AX_OBJC_EXCEPTIONS
182     }
183     
184     return attributesString;
185 }
186
187 static JSValueRef convertElementsToObjectArray(JSContextRef context, Vector<RefPtr<AccessibilityUIElement>>& elements)
188 {
189     JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
190     JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
191     size_t elementCount = elements.size();
192     for (size_t i = 0; i < elementCount; ++i)
193         JSObjectSetPropertyAtIndex(context, arrayObj, i, JSObjectMake(context, elements[i]->wrapperClass(), elements[i].get()), 0);
194     
195     return arrayResult;
196 }
197
198 static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
199 {
200     Vector<UniChar> buffer([attribute length]);
201     [attribute getCharacters:buffer.data()];
202     buffer.append(':');
203     buffer.append(' ');
204
205     Vector<UniChar> valueBuffer([value length]);
206     [value getCharacters:valueBuffer.data()];
207     buffer.appendVector(valueBuffer);
208
209     return JSStringCreateWithCharacters(buffer.data(), buffer.size());
210 }
211
212 static void convertNSArrayToVector(NSArray* array, Vector<RefPtr<AccessibilityUIElement> >& elementVector)
213 {
214     NSUInteger count = [array count];
215     for (NSUInteger i = 0; i < count; ++i)
216         elementVector.append(AccessibilityUIElement::create([array objectAtIndex:i]));
217 }
218
219 static JSStringRef descriptionOfElements(Vector<RefPtr<AccessibilityUIElement> >& elementVector)
220 {
221     NSMutableString* allElementString = [NSMutableString string];
222     size_t size = elementVector.size();
223     for (size_t i = 0; i < size; ++i) {
224         RefPtr<AccessibilityUIElement> uiElement = elementVector[i];
225         NSString* attributes = attributesOfElement(uiElement->platformUIElement());
226         [allElementString appendFormat:@"%@\n------------\n", attributes];
227     }
228     
229     return [allElementString createJSStringRef];
230 }
231
232 static NSDictionary *searchPredicateParameterizedAttributeForSearchCriteria(JSContextRef context, AccessibilityUIElement *startElement, bool isDirectionNext, unsigned resultsLimit, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
233 {
234     NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
235     
236     if (startElement && startElement->platformUIElement())
237         [parameterizedAttribute setObject:(id)startElement->platformUIElement() forKey:@"AXStartElement"];
238     
239     [parameterizedAttribute setObject:(isDirectionNext) ? @"AXDirectionNext" : @"AXDirectionPrevious" forKey:@"AXDirection"];
240     
241     [parameterizedAttribute setObject:@(resultsLimit) forKey:@"AXResultsLimit"];
242     
243     if (searchKey) {
244         id searchKeyParameter = nil;
245         if (JSValueIsString(context, searchKey)) {
246             JSRetainPtr<JSStringRef> searchKeyString(Adopt, JSValueToStringCopy(context, searchKey, nullptr));
247             if (searchKeyString)
248                 searchKeyParameter = [NSString stringWithJSStringRef:searchKeyString.get()];
249         }
250         else if (JSValueIsObject(context, searchKey)) {
251             JSObjectRef searchKeyArray = JSValueToObject(context, searchKey, nullptr);
252             unsigned searchKeyArrayLength = 0;
253             
254             JSRetainPtr<JSStringRef> lengthPropertyString(Adopt, JSStringCreateWithUTF8CString("length"));
255             JSValueRef searchKeyArrayLengthValue = JSObjectGetProperty(context, searchKeyArray, lengthPropertyString.get(), nullptr);
256             if (searchKeyArrayLengthValue && JSValueIsNumber(context, searchKeyArrayLengthValue))
257                 searchKeyArrayLength = static_cast<unsigned>(JSValueToNumber(context, searchKeyArrayLengthValue, nullptr));
258             
259             for (unsigned i = 0; i < searchKeyArrayLength; ++i) {
260                 JSValueRef searchKeyValue = JSObjectGetPropertyAtIndex(context, searchKeyArray, i, nullptr);
261                 JSStringRef searchKeyString = JSValueToStringCopy(context, searchKeyValue, nullptr);
262                 if (searchKeyString) {
263                     if (!searchKeyParameter)
264                         searchKeyParameter = [NSMutableArray array];
265                     [searchKeyParameter addObject:[NSString stringWithJSStringRef:searchKeyString]];
266                     JSStringRelease(searchKeyString);
267                 }
268             }
269         }
270         if (searchKeyParameter)
271             [parameterizedAttribute setObject:searchKeyParameter forKey:@"AXSearchKey"];
272     }
273     
274     if (searchText && JSStringGetLength(searchText))
275         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:searchText] forKey:@"AXSearchText"];
276     
277     [parameterizedAttribute setObject:@(visibleOnly) forKey:@"AXVisibleOnly"];
278     
279     [parameterizedAttribute setObject:@(immediateDescendantsOnly) forKey:@"AXImmediateDescendantsOnly"];
280     
281     return parameterizedAttribute;
282 }
283
284 static NSDictionary *selectTextParameterizedAttributeForCriteria(JSContextRef context, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity)
285 {
286     NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
287     
288     if (ambiguityResolution)
289         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:ambiguityResolution] forKey:@"AXSelectTextAmbiguityResolution"];
290     
291     if (searchStrings) {
292         NSMutableArray *searchStringsParameter = [NSMutableArray array];
293         if (JSValueIsString(context, searchStrings)) {
294             JSRetainPtr<JSStringRef> searchStringsString(Adopt, JSValueToStringCopy(context, searchStrings, nullptr));
295             if (searchStringsString)
296                 [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
297         }
298         else if (JSValueIsObject(context, searchStrings)) {
299             JSObjectRef searchStringsArray = JSValueToObject(context, searchStrings, nullptr);
300             unsigned searchStringsArrayLength = 0;
301             
302             JSRetainPtr<JSStringRef> lengthPropertyString(Adopt, JSStringCreateWithUTF8CString("length"));
303             JSValueRef searchStringsArrayLengthValue = JSObjectGetProperty(context, searchStringsArray, lengthPropertyString.get(), nullptr);
304             if (searchStringsArrayLengthValue && JSValueIsNumber(context, searchStringsArrayLengthValue))
305                 searchStringsArrayLength = static_cast<unsigned>(JSValueToNumber(context, searchStringsArrayLengthValue, nullptr));
306             
307             for (unsigned i = 0; i < searchStringsArrayLength; ++i) {
308                 JSRetainPtr<JSStringRef> searchStringsString(Adopt, JSValueToStringCopy(context, JSObjectGetPropertyAtIndex(context, searchStringsArray, i, nullptr), nullptr));
309                 if (searchStringsString)
310                     [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
311             }
312         }
313         [parameterizedAttribute setObject:searchStringsParameter forKey:@"AXSelectTextSearchStrings"];
314     }
315     
316     if (replacementString) {
317         [parameterizedAttribute setObject:@"AXSelectTextActivityFindAndReplace" forKey:@"AXSelectTextActivity"];
318         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:replacementString] forKey:@"AXSelectTextReplacementString"];
319     } else
320         [parameterizedAttribute setObject:@"AXSelectTextActivityFindAndSelect" forKey:@"AXSelectTextActivity"];
321     
322     if (activity)
323         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:activity] forKey:@"AXSelectTextActivity"];
324     
325     return parameterizedAttribute;
326 }
327
328 void AccessibilityUIElement::getLinkedUIElements(Vector<RefPtr<AccessibilityUIElement> >& elementVector)
329 {
330     BEGIN_AX_OBJC_EXCEPTIONS
331     NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
332     convertNSArrayToVector(linkedElements, elementVector);
333     END_AX_OBJC_EXCEPTIONS
334 }
335
336 void AccessibilityUIElement::getDocumentLinks(Vector<RefPtr<AccessibilityUIElement> >& elementVector)
337 {
338     BEGIN_AX_OBJC_EXCEPTIONS
339     NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
340     convertNSArrayToVector(linkElements, elementVector);
341     END_AX_OBJC_EXCEPTIONS
342 }
343
344 void AccessibilityUIElement::getUIElementsWithAttribute(JSStringRef attribute, Vector<RefPtr<AccessibilityUIElement> >& elements) const
345 {
346     BEGIN_AX_OBJC_EXCEPTIONS
347     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
348     if ([value isKindOfClass:[NSArray class]])
349         convertNSArrayToVector(value, elements);
350     END_AX_OBJC_EXCEPTIONS
351 }
352
353 void AccessibilityUIElement::getChildren(Vector<RefPtr<AccessibilityUIElement> >& elementVector)
354 {
355     BEGIN_AX_OBJC_EXCEPTIONS
356     NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
357     convertNSArrayToVector(children, elementVector);
358     END_AX_OBJC_EXCEPTIONS
359 }
360
361 void AccessibilityUIElement::getChildrenWithRange(Vector<RefPtr<AccessibilityUIElement> >& elementVector, unsigned location, unsigned length)
362 {
363     BEGIN_AX_OBJC_EXCEPTIONS
364     NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
365     convertNSArrayToVector(children, elementVector);
366     END_AX_OBJC_EXCEPTIONS
367 }
368
369 JSValueRef AccessibilityUIElement::rowHeaders() const
370 {
371     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
372     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
373     
374     BEGIN_AX_OBJC_EXCEPTIONS
375     Vector<RefPtr<AccessibilityUIElement>> elements;
376     id value = [m_element accessibilityAttributeValue:NSAccessibilityRowHeaderUIElementsAttribute];
377     if ([value isKindOfClass:[NSArray class]])
378         convertNSArrayToVector(value, elements);
379     return convertElementsToObjectArray(context, elements);
380     END_AX_OBJC_EXCEPTIONS
381 }
382
383 JSValueRef AccessibilityUIElement::columnHeaders() const
384 {
385     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
386     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
387
388     BEGIN_AX_OBJC_EXCEPTIONS
389     Vector<RefPtr<AccessibilityUIElement>> elements;
390     id value = [m_element accessibilityAttributeValue:NSAccessibilityColumnHeaderUIElementsAttribute];
391     if ([value isKindOfClass:[NSArray class]])
392         convertNSArrayToVector(value, elements);
393     return convertElementsToObjectArray(context, elements);
394     END_AX_OBJC_EXCEPTIONS
395 }
396     
397 int AccessibilityUIElement::childrenCount()
398 {
399     Vector<RefPtr<AccessibilityUIElement> > children;
400     getChildren(children);
401     
402     return children.size();
403 }
404
405 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::elementAtPoint(int x, int y)
406 {
407     id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
408     if (!element)
409         return nil;
410     
411     return AccessibilityUIElement::create(element);
412 }
413
414 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
415 {
416     return [m_element accessibilityIndexOfChild:element->platformUIElement()];
417 }
418
419 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned index)
420 {
421     Vector<RefPtr<AccessibilityUIElement> > children;
422     getChildrenWithRange(children, index, 1);
423
424     if (children.size() == 1)
425         return children[0];
426     return nullptr;
427 }
428
429 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
430 {
431     BEGIN_AX_OBJC_EXCEPTIONS
432     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
433     if (index < [objects count])
434         return AccessibilityUIElement::create([objects objectAtIndex:index]);
435     END_AX_OBJC_EXCEPTIONS
436     
437     return nullptr;
438 }
439
440 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
441 {
442     BEGIN_AX_OBJC_EXCEPTIONS
443     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityOwnsAttribute];
444     if (index < [objects count])
445         return AccessibilityUIElement::create([objects objectAtIndex:index]);
446     END_AX_OBJC_EXCEPTIONS
447     
448     return nullptr;
449 }
450
451 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
452 {
453     BEGIN_AX_OBJC_EXCEPTIONS
454     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
455     if (index < [objects count])
456         return AccessibilityUIElement::create([objects objectAtIndex:index]);
457     END_AX_OBJC_EXCEPTIONS
458     
459     return nullptr;
460 }
461
462 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaControlsElementAtIndex(unsigned index)
463 {
464     BEGIN_AX_OBJC_EXCEPTIONS
465     NSArray* ariaControls = [m_element accessibilityAttributeValue:@"AXARIAControls"];
466     if (index < [ariaControls count])
467         return AccessibilityUIElement::create([ariaControls objectAtIndex:index]);
468     END_AX_OBJC_EXCEPTIONS
469     return nullptr;
470 }
471
472 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
473 {
474     BEGIN_AX_OBJC_EXCEPTIONS
475     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedRowsAttribute];
476     if (index < [rows count])
477         return AccessibilityUIElement::create([rows objectAtIndex:index]);
478     END_AX_OBJC_EXCEPTIONS
479
480     return nullptr;
481 }
482     
483 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::rowAtIndex(unsigned index)
484 {
485     BEGIN_AX_OBJC_EXCEPTIONS
486     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
487     if (index < [rows count])
488         return AccessibilityUIElement::create([rows objectAtIndex:index]);
489     END_AX_OBJC_EXCEPTIONS
490     
491     return nullptr;
492 }
493
494 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
495 {
496     BEGIN_AX_OBJC_EXCEPTIONS
497     NSArray* array = [m_element accessibilityAttributeValue:NSAccessibilitySelectedChildrenAttribute];
498     if (index < [array count])
499         return AccessibilityUIElement::create([array objectAtIndex:index]);
500     END_AX_OBJC_EXCEPTIONS
501     
502     return nullptr;
503 }
504
505 unsigned AccessibilityUIElement::selectedChildrenCount() const
506 {
507     BEGIN_AX_OBJC_EXCEPTIONS
508     return [m_element accessibilityArrayAttributeCount:NSAccessibilitySelectedChildrenAttribute];
509     END_AX_OBJC_EXCEPTIONS
510
511     return 0;
512 }
513
514 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedRowAtIndex(unsigned index)
515 {
516     BEGIN_AX_OBJC_EXCEPTIONS
517     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilitySelectedRowsAttribute];
518     if (index < [rows count])
519         return AccessibilityUIElement::create([rows objectAtIndex:index]);
520     END_AX_OBJC_EXCEPTIONS
521     
522     return nullptr;
523 }
524
525 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::titleUIElement()
526 {
527     BEGIN_AX_OBJC_EXCEPTIONS
528     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityTitleUIElementAttribute];
529     if (accessibilityObject)
530         return AccessibilityUIElement::create(accessibilityObject);
531     END_AX_OBJC_EXCEPTIONS
532     
533     return nullptr;
534 }
535
536 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::parentElement()
537 {
538     BEGIN_AX_OBJC_EXCEPTIONS
539     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityParentAttribute];
540     if (accessibilityObject)
541         return AccessibilityUIElement::create(accessibilityObject);
542     END_AX_OBJC_EXCEPTIONS
543     
544     return nullptr;
545 }
546
547 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedByRow()
548 {
549     BEGIN_AX_OBJC_EXCEPTIONS
550     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedByRowAttribute];
551     if (accessibilityObject)
552         return AccessibilityUIElement::create(accessibilityObject);
553     END_AX_OBJC_EXCEPTIONS
554     
555     return nullptr;
556 }
557
558 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfLinkedUIElements()
559 {
560     Vector<RefPtr<AccessibilityUIElement> > linkedElements;
561     getLinkedUIElements(linkedElements);
562     return descriptionOfElements(linkedElements);
563 }
564
565 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfDocumentLinks()
566 {
567     Vector<RefPtr<AccessibilityUIElement> > linkElements;
568     getDocumentLinks(linkElements);
569     return descriptionOfElements(linkElements);
570 }
571
572 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfChildren()
573 {
574     Vector<RefPtr<AccessibilityUIElement> > children;
575     getChildren(children);
576     return descriptionOfElements(children);
577 }
578
579 JSRetainPtr<JSStringRef> AccessibilityUIElement::allAttributes()
580 {
581     NSString* attributes = attributesOfElement(m_element);
582     return [attributes createJSStringRef];
583 }
584
585 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
586 {
587     BEGIN_AX_OBJC_EXCEPTIONS
588     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
589     if ([value isKindOfClass:[NSString class]])
590         return [value createJSStringRef];
591     END_AX_OBJC_EXCEPTIONS
592
593     return nullptr;
594 }
595
596 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
597 {
598     BEGIN_AX_OBJC_EXCEPTIONS
599     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
600     if ([value isKindOfClass:[NSNumber class]])
601         return [value doubleValue];
602     END_AX_OBJC_EXCEPTIONS
603     
604     return 0;
605 }
606
607 JSValueRef AccessibilityUIElement::uiElementArrayAttributeValue(JSStringRef attribute) const
608 {
609     WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
610     JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
611     
612     Vector<RefPtr<AccessibilityUIElement>> elements;
613     getUIElementsWithAttribute(attribute, elements);
614     return convertElementsToObjectArray(context, elements);
615 }
616
617 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
618 {
619     BEGIN_AX_OBJC_EXCEPTIONS
620     id uiElement = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
621     return AccessibilityUIElement::create(uiElement);
622     END_AX_OBJC_EXCEPTIONS
623     
624     return nullptr;
625 }
626     
627 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
628 {
629     BEGIN_AX_OBJC_EXCEPTIONS
630     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
631     if ([value isKindOfClass:[NSNumber class]])
632         return [value boolValue];
633     END_AX_OBJC_EXCEPTIONS
634     
635     return false;
636 }
637
638 void AccessibilityUIElement::setBoolAttributeValue(JSStringRef attribute, bool value)
639 {
640     BEGIN_AX_OBJC_EXCEPTIONS
641     [m_element _accessibilitySetTestValue:@(value) forAttribute:[NSString stringWithJSStringRef:attribute]];
642     END_AX_OBJC_EXCEPTIONS
643 }
644
645 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
646 {
647     BEGIN_AX_OBJC_EXCEPTIONS
648     return [m_element accessibilityIsAttributeSettable:[NSString stringWithJSStringRef:attribute]];
649     END_AX_OBJC_EXCEPTIONS
650     
651     return false;
652 }
653
654 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
655 {
656     BEGIN_AX_OBJC_EXCEPTIONS
657     return [[m_element accessibilityAttributeNames] containsObject:[NSString stringWithJSStringRef:attribute]];
658     END_AX_OBJC_EXCEPTIONS
659     
660     return false;
661 }
662
663 JSRetainPtr<JSStringRef> AccessibilityUIElement::parameterizedAttributeNames()
664 {
665     NSArray* supportedParameterizedAttributes = [m_element accessibilityParameterizedAttributeNames];
666     
667     NSMutableString* attributesString = [NSMutableString string];
668     for (NSUInteger i = 0; i < [supportedParameterizedAttributes count]; ++i) {
669         [attributesString appendFormat:@"%@\n", [supportedParameterizedAttributes objectAtIndex:i]];
670     }
671     
672     return [attributesString createJSStringRef];
673 }
674
675 JSRetainPtr<JSStringRef> AccessibilityUIElement::role()
676 {
677     BEGIN_AX_OBJC_EXCEPTIONS
678     NSString *role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleAttribute], m_element);
679     return concatenateAttributeAndValue(@"AXRole", role);
680     END_AX_OBJC_EXCEPTIONS
681     
682     return nullptr;
683 }
684
685 JSRetainPtr<JSStringRef> AccessibilityUIElement::subrole()
686 {
687     BEGIN_AX_OBJC_EXCEPTIONS
688     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilitySubroleAttribute], m_element);
689     return concatenateAttributeAndValue(@"AXSubrole", role);
690     END_AX_OBJC_EXCEPTIONS
691
692     return nullptr;
693 }
694
695 JSRetainPtr<JSStringRef> AccessibilityUIElement::roleDescription()
696 {
697     BEGIN_AX_OBJC_EXCEPTIONS
698     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute], m_element);
699     return concatenateAttributeAndValue(@"AXRoleDescription", role);
700     END_AX_OBJC_EXCEPTIONS
701     
702     return nullptr;
703 }
704
705 JSRetainPtr<JSStringRef> AccessibilityUIElement::computedRoleString()
706 {
707     BEGIN_AX_OBJC_EXCEPTIONS
708     NSString *computedRoleString = descriptionOfValue([m_element accessibilityAttributeValue:@"AXARIARole"], m_element);
709     return [computedRoleString createJSStringRef];
710     END_AX_OBJC_EXCEPTIONS
711     
712     return nullptr;
713 }
714
715 JSRetainPtr<JSStringRef> AccessibilityUIElement::title()
716 {
717     BEGIN_AX_OBJC_EXCEPTIONS
718     NSString* title = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityTitleAttribute], m_element);
719     return concatenateAttributeAndValue(@"AXTitle", title);
720     END_AX_OBJC_EXCEPTIONS
721
722     return nullptr;
723 }
724
725 JSRetainPtr<JSStringRef> AccessibilityUIElement::description()
726 {
727     BEGIN_AX_OBJC_EXCEPTIONS
728     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityDescriptionAttribute], m_element);
729     return concatenateAttributeAndValue(@"AXDescription", description);
730     END_AX_OBJC_EXCEPTIONS
731
732     return nullptr;
733 }
734
735 JSRetainPtr<JSStringRef> AccessibilityUIElement::orientation() const
736 {
737     BEGIN_AX_OBJC_EXCEPTIONS
738     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityOrientationAttribute], m_element);
739     return concatenateAttributeAndValue(@"AXOrientation", description);    
740     END_AX_OBJC_EXCEPTIONS
741
742     return nullptr;
743 }
744
745 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringValue()
746 {
747     BEGIN_AX_OBJC_EXCEPTIONS
748     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityValueAttribute], m_element);
749     if (description)
750         return concatenateAttributeAndValue(@"AXValue", description);
751     END_AX_OBJC_EXCEPTIONS
752
753     return nullptr;
754 }
755
756 JSRetainPtr<JSStringRef> AccessibilityUIElement::language()
757 {
758     BEGIN_AX_OBJC_EXCEPTIONS
759     id description = descriptionOfValue([m_element accessibilityAttributeValue:@"AXLanguage"], m_element);
760     return concatenateAttributeAndValue(@"AXLanguage", description);
761     END_AX_OBJC_EXCEPTIONS
762
763     return nullptr;
764 }
765
766 JSRetainPtr<JSStringRef> AccessibilityUIElement::helpText() const
767 {
768     BEGIN_AX_OBJC_EXCEPTIONS
769     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityHelpAttribute], m_element);
770     return concatenateAttributeAndValue(@"AXHelp", description);
771     END_AX_OBJC_EXCEPTIONS
772     
773     return nullptr;
774 }
775
776 double AccessibilityUIElement::x()
777 {
778     BEGIN_AX_OBJC_EXCEPTIONS
779     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
780     return static_cast<double>([positionValue pointValue].x);    
781     END_AX_OBJC_EXCEPTIONS
782     
783     return 0.0f;
784 }
785
786 double AccessibilityUIElement::y()
787 {
788     BEGIN_AX_OBJC_EXCEPTIONS
789     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
790     return static_cast<double>([positionValue pointValue].y);    
791     END_AX_OBJC_EXCEPTIONS
792     
793     return 0.0f;
794 }
795
796 double AccessibilityUIElement::width()
797 {
798     BEGIN_AX_OBJC_EXCEPTIONS
799     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
800     return static_cast<double>([sizeValue sizeValue].width);
801     END_AX_OBJC_EXCEPTIONS
802     
803     return 0.0f;
804 }
805
806 double AccessibilityUIElement::height()
807 {
808     BEGIN_AX_OBJC_EXCEPTIONS
809     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
810     return static_cast<double>([sizeValue sizeValue].height);
811     END_AX_OBJC_EXCEPTIONS
812     
813     return 0.0f;
814 }
815
816 double AccessibilityUIElement::clickPointX()
817 {
818     BEGIN_AX_OBJC_EXCEPTIONS
819     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
820     return static_cast<double>([positionValue pointValue].x);        
821     END_AX_OBJC_EXCEPTIONS
822     
823     return 0.0f;
824 }
825
826 double AccessibilityUIElement::clickPointY()
827 {
828     BEGIN_AX_OBJC_EXCEPTIONS
829     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
830     return static_cast<double>([positionValue pointValue].y);
831     END_AX_OBJC_EXCEPTIONS
832     
833     return 0.0f;
834 }
835
836 double AccessibilityUIElement::intValue() const
837 {
838     BEGIN_AX_OBJC_EXCEPTIONS
839     id value = [m_element accessibilityAttributeValue:NSAccessibilityValueAttribute];
840     if ([value isKindOfClass:[NSNumber class]])
841         return [(NSNumber*)value doubleValue]; 
842     END_AX_OBJC_EXCEPTIONS
843
844     return 0.0f;
845 }
846
847 double AccessibilityUIElement::minValue()
848 {
849     BEGIN_AX_OBJC_EXCEPTIONS
850     id value = [m_element accessibilityAttributeValue:NSAccessibilityMinValueAttribute];
851     if ([value isKindOfClass:[NSNumber class]])
852         return [(NSNumber*)value doubleValue]; 
853     END_AX_OBJC_EXCEPTIONS
854
855     return 0.0f;
856 }
857
858 double AccessibilityUIElement::maxValue()
859 {
860     BEGIN_AX_OBJC_EXCEPTIONS
861     id value = [m_element accessibilityAttributeValue:NSAccessibilityMaxValueAttribute];
862     if ([value isKindOfClass:[NSNumber class]])
863         return [(NSNumber*)value doubleValue]; 
864     END_AX_OBJC_EXCEPTIONS
865
866     return 0.0;
867 }
868
869 JSRetainPtr<JSStringRef> AccessibilityUIElement::valueDescription()
870 {
871     BEGIN_AX_OBJC_EXCEPTIONS
872     NSString* valueDescription = [m_element accessibilityAttributeValue:NSAccessibilityValueDescriptionAttribute];
873     if ([valueDescription isKindOfClass:[NSString class]])
874         return concatenateAttributeAndValue(@"AXValueDescription", valueDescription);
875     END_AX_OBJC_EXCEPTIONS
876     
877     return nullptr;
878 }
879
880 int AccessibilityUIElement::insertionPointLineNumber()
881 {
882     BEGIN_AX_OBJC_EXCEPTIONS
883     id value = [m_element accessibilityAttributeValue:NSAccessibilityInsertionPointLineNumberAttribute];
884     if ([value isKindOfClass:[NSNumber class]])
885         return [(NSNumber *)value intValue]; 
886     END_AX_OBJC_EXCEPTIONS
887     
888     return -1;
889 }
890
891 bool AccessibilityUIElement::isPressActionSupported()
892 {
893     BEGIN_AX_OBJC_EXCEPTIONS
894     NSArray* actions = [m_element accessibilityActionNames];
895     return [actions containsObject:NSAccessibilityPressAction];
896     END_AX_OBJC_EXCEPTIONS
897     
898     return false;
899 }
900
901 bool AccessibilityUIElement::isIncrementActionSupported()
902 {
903     BEGIN_AX_OBJC_EXCEPTIONS
904     NSArray* actions = [m_element accessibilityActionNames];
905     return [actions containsObject:NSAccessibilityIncrementAction];
906     END_AX_OBJC_EXCEPTIONS
907     
908     return false;
909 }
910
911 bool AccessibilityUIElement::isDecrementActionSupported()
912 {
913     BEGIN_AX_OBJC_EXCEPTIONS
914     NSArray* actions = [m_element accessibilityActionNames];
915     return [actions containsObject:NSAccessibilityDecrementAction];
916     END_AX_OBJC_EXCEPTIONS
917     
918     return false;
919 }
920
921 bool AccessibilityUIElement::isEnabled()
922 {
923     BEGIN_AX_OBJC_EXCEPTIONS
924     id value = [m_element accessibilityAttributeValue:NSAccessibilityEnabledAttribute];
925     if ([value isKindOfClass:[NSNumber class]])
926         return [value boolValue];
927     END_AX_OBJC_EXCEPTIONS
928     
929     return false;
930 }
931
932 bool AccessibilityUIElement::isRequired() const
933 {
934     BEGIN_AX_OBJC_EXCEPTIONS
935     id value = [m_element accessibilityAttributeValue:@"AXRequired"];
936     if ([value isKindOfClass:[NSNumber class]])
937         return [value boolValue];
938     END_AX_OBJC_EXCEPTIONS
939     
940     return false;
941 }
942
943 bool AccessibilityUIElement::isFocused() const
944 {
945     BEGIN_AX_OBJC_EXCEPTIONS
946     id value = [m_element accessibilityAttributeValue:NSAccessibilityFocusedAttribute];
947     if ([value isKindOfClass:[NSNumber class]])
948         return [value boolValue];
949     END_AX_OBJC_EXCEPTIONS
950     
951     return false;
952 }
953
954 bool AccessibilityUIElement::isSelected() const
955 {
956     BEGIN_AX_OBJC_EXCEPTIONS
957     id value = [m_element accessibilityAttributeValue:NSAccessibilitySelectedAttribute];
958     if ([value isKindOfClass:[NSNumber class]])
959         return [value boolValue];
960     END_AX_OBJC_EXCEPTIONS
961     
962     return false;
963 }
964
965 bool AccessibilityUIElement::isSelectedOptionActive() const
966 {
967     // FIXME: implement
968     return false;
969 }
970
971 bool AccessibilityUIElement::isIndeterminate() const
972 {
973     BOOL result = NO;
974     BEGIN_AX_OBJC_EXCEPTIONS
975     id value = [m_element accessibilityAttributeValue:NSAccessibilityValueAttribute];
976     if ([value isKindOfClass:[NSNumber class]])
977         result = [value intValue] == 2;
978     END_AX_OBJC_EXCEPTIONS
979     return result;
980 }
981
982 bool AccessibilityUIElement::isExpanded() const
983 {
984     BEGIN_AX_OBJC_EXCEPTIONS
985     id value = [m_element accessibilityAttributeValue:NSAccessibilityExpandedAttribute];
986     if ([value isKindOfClass:[NSNumber class]])
987         return [value boolValue];
988     END_AX_OBJC_EXCEPTIONS
989     
990     return false;
991 }
992
993 bool AccessibilityUIElement::isChecked() const
994 {
995     // On the Mac, intValue()==1 if a a checkable control is checked.
996     return intValue() == 1;
997 }
998
999 int AccessibilityUIElement::hierarchicalLevel() const
1000 {
1001     BEGIN_AX_OBJC_EXCEPTIONS
1002     id value = [m_element accessibilityAttributeValue:NSAccessibilityDisclosureLevelAttribute];
1003     if ([value isKindOfClass:[NSNumber class]])
1004         return [value intValue];
1005     END_AX_OBJC_EXCEPTIONS
1006
1007     return 0;
1008 }
1009     
1010 JSRetainPtr<JSStringRef> AccessibilityUIElement::classList() const
1011 {
1012     BEGIN_AX_OBJC_EXCEPTIONS
1013     id value = [m_element accessibilityAttributeValue:@"AXDOMClassList"];
1014     if (![value isKindOfClass:[NSArray class]])
1015         return nullptr;
1016     
1017     NSMutableString* classList = [NSMutableString string];
1018     NSInteger length = [value count];
1019     for (NSInteger k = 0; k < length; ++k) {
1020         [classList appendString:[value objectAtIndex:k]];
1021         if (k < length - 1)
1022             [classList appendString:@", "];
1023     }
1024     
1025     return [classList createJSStringRef];
1026     END_AX_OBJC_EXCEPTIONS
1027     
1028     return nullptr;
1029 }
1030
1031 JSRetainPtr<JSStringRef> AccessibilityUIElement::speak()
1032 {
1033     BEGIN_AX_OBJC_EXCEPTIONS
1034     id value = [m_element accessibilityAttributeValue:@"AXDRTSpeechAttribute"];
1035     if ([value isKindOfClass:[NSString class]])
1036         return [value createJSStringRef];
1037     END_AX_OBJC_EXCEPTIONS
1038         
1039     return nullptr;
1040 }
1041
1042 bool AccessibilityUIElement::ariaIsGrabbed() const
1043 {
1044     BEGIN_AX_OBJC_EXCEPTIONS
1045     id value = [m_element accessibilityAttributeValue:NSAccessibilityGrabbedAttribute];
1046     if ([value isKindOfClass:[NSNumber class]])
1047         return [value boolValue];
1048     END_AX_OBJC_EXCEPTIONS
1049
1050     return false;
1051 }
1052
1053 JSRetainPtr<JSStringRef> AccessibilityUIElement::ariaDropEffects() const
1054 {
1055     BEGIN_AX_OBJC_EXCEPTIONS
1056     id value = [m_element accessibilityAttributeValue:NSAccessibilityDropEffectsAttribute];
1057     if (![value isKindOfClass:[NSArray class]])
1058         return nullptr;
1059
1060     NSMutableString* dropEffects = [NSMutableString string];
1061     NSInteger length = [value count];
1062     for (NSInteger k = 0; k < length; ++k) {
1063         [dropEffects appendString:[value objectAtIndex:k]];
1064         if (k < length - 1)
1065             [dropEffects appendString:@","];
1066     }
1067     
1068     return [dropEffects createJSStringRef];
1069     END_AX_OBJC_EXCEPTIONS
1070     
1071     return nullptr;
1072 }
1073
1074 // parameterized attributes
1075 int AccessibilityUIElement::lineForIndex(int index)
1076 {
1077     BEGIN_AX_OBJC_EXCEPTIONS
1078     id value = [m_element accessibilityAttributeValue:NSAccessibilityLineForIndexParameterizedAttribute forParameter:[NSNumber numberWithInt:index]];
1079     if ([value isKindOfClass:[NSNumber class]])
1080         return [(NSNumber *)value intValue]; 
1081     END_AX_OBJC_EXCEPTIONS
1082
1083     return -1;
1084 }
1085
1086 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForLine(int line)
1087 {
1088     BEGIN_AX_OBJC_EXCEPTIONS
1089     id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForLineParameterizedAttribute forParameter:[NSNumber numberWithInt:line]];
1090     if ([value isKindOfClass:[NSValue class]])
1091         return [NSStringFromRange([value rangeValue]) createJSStringRef];
1092     END_AX_OBJC_EXCEPTIONS
1093     
1094     return nullptr;
1095 }
1096
1097 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForPosition(int x, int y)
1098 {
1099     BEGIN_AX_OBJC_EXCEPTIONS
1100     id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForPositionParameterizedAttribute forParameter:[NSValue valueWithPoint:NSMakePoint(x, y)]];
1101     if ([value isKindOfClass:[NSValue class]])
1102         return [NSStringFromRange([value rangeValue]) createJSStringRef];
1103     END_AX_OBJC_EXCEPTIONS
1104
1105     return nullptr;
1106 }
1107
1108 JSRetainPtr<JSStringRef> AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
1109 {
1110     NSRange range = NSMakeRange(location, length);
1111     BEGIN_AX_OBJC_EXCEPTIONS
1112     id value = [m_element accessibilityAttributeValue:NSAccessibilityBoundsForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
1113     NSRect rect = NSMakeRect(0,0,0,0);
1114     if ([value isKindOfClass:[NSValue class]])
1115         rect = [value rectValue]; 
1116     
1117     // don't return position information because it is platform dependent
1118     NSMutableString* boundsDescription = [NSMutableString stringWithFormat:@"{{%f, %f}, {%f, %f}}",-1.0f,-1.0f,rect.size.width,rect.size.height];
1119     return [boundsDescription createJSStringRef];
1120     END_AX_OBJC_EXCEPTIONS
1121     
1122     return nullptr;
1123 }
1124
1125 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
1126 {
1127     NSRange range = NSMakeRange(location, length);
1128     BEGIN_AX_OBJC_EXCEPTIONS
1129     id string = [m_element accessibilityAttributeValue:NSAccessibilityStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
1130     if (![string isKindOfClass:[NSString class]])
1131         return nullptr;
1132     
1133     return [string createJSStringRef];
1134     END_AX_OBJC_EXCEPTIONS
1135     
1136     return nullptr;
1137 }
1138
1139 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
1140 {
1141     NSRange range = NSMakeRange(location, length);
1142     BEGIN_AX_OBJC_EXCEPTIONS
1143     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
1144     if (![string isKindOfClass:[NSAttributedString class]])
1145         return nullptr;
1146     
1147     NSString* stringWithAttrs = [string description];
1148     return [stringWithAttrs createJSStringRef];
1149     END_AX_OBJC_EXCEPTIONS
1150     
1151     return nullptr;
1152 }
1153
1154 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
1155 {
1156     NSRange range = NSMakeRange(location, length);
1157     BEGIN_AX_OBJC_EXCEPTIONS
1158     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
1159     if (![string isKindOfClass:[NSAttributedString class]])
1160         return false;
1161
1162     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
1163     BOOL misspelled = [[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue];
1164 #if PLATFORM(MAC)
1165     if (misspelled)
1166         misspelled = [[attrs objectForKey:NSAccessibilityMarkedMisspelledTextAttribute] boolValue];
1167 #endif
1168     return misspelled;
1169     END_AX_OBJC_EXCEPTIONS
1170     
1171     return false;
1172 }
1173
1174 unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef context, AccessibilityUIElement *startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
1175 {
1176     BEGIN_AX_OBJC_EXCEPTIONS
1177     NSDictionary *parameterizedAttribute = searchPredicateParameterizedAttributeForSearchCriteria(context, startElement, isDirectionNext, UINT_MAX, searchKey, searchText, visibleOnly, immediateDescendantsOnly);
1178     id value = [m_element accessibilityAttributeValue:@"AXUIElementCountForSearchPredicate" forParameter:parameterizedAttribute];
1179     if ([value isKindOfClass:[NSNumber class]])
1180         return [value unsignedIntValue];
1181     END_AX_OBJC_EXCEPTIONS
1182     
1183     return 0;
1184 }
1185
1186 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement *startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
1187 {
1188     BEGIN_AX_OBJC_EXCEPTIONS
1189     NSDictionary *parameterizedAttribute = searchPredicateParameterizedAttributeForSearchCriteria(context, startElement, isDirectionNext, 1, searchKey, searchText, visibleOnly, immediateDescendantsOnly);
1190     id value = [m_element accessibilityAttributeValue:@"AXUIElementsForSearchPredicate" forParameter:parameterizedAttribute];
1191     if ([value isKindOfClass:[NSArray class]])
1192         return AccessibilityUIElement::create([value lastObject]);
1193     END_AX_OBJC_EXCEPTIONS
1194     
1195     return nullptr;
1196 }
1197
1198 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectTextWithCriteria(JSContextRef context, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity)
1199 {
1200     BEGIN_AX_OBJC_EXCEPTIONS
1201     NSDictionary *parameterizedAttribute = selectTextParameterizedAttributeForCriteria(context, ambiguityResolution, searchStrings, replacementString, activity);
1202     id result = [m_element accessibilityAttributeValue:@"AXSelectTextWithCriteria" forParameter:parameterizedAttribute];
1203     if ([result isKindOfClass:[NSString class]])
1204         return [result createJSStringRef];
1205     END_AX_OBJC_EXCEPTIONS
1206     
1207     return nullptr;
1208 }
1209
1210 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
1211 {
1212     // not yet defined in AppKit... odd
1213     BEGIN_AX_OBJC_EXCEPTIONS
1214     NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
1215     Vector<RefPtr<AccessibilityUIElement> > columnHeadersVector;
1216     convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
1217     return descriptionOfElements(columnHeadersVector);
1218     END_AX_OBJC_EXCEPTIONS
1219     
1220     return nullptr;
1221 }
1222
1223 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRowHeaders()
1224 {
1225     BEGIN_AX_OBJC_EXCEPTIONS
1226     NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
1227     Vector<RefPtr<AccessibilityUIElement> > rowHeadersVector;
1228     convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
1229     return descriptionOfElements(rowHeadersVector);
1230     END_AX_OBJC_EXCEPTIONS
1231     
1232     return nullptr;
1233 }
1234
1235 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumns()
1236 {
1237     BEGIN_AX_OBJC_EXCEPTIONS
1238     NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
1239     Vector<RefPtr<AccessibilityUIElement> > columnsVector;
1240     convertNSArrayToVector(columnsArray, columnsVector);
1241     return descriptionOfElements(columnsVector);
1242     END_AX_OBJC_EXCEPTIONS
1243     
1244     return nullptr;
1245 }
1246
1247 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRows()
1248 {
1249     BEGIN_AX_OBJC_EXCEPTIONS
1250     NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
1251     Vector<RefPtr<AccessibilityUIElement> > rowsVector;
1252     convertNSArrayToVector(rowsArray, rowsVector);
1253     return descriptionOfElements(rowsVector);
1254     END_AX_OBJC_EXCEPTIONS
1255     
1256     return nullptr;
1257 }
1258
1259 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfVisibleCells()
1260 {
1261     BEGIN_AX_OBJC_EXCEPTIONS
1262     NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
1263     Vector<RefPtr<AccessibilityUIElement> > cellsVector;
1264     convertNSArrayToVector(cellsArray, cellsVector);
1265     return descriptionOfElements(cellsVector);
1266     END_AX_OBJC_EXCEPTIONS
1267     
1268     return nullptr;
1269 }
1270
1271 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfHeader()
1272 {
1273     BEGIN_AX_OBJC_EXCEPTIONS
1274     id headerObject = [m_element accessibilityAttributeValue:NSAccessibilityHeaderAttribute];
1275     if (!headerObject)
1276         return [@"" createJSStringRef];
1277     
1278     Vector<RefPtr<AccessibilityUIElement> > headerVector;
1279     headerVector.append(AccessibilityUIElement::create(headerObject));
1280     return descriptionOfElements(headerVector);
1281     END_AX_OBJC_EXCEPTIONS
1282     
1283     return nullptr;
1284 }
1285
1286 int AccessibilityUIElement::rowCount()
1287 {
1288     BEGIN_AX_OBJC_EXCEPTIONS
1289     return [m_element accessibilityArrayAttributeCount:NSAccessibilityRowsAttribute];
1290     END_AX_OBJC_EXCEPTIONS
1291     
1292     return 0;
1293 }
1294
1295 int AccessibilityUIElement::columnCount()
1296 {
1297     BEGIN_AX_OBJC_EXCEPTIONS
1298     return [m_element accessibilityArrayAttributeCount:NSAccessibilityColumnsAttribute];
1299     END_AX_OBJC_EXCEPTIONS
1300     
1301     return 0;
1302 }
1303
1304 int AccessibilityUIElement::indexInTable()
1305 {
1306     BEGIN_AX_OBJC_EXCEPTIONS
1307     NSNumber* indexNumber = [m_element accessibilityAttributeValue:NSAccessibilityIndexAttribute];
1308     if (indexNumber)
1309         return [indexNumber intValue];
1310     END_AX_OBJC_EXCEPTIONS
1311
1312     return -1;
1313 }
1314
1315 JSRetainPtr<JSStringRef> AccessibilityUIElement::rowIndexRange()
1316 {
1317     NSRange range = NSMakeRange(0, 0);
1318     BEGIN_AX_OBJC_EXCEPTIONS
1319     NSValue* indexRange = [m_element accessibilityAttributeValue:@"AXRowIndexRange"];
1320     if (indexRange)
1321         range = [indexRange rangeValue];
1322     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1323     return [rangeDescription createJSStringRef];
1324     END_AX_OBJC_EXCEPTIONS
1325     
1326     return nullptr;
1327 }
1328
1329 JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange()
1330 {
1331     NSRange range = NSMakeRange(0, 0);
1332     BEGIN_AX_OBJC_EXCEPTIONS
1333     NSNumber* indexRange = [m_element accessibilityAttributeValue:@"AXColumnIndexRange"];
1334     if (indexRange)
1335         range = [indexRange rangeValue];
1336     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1337     return [rangeDescription createJSStringRef];
1338     END_AX_OBJC_EXCEPTIONS
1339     
1340     return nullptr;
1341 }
1342
1343 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1344 {
1345     NSArray *colRowArray = [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:col], [NSNumber numberWithUnsignedInt:row], nil];
1346     BEGIN_AX_OBJC_EXCEPTIONS
1347     return AccessibilityUIElement::create([m_element accessibilityAttributeValue:@"AXCellForColumnAndRow" forParameter:colRowArray]);
1348     END_AX_OBJC_EXCEPTIONS    
1349
1350     return nullptr;
1351 }
1352
1353 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::horizontalScrollbar() const
1354 {
1355     if (!m_element)
1356         return nullptr;
1357
1358     BEGIN_AX_OBJC_EXCEPTIONS
1359     return AccessibilityUIElement::create([m_element accessibilityAttributeValue:NSAccessibilityHorizontalScrollBarAttribute]);
1360     END_AX_OBJC_EXCEPTIONS    
1361     
1362     return nullptr;
1363 }
1364
1365 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::verticalScrollbar() const
1366 {
1367     if (!m_element)
1368         return nullptr;
1369     
1370     BEGIN_AX_OBJC_EXCEPTIONS
1371     return AccessibilityUIElement::create([m_element accessibilityAttributeValue:NSAccessibilityVerticalScrollBarAttribute]);
1372     END_AX_OBJC_EXCEPTIONS        
1373
1374     return nullptr;
1375 }
1376
1377 void AccessibilityUIElement::scrollToMakeVisible()
1378 {
1379     BEGIN_AX_OBJC_EXCEPTIONS
1380     [m_element accessibilityPerformAction:@"AXScrollToVisible"];
1381     END_AX_OBJC_EXCEPTIONS
1382 }
1383     
1384 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
1385 {
1386     BEGIN_AX_OBJC_EXCEPTIONS
1387     [m_element _accessibilityScrollToGlobalPoint:NSMakePoint(x, y)];
1388     END_AX_OBJC_EXCEPTIONS
1389 }
1390
1391 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
1392 {
1393     BEGIN_AX_OBJC_EXCEPTIONS
1394     [m_element _accessibilityScrollToMakeVisibleWithSubFocus:NSMakeRect(x, y, width, height)];
1395     END_AX_OBJC_EXCEPTIONS
1396 }
1397
1398 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectedTextRange()
1399 {
1400     NSRange range = NSMakeRange(NSNotFound, 0);
1401     BEGIN_AX_OBJC_EXCEPTIONS
1402     NSValue *indexRange = [m_element accessibilityAttributeValue:NSAccessibilitySelectedTextRangeAttribute];
1403     if (indexRange)
1404         range = [indexRange rangeValue];
1405     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1406     return [rangeDescription createJSStringRef];
1407     END_AX_OBJC_EXCEPTIONS
1408     
1409     return nullptr;
1410 }
1411
1412 bool AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1413 {
1414     NSRange textRange = NSMakeRange(location, length);
1415     NSValue *textRangeValue = [NSValue valueWithRange:textRange];
1416     BEGIN_AX_OBJC_EXCEPTIONS
1417     [m_element accessibilitySetValue:textRangeValue forAttribute:NSAccessibilitySelectedTextRangeAttribute];
1418     END_AX_OBJC_EXCEPTIONS
1419
1420     return true;
1421 }
1422
1423 bool AccessibilityUIElement::setSelectedVisibleTextRange(AccessibilityTextMarkerRange* markerRange)
1424 {
1425     BEGIN_AX_OBJC_EXCEPTIONS
1426     [m_element accessibilitySetValue:(id)markerRange->platformTextMarkerRange() forAttribute:NSAccessibilitySelectedTextMarkerRangeAttribute];
1427     END_AX_OBJC_EXCEPTIONS
1428
1429     return true;
1430 }
1431
1432 void AccessibilityUIElement::increment()
1433 {
1434     BEGIN_AX_OBJC_EXCEPTIONS
1435     [m_element accessibilityPerformAction:NSAccessibilityIncrementAction];
1436     END_AX_OBJC_EXCEPTIONS
1437 }
1438
1439 void AccessibilityUIElement::decrement()
1440 {
1441     BEGIN_AX_OBJC_EXCEPTIONS
1442     [m_element accessibilityPerformAction:NSAccessibilityDecrementAction];
1443     END_AX_OBJC_EXCEPTIONS
1444 }
1445
1446 void AccessibilityUIElement::showMenu()
1447 {
1448     BEGIN_AX_OBJC_EXCEPTIONS
1449     [m_element accessibilityPerformAction:NSAccessibilityShowMenuAction];
1450     END_AX_OBJC_EXCEPTIONS
1451 }
1452
1453 void AccessibilityUIElement::press()
1454 {
1455     BEGIN_AX_OBJC_EXCEPTIONS
1456     [m_element accessibilityPerformAction:NSAccessibilityPressAction];
1457     END_AX_OBJC_EXCEPTIONS
1458 }
1459
1460 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1461 {
1462     BEGIN_AX_OBJC_EXCEPTIONS
1463     NSArray* array = [NSArray arrayWithObject:element->platformUIElement()];
1464     [m_element accessibilitySetValue:array forAttribute:NSAccessibilitySelectedChildrenAttribute];
1465     END_AX_OBJC_EXCEPTIONS    
1466 }
1467
1468 void AccessibilityUIElement::setSelectedChildAtIndex(unsigned index) const
1469 {
1470     BEGIN_AX_OBJC_EXCEPTIONS
1471     RefPtr<AccessibilityUIElement> element = const_cast<AccessibilityUIElement*>(this)->childAtIndex(index);
1472     if (!element)
1473         return;
1474     NSArray *selectedChildren = [m_element accessibilityAttributeValue:NSAccessibilitySelectedChildrenAttribute];
1475     NSArray *array = [NSArray arrayWithObject:element->platformUIElement()];
1476     if (selectedChildren)
1477         array = [selectedChildren arrayByAddingObjectsFromArray:array];
1478     [m_element _accessibilitySetValue:array forAttribute:NSAccessibilitySelectedChildrenAttribute];
1479     END_AX_OBJC_EXCEPTIONS
1480 }
1481
1482 void AccessibilityUIElement::removeSelectionAtIndex(unsigned index) const
1483 {
1484     BEGIN_AX_OBJC_EXCEPTIONS
1485     RefPtr<AccessibilityUIElement> element = const_cast<AccessibilityUIElement*>(this)->childAtIndex(index);
1486     NSArray *selectedChildren = [m_element accessibilityAttributeValue:NSAccessibilitySelectedChildrenAttribute];
1487     if (!element || !selectedChildren)
1488         return;
1489     NSMutableArray *array = [NSMutableArray arrayWithArray:selectedChildren];
1490     [array removeObject:element->platformUIElement()];
1491     [m_element _accessibilitySetValue:array forAttribute:NSAccessibilitySelectedChildrenAttribute];
1492     END_AX_OBJC_EXCEPTIONS
1493 }
1494
1495 JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const
1496 {
1497     // FIXME: implement
1498     return JSStringCreateWithCharacters(0, 0);
1499 }
1500
1501 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentEncoding()
1502 {
1503     BEGIN_AX_OBJC_EXCEPTIONS
1504     id value = [m_element accessibilityAttributeValue:@"AXDocumentEncoding"];
1505     if ([value isKindOfClass:[NSString class]])
1506         return [value createJSStringRef];
1507     END_AX_OBJC_EXCEPTIONS
1508     
1509     return JSStringCreateWithCharacters(0, 0);
1510 }
1511
1512 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentURI()
1513 {
1514     BEGIN_AX_OBJC_EXCEPTIONS
1515     id value = [m_element accessibilityAttributeValue:@"AXDocumentURI"];
1516     if ([value isKindOfClass:[NSString class]])
1517         return [value createJSStringRef];
1518     END_AX_OBJC_EXCEPTIONS
1519     
1520     return JSStringCreateWithCharacters(0, 0);
1521 }
1522
1523 JSRetainPtr<JSStringRef> AccessibilityUIElement::url()
1524 {
1525     BEGIN_AX_OBJC_EXCEPTIONS
1526     NSURL *url = [m_element accessibilityAttributeValue:NSAccessibilityURLAttribute];
1527     return [[url absoluteString] createJSStringRef];    
1528     END_AX_OBJC_EXCEPTIONS
1529     
1530     return nullptr;
1531 }
1532
1533 bool AccessibilityUIElement::addNotificationListener(JSValueRef functionCallback)
1534 {
1535     if (!functionCallback)
1536         return false;
1537  
1538     // Mac programmers should not be adding more than one notification listener per element.
1539     // Other platforms may be different.
1540     if (m_notificationHandler)
1541         return false;
1542     m_notificationHandler = [[AccessibilityNotificationHandler alloc] init];
1543     [m_notificationHandler setPlatformElement:platformUIElement()];
1544     [m_notificationHandler setCallback:functionCallback];
1545     [m_notificationHandler startObserving];
1546
1547     return true;
1548 }
1549
1550 bool AccessibilityUIElement::removeNotificationListener()
1551 {
1552     // Mac programmers should not be trying to remove a listener that's already removed.
1553     ASSERT(m_notificationHandler);
1554
1555     [m_notificationHandler stopObserving];
1556     [m_notificationHandler release];
1557     m_notificationHandler = nil;
1558     
1559     return true;
1560 }
1561
1562 bool AccessibilityUIElement::isFocusable() const
1563 {
1564     bool result = false;
1565     BEGIN_AX_OBJC_EXCEPTIONS
1566     result = [m_element accessibilityIsAttributeSettable:NSAccessibilityFocusedAttribute];
1567     END_AX_OBJC_EXCEPTIONS
1568     
1569     return result;
1570 }
1571
1572 bool AccessibilityUIElement::isSelectable() const
1573 {
1574     bool result = false;
1575     BEGIN_AX_OBJC_EXCEPTIONS
1576     result = [m_element accessibilityIsAttributeSettable:NSAccessibilitySelectedAttribute];
1577     END_AX_OBJC_EXCEPTIONS
1578     return result;
1579 }
1580
1581 bool AccessibilityUIElement::isMultiSelectable() const
1582 {
1583     BOOL result = NO;
1584     BEGIN_AX_OBJC_EXCEPTIONS
1585     id value = [m_element accessibilityAttributeValue:@"AXIsMultiSelectable"];
1586     if ([value isKindOfClass:[NSNumber class]])
1587         result = [value boolValue];
1588     END_AX_OBJC_EXCEPTIONS
1589     return result;
1590 }
1591
1592 bool AccessibilityUIElement::isVisible() const
1593 {
1594     // FIXME: implement
1595     return false;
1596 }
1597
1598 bool AccessibilityUIElement::isOffScreen() const
1599 {
1600     // FIXME: implement
1601     return false;
1602 }
1603
1604 bool AccessibilityUIElement::isCollapsed() const
1605 {
1606     // FIXME: implement
1607     return false;
1608 }
1609
1610 bool AccessibilityUIElement::isIgnored() const
1611 {
1612     BOOL result = NO;
1613     BEGIN_AX_OBJC_EXCEPTIONS
1614     result = [m_element accessibilityIsIgnored];
1615     END_AX_OBJC_EXCEPTIONS
1616     return result;
1617 }
1618
1619 bool AccessibilityUIElement::hasPopup() const
1620 {
1621     BEGIN_AX_OBJC_EXCEPTIONS
1622     id value = [m_element accessibilityAttributeValue:@"AXHasPopup"];
1623     if ([value isKindOfClass:[NSNumber class]])
1624         return [value boolValue];
1625     END_AX_OBJC_EXCEPTIONS
1626
1627     return false;
1628 }
1629
1630 void AccessibilityUIElement::takeFocus()
1631 {
1632     BEGIN_AX_OBJC_EXCEPTIONS
1633     [m_element accessibilitySetValue:@YES forAttribute:NSAccessibilityFocusedAttribute];
1634     END_AX_OBJC_EXCEPTIONS
1635 }
1636
1637 void AccessibilityUIElement::takeSelection()
1638 {
1639     // FIXME: implement
1640 }
1641
1642 void AccessibilityUIElement::addSelection()
1643 {
1644     // FIXME: implement
1645 }
1646
1647 void AccessibilityUIElement::removeSelection()
1648 {
1649     // FIXME: implement
1650 }
1651
1652 // Text markers
1653 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::lineTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
1654 {
1655     BEGIN_AX_OBJC_EXCEPTIONS
1656     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXLineTextMarkerRangeForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1657     return AccessibilityTextMarkerRange::create(textMarkerRange);
1658     END_AX_OBJC_EXCEPTIONS
1659     
1660     return nullptr;
1661 }
1662
1663 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1664 {
1665     BEGIN_AX_OBJC_EXCEPTIONS
1666     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUIElement" forParameter:element->platformUIElement()];
1667     return AccessibilityTextMarkerRange::create(textMarkerRange);
1668     END_AX_OBJC_EXCEPTIONS
1669     
1670     return nullptr;
1671 }
1672
1673 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1674 {
1675     BEGIN_AX_OBJC_EXCEPTIONS
1676     NSNumber* lengthValue = [m_element accessibilityAttributeValue:@"AXLengthForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1677     return [lengthValue intValue];
1678     END_AX_OBJC_EXCEPTIONS
1679     
1680     return 0;
1681 }
1682
1683 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1684 {
1685     BEGIN_AX_OBJC_EXCEPTIONS
1686     id previousMarker = [m_element accessibilityAttributeValue:@"AXPreviousTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1687     return AccessibilityTextMarker::create(previousMarker);
1688     END_AX_OBJC_EXCEPTIONS
1689     
1690     return nullptr;
1691 }
1692
1693 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1694 {
1695     BEGIN_AX_OBJC_EXCEPTIONS
1696     id nextMarker = [m_element accessibilityAttributeValue:@"AXNextTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1697     return AccessibilityTextMarker::create(nextMarker);
1698     END_AX_OBJC_EXCEPTIONS
1699     
1700     return nullptr;
1701 }
1702
1703 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1704 {
1705     BEGIN_AX_OBJC_EXCEPTIONS
1706     id textString = [m_element accessibilityAttributeValue:@"AXStringForTextMarkerRange" forParameter:(id)markerRange->platformTextMarkerRange()];
1707     return [textString createJSStringRef];
1708     END_AX_OBJC_EXCEPTIONS
1709     
1710     return nullptr;
1711 }
1712
1713 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1714 {
1715     BEGIN_AX_OBJC_EXCEPTIONS
1716     NSArray* textMarkers = [NSArray arrayWithObjects:(id)startMarker->platformTextMarker(), (id)endMarker->platformTextMarker(), nil];
1717     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUnorderedTextMarkers" forParameter:textMarkers];
1718     return AccessibilityTextMarkerRange::create(textMarkerRange);
1719     END_AX_OBJC_EXCEPTIONS
1720     
1721     return nullptr;
1722 }
1723     
1724 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::selectedTextMarkerRange()
1725 {
1726     BEGIN_AX_OBJC_EXCEPTIONS
1727     id textMarkerRange = [m_element accessibilityAttributeValue:NSAccessibilitySelectedTextMarkerRangeAttribute];
1728     return AccessibilityTextMarkerRange::create(textMarkerRange);
1729     END_AX_OBJC_EXCEPTIONS
1730     
1731     return nullptr;
1732 }
1733
1734 void AccessibilityUIElement::resetSelectedTextMarkerRange()
1735 {
1736     id start = [m_element accessibilityAttributeValue:@"AXStartTextMarker"];
1737     if (!start)
1738         return;
1739     
1740     NSArray* textMarkers = @[start, start];
1741     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUnorderedTextMarkers" forParameter:textMarkers];
1742     if (!textMarkerRange)
1743         return;
1744     
1745     BEGIN_AX_OBJC_EXCEPTIONS
1746     [m_element _accessibilitySetTestValue:textMarkerRange forAttribute:NSAccessibilitySelectedTextMarkerRangeAttribute];
1747     END_AX_OBJC_EXCEPTIONS
1748 }
1749
1750 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1751 {
1752     BEGIN_AX_OBJC_EXCEPTIONS
1753     id textMarker = [m_element accessibilityAttributeValue:@"AXStartTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1754     return AccessibilityTextMarker::create(textMarker);
1755     END_AX_OBJC_EXCEPTIONS
1756     
1757     return nullptr;
1758 }
1759
1760 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1761 {
1762     BEGIN_AX_OBJC_EXCEPTIONS
1763     id textMarker = [m_element accessibilityAttributeValue:@"AXEndTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1764     return AccessibilityTextMarker::create(textMarker);
1765     END_AX_OBJC_EXCEPTIONS
1766     
1767     return nullptr;
1768 }
1769
1770 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForBounds(int x, int y, int width, int height)
1771 {
1772     BEGIN_AX_OBJC_EXCEPTIONS
1773     id textMarker = [m_element accessibilityAttributeValue:NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute forParameter:[NSValue valueWithRect:NSMakeRect(x, y, width, height)]];
1774     return AccessibilityTextMarker::create(textMarker);
1775     END_AX_OBJC_EXCEPTIONS
1776     
1777     return nullptr;
1778 }
1779
1780 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForBounds(int x, int y, int width, int height)
1781 {
1782     BEGIN_AX_OBJC_EXCEPTIONS
1783     id textMarker = [m_element accessibilityAttributeValue:NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute forParameter:[NSValue valueWithRect:NSMakeRect(x, y, width, height)]];
1784     return AccessibilityTextMarker::create(textMarker);
1785     END_AX_OBJC_EXCEPTIONS
1786     
1787     return nullptr;
1788 }
1789
1790 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForPoint(int x, int y)
1791 {
1792     BEGIN_AX_OBJC_EXCEPTIONS
1793     id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForPosition" forParameter:[NSValue valueWithPoint:NSMakePoint(x, y)]];
1794     return AccessibilityTextMarker::create(textMarker);
1795     END_AX_OBJC_EXCEPTIONS
1796     
1797     return nullptr;
1798 }
1799
1800 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1801 {
1802     BEGIN_AX_OBJC_EXCEPTIONS
1803     id uiElement = [m_element accessibilityAttributeValue:@"AXUIElementForTextMarker" forParameter:(id)marker->platformTextMarker()];
1804     if (uiElement)
1805         return AccessibilityUIElement::create(uiElement);
1806     END_AX_OBJC_EXCEPTIONS
1807     
1808     return nullptr;
1809 }
1810     
1811 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
1812 {
1813     BEGIN_AX_OBJC_EXCEPTIONS
1814     NSAttributedString* string = [m_element accessibilityAttributeValue:@"AXAttributedStringForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1815     if (![string isKindOfClass:[NSAttributedString class]])
1816         return false;
1817     
1818     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
1819     if ([attrs objectForKey:[NSString stringWithJSStringRef:attribute]])
1820         return true;    
1821     END_AX_OBJC_EXCEPTIONS
1822     
1823     return false;
1824 }
1825     
1826 int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
1827 {
1828     BEGIN_AX_OBJC_EXCEPTIONS
1829     NSNumber* indexNumber = [m_element accessibilityAttributeValue:@"AXIndexForTextMarker" forParameter:(id)marker->platformTextMarker()];
1830     return [indexNumber intValue];
1831     END_AX_OBJC_EXCEPTIONS
1832     
1833     return -1;
1834 }
1835
1836 bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
1837 {
1838     BEGIN_AX_OBJC_EXCEPTIONS
1839     NSNumber* validNumber = [m_element accessibilityAttributeValue:@"AXTextMarkerIsValid" forParameter:(id)textMarker->platformTextMarker()];
1840     return [validNumber boolValue];
1841     END_AX_OBJC_EXCEPTIONS
1842     
1843     return false;
1844 }
1845
1846 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int textIndex)
1847 {
1848     BEGIN_AX_OBJC_EXCEPTIONS
1849     id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForIndex" forParameter:[NSNumber numberWithInteger:textIndex]];
1850     return AccessibilityTextMarker::create(textMarker);
1851     END_AX_OBJC_EXCEPTIONS
1852     
1853     return nullptr;
1854 }
1855     
1856 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarker()
1857 {
1858     BEGIN_AX_OBJC_EXCEPTIONS
1859     id textMarker = [m_element accessibilityAttributeValue:@"AXStartTextMarker"];
1860     return AccessibilityTextMarker::create(textMarker);
1861     END_AX_OBJC_EXCEPTIONS
1862     
1863     return nullptr;
1864 }
1865
1866 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarker()
1867 {
1868     BEGIN_AX_OBJC_EXCEPTIONS
1869     id textMarker = [m_element accessibilityAttributeValue:@"AXEndTextMarker"];
1870     return AccessibilityTextMarker::create(textMarker);
1871     END_AX_OBJC_EXCEPTIONS
1872     
1873     return nullptr;
1874 }
1875
1876 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
1877 {
1878     BEGIN_AX_OBJC_EXCEPTIONS
1879     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXLeftWordTextMarkerRangeForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1880     return AccessibilityTextMarkerRange::create(textMarkerRange);
1881     END_AX_OBJC_EXCEPTIONS
1882     
1883     return nullptr;
1884 }
1885
1886 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
1887 {
1888     BEGIN_AX_OBJC_EXCEPTIONS
1889     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXRightWordTextMarkerRangeForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1890     return AccessibilityTextMarkerRange::create(textMarkerRange);
1891     END_AX_OBJC_EXCEPTIONS
1892     
1893     return nullptr;
1894 }
1895
1896 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
1897 {
1898     BEGIN_AX_OBJC_EXCEPTIONS
1899     id previousWordStartMarker = [m_element accessibilityAttributeValue:@"AXPreviousWordStartTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1900     return AccessibilityTextMarker::create(previousWordStartMarker);
1901     END_AX_OBJC_EXCEPTIONS
1902     
1903     return nullptr;
1904 }
1905
1906 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
1907 {
1908     BEGIN_AX_OBJC_EXCEPTIONS
1909     id nextWordEndMarker = [m_element accessibilityAttributeValue:@"AXNextWordEndTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1910     return AccessibilityTextMarker::create(nextWordEndMarker);
1911     END_AX_OBJC_EXCEPTIONS
1912     
1913     return nullptr;
1914 }
1915
1916 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
1917 {
1918     BEGIN_AX_OBJC_EXCEPTIONS
1919     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXParagraphTextMarkerRangeForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1920     return AccessibilityTextMarkerRange::create(textMarkerRange);
1921     END_AX_OBJC_EXCEPTIONS
1922     
1923     return nullptr;
1924 }
1925
1926 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
1927 {
1928     BEGIN_AX_OBJC_EXCEPTIONS
1929     id previousParagraphStartMarker = [m_element accessibilityAttributeValue:@"AXPreviousParagraphStartTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1930     return AccessibilityTextMarker::create(previousParagraphStartMarker);
1931     END_AX_OBJC_EXCEPTIONS
1932     
1933     return nullptr;
1934 }
1935
1936 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
1937 {
1938     BEGIN_AX_OBJC_EXCEPTIONS
1939     id nextParagraphEndMarker = [m_element accessibilityAttributeValue:@"AXNextParagraphEndTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1940     return AccessibilityTextMarker::create(nextParagraphEndMarker);
1941     END_AX_OBJC_EXCEPTIONS
1942     
1943     return nullptr;
1944 }
1945
1946 static NSString *_convertMathMultiscriptPairsToString(NSArray *pairs)
1947 {
1948     __block NSMutableString *result = [NSMutableString string];
1949     [pairs enumerateObjectsUsingBlock:^(id pair, NSUInteger index, BOOL *stop) {
1950         for (NSString *key in pair)
1951             [result appendFormat:@"\t%lu. %@ = %@\n", (unsigned long)index, key, [[pair objectForKey:key] accessibilityAttributeValue:NSAccessibilitySubroleAttribute]];
1952     }];
1953     
1954     return result;
1955 }
1956     
1957 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPostscriptsDescription() const
1958 {
1959     BEGIN_AX_OBJC_EXCEPTIONS
1960     NSArray *pairs = [m_element accessibilityAttributeValue:@"AXMathPostscripts"];
1961     return [_convertMathMultiscriptPairsToString(pairs) createJSStringRef];
1962     END_AX_OBJC_EXCEPTIONS
1963     
1964     return nullptr;
1965 }
1966
1967 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPrescriptsDescription() const
1968 {
1969     BEGIN_AX_OBJC_EXCEPTIONS
1970     NSArray *pairs = [m_element accessibilityAttributeValue:@"AXMathPrescripts"];
1971     return [_convertMathMultiscriptPairsToString(pairs) createJSStringRef];
1972     END_AX_OBJC_EXCEPTIONS
1973     
1974     return nullptr;
1975 }
1976     
1977 JSRetainPtr<JSStringRef> AccessibilityUIElement::pathDescription() const
1978 {
1979     BEGIN_AX_OBJC_EXCEPTIONS
1980     NSMutableString *result = [NSMutableString stringWithString:@"\nStart Path\n"];
1981     NSBezierPath *bezierPath = [m_element accessibilityAttributeValue:NSAccessibilityPathAttribute];
1982     
1983     NSUInteger elementCount = [bezierPath elementCount];
1984     NSPoint points[3];
1985     for (NSUInteger i = 0; i < elementCount; i++) {
1986         switch ([bezierPath elementAtIndex:i associatedPoints:points]) {
1987         case NSMoveToBezierPathElement:
1988             [result appendString:@"\tMove to point\n"];
1989             break;
1990             
1991         case NSLineToBezierPathElement:
1992             [result appendString:@"\tLine to\n"];
1993             break;
1994             
1995         case NSCurveToBezierPathElement:
1996             [result appendString:@"\tCurve to\n"];
1997             break;
1998             
1999         case NSClosePathBezierPathElement:
2000             [result appendString:@"\tClose\n"];
2001             break;
2002         }
2003     }
2004     
2005     return [result createJSStringRef];
2006     END_AX_OBJC_EXCEPTIONS
2007     
2008     return nullptr;
2009 }
2010     
2011 JSRetainPtr<JSStringRef> AccessibilityUIElement::supportedActions() const
2012 {
2013     BEGIN_AX_OBJC_EXCEPTIONS
2014     NSArray *names = [m_element accessibilityActionNames];
2015     return [[names componentsJoinedByString:@","] createJSStringRef];
2016     END_AX_OBJC_EXCEPTIONS
2017     
2018     return nullptr;
2019 }
2020
2021 } // namespace WTR
2022
2023 #endif // HAVE(ACCESSIBILITY)