18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2d0825bca7fe65beaee391d30da42e937db621564Steve Block * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     documentation and/or other materials provided with the distribution.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     its contributors may be used to endorse or promote products derived
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     from this software without specific prior written permission.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AXObjectCache.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "AccessibilityARIAGrid.h"
335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "AccessibilityARIAGridCell.h"
34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "AccessibilityARIAGridRow.h"
35643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "AccessibilityImageMapLink.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityList.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityListBox.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityListBoxOption.h"
39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "AccessibilityMediaControls.h"
40d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "AccessibilityMenuList.h"
41d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "AccessibilityMenuListOption.h"
42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "AccessibilityMenuListPopup.h"
43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "AccessibilityProgressIndicator.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityRenderObject.h"
45cad810f21b803229eb11403f9209855525a25d57Steve Block#include "AccessibilityScrollView.h"
46d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "AccessibilityScrollbar.h"
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "AccessibilitySlider.h"
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityTable.h"
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityTableCell.h"
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityTableColumn.h"
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityTableHeaderContainer.h"
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityTableRow.h"
53cad810f21b803229eb11403f9209855525a25d57Steve Block#include "Document.h"
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "FocusController.h"
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Frame.h"
56d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "HTMLAreaElement.h"
57d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "HTMLImageElement.h"
58058ccc7ba0a4d59b9f6e92808332aa9895425fc7Andrei Popescu#include "HTMLNames.h"
59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(VIDEO)
60231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "MediaControlElements.h"
61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "InputElement.h"
63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Page.h"
64dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderListBox.h"
65dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderMenuList.h"
66cad810f21b803229eb11403f9209855525a25d57Steve Block#include "RenderProgress.h"
67cad810f21b803229eb11403f9209855525a25d57Steve Block#include "RenderSlider.h"
68dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderTable.h"
69dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderTableCell.h"
70dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch#include "RenderTableRow.h"
715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "RenderView.h"
72cad810f21b803229eb11403f9209855525a25d57Steve Block#include "ScrollView.h"
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/PassRefPtr.h>
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AXObjectCache::gAccessibilityEnabled = false;
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool AXObjectCache::gAccessibilityEnhancedUserInterfaceEnabled = false;
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
83cad810f21b803229eb11403f9209855525a25d57Steve BlockAXObjectCache::AXObjectCache(const Document* doc)
845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    : m_notificationPostTimer(this, &AXObjectCache::notificationPostTimerFired)
855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
86cad810f21b803229eb11403f9209855525a25d57Steve Block    m_document = const_cast<Document*>(doc);
875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectAXObjectCache::~AXObjectCache()
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HashMap<AXID, RefPtr<AccessibilityObject> >::iterator end = m_objects.end();
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (HashMap<AXID, RefPtr<AccessibilityObject> >::iterator it = m_objects.begin(); it != end; ++it) {
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        AccessibilityObject* obj = (*it).second.get();
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        detachWrapper(obj);
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        obj->detach();
968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        removeAXID(obj);
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
100d0825bca7fe65beaee391d30da42e937db621564Steve BlockAccessibilityObject* AXObjectCache::focusedImageMapUIElement(HTMLAreaElement* areaElement)
101d0825bca7fe65beaee391d30da42e937db621564Steve Block{
102d0825bca7fe65beaee391d30da42e937db621564Steve Block    // Find the corresponding accessibility object for the HTMLAreaElement. This should be
103d0825bca7fe65beaee391d30da42e937db621564Steve Block    // in the list of children for its corresponding image.
104d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!areaElement)
105d0825bca7fe65beaee391d30da42e937db621564Steve Block        return 0;
106d0825bca7fe65beaee391d30da42e937db621564Steve Block
107d0825bca7fe65beaee391d30da42e937db621564Steve Block    HTMLImageElement* imageElement = areaElement->imageElement();
108d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!imageElement)
109d0825bca7fe65beaee391d30da42e937db621564Steve Block        return 0;
110d0825bca7fe65beaee391d30da42e937db621564Steve Block
111d0825bca7fe65beaee391d30da42e937db621564Steve Block    AccessibilityObject* axRenderImage = areaElement->document()->axObjectCache()->getOrCreate(imageElement->renderer());
112d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!axRenderImage)
113d0825bca7fe65beaee391d30da42e937db621564Steve Block        return 0;
114d0825bca7fe65beaee391d30da42e937db621564Steve Block
115d0825bca7fe65beaee391d30da42e937db621564Steve Block    AccessibilityObject::AccessibilityChildrenVector imageChildren = axRenderImage->children();
116d0825bca7fe65beaee391d30da42e937db621564Steve Block    unsigned count = imageChildren.size();
117d0825bca7fe65beaee391d30da42e937db621564Steve Block    for (unsigned k = 0; k < count; ++k) {
118d0825bca7fe65beaee391d30da42e937db621564Steve Block        AccessibilityObject* child = imageChildren[k].get();
119d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (!child->isImageMapLink())
120d0825bca7fe65beaee391d30da42e937db621564Steve Block            continue;
121d0825bca7fe65beaee391d30da42e937db621564Steve Block
122d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (static_cast<AccessibilityImageMapLink*>(child)->areaElement() == areaElement)
123d0825bca7fe65beaee391d30da42e937db621564Steve Block            return child;
124d0825bca7fe65beaee391d30da42e937db621564Steve Block    }
125d0825bca7fe65beaee391d30da42e937db621564Steve Block
126d0825bca7fe65beaee391d30da42e937db621564Steve Block    return 0;
127d0825bca7fe65beaee391d30da42e937db621564Steve Block}
128d0825bca7fe65beaee391d30da42e937db621564Steve Block
129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockAccessibilityObject* AXObjectCache::focusedUIElementForPage(const Page* page)
130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // get the focused node in the page
132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Document* focusedDocument = page->focusController()->focusedOrMainFrame()->document();
133231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Node* focusedNode = focusedDocument->focusedNode();
134231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!focusedNode)
135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        focusedNode = focusedDocument;
136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
137d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (focusedNode->hasTagName(areaTag))
138d0825bca7fe65beaee391d30da42e937db621564Steve Block        return focusedImageMapUIElement(static_cast<HTMLAreaElement*>(focusedNode));
139d0825bca7fe65beaee391d30da42e937db621564Steve Block
140231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RenderObject* focusedNodeRenderer = focusedNode->renderer();
141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!focusedNodeRenderer)
142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return 0;
143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    AccessibilityObject* obj = focusedNodeRenderer->document()->axObjectCache()->getOrCreate(focusedNodeRenderer);
145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (obj->shouldFocusActiveDescendant()) {
147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (AccessibilityObject* descendant = obj->activeDescendant())
148231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            obj = descendant;
149231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
150231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // the HTML element, for example, is focusable but has an AX object that is ignored
152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (obj->accessibilityIsIgnored())
153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        obj = obj->parentObjectUnignored();
154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return obj;
156231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
158cad810f21b803229eb11403f9209855525a25d57Steve BlockAccessibilityObject* AXObjectCache::get(Widget* widget)
159cad810f21b803229eb11403f9209855525a25d57Steve Block{
160cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!widget)
161cad810f21b803229eb11403f9209855525a25d57Steve Block        return 0;
162cad810f21b803229eb11403f9209855525a25d57Steve Block
163cad810f21b803229eb11403f9209855525a25d57Steve Block    AXID axID = m_widgetObjectMapping.get(widget);
164cad810f21b803229eb11403f9209855525a25d57Steve Block    ASSERT(!HashTraits<AXID>::isDeletedValue(axID));
165cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!axID)
166cad810f21b803229eb11403f9209855525a25d57Steve Block        return 0;
167cad810f21b803229eb11403f9209855525a25d57Steve Block
168cad810f21b803229eb11403f9209855525a25d57Steve Block    return m_objects.get(axID).get();
169cad810f21b803229eb11403f9209855525a25d57Steve Block}
170cad810f21b803229eb11403f9209855525a25d57Steve Block
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectAccessibilityObject* AXObjectCache::get(RenderObject* renderer)
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    AXID axID = m_renderObjectMapping.get(renderer);
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!HashTraits<AXID>::isDeletedValue(axID));
178cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!axID)
179cad810f21b803229eb11403f9209855525a25d57Steve Block        return 0;
1808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
181cad810f21b803229eb11403f9209855525a25d57Steve Block    return m_objects.get(axID).get();
1828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
183dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
184dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch// FIXME: This probably belongs on Node.
185dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch// FIXME: This should take a const char*, but one caller passes nullAtom.
186dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochbool nodeHasRole(Node* node, const String& role)
1875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!node || !node->isElementNode())
1895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return false;
190dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
1915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return equalIgnoringCase(static_cast<Element*>(node)->getAttribute(roleAttr), role);
1925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
194dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochstatic PassRefPtr<AccessibilityObject> createFromRenderer(RenderObject* renderer)
1958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
196dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // FIXME: How could renderer->node() ever not be an Element?
197dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Node* node = renderer->node();
1985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
199dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // If the node is aria role="list" or the aria role is empty and its a
200dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // ul/ol/dl type (it shouldn't be a list if aria says otherwise).
201dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (node && ((nodeHasRole(node, "list") || nodeHasRole(node, "directory"))
202dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch                      || (nodeHasRole(node, nullAtom) && (node->hasTagName(ulTag) || node->hasTagName(olTag) || node->hasTagName(dlTag)))))
203dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return AccessibilityList::create(renderer);
204dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
205dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // aria tables
206dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (nodeHasRole(node, "grid") || nodeHasRole(node, "treegrid"))
207dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return AccessibilityARIAGrid::create(renderer);
208dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (nodeHasRole(node, "row"))
209dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return AccessibilityARIAGridRow::create(renderer);
210dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (nodeHasRole(node, "gridcell") || nodeHasRole(node, "columnheader") || nodeHasRole(node, "rowheader"))
211dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return AccessibilityARIAGridCell::create(renderer);
2125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
213231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(VIDEO)
214dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // media controls
215dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (node && node->isMediaControlElement())
216dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return AccessibilityMediaControl::create(renderer);
217231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
218231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
219dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (renderer->isBoxModelObject()) {
220dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        RenderBoxModelObject* cssBox = toRenderBoxModelObject(renderer);
221dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (cssBox->isListBox())
222dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            return AccessibilityListBox::create(toRenderListBox(cssBox));
223dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (cssBox->isMenuList())
224dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            return AccessibilityMenuList::create(toRenderMenuList(cssBox));
225dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
226dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        // standard tables
227dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (cssBox->isTable())
228dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            return AccessibilityTable::create(toRenderTable(cssBox));
229dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (cssBox->isTableRow())
230dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            return AccessibilityTableRow::create(toRenderTableRow(cssBox));
231dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (cssBox->isTableCell())
232dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            return AccessibilityTableCell::create(toRenderTableCell(cssBox));
233dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
234dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if ENABLE(PROGRESS_TAG)
235dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // progress bar
236dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (cssBox->isProgress())
237dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            return AccessibilityProgressIndicator::create(toRenderProgress(cssBox));
238dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif
239dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // input type=range
241dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (cssBox->isSlider())
242dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            return AccessibilitySlider::create(toRenderSlider(cssBox));
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
244dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
245dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    return AccessibilityRenderObject::create(renderer);
246dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch}
247dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
248cad810f21b803229eb11403f9209855525a25d57Steve BlockAccessibilityObject* AXObjectCache::getOrCreate(Widget* widget)
249cad810f21b803229eb11403f9209855525a25d57Steve Block{
250cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!widget)
251cad810f21b803229eb11403f9209855525a25d57Steve Block        return 0;
252cad810f21b803229eb11403f9209855525a25d57Steve Block
253cad810f21b803229eb11403f9209855525a25d57Steve Block    if (AccessibilityObject* obj = get(widget))
254cad810f21b803229eb11403f9209855525a25d57Steve Block        return obj;
255cad810f21b803229eb11403f9209855525a25d57Steve Block
256cad810f21b803229eb11403f9209855525a25d57Steve Block    RefPtr<AccessibilityObject> newObj = 0;
257cad810f21b803229eb11403f9209855525a25d57Steve Block    if (widget->isFrameView())
258cad810f21b803229eb11403f9209855525a25d57Steve Block        newObj = AccessibilityScrollView::create(static_cast<ScrollView*>(widget));
259cad810f21b803229eb11403f9209855525a25d57Steve Block    else if (widget->isScrollbar())
260cad810f21b803229eb11403f9209855525a25d57Steve Block        newObj = AccessibilityScrollbar::create(static_cast<Scrollbar*>(widget));
261cad810f21b803229eb11403f9209855525a25d57Steve Block
262cad810f21b803229eb11403f9209855525a25d57Steve Block    getAXID(newObj.get());
263cad810f21b803229eb11403f9209855525a25d57Steve Block
264cad810f21b803229eb11403f9209855525a25d57Steve Block    m_widgetObjectMapping.set(widget, newObj->axObjectID());
265cad810f21b803229eb11403f9209855525a25d57Steve Block    m_objects.set(newObj->axObjectID(), newObj);
266cad810f21b803229eb11403f9209855525a25d57Steve Block    attachWrapper(newObj.get());
267cad810f21b803229eb11403f9209855525a25d57Steve Block    return newObj.get();
268cad810f21b803229eb11403f9209855525a25d57Steve Block}
269cad810f21b803229eb11403f9209855525a25d57Steve Block
270dd8bb3de4f353a81954234999f1fea748aee2ea9Ben MurdochAccessibilityObject* AXObjectCache::getOrCreate(RenderObject* renderer)
271dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{
272dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (!renderer)
273dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return 0;
274dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
275dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (AccessibilityObject* obj = get(renderer))
276dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return obj;
277dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
278dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    RefPtr<AccessibilityObject> newObj = createFromRenderer(renderer);
279dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
280dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    getAXID(newObj.get());
281dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
282dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    m_renderObjectMapping.set(renderer, newObj->axObjectID());
283dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    m_objects.set(newObj->axObjectID(), newObj);
284dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    attachWrapper(newObj.get());
285dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    return newObj.get();
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
287cad810f21b803229eb11403f9209855525a25d57Steve Block
288cad810f21b803229eb11403f9209855525a25d57Steve BlockAccessibilityObject* AXObjectCache::rootObject()
289cad810f21b803229eb11403f9209855525a25d57Steve Block{
290cad810f21b803229eb11403f9209855525a25d57Steve Block    return getOrCreate(m_document->view());
291cad810f21b803229eb11403f9209855525a25d57Steve Block}
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
29381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochAccessibilityObject* AXObjectCache::rootObjectForFrame(Frame* frame)
29481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
29581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!frame)
29681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return 0;
29781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return getOrCreate(frame->view());
29881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
29981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
3008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianAccessibilityObject* AXObjectCache::getOrCreate(AccessibilityRole role)
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<AccessibilityObject> obj = 0;
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // will be filled in...
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    switch (role) {
306643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case ListBoxOptionRole:
307643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        obj = AccessibilityListBoxOption::create();
308643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
309643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case ImageMapLinkRole:
310643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        obj = AccessibilityImageMapLink::create();
311643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
312643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case ColumnRole:
313643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        obj = AccessibilityTableColumn::create();
314643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
315643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case TableHeaderContainerRole:
316643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        obj = AccessibilityTableHeaderContainer::create();
317643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
318643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    case SliderThumbRole:
319643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        obj = AccessibilitySliderThumb::create();
320643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break;
321d0825bca7fe65beaee391d30da42e937db621564Steve Block    case MenuListPopupRole:
322d0825bca7fe65beaee391d30da42e937db621564Steve Block        obj = AccessibilityMenuListPopup::create();
323d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
324d0825bca7fe65beaee391d30da42e937db621564Steve Block    case MenuListOptionRole:
325d0825bca7fe65beaee391d30da42e937db621564Steve Block        obj = AccessibilityMenuListOption::create();
326d0825bca7fe65beaee391d30da42e937db621564Steve Block        break;
327643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    default:
328643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        obj = 0;
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (obj)
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        getAXID(obj.get());
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_objects.set(obj->axObjectID(), obj);
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    attachWrapper(obj.get());
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return obj.get();
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AXObjectCache::remove(AXID axID)
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!axID)
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // first fetch object to operate some cleanup functions on it
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    AccessibilityObject* obj = m_objects.get(axID).get();
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!obj)
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    detachWrapper(obj);
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    obj->detach();
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    removeAXID(obj);
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // finally remove the object
356643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!m_objects.take(axID))
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_objects.size() >= m_idsInUse.size());
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AXObjectCache::remove(RenderObject* renderer)
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    AXID axID = m_renderObjectMapping.get(renderer);
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    remove(axID);
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_renderObjectMapping.remove(renderer);
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
372cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid AXObjectCache::remove(Widget* view)
373cad810f21b803229eb11403f9209855525a25d57Steve Block{
374cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!view)
375cad810f21b803229eb11403f9209855525a25d57Steve Block        return;
376cad810f21b803229eb11403f9209855525a25d57Steve Block
377cad810f21b803229eb11403f9209855525a25d57Steve Block    AXID axID = m_widgetObjectMapping.get(view);
378cad810f21b803229eb11403f9209855525a25d57Steve Block    remove(axID);
379cad810f21b803229eb11403f9209855525a25d57Steve Block    m_widgetObjectMapping.remove(view);
380cad810f21b803229eb11403f9209855525a25d57Steve Block}
381cad810f21b803229eb11403f9209855525a25d57Steve Block
382cad810f21b803229eb11403f9209855525a25d57Steve Block
383e14391e94c850b8bd03680c23b38978db68687a8John Reck#if !PLATFORM(WIN) || OS(WINCE)
384231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockAXID AXObjectCache::platformGenerateAXID() const
385231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
386231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    static AXID lastUsedID = 0;
387231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
388231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Generate a new ID.
389231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    AXID objID = lastUsedID;
390231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    do {
391231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ++objID;
392643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    } while (!objID || HashTraits<AXID>::isDeletedValue(objID) || m_idsInUse.contains(objID));
393231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
394231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    lastUsedID = objID;
395231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
396231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return objID;
397231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
398231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
399231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectAXID AXObjectCache::getAXID(AccessibilityObject* obj)
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // check for already-assigned ID
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    AXID objID = obj->axObjectID();
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (objID) {
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_idsInUse.contains(objID));
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return objID;
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
408231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
409231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    objID = platformGenerateAXID();
410231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_idsInUse.add(objID);
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    obj->setAXObjectID(objID);
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return objID;
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
417d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid AXObjectCache::removeAXID(AccessibilityObject* object)
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
419d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!object)
4208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
4218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
422d0825bca7fe65beaee391d30da42e937db621564Steve Block    AXID objID = object->axObjectID();
423643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!objID)
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!HashTraits<AXID>::isDeletedValue(objID));
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_idsInUse.contains(objID));
427d0825bca7fe65beaee391d30da42e937db621564Steve Block    object->setAXObjectID(0);
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_idsInUse.remove(objID);
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
431d0825bca7fe65beaee391d30da42e937db621564Steve Block#if HAVE(ACCESSIBILITY)
432d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid AXObjectCache::contentChanged(RenderObject* renderer)
433d0825bca7fe65beaee391d30da42e937db621564Steve Block{
434d0825bca7fe65beaee391d30da42e937db621564Steve Block    AccessibilityObject* object = getOrCreate(renderer);
435d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (object)
436d0825bca7fe65beaee391d30da42e937db621564Steve Block        object->contentChanged();
437d0825bca7fe65beaee391d30da42e937db621564Steve Block}
438d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif
439d0825bca7fe65beaee391d30da42e937db621564Steve Block
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AXObjectCache::childrenChanged(RenderObject* renderer)
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    AXID axID = m_renderObjectMapping.get(renderer);
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!axID)
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    AccessibilityObject* obj = m_objects.get(axID).get();
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (obj)
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        obj->childrenChanged();
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid AXObjectCache::notificationPostTimerFired(Timer<AXObjectCache>*)
4555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
4565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_notificationPostTimer.stop();
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    unsigned i = 0, count = m_notificationsToPost.size();
4595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    for (i = 0; i < count; ++i) {
4600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        AccessibilityObject* obj = m_notificationsToPost[i].first.get();
4615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#ifndef NDEBUG
4625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Make sure none of the render views are in the process of being layed out.
4635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Notifications should only be sent after the renderer has finished
4645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (obj->isAccessibilityRenderObject()) {
4655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            AccessibilityRenderObject* renderObj = static_cast<AccessibilityRenderObject*>(obj);
4665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            RenderObject* renderer = renderObj->renderer();
4675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (renderer && renderer->view())
4685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                ASSERT(!renderer->view()->layoutState());
4695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
4705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#endif
4715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        postPlatformNotification(obj, m_notificationsToPost[i].second);
4735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
4745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_notificationsToPost.clear();
4765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
4775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(ACCESSIBILITY)
479d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid AXObjectCache::postNotification(RenderObject* renderer, AXNotification notification, bool postToElement, PostType postType)
4805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
4815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Notifications for text input objects are sent to that object.
4825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // All others are sent to the top WebArea.
4835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!renderer)
4845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
4855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Get an accessibility object that already exists. One should not be created here
4875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // because a render update may be in progress and creating an AX object can re-trigger a layout
488d0825bca7fe65beaee391d30da42e937db621564Steve Block    RefPtr<AccessibilityObject> object = get(renderer);
489d0825bca7fe65beaee391d30da42e937db621564Steve Block    while (!object && renderer) {
4905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        renderer = renderer->parent();
491d0825bca7fe65beaee391d30da42e937db621564Steve Block        object = get(renderer);
4925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
4935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!renderer)
4955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
4965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
497d0825bca7fe65beaee391d30da42e937db621564Steve Block    postNotification(object.get(), renderer->document(), notification, postToElement, postType);
498d0825bca7fe65beaee391d30da42e937db621564Steve Block}
499d0825bca7fe65beaee391d30da42e937db621564Steve Block
500d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid AXObjectCache::postNotification(AccessibilityObject* object, Document* document, AXNotification notification, bool postToElement, PostType postType)
501d0825bca7fe65beaee391d30da42e937db621564Steve Block{
502d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (object && !postToElement)
503d0825bca7fe65beaee391d30da42e937db621564Steve Block        object = object->observableObject();
504d0825bca7fe65beaee391d30da42e937db621564Steve Block
505d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!object && document)
506d0825bca7fe65beaee391d30da42e937db621564Steve Block        object = get(document->renderer());
507d0825bca7fe65beaee391d30da42e937db621564Steve Block
508d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!object)
5095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
5105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
511d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (postType == PostAsynchronously) {
512d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_notificationsToPost.append(make_pair(object, notification));
513d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (!m_notificationPostTimer.isActive())
514d0825bca7fe65beaee391d30da42e937db621564Steve Block            m_notificationPostTimer.startOneShot(0);
515d0825bca7fe65beaee391d30da42e937db621564Steve Block    } else
516d0825bca7fe65beaee391d30da42e937db621564Steve Block        postPlatformNotification(object, notification);
5175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
5185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AXObjectCache::selectedChildrenChanged(RenderObject* renderer)
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
521dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // postToElement is false so that you can pass in any child of an element and it will go up the parent tree
522dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // to find the container which should send out the notification.
523dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    postNotification(renderer, AXSelectedChildrenChanged, false);
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
525bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
526bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AXObjectCache::nodeTextChangeNotification(RenderObject* renderer, AXTextChange textChange, unsigned offset, unsigned count)
527bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
528bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (!renderer)
529bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        return;
530bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
531bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Delegate on the right platform
532bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    AccessibilityObject* obj = getOrCreate(renderer);
533bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    nodeTextChangePlatformNotification(obj, textChange, offset, count);
534bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(ACCESSIBILITY)
538cad810f21b803229eb11403f9209855525a25d57Steve Block
539cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid AXObjectCache::handleScrollbarUpdate(ScrollView* view)
540cad810f21b803229eb11403f9209855525a25d57Steve Block{
541cad810f21b803229eb11403f9209855525a25d57Steve Block    if (!view)
542cad810f21b803229eb11403f9209855525a25d57Steve Block        return;
543cad810f21b803229eb11403f9209855525a25d57Steve Block
544cad810f21b803229eb11403f9209855525a25d57Steve Block    // We don't want to create a scroll view from this method, only update an existing one.
545cad810f21b803229eb11403f9209855525a25d57Steve Block    AccessibilityObject* scrollViewObject = get(view);
546cad810f21b803229eb11403f9209855525a25d57Steve Block    if (scrollViewObject)
547cad810f21b803229eb11403f9209855525a25d57Steve Block        scrollViewObject->updateChildrenIfNecessary();
548cad810f21b803229eb11403f9209855525a25d57Steve Block}
549cad810f21b803229eb11403f9209855525a25d57Steve Block
55006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenvoid AXObjectCache::handleAriaExpandedChange(RenderObject *renderer)
55106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
55206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (!renderer)
55306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return;
55406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    AccessibilityObject* obj = getOrCreate(renderer);
55506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (obj)
55606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        obj->handleAriaExpandedChanged();
55706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
55806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AXObjectCache::handleActiveDescendantChanged(RenderObject* renderer)
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    AccessibilityObject* obj = getOrCreate(renderer);
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (obj)
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        obj->handleActiveDescendantChanged();
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AXObjectCache::handleAriaRoleChanged(RenderObject* renderer)
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!renderer)
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    AccessibilityObject* obj = getOrCreate(renderer);
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (obj && obj->isAccessibilityRenderObject())
5740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        static_cast<AccessibilityRenderObject*>(obj)->updateAccessibilityRole();
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
577bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
5780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochVisiblePosition AXObjectCache::visiblePositionForTextMarkerData(TextMarkerData& textMarkerData)
5790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
580bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (!isNodeInUse(textMarkerData.node))
581bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        return VisiblePosition();
582bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
58381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // FIXME: Accessability should make it clear these are DOM-compliant offsets or store Position objects.
58481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    VisiblePosition visiblePos = VisiblePosition(Position(textMarkerData.node, textMarkerData.offset), textMarkerData.affinity);
5850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    Position deepPos = visiblePos.deepEquivalent();
5860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (deepPos.isNull())
5870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return VisiblePosition();
5880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
58981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    RenderObject* renderer = deepPos.deprecatedNode()->renderer();
5900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!renderer)
5910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return VisiblePosition();
5920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    AXObjectCache* cache = renderer->document()->axObjectCache();
5940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!cache->isIDinUse(textMarkerData.axID))
5950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return VisiblePosition();
5960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
59781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (deepPos.deprecatedNode() != textMarkerData.node || deepPos.deprecatedEditingOffset() != textMarkerData.offset)
5980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return VisiblePosition();
5990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return visiblePos;
6010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid AXObjectCache::textMarkerDataForVisiblePosition(TextMarkerData& textMarkerData, const VisiblePosition& visiblePos)
6040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
6050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // This memory must be bzero'd so instances of TextMarkerData can be tested for byte-equivalence.
6060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // This also allows callers to check for failure by looking at textMarkerData upon return.
6070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    memset(&textMarkerData, 0, sizeof(TextMarkerData));
6080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (visiblePos.isNull())
6100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
6110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    Position deepPos = visiblePos.deepEquivalent();
61381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    Node* domNode = deepPos.deprecatedNode();
6140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(domNode);
6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!domNode)
6160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
6170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (domNode->isHTMLElement()) {
6192bde8e466a4451c7319e3a072d118917957d6554Steve Block        InputElement* inputElement = domNode->toInputElement();
6200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (inputElement && inputElement->isPasswordField())
6210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return;
6220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
6230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // locate the renderer, which must exist for a visible dom node
6250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RenderObject* renderer = domNode->renderer();
6260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(renderer);
6270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // find or create an accessibility object for this renderer
6290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    AXObjectCache* cache = renderer->document()->axObjectCache();
6300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RefPtr<AccessibilityObject> obj = cache->getOrCreate(renderer);
6310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    textMarkerData.axID = obj.get()->axObjectID();
6330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    textMarkerData.node = domNode;
6340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    textMarkerData.offset = deepPos.deprecatedEditingOffset();
635bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    textMarkerData.affinity = visiblePos.affinity();
636bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
637bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    cache->setNodeInUse(domNode);
6380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
6390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
641