[GTK] accessibility/svg-remote-element.html is failing
[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     // FIXME: implement
965     return false;
966 }
967
968 bool AccessibilityUIElement::isIncrementActionSupported()
969 {
970     // FIXME: implement
971     return false;
972 }
973
974 bool AccessibilityUIElement::isDecrementActionSupported()
975 {
976     // FIXME: implement
977     return false;
978 }
979
980 bool AccessibilityUIElement::isEnabled()
981 {
982     return checkElementState(m_element.get(), ATK_STATE_ENABLED);
983 }
984
985 bool AccessibilityUIElement::isRequired() const
986 {
987     return checkElementState(m_element.get(), ATK_STATE_REQUIRED);
988 }
989
990 bool AccessibilityUIElement::isFocused() const
991 {
992     return checkElementState(m_element.get(), ATK_STATE_FOCUSED);
993 }
994
995 bool AccessibilityUIElement::isSelected() const
996 {
997     return checkElementState(m_element.get(), ATK_STATE_SELECTED);
998 }
999
1000 bool AccessibilityUIElement::isExpanded() const
1001 {
1002     return checkElementState(m_element.get(), ATK_STATE_EXPANDED);
1003 }
1004
1005 bool AccessibilityUIElement::isChecked() const
1006 {
1007     return checkElementState(m_element.get(), ATK_STATE_CHECKED);
1008 }
1009
1010 int AccessibilityUIElement::hierarchicalLevel() const
1011 {
1012     // FIXME: implement
1013     return 0;
1014 }
1015
1016 JSRetainPtr<JSStringRef> AccessibilityUIElement::speak()
1017 {
1018     // FIXME: implement
1019     return JSStringCreateWithCharacters(0, 0);
1020 }
1021
1022 bool AccessibilityUIElement::ariaIsGrabbed() const
1023 {
1024     // FIXME: implement
1025     return false;
1026 }
1027
1028 JSRetainPtr<JSStringRef> AccessibilityUIElement::ariaDropEffects() const
1029 {
1030     // FIXME: implement
1031     return JSStringCreateWithCharacters(0, 0);
1032 }
1033
1034 // parameterized attributes
1035 int AccessibilityUIElement::lineForIndex(int index)
1036 {
1037     // FIXME: implement
1038     return 0;
1039 }
1040
1041 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForLine(int line)
1042 {
1043     // FIXME: implement
1044     return JSStringCreateWithCharacters(0, 0);
1045 }
1046
1047 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForPosition(int x, int y)
1048 {
1049     // FIXME: implement
1050     return JSStringCreateWithCharacters(0, 0);
1051 }
1052
1053 JSRetainPtr<JSStringRef> AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
1054 {
1055     // FIXME: implement
1056     return JSStringCreateWithCharacters(0, 0);
1057 }
1058
1059 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
1060 {
1061     // FIXME: implement
1062     return JSStringCreateWithCharacters(0, 0);
1063 }
1064
1065 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
1066 {
1067     // FIXME: implement
1068     return JSStringCreateWithCharacters(0, 0);
1069 }
1070
1071 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
1072 {
1073     // FIXME: implement
1074     return false;
1075 }
1076
1077 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly)
1078 {
1079     // FIXME: implement
1080     return 0;
1081 }
1082
1083 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
1084 {
1085     // FIXME: implement
1086     return JSStringCreateWithCharacters(0, 0);
1087 }
1088
1089 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRowHeaders()
1090 {
1091     // FIXME: implement
1092     return JSStringCreateWithCharacters(0, 0);
1093 }
1094
1095 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumns()
1096 {
1097     // FIXME: implement
1098     return JSStringCreateWithCharacters(0, 0);
1099 }
1100
1101 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRows()
1102 {
1103     // FIXME: implement
1104     return JSStringCreateWithCharacters(0, 0);
1105 }
1106
1107 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfVisibleCells()
1108 {
1109     // FIXME: implement
1110     return JSStringCreateWithCharacters(0, 0);
1111 }
1112
1113 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfHeader()
1114 {
1115     // FIXME: implement
1116     return JSStringCreateWithCharacters(0, 0);
1117 }
1118
1119 int AccessibilityUIElement::rowCount()
1120 {
1121     if (!ATK_IS_TABLE(m_element.get()))
1122         return 0;
1123
1124     return atk_table_get_n_rows(ATK_TABLE(m_element.get()));
1125 }
1126
1127 int AccessibilityUIElement::columnCount()
1128 {
1129     if (!ATK_IS_TABLE(m_element.get()))
1130         return 0;
1131
1132     return atk_table_get_n_columns(ATK_TABLE(m_element.get()));
1133 }
1134
1135 int AccessibilityUIElement::indexInTable()
1136 {
1137     // FIXME: implement
1138     return -1;
1139 }
1140
1141 JSRetainPtr<JSStringRef> AccessibilityUIElement::rowIndexRange()
1142 {
1143     // Range in table for rows.
1144     return indexRangeInTable(m_element.get(), true);
1145 }
1146
1147 JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange()
1148 {
1149     // Range in table for columns.
1150     return indexRangeInTable(m_element.get(), false);
1151 }
1152
1153 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1154 {
1155     if (!ATK_IS_TABLE(m_element.get()))
1156         return 0;
1157
1158     // Adopt the AtkObject representing the cell because
1159     // at_table_ref_at() transfers full ownership.
1160     GRefPtr<AtkObject> foundCell = adoptGRef(atk_table_ref_at(ATK_TABLE(m_element.get()), row, col));
1161     return foundCell ? AccessibilityUIElement::create(foundCell.get()) : 0;
1162 }
1163
1164 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::horizontalScrollbar() const
1165 {
1166     // FIXME: implement
1167     return 0;
1168 }
1169
1170 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::verticalScrollbar() const
1171 {
1172     // FIXME: implement
1173     return 0;
1174 }
1175
1176 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectedTextRange()
1177 {
1178     // FIXME: implement
1179     return JSStringCreateWithCharacters(0, 0);
1180 }
1181
1182 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1183 {
1184     // FIXME: implement
1185 }
1186
1187 void AccessibilityUIElement::increment()
1188 {
1189     alterCurrentValue(m_element.get(), 1);
1190 }
1191
1192 void AccessibilityUIElement::decrement()
1193 {
1194     alterCurrentValue(m_element.get(), -1);
1195 }
1196
1197 void AccessibilityUIElement::showMenu()
1198 {
1199     // FIXME: implement
1200 }
1201
1202 void AccessibilityUIElement::press()
1203 {
1204     if (!ATK_IS_ACTION(m_element.get()))
1205         return;
1206
1207     // Only one action per object is supported so far.
1208     atk_action_do_action(ATK_ACTION(m_element.get()), 0);
1209 }
1210
1211 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1212 {
1213     // FIXME: implement
1214 }
1215
1216 JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const
1217 {
1218     // FIXME: implement
1219     return JSStringCreateWithCharacters(0, 0);
1220 }
1221
1222 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentEncoding()
1223 {
1224     if (!ATK_IS_DOCUMENT(m_element.get()))
1225         return JSStringCreateWithCharacters(0, 0);
1226
1227     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get()));
1228     if (role != ATK_ROLE_DOCUMENT_FRAME)
1229         return JSStringCreateWithCharacters(0, 0);
1230
1231     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "Encoding"));
1232 }
1233
1234 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentURI()
1235 {
1236     if (!ATK_IS_DOCUMENT(m_element.get()))
1237         return JSStringCreateWithCharacters(0, 0);
1238
1239     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get()));
1240     if (role != ATK_ROLE_DOCUMENT_FRAME)
1241         return JSStringCreateWithCharacters(0, 0);
1242
1243     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "URI"));
1244 }
1245
1246 JSRetainPtr<JSStringRef> AccessibilityUIElement::url()
1247 {
1248     if (!ATK_IS_HYPERLINK_IMPL(m_element.get()))
1249         return JSStringCreateWithCharacters(0, 0);
1250
1251     AtkHyperlink* hyperlink = atk_hyperlink_impl_get_hyperlink(ATK_HYPERLINK_IMPL(m_element.get()));
1252     GOwnPtr<char> hyperlinkURI(atk_hyperlink_get_uri(hyperlink, 0));
1253
1254     // Build the result string, stripping the absolute URL paths if present.
1255     char* localURI = g_strstr_len(hyperlinkURI.get(), -1, "LayoutTests");
1256     String axURL = String::format("AXURL: %s", localURI ? localURI : hyperlinkURI.get());
1257     return JSStringCreateWithUTF8CString(axURL.utf8().data());
1258 }
1259
1260 bool AccessibilityUIElement::addNotificationListener(JSValueRef functionCallback)
1261 {
1262     if (!functionCallback)
1263         return false;
1264
1265     // Only one notification listener per element.
1266     if (m_notificationHandler)
1267         return false;
1268
1269     m_notificationHandler = AccessibilityNotificationHandler::create();
1270     m_notificationHandler->setPlatformElement(platformUIElement());
1271     m_notificationHandler->setNotificationFunctionCallback(functionCallback);
1272
1273     return true;
1274 }
1275
1276 bool AccessibilityUIElement::removeNotificationListener()
1277 {
1278     // Programmers should not be trying to remove a listener that's already removed.
1279     ASSERT(m_notificationHandler);
1280     m_notificationHandler = 0;
1281
1282     return true;
1283 }
1284
1285 bool AccessibilityUIElement::isFocusable() const
1286 {
1287     return checkElementState(m_element.get(), ATK_STATE_FOCUSABLE);
1288 }
1289
1290 bool AccessibilityUIElement::isSelectable() const
1291 {
1292     return checkElementState(m_element.get(), ATK_STATE_SELECTABLE);
1293 }
1294
1295 bool AccessibilityUIElement::isMultiSelectable() const
1296 {
1297     return checkElementState(m_element.get(), ATK_STATE_MULTISELECTABLE);
1298 }
1299
1300 bool AccessibilityUIElement::isVisible() const
1301 {
1302     return checkElementState(m_element.get(), ATK_STATE_VISIBLE);
1303 }
1304
1305 bool AccessibilityUIElement::isOffScreen() const
1306 {
1307     // FIXME: implement
1308     return false;
1309 }
1310
1311 bool AccessibilityUIElement::isCollapsed() const
1312 {
1313     // FIXME: implement
1314     return false;
1315 }
1316
1317 bool AccessibilityUIElement::isIgnored() const
1318 {
1319     // FIXME: implement
1320     return false;
1321 }
1322
1323 bool AccessibilityUIElement::hasPopup() const
1324 {
1325     if (!ATK_IS_OBJECT(m_element.get()))
1326         return false;
1327
1328     String hasPopupValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "haspopup");
1329     return equalIgnoringCase(hasPopupValue, "true");
1330 }
1331
1332 void AccessibilityUIElement::takeFocus()
1333 {
1334     // FIXME: implement
1335 }
1336
1337 void AccessibilityUIElement::takeSelection()
1338 {
1339     // FIXME: implement
1340 }
1341
1342 void AccessibilityUIElement::addSelection()
1343 {
1344     // FIXME: implement
1345 }
1346
1347 void AccessibilityUIElement::removeSelection()
1348 {
1349     // FIXME: implement
1350 }
1351
1352 // Text markers
1353 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1354 {
1355     // FIXME: implement
1356     return 0;
1357 }
1358
1359 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1360 {
1361     // FIXME: implement
1362     return 0;
1363 }
1364
1365 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1366 {
1367     // FIXME: implement
1368     return 0;
1369 }
1370
1371 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1372 {
1373     // FIXME: implement
1374     return 0;
1375 }
1376
1377 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1378 {
1379     // FIXME: implement
1380     return JSStringCreateWithCharacters(0, 0);
1381 }
1382
1383 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1384 {
1385     // FIXME: implement
1386     return 0;
1387 }
1388
1389 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1390 {
1391     // FIXME: implement
1392     return 0;
1393 }
1394
1395 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1396 {
1397     // FIXME: implement
1398     return 0;
1399 }
1400
1401 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForBounds(int x, int y, int width, int height)
1402 {
1403     // FIXME: implement
1404     return 0;
1405 }
1406
1407 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForBounds(int x, int y, int width, int height)
1408 {
1409     // FIXME: implement
1410     return 0;
1411 }
1412
1413 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForPoint(int x, int y)
1414 {
1415     // FIXME: implement
1416     return 0;
1417 }
1418
1419 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1420 {
1421     // FIXME: implement
1422     return 0;
1423 }
1424
1425 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
1426 {
1427     // FIXME: implement
1428     return false;
1429 }
1430
1431 int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
1432 {
1433     // FIXME: implement
1434     return -1;
1435 }
1436
1437 bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
1438 {
1439     // FIXME: implement
1440     return false;
1441 }
1442
1443 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int textIndex)
1444 {
1445     // FIXME: implement
1446     return 0;
1447 }
1448
1449 void AccessibilityUIElement::scrollToMakeVisible()
1450 {
1451     // FIXME: implement
1452 }
1453
1454 JSRetainPtr<JSStringRef> AccessibilityUIElement::supportedActions() const
1455 {
1456     // FIXME: implement
1457     return 0;
1458 }
1459
1460 JSRetainPtr<JSStringRef> AccessibilityUIElement::pathDescription() const
1461 {
1462     notImplemented();
1463     return 0;
1464 }
1465
1466 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPostscriptsDescription() const
1467 {
1468     notImplemented();
1469     return 0;
1470 }
1471
1472 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPrescriptsDescription() const
1473 {
1474     notImplemented();
1475     return 0;
1476 }
1477
1478 JSRetainPtr<JSStringRef> AccessibilityUIElement::classList() const
1479 {
1480     notImplemented();
1481     return 0;
1482 }
1483
1484 } // namespace WTR
1485
1486 #endif