Home | History | Annotate | Download | only in accessibility
      1 /*
      2  * Copyright (C) 2010 Apple Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      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.
     12  *
     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.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/accessibility/AXMenuListPopup.h"
     28 
     29 #include "core/accessibility/AXMenuListOption.h"
     30 #include "core/accessibility/AXObjectCache.h"
     31 #include "core/html/HTMLSelectElement.h"
     32 
     33 namespace blink {
     34 
     35 using namespace HTMLNames;
     36 
     37 AXMenuListPopup::AXMenuListPopup()
     38 {
     39 }
     40 
     41 bool AXMenuListPopup::isVisible() const
     42 {
     43     return false;
     44 }
     45 
     46 bool AXMenuListPopup::isOffScreen() const
     47 {
     48     if (!m_parent)
     49         return true;
     50 
     51     return m_parent->isCollapsed();
     52 }
     53 
     54 bool AXMenuListPopup::isEnabled() const
     55 {
     56     if (!m_parent)
     57         return false;
     58 
     59     return m_parent->isEnabled();
     60 }
     61 
     62 bool AXMenuListPopup::computeAccessibilityIsIgnored() const
     63 {
     64     return accessibilityIsIgnoredByDefault();
     65 }
     66 
     67 AXMenuListOption* AXMenuListPopup::menuListOptionAXObject(HTMLElement* element) const
     68 {
     69     ASSERT(element);
     70     if (!isHTMLOptionElement(*element))
     71         return 0;
     72 
     73     AXObject* object = document()->axObjectCache()->getOrCreate(MenuListOptionRole);
     74     ASSERT_WITH_SECURITY_IMPLICATION(object->isMenuListOption());
     75 
     76     AXMenuListOption* option = toAXMenuListOption(object);
     77     option->setElement(element);
     78 
     79     return option;
     80 }
     81 
     82 bool AXMenuListPopup::press() const
     83 {
     84     if (!m_parent)
     85         return false;
     86 
     87     m_parent->press();
     88     return true;
     89 }
     90 
     91 void AXMenuListPopup::addChildren()
     92 {
     93     if (!m_parent)
     94         return;
     95 
     96     Node* selectNode = m_parent->node();
     97     if (!selectNode)
     98         return;
     99 
    100     m_haveChildren = true;
    101 
    102     const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = toHTMLSelectElement(selectNode)->listItems();
    103     unsigned length = listItems.size();
    104     for (unsigned i = 0; i < length; i++) {
    105         AXMenuListOption* option = menuListOptionAXObject(listItems[i]);
    106         if (option) {
    107             option->setParent(this);
    108             m_children.append(option);
    109         }
    110     }
    111 }
    112 
    113 void AXMenuListPopup::childrenChanged()
    114 {
    115     AXObjectCache* cache = axObjectCache();
    116     if (!cache)
    117         return;
    118     for (size_t i = m_children.size(); i > 0 ; --i) {
    119         AXObject* child = m_children[i - 1].get();
    120         // FIXME: How could children end up in here that have no actionElement(), the check
    121         // in menuListOptionAXObject would seem to prevent that.
    122         if (child->actionElement()) {
    123             child->detachFromParent();
    124             cache->remove(child->axObjectID());
    125         }
    126     }
    127 
    128     m_children.clear();
    129     m_haveChildren = false;
    130 }
    131 
    132 void AXMenuListPopup::didUpdateActiveOption(int optionIndex)
    133 {
    134     // We defer creation of the children until updating the active option so that we don't
    135     // create AXObjects for <option> elements while they're in the middle of removal.
    136     if (!m_haveChildren)
    137         addChildren();
    138 
    139     ASSERT_ARG(optionIndex, optionIndex >= 0);
    140     ASSERT_ARG(optionIndex, optionIndex < static_cast<int>(m_children.size()));
    141 
    142     AXObjectCache* cache = axObjectCache();
    143     RefPtr<AXObject> child = m_children[optionIndex].get();
    144 
    145     cache->postNotification(child.get(), document(), AXObjectCache::AXFocusedUIElementChanged, true, PostSynchronously);
    146     cache->postNotification(child.get(), document(), AXObjectCache::AXMenuListItemSelected, true, PostSynchronously);
    147 }
    148 
    149 } // namespace blink
    150