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