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