Changeset 131871 in webkit


Ignore:
Timestamp:
Oct 19, 2012 1:01:06 AM (12 years ago)
Author:
dmazzoni@google.com
Message:

AX: labelForElement is slow when there are a lot of DOM elements
https://bugs.webkit.org/show_bug.cgi?id=97825

Reviewed by Ryosuke Niwa.

Source/WebCore:

Adds a DocumentOrderedMap to TreeScope that allows accessibility to
quickly map from an id to the label for that id. This speeds up
AccessibilityNode::labelForElement, which was a bottleneck in Chromium
when accessibility was on.

Tests: accessibility/title-ui-element-correctness.html

perf/accessibility-title-ui-element.html

  • accessibility/AccessibilityNodeObject.cpp:

(WebCore::AccessibilityNodeObject::labelForElement):

  • dom/DocumentOrderedMap.cpp:

(WebCore::keyMatchesLabelForAttribute):
(WebCore):
(WebCore::DocumentOrderedMap::get):
(WebCore::DocumentOrderedMap::getElementByLabelForAttribute):

  • dom/DocumentOrderedMap.h:

(DocumentOrderedMap):

  • dom/Element.cpp:

(WebCore::Element::insertedInto):
(WebCore::Element::removedFrom):
(WebCore::Element::updateLabel):
(WebCore):
(WebCore::Element::willModifyAttribute):

  • dom/Element.h:

(Element):

  • dom/TreeScope.cpp:

(WebCore::TreeScope::TreeScope):
(WebCore::TreeScope::destroyTreeScopeData):
(WebCore::TreeScope::addLabel):
(WebCore):
(WebCore::TreeScope::removeLabel):
(WebCore::TreeScope::labelElementForId):

  • dom/TreeScope.h:

(WebCore):
(TreeScope):
(WebCore::TreeScope::shouldCacheLabelsByForAttribute):

Tools:

Implement titleUIElement in the chromium port of DRT, and
fix getAccessibleElementById so that it ensures the backing store
is up-to-date.

  • DumpRenderTree/chromium/TestRunner/AccessibilityControllerChromium.cpp:

(AccessibilityController::getAccessibleElementById):

  • DumpRenderTree/chromium/TestRunner/AccessibilityUIElementChromium.cpp:

(AccessibilityUIElement::titleUIElementCallback):

LayoutTests:

Adds two new tests for titleUIElement that run on both Mac and
Chromium. One tests correctness, the other tests speed.

Fixes one test so that it passes on Chromium.
Enables other tests that now pass on Chromium.

  • accessibility/secure-textfield-title-ui.html:
  • accessibility/title-ui-element-correctness-expected.txt: Added.
  • accessibility/title-ui-element-correctness.html: Added.
  • perf/accessibility-title-ui-element-expected.txt: Added.
  • perf/accessibility-title-ui-element.html: Added.
  • platform/chromium/TestExpectations:
