void AccessibilityMenuListPopup::childrenChanged()
{
    for (size_t i = m_children.size(); i > 0 ; --i) {
        AccessibilityObject* child = m_children[i - 1].get();
        if (child->actionElement() && !child->actionElement()->attached()) {
            m_menuList->renderer()->document()->axObjectCache()->remove(child->axObjectID());
            m_children.remove(i - 1);
        }
    }
}
void AccessibilityMenuListPopup::childrenChanged()
{
    AXObjectCache* cache = axObjectCache();
    for (size_t i = m_children.size(); i > 0 ; --i) {
        AccessibilityObject* child = m_children[i - 1].get();
        if (child->actionElement() && !child->actionElement()->inRenderedDocument()) {
            child->detachFromParent();
            cache->remove(child->axObjectID());
        }
    }
    
    m_children.clear();
    m_haveChildren = false;
    addChildren();
}
static AtkAttributeSet* webkitAccessibleGetAttributes(AtkObject* object)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(object), 0);

    AtkAttributeSet* attributeSet = 0;
#if PLATFORM(GTK)
    attributeSet = addToAtkAttributeSet(attributeSet, "toolkit", "WebKitGtk");
#elif PLATFORM(EFL)
    attributeSet = addToAtkAttributeSet(attributeSet, "toolkit", "WebKitEfl");
