Changeset 156835 in webkit


Ignore:
Timestamp:
Oct 3, 2013 8:21:21 AM (11 years ago)
Author:
mario@webkit.org
Message:

[ATK] Expose aria-invalid as a text attribute (not object attribute)
https://bugs.webkit.org/show_bug.cgi?id=122015

Reviewed by Chris Fleizach.

Source/WebCore:

Expose the aria-invalid attribute correctly through a text
attribute (through the AtkText interface) instead of using an
object, according to what the WAI-ARIA specs says.
http://www.w3.org/TR/wai-aria-implementation/#mapping_state-property

This will be tested by accesibility/aria-invalid.html, which should
keep passing after thanks to the changes done in the DRT and WKTR.

  • accessibility/AccessibilityObject.cpp:

(WebCore::AccessibilityObject::invalidStatus): Update this method
to only return values recognized by the WAI-ARIA specification.

  • accessibility/atk/WebKitAccessibleInterfaceText.cpp:

(getAttributeSetForAccessibilityObject): Expose aria-invalid as a
custom text attribute 'invalid', following the lead of Firefox.
Also register that custom attribute as a AtkTextAttribute.

  • accessibility/atk/WebKitAccessibleWrapperAtk.cpp:

(webkitAccessibleGetAttributes): Remove exposure of aria-invalid
as an object attribute from here.

Tools:

Adapted DRT and WKTR to check the exposure of the aria-invalid
attribute as a text attribute, instead of an object attribute.

Also, done some refactoring of the code to try to keep things
simpler and more coherent, by defining new helper functions,
simplifying code, moving static variables and functions into
unnammed namespaces and so on, without altering the logic other
than for checking the text attribute for aria-invalid.

  • DumpRenderTree/atk/AccessibilityUIElementAtk.cpp:

(coreAttributeToAtkAttribute): Consider 'invalid' as the name of
the attribute exposed by the ATK wrapper, not 'aria-invalid'.
Also, never return an empty string if not falling through any of
the cases checked here, and return the original attribute instead.
(atkAttributeValueToCoreAttributeValue): New helper function to
match the attributes values returned by the ATK wrapper with the
values expected by the layout tests. Moved the mappings for the
values of AXSortDirection here as well.
(getAttributeSet): New helper function to retrieve a list of
attributes (an AtkAttributeSet) from an AtkObject using the right
API depending on whether we want the object attributes or the text
attributes (in case the object implements AtkText).
(getAttributeSetValueForId): Simplified by using getAttributeSet
and atkAttributeValueToCoreAttributeValue. Also, added a new
parameter to indicater whether we are interested in object
attributes or text attributes.
(getAtkAttributeSetAsString): Ditto.
(attributesOfElement): Updated to pass the new required parameter
to getAtkAttributeSetAsString, indicating that we want the object
attributes in this case, for backwards compatibility.
(indexRangeInTable): Moved up in the file into the unnammed namespace.
(alterCurrentValue): Ditto.
(AccessibilityUIElement::stringAttributeValue): After moving most
of the code here to the new helper functions, simplified it by
just checking whether the required attribute is provided as an
object attribute or, if that's not the case, as a text attribute.
(AccessibilityUIElement::isAttributeSupported): Ditto.
(AccessibilityUIElement::intValue): Updated to pass the new
required parameter to getAttributeSetValueForId, indicating that
we want the object attributes in this case.
(AccessibilityUIElement::hasPopup): Ditto.

  • WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp:

(WTR::coreAttributeToAtkAttribute): Same changes than for DRT.
(WTR::atkAttributeValueToCoreAttributeValue): Ditto.
(WTR::getAttributeSet): Ditto.
(WTR::getAttributeSetValueForId): Ditto.
(WTR::getAtkAttributeSetAsString): Ditto.
(WTR::attributesOfElement): Ditto.
(WTR::AccessibilityUIElement::stringAttributeValue): Ditto.
(WTR::AccessibilityUIElement::isAttributeSupported): Ditto.
(WTR::AccessibilityUIElement::intValue): Ditto.
(WTR::AccessibilityUIElement::hasPopup): Ditto.

LayoutTests:

