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