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