Updated the aria-invalid.html layout test to make sure that it
behaves as defined by the WAI-ARIA specification for values other
than 'false', 'true', 'grammar' and 'spelling'.

  • accessibility/aria-invalid.html: Updated test.
  • accessibility/aria-invalid-expected.txt: Updated expectations.
Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r156832 r156835  
     12013-10-02  Mario Sanchez Prada  <mario.prada@samsung.com>
     2
     3        [ATK] Expose aria-invalid as a text attribute (not object attribute)
     4        https://bugs.webkit.org/show_bug.cgi?id=122015
     5
     6        Reviewed by Chris Fleizach.
     7
     8        Updated the aria-invalid.html layout test to make sure that it
     9        behaves as defined by the WAI-ARIA specification for values other
     10        than 'false', 'true', 'grammar' and 'spelling'.
     11
     12        * accessibility/aria-invalid.html: Updated test.
     13        * accessibility/aria-invalid-expected.txt: Updated expectations.
     14
    1152013-10-03  Ryosuke Niwa  <rniwa@webkit.org>
    216
  • trunk/LayoutTests/accessibility/aria-invalid-expected.txt

    r108373 r156835  
    1    
     1      
    22This tests that aria-invalid causes the right attribute to be returned and it ensures a notification is sent when it changes.
    33
     
    77PASS accessibilityController.focusedElement.stringAttributeValue('AXInvalid') is 'true'
    88PASS accessibilityController.focusedElement.stringAttributeValue('AXInvalid') is 'grammar'
     9PASS accessibilityController.focusedElement.stringAttributeValue('AXInvalid') is 'spelling'
     10PASS accessibilityController.focusedElement.stringAttributeValue('AXInvalid') is 'true'
     11PASS accessibilityController.focusedElement.stringAttributeValue('AXInvalid') is 'false'
    912PASS accessibilityController.focusedElement.stringAttributeValue('AXInvalid') is 'false'
    1013PASS accessibilityController.focusedElement.stringAttributeValue('AXInvalid') is 'false'
  • trunk/LayoutTests/accessibility/aria-invalid.html

    r155274 r156835  
    99<input type="text" id="text1" aria-invalid="true">
    1010<input type="text" id="text2" aria-invalid="grammar">
    11 <input type="text" id="text3" aria-invalid="">
    12 <input type="text" id="text4">
     11<input type="text" id="text3" aria-invalid="spelling">
     12<input type="text" id="text4" aria-invalid="notallowed">
     13<input type="text" id="text5" aria-invalid="false">
     14<input type="text" id="text6" aria-invalid="">
     15<input type="text" id="text7">
    1316
    1417<p id="description"></p>
     
    3942
    4043        document.getElementById("text3").focus();
     44        shouldBe("accessibilityController.focusedElement.stringAttributeValue('AXInvalid')", "'spelling'");
     45
     46        document.getElementById("text4").focus();
     47        shouldBe("accessibilityController.focusedElement.stringAttributeValue('AXInvalid')", "'true'");
     48
     49        document.getElementById("text5").focus();
    4150        shouldBe("accessibilityController.focusedElement.stringAttributeValue('AXInvalid')", "'false'");
    4251
    43         document.getElementById("text4").focus();
     52        document.getElementById("text6").focus();
     53        shouldBe("accessibilityController.focusedElement.stringAttributeValue('AXInvalid')", "'false'");
     54
     55        document.getElementById("text7").focus();
    4456        shouldBe("accessibilityController.focusedElement.stringAttributeValue('AXInvalid')", "'false'");
    4557
     
    4860        shouldBeTrue("addedNotification");
    4961
    50         document.getElementById("text4").setAttribute("aria-invalid", "spelling");
     62        document.getElementById("text7").setAttribute("aria-invalid", "spelling");
    5163    }
    5264
  • trunk/Source/WebCore/ChangeLog

    r156831 r156835  
     12013-10-02  Mario Sanchez Prada  <mario.prada@samsung.com>
     2
     3        [ATK] Expose aria-invalid as a text attribute (not object attribute)
     4        https://bugs.webkit.org/show_bug.cgi?id=122015
     5
     6        Reviewed by Chris Fleizach.
     7
     8        Expose the aria-invalid attribute correctly through a text
     9        attribute (through the AtkText interface) instead of using an
     10        object, according to what the WAI-ARIA specs says.
     11        http://www.w3.org/TR/wai-aria-implementation/#mapping_state-property
     12
     13        This will be tested by accesibility/aria-invalid.html, which should
     14        keep passing after thanks to the changes done in the DRT and WKTR.
     15
     16        * accessibility/AccessibilityObject.cpp:
     17        (WebCore::AccessibilityObject::invalidStatus): Update this method
     18        to only return values recognized by the WAI-ARIA specification.
     19
     20        * accessibility/atk/WebKitAccessibleInterfaceText.cpp:
     21        (getAttributeSetForAccessibilityObject): Expose aria-invalid as a
     22        custom text attribute 'invalid', following the lead of Firefox.
     23        Also register that custom attribute as a AtkTextAttribute.
     24        * accessibility/atk/WebKitAccessibleWrapperAtk.cpp:
     25        (webkitAccessibleGetAttributes): Remove exposure of aria-invalid
     26        as an object attribute from here.
     27
    1282013-10-03  Zan Dobersek  <zdobersek@igalia.com>
    229
  • trunk/Source/WebCore/accessibility/AccessibilityObject.cpp

    r156409 r156835  
    13441344{
    13451345    DEFINE_STATIC_LOCAL(const AtomicString, invalidStatusFalse, ("false", AtomicString::ConstructFromLiteral));
     1346    DEFINE_STATIC_LOCAL(const AtomicString, invalidStatusTrue, ("true", AtomicString::ConstructFromLiteral));
    13461347   
    13471348    // aria-invalid can return false (default), grammer, spelling, or true.
    13481349    const AtomicString& ariaInvalid = getAttribute(aria_invalidAttr);
    13491350   
    1350     // If empty or not present, it should return false.
    1351     if (ariaInvalid.isEmpty())
     1351    // If 'false', empty or not present, it should return false.
     1352    if (ariaInvalid.isEmpty() || equalIgnoringCase(ariaInvalid, invalidStatusFalse))
    13521353        return invalidStatusFalse;
    13531354   
    1354     return ariaInvalid;
     1355    // Only 'true', 'grammar' and 'spelling' are values recognised by the WAI-ARIA
     1356    // specification. Any other non empty string should be treated as 'true'.
     1357    if (equalIgnoringCase(ariaInvalid, "spelling") || equalIgnoringCase(ariaInvalid, "grammar"))
     1358        return ariaInvalid;
     1359    return invalidStatusTrue;
    13551360}
    13561361 
  • trunk/Source/WebCore/accessibility/atk/WebKitAccessibleInterfaceText.cpp

    r156532 r156835  
    5757using namespace WebCore;
    5858
     59// Text attribute to expose the ARIA 'aria-invalid' attribute. Initially initialized
     60// to ATK_TEXT_ATTR_INVALID (which means 'invalid' text attribute'), will later on
     61// hold a reference to the custom registered AtkTextAttribute that we will use.
     62static AtkTextAttribute atkTextAttributeInvalid = ATK_TEXT_ATTR_INVALID;
     63
    5964static AccessibilityObject* core(AtkText* text)
    6065{
     
    294299    if (!language.isEmpty())
    295300        result = addToAtkAttributeSet(result, atk_text_attribute_get_name(ATK_TEXT_ATTR_LANGUAGE), language.utf8().data());
     301
     302    String invalidStatus = object->invalidStatus().string();
     303    if (invalidStatus != "false") {
     304        // Register the custom attribute for 'aria-invalid' if not done yet.
     305        if (atkTextAttributeInvalid == ATK_TEXT_ATTR_INVALID)
     306            atkTextAttributeInvalid = atk_text_attribute_register("invalid");
     307
     308        result = addToAtkAttributeSet(result, atk_text_attribute_get_name(atkTextAttributeInvalid), invalidStatus.utf8().data());
     309    }
    296310
    297311    return result;
  • trunk/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp

    r156532 r156835  
    505505    if (coreObject->ariaHasPopup())
    506506        attributeSet = addToAtkAttributeSet(attributeSet, "haspopup", "true");
    507 
    508     String invalidStatus = coreObject->invalidStatus().string();
    509     if (!invalidStatus.isEmpty() && invalidStatus != "false")
    510         attributeSet = addToAtkAttributeSet(attributeSet, "aria-invalid", coreObject->invalidStatus().string().utf8().data());
    511507
    512508    AccessibilitySortDirection sortDirection = coreObject->sortDirection();
  • trunk/Tools/ChangeLog

    r156803 r156835  
     12013-10-02  Mario Sanchez Prada  <mario.prada@samsung.com>
     2
     3        [ATK] Expose aria-invalid as a text attribute (not object attribute)
     4        https://bugs.webkit.org/show_bug.cgi?id=122015
     5
     6        Reviewed by Chris Fleizach.
     7
     8        Adapted DRT and WKTR to check the exposure of the aria-invalid
     9        attribute as a text attribute, instead of an object attribute.
     10
     11        Also, done some refactoring of the code to try to keep things
     12        simpler and more coherent, by defining new helper functions,
     13        simplifying code, moving static variables and functions into
     14        unnammed namespaces and so on, without altering the logic other
     15        than for checking the text attribute for aria-invalid.
     16
     17        * DumpRenderTree/atk/AccessibilityUIElementAtk.cpp:
     18        (coreAttributeToAtkAttribute): Consider 'invalid' as the name of
     19        the attribute exposed by the ATK wrapper, not 'aria-invalid'.
     20        Also, never return an empty string if not falling through any of
     21        the cases checked here, and return the original attribute instead.
     22        (atkAttributeValueToCoreAttributeValue): New helper function to
     23        match the attributes values returned by the ATK wrapper with the
     24        values expected by the layout tests. Moved the mappings for the
     25        values of AXSortDirection here as well.
     26        (getAttributeSet): New helper function to retrieve a list of
     27        attributes (an AtkAttributeSet) from an AtkObject using the right
     28        API depending on whether we want the object attributes or the text
     29        attributes (in case the object implements AtkText).
     30        (getAttributeSetValueForId): Simplified by using getAttributeSet
     31        and atkAttributeValueToCoreAttributeValue. Also, added a new
     32        parameter to indicater whether we are interested in object
     33        attributes or text attributes.
     34        (getAtkAttributeSetAsString): Ditto.
     35        (attributesOfElement): Updated to pass the new required parameter
     36        to getAtkAttributeSetAsString, indicating that we want the object
     37        attributes in this case, for backwards compatibility.
     38        (indexRangeInTable): Moved up in the file into the unnammed namespace.
     39        (alterCurrentValue): Ditto.
     40        (AccessibilityUIElement::stringAttributeValue): After moving most
     41        of the code here to the new helper functions, simplified it by
     42        just checking whether the required attribute is provided as an
     43        object attribute or, if that's not the case, as a text attribute.
     44        (AccessibilityUIElement::isAttributeSupported): Ditto.
     45        (AccessibilityUIElement::intValue): Updated to pass the new
     46        required parameter to getAttributeSetValueForId, indicating that
     47        we want the object attributes in this case.
     48        (AccessibilityUIElement::hasPopup): Ditto.
     49
     50        * WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp:
     51        (WTR::coreAttributeToAtkAttribute): Same changes than for DRT.
     52        (WTR::atkAttributeValueToCoreAttributeValue): Ditto.
     53        (WTR::getAttributeSet): Ditto.
     54        (WTR::getAttributeSetValueForId): Ditto.
     55        (WTR::getAtkAttributeSetAsString): Ditto.
     56        (WTR::attributesOfElement): Ditto.
     57        (WTR::AccessibilityUIElement::stringAttributeValue): Ditto.
     58        (WTR::AccessibilityUIElement::isAttributeSupported): Ditto.
     59        (WTR::AccessibilityUIElement::intValue): Ditto.
     60        (WTR::AccessibilityUIElement::hasPopup): Ditto.
     61
    1622013-10-02  Ryosuke Niwa  <rniwa@webkit.org>
    263
  • trunk/Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp

    r156551 r156835  
    22 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
    33 * Copyright (C) 2009 Jan Michael Alonzo
     4 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    4243#include <wtf/unicode/CharacterNames.h>
    4344
    44 static String coreAttributeToAtkAttribute(JSStringRef attribute)
     45namespace {
     46
     47enum AtkAttributeType {
     48    ObjectAttributeType,
     49    TextAttributeType
     50};
     51
     52enum AttributeDomain {
     53    CoreDomain = 0,
     54    AtkDomain
     55};
     56
     57enum AttributesIndex {
     58    // Attribute names.
     59    InvalidNameIndex = 0,
     60    PlaceholderNameIndex,
     61    SortNameIndex,
     62
     63    // Attribute values.
     64    SortAscendingValueIndex,
     65    SortDescendingValueIndex,
     66    SortUnknownValueIndex,
     67
     68    NumberOfAttributes
     69};
     70
     71// Attribute names & Values (keep on sync with enum AttributesIndex).
     72const String attributesMap[][2] = {
     73    // Attribute names.
     74    { "AXInvalid", "invalid" },
     75    { "AXPlaceholderValue", "placeholder-text" } ,
     76    { "AXSortDirection", "sort" },
     77
     78    // Attribute values.
     79    { "AXAscendingSortDirection", "ascending" },
     80    { "AXDescendingSortDirection", "descending" },
     81    { "AXUnknownSortDirection", "unknown" }
     82};
     83
     84String coreAttributeToAtkAttribute(JSStringRef attribute)
    4585{
    4686    size_t bufferSize = JSStringGetMaximumUTF8CStringSize(attribute);
     
    4989
    5090    String attributeString = String::fromUTF8(buffer.get());
    51     if (attributeString == "AXInvalid")
    52         return "aria-invalid";
    53 
    54     if (attributeString == "AXPlaceholderValue")
    55         return "placeholder-text";
    56 
    57     if (attributeString == "AXSortDirection")
    58         return "sort";
    59 
    60     return String();
    61 }
    62 
    63 static String getAttributeSetValueForId(AtkObject* accessible, const char* id)
    64 {
    65     const char* attributeValue = 0;
    66     AtkAttributeSet* attributeSet = atk_object_get_attributes(accessible);
     91    for (int i = 0; i < NumberOfAttributes; ++i) {
     92        if (attributesMap[i][CoreDomain] == attributeString)
     93            return attributesMap[i][AtkDomain];
     94    }
     95
     96    return attributeString;
     97}
     98
     99String atkAttributeValueToCoreAttributeValue(AtkAttributeType type, const String& id, const String& value)
     100{
     101    if (type == ObjectAttributeType) {
     102        // We need to translate ATK values exposed for 'aria-sort' (e.g. 'ascending')
     103        // into those expected by the layout tests (e.g. 'AXAscendingSortDirection').
     104        if (id == attributesMap[SortNameIndex][AtkDomain] && !value.isEmpty()) {
     105            if (value == attributesMap[SortAscendingValueIndex][AtkDomain])
     106                return attributesMap[SortAscendingValueIndex][CoreDomain];
     107            if (value == attributesMap[SortDescendingValueIndex][AtkDomain])
     108                return attributesMap[SortDescendingValueIndex][CoreDomain];
     109
     110            return attributesMap[SortUnknownValueIndex][CoreDomain];
     111        }
     112    } else if (type == TextAttributeType) {
     113        // In case of 'aria-invalid' when the attribute empty or has "false" for ATK
     114        // it should not be mapped at all, but layout tests will expect 'false'.
     115        if (id == attributesMap[InvalidNameIndex][AtkDomain] && value.isEmpty())
     116            return "false";
     117    }
     118
     119    return value;
     120}
     121
     122AtkAttributeSet* getAttributeSet(AtkObject* accessible, AtkAttributeType type)
     123{
     124    if (type == ObjectAttributeType)
     125        return atk_object_get_attributes(accessible);
     126
     127    if (type == TextAttributeType) {
     128        if (!ATK_IS_TEXT(accessible))
     129            return 0;
     130
     131        return atk_text_get_default_attributes(ATK_TEXT(accessible));
     132    }
     133
     134    ASSERT_NOT_REACHED();
     135    return 0;
     136}
     137
     138String getAttributeSetValueForId(AtkObject* accessible, AtkAttributeType type, String id)
     139{
     140    AtkAttributeSet* attributeSet = getAttributeSet(accessible, type);
     141    if (!attributeSet)
     142        return String();
     143
     144    String attributeValue;
    67145    for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
    68146        AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(attributes->data);
    69         if (!strcmp(atkAttribute->name, id)) {
    70             attributeValue = atkAttribute->value;
     147        if (id == atkAttribute->name) {
     148            attributeValue = String::fromUTF8(atkAttribute->value);
    71149            break;
    72150        }
    73151    }
    74 
    75     String atkAttributeValue = String::fromUTF8(attributeValue);
    76152    atk_attribute_set_free(attributeSet);
    77153
    78     return atkAttributeValue;
    79 }
    80 
    81 static String getAtkAttributeSetAsString(AtkObject* accessible)
    82 {
     154    return atkAttributeValueToCoreAttributeValue(type, id, attributeValue);
     155}
     156
     157String getAtkAttributeSetAsString(AtkObject* accessible, AtkAttributeType type)
     158{
     159    AtkAttributeSet* attributeSet = getAttributeSet(accessible, type);
     160    if (!attributeSet)
     161        return String();
     162
    83163    StringBuilder builder;
    84 
    85     AtkAttributeSet* attributeSet = atk_object_get_attributes(accessible);
    86164    for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
    87165        AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
     
    96174}
    97175
    98 static inline const char* roleToString(AtkRole role)
     176inline const char* roleToString(AtkRole role)
    99177{
    100178    switch (role) {
     
    210288}
    211289
    212 static inline gchar* replaceCharactersForResults(gchar* str)
     290inline gchar* replaceCharactersForResults(gchar* str)
    213291{
    214292    String uString = String::fromUTF8(str);
     
    226304}
    227305
    228 static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
     306bool checkElementState(PlatformUIElement element, AtkStateType stateType)
    229307{
    230308    if (!ATK_IS_OBJECT(element))
     
    235313}
    236314
    237 static String attributesOfElement(AccessibilityUIElement* element)
     315String attributesOfElement(AccessibilityUIElement* element)
    238316{
    239317    StringBuilder builder;
     
    281359    // We append the ATK specific attributes as a single line at the end.
    282360    builder.append("AXPlatformAttributes: ");
    283     builder.append(getAtkAttributeSetAsString(element->platformUIElement()));
     361    builder.append(getAtkAttributeSetAsString(element->platformUIElement(), ObjectAttributeType));
    284362
    285363    return builder.toString();
    286364}
    287365
    288 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
    289     : m_element(element)
    290 {
    291     if (m_element)
    292         g_object_ref(m_element);
    293 }
    294 
    295 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
    296     : m_element(other.m_element)
    297 {
    298     if (m_element)
    299         g_object_ref(m_element);
    300 }
    301 
    302 AccessibilityUIElement::~AccessibilityUIElement()
    303 {
    304     if (m_element)
    305         g_object_unref(m_element);
    306 }
    307 
    308 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elements)
    309 {
    310     // FIXME: implement
    311 }
    312 
    313 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
    314 {
    315     // FIXME: implement
    316 }
    317 
    318 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
    319 {
    320     if (!ATK_IS_OBJECT(m_element))
    321         return;
    322 
    323     int count = childrenCount();
    324     for (int i = 0; i < count; i++) {
    325         AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
    326         children.append(AccessibilityUIElement(child));
    327     }
    328 }
    329 
    330 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned start, unsigned end)
    331 {
    332     if (!ATK_IS_OBJECT(m_element))
    333         return;
    334 
    335     for (unsigned i = start; i < end; i++) {
    336         AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
    337         elementVector.append(AccessibilityUIElement(child));
    338     }
    339 }
    340 
    341 int AccessibilityUIElement::rowCount()
    342 {
    343     if (!ATK_IS_TABLE(m_element))
    344         return 0;
    345 
    346     return atk_table_get_n_rows(ATK_TABLE(m_element));
    347 }
    348 
    349 int AccessibilityUIElement::columnCount()
    350 {
    351     if (!ATK_IS_TABLE(m_element))
    352         return 0;
    353 
    354     return atk_table_get_n_columns(ATK_TABLE(m_element));
    355 }
    356 
    357 int AccessibilityUIElement::childrenCount()
    358 {
    359     if (!ATK_IS_OBJECT(m_element))
    360         return 0;
    361 
    362     return atk_object_get_n_accessible_children(ATK_OBJECT(m_element));
    363 }
    364 
    365 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
    366 {
    367     if (!ATK_IS_COMPONENT(m_element))
    368         return 0;
    369 
    370     return AccessibilityUIElement(atk_component_ref_accessible_at_point(ATK_COMPONENT(m_element), x, y, ATK_XY_WINDOW));
    371 }
    372 
    373 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
    374 {
    375     // FIXME: implement
    376     return 0;
    377 }
    378 
    379 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
    380 {
    381     if (!ATK_IS_OBJECT(m_element))
    382         return 0;
    383 
    384     Vector<AccessibilityUIElement> children;
    385     getChildrenWithRange(children, index, index + 1);
    386 
    387     if (children.size() == 1)
    388         return children.at(0);
    389 
    390     return 0;
    391 }
    392 
    393 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
    394 {
    395     // FIXME: implement
    396     return 0;
    397 }
    398 
    399 JSStringRef AccessibilityUIElement::allAttributes()
    400 {
    401     if (!ATK_IS_OBJECT(m_element))
    402         return JSStringCreateWithCharacters(0, 0);
    403 
    404     return JSStringCreateWithUTF8CString(attributesOfElement(this).utf8().data());
    405 }
    406 
    407 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
    408 {
    409     // FIXME: implement
    410     return JSStringCreateWithCharacters(0, 0);
    411 }
    412 
    413 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
    414 {
    415     // FIXME: implement
    416     return JSStringCreateWithCharacters(0, 0);
    417 }
    418 
    419 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
    420 {
    421     if (!ATK_IS_OBJECT(m_element))
    422         return 0;
    423 
    424     AtkRelationSet* set = atk_object_ref_relation_set(ATK_OBJECT(m_element));
    425     if (!set)
    426         return 0;
    427 
    428     AtkObject* target = 0;
    429     int count = atk_relation_set_get_n_relations(set);
    430     for (int i = 0; i < count; i++) {
    431         AtkRelation* relation = atk_relation_set_get_relation(set, i);
    432         if (atk_relation_get_relation_type(relation) == ATK_RELATION_LABELLED_BY) {
    433             GPtrArray* targetList = atk_relation_get_target(relation);
    434             if (targetList->len)
    435                 target = static_cast<AtkObject*>(g_ptr_array_index(targetList, 0));
    436         }
    437     }
    438 
    439     g_object_unref(set);
    440     return target ? AccessibilityUIElement(target) : 0;
    441 }
    442 
    443 AccessibilityUIElement AccessibilityUIElement::parentElement()
    444 {
    445     if (!ATK_IS_OBJECT(m_element))
    446         return 0;
    447 
    448     AtkObject* parent =  atk_object_get_parent(ATK_OBJECT(m_element));
    449     return parent ? AccessibilityUIElement(parent) : 0;
    450 }
    451 
    452 JSStringRef AccessibilityUIElement::attributesOfChildren()
    453 {
    454     if (!ATK_IS_OBJECT(m_element))
    455         return JSStringCreateWithCharacters(0, 0);
    456 
    457     Vector<AccessibilityUIElement> children;
    458     getChildren(children);
    459 
    460     StringBuilder builder;
    461     for (Vector<AccessibilityUIElement>::iterator it = children.begin(); it != children.end(); ++it) {
    462         builder.append(attributesOfElement(it));
    463         builder.append("\n------------\n");
    464     }
    465 
    466     return JSStringCreateWithUTF8CString(builder.toString().utf8().data());
    467 }
    468 
    469 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
    470 {
    471     // FIXME: implement
    472     return JSStringCreateWithCharacters(0, 0);
    473 }
    474 
    475 JSStringRef AccessibilityUIElement::role()
    476 {
    477     if (!ATK_IS_OBJECT(m_element))
    478         return JSStringCreateWithCharacters(0, 0);
    479 
    480     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
    481     if (!role)
    482         return JSStringCreateWithCharacters(0, 0);
    483 
    484     GOwnPtr<char> roleStringWithPrefix(g_strdup_printf("AXRole: %s", roleToString(role)));
    485     return JSStringCreateWithUTF8CString(roleStringWithPrefix.get());
    486 }
    487 
    488 JSStringRef AccessibilityUIElement::subrole()
    489 {
    490     return 0;
    491 }
    492 
    493 JSStringRef AccessibilityUIElement::roleDescription()
    494 {
    495     return 0;
    496 }
    497 
    498 JSStringRef AccessibilityUIElement::title()
    499 {
    500     if (!ATK_IS_OBJECT(m_element))
    501         return JSStringCreateWithCharacters(0, 0);
    502 
    503     const gchar* name = atk_object_get_name(ATK_OBJECT(m_element));
    504     GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name ? name : ""));
    505 
    506     return JSStringCreateWithUTF8CString(axTitle.get());
    507 }
    508 
    509 JSStringRef AccessibilityUIElement::description()
    510 {
    511     if (!ATK_IS_OBJECT(m_element))
    512         return JSStringCreateWithCharacters(0, 0);
    513 
    514     const gchar* description = atk_object_get_description(ATK_OBJECT(m_element));
    515     if (!description)
    516         return JSStringCreateWithCharacters(0, 0);
    517 
    518     GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
    519 
    520     return JSStringCreateWithUTF8CString(axDesc.get());
    521 }
    522 
    523 JSStringRef AccessibilityUIElement::stringValue()
    524 {
    525     if (!ATK_IS_TEXT(m_element))
    526         return JSStringCreateWithCharacters(0, 0);
    527 
    528     GOwnPtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element), 0, -1));
    529     GOwnPtr<gchar> textWithReplacedCharacters(replaceCharactersForResults(text.get()));
    530     GOwnPtr<gchar> axValue(g_strdup_printf("AXValue: %s", textWithReplacedCharacters.get()));
    531 
    532     return JSStringCreateWithUTF8CString(axValue.get());
    533 }
    534 
    535 JSStringRef AccessibilityUIElement::language()
    536 {
    537     if (!ATK_IS_OBJECT(m_element))
    538         return JSStringCreateWithCharacters(0, 0);
    539 
    540     const gchar* locale = atk_object_get_object_locale(ATK_OBJECT(m_element));
    541     if (!locale)
    542         return JSStringCreateWithCharacters(0, 0);
    543 
    544     GOwnPtr<char> axValue(g_strdup_printf("AXLanguage: %s", locale));
    545     return JSStringCreateWithUTF8CString(axValue.get());
    546 }
    547 
    548 JSStringRef AccessibilityUIElement::helpText() const
    549 {
    550     // FIXME: We need to provide a proper implementation for this that does
    551     // not depend on Mac specific concepts such as ATK_RELATION_DESCRIBED_BY,
    552     // once it's implemented (see http://webkit.org/b/121684).
    553     return JSStringCreateWithCharacters(0, 0);
    554 }
    555 
    556 double AccessibilityUIElement::x()
    557 {
    558     if (!ATK_IS_COMPONENT(m_element))
    559         return 0;
    560 
    561     int x, y;
    562     atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
    563 
    564     return x;
    565 }
    566 
    567 double AccessibilityUIElement::y()
    568 {
    569     if (!ATK_IS_COMPONENT(m_element))
    570         return 0;
    571 
    572     int x, y;
    573     atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
    574 
    575     return y;
    576 }
    577 
    578 double AccessibilityUIElement::width()
    579 {
    580     if (!ATK_IS_COMPONENT(m_element))
    581         return 0;
    582 
    583     int width, height;
    584     atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
    585 
    586     return width;
    587 }
    588 
    589 double AccessibilityUIElement::height()
    590 {
    591     if (!ATK_IS_COMPONENT(m_element))
    592         return 0;
    593 
    594     int width, height;
    595     atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
    596 
    597     return height;
    598 }
    599 
    600 double AccessibilityUIElement::clickPointX()
    601 {
    602     // Note: This is not something we have in ATK.
    603     return 0;
    604 }
    605 
    606 double AccessibilityUIElement::clickPointY()
    607 {
    608     // Note: This is not something we have in ATK.
    609     return 0;
    610 }
    611 
    612 JSStringRef AccessibilityUIElement::orientation() const
    613 {
    614     if (!ATK_IS_OBJECT(m_element))
    615         return JSStringCreateWithCharacters(0, 0);
    616 
    617     const char* axOrientation = 0;
    618     if (checkElementState(m_element, ATK_STATE_HORIZONTAL))
    619         axOrientation = "AXOrientation: AXHorizontalOrientation";
    620     else if (checkElementState(m_element, ATK_STATE_VERTICAL))
    621         axOrientation = "AXOrientation: AXVerticalOrientation";
    622 
    623     if (!axOrientation)
    624         return JSStringCreateWithCharacters(0, 0);
    625 
    626     return JSStringCreateWithUTF8CString(axOrientation);
    627 }
    628 
    629 double AccessibilityUIElement::intValue() const
    630 {
    631     if (!ATK_IS_OBJECT(m_element))
    632         return 0;
    633 
    634     if (ATK_IS_VALUE(m_element)) {
    635         GValue value = G_VALUE_INIT;
    636         atk_value_get_current_value(ATK_VALUE(m_element), &value);
    637         if (!G_VALUE_HOLDS_FLOAT(&value))
    638             return 0;
    639         return g_value_get_float(&value);
    640     }
    641 
    642     // Consider headings as an special case when returning the "int value" of
    643     // an AccessibilityUIElement, so we can reuse some tests to check the level
    644     // both for HTML headings and objects with the aria-level attribute.
    645     if (atk_object_get_role(ATK_OBJECT(m_element)) == ATK_ROLE_HEADING) {
    646         String headingLevel = getAttributeSetValueForId(ATK_OBJECT(m_element), "level");
    647         bool ok;
    648         double headingLevelValue = headingLevel.toDouble(&ok);
    649         if (ok)
    650             return headingLevelValue;
    651     }
    652 
    653     return 0;
    654 }
    655 
    656 double AccessibilityUIElement::minValue()
    657 {
    658     if (!ATK_IS_VALUE(m_element))
    659         return 0;
    660 
    661     GValue value = G_VALUE_INIT;
    662     atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
    663     if (!G_VALUE_HOLDS_FLOAT(&value))
    664         return 0;
    665     return g_value_get_float(&value);
    666 }
    667 
    668 double AccessibilityUIElement::maxValue()
    669 {
    670     if (!ATK_IS_VALUE(m_element))
    671         return 0;
    672 
    673     GValue value = G_VALUE_INIT;
    674     atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
    675     if (!G_VALUE_HOLDS_FLOAT(&value))
    676         return 0;
    677     return g_value_get_float(&value);
    678 }
    679 
    680 JSStringRef AccessibilityUIElement::valueDescription()
    681 {
    682     // FIXME: implement after it has been implemented in ATK.
    683     // See: https://bugzilla.gnome.org/show_bug.cgi?id=684576
    684     return JSStringCreateWithCharacters(0, 0);
    685 }
    686 
    687 bool AccessibilityUIElement::isEnabled()
    688 {
    689     return checkElementState(m_element, ATK_STATE_ENABLED);
    690 }
    691 
    692 int AccessibilityUIElement::insertionPointLineNumber()
    693 {
    694     // FIXME: implement
    695     return 0;
    696 }
    697 
    698 bool AccessibilityUIElement::isPressActionSupported()
    699 {
    700     // FIXME: implement
    701     return false;
    702 }
    703 
    704 bool AccessibilityUIElement::isIncrementActionSupported()
    705 {
    706     // FIXME: implement
    707     return false;
    708 }
    709 
    710 bool AccessibilityUIElement::isDecrementActionSupported()
    711 {
    712     // FIXME: implement
    713     return false;
    714 }
    715 
    716 bool AccessibilityUIElement::isRequired() const
    717 {
    718     return checkElementState(m_element, ATK_STATE_REQUIRED);
    719 }
    720 
    721 bool AccessibilityUIElement::isFocused() const
    722 {
    723     if (!ATK_IS_OBJECT(m_element))
    724         return false;
    725 
    726     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
    727     gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
    728 
    729     return isFocused;
    730 }
    731 
    732 bool AccessibilityUIElement::isSelected() const
    733 {
    734     return checkElementState(m_element, ATK_STATE_SELECTED);
    735 }
    736 
    737 int AccessibilityUIElement::hierarchicalLevel() const
    738 {
    739     // FIXME: implement
    740     return 0;
    741 }
    742 
    743 bool AccessibilityUIElement::ariaIsGrabbed() const
    744 {
    745     return false;
    746 }
    747 
    748 JSStringRef AccessibilityUIElement::ariaDropEffects() const
    749 {   
    750     return 0;
    751 }
    752 
    753 bool AccessibilityUIElement::isExpanded() const
    754 {
    755     if (!ATK_IS_OBJECT(m_element))
    756         return false;
    757 
    758     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
    759     gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED);
    760 
    761     return isExpanded;
    762 }
    763 
    764 bool AccessibilityUIElement::isChecked() const
    765 {
    766     if (!ATK_IS_OBJECT(m_element))
    767         return false;
    768 
    769     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
    770     gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED);
    771 
    772     return isChecked;
    773 }
    774 
    775 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
    776 {
    777     // FIXME: implement
    778     return JSStringCreateWithCharacters(0, 0);
    779 }
    780 
    781 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
    782 {
    783     // FIXME: implement
    784     return JSStringCreateWithCharacters(0, 0);
    785 }
    786 
    787 JSStringRef AccessibilityUIElement::attributesOfColumns()
    788 {
    789     // FIXME: implement
    790     return JSStringCreateWithCharacters(0, 0);
    791 }
    792 
    793 JSStringRef AccessibilityUIElement::attributesOfRows()
    794 {
    795     // FIXME: implement
    796     return JSStringCreateWithCharacters(0, 0);
    797 }
    798 
    799 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
    800 {
    801     // FIXME: implement
    802     return JSStringCreateWithCharacters(0, 0);
    803 }
    804 
    805 JSStringRef AccessibilityUIElement::attributesOfHeader()
    806 {
    807     // FIXME: implement
    808     return JSStringCreateWithCharacters(0, 0);
    809 }
    810 
    811 int AccessibilityUIElement::indexInTable()
    812 {
    813     // FIXME: implement
    814     return 0;
    815 }
    816 
    817 static JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
     366} // namespace
     367
     368JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
    818369{
    819370    GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
     
    853404}
    854405
     406void alterCurrentValue(PlatformUIElement element, int factor)
     407{
     408    if (!ATK_IS_VALUE(element))
     409        return;
     410
     411    GValue currentValue = G_VALUE_INIT;
     412    atk_value_get_current_value(ATK_VALUE(element), &currentValue);
     413
     414    GValue increment = G_VALUE_INIT;
     415    atk_value_get_minimum_increment(ATK_VALUE(element), &increment);
     416
     417    GValue newValue = G_VALUE_INIT;
     418    g_value_init(&newValue, G_TYPE_FLOAT);
     419
     420    g_value_set_float(&newValue, g_value_get_float(&currentValue) + factor * g_value_get_float(&increment));
     421    atk_value_set_current_value(ATK_VALUE(element), &newValue);
     422
     423    g_value_unset(&newValue);
     424    g_value_unset(&increment);
     425    g_value_unset(&currentValue);
     426}
     427
     428AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
     429    : m_element(element)
     430{
     431    if (m_element)
     432        g_object_ref(m_element);
     433}
     434
     435AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
     436    : m_element(other.m_element)
     437{
     438    if (m_element)
     439        g_object_ref(m_element);
     440}
     441
     442AccessibilityUIElement::~AccessibilityUIElement()
     443{
     444    if (m_element)
     445        g_object_unref(m_element);
     446}
     447
     448void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elements)
     449{
     450    // FIXME: implement
     451}
     452
     453void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
     454{
     455    // FIXME: implement
     456}
     457
     458void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
     459{
     460    if (!ATK_IS_OBJECT(m_element))
     461        return;
     462
     463    int count = childrenCount();
     464    for (int i = 0; i < count; i++) {
     465        AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
     466        children.append(AccessibilityUIElement(child));
     467    }
     468}
     469
     470void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned start, unsigned end)
     471{
     472    if (!ATK_IS_OBJECT(m_element))
     473        return;
     474
     475    for (unsigned i = start; i < end; i++) {
     476        AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
     477        elementVector.append(AccessibilityUIElement(child));
     478    }
     479}
     480
     481int AccessibilityUIElement::rowCount()
     482{
     483    if (!ATK_IS_TABLE(m_element))
     484        return 0;
     485
     486    return atk_table_get_n_rows(ATK_TABLE(m_element));
     487}
     488
     489int AccessibilityUIElement::columnCount()
     490{
     491    if (!ATK_IS_TABLE(m_element))
     492        return 0;
     493
     494    return atk_table_get_n_columns(ATK_TABLE(m_element));
     495}
     496
     497int AccessibilityUIElement::childrenCount()
     498{
     499    if (!ATK_IS_OBJECT(m_element))
     500        return 0;
     501
     502    return atk_object_get_n_accessible_children(ATK_OBJECT(m_element));
     503}
     504
     505AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
     506{
     507    if (!ATK_IS_COMPONENT(m_element))
     508        return 0;
     509
     510    return AccessibilityUIElement(atk_component_ref_accessible_at_point(ATK_COMPONENT(m_element), x, y, ATK_XY_WINDOW));
     511}
     512
     513AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
     514{
     515    // FIXME: implement
     516    return 0;
     517}
     518
     519AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
     520{
     521    if (!ATK_IS_OBJECT(m_element))
     522        return 0;
     523
     524    Vector<AccessibilityUIElement> children;
     525    getChildrenWithRange(children, index, index + 1);
     526
     527    if (children.size() == 1)
     528        return children.at(0);
     529
     530    return 0;
     531}
     532
     533unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
     534{
     535    // FIXME: implement
     536    return 0;
     537}
     538
     539JSStringRef AccessibilityUIElement::allAttributes()
     540{
     541    if (!ATK_IS_OBJECT(m_element))
     542        return JSStringCreateWithCharacters(0, 0);
     543
     544    return JSStringCreateWithUTF8CString(attributesOfElement(this).utf8().data());
     545}
     546
     547JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
     548{
     549    // FIXME: implement
     550    return JSStringCreateWithCharacters(0, 0);
     551}
     552
     553JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
     554{
     555    // FIXME: implement
     556    return JSStringCreateWithCharacters(0, 0);
     557}
     558
     559AccessibilityUIElement AccessibilityUIElement::titleUIElement()
     560{
     561    if (!ATK_IS_OBJECT(m_element))
     562        return 0;
     563
     564    AtkRelationSet* set = atk_object_ref_relation_set(ATK_OBJECT(m_element));
     565    if (!set)
     566        return 0;
     567
     568    AtkObject* target = 0;
     569    int count = atk_relation_set_get_n_relations(set);
     570    for (int i = 0; i < count; i++) {
     571        AtkRelation* relation = atk_relation_set_get_relation(set, i);
     572        if (atk_relation_get_relation_type(relation) == ATK_RELATION_LABELLED_BY) {
     573            GPtrArray* targetList = atk_relation_get_target(relation);
     574            if (targetList->len)
     575                target = static_cast<AtkObject*>(g_ptr_array_index(targetList, 0));
     576        }
     577    }
     578
     579    g_object_unref(set);
     580    return target ? AccessibilityUIElement(target) : 0;
     581}
     582
     583AccessibilityUIElement AccessibilityUIElement::parentElement()
     584{
     585    if (!ATK_IS_OBJECT(m_element))
     586        return 0;
     587
     588    AtkObject* parent =  atk_object_get_parent(ATK_OBJECT(m_element));
     589    return parent ? AccessibilityUIElement(parent) : 0;
     590}
     591
     592JSStringRef AccessibilityUIElement::attributesOfChildren()
     593{
     594    if (!ATK_IS_OBJECT(m_element))
     595        return JSStringCreateWithCharacters(0, 0);
     596
     597    Vector<AccessibilityUIElement> children;
     598    getChildren(children);
     599
     600    StringBuilder builder;
     601    for (Vector<AccessibilityUIElement>::iterator it = children.begin(); it != children.end(); ++it) {
     602        builder.append(attributesOfElement(it));
     603        builder.append("\n------------\n");
     604    }
     605
     606    return JSStringCreateWithUTF8CString(builder.toString().utf8().data());
     607}
     608
     609JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
     610{
     611    // FIXME: implement
     612    return JSStringCreateWithCharacters(0, 0);
     613}
     614
     615JSStringRef AccessibilityUIElement::role()
     616{
     617    if (!ATK_IS_OBJECT(m_element))
     618        return JSStringCreateWithCharacters(0, 0);
     619
     620    AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
     621    if (!role)
     622        return JSStringCreateWithCharacters(0, 0);
     623
     624    GOwnPtr<char> roleStringWithPrefix(g_strdup_printf("AXRole: %s", roleToString(role)));
     625    return JSStringCreateWithUTF8CString(roleStringWithPrefix.get());
     626}
     627
     628JSStringRef AccessibilityUIElement::subrole()
     629{
     630    return 0;
     631}
     632
     633JSStringRef AccessibilityUIElement::roleDescription()
     634{
     635    return 0;
     636}
     637
     638JSStringRef AccessibilityUIElement::title()
     639{
     640    if (!ATK_IS_OBJECT(m_element))
     641        return JSStringCreateWithCharacters(0, 0);
     642
     643    const gchar* name = atk_object_get_name(ATK_OBJECT(m_element));
     644    GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name ? name : ""));
     645
     646    return JSStringCreateWithUTF8CString(axTitle.get());
     647}
     648
     649JSStringRef AccessibilityUIElement::description()
     650{
     651    if (!ATK_IS_OBJECT(m_element))
     652        return JSStringCreateWithCharacters(0, 0);
     653
     654    const gchar* description = atk_object_get_description(ATK_OBJECT(m_element));
     655    if (!description)
     656        return JSStringCreateWithCharacters(0, 0);
     657
     658    GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
     659
     660    return JSStringCreateWithUTF8CString(axDesc.get());
     661}
     662
     663JSStringRef AccessibilityUIElement::stringValue()
     664{
     665    if (!ATK_IS_TEXT(m_element))
     666        return JSStringCreateWithCharacters(0, 0);
     667
     668    GOwnPtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element), 0, -1));
     669    GOwnPtr<gchar> textWithReplacedCharacters(replaceCharactersForResults(text.get()));
     670    GOwnPtr<gchar> axValue(g_strdup_printf("AXValue: %s", textWithReplacedCharacters.get()));
     671
     672    return JSStringCreateWithUTF8CString(axValue.get());
     673}
     674
     675JSStringRef AccessibilityUIElement::language()
     676{
     677    if (!ATK_IS_OBJECT(m_element))
     678        return JSStringCreateWithCharacters(0, 0);
     679
     680    const gchar* locale = atk_object_get_object_locale(ATK_OBJECT(m_element));
     681    if (!locale)
     682        return JSStringCreateWithCharacters(0, 0);
     683
     684    GOwnPtr<char> axValue(g_strdup_printf("AXLanguage: %s", locale));
     685    return JSStringCreateWithUTF8CString(axValue.get());
     686}
     687
     688JSStringRef AccessibilityUIElement::helpText() const
     689{
     690    // FIXME: We need to provide a proper implementation for this that does
     691    // not depend on Mac specific concepts such as ATK_RELATION_DESCRIBED_BY,
     692    // once it's implemented (see http://webkit.org/b/121684).
     693    return JSStringCreateWithCharacters(0, 0);
     694}
     695
     696double AccessibilityUIElement::x()
     697{
     698    if (!ATK_IS_COMPONENT(m_element))
     699        return 0;
     700
     701    int x, y;
     702    atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
     703
     704    return x;
     705}
     706
     707double AccessibilityUIElement::y()
     708{
     709    if (!ATK_IS_COMPONENT(m_element))
     710        return 0;
     711
     712    int x, y;
     713    atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
     714
     715    return y;
     716}
     717
     718double AccessibilityUIElement::width()
     719{
     720    if (!ATK_IS_COMPONENT(m_element))
     721        return 0;
     722
     723    int width, height;
     724    atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
     725
     726    return width;
     727}
     728
     729double AccessibilityUIElement::height()
     730{
     731    if (!ATK_IS_COMPONENT(m_element))
     732        return 0;
     733
     734    int width, height;
     735    atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
     736
     737    return height;
     738}
     739
     740double AccessibilityUIElement::clickPointX()
     741{
     742    // Note: This is not something we have in ATK.
     743    return 0;
     744}
     745
     746double AccessibilityUIElement::clickPointY()
     747{
     748    // Note: This is not something we have in ATK.
     749    return 0;
     750}
     751
     752JSStringRef AccessibilityUIElement::orientation() const
     753{
     754    if (!ATK_IS_OBJECT(m_element))
     755        return JSStringCreateWithCharacters(0, 0);
     756
     757    const char* axOrientation = 0;
     758    if (checkElementState(m_element, ATK_STATE_HORIZONTAL))
     759        axOrientation = "AXOrientation: AXHorizontalOrientation";
     760    else if (checkElementState(m_element, ATK_STATE_VERTICAL))
     761        axOrientation = "AXOrientation: AXVerticalOrientation";
     762
     763    if (!axOrientation)
     764        return JSStringCreateWithCharacters(0, 0);
     765
     766    return JSStringCreateWithUTF8CString(axOrientation);
     767}
     768
     769double AccessibilityUIElement::intValue() const
     770{
     771    if (!ATK_IS_OBJECT(m_element))
     772        return 0;
     773
     774    if (ATK_IS_VALUE(m_element)) {
     775        GValue value = G_VALUE_INIT;
     776        atk_value_get_current_value(ATK_VALUE(m_element), &value);
     777        if (!G_VALUE_HOLDS_FLOAT(&value))
     778            return 0;
     779        return g_value_get_float(&value);
     780    }
     781
     782    // Consider headings as an special case when returning the "int value" of
     783    // an AccessibilityUIElement, so we can reuse some tests to check the level
     784    // both for HTML headings and objects with the aria-level attribute.
     785    if (atk_object_get_role(ATK_OBJECT(m_element)) == ATK_ROLE_HEADING) {
     786        String headingLevel = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, "level");
     787        bool ok;
     788        double headingLevelValue = headingLevel.toDouble(&ok);
     789        if (ok)
     790            return headingLevelValue;
     791    }
     792
     793    return 0;
     794}
     795
     796double AccessibilityUIElement::minValue()
     797{
     798    if (!ATK_IS_VALUE(m_element))
     799        return 0;
     800
     801    GValue value = G_VALUE_INIT;
     802    atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
     803    if (!G_VALUE_HOLDS_FLOAT(&value))
     804        return 0;
     805    return g_value_get_float(&value);
     806}
     807
     808double AccessibilityUIElement::maxValue()
     809{
     810    if (!ATK_IS_VALUE(m_element))
     811        return 0;
     812
     813    GValue value = G_VALUE_INIT;
     814    atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
     815    if (!G_VALUE_HOLDS_FLOAT(&value))
     816        return 0;
     817    return g_value_get_float(&value);
     818}
     819
     820JSStringRef AccessibilityUIElement::valueDescription()
     821{
     822    // FIXME: implement after it has been implemented in ATK.
     823    // See: https://bugzilla.gnome.org/show_bug.cgi?id=684576
     824    return JSStringCreateWithCharacters(0, 0);
     825}
     826
     827bool AccessibilityUIElement::isEnabled()
     828{
     829    return checkElementState(m_element, ATK_STATE_ENABLED);
     830}
     831
     832int AccessibilityUIElement::insertionPointLineNumber()
     833{
     834    // FIXME: implement
     835    return 0;
     836}
     837
     838bool AccessibilityUIElement::isPressActionSupported()
     839{
     840    // FIXME: implement
     841    return false;
     842}
     843
     844bool AccessibilityUIElement::isIncrementActionSupported()
     845{
     846    // FIXME: implement
     847    return false;
     848}
     849
     850bool AccessibilityUIElement::isDecrementActionSupported()
     851{
     852    // FIXME: implement
     853    return false;
     854}
     855
     856bool AccessibilityUIElement::isRequired() const
     857{
     858    return checkElementState(m_element, ATK_STATE_REQUIRED);
     859}
     860
     861bool AccessibilityUIElement::isFocused() const
     862{
     863    if (!ATK_IS_OBJECT(m_element))
     864        return false;
     865
     866    GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
     867    gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
     868
     869    return isFocused;
     870}
     871
     872bool AccessibilityUIElement::isSelected() const
     873{
     874    return checkElementState(m_element, ATK_STATE_SELECTED);
     875}
     876
     877int AccessibilityUIElement::hierarchicalLevel() const
     878{
     879    // FIXME: implement
     880    return 0;
     881}
     882
     883bool AccessibilityUIElement::ariaIsGrabbed() const
     884{
     885    return false;
     886}
     887
     888JSStringRef AccessibilityUIElement::ariaDropEffects() const
     889{   
     890    return 0;
     891}
     892
     893bool AccessibilityUIElement::isExpanded() const
     894{
     895    if (!ATK_IS_OBJECT(m_element))
     896        return false;
     897
     898    GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
     899    gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED);
     900
     901    return isExpanded;
     902}
     903
     904bool AccessibilityUIElement::isChecked() const
     905{
     906    if (!ATK_IS_OBJECT(m_element))
     907        return false;
     908
     909    GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
     910    gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED);
     911
     912    return isChecked;
     913}
     914
     915JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
     916{
     917    // FIXME: implement
     918    return JSStringCreateWithCharacters(0, 0);
     919}
     920
     921JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
     922{
     923    // FIXME: implement
     924    return JSStringCreateWithCharacters(0, 0);
     925}
     926
     927JSStringRef AccessibilityUIElement::attributesOfColumns()
     928{
     929    // FIXME: implement
     930    return JSStringCreateWithCharacters(0, 0);
     931}
     932
     933JSStringRef AccessibilityUIElement::attributesOfRows()
     934{
     935    // FIXME: implement
     936    return JSStringCreateWithCharacters(0, 0);
     937}
     938
     939JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
     940{
     941    // FIXME: implement
     942    return JSStringCreateWithCharacters(0, 0);
     943}
     944
     945JSStringRef AccessibilityUIElement::attributesOfHeader()
     946{
     947    // FIXME: implement
     948    return JSStringCreateWithCharacters(0, 0);
     949}
     950
     951int AccessibilityUIElement::indexInTable()
     952{
     953    // FIXME: implement
     954    return 0;
     955}
     956
    855957JSStringRef AccessibilityUIElement::rowIndexRange()
    856958{
     
    9291031
    9301032    String atkAttributeName = coreAttributeToAtkAttribute(attribute);
    931     if (atkAttributeName.isEmpty())
    932         return JSStringCreateWithCharacters(0, 0);
    933 
    934     String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), atkAttributeName.utf8().data());
    935 
    936     // In case of 'aria-invalid' when the attribute empty or has "false" for ATK
    937     // according to http://www.w3.org/WAI/PF/aria-implementation/#mapping attribute
    938     // is not mapped but layout tests will expect 'false'.
    939     if (attributeValue.isEmpty() && atkAttributeName == "aria-invalid")
    940         return JSStringCreateWithUTF8CString("false");
    941 
    942     // We need to translate ATK values exposed for 'aria-sort' (e.g. 'ascending')
    943     // into those expected by the layout tests (e.g. 'AXAscendingSortDirection').
    944     if (atkAttributeName == "sort") {
    945         if (attributeValue == "ascending")
    946             return JSStringCreateWithUTF8CString("AXAscendingSortDirection");
    947         if (attributeValue == "descending")
    948             return JSStringCreateWithUTF8CString("AXDescendingSortDirection");
    949 
    950         return JSStringCreateWithUTF8CString("AXUnknownSortDirection");
    951     }
     1033
     1034    // Try object attributes first.
     1035    String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, atkAttributeName);
     1036
     1037    // Try text attributes if the requested one was not found and we have an AtkText object.
     1038    if (attributeValue.isEmpty() && ATK_IS_TEXT(m_element))
     1039        attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), TextAttributeType, atkAttributeName);
    9521040
    9531041    return JSStringCreateWithUTF8CString(attributeValue.utf8().data());
     
    9811069        return false;
    9821070
    983     String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), atkAttributeName.utf8().data());
     1071    // For now, an attribute is supported whether it's exposed as a object or a text attribute.
     1072    String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, atkAttributeName);
     1073    if (attributeValue.isEmpty())
     1074        attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), TextAttributeType, atkAttributeName);
     1075
    9841076    return !attributeValue.isEmpty();
    985 }
    986 
    987 static void alterCurrentValue(PlatformUIElement element, int factor)
    988 {
    989     if (!ATK_IS_VALUE(element))
    990         return;
    991 
    992     GValue currentValue = G_VALUE_INIT;
    993     atk_value_get_current_value(ATK_VALUE(element), &currentValue);
    994 
    995     GValue increment = G_VALUE_INIT;
    996     atk_value_get_minimum_increment(ATK_VALUE(element), &increment);
    997 
    998     GValue newValue = G_VALUE_INIT;
    999     g_value_init(&newValue, G_TYPE_FLOAT);
    1000 
    1001     g_value_set_float(&newValue, g_value_get_float(&currentValue) + factor * g_value_get_float(&increment));
    1002     atk_value_set_current_value(ATK_VALUE(element), &newValue);
    1003 
    1004     g_value_unset(&newValue);
    1005     g_value_unset(&increment);
    1006     g_value_unset(&currentValue);
    10071077}
    10081078
     
    11771247        return false;
    11781248
    1179     return equalIgnoringCase(getAttributeSetValueForId(ATK_OBJECT(m_element), "haspopup"), "true");
     1249    String hasPopupValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, "haspopup");
     1250    return equalIgnoringCase(hasPopupValue, "true");
    11801251}
    11811252
  • trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp

    r156551 r156835  
    22 * Copyright (C) 2011 Apple Inc. All Rights Reserved.
    33 * Copyright (C) 2012 Igalia S.L.
     4 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    4647namespace WTR {
    4748
    48 static String coreAttributeToAtkAttribute(JSStringRef attribute)
     49namespace {
     50
     51enum AtkAttributeType {
     52    ObjectAttributeType,
     53    TextAttributeType
     54};
     55
     56enum AttributeDomain {
     57    CoreDomain = 0,
     58    AtkDomain
     59};
     60
     61enum 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).
     76const 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
     88String coreAttributeToAtkAttribute(JSStringRef attribute)
    4989{
    5090    size_t bufferSize = JSStringGetMaximumUTF8CStringSize(attribute);
     
    5393
    5494    String attributeString = String::fromUTF8(buffer.get());
    55     if (attributeString == "AXInvalid")
    56         return "aria-invalid";
    57 
    58     if (attributeString == "AXPlaceholderValue")
    59         return "placeholder-text";
    60    
    61     if (attributeString == "AXSortDirection")
    62         return "sort";
    63 
    64     return String();
    65 }
    66 
    67 static String getAttributeSetValueForId(AtkObject* accessible, const char* id)
    68 {
    69     const char* attributeValue = 0;
    70     AtkAttributeSet* attributeSet = atk_object_get_attributes(accessible);
     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
     103String 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
     126AtkAttributeSet* 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
     142String getAttributeSetValueForId(AtkObject* accessible, AtkAttributeType type, String id)
     143{
     144    AtkAttributeSet* attributeSet = getAttributeSet(accessible, type);
     145    if (!attributeSet)
     146        return String();
     147
     148    String attributeValue;
    71149    for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
    72150        AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(attributes->data);
    73         if (!strcmp(atkAttribute->name, id)) {
    74             attributeValue = atkAttribute->value;
     151        if (id == atkAttribute->name) {
     152            attributeValue = String::fromUTF8(atkAttribute->value);
    75153            break;
    76154        }
    77155    }
    78 
    79     String atkAttributeValue = String::fromUTF8(attributeValue);
    80156    atk_attribute_set_free(attributeSet);
    81157
    82     return atkAttributeValue;
    83 }
    84 
    85 static String getAtkAttributeSetAsString(AtkObject* accessible)
    86 {
     158    return atkAttributeValueToCoreAttributeValue(type, id, attributeValue);
     159}
     160
     161String getAtkAttributeSetAsString(AtkObject* accessible, AtkAttributeType type)
     162{
     163    AtkAttributeSet* attributeSet = getAttributeSet(accessible, type);
     164    if (!attributeSet)
     165        return String();
     166
    87167    StringBuilder builder;
    88 
    89     AtkAttributeSet* attributeSet = atk_object_get_attributes(accessible);
    90168    for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
    91169        AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
     
    100178}
    101179
    102 static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
     180bool checkElementState(PlatformUIElement element, AtkStateType stateType)
    103181{
    104182    if (!ATK_IS_OBJECT(element.get()))
     
    109187}
    110188
    111 static JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
     189JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
    112190{
    113191    GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
     
    147225}
    148226
    149 static void alterCurrentValue(PlatformUIElement element, int factor)
     227void alterCurrentValue(PlatformUIElement element, int factor)
    150228{
    151229    if (!ATK_IS_VALUE(element.get()))
     
    169247}
    170248
    171 static gchar* replaceCharactersForResults(gchar* str)
     249gchar* replaceCharactersForResults(gchar* str)
    172250{
    173251    WTF::String uString = WTF::String::fromUTF8(str);
     
    185263}
    186264
    187 static const gchar* roleToString(AtkRole role)
     265const gchar* roleToString(AtkRole role)
    188266{
    189267    switch (role) {
     
    299377}
    300378
    301 static String attributesOfElement(AccessibilityUIElement* element)
     379String attributesOfElement(AccessibilityUIElement* element)
    302380{
    303381    StringBuilder builder;
     
    346424    // We append the ATK specific attributes as a single line at the end.
    347425    builder.append("AXPlatformAttributes: ");
    348     builder.append(getAtkAttributeSetAsString(element->platformUIElement().get()));
     426    builder.append(getAtkAttributeSetAsString(element->platformUIElement().get(), ObjectAttributeType));
    349427
    350428    return builder.toString();
    351429}
     430
     431} // namespace
    352432
    353433AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
     
    571651
    572652    String atkAttributeName = coreAttributeToAtkAttribute(attribute);
    573     if (atkAttributeName.isNull())
    574         return JSStringCreateWithCharacters(0, 0);
    575 
    576     String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), atkAttributeName.utf8().data());
    577 
    578     // In case of 'aria-invalid' when the attribute empty or has "false" for ATK
    579     // according to http://www.w3.org/WAI/PF/aria-implementation/#mapping attribute
    580     // is not mapped but layout tests will expect 'false'.
    581     if (attributeValue.isEmpty() && atkAttributeName == "aria-invalid")
    582         return JSStringCreateWithUTF8CString("false");
    583 
    584     // We need to translate ATK values exposed for 'aria-sort' (e.g. 'ascending')
    585     // into those expected by the layout tests (e.g. 'AXAscendingSortDirection').
    586     if (atkAttributeName == "sort") {
    587         if (attributeValue == "ascending")
    588             return JSStringCreateWithUTF8CString("AXAscendingSortDirection");
    589         if (attributeValue == "descending")
    590             return JSStringCreateWithUTF8CString("AXDescendingSortDirection");
    591 
    592         return JSStringCreateWithUTF8CString("AXUnknownSortDirection");
    593     }
     653
     654    // Try object attributes first.
     655    String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, atkAttributeName);
     656
     657    // Try text attributes if the requested one was not found and we have an AtkText object.
     658    if (attributeValue.isEmpty() && ATK_IS_TEXT(m_element.get()))
     659        attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), TextAttributeType, atkAttributeName);
    594660
    595661    return JSStringCreateWithUTF8CString(attributeValue.utf8().data());
     
    629695        return false;
    630696
    631     String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), atkAttributeName.utf8().data());
     697    // For now, an attribute is supported whether it's exposed as a object or a text attribute.
     698    String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, atkAttributeName);
     699    if (attributeValue.isEmpty())
     700        attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), TextAttributeType, atkAttributeName);
     701
    632702    return !attributeValue.isEmpty();
    633703}
     
    808878    // both for HTML headings and objects with the aria-level attribute.
    809879    if (atk_object_get_role(ATK_OBJECT(m_element.get())) == ATK_ROLE_HEADING) {
    810         String headingLevel = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), "level");
     880        String headingLevel = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "level");
    811881        bool ok;
    812882        double headingLevelValue = headingLevel.toDouble(&ok);
     
    12141284        return false;
    12151285
    1216     return equalIgnoringCase(getAttributeSetValueForId(ATK_OBJECT(m_element.get()), "haspopup"), "true");
     1286    String hasPopupValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "haspopup");
     1287    return equalIgnoringCase(hasPopupValue, "true");
    12171288}
    12181289
Note: See TracChangeset for help on using the changeset viewer.