#endif

    AccessibilityObject* coreObject = core(object);
    if (!coreObject)
        return attributeSet;

    // Hack needed for WebKit2 tests because obtaining an element by its ID
    // cannot be done from the UIProcess. Assistive technologies have no need
    // for this information.
    Element* element = coreObject->element() ? coreObject->element() : coreObject->actionElement();
    if (element) {
        String id = element->getIdAttribute().string();
        if (!id.isEmpty())
            attributeSet = addToAtkAttributeSet(attributeSet, "html-id", id.utf8().data());
    }

    int headingLevel = coreObject->headingLevel();
    if (headingLevel) {
        String value = String::number(headingLevel);
        attributeSet = addToAtkAttributeSet(attributeSet, "level", value.utf8().data());
    }

    if (coreObject->roleValue() == MathElementRole) {
        if (coreObject->isMathMultiscriptObject(PreSuperscript) || coreObject->isMathMultiscriptObject(PreSubscript))
            attributeSet = addToAtkAttributeSet(attributeSet, "multiscript-type", "pre");
        else if (coreObject->isMathMultiscriptObject(PostSuperscript) || coreObject->isMathMultiscriptObject(PostSubscript))
            attributeSet = addToAtkAttributeSet(attributeSet, "multiscript-type", "post");
    }

    // Set the 'layout-guess' attribute to help Assistive
    // Technologies know when an exposed table is not data table.
    if (is<AccessibilityTable>(*coreObject) && downcast<AccessibilityTable>(*coreObject).isExposableThroughAccessibility() && !coreObject->isDataTable())
        attributeSet = addToAtkAttributeSet(attributeSet, "layout-guess", "true");

    String placeholder = coreObject->placeholderValue();
    if (!placeholder.isEmpty())
        attributeSet = addToAtkAttributeSet(attributeSet, "placeholder-text", placeholder.utf8().data());

    if (coreObject->ariaHasPopup())
        attributeSet = addToAtkAttributeSet(attributeSet, "haspopup", "true");

    AccessibilitySortDirection sortDirection = coreObject->sortDirection();
    if (sortDirection != SortDirectionNone) {
        // WAI-ARIA spec says to translate the value as is from the attribute.
        const AtomicString& sortAttribute = coreObject->getAttribute(HTMLNames::aria_sortAttr);
        attributeSet = addToAtkAttributeSet(attributeSet, "sort", sortAttribute.string().utf8().data());
    }

    if (coreObject->supportsARIAPosInSet())
        attributeSet = addToAtkAttributeSet(attributeSet, "posinset", String::number(coreObject->ariaPosInSet()).utf8().data());

    if (coreObject->supportsARIASetSize())
        attributeSet = addToAtkAttributeSet(attributeSet, "setsize", String::number(coreObject->ariaSetSize()).utf8().data());

    // Landmarks will be exposed with xml-roles object attributes, with the exception
    // of LandmarkApplicationRole, which will be exposed with ATK_ROLE_EMBEDDED.
    AccessibilityRole role = coreObject->roleValue();
    switch (role) {
    case LandmarkBannerRole:
        attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "banner");
        break;
    case LandmarkComplementaryRole:
        attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "complementary");
        break;
    case LandmarkContentInfoRole:
        attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "contentinfo");
        break;
    case LandmarkMainRole:
        attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "main");
        break;
    case LandmarkNavigationRole:
        attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "navigation");
        break;
    case LandmarkSearchRole:
        attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", "search");
        break;
    default:
        break;
    }

    return attributeSet;
}
static AtkAttributeSet* webkitAccessibleGetAttributes(AtkObject* object)
{
    g_return_val_if_fail(WEBKIT_IS_ACCESSIBLE(object), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(object), 0);

    AtkAttributeSet* attributeSet = nullptr;
#if PLATFORM(GTK)
    attributeSet = addToAtkAttributeSet(attributeSet, "toolkit", "WebKitGtk");
#elif PLATFORM(EFL)
    attributeSet = addToAtkAttributeSet(attributeSet, "toolkit", "WebKitEfl");
#endif

    AccessibilityObject* coreObject = core(object);
    if (!coreObject)
        return attributeSet;

    // Hack needed for WebKit2 tests because obtaining an element by its ID
    // cannot be done from the UIProcess. Assistive technologies have no need
    // for this information.
    Element* element = coreObject->element() ? coreObject->element() : coreObject->actionElement();
    if (element) {
        String tagName = element->tagName();
        if (!tagName.isEmpty())
            attributeSet = addToAtkAttributeSet(attributeSet, "tag", tagName.lower().utf8().data());
        String id = element->getIdAttribute().string();
        if (!id.isEmpty())
            attributeSet = addToAtkAttributeSet(attributeSet, "html-id", id.utf8().data());
    }

    int headingLevel = coreObject->headingLevel();
    if (headingLevel) {
        String value = String::number(headingLevel);
        attributeSet = addToAtkAttributeSet(attributeSet, "level", value.utf8().data());
    }

    if (coreObject->roleValue() == MathElementRole) {
        if (coreObject->isMathMultiscriptObject(PreSuperscript) || coreObject->isMathMultiscriptObject(PreSubscript))
            attributeSet = addToAtkAttributeSet(attributeSet, "multiscript-type", "pre");
        else if (coreObject->isMathMultiscriptObject(PostSuperscript) || coreObject->isMathMultiscriptObject(PostSubscript))
            attributeSet = addToAtkAttributeSet(attributeSet, "multiscript-type", "post");
    }

    // Set the 'layout-guess' attribute to help Assistive
    // Technologies know when an exposed table is not data table.
    if (is<AccessibilityTable>(*coreObject) && downcast<AccessibilityTable>(*coreObject).isExposableThroughAccessibility() && !coreObject->isDataTable())
        attributeSet = addToAtkAttributeSet(attributeSet, "layout-guess", "true");

    String placeholder = coreObject->placeholderValue();
    if (!placeholder.isEmpty())
        attributeSet = addToAtkAttributeSet(attributeSet, "placeholder-text", placeholder.utf8().data());

    if (coreObject->ariaHasPopup())
        attributeSet = addToAtkAttributeSet(attributeSet, "haspopup", "true");

    AccessibilitySortDirection sortDirection = coreObject->sortDirection();
    if (sortDirection != SortDirectionNone) {
        // WAI-ARIA spec says to translate the value as is from the attribute.
        const AtomicString& sortAttribute = coreObject->getAttribute(HTMLNames::aria_sortAttr);
        attributeSet = addToAtkAttributeSet(attributeSet, "sort", sortAttribute.string().utf8().data());
    }

    if (coreObject->supportsARIAPosInSet())
        attributeSet = addToAtkAttributeSet(attributeSet, "posinset", String::number(coreObject->ariaPosInSet()).utf8().data());

    if (coreObject->supportsARIASetSize())
        attributeSet = addToAtkAttributeSet(attributeSet, "setsize", String::number(coreObject->ariaSetSize()).utf8().data());

    // According to the W3C Core Accessibility API Mappings 1.1, section 5.4.1 General Rules:
    // "User agents must expose the WAI-ARIA role string if the API supports a mechanism to do so."
    // In the case of ATK, the mechanism to do so is an object attribute pair (xml-roles:"string").
    // The computedRoleString is primarily for testing, and not limited to elements with ARIA roles.
    // Because the computedRoleString currently contains the ARIA role string, we'll use it for
    // both purposes, as the "computed-role" object attribute for all elements which have a value
    // and also via the "xml-roles" attribute for elements with ARIA, as well as for landmarks.
    String roleString = coreObject->computedRoleString();
    if (!roleString.isEmpty()) {
        if (coreObject->ariaRoleAttribute() != UnknownRole || coreObject->isLandmark())
            attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", roleString.utf8().data());
        attributeSet = addToAtkAttributeSet(attributeSet, "computed-role", roleString.utf8().data());
    }

    return attributeSet;
}