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