cf6748579b1f3f7b010333072994fe54992f0161
[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 "AccessibilityNotificationHandler.h"
29 #import "AccessibilityUIElement.h"
30
31 #import <Foundation/Foundation.h>
32 #import <JavaScriptCore/JSRetainPtr.h>
33 #import <JavaScriptCore/JSStringRef.h>
34 #import <JavaScriptCore/JSStringRefCF.h>
35 #import <WebKit/WebFrame.h>
36 #import <WebKit/WebHTMLView.h>
37 #import <WebKit/WebTypesInternal.h>
38 #import <wtf/RetainPtr.h>
39 #import <wtf/Vector.h>
40
41
42 #ifndef NSAccessibilityOwnsAttribute
43 #define NSAccessibilityOwnsAttribute @"AXOwns"
44 #endif
45
46 #ifndef NSAccessibilityGrabbedAttribute
47 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
48 #endif
49
50 #ifndef NSAccessibilityDropEffectsAttribute
51 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
52 #endif
53
54 // If an unsupported attribute is passed in, it will raise an accessibility exception. These are usually caught by the Accessibility Runtime to inform
55 // the AX client app of the error. However, DRT is the AX client app, so it must catch these exceptions.
56 #define BEGIN_AX_OBJC_EXCEPTIONS @try {
57 #define END_AX_OBJC_EXCEPTIONS } @catch(NSException *e) { if (![[e name] isEqualToString:NSAccessibilityException]) @throw; }
58
59
60 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
61
62 @interface NSObject (WebKitAccessibilityAdditions)
63 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
64 - (NSUInteger)accessibilityIndexOfChild:(id)child;
65 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
66 @end
67
68 @interface NSString (JSStringRefAdditions)
69 + (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef;
70 - (JSStringRef)createJSStringRef;
71 @end
72
73 @implementation NSString (JSStringRefAdditions)
74
75 + (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef
76 {
77     if (!jsStringRef)
78         return NULL;
79     
80     CFStringRef cfString = JSStringCopyCFString(kCFAllocatorDefault, jsStringRef);
81     return [(NSString *)cfString autorelease];
82 }
83
84 - (JSStringRef)createJSStringRef
85 {
86     return JSStringCreateWithCFString((CFStringRef)self);
87 }
88
89 @end
90
91 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
92     : m_element(element)
93     , m_notificationHandler(0)
94 {
95     // FIXME: ap@webkit.org says ObjC objects need to be CFRetained/CFRelease to be GC-compliant on the mac.
96     [m_element retain];
97 }
98
99 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
100     : m_element(other.m_element)
101     , m_notificationHandler(0)
102 {
103     [m_element retain];
104 }
105
106 AccessibilityUIElement::~AccessibilityUIElement()
107 {
108     // The notification handler should be nil because removeNotificationListener() should have been called in the test.
109     ASSERT(!m_notificationHandler);
110     [m_element release];
111 }
112
113 static NSString* descriptionOfValue(id valueObject, id focusedAccessibilityObject)
114 {
115     if (!valueObject)
116         return NULL;
117
118     if ([valueObject isKindOfClass:[NSArray class]])
119         return [NSString stringWithFormat:@"<array of size %lu>", static_cast<unsigned long>([(NSArray*)valueObject count])];
120
121     if ([valueObject isKindOfClass:[NSNumber class]])
122         return [(NSNumber*)valueObject stringValue];
123
124     if ([valueObject isKindOfClass:[NSValue class]]) {
125         NSString* type = [NSString stringWithCString:[valueObject objCType] encoding:NSASCIIStringEncoding];
126         NSValue* value = (NSValue*)valueObject;
127         if ([type rangeOfString:@"NSRect"].length > 0)
128             return [NSString stringWithFormat:@"NSRect: %@", NSStringFromRect([value rectValue])];
129         if ([type rangeOfString:@"NSPoint"].length > 0)
130             return [NSString stringWithFormat:@"NSPoint: %@", NSStringFromPoint([value pointValue])];
131         if ([type rangeOfString:@"NSSize"].length > 0)
132             return [NSString stringWithFormat:@"NSSize: %@", NSStringFromSize([value sizeValue])];
133         if ([type rangeOfString:@"NSRange"].length > 0)
134             return [NSString stringWithFormat:@"NSRange: %@", NSStringFromRange([value rangeValue])];
135     }
136
137     // Strip absolute URL paths
138     NSString* description = [valueObject description];
139     NSRange range = [description rangeOfString:@"LayoutTests"];
140     if (range.length)
141         return [description substringFromIndex:range.location];
142
143     // Strip pointer locations
144     if ([description rangeOfString:@"0x"].length) {
145         NSString* role = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityRoleAttribute];
146         NSString* title = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityTitleAttribute];
147         if ([title length])
148             return [NSString stringWithFormat:@"<%@: '%@'>", role, title];
149         return [NSString stringWithFormat:@"<%@>", role];
150     }
151     
152     return [valueObject description];
153 }
154
155 static NSString* attributesOfElement(id accessibilityObject)
156 {
157     NSArray* supportedAttributes = [accessibilityObject accessibilityAttributeNames];
158
159     NSMutableString* attributesString = [NSMutableString string];
160     for (NSUInteger i = 0; i < [supportedAttributes count]; ++i) {
161         NSString* attribute = [supportedAttributes objectAtIndex:i];
162         
163         // Right now, position provides useless and screen-specific information, so we do not
164         // want to include it for the sake of universally passing tests.
165         if ([attribute isEqualToString:@"AXPosition"])
166             continue;
167         
168         // accessibilityAttributeValue: can throw an if an attribute is not returned.
169         // For DumpRenderTree's purpose, we should ignore those exceptions
170         BEGIN_AX_OBJC_EXCEPTIONS
171         id valueObject = [accessibilityObject accessibilityAttributeValue:attribute];
172         NSString* value = descriptionOfValue(valueObject, accessibilityObject);
173         [attributesString appendFormat:@"%@: %@\n", attribute, value];
174         END_AX_OBJC_EXCEPTIONS
175     }
176     
177     return attributesString;
178 }
179
180 static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
181 {
182     Vector<UniChar> buffer([attribute length]);
183     [attribute getCharacters:buffer.data()];
184     buffer.append(':');
185     buffer.append(' ');
186
187     Vector<UniChar> valueBuffer([value length]);
188     [value getCharacters:valueBuffer.data()];
189     buffer.append(valueBuffer);
190
191     return JSStringCreateWithCharacters(buffer.data(), buffer.size());
192 }
193
194 static void convertNSArrayToVector(NSArray* array, Vector<AccessibilityUIElement>& elementVector)
195 {
196     NSUInteger count = [array count];
197     for (NSUInteger i = 0; i < count; ++i)
198         elementVector.append(AccessibilityUIElement([array objectAtIndex:i]));
199 }
200
201 static JSStringRef descriptionOfElements(Vector<AccessibilityUIElement>& elementVector)
202 {
203     NSMutableString* allElementString = [NSMutableString string];
204     size_t size = elementVector.size();
205     for (size_t i = 0; i < size; ++i) {
206         NSString* attributes = attributesOfElement(elementVector[i].platformUIElement());
207         [allElementString appendFormat:@"%@\n------------\n", attributes];
208     }
209     
210     return [allElementString createJSStringRef];
211 }
212
213 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
214 {
215     BEGIN_AX_OBJC_EXCEPTIONS
216     NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
217     convertNSArrayToVector(linkedElements, elementVector);
218     END_AX_OBJC_EXCEPTIONS
219 }
220
221 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
222 {
223     BEGIN_AX_OBJC_EXCEPTIONS
224     NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
225     convertNSArrayToVector(linkElements, elementVector);
226     END_AX_OBJC_EXCEPTIONS
227 }
228
229 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
230 {
231     BEGIN_AX_OBJC_EXCEPTIONS
232     NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
233     convertNSArrayToVector(children, elementVector);
234     END_AX_OBJC_EXCEPTIONS
235 }
236
237 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
238 {
239     BEGIN_AX_OBJC_EXCEPTIONS
240     NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
241     convertNSArrayToVector(children, elementVector);
242     END_AX_OBJC_EXCEPTIONS
243 }
244
245 int AccessibilityUIElement::childrenCount()
246 {
247     Vector<AccessibilityUIElement> children;
248     getChildren(children);
249     
250     return children.size();
251 }
252
253 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
254 {
255     id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
256     if (!element)
257         return nil;
258     
259     return AccessibilityUIElement(element); 
260 }
261
262 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
263 {
264     return [m_element accessibilityIndexOfChild:element->platformUIElement()];
265 }
266
267 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
268 {
269     Vector<AccessibilityUIElement> children;
270     getChildrenWithRange(children, index, 1);
271
272     if (children.size() == 1)
273         return children[0];
274     return 0;
275 }
276
277 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
278 {
279     BEGIN_AX_OBJC_EXCEPTIONS
280     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
281     if (index < [objects count])
282         return [objects objectAtIndex:index];
283     END_AX_OBJC_EXCEPTIONS
284     
285     return 0;
286 }
287
288 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
289 {
290     BEGIN_AX_OBJC_EXCEPTIONS
291     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityOwnsAttribute];
292     if (index < [objects count])
293         return [objects objectAtIndex:index];
294     END_AX_OBJC_EXCEPTIONS
295     
296     return 0;
297 }
298
299 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
300 {
301     BEGIN_AX_OBJC_EXCEPTIONS
302     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
303     if (index < [objects count])
304         return [objects objectAtIndex:index];
305     END_AX_OBJC_EXCEPTIONS
306     
307     return 0;
308 }
309
310 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
311 {
312     BEGIN_AX_OBJC_EXCEPTIONS
313     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedRowsAttribute];
314     if (index < [rows count])
315         return [rows objectAtIndex:index];
316     END_AX_OBJC_EXCEPTIONS
317
318     return 0;
319 }
320
321 AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
322 {
323     BEGIN_AX_OBJC_EXCEPTIONS
324     NSArray* array = [m_element accessibilityAttributeValue:NSAccessibilitySelectedChildrenAttribute];
325     if (index < [array count])
326         return [array objectAtIndex:index];
327     END_AX_OBJC_EXCEPTIONS
328     
329     return 0;
330 }
331
332 unsigned AccessibilityUIElement::selectedChildrenCount() const
333 {
334     BEGIN_AX_OBJC_EXCEPTIONS
335     return [m_element accessibilityArrayAttributeCount:NSAccessibilitySelectedChildrenAttribute];
336     END_AX_OBJC_EXCEPTIONS
337
338     return 0;
339 }
340
341 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
342 {
343     BEGIN_AX_OBJC_EXCEPTIONS
344     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilitySelectedRowsAttribute];
345     if (index < [rows count])
346         return [rows objectAtIndex:index];
347     END_AX_OBJC_EXCEPTIONS
348     
349     return 0;
350 }
351
352 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
353 {
354     BEGIN_AX_OBJC_EXCEPTIONS
355     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
356     if (index < [rows count])
357         return [rows objectAtIndex:index];
358     END_AX_OBJC_EXCEPTIONS
359     
360     return 0;
361 }
362
363 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
364 {
365     BEGIN_AX_OBJC_EXCEPTIONS
366     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityTitleUIElementAttribute];
367     if (accessibilityObject)
368         return AccessibilityUIElement(accessibilityObject);
369     END_AX_OBJC_EXCEPTIONS
370     
371     return 0;
372 }
373
374 AccessibilityUIElement AccessibilityUIElement::parentElement()
375 {
376     BEGIN_AX_OBJC_EXCEPTIONS
377     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityParentAttribute];
378     if (accessibilityObject)
379         return AccessibilityUIElement(accessibilityObject);
380     END_AX_OBJC_EXCEPTIONS
381     
382     return 0;
383 }
384
385 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
386 {
387     BEGIN_AX_OBJC_EXCEPTIONS
388     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedByRowAttribute];
389     if (accessibilityObject)
390         return AccessibilityUIElement(accessibilityObject);
391     END_AX_OBJC_EXCEPTIONS
392     
393     return 0;
394 }
395
396 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
397 {
398     Vector<AccessibilityUIElement> linkedElements;
399     getLinkedUIElements(linkedElements);
400     return descriptionOfElements(linkedElements);
401 }
402
403 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
404 {
405     Vector<AccessibilityUIElement> linkElements;
406     getDocumentLinks(linkElements);
407     return descriptionOfElements(linkElements);
408 }
409
410 JSStringRef AccessibilityUIElement::attributesOfChildren()
411 {
412     Vector<AccessibilityUIElement> children;
413     getChildren(children);
414     return descriptionOfElements(children);
415 }
416
417 JSStringRef AccessibilityUIElement::allAttributes()
418 {
419     NSString* attributes = attributesOfElement(m_element);
420     return [attributes createJSStringRef];
421 }
422
423 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
424 {
425     BEGIN_AX_OBJC_EXCEPTIONS
426     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
427     if ([value isKindOfClass:[NSString class]])
428         return [value createJSStringRef];
429     END_AX_OBJC_EXCEPTIONS
430
431     return 0;
432 }
433
434 AccessibilityUIElement AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
435 {
436     BEGIN_AX_OBJC_EXCEPTIONS
437     id uiElement = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
438     return AccessibilityUIElement(uiElement);
439     END_AX_OBJC_EXCEPTIONS
440     
441     return 0;
442 }
443
444
445 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
446 {
447     BEGIN_AX_OBJC_EXCEPTIONS
448     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
449     if ([value isKindOfClass:[NSNumber class]])
450         return [value doubleValue];
451     END_AX_OBJC_EXCEPTIONS
452     
453     return 0;
454 }
455
456 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
457 {
458     BEGIN_AX_OBJC_EXCEPTIONS
459     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
460     if ([value isKindOfClass:[NSNumber class]])
461         return [value boolValue];
462     END_AX_OBJC_EXCEPTIONS
463     
464     return false;
465 }
466
467 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
468 {
469     BEGIN_AX_OBJC_EXCEPTIONS
470     return [m_element accessibilityIsAttributeSettable:[NSString stringWithJSStringRef:attribute]];
471     END_AX_OBJC_EXCEPTIONS
472     
473     return false;
474 }
475
476 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
477 {
478     BEGIN_AX_OBJC_EXCEPTIONS
479     return [[m_element accessibilityAttributeNames] containsObject:[NSString stringWithJSStringRef:attribute]];
480     END_AX_OBJC_EXCEPTIONS
481     
482     return false;
483 }
484
485 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
486 {
487     NSArray* supportedParameterizedAttributes = [m_element accessibilityParameterizedAttributeNames];
488     
489     NSMutableString* attributesString = [NSMutableString string];
490     for (NSUInteger i = 0; i < [supportedParameterizedAttributes count]; ++i) {
491         [attributesString appendFormat:@"%@\n", [supportedParameterizedAttributes objectAtIndex:i]];
492     }
493     
494     return [attributesString createJSStringRef];
495 }
496
497 JSStringRef AccessibilityUIElement::role()
498 {
499     BEGIN_AX_OBJC_EXCEPTIONS
500     NSString *role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleAttribute], m_element);
501     return concatenateAttributeAndValue(@"AXRole", role);
502     END_AX_OBJC_EXCEPTIONS
503     
504     return 0;
505 }
506
507 JSStringRef AccessibilityUIElement::subrole()
508 {
509     BEGIN_AX_OBJC_EXCEPTIONS
510     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilitySubroleAttribute], m_element);
511     return concatenateAttributeAndValue(@"AXSubrole", role);
512     END_AX_OBJC_EXCEPTIONS
513
514     return 0;
515 }
516
517 JSStringRef AccessibilityUIElement::roleDescription()
518 {
519     BEGIN_AX_OBJC_EXCEPTIONS
520     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute], m_element);
521     return concatenateAttributeAndValue(@"AXRoleDescription", role);
522     END_AX_OBJC_EXCEPTIONS
523     
524     return 0;
525 }
526
527 JSStringRef AccessibilityUIElement::title()
528 {
529     BEGIN_AX_OBJC_EXCEPTIONS
530     NSString* title = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityTitleAttribute], m_element);
531     return concatenateAttributeAndValue(@"AXTitle", title);
532     END_AX_OBJC_EXCEPTIONS
533
534     return 0;
535 }
536
537 JSStringRef AccessibilityUIElement::description()
538 {
539     BEGIN_AX_OBJC_EXCEPTIONS
540     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityDescriptionAttribute], m_element);
541     return concatenateAttributeAndValue(@"AXDescription", description);
542     END_AX_OBJC_EXCEPTIONS
543
544     return 0;
545 }
546
547 JSStringRef AccessibilityUIElement::orientation() const
548 {
549     BEGIN_AX_OBJC_EXCEPTIONS
550     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityOrientationAttribute], m_element);
551     return concatenateAttributeAndValue(@"AXOrientation", description);    
552     END_AX_OBJC_EXCEPTIONS
553
554     return 0;
555 }
556
557 JSStringRef AccessibilityUIElement::stringValue()
558 {
559     BEGIN_AX_OBJC_EXCEPTIONS
560     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityValueAttribute], m_element);
561     return concatenateAttributeAndValue(@"AXValue", description);
562     END_AX_OBJC_EXCEPTIONS
563
564     return 0;
565 }
566
567 JSStringRef AccessibilityUIElement::language()
568 {
569     BEGIN_AX_OBJC_EXCEPTIONS
570     id description = descriptionOfValue([m_element accessibilityAttributeValue:@"AXLanguage"], m_element);
571     return concatenateAttributeAndValue(@"AXLanguage", description);
572     END_AX_OBJC_EXCEPTIONS
573
574     return 0;
575 }
576
577 JSStringRef AccessibilityUIElement::helpText() const
578 {
579     BEGIN_AX_OBJC_EXCEPTIONS
580     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityHelpAttribute], m_element);
581     return concatenateAttributeAndValue(@"AXHelp", description);
582     END_AX_OBJC_EXCEPTIONS
583     
584     return 0;
585 }
586
587 double AccessibilityUIElement::x()
588 {
589     BEGIN_AX_OBJC_EXCEPTIONS
590     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
591     return static_cast<double>([positionValue pointValue].x);    
592     END_AX_OBJC_EXCEPTIONS
593     
594     return 0.0f;
595 }
596
597 double AccessibilityUIElement::y()
598 {
599     BEGIN_AX_OBJC_EXCEPTIONS
600     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
601     return static_cast<double>([positionValue pointValue].y);    
602     END_AX_OBJC_EXCEPTIONS
603     
604     return 0.0f;
605 }
606
607 double AccessibilityUIElement::width()
608 {
609     BEGIN_AX_OBJC_EXCEPTIONS
610     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
611     return static_cast<double>([sizeValue sizeValue].width);
612     END_AX_OBJC_EXCEPTIONS
613     
614     return 0.0f;
615 }
616
617 double AccessibilityUIElement::height()
618 {
619     BEGIN_AX_OBJC_EXCEPTIONS
620     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
621     return static_cast<double>([sizeValue sizeValue].height);
622     END_AX_OBJC_EXCEPTIONS
623     
624     return 0.0f;
625 }
626
627 double AccessibilityUIElement::clickPointX()
628 {
629     BEGIN_AX_OBJC_EXCEPTIONS
630     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
631     return static_cast<double>([positionValue pointValue].x);        
632     END_AX_OBJC_EXCEPTIONS
633     
634     return 0.0f;
635 }
636
637 double AccessibilityUIElement::clickPointY()
638 {
639     BEGIN_AX_OBJC_EXCEPTIONS
640     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
641     return static_cast<double>([positionValue pointValue].y);
642     END_AX_OBJC_EXCEPTIONS
643     
644     return 0.0f;
645 }
646
647 double AccessibilityUIElement::intValue() const
648 {
649     BEGIN_AX_OBJC_EXCEPTIONS
650     id value = [m_element accessibilityAttributeValue:NSAccessibilityValueAttribute];
651     if ([value isKindOfClass:[NSNumber class]])
652         return [(NSNumber*)value doubleValue]; 
653     END_AX_OBJC_EXCEPTIONS
654
655     return 0.0f;
656 }
657
658 double AccessibilityUIElement::minValue()
659 {
660     BEGIN_AX_OBJC_EXCEPTIONS
661     id value = [m_element accessibilityAttributeValue:NSAccessibilityMinValueAttribute];
662     if ([value isKindOfClass:[NSNumber class]])
663         return [(NSNumber*)value doubleValue]; 
664     END_AX_OBJC_EXCEPTIONS
665
666     return 0.0f;
667 }
668
669 double AccessibilityUIElement::maxValue()
670 {
671     BEGIN_AX_OBJC_EXCEPTIONS
672     id value = [m_element accessibilityAttributeValue:NSAccessibilityMaxValueAttribute];
673     if ([value isKindOfClass:[NSNumber class]])
674         return [(NSNumber*)value doubleValue]; 
675     END_AX_OBJC_EXCEPTIONS
676
677     return 0.0;
678 }
679
680 JSStringRef AccessibilityUIElement::valueDescription()
681 {
682     BEGIN_AX_OBJC_EXCEPTIONS
683     NSString* valueDescription = [m_element accessibilityAttributeValue:NSAccessibilityValueDescriptionAttribute];
684     if ([valueDescription isKindOfClass:[NSString class]])
685          return [valueDescription createJSStringRef];
686
687     END_AX_OBJC_EXCEPTIONS
688     return 0;
689 }
690
691 int AccessibilityUIElement::insertionPointLineNumber()
692 {
693     BEGIN_AX_OBJC_EXCEPTIONS
694     id value = [m_element accessibilityAttributeValue:NSAccessibilityInsertionPointLineNumberAttribute];
695     if ([value isKindOfClass:[NSNumber class]])
696         return [(NSNumber *)value intValue]; 
697     END_AX_OBJC_EXCEPTIONS
698     
699     return -1;
700 }
701
702 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
703 {
704     BEGIN_AX_OBJC_EXCEPTIONS
705     NSArray* actions = [m_element accessibilityActionNames];
706     return [actions containsObject:[NSString stringWithJSStringRef:action]];
707     END_AX_OBJC_EXCEPTIONS
708     
709     return false;
710 }
711
712 bool AccessibilityUIElement::isEnabled()
713 {
714     BEGIN_AX_OBJC_EXCEPTIONS
715     id value = [m_element accessibilityAttributeValue:NSAccessibilityEnabledAttribute];
716     if ([value isKindOfClass:[NSNumber class]])
717         return [value boolValue];
718     END_AX_OBJC_EXCEPTIONS
719     
720     return false;
721 }
722
723 bool AccessibilityUIElement::isRequired() const
724 {
725     BEGIN_AX_OBJC_EXCEPTIONS
726     id value = [m_element accessibilityAttributeValue:@"AXRequired"];
727     if ([value isKindOfClass:[NSNumber class]])
728         return [value boolValue];
729     END_AX_OBJC_EXCEPTIONS
730     
731     return false;
732 }
733
734 bool AccessibilityUIElement::isFocused() const
735 {
736     // FIXME: implement
737     return false;
738 }
739
740 bool AccessibilityUIElement::isSelected() const
741 {
742     BEGIN_AX_OBJC_EXCEPTIONS
743     id value = [m_element accessibilityAttributeValue:NSAccessibilitySelectedAttribute];
744     if ([value isKindOfClass:[NSNumber class]])
745         return [value boolValue];
746     END_AX_OBJC_EXCEPTIONS
747     
748     return false;
749 }
750
751 bool AccessibilityUIElement::isExpanded() const
752 {
753     BEGIN_AX_OBJC_EXCEPTIONS
754     id value = [m_element accessibilityAttributeValue:NSAccessibilityExpandedAttribute];
755     if ([value isKindOfClass:[NSNumber class]])
756         return [value boolValue];
757     END_AX_OBJC_EXCEPTIONS
758     
759     return false;
760 }
761
762 bool AccessibilityUIElement::isChecked() const
763 {
764     // On the Mac, intValue()==1 if a a checkable control is checked.
765     return intValue() == 1;
766 }
767
768 int AccessibilityUIElement::hierarchicalLevel() const
769 {
770     BEGIN_AX_OBJC_EXCEPTIONS
771     id value = [m_element accessibilityAttributeValue:NSAccessibilityDisclosureLevelAttribute];
772     if ([value isKindOfClass:[NSNumber class]])
773         return [value intValue];
774     END_AX_OBJC_EXCEPTIONS
775
776     return 0;
777 }
778
779 JSStringRef AccessibilityUIElement::speak()
780 {
781     BEGIN_AX_OBJC_EXCEPTIONS
782     id value = [m_element accessibilityAttributeValue:@"AXDRTSpeechAttribute"];
783     if ([value isKindOfClass:[NSString class]])
784         return [value createJSStringRef];
785     END_AX_OBJC_EXCEPTIONS
786         
787     return 0;
788 }
789
790 bool AccessibilityUIElement::ariaIsGrabbed() const
791 {
792     BEGIN_AX_OBJC_EXCEPTIONS
793     id value = [m_element accessibilityAttributeValue:NSAccessibilityGrabbedAttribute];
794     if ([value isKindOfClass:[NSNumber class]])
795         return [value boolValue];
796     END_AX_OBJC_EXCEPTIONS
797
798     return false;
799 }
800
801 JSStringRef AccessibilityUIElement::ariaDropEffects() const
802 {
803     BEGIN_AX_OBJC_EXCEPTIONS
804     id value = [m_element accessibilityAttributeValue:NSAccessibilityDropEffectsAttribute];
805     if (![value isKindOfClass:[NSArray class]])
806         return 0;
807
808     NSMutableString* dropEffects = [NSMutableString string];
809     NSInteger length = [value count];
810     for (NSInteger k = 0; k < length; ++k) {
811         [dropEffects appendString:[value objectAtIndex:k]];
812         if (k < length - 1)
813             [dropEffects appendString:@","];
814     }
815     
816     return [dropEffects createJSStringRef];
817     END_AX_OBJC_EXCEPTIONS
818     
819     return 0;
820 }
821
822 // parameterized attributes
823 int AccessibilityUIElement::lineForIndex(int index)
824 {
825     BEGIN_AX_OBJC_EXCEPTIONS
826     id value = [m_element accessibilityAttributeValue:NSAccessibilityLineForIndexParameterizedAttribute forParameter:[NSNumber numberWithInt:index]];
827     if ([value isKindOfClass:[NSNumber class]])
828         return [(NSNumber *)value intValue]; 
829     END_AX_OBJC_EXCEPTIONS
830
831     return -1;
832 }
833
834 JSStringRef AccessibilityUIElement::rangeForLine(int line)
835 {
836     BEGIN_AX_OBJC_EXCEPTIONS
837     id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForLineParameterizedAttribute forParameter:[NSNumber numberWithInt:line]];
838     if ([value isKindOfClass:[NSValue class]]) {
839         return [NSStringFromRange([value rangeValue]) createJSStringRef];
840     }
841     END_AX_OBJC_EXCEPTIONS
842     
843     return 0;
844 }
845
846 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
847 {
848     NSRange range = NSMakeRange(location, length);
849     BEGIN_AX_OBJC_EXCEPTIONS
850     id value = [m_element accessibilityAttributeValue:NSAccessibilityBoundsForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
851     NSRect rect = NSMakeRect(0,0,0,0);
852     if ([value isKindOfClass:[NSValue class]])
853         rect = [value rectValue]; 
854     
855     // don't return position information because it is platform dependent
856     NSMutableString* boundsDescription = [NSMutableString stringWithFormat:@"{{%f, %f}, {%f, %f}}",-1.0f,-1.0f,rect.size.width,rect.size.height];
857     return [boundsDescription createJSStringRef];
858     END_AX_OBJC_EXCEPTIONS
859     
860     return 0;
861 }
862
863 JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
864 {
865     NSRange range = NSMakeRange(location, length);
866     BEGIN_AX_OBJC_EXCEPTIONS
867     id string = [m_element accessibilityAttributeValue:NSAccessibilityStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
868     if (![string isKindOfClass:[NSString class]])
869         return 0;
870     
871     return [string createJSStringRef];
872     END_AX_OBJC_EXCEPTIONS
873     
874     return 0;
875 }
876
877 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
878 {
879     NSRange range = NSMakeRange(location, length);
880     BEGIN_AX_OBJC_EXCEPTIONS
881     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
882     if (![string isKindOfClass:[NSAttributedString class]])
883         return 0;
884     
885     NSString* stringWithAttrs = [string description];
886     return [stringWithAttrs createJSStringRef];
887     END_AX_OBJC_EXCEPTIONS
888     
889     return 0;
890 }
891
892 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
893 {
894     NSRange range = NSMakeRange(location, length);
895     BEGIN_AX_OBJC_EXCEPTIONS
896     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
897     if (![string isKindOfClass:[NSAttributedString class]])
898         return false;
899
900     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
901     if([[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue])
902         return true;    
903     END_AX_OBJC_EXCEPTIONS
904     
905     return false;
906 }
907
908 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
909 {
910     BEGIN_AX_OBJC_EXCEPTIONS
911     NSMutableDictionary* parameter = [NSMutableDictionary dictionary];
912     [parameter setObject:(isDirectionNext) ? @"AXDirectionNext" : @"AXDirectionPrevious" forKey:@"AXDirection"];
913     [parameter setObject:[NSNumber numberWithInt:1] forKey:@"AXResultsLimit"];
914     if (startElement && startElement->platformUIElement())
915         [parameter setObject:(id)startElement->platformUIElement() forKey:@"AXStartElement"];
916     if (searchKey)
917         [parameter setObject:[NSString stringWithJSStringRef:searchKey] forKey:@"AXSearchKey"];
918     if (searchText)
919         [parameter setObject:[NSString stringWithJSStringRef:searchText] forKey:@"AXSearchText"];
920     
921     id uiElement = [[m_element accessibilityAttributeValue:@"AXUIElementsForSearchPredicate" forParameter:parameter] lastObject];
922     return AccessibilityUIElement(uiElement);
923     END_AX_OBJC_EXCEPTIONS
924     
925     return 0;
926 }
927
928 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
929 {
930     // not yet defined in AppKit... odd
931     BEGIN_AX_OBJC_EXCEPTIONS
932     NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
933     Vector<AccessibilityUIElement> columnHeadersVector;
934     convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
935     return descriptionOfElements(columnHeadersVector);
936     END_AX_OBJC_EXCEPTIONS
937     
938     return 0;
939 }
940
941 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
942 {
943     BEGIN_AX_OBJC_EXCEPTIONS
944     NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
945     Vector<AccessibilityUIElement> rowHeadersVector;
946     convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
947     return descriptionOfElements(rowHeadersVector);
948     END_AX_OBJC_EXCEPTIONS
949     
950     return 0;
951 }
952
953 JSStringRef AccessibilityUIElement::attributesOfColumns()
954 {
955     BEGIN_AX_OBJC_EXCEPTIONS
956     NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
957     Vector<AccessibilityUIElement> columnsVector;
958     convertNSArrayToVector(columnsArray, columnsVector);
959     return descriptionOfElements(columnsVector);
960     END_AX_OBJC_EXCEPTIONS
961     
962     return 0;
963 }
964
965 JSStringRef AccessibilityUIElement::attributesOfRows()
966 {
967     BEGIN_AX_OBJC_EXCEPTIONS
968     NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
969     Vector<AccessibilityUIElement> rowsVector;
970     convertNSArrayToVector(rowsArray, rowsVector);
971     return descriptionOfElements(rowsVector);
972     END_AX_OBJC_EXCEPTIONS
973     
974     return 0;
975 }
976
977 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
978 {
979     BEGIN_AX_OBJC_EXCEPTIONS
980     NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
981     Vector<AccessibilityUIElement> cellsVector;
982     convertNSArrayToVector(cellsArray, cellsVector);
983     return descriptionOfElements(cellsVector);
984     END_AX_OBJC_EXCEPTIONS
985     
986     return 0;
987 }
988
989 JSStringRef AccessibilityUIElement::attributesOfHeader()
990 {
991     BEGIN_AX_OBJC_EXCEPTIONS
992     id headerObject = [m_element accessibilityAttributeValue:NSAccessibilityHeaderAttribute];
993     if (!headerObject)
994         return [@"" createJSStringRef];
995     
996     Vector<AccessibilityUIElement> headerVector;
997     headerVector.append(headerObject);
998     return descriptionOfElements(headerVector);
999     END_AX_OBJC_EXCEPTIONS
1000     
1001     return 0;
1002 }
1003
1004 int AccessibilityUIElement::rowCount()
1005 {
1006     BEGIN_AX_OBJC_EXCEPTIONS
1007     return [m_element accessibilityArrayAttributeCount:NSAccessibilityRowsAttribute];
1008     END_AX_OBJC_EXCEPTIONS
1009     
1010     return 0;
1011 }
1012
1013 int AccessibilityUIElement::columnCount()
1014 {
1015     BEGIN_AX_OBJC_EXCEPTIONS
1016     return [m_element accessibilityArrayAttributeCount:NSAccessibilityColumnsAttribute];
1017     END_AX_OBJC_EXCEPTIONS
1018     
1019     return 0;
1020 }
1021
1022 int AccessibilityUIElement::indexInTable()
1023 {
1024     BEGIN_AX_OBJC_EXCEPTIONS
1025     NSNumber* indexNumber = [m_element accessibilityAttributeValue:NSAccessibilityIndexAttribute];
1026     if (indexNumber)
1027         return [indexNumber intValue];
1028     END_AX_OBJC_EXCEPTIONS
1029
1030     return -1;
1031 }
1032
1033 JSStringRef AccessibilityUIElement::rowIndexRange()
1034 {
1035     NSRange range = NSMakeRange(0, 0);
1036     BEGIN_AX_OBJC_EXCEPTIONS
1037     NSValue* indexRange = [m_element accessibilityAttributeValue:@"AXRowIndexRange"];
1038     if (indexRange)
1039         range = [indexRange rangeValue];
1040     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1041     return [rangeDescription createJSStringRef];
1042     END_AX_OBJC_EXCEPTIONS
1043     
1044     return 0;
1045 }
1046
1047 JSStringRef AccessibilityUIElement::columnIndexRange()
1048 {
1049     NSRange range = NSMakeRange(0, 0);
1050     BEGIN_AX_OBJC_EXCEPTIONS
1051     NSNumber* indexRange = [m_element accessibilityAttributeValue:@"AXColumnIndexRange"];
1052     if (indexRange)
1053         range = [indexRange rangeValue];
1054     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}",static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1055     return [rangeDescription createJSStringRef];    
1056     END_AX_OBJC_EXCEPTIONS
1057     
1058     return 0;
1059 }
1060
1061 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1062 {
1063     NSArray *colRowArray = [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:col], [NSNumber numberWithUnsignedInt:row], nil];
1064     BEGIN_AX_OBJC_EXCEPTIONS
1065     return [m_element accessibilityAttributeValue:@"AXCellForColumnAndRow" forParameter:colRowArray];
1066     END_AX_OBJC_EXCEPTIONS    
1067
1068     return 0;
1069 }
1070
1071 AccessibilityUIElement AccessibilityUIElement::horizontalScrollbar() const
1072 {
1073     BEGIN_AX_OBJC_EXCEPTIONS
1074     return AccessibilityUIElement([m_element accessibilityAttributeValue:NSAccessibilityHorizontalScrollBarAttribute]);
1075     END_AX_OBJC_EXCEPTIONS    
1076     
1077     return 0;
1078 }
1079
1080 AccessibilityUIElement AccessibilityUIElement::verticalScrollbar() const
1081 {
1082     BEGIN_AX_OBJC_EXCEPTIONS
1083     return AccessibilityUIElement([m_element accessibilityAttributeValue:NSAccessibilityVerticalScrollBarAttribute]);
1084     END_AX_OBJC_EXCEPTIONS        
1085
1086     return 0;
1087 }
1088
1089 JSStringRef AccessibilityUIElement::selectedTextRange()
1090 {
1091     NSRange range = NSMakeRange(NSNotFound, 0);
1092     BEGIN_AX_OBJC_EXCEPTIONS
1093     NSValue *indexRange = [m_element accessibilityAttributeValue:NSAccessibilitySelectedTextRangeAttribute];
1094     if (indexRange)
1095         range = [indexRange rangeValue];
1096     NSMutableString *rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1097     return [rangeDescription createJSStringRef];    
1098     END_AX_OBJC_EXCEPTIONS
1099     
1100     return 0;
1101 }
1102
1103 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1104 {
1105     NSRange textRange = NSMakeRange(location, length);
1106     NSValue *textRangeValue = [NSValue valueWithRange:textRange];
1107     BEGIN_AX_OBJC_EXCEPTIONS
1108     [m_element accessibilitySetValue:textRangeValue forAttribute:NSAccessibilitySelectedTextRangeAttribute];
1109     END_AX_OBJC_EXCEPTIONS
1110 }
1111
1112 void AccessibilityUIElement::increment()
1113 {
1114     BEGIN_AX_OBJC_EXCEPTIONS
1115     [m_element accessibilityPerformAction:NSAccessibilityIncrementAction];
1116     END_AX_OBJC_EXCEPTIONS
1117 }
1118
1119 void AccessibilityUIElement::decrement()
1120 {
1121     BEGIN_AX_OBJC_EXCEPTIONS
1122     [m_element accessibilityPerformAction:NSAccessibilityDecrementAction];
1123     END_AX_OBJC_EXCEPTIONS
1124 }
1125
1126 void AccessibilityUIElement::showMenu()
1127 {
1128     BEGIN_AX_OBJC_EXCEPTIONS
1129     [m_element accessibilityPerformAction:NSAccessibilityShowMenuAction];
1130     END_AX_OBJC_EXCEPTIONS
1131 }
1132
1133 void AccessibilityUIElement::press()
1134 {
1135     BEGIN_AX_OBJC_EXCEPTIONS
1136     [m_element accessibilityPerformAction:NSAccessibilityPressAction];
1137     END_AX_OBJC_EXCEPTIONS
1138 }
1139
1140 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1141 {
1142     BEGIN_AX_OBJC_EXCEPTIONS
1143     NSArray* array = [NSArray arrayWithObject:element->platformUIElement()];
1144     [m_element accessibilitySetValue:array forAttribute:NSAccessibilitySelectedChildrenAttribute];
1145     END_AX_OBJC_EXCEPTIONS    
1146 }
1147
1148 JSStringRef AccessibilityUIElement::accessibilityValue() const
1149 {
1150     // FIXME: implement
1151     return JSStringCreateWithCharacters(0, 0);
1152 }
1153
1154 JSStringRef AccessibilityUIElement::documentEncoding()
1155 {
1156     return JSStringCreateWithCharacters(0, 0);
1157 }
1158
1159 JSStringRef AccessibilityUIElement::documentURI()
1160 {
1161     return JSStringCreateWithCharacters(0, 0);
1162 }
1163
1164 JSStringRef AccessibilityUIElement::url()
1165 {
1166     BEGIN_AX_OBJC_EXCEPTIONS
1167     NSURL *url = [m_element accessibilityAttributeValue:NSAccessibilityURLAttribute];
1168     return [[url absoluteString] createJSStringRef];    
1169     END_AX_OBJC_EXCEPTIONS
1170     
1171     return nil;
1172 }
1173
1174 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
1175 {
1176     if (!functionCallback)
1177         return false;
1178  
1179     // Mac programmers should not be adding more than one notification listener per element.
1180     // Other platforms may be different.
1181     if (m_notificationHandler)
1182         return false;
1183     m_notificationHandler = [[AccessibilityNotificationHandler alloc] init];
1184     [m_notificationHandler setPlatformElement:platformUIElement()];
1185     [m_notificationHandler setCallback:functionCallback];
1186     [m_notificationHandler startObserving];
1187
1188     return true;
1189 }
1190
1191 void AccessibilityUIElement::removeNotificationListener()
1192 {
1193     // Mac programmers should not be trying to remove a listener that's already removed.
1194     ASSERT(m_notificationHandler);
1195
1196     [m_notificationHandler release];
1197     m_notificationHandler = nil;
1198 }
1199
1200 bool AccessibilityUIElement::isFocusable() const
1201 {
1202     bool result = false;
1203     BEGIN_AX_OBJC_EXCEPTIONS
1204     result = [m_element accessibilityIsAttributeSettable:NSAccessibilityFocusedAttribute];
1205     END_AX_OBJC_EXCEPTIONS
1206     
1207     return result;
1208 }
1209
1210 bool AccessibilityUIElement::isSelectable() const
1211 {
1212     // FIXME: implement
1213     return false;
1214 }
1215
1216 bool AccessibilityUIElement::isMultiSelectable() const
1217 {
1218     // FIXME: implement
1219     return false;
1220 }
1221
1222 bool AccessibilityUIElement::isSelectedOptionActive() const
1223 {
1224     // FIXME: implement
1225     return false;
1226 }
1227
1228 bool AccessibilityUIElement::isVisible() const
1229 {
1230     // FIXME: implement
1231     return false;
1232 }
1233
1234 bool AccessibilityUIElement::isOffScreen() const
1235 {
1236     // FIXME: implement
1237     return false;
1238 }
1239
1240 bool AccessibilityUIElement::isCollapsed() const
1241 {
1242     // FIXME: implement
1243     return false;
1244 }
1245
1246 bool AccessibilityUIElement::isIgnored() const
1247 {
1248     BOOL result = NO;
1249     BEGIN_AX_OBJC_EXCEPTIONS
1250     result = [m_element accessibilityIsIgnored];
1251     END_AX_OBJC_EXCEPTIONS
1252     return result;
1253 }
1254
1255 bool AccessibilityUIElement::hasPopup() const
1256 {
1257     BEGIN_AX_OBJC_EXCEPTIONS
1258     id value = [m_element accessibilityAttributeValue:@"AXHasPopup"];
1259     if ([value isKindOfClass:[NSNumber class]])
1260         return [value boolValue];
1261     END_AX_OBJC_EXCEPTIONS
1262
1263     return false;
1264 }
1265
1266 void AccessibilityUIElement::takeFocus()
1267 {
1268     // FIXME: implement
1269 }
1270
1271 void AccessibilityUIElement::takeSelection()
1272 {
1273     // FIXME: implement
1274 }
1275
1276 void AccessibilityUIElement::addSelection()
1277 {
1278     // FIXME: implement
1279 }
1280
1281 void AccessibilityUIElement::removeSelection()
1282 {
1283     // FIXME: implement
1284 }
1285
1286 #if SUPPORTS_AX_TEXTMARKERS
1287
1288 // Text markers
1289 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1290 {
1291     BEGIN_AX_OBJC_EXCEPTIONS
1292     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUIElement" forParameter:element->platformUIElement()];
1293     return AccessibilityTextMarkerRange(textMarkerRange);
1294     END_AX_OBJC_EXCEPTIONS
1295     
1296     return 0;
1297 }
1298
1299 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1300 {
1301     BEGIN_AX_OBJC_EXCEPTIONS
1302     NSNumber* lengthValue = [m_element accessibilityAttributeValue:@"AXLengthForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1303     return [lengthValue intValue];
1304     END_AX_OBJC_EXCEPTIONS
1305     
1306     return 0;
1307 }
1308
1309 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
1310 {
1311     BEGIN_AX_OBJC_EXCEPTIONS
1312     NSAttributedString* string = [m_element accessibilityAttributeValue:@"AXAttributedStringForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1313     if (![string isKindOfClass:[NSAttributedString class]])
1314         return false;
1315     
1316     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
1317     if ([attrs objectForKey:[NSString stringWithJSStringRef:attribute]])
1318         return true;    
1319     END_AX_OBJC_EXCEPTIONS
1320     
1321     return false;
1322 }
1323
1324 int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
1325 {
1326     BEGIN_AX_OBJC_EXCEPTIONS
1327     NSNumber* indexNumber = [m_element accessibilityAttributeValue:@"AXIndexForTextMarker" forParameter:(id)marker->platformTextMarker()];
1328     return [indexNumber intValue];
1329     END_AX_OBJC_EXCEPTIONS
1330     
1331     return -1;
1332 }
1333
1334 AccessibilityTextMarker AccessibilityUIElement::textMarkerForIndex(int textIndex)
1335 {
1336     BEGIN_AX_OBJC_EXCEPTIONS
1337     id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForIndex" forParameter:[NSNumber numberWithInteger:textIndex]];
1338     return AccessibilityTextMarker(textMarker);
1339     END_AX_OBJC_EXCEPTIONS
1340     
1341     return 0;
1342 }
1343
1344 bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
1345 {
1346     BEGIN_AX_OBJC_EXCEPTIONS
1347     NSNumber* validNumber = [m_element accessibilityAttributeValue:@"AXTextMarkerIsValid" forParameter:(id)textMarker->platformTextMarker()];
1348     return [validNumber boolValue];
1349     END_AX_OBJC_EXCEPTIONS
1350
1351     return false;
1352 }
1353
1354 AccessibilityTextMarker AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1355 {
1356     BEGIN_AX_OBJC_EXCEPTIONS
1357     id previousMarker = [m_element accessibilityAttributeValue:@"AXPreviousTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1358     return AccessibilityTextMarker(previousMarker);
1359     END_AX_OBJC_EXCEPTIONS
1360     
1361     return 0;
1362 }
1363
1364 AccessibilityTextMarker AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1365 {
1366     BEGIN_AX_OBJC_EXCEPTIONS
1367     id nextMarker = [m_element accessibilityAttributeValue:@"AXNextTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1368     return AccessibilityTextMarker(nextMarker);
1369     END_AX_OBJC_EXCEPTIONS
1370     
1371     return 0;
1372 }
1373
1374 JSStringRef AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1375 {
1376     BEGIN_AX_OBJC_EXCEPTIONS
1377     id textString = [m_element accessibilityAttributeValue:@"AXStringForTextMarkerRange" forParameter:(id)markerRange->platformTextMarkerRange()];
1378     return [textString createJSStringRef];
1379     END_AX_OBJC_EXCEPTIONS
1380     
1381     return 0;
1382 }
1383
1384 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1385 {
1386     BEGIN_AX_OBJC_EXCEPTIONS
1387     NSArray* textMarkers = [NSArray arrayWithObjects:(id)startMarker->platformTextMarker(), (id)endMarker->platformTextMarker(), nil];
1388     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUnorderedTextMarkers" forParameter:textMarkers];
1389     return AccessibilityTextMarkerRange(textMarkerRange);
1390     END_AX_OBJC_EXCEPTIONS
1391     
1392     return 0;
1393 }
1394
1395 AccessibilityTextMarker AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1396 {
1397     BEGIN_AX_OBJC_EXCEPTIONS
1398     id textMarker = [m_element accessibilityAttributeValue:@"AXStartTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1399     return AccessibilityTextMarker(textMarker);
1400     END_AX_OBJC_EXCEPTIONS
1401     
1402     return 0;    
1403 }
1404
1405 AccessibilityTextMarker AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1406 {
1407     BEGIN_AX_OBJC_EXCEPTIONS
1408     id textMarker = [m_element accessibilityAttributeValue:@"AXEndTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1409     return AccessibilityTextMarker(textMarker);
1410     END_AX_OBJC_EXCEPTIONS
1411     
1412     return 0;    
1413 }
1414
1415 AccessibilityTextMarker AccessibilityUIElement::textMarkerForPoint(int x, int y)
1416 {
1417     BEGIN_AX_OBJC_EXCEPTIONS
1418     id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForPosition" forParameter:[NSValue valueWithPoint:NSMakePoint(x, y)]];
1419     return AccessibilityTextMarker(textMarker);
1420     END_AX_OBJC_EXCEPTIONS
1421     
1422     return 0;    
1423 }
1424
1425 AccessibilityUIElement AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1426 {
1427     BEGIN_AX_OBJC_EXCEPTIONS
1428     id uiElement = [m_element accessibilityAttributeValue:@"AXUIElementForTextMarker" forParameter:(id)marker->platformTextMarker()];
1429     return AccessibilityUIElement(uiElement);
1430     END_AX_OBJC_EXCEPTIONS
1431     
1432     return 0;  
1433 }
1434
1435 #endif // SUPPORTS_AX_TEXTMARKERS
1436
1437 void AccessibilityUIElement::scrollToMakeVisible()
1438 {
1439     // FIXME: implement
1440 }
1441
1442 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
1443 {
1444     // FIXME: implement
1445 }
1446
1447 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
1448 {
1449     // FIXME: implement
1450 }