Location:
trunk
Files:
4 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r131864 r131871  
     12012-10-18  Dominic Mazzoni  <dmazzoni@google.com>
     2
     3        AX: labelForElement is slow when there are a lot of DOM elements
     4        https://bugs.webkit.org/show_bug.cgi?id=97825
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Adds two new tests for titleUIElement that run on both Mac and
     9        Chromium. One tests correctness, the other tests speed.
     10
     11        Fixes one test so that it passes on Chromium.
     12        Enables other tests that now pass on Chromium.
     13
     14        * accessibility/secure-textfield-title-ui.html:
     15        * accessibility/title-ui-element-correctness-expected.txt: Added.
     16        * accessibility/title-ui-element-correctness.html: Added.
     17        * perf/accessibility-title-ui-element-expected.txt: Added.
     18        * perf/accessibility-title-ui-element.html: Added.
     19        * platform/chromium/TestExpectations:
     20
    1212012-10-18  Alexander Pavlov  <apavlov@chromium.org>
    222
  • trunk/LayoutTests/accessibility/secure-textfield-title-ui.html

    r131124 r131871  
    2222            var titleUIElement = accessibilityController.focusedElement.titleUIElement();
    2323            var titleText = titleUIElement.childAtIndex(0);
    24             var pattern = "AXValue: Password";
    25             if (titleText.allAttributes().indexOf(pattern) != -1) {
     24            if (titleText.stringValue == "AXValue: Password") {
    2625                result.innerText += "Test passed\n";
    2726            }
  • trunk/LayoutTests/platform/chromium/TestExpectations

    r131852 r131871  
    14031403crbug.com/10322 accessibility/lists.html [ Skip ]
    14041404crbug.com/10322 accessibility/media-element.html [ Skip ]
    1405 crbug.com/10322 accessibility/non-data-table-cell-title-ui-element.html [ Skip ]
    14061405crbug.com/10322 accessibility/onclick-handlers.html [ Skip ]
    14071406crbug.com/10322 accessibility/placeholder.html [ Skip ]
     
    14091408crbug.com/10322 accessibility/radio-button-checkbox-size.html [ Skip ]
    14101409crbug.com/10322 accessibility/radio-button-group-members.html [ Skip ]
    1411 crbug.com/10322 accessibility/radio-button-title-label.html [ Skip ]
    1412 crbug.com/10322 accessibility/secure-textfield-title-ui.html [ Skip ]
    14131410crbug.com/10322 accessibility/table-attributes.html [ Skip ]
    14141411crbug.com/10322 accessibility/table-cell-spans.html [ Skip ]
     
    14191416crbug.com/10322 accessibility/table-with-aria-role.html [ Skip ]
    14201417crbug.com/10322 accessibility/table-with-rules.html [ Skip ]
    1421 crbug.com/10322 accessibility/th-as-title-ui.html [ Skip ]
    14221418crbug.com/10322 accessibility/transformed-element.html [ Skip ]
    14231419crbug.com/10322 accessibility/visible-elements.html [ Skip ]
  • trunk/Source/WebCore/ChangeLog

    r131870 r131871  
     12012-10-18  Dominic Mazzoni  <dmazzoni@google.com>
     2
     3        AX: labelForElement is slow when there are a lot of DOM elements
     4        https://bugs.webkit.org/show_bug.cgi?id=97825
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Adds a DocumentOrderedMap to TreeScope that allows accessibility to
     9        quickly map from an id to the label for that id. This speeds up
     10        AccessibilityNode::labelForElement, which was a bottleneck in Chromium
     11        when accessibility was on.
     12
     13        Tests: accessibility/title-ui-element-correctness.html
     14               perf/accessibility-title-ui-element.html
     15
     16        * accessibility/AccessibilityNodeObject.cpp:
     17        (WebCore::AccessibilityNodeObject::labelForElement):
     18        * dom/DocumentOrderedMap.cpp:
     19        (WebCore::keyMatchesLabelForAttribute):
     20        (WebCore):
     21        (WebCore::DocumentOrderedMap::get):
     22        (WebCore::DocumentOrderedMap::getElementByLabelForAttribute):
     23        * dom/DocumentOrderedMap.h:
     24        (DocumentOrderedMap):
     25        * dom/Element.cpp:
     26        (WebCore::Element::insertedInto):
     27        (WebCore::Element::removedFrom):
     28        (WebCore::Element::updateLabel):
     29        (WebCore):
     30        (WebCore::Element::willModifyAttribute):
     31        * dom/Element.h:
     32        (Element):
     33        * dom/TreeScope.cpp:
     34        (WebCore::TreeScope::TreeScope):
     35        (WebCore::TreeScope::destroyTreeScopeData):
     36        (WebCore::TreeScope::addLabel):
     37        (WebCore):
     38        (WebCore::TreeScope::removeLabel):
     39        (WebCore::TreeScope::labelElementForId):
     40        * dom/TreeScope.h:
     41        (WebCore):
     42        (TreeScope):
     43        (WebCore::TreeScope::shouldCacheLabelsByForAttribute):
     44
    1452012-10-19  Eugene Klyuchnikov  <eustas.bug@gmail.com>
    246
  • trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp

    r131124 r131871  
    6060#include "HitTestRequest.h"
    6161#include "HitTestResult.h"
     62#include "LabelableElement.h"
    6263#include "LocalizedStrings.h"
    6364#include "MathMLNames.h"
     
    10021003HTMLLabelElement* AccessibilityNodeObject::labelForElement(Element* element) const
    10031004{
    1004     RefPtr<NodeList> list = element->document()->getElementsByTagName("label");
    1005     unsigned len = list->length();
    1006     for (unsigned i = 0; i < len; i++) {
    1007         if (list->item(i)->hasTagName(labelTag)) {
    1008             HTMLLabelElement* label = static_cast<HTMLLabelElement*>(list->item(i));
    1009             if (label->control() == element)
    1010                 return label;
    1011         }
     1005    if (!element->isHTMLElement() || !toHTMLElement(element)->isLabelable())
     1006        return 0;
     1007
     1008    const AtomicString& id = element->getIdAttribute();
     1009    if (!id.isEmpty()) {
     1010        if (HTMLLabelElement* label = element->treeScope()->labelElementForId(id))
     1011            return label;
     1012    }
     1013
     1014    for (Element* parent = element->parentElement(); parent; parent = parent->parentElement()) {
     1015        if (parent->hasTagName(labelTag))
     1016            return static_cast<HTMLLabelElement*>(parent);
    10121017    }
    10131018
  • trunk/Source/WebCore/dom/DocumentOrderedMap.cpp

    r131124 r131871  
    5454{
    5555    return element->hasTagName(mapTag) && static_cast<HTMLMapElement*>(element)->getName().lower().impl() == key;
     56}
     57
     58inline bool keyMatchesLabelForAttribute(AtomicStringImpl* key, Element* element)
     59{
     60    return element->hasTagName(labelTag) && element->getAttribute(forAttr).impl() == key;
    5661}
    5762
     
    150155}
    151156
     157Element* DocumentOrderedMap::getElementByLabelForAttribute(AtomicStringImpl* key, const TreeScope* scope) const
     158{
     159    return get<keyMatchesLabelForAttribute>(key, scope);
     160}
     161
    152162} // namespace WebCore
    153 
  • trunk/Source/WebCore/dom/DocumentOrderedMap.h

    r131124 r131871  
    5353    Element* getElementByMapName(AtomicStringImpl*, const TreeScope*) const;
    5454    Element* getElementByLowercasedMapName(AtomicStringImpl*, const TreeScope*) const;
     55    Element* getElementByLabelForAttribute(AtomicStringImpl*, const TreeScope*) const;
    5556
    5657    void checkConsistency() const;
     
    8182
    8283#endif // DocumentOrderedMap_h
    83 
  • trunk/Source/WebCore/dom/Element.cpp

    r131739 r131871  
    4949#include "HTMLFormCollection.h"
    5050#include "HTMLFrameOwnerElement.h"
     51#include "HTMLLabelElement.h"
    5152#include "HTMLNames.h"
    5253#include "HTMLOptionsCollection.h"
     
    960961        updateName(nullAtom, nameValue);
    961962
     963    if (hasTagName(labelTag)) {
     964        TreeScope* scope = treeScope();
     965        if (scope->shouldCacheLabelsByForAttribute())
     966            updateLabel(scope, nullAtom, fastGetAttribute(forAttr));
     967    }
     968
    962969    return InsertionDone;
    963970}
     
    984991        if (!nameValue.isNull())
    985992            updateName(nameValue, nullAtom);
     993
     994        if (hasTagName(labelTag)) {
     995            TreeScope* treeScope = insertionPoint->treeScope();
     996            if (treeScope->shouldCacheLabelsByForAttribute())
     997                updateLabel(treeScope, fastGetAttribute(forAttr), nullAtom);
     998        }
    986999    }
    9871000
     
    21262139#endif
    21272140
     2141void Element::updateLabel(TreeScope* scope, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue)
     2142{
     2143    ASSERT(hasTagName(labelTag));
     2144
     2145    if (!inDocument())
     2146        return;
     2147
     2148    if (oldForAttributeValue == newForAttributeValue)
     2149        return;
     2150
     2151    if (!oldForAttributeValue.isEmpty())
     2152        scope->removeLabel(oldForAttributeValue, static_cast<HTMLLabelElement*>(this));
     2153    if (!newForAttributeValue.isEmpty())
     2154        scope->addLabel(newForAttributeValue, static_cast<HTMLLabelElement*>(this));
     2155}
     2156
    21282157void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
    21292158{
     
    21322161    else if (name == HTMLNames::nameAttr)
    21332162        updateName(oldValue, newValue);
     2163    else if (name == HTMLNames::forAttr && hasTagName(labelTag)) {
     2164        TreeScope* scope = treeScope();
     2165        if (scope->shouldCacheLabelsByForAttribute())
     2166            updateLabel(scope, oldValue, newValue);
     2167    }
    21342168
    21352169#if ENABLE(MUTATION_OBSERVERS)
  • trunk/Source/WebCore/dom/Element.h

    r131124 r131871  
    316316    void updateId(TreeScope*, const AtomicString& oldId, const AtomicString& newId);
    317317    void updateName(const AtomicString& oldName, const AtomicString& newName);
     318    void updateLabel(TreeScope*, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue);
    318319
    319320    void removeCachedHTMLCollection(HTMLCollection*, CollectionType);
  • trunk/Source/WebCore/dom/TreeScope.cpp

    r131549 r131871  
    3737#include "HTMLAnchorElement.h"
    3838#include "HTMLFrameOwnerElement.h"
     39#include "HTMLLabelElement.h"
    3940#include "HTMLMapElement.h"
    4041#include "HTMLNames.h"
     
    5657    : m_rootNode(rootNode)
    5758    , m_parentTreeScope(0)
     59    , m_shouldCacheLabelsByForAttribute(false)
    5860    , m_idTargetObserverRegistry(IdTargetObserverRegistry::create())
    5961{
     
    7375    m_elementsById.clear();
    7476    m_imageMapsByName.clear();
     77    m_labelsByForAttribute.clear();
    7578}
    7679
     
    143146        return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByLowercasedMapName(AtomicString(name.lower()).impl(), this));
    144147    return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByMapName(AtomicString(name).impl(), this));
     148}
     149
     150void TreeScope::addLabel(const AtomicString& forAttributeValue, HTMLLabelElement* element)
     151{
     152    m_labelsByForAttribute.add(forAttributeValue.impl(), element);
     153}
     154
     155void TreeScope::removeLabel(const AtomicString& forAttributeValue, HTMLLabelElement* element)
     156{
     157    m_labelsByForAttribute.remove(forAttributeValue.impl(), element);
     158}
     159
     160HTMLLabelElement* TreeScope::labelElementForId(const AtomicString& forAttributeValue)
     161{
     162    if (!m_shouldCacheLabelsByForAttribute) {
     163        m_shouldCacheLabelsByForAttribute = true;
     164        for (Node* node = rootNode(); node; node = node->traverseNextNode()) {
     165            if (node->hasTagName(labelTag)) {
     166                HTMLLabelElement* label = static_cast<HTMLLabelElement*>(node);
     167                const AtomicString& forValue = label->fastGetAttribute(forAttr);
     168                if (!forValue.isEmpty())
     169                    addLabel(forValue, label);
     170            }
     171        }
     172    }
     173
     174    if (forAttributeValue.isEmpty())
     175        return 0;
     176
     177    return static_cast<HTMLLabelElement*>(m_labelsByForAttribute.getElementByLabelForAttribute(forAttributeValue.impl(), this));
    145178}
    146179
  • trunk/Source/WebCore/dom/TreeScope.h

    r131124 r131871  
    3636class DOMSelection;
    3737class Element;
     38class HTMLLabelElement;
    3839class HTMLMapElement;
    3940class IdTargetObserverRegistry;
     
    6263    void removeImageMap(HTMLMapElement*);
    6364    HTMLMapElement* getImageMap(const String& url) const;
     65
     66    // For accessibility.
     67    bool shouldCacheLabelsByForAttribute() const { return m_shouldCacheLabelsByForAttribute; }
     68    void addLabel(const AtomicString& forAttributeValue, HTMLLabelElement*);
     69    void removeLabel(const AtomicString& forAttributeValue, HTMLLabelElement*);
     70    HTMLLabelElement* labelElementForId(const AtomicString& forAttributeValue);
    6471
    6572    DOMSelection* getSelection() const;
     
    95102    DocumentOrderedMap m_imageMapsByName;
    96103
     104    DocumentOrderedMap m_labelsByForAttribute;
     105    bool m_shouldCacheLabelsByForAttribute;
     106
    97107    OwnPtr<IdTargetObserverRegistry> m_idTargetObserverRegistry;
    98108
  • trunk/Tools/ChangeLog

    r131869 r131871  
     12012-10-18  Dominic Mazzoni  <dmazzoni@google.com>
     2
     3        AX: labelForElement is slow when there are a lot of DOM elements
     4        https://bugs.webkit.org/show_bug.cgi?id=97825
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Implement titleUIElement in the chromium port of DRT, and
     9        fix getAccessibleElementById so that it ensures the backing store
     10        is up-to-date.
     11
     12        * DumpRenderTree/chromium/TestRunner/AccessibilityControllerChromium.cpp:
     13        (AccessibilityController::getAccessibleElementById):
     14        * DumpRenderTree/chromium/TestRunner/AccessibilityUIElementChromium.cpp:
     15        (AccessibilityUIElement::titleUIElementCallback):
     16
    1172012-10-17  Ilya Tikhonovsky  <loislo@chromium.org>
    218
  • trunk/Tools/DumpRenderTree/chromium/TestRunner/src/AccessibilityControllerChromium.cpp

    r131828 r131871  
    118118        m_rootElement = m_webView->accessibilityObject();
    119119
     120    if (!m_rootElement.updateBackingStoreAndCheckValidity())
     121        return 0;
     122
    120123    return findAccessibleElementByIdRecursive(m_rootElement, WebString::fromUTF8(id.c_str()));
    121124}
  • trunk/Tools/DumpRenderTree/chromium/TestRunner/src/AccessibilityUIElementChromium.cpp

    r131828 r131871  
    775775void AccessibilityUIElement::titleUIElementCallback(const CppArgumentList&, CppVariant* result)
    776776{
    777     result->setNull();
     777    WebAccessibilityObject obj = accessibilityObject().titleUIElement();
     778    if (obj.isNull()) {
     779        result->setNull();
     780        return;
     781    }
     782
     783    result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
    778784}
    779785
Note: See TracChangeset for help on using the changeset viewer.