2 * Copyright (C) 2010 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "AccessibilityMenuList.h"
29 #include "AXObjectCache.h"
30 #include "AccessibilityMenuListPopup.h"
31 #include "RenderMenuList.h"
35 AccessibilityMenuList::AccessibilityMenuList(RenderMenuList* renderer)
36 : AccessibilityRenderObject(renderer)
40 Ref<AccessibilityMenuList> AccessibilityMenuList::create(RenderMenuList* renderer)
42 return adoptRef(*new AccessibilityMenuList(renderer));
45 bool AccessibilityMenuList::press()
48 RenderMenuList* menuList = static_cast<RenderMenuList*>(m_renderer);
49 if (menuList->popupIsVisible())
50 menuList->hidePopup();
52 menuList->showPopup();
59 void AccessibilityMenuList::addChildren()
64 AXObjectCache* cache = axObjectCache();
68 AccessibilityObject* list = cache->getOrCreate(MenuListPopupRole);
72 downcast<AccessibilityMockObject>(*list).setParent(this);
73 if (list->accessibilityIsIgnored()) {
74 cache->remove(list->axObjectID());
78 m_haveChildren = true;
79 m_children.append(list);
84 void AccessibilityMenuList::childrenChanged()
86 if (m_children.isEmpty())
89 ASSERT(m_children.size() == 1);
90 m_children[0]->childrenChanged();
93 bool AccessibilityMenuList::isCollapsed() const
96 return !static_cast<RenderMenuList*>(m_renderer)->popupIsVisible();
102 bool AccessibilityMenuList::canSetFocusAttribute() const
107 return !downcast<Element>(*node()).isDisabledFormControl();
110 void AccessibilityMenuList::didUpdateActiveOption(int optionIndex)
112 Ref<Document> document(m_renderer->document());
113 AXObjectCache* cache = document->axObjectCache();
115 const auto& childObjects = children();
116 if (!childObjects.isEmpty()) {
117 ASSERT(childObjects.size() == 1);
118 ASSERT(is<AccessibilityMenuListPopup>(*childObjects[0]));
120 // We might be calling this method in situations where the renderers for list items
121 // associated to the menu list have not been created (e.g. they might be rendered
122 // in the UI process, as it's the case in the GTK+ port, which uses GtkMenuItem).
123 // So, we need to make sure that the accessibility popup object has some children
124 // before asking it to update its active option, or it will read invalid memory.
125 // You can reproduce the issue in the GTK+ port by removing this check and running
126 // accessibility/insert-selected-option-into-select-causes-crash.html (will crash).
127 int popupChildrenSize = static_cast<int>(childObjects[0]->children().size());
128 if (is<AccessibilityMenuListPopup>(*childObjects[0]) && optionIndex >= 0 && optionIndex < popupChildrenSize)
129 downcast<AccessibilityMenuListPopup>(*childObjects[0]).didUpdateActiveOption(optionIndex);
132 cache->postNotification(this, document.ptr(), AXObjectCache::AXMenuListValueChanged, TargetElement, PostSynchronously);
135 } // namespace WebCore