[EFL] accessibility/button-press-action.html
[WebKit-https.git] / Tools / WebKitTestRunner / InjectedBundle / atk / AccessibilityUIElementAtk.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2012 Igalia S.L.
4  * Copyright (C) 2013 Samsung Electronics. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "AccessibilityUIElement.h"
30
31 #if HAVE(ACCESSIBILITY)
32
33 #include "InjectedBundle.h"
34 #include "InjectedBundlePage.h"
35 #include "NotImplemented.h"
36 #include <JavaScriptCore/JSStringRef.h>
37 #include <JavaScriptCore/OpaqueJSString.h>
38 #include <atk/atk.h>
39 #include <wtf/Assertions.h>
40 #include <wtf/gobject/GOwnPtr.h>
41 #include <wtf/gobject/GRefPtr.h>
42 #include <wtf/text/CString.h>
43 #include <wtf/text/StringBuilder.h>
44 #include <wtf/text/WTFString.h>
45 #include <wtf/unicode/CharacterNames.h>
46
47 namespace WTR {
48
49 namespace {
50
51 enum AtkAttributeType {
52     ObjectAttributeType,
53     TextAttributeType
54 };
55
56 enum AttributeDomain {
57     CoreDomain = 0,
58     AtkDomain
59 };
60
61 enum AttributesIndex {
62     // Attribute names.
63     InvalidNameIndex = 0,
64     PlaceholderNameIndex,
65     SortNameIndex,
66
67     // Attribute values.
68     SortAscendingValueIndex,
69     SortDescendingValueIndex,
70     SortUnknownValueIndex,
71
72     NumberOfAttributes
73 };
74
75 // Attribute names & Values (keep on sync with enum AttributesIndex).
76 const String attributesMap[][2] = {
77     // Attribute names.
78     { "AXInvalid", "invalid" },
79     { "AXPlaceholderValue", "placeholder-text" } ,
80     { "AXSortDirection", "sort" },
81
82     // Attribute values.
83     { "AXAscendingSortDirection", "ascending" },
84     { "AXDescendingSortDirection", "descending" },
85     { "AXUnknownSortDirection", "unknown" }
86 };
87
88 String coreAttributeToAtkAttribute(JSStringRef attribute)
89 {
90     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(attribute);
91     GOwnPtr<gchar> buffer(static_cast<gchar*>(g_malloc(bufferSize)));
92     JSStringGetUTF8CString(attribute, buffer.get(), bufferSize);
93
94     String attributeString = String::fromUTF8(buffer.get());
95     for (int i = 0; i < NumberOfAttributes; ++i) {
96         if (attributesMap[i][CoreDomain] == attributeString)
97             return attributesMap[i][AtkDomain];
98     }
99
100     return attributeString;
101 }
102
103 String atkAttributeValueToCoreAttributeValue(AtkAttributeType type, const String& id, const String& value)
104 {
105     if (type == ObjectAttributeType) {
106         // We need to translate ATK values exposed for 'aria-sort' (e.g. 'ascending')
107         // into those expected by the layout tests (e.g. 'AXAscendingSortDirection').
108         if (id == attributesMap[SortNameIndex][AtkDomain] && !value.isEmpty()) {
109             if (value == attributesMap[SortAscendingValueIndex][AtkDomain])
110                 return attributesMap[SortAscendingValueIndex][CoreDomain];
111             if (value == attributesMap[SortDescendingValueIndex][AtkDomain])
112                 return attributesMap[SortDescendingValueIndex][CoreDomain];
113
114             return attributesMap[SortUnknownValueIndex][CoreDomain];
115         }
116     } else if (type == TextAttributeType) {
117         // In case of 'aria-invalid' when the attribute empty or has "false" for ATK
118         // it should not be mapped at all, but layout tests will expect 'false'.
119         if (id == attributesMap[InvalidNameIndex][AtkDomain] && value.isEmpty())
120             return "false";
121     }
122
123     return value;
124 }
125
126 AtkAttributeSet* getAttributeSet(AtkObject* accessible, AtkAttributeType type)
127 {
128     if (type == ObjectAttributeType)
129         return atk_object_get_attributes(accessible);
130
131     if (type == TextAttributeType) {
132         if (!ATK_IS_TEXT(accessible))
133             return 0;
134
135         return atk_text_get_default_attributes(ATK_TEXT(accessible));
136     }
137
138     ASSERT_NOT_REACHED();
139     return 0;
140 }
141
142 String getAttributeSetValueForId(AtkObject* accessible, AtkAttributeType type, String id)
143 {
144     AtkAttributeSet* attributeSet = getAttributeSet(accessible, type);
145     if (!attributeSet)
146         return String();
147
148     String attributeValue;
149     for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
150         AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(attributes->data);
151         if (id == atkAttribute->name) {
152             attributeValue = String::fromUTF8(atkAttribute->value);
153             break;
154         }
155     }
156     atk_attribute_set_free(attributeSet);
157
158     return atkAttributeValueToCoreAttributeValue(type, id, attributeValue);
159 }
160
161 String getAtkAttributeSetAsString(AtkObject* accessible, AtkAttributeType type)
162 {
163     AtkAttributeSet* attributeSet = getAttributeSet(accessible, type);
164     if (!attributeSet)
165         return String();
166
167     StringBuilder builder;
168     for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
169         AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
170         GOwnPtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL));
171         builder.append(attributeData.get());
172         if (attributes->next)
173             builder.append(", ");
174     }
175     atk_attribute_set_free(attributeSet);
176
177     return builder.toString();
178 }
179
180 bool checkElementState(PlatformUIElement element, AtkStateType stateType)
181 {
182     if (!ATK_IS_OBJECT(element.get()))
183         return false;
184
185     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element.get())));
186     return atk_state_set_contains_state(stateSet.get(), stateType);
187 }
188
189 JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
190 {
191     GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
192
193     if (!ATK_IS_OBJECT(element.get()))
194         return JSStringCreateWithUTF8CString(rangeString.get());
195
196     AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element.get()));
197     if (!axTable || !ATK_IS_TABLE(axTable))
198         return JSStringCreateWithUTF8CString(rangeString.get());
199
200     // Look for the cell in the table.
201     gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element.get()));
202     if (indexInParent == -1)
203         return JSStringCreateWithUTF8CString(rangeString.get());
204
205     int row = -1;
206     int column = -1;
207     row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent);
208     column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent);
209
210     // Get the actual values, if row and columns are valid values.
211     if (row != -1 && column != -1) {
212         int base = 0;
213         int length = 0;
214         if (isRowRange) {
215             base = row;
216             length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column);
217         } else {
218             base = column;
219             length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column);
220         }
221         rangeString.set(g_strdup_printf("{%d, %d}", base, length));
222     }
223
224     return JSStringCreateWithUTF8CString(rangeString.get());
225 }
226
227 void alterCurrentValue(PlatformUIElement element, int factor)
228 {
229     if (!ATK_IS_VALUE(element.get()))
230         return;
231
232     GValue currentValue = G_VALUE_INIT;
233     atk_value_get_current_value(ATK_VALUE(element.get()), &currentValue);
234
235     GValue increment = G_VALUE_INIT;
236     atk_value_get_minimum_increment(ATK_VALUE(element.get()), &increment);
237
238     GValue newValue = G_VALUE_INIT;
239     g_value_init(&newValue, G_TYPE_FLOAT);
240
241     g_value_set_float(&newValue, g_value_get_float(&currentValue) + factor * g_value_get_float(&increment));
242     atk_value_set_current_value(ATK_VALUE(element.get()), &newValue);
243
244     g_value_unset(&newValue);
245     g_value_unset(&increment);
246     g_value_unset(&currentValue);
247 }
248
249 gchar* replaceCharactersForResults(gchar* str)
250 {
251     WTF::String uString = WTF::String::fromUTF8(str);
252
253     // The object replacement character is passed along to ATs so we need to be
254     // able to test for their presence and do so without causing test failures.
255     uString.replace(objectReplacementCharacter, "<obj>");
256
257     // The presence of newline characters in accessible text of a single object
258     // is appropriate, but it makes test results (especially the accessible tree)
259     // harder to read.
260     uString.replace("\n", "<\\n>");
261
262     return g_strdup(uString.utf8().data());
263 }
264
265 const gchar* roleToString(AtkRole role)
266 {
267     switch (role) {
268     case ATK_ROLE_ALERT:
269         return "AXAlert";
270     case ATK_ROLE_CANVAS:
271         return "AXCanvas";
272     case ATK_ROLE_CHECK_BOX:
273         return "AXCheckBox";
274     case ATK_ROLE_COLOR_CHOOSER:
275         return "AXColorWell";
276     case ATK_ROLE_COLUMN_HEADER:
277         return "AXColumnHeader";
278     case ATK_ROLE_COMBO_BOX:
279         return "AXComboBox";
280     case ATK_ROLE_DOCUMENT_FRAME:
281         return "AXWebArea";
282     case ATK_ROLE_ENTRY:
283         return "AXTextField";
284     case ATK_ROLE_FOOTER:
285         return "AXFooter";
286     case ATK_ROLE_FORM:
287         return "AXForm";
288     case ATK_ROLE_GROUPING:
289         return "AXGroup";
290     case ATK_ROLE_HEADING:
291         return "AXHeading";
292     case ATK_ROLE_IMAGE:
293         return "AXImage";
294     case ATK_ROLE_IMAGE_MAP:
295         return "AXImageMap";
296     case ATK_ROLE_LABEL:
297         return "AXLabel";
298     case ATK_ROLE_LINK:
299         return "AXLink";
300     case ATK_ROLE_LIST:
301         return "AXList";
302     case ATK_ROLE_LIST_BOX:
303         return "AXListBox";
304     case ATK_ROLE_LIST_ITEM:
305         return "AXListItem";
306     case ATK_ROLE_MENU:
307         return "AXMenu";
308     case ATK_ROLE_MENU_BAR:
309         return "AXMenuBar";
310     case ATK_ROLE_MENU_ITEM:
311         return "AXMenuItem";
312     case ATK_ROLE_PAGE_TAB:
313         return "AXTab";
314     case ATK_ROLE_PAGE_TAB_LIST:
315         return "AXTabGroup";
316     case ATK_ROLE_PANEL:
317         return "AXGroup";
318     case ATK_ROLE_PARAGRAPH:
319         return "AXParagraph";
320     case ATK_ROLE_PASSWORD_TEXT:
321         return "AXPasswordField";
322     case ATK_ROLE_PROGRESS_BAR:
323         return "AXProgressIndicator";
324     case ATK_ROLE_PUSH_BUTTON:
325         return "AXButton";
326     case ATK_ROLE_RADIO_BUTTON:
327         return "AXRadioButton";
328     case ATK_ROLE_RADIO_MENU_ITEM:
329         return "AXRadioMenuItem";
330     case ATK_ROLE_ROW_HEADER:
331         return "AXRowHeader";
332     case ATK_ROLE_RULER:
333         return "AXRuler";
334     case ATK_ROLE_SCROLL_BAR:
335         return "AXScrollBar";
336     case ATK_ROLE_SCROLL_PANE:
337         return "AXScrollArea";
338     case ATK_ROLE_SECTION:
339         return "AXDiv";
340     case ATK_ROLE_SEPARATOR:
341         return "AXHorizontalRule";
342     case ATK_ROLE_SLIDER:
343         return "AXSlider";
344     case ATK_ROLE_SPIN_BUTTON:
345         return "AXSpinButton";
346     case ATK_ROLE_TABLE:
347         return "AXTable";
348     case ATK_ROLE_TABLE_CELL:
349         return "AXCell";
350     case ATK_ROLE_TABLE_COLUMN_HEADER:
351         return "AXColumnHeader";
352     case ATK_ROLE_TABLE_ROW:
353         return "AXRow";
354     case ATK_ROLE_TABLE_ROW_HEADER:
355         return "AXRowHeader";
356     case ATK_ROLE_TOGGLE_BUTTON:
357         return "AXToggleButton";
358     case ATK_ROLE_TOOL_BAR:
359         return "AXToolbar";
360     case ATK_ROLE_TOOL_TIP:
361         return "AXUserInterfaceTooltip";
362     case ATK_ROLE_TREE:
363         return "AXTree";
364     case ATK_ROLE_TREE_TABLE:
365         return "AXTreeGrid";
366     case ATK_ROLE_TREE_ITEM:
367         return "AXTreeItem";
368     case ATK_ROLE_WINDOW:
369         return "AXWindow";
370     case ATK_ROLE_UNKNOWN:
371         return "AXUnknown";
372     default:
373         // We want to distinguish ATK_ROLE_UNKNOWN from a known AtkRole which
374         // our DRT isn't properly handling.
375         return "FIXME not identified";
376     }
377 }
378
379 String attributesOfElement(AccessibilityUIElement* element)
380 {
381     StringBuilder builder;
382
383     builder.append(String::format("%s\n", element->role()->string().utf8().data()));
384
385     // For the parent we print its role and its name, if available.
386     builder.append("AXParent: ");
387     RefPtr<AccessibilityUIElement> parent = element->parentElement();
388     AtkObject* atkParent = parent ? parent->platformUIElement().get() : 0;
389     if (atkParent) {
390         builder.append(roleToString(atk_object_get_role(atkParent)));
391         const char* parentName = atk_object_get_name(atkParent);
392         if (parentName && g_utf8_strlen(parentName, -1))
393             builder.append(String::format(": %s", parentName));
394     } else
395         builder.append("(null)");
396     builder.append("\n");
397
398     builder.append(String::format("AXChildren: %d\n", element->childrenCount()));
399     builder.append(String::format("AXPosition: { %f, %f }\n", element->x(), element->y()));
400     builder.append(String::format("AXSize: { %f, %f }\n", element->width(), element->height()));
401
402     String title = element->title()->string();
403     if (!title.isEmpty())
404         builder.append(String::format("%s\n", title.utf8().data()));
405
406     String description = element->description()->string();
407     if (!description.isEmpty())
408         builder.append(String::format("%s\n", description.utf8().data()));
409
410     String value = element->stringValue()->string();
411     if (!value.isEmpty())
412         builder.append(String::format("%s\n", value.utf8().data()));
413
414     builder.append(String::format("AXFocusable: %d\n", element->isFocusable()));
415     builder.append(String::format("AXFocused: %d\n", element->isFocused()));
416     builder.append(String::format("AXSelectable: %d\n", element->isSelectable()));
417     builder.append(String::format("AXSelected: %d\n", element->isSelected()));
418     builder.append(String::format("AXMultiSelectable: %d\n", element->isMultiSelectable()));
419     builder.append(String::format("AXEnabled: %d\n", element->isEnabled()));
420     builder.append(String::format("AXExpanded: %d\n", element->isExpanded()));
421     builder.append(String::format("AXRequired: %d\n", element->isRequired()));
422     builder.append(String::format("AXChecked: %d\n", element->isChecked()));
423
424     String url = element->url()->string();
425     if (!url.isEmpty())
426         builder.append(String::format("%s\n", url.utf8().data()));
427
428     // We append the ATK specific attributes as a single line at the end.
429     builder.append("AXPlatformAttributes: ");
430     builder.append(getAtkAttributeSetAsString(element->platformUIElement().get(), ObjectAttributeType));
431
432     return builder.toString();
433 }
434
435 } // namespace
436
437 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
438     : m_element(element)
439 {
440 }
441
442 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
443     : JSWrappable()
444     , m_element(other.m_element)
445 {
446 }
447
448 AccessibilityUIElement::~AccessibilityUIElement()
449 {
450 }
451
452 bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement)
453 {
454     return m_element == otherElement->platformUIElement();
455 }
456
457 void AccessibilityUIElement::getChildren(Vector<RefPtr<AccessibilityUIElement> >& children)
458 {
459     if (!ATK_IS_OBJECT(m_element.get()))
460         return;
461
462     int count = childrenCount();
463     for (int i = 0; i < count; i++) {
464         GRefPtr<AtkObject> child = adoptGRef(atk_object_ref_accessible_child(ATK_OBJECT(m_element.get()), i));
465         children.append(AccessibilityUIElement::create(child.get()));
466     }
467 }
468
469 void AccessibilityUIElement::getChildrenWithRange(Vector<RefPtr<AccessibilityUIElement> >& children, unsigned location, unsigned length)
470 {
471     if (!ATK_IS_OBJECT(m_element.get()))
472         return;
473     unsigned end = location + length;
474     for (unsigned i = location; i < end; i++) {
475         GRefPtr<AtkObject> child = adoptGRef(atk_object_ref_accessible_child(ATK_OBJECT(m_element.get()), i));
476         children.append(AccessibilityUIElement::create(child.get()));
477     }
478 }
479
480 int AccessibilityUIElement::childrenCount()
481 {
482     if (!ATK_IS_OBJECT(m_element.get()))
483         return 0;
484
485     return atk_object_get_n_accessible_children(ATK_OBJECT(m_element.get()));
486 }
487
488 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::elementAtPoint(int x, int y)
489 {
490     if (!ATK_IS_COMPONENT(m_element.get()))
491         return 0;
492
493     GRefPtr<AtkObject> objectAtPoint = adoptGRef(atk_component_ref_accessible_at_point(ATK_COMPONENT(m_element.get()), x, y, ATK_XY_WINDOW));
494     return objectAtPoint ? AccessibilityUIElement::create(objectAtPoint.get()) : 0;
495 }
496
497 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
498 {
499     if (!ATK_IS_OBJECT(m_element.get()))
500         return 0;
501
502     Vector<RefPtr<AccessibilityUIElement> > children;
503     getChildren(children);
504
505     unsigned count = children.size();
506     for (unsigned i = 0; i < count; i++)
507         if (children[i]->isEqual(element))
508             return i;
509
510     return 0;
511 }
512
513 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned index)
514 {
515     if (!ATK_IS_OBJECT(m_element.get()))
516         return 0;
517
518     Vector<RefPtr<AccessibilityUIElement> > children;
519     getChildrenWithRange(children, index, 1);
520
521     if (children.size() == 1)
522         return children[0];
523
524     return 0;
525 }
526
527 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
528 {
529     // FIXME: implement
530     return 0;
531 }
532
533 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
534 {
535     // FIXME: implement
536     return 0;
537 }
538
539 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
540 {
541     // FIXME: implement
542     return 0;
543 }
544
545 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
546 {
547     // FIXME: implement
548     return 0;
549 }
550
551 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::rowAtIndex(unsigned index)
552 {
553     // FIXME: implement
554     return 0;
555 }
556
557 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
558 {
559     // FIXME: implement
560     return 0;
561 }
562
563 unsigned AccessibilityUIElement::selectedChildrenCount() const
564 {
565     // FIXME: implement
566     return 0;
567 }
568
569 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedRowAtIndex(unsigned index)
570 {
571     // FIXME: implement
572     return 0;
573 }
574
575 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::titleUIElement()
576 {
577     if (!ATK_IS_OBJECT(m_element.get()))
578         return 0;
579
580     AtkRelationSet* set = atk_object_ref_relation_set(ATK_OBJECT(m_element.get()));
581     if (!set)
582         return 0;
583
584     AtkObject* target = 0;
585     int count = atk_relation_set_get_n_relations(set);
586     for (int i = 0; i < count; i++) {
587         AtkRelation* relation = atk_relation_set_get_relation(set, i);
588         if (atk_relation_get_relation_type(relation) == ATK_RELATION_LABELLED_BY) {
589             GPtrArray* targetList = atk_relation_get_target(relation);
590             if (targetList->len)
591                 target = static_cast<AtkObject*>(g_ptr_array_index(targetList, 0));
592         }
593     }
594
595     g_object_unref(set);
596     return target ? AccessibilityUIElement::create(target) : 0;
597 }
598
599 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::parentElement()
600 {
601     if (!ATK_IS_OBJECT(m_element.get()))
602         return 0;
603
604     AtkObject* parent = atk_object_get_parent(ATK_OBJECT(m_element.get()));
605     return parent ? AccessibilityUIElement::create(parent) : 0;
606 }
607
608 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedByRow()
609 {
610     // FIXME: implement
611     return 0;
612 }
613
614 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfLinkedUIElements()
615 {
616     // FIXME: implement
617     return JSStringCreateWithCharacters(0, 0);
618 }
619
620 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfDocumentLinks()
621 {
622     // FIXME: implement
623     return JSStringCreateWithCharacters(0, 0);
624 }
625
626 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfChildren()
627 {
628     if (!ATK_IS_OBJECT(m_element.get()))
629         return JSStringCreateWithCharacters(0, 0);
630
631     Vector<RefPtr<AccessibilityUIElement> > children;
632     getChildren(children);
633
634     StringBuilder builder;
635     for (Vector<RefPtr<AccessibilityUIElement> >::iterator it = children.begin(); it != children.end(); ++it) {
636         builder.append(attributesOfElement(it->get()));
637         builder.append("\n------------\n");
638     }
639
640     return JSStringCreateWithUTF8CString(builder.toString().utf8().data());
641 }
642
643 JSRetainPtr<JSStringRef> AccessibilityUIElement::allAttributes()
644 {
645     if (!ATK_IS_OBJECT(m_element.get()))
646         return JSStringCreateWithCharacters(0, 0);
647
648     return JSStringCreateWithUTF8CString(attributesOfElement(this).utf8().data());
649 }
650
651 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
652 {
653     if (!ATK_IS_OBJECT(m_element.get()))
654         return JSStringCreateWithCharacters(0, 0);
655
656     String atkAttributeName = coreAttributeToAtkAttribute(attribute);
657
658     // Try object attributes first.
659     String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, atkAttributeName);
660
661     // Try text attributes if the requested one was not found and we have an AtkText object.
662     if (attributeValue.isEmpty() && ATK_IS_TEXT(m_element.get()))
663         attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), TextAttributeType, atkAttributeName);
664
665     // Additional check to make sure that the exposure of the state ATK_STATE_INVALID_ENTRY
666     // is consistent with the exposure of aria-invalid as a text attribute, if present.
667     if (atkAttributeName == attributesMap[InvalidNameIndex][AtkDomain]) {
668         bool isInvalidState = checkElementState(m_element.get(), ATK_STATE_INVALID_ENTRY);
669         if (attributeValue.isEmpty())
670             return JSStringCreateWithUTF8CString(isInvalidState ? "true" : "false");
671
672         // If the text attribute was there, check that it's consistent with
673         // what the state says or force the test to fail otherwise.
674         bool isAriaInvalid = attributeValue != "false";
675         if (isInvalidState != isAriaInvalid)
676             return JSStringCreateWithCharacters(0, 0);
677     }
678
679     return JSStringCreateWithUTF8CString(attributeValue.utf8().data());
680 }
681
682 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
683 {
684     // FIXME: implement
685     return 0;
686 }
687
688 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
689 {
690     // FIXME: implement
691     return 0;
692 }
693
694 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
695 {
696     // FIXME: implement
697     return false;
698 }
699
700 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
701 {
702     // FIXME: implement
703     return false;
704 }
705
706 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
707 {
708     if (!ATK_IS_OBJECT(m_element.get()))
709         return false;
710
711     String atkAttributeName = coreAttributeToAtkAttribute(attribute);
712     if (atkAttributeName.isEmpty())
713         return false;
714
715     // For now, an attribute is supported whether it's exposed as a object or a text attribute.
716     String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, atkAttributeName);
717     if (attributeValue.isEmpty())
718         attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), TextAttributeType, atkAttributeName);
719
720     return !attributeValue.isEmpty();
721 }
722
723 JSRetainPtr<JSStringRef> AccessibilityUIElement::parameterizedAttributeNames()
724 {
725     // FIXME: implement
726     return JSStringCreateWithCharacters(0, 0);
727 }
728
729 JSRetainPtr<JSStringRef> AccessibilityUIElement::role()
730 {
731     if (!ATK_IS_OBJECT(m_element.get()))
732         return JSStringCreateWithCharacters(0, 0);
733
734     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get()));
735     if (!role)
736         return JSStringCreateWithCharacters(0, 0);
737
738     GOwnPtr<char> roleStringWithPrefix(g_strdup_printf("AXRole: %s", roleToString(role)));
739     return JSStringCreateWithUTF8CString(roleStringWithPrefix.get());
740 }
741
742 JSRetainPtr<JSStringRef> AccessibilityUIElement::subrole()
743 {
744     // FIXME: implement
745     return JSStringCreateWithCharacters(0, 0);
746 }
747
748 JSRetainPtr<JSStringRef> AccessibilityUIElement::roleDescription()
749 {
750     // FIXME: implement
751     return JSStringCreateWithCharacters(0, 0);
752 }
753
754 JSRetainPtr<JSStringRef> AccessibilityUIElement::title()
755 {
756     if (!ATK_IS_OBJECT(m_element.get()))
757         return JSStringCreateWithCharacters(0, 0);
758
759     const gchar* name = atk_object_get_name(ATK_OBJECT(m_element.get()));
760     GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name ? name : ""));
761
762     return JSStringCreateWithUTF8CString(axTitle.get());
763 }
764
765 JSRetainPtr<JSStringRef> AccessibilityUIElement::description()
766 {
767     if (!ATK_IS_OBJECT(m_element.get()))
768         return JSStringCreateWithCharacters(0, 0);
769
770     const gchar* description = atk_object_get_description(ATK_OBJECT(m_element.get()));
771     if (!description)
772         return JSStringCreateWithCharacters(0, 0);
773
774     GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
775
776     return JSStringCreateWithUTF8CString(axDesc.get());
777 }
778
779 JSRetainPtr<JSStringRef> AccessibilityUIElement::orientation() const
780 {
781     if (!ATK_IS_OBJECT(m_element.get()))
782         return JSStringCreateWithCharacters(0, 0);
783
784     const gchar* axOrientation = 0;
785     if (checkElementState(m_element.get(), ATK_STATE_HORIZONTAL))
786         axOrientation = "AXOrientation: AXHorizontalOrientation";
787     else if (checkElementState(m_element.get(), ATK_STATE_VERTICAL))
788         axOrientation = "AXOrientation: AXVerticalOrientation";
789
790     if (!axOrientation)
791         return JSStringCreateWithCharacters(0, 0);
792
793     return JSStringCreateWithUTF8CString(axOrientation);
794 }
795
796 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringValue()
797 {
798     if (!ATK_IS_TEXT(m_element.get()))
799         return JSStringCreateWithCharacters(0, 0);
800
801     GOwnPtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element.get()), 0, -1));
802     GOwnPtr<gchar> textWithReplacedCharacters(replaceCharactersForResults(text.get()));
803     GOwnPtr<gchar> axValue(g_strdup_printf("AXValue: %s", textWithReplacedCharacters.get()));
804
805     return JSStringCreateWithUTF8CString(axValue.get());
806 }
807
808 JSRetainPtr<JSStringRef> AccessibilityUIElement::language()
809 {
810     if (!ATK_IS_OBJECT(m_element.get()))
811         return JSStringCreateWithCharacters(0, 0);
812
813     const gchar* locale = atk_object_get_object_locale(ATK_OBJECT(m_element.get()));
814     if (!locale)
815         return JSStringCreateWithCharacters(0, 0);
816
817     GOwnPtr<char> axValue(g_strdup_printf("AXLanguage: %s", locale));
818     return JSStringCreateWithUTF8CString(axValue.get());
819 }
820
821 JSRetainPtr<JSStringRef> AccessibilityUIElement::helpText() const
822 {
823     // FIXME: We need to provide a proper implementation for this that does
824     // not depend on Mac specific concepts such as ATK_RELATION_DESCRIBED_BY,
825     // once it's implemented (see http://webkit.org/b/121684).
826     return JSStringCreateWithCharacters(0, 0);
827 }
828
829 double AccessibilityUIElement::x()
830 {
831     if (!ATK_IS_COMPONENT(m_element.get()))
832         return 0;
833
834     int x, y;
835     atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_SCREEN);
836     return x;
837 }
838
839 double AccessibilityUIElement::y()
840 {
841     if (!ATK_IS_COMPONENT(m_element.get()))
842         return 0;
843
844     int x, y;
845     atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_SCREEN);
846     return y;
847 }
848
849 double AccessibilityUIElement::width()
850 {
851     if (!ATK_IS_COMPONENT(m_element.get()))
852         return 0;
853
854     int width, height;
855     atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height);
856     return width;
857 }
858
859 double AccessibilityUIElement::height()
860 {
861     if (!ATK_IS_COMPONENT(m_element.get()))
862         return 0;
863
864     int width, height;
865     atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height);
866     return height;
867 }
868
869 double AccessibilityUIElement::clickPointX()
870 {
871     if (!ATK_IS_COMPONENT(m_element.get()))
872         return 0;
873
874     int x, y;
875     atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_WINDOW);
876
877     int width, height;
878     atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height);
879
880     return x + width / 2.0;
881 }
882
883 double AccessibilityUIElement::clickPointY()
884 {
885     if (!ATK_IS_COMPONENT(m_element.get()))
886         return 0;
887
888     int x, y;
889     atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_WINDOW);
890
891     int width, height;
892     atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height);
893
894     return y + height / 2.0;
895 }
896
897 double AccessibilityUIElement::intValue() const
898 {
899     if (!ATK_IS_OBJECT(m_element.get()))
900         return 0;
901
902     if (ATK_IS_VALUE(m_element.get())) {
903         GValue value = G_VALUE_INIT;
904         atk_value_get_current_value(ATK_VALUE(m_element.get()), &value);
905         if (!G_VALUE_HOLDS_FLOAT(&value))
906             return 0;
907         return g_value_get_float(&value);
908     }
909
910     // Consider headings as an special case when returning the "int value" of
911     // an AccessibilityUIElement, so we can reuse some tests to check the level
912     // both for HTML headings and objects with the aria-level attribute.
913     if (atk_object_get_role(ATK_OBJECT(m_element.get())) == ATK_ROLE_HEADING) {
914         String headingLevel = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "level");
915         bool ok;
916         double headingLevelValue = headingLevel.toDouble(&ok);
917         if (ok)
918             return headingLevelValue;
919     }
920
921     return 0;
922 }
923
924 double AccessibilityUIElement::minValue()
925 {
926     if (!ATK_IS_VALUE(m_element.get()))
927         return 0;
928
929     GValue value = G_VALUE_INIT;
930     atk_value_get_minimum_value(ATK_VALUE(m_element.get()), &value);
931     if (!G_VALUE_HOLDS_FLOAT(&value))
932         return 0;
933
934     return g_value_get_float(&value);
935 }
936
937 double AccessibilityUIElement::maxValue()
938 {
939     if (!ATK_IS_VALUE(m_element.get()))
940         return 0;
941
942     GValue value = G_VALUE_INIT;
943     atk_value_get_maximum_value(ATK_VALUE(m_element.get()), &value);
944     if (!G_VALUE_HOLDS_FLOAT(&value))
945         return 0;
946
947     return g_value_get_float(&value);
948 }
949
950 JSRetainPtr<JSStringRef> AccessibilityUIElement::valueDescription()
951 {
952     // FIXME: implement
953     return JSStringCreateWithCharacters(0, 0);
954 }
955
956 int AccessibilityUIElement::insertionPointLineNumber()
957 {
958     // FIXME: implement
959     return -1;
960 }
961
962 bool AccessibilityUIElement::isPressActionSupported()
963 {
964     if (!ATK_IS_ACTION(m_element.get()))
965         return false;
966
967     return equalIgnoringCase(atk_action_get_name(ATK_ACTION(m_element.get()), 0), String("press"));
968 }
969
970 bool AccessibilityUIElement::isIncrementActionSupported()
971 {
972     // FIXME: implement
973     return false;
974 }
975
976 bool AccessibilityUIElement::isDecrementActionSupported()
977 {
978     // FIXME: implement
979     return false;
980 }
981
982 bool AccessibilityUIElement::isEnabled()
983 {
984     return checkElementState(m_element.get(), ATK_STATE_ENABLED);
985 }
986
987 bool AccessibilityUIElement::isRequired() const
988 {
989     return checkElementState(m_element.get(), ATK_STATE_REQUIRED);
990 }
991
992 bool AccessibilityUIElement::isFocused() const
993 {
994     return checkElementState(m_element.get(), ATK_STATE_FOCUSED);
995 }
996
997 bool AccessibilityUIElement::isSelected() const
998 {
999     return checkElementState(m_element.get(), ATK_STATE_SELECTED);
1000 }
1001
1002 bool AccessibilityUIElement::isExpanded() const
1003 {
1004     return checkElementState(m_element.get(), ATK_STATE_EXPANDED);
1005 }
1006
1007 bool AccessibilityUIElement::isChecked() const
1008 {
1009     return checkElementState(m_element.get(), ATK_STATE_CHECKED);
1010 }
1011
1012 int AccessibilityUIElement::hierarchicalLevel() const
1013 {
1014     // FIXME: implement
1015     return 0;
1016 }
1017
1018 JSRetainPtr<JSStringRef> AccessibilityUIElement::speak()
1019 {
1020     // FIXME: implement
1021     return JSStringCreateWithCharacters(0, 0);
1022 }
1023
1024 bool AccessibilityUIElement::ariaIsGrabbed() const
1025 {
1026     // FIXME: implement
1027     return false;
1028 }
1029
1030 JSRetainPtr<JSStringRef> AccessibilityUIElement::ariaDropEffects() const
1031 {
1032     // FIXME: implement
1033     return JSStringCreateWithCharacters(0, 0);
1034 }
1035
1036 // parameterized attributes
1037 int AccessibilityUIElement::lineForIndex(int index)
1038 {
1039     // FIXME: implement
1040     return 0;
1041 }
1042
1043 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForLine(int line)
1044 {
1045     // FIXME: implement
1046     return JSStringCreateWithCharacters(0, 0);
1047 }
1048
1049 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForPosition(int x, int y)
1050 {
1051     // FIXME: implement
1052     return JSStringCreateWithCharacters(0, 0);
1053 }
1054
1055 JSRetainPtr<JSStringRef> AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
1056 {
1057     // FIXME: implement
1058     return JSStringCreateWithCharacters(0, 0);
1059 }
1060
1061 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
1062 {
1063     // FIXME: implement
1064     return JSStringCreateWithCharacters(0, 0);
1065 }
1066
1067 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
1068 {
1069     // FIXME: implement
1070     return JSStringCreateWithCharacters(0, 0);
1071 }
1072
1073 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
1074 {
1075     // FIXME: implement
1076     return false;
1077 }
1078
1079 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly)
1080 {
1081     // FIXME: implement
1082     return 0;
1083 }
1084
1085 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
1086 {
1087     // FIXME: implement
1088     return JSStringCreateWithCharacters(0, 0);
1089 }
1090
1091 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRowHeaders()
1092 {
1093     // FIXME: implement
1094     return JSStringCreateWithCharacters(0, 0);
1095 }
1096
1097 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumns()
1098 {
1099     // FIXME: implement
1100     return JSStringCreateWithCharacters(0, 0);
1101 }
1102
1103 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRows()
1104 {
1105     // FIXME: implement
1106     return JSStringCreateWithCharacters(0, 0);
1107 }
1108
1109 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfVisibleCells()
1110 {
1111     // FIXME: implement
1112     return JSStringCreateWithCharacters(0, 0);
1113 }
1114
1115 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfHeader()
1116 {
1117     // FIXME: implement
1118     return JSStringCreateWithCharacters(0, 0);
1119 }
1120
1121 int AccessibilityUIElement::rowCount()
1122 {
1123     if (!ATK_IS_TABLE(m_element.get()))
1124         return 0;
1125
1126     return atk_table_get_n_rows(ATK_TABLE(m_element.get()));
1127 }
1128
1129 int AccessibilityUIElement::columnCount()
1130 {
1131     if (!ATK_IS_TABLE(m_element.get()))
1132         return 0;
1133
1134     return atk_table_get_n_columns(ATK_TABLE(m_element.get()));
1135 }
1136
1137 int AccessibilityUIElement::indexInTable()
1138 {
1139     // FIXME: implement
1140     return -1;
1141 }
1142
1143 JSRetainPtr<JSStringRef> AccessibilityUIElement::rowIndexRange()
1144 {
1145     // Range in table for rows.
1146     return indexRangeInTable(m_element.get(), true);
1147 }
1148
1149 JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange()
1150 {
1151     // Range in table for columns.
1152     return indexRangeInTable(m_element.get(), false);
1153 }
1154
1155 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1156 {
1157     if (!ATK_IS_TABLE(m_element.get()))
1158         return 0;
1159
1160     // Adopt the AtkObject representing the cell because
1161     // at_table_ref_at() transfers full ownership.
1162     GRefPtr<AtkObject> foundCell = adoptGRef(atk_table_ref_at(ATK_TABLE(m_element.get()), row, col));
1163     return foundCell ? AccessibilityUIElement::create(foundCell.get()) : 0;
1164 }
1165
1166 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::horizontalScrollbar() const
1167 {
1168     // FIXME: implement
1169     return 0;
1170 }
1171
1172 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::verticalScrollbar() const
1173 {
1174     // FIXME: implement
1175     return 0;
1176 }
1177
1178 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectedTextRange()
1179 {
1180     if (!ATK_IS_TEXT(m_element.get()))
1181         return JSStringCreateWithCharacters(0, 0);
1182
1183     gint start, end;
1184     g_free(atk_text_get_selection(ATK_TEXT(m_element.get()), 0, &start, &end));
1185
1186     GOwnPtr<gchar> selection(g_strdup_printf("{%d, %d}", start, end - start));
1187     return JSStringCreateWithUTF8CString(selection.get());
1188 }
1189
1190 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1191 {
1192     if (!ATK_IS_TEXT(m_element.get()))
1193         return;
1194
1195     atk_text_set_selection(ATK_TEXT(m_element.get()), 0, location, location + length);
1196 }
1197
1198 void AccessibilityUIElement::increment()
1199 {
1200     alterCurrentValue(m_element.get(), 1);
1201 }
1202
1203 void AccessibilityUIElement::decrement()
1204 {
1205     alterCurrentValue(m_element.get(), -1);
1206 }
1207
1208 void AccessibilityUIElement::showMenu()
1209 {
1210     // FIXME: implement
1211 }
1212
1213 void AccessibilityUIElement::press()
1214 {
1215     if (!ATK_IS_ACTION(m_element.get()))
1216         return;
1217
1218     // Only one action per object is supported so far.
1219     atk_action_do_action(ATK_ACTION(m_element.get()), 0);
1220 }
1221
1222 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1223 {
1224     // FIXME: implement
1225 }
1226
1227 JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const
1228 {
1229     // FIXME: implement
1230     return JSStringCreateWithCharacters(0, 0);
1231 }
1232
1233 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentEncoding()
1234 {
1235     if (!ATK_IS_DOCUMENT(m_element.get()))
1236         return JSStringCreateWithCharacters(0, 0);
1237
1238     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get()));
1239     if (role != ATK_ROLE_DOCUMENT_FRAME)
1240         return JSStringCreateWithCharacters(0, 0);
1241
1242     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "Encoding"));
1243 }
1244
1245 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentURI()
1246 {
1247     if (!ATK_IS_DOCUMENT(m_element.get()))
1248         return JSStringCreateWithCharacters(0, 0);
1249
1250     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get()));
1251     if (role != ATK_ROLE_DOCUMENT_FRAME)
1252         return JSStringCreateWithCharacters(0, 0);
1253
1254     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "URI"));
1255 }
1256
1257 JSRetainPtr<JSStringRef> AccessibilityUIElement::url()
1258 {
1259     if (!ATK_IS_HYPERLINK_IMPL(m_element.get()))
1260         return JSStringCreateWithCharacters(0, 0);
1261
1262     AtkHyperlink* hyperlink = atk_hyperlink_impl_get_hyperlink(ATK_HYPERLINK_IMPL(m_element.get()));
1263     GOwnPtr<char> hyperlinkURI(atk_hyperlink_get_uri(hyperlink, 0));
1264
1265     // Build the result string, stripping the absolute URL paths if present.
1266     char* localURI = g_strstr_len(hyperlinkURI.get(), -1, "LayoutTests");
1267     String axURL = String::format("AXURL: %s", localURI ? localURI : hyperlinkURI.get());
1268     return JSStringCreateWithUTF8CString(axURL.utf8().data());
1269 }
1270
1271 bool AccessibilityUIElement::addNotificationListener(JSValueRef functionCallback)
1272 {
1273     if (!functionCallback)
1274         return false;
1275
1276     // Only one notification listener per element.
1277     if (m_notificationHandler)
1278         return false;
1279
1280     m_notificationHandler = AccessibilityNotificationHandler::create();
1281     m_notificationHandler->setPlatformElement(platformUIElement());
1282     m_notificationHandler->setNotificationFunctionCallback(functionCallback);
1283
1284     return true;
1285 }
1286
1287 bool AccessibilityUIElement::removeNotificationListener()
1288 {
1289     // Programmers should not be trying to remove a listener that's already removed.
1290     ASSERT(m_notificationHandler);
1291     m_notificationHandler = 0;
1292
1293     return true;
1294 }
1295
1296 bool AccessibilityUIElement::isFocusable() const
1297 {
1298     return checkElementState(m_element.get(), ATK_STATE_FOCUSABLE);
1299 }
1300
1301 bool AccessibilityUIElement::isSelectable() const
1302 {
1303     return checkElementState(m_element.get(), ATK_STATE_SELECTABLE);
1304 }
1305
1306 bool AccessibilityUIElement::isMultiSelectable() const
1307 {
1308     return checkElementState(m_element.get(), ATK_STATE_MULTISELECTABLE);
1309 }
1310
1311 bool AccessibilityUIElement::isVisible() const
1312 {
1313     return checkElementState(m_element.get(), ATK_STATE_VISIBLE);
1314 }
1315
1316 bool AccessibilityUIElement::isOffScreen() const
1317 {
1318     // FIXME: implement
1319     return false;
1320 }
1321
1322 bool AccessibilityUIElement::isCollapsed() const
1323 {
1324     // FIXME: implement
1325     return false;
1326 }
1327
1328 bool AccessibilityUIElement::isIgnored() const
1329 {
1330     // FIXME: implement
1331     return false;
1332 }
1333
1334 bool AccessibilityUIElement::hasPopup() const
1335 {
1336     if (!ATK_IS_OBJECT(m_element.get()))
1337         return false;
1338
1339     String hasPopupValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "haspopup");
1340     return equalIgnoringCase(hasPopupValue, "true");
1341 }
1342
1343 void AccessibilityUIElement::takeFocus()
1344 {
1345     // FIXME: implement
1346 }
1347
1348 void AccessibilityUIElement::takeSelection()
1349 {
1350     // FIXME: implement
1351 }
1352
1353 void AccessibilityUIElement::addSelection()
1354 {
1355     // FIXME: implement
1356 }
1357
1358 void AccessibilityUIElement::removeSelection()
1359 {
1360     // FIXME: implement
1361 }
1362
1363 // Text markers
1364 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1365 {
1366     // FIXME: implement
1367     return 0;
1368 }
1369
1370 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1371 {
1372     // FIXME: implement
1373     return 0;
1374 }
1375
1376 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1377 {
1378     // FIXME: implement
1379     return 0;
1380 }
1381
1382 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1383 {
1384     // FIXME: implement
1385     return 0;
1386 }
1387
1388 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1389 {
1390     // FIXME: implement
1391     return JSStringCreateWithCharacters(0, 0);
1392 }
1393
1394 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1395 {
1396     // FIXME: implement
1397     return 0;
1398 }
1399
1400 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1401 {
1402     // FIXME: implement
1403     return 0;
1404 }
1405
1406 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1407 {
1408     // FIXME: implement
1409     return 0;
1410 }
1411
1412 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForBounds(int x, int y, int width, int height)
1413 {
1414     // FIXME: implement
1415     return 0;
1416 }
1417
1418 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForBounds(int x, int y, int width, int height)
1419 {
1420     // FIXME: implement
1421     return 0;
1422 }
1423
1424 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForPoint(int x, int y)
1425 {
1426     // FIXME: implement
1427     return 0;
1428 }
1429
1430 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1431 {
1432     // FIXME: implement
1433     return 0;
1434 }
1435
1436 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
1437 {
1438     // FIXME: implement
1439     return false;
1440 }
1441
1442 int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
1443 {
1444     // FIXME: implement
1445     return -1;
1446 }
1447
1448 bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
1449 {
1450     // FIXME: implement
1451     return false;
1452 }
1453
1454 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int textIndex)
1455 {
1456     // FIXME: implement
1457     return 0;
1458 }
1459
1460 void AccessibilityUIElement::scrollToMakeVisible()
1461 {
1462     // FIXME: implement
1463 }
1464
1465 JSRetainPtr<JSStringRef> AccessibilityUIElement::supportedActions() const
1466 {
1467     // FIXME: implement
1468     return 0;
1469 }
1470
1471 JSRetainPtr<JSStringRef> AccessibilityUIElement::pathDescription() const
1472 {
1473     notImplemented();
1474     return 0;
1475 }
1476
1477 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPostscriptsDescription() const
1478 {
1479     notImplemented();
1480     return 0;
1481 }
1482
1483 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPrescriptsDescription() const
1484 {
1485     notImplemented();
1486     return 0;
1487 }
1488
1489 JSRetainPtr<JSStringRef> AccessibilityUIElement::classList() const
1490 {
1491     notImplemented();
1492     return 0;
1493 }
1494
1495 } // namespace WTR
1496
1497 #endif