summaryrefslogtreecommitdiffstats
path: root/WebCore/accessibility
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-07-22 15:37:06 +0100
committerBen Murdoch <benm@google.com>2010-07-27 10:20:25 +0100
commit967717af5423377c967781471ee106e2bb4e11c8 (patch)
tree1e701dc0a12f7f07cce1df4a7681717de77a211b /WebCore/accessibility
parentdcc30a9fca45f634b1d3a12b276d3a0ccce99fc3 (diff)
downloadexternal_webkit-967717af5423377c967781471ee106e2bb4e11c8.zip
external_webkit-967717af5423377c967781471ee106e2bb4e11c8.tar.gz
external_webkit-967717af5423377c967781471ee106e2bb4e11c8.tar.bz2
Merge WebKit at r63859 : Initial merge by git.
Change-Id: Ie8096c63ec7c991c9a9cba8bdd9c3b74a3b8ed62
Diffstat (limited to 'WebCore/accessibility')
-rw-r--r--WebCore/accessibility/AccessibilityImageMapLink.cpp16
-rw-r--r--WebCore/accessibility/AccessibilityImageMapLink.h1
-rw-r--r--WebCore/accessibility/AccessibilityListBoxOption.cpp9
-rw-r--r--WebCore/accessibility/AccessibilityListBoxOption.h3
-rw-r--r--WebCore/accessibility/AccessibilityObject.cpp52
-rw-r--r--WebCore/accessibility/AccessibilityObject.h17
-rw-r--r--WebCore/accessibility/AccessibilityRenderObject.cpp101
-rw-r--r--WebCore/accessibility/AccessibilityRenderObject.h10
-rw-r--r--WebCore/accessibility/AccessibilityTable.cpp30
-rw-r--r--WebCore/accessibility/AccessibilityTableCell.cpp7
-rw-r--r--WebCore/accessibility/AccessibilityTableColumn.cpp3
11 files changed, 125 insertions, 124 deletions
diff --git a/WebCore/accessibility/AccessibilityImageMapLink.cpp b/WebCore/accessibility/AccessibilityImageMapLink.cpp
index 2eac8d3..924ba21 100644
--- a/WebCore/accessibility/AccessibilityImageMapLink.cpp
+++ b/WebCore/accessibility/AccessibilityImageMapLink.cpp
@@ -73,7 +73,7 @@ AccessibilityRole AccessibilityImageMapLink::roleValue() const
if (!m_areaElement)
return WebCoreLinkRole;
- const AtomicString& ariaRole = m_areaElement->getAttribute(roleAttr);
+ const AtomicString& ariaRole = getAttribute(roleAttr);
if (!ariaRole.isEmpty())
return AccessibilityObject::ariaRoleToWebCoreRole(ariaRole);
@@ -100,13 +100,10 @@ KURL AccessibilityImageMapLink::url() const
String AccessibilityImageMapLink::accessibilityDescription() const
{
- if (!m_areaElement)
- return String();
-
- const AtomicString& ariaLabel = m_areaElement->getAttribute(aria_labelAttr);
+ const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
if (!ariaLabel.isEmpty())
return ariaLabel;
- const AtomicString& alt = m_areaElement->getAttribute(altAttr);
+ const AtomicString& alt = getAttribute(altAttr);
if (!alt.isEmpty())
return alt;
@@ -115,13 +112,10 @@ String AccessibilityImageMapLink::accessibilityDescription() const
String AccessibilityImageMapLink::title() const
{
- if (!m_areaElement)
- return String();
-
- const AtomicString& title = m_areaElement->getAttribute(titleAttr);
+ const AtomicString& title = getAttribute(titleAttr);
if (!title.isEmpty())
return title;
- const AtomicString& summary = m_areaElement->getAttribute(summaryAttr);
+ const AtomicString& summary = getAttribute(summaryAttr);
if (!summary.isEmpty())
return summary;
diff --git a/WebCore/accessibility/AccessibilityImageMapLink.h b/WebCore/accessibility/AccessibilityImageMapLink.h
index ca4c62c..e2e1544 100644
--- a/WebCore/accessibility/AccessibilityImageMapLink.h
+++ b/WebCore/accessibility/AccessibilityImageMapLink.h
@@ -49,6 +49,7 @@ public:
void setHTMLMapElement(HTMLMapElement* element) { m_mapElement = element; }
HTMLMapElement* mapElement() const { return m_mapElement; }
+ virtual Node* node() const { return m_areaElement; }
void setParent(AccessibilityObject* parent) { m_parent = parent; }
virtual AccessibilityRole roleValue() const;
diff --git a/WebCore/accessibility/AccessibilityListBoxOption.cpp b/WebCore/accessibility/AccessibilityListBoxOption.cpp
index 57519e3..3e4dad9 100644
--- a/WebCore/accessibility/AccessibilityListBoxOption.cpp
+++ b/WebCore/accessibility/AccessibilityListBoxOption.cpp
@@ -110,17 +110,12 @@ bool AccessibilityListBoxOption::accessibilityIsIgnored() const
if (!m_optionElement)
return true;
- if (equalIgnoringCase(getAttribute(m_optionElement, aria_hiddenAttr), "true"))
+ if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "true"))
return true;
return parentObject()->accessibilityIsIgnored();
}
-String AccessibilityListBoxOption::language() const
-{
- return AccessibilityObject::language(m_optionElement);
-}
-
bool AccessibilityListBoxOption::canSetSelectedAttribute() const
{
if (!m_optionElement)
@@ -144,7 +139,7 @@ String AccessibilityListBoxOption::stringValue() const
if (!m_optionElement)
return String();
- const AtomicString& ariaLabel = getAttribute(m_optionElement, aria_labelAttr);
+ const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
if (!ariaLabel.isNull())
return ariaLabel;
diff --git a/WebCore/accessibility/AccessibilityListBoxOption.h b/WebCore/accessibility/AccessibilityListBoxOption.h
index 1da77e7..c4c9315 100644
--- a/WebCore/accessibility/AccessibilityListBoxOption.h
+++ b/WebCore/accessibility/AccessibilityListBoxOption.h
@@ -56,7 +56,7 @@ public:
virtual bool isEnabled() const;
virtual String stringValue() const;
virtual Element* actionElement() const;
-
+ virtual Node* node() const { return m_optionElement; }
virtual void setSelected(bool);
virtual bool canSetSelectedAttribute() const;
@@ -68,7 +68,6 @@ public:
private:
HTMLElement* m_optionElement;
- virtual String language() const;
virtual bool canHaveChildren() const { return false; }
HTMLSelectElement* listBoxOptionParentNode() const;
int listBoxOptionIndex() const;
diff --git a/WebCore/accessibility/AccessibilityObject.cpp b/WebCore/accessibility/AccessibilityObject.cpp
index 555ba6f..bc4e2f5 100644
--- a/WebCore/accessibility/AccessibilityObject.cpp
+++ b/WebCore/accessibility/AccessibilityObject.cpp
@@ -148,17 +148,12 @@ bool AccessibilityObject::press() const
return true;
}
-String AccessibilityObject::language(Node* node) const
-{
- const AtomicString& lang = getAttribute(node, langAttr);
- if (lang.isEmpty())
- return AccessibilityObject::language();
-
- return lang;
-}
-
String AccessibilityObject::language() const
{
+ const AtomicString& lang = getAttribute(langAttr);
+ if (!lang.isEmpty())
+ return lang;
+
AccessibilityObject* parent = parentObject();
// as a last resort, fall back to the content language specified in the meta tag
@@ -166,7 +161,7 @@ String AccessibilityObject::language() const
Document* doc = document();
if (doc)
return doc->contentLanguage();
- return String();
+ return nullAtom;
}
return parent->language();
@@ -403,7 +398,7 @@ static bool replacedNodeNeedsCharacter(Node* replacedNode)
}
// Finds a RenderListItem parent give a node.
-RenderListItem* AccessibilityObject::renderListItemContainerForNode(Node* node) const
+static RenderListItem* renderListItemContainerForNode(Node* node)
{
for (Node* stringNode = node; stringNode; stringNode = stringNode->parent()) {
RenderObject* renderObject = stringNode->renderer();
@@ -844,15 +839,16 @@ const String& AccessibilityObject::actionVerb() const
}
}
-const AtomicString& AccessibilityObject::getAttribute(Node* node, const QualifiedName& attribute)
+const AtomicString& AccessibilityObject::getAttribute(const QualifiedName& attribute) const
{
- if (!node)
+ Node* elementNode = node();
+ if (!elementNode)
return nullAtom;
- if (!node->isElementNode())
+ if (!elementNode->isElementNode())
return nullAtom;
- Element* element = static_cast<Element*>(node);
+ Element* element = static_cast<Element*>(elementNode);
return element->getAttribute(attribute);
}
@@ -980,6 +976,32 @@ bool AccessibilityObject::supportsARIALiveRegion() const
const AtomicString& liveRegion = ariaLiveRegionStatus();
return equalIgnoringCase(liveRegion, "polite") || equalIgnoringCase(liveRegion, "assertive");
}
+
+int AccessibilityObject::intValue() const
+{
+ if (isPasswordField())
+ return 0;
+
+ if (isHeading())
+ return headingLevel();
+
+ // If this is a real checkbox or radio button, AccessibilityRenderObject will handle.
+ // If it's an ARIA checkbox or radio, the aria-checked attribute should be used.
+ if (isCheckboxOrRadio())
+ return equalIgnoringCase(getAttribute(aria_checkedAttr), "true");
+
+ return 0;
+}
+bool AccessibilityObject::hasIntValue() const
+{
+ if (isHeading())
+ return true;
+
+ if (isCheckboxOrRadio())
+ return true;
+
+ return false;
+}
} // namespace WebCore
diff --git a/WebCore/accessibility/AccessibilityObject.h b/WebCore/accessibility/AccessibilityObject.h
index 3c8d392..400a200 100644
--- a/WebCore/accessibility/AccessibilityObject.h
+++ b/WebCore/accessibility/AccessibilityObject.h
@@ -264,7 +264,8 @@ public:
virtual bool isTextControl() const { return false; }
virtual bool isNativeTextControl() const { return false; }
virtual bool isWebArea() const { return false; }
- virtual bool isCheckboxOrRadio() const { return false; }
+ virtual bool isCheckbox() const { return roleValue() == CheckBoxRole; }
+ virtual bool isRadioButton() const { return roleValue() == RadioButtonRole; }
virtual bool isListBox() const { return roleValue() == ListBoxRole; }
virtual bool isMediaTimeline() const { return false; }
virtual bool isMenuRelated() const { return false; }
@@ -298,6 +299,7 @@ public:
bool isScrollbar() const { return roleValue() == ScrollBarRole; }
bool isButton() const { return roleValue() == ButtonRole; }
bool isListItem() const { return roleValue() == ListItemRole; }
+ bool isCheckboxOrRadio() const { return isCheckbox() || isRadioButton(); }
virtual bool isChecked() const { return false; }
virtual bool isEnabled() const { return false; }
@@ -325,16 +327,17 @@ public:
virtual bool canSetSelectedChildrenAttribute() const { return false; }
virtual bool canSetExpandedAttribute() const { return false; }
- virtual bool hasIntValue() const { return false; }
-
+ bool hasIntValue() const;
+ virtual int intValue() const;
+
// A programmatic way to set a name on an AccessibleObject.
virtual void setAccessibleName(String&) { }
+ virtual Node* node() const { return 0; }
bool accessibilityShouldUseUniqueId() const { return true; }
virtual bool accessibilityIsIgnored() const { return true; }
virtual int headingLevel() const { return 0; }
- virtual int intValue() const { return 0; }
virtual String valueDescription() const { return String(); }
virtual float valueForRange() const { return 0.0f; }
virtual float maxValueForRange() const { return 0.0f; }
@@ -419,8 +422,7 @@ public:
virtual Document* document() const { return 0; }
virtual FrameView* topDocumentFrameView() const { return 0; }
virtual FrameView* documentFrameView() const;
- virtual String language() const;
- String language(Node*) const;
+ String language() const;
virtual unsigned hierarchicalLevel() const { return 0; }
virtual void setFocused(bool) { }
@@ -454,7 +456,7 @@ public:
virtual void handleAriaExpandedChanged() { }
static AccessibilityRole ariaRoleToWebCoreRole(const String&);
- static const AtomicString& getAttribute(Node*, const QualifiedName&);
+ const AtomicString& getAttribute(const QualifiedName&) const;
virtual VisiblePositionRange visiblePositionRange() const { return VisiblePositionRange(); }
virtual VisiblePositionRange visiblePositionRangeForLine(unsigned) const { return VisiblePositionRange(); }
@@ -564,7 +566,6 @@ protected:
virtual void clearChildren();
virtual bool isDetached() const { return true; }
- RenderListItem* renderListItemContainerForNode(Node* node) const;
#if PLATFORM(MAC)
RetainPtr<AccessibilityObjectWrapper> m_wrapper;
diff --git a/WebCore/accessibility/AccessibilityRenderObject.cpp b/WebCore/accessibility/AccessibilityRenderObject.cpp
index 2e53703..1b3c461 100644
--- a/WebCore/accessibility/AccessibilityRenderObject.cpp
+++ b/WebCore/accessibility/AccessibilityRenderObject.cpp
@@ -476,12 +476,6 @@ bool AccessibilityRenderObject::isPasswordField() const
return inputElement->isPasswordField();
}
-
-bool AccessibilityRenderObject::isCheckboxOrRadio() const
-{
- AccessibilityRole role = roleValue();
- return role == RadioButtonRole || role == CheckBoxRole;
-}
bool AccessibilityRenderObject::isFileUploadButton() const
{
@@ -660,36 +654,29 @@ bool AccessibilityRenderObject::isOffScreen() const
int AccessibilityRenderObject::headingLevel() const
{
// headings can be in block flow and non-block flow
- if (!m_renderer)
- return 0;
-
- Node* node = m_renderer->node();
- if (!node)
+ Node* element = node();
+ if (!element)
return 0;
- if (ariaRoleAttribute() == HeadingRole) {
- if (!node->isElementNode())
- return 0;
- Element* element = static_cast<Element*>(node);
- return element->getAttribute(aria_levelAttr).toInt();
- }
+ if (ariaRoleAttribute() == HeadingRole)
+ return getAttribute(aria_levelAttr).toInt();
- if (node->hasTagName(h1Tag))
+ if (element->hasTagName(h1Tag))
return 1;
- if (node->hasTagName(h2Tag))
+ if (element->hasTagName(h2Tag))
return 2;
- if (node->hasTagName(h3Tag))
+ if (element->hasTagName(h3Tag))
return 3;
- if (node->hasTagName(h4Tag))
+ if (element->hasTagName(h4Tag))
return 4;
- if (node->hasTagName(h5Tag))
+ if (element->hasTagName(h5Tag))
return 5;
- if (node->hasTagName(h6Tag))
+ if (element->hasTagName(h6Tag))
return 6;
return 0;
@@ -760,11 +747,6 @@ AccessibilityObject* AccessibilityRenderObject::selectedTabItem()
}
return 0;
}
-
-const AtomicString& AccessibilityRenderObject::getAttribute(const QualifiedName& attribute) const
-{
- return AccessibilityObject::getAttribute(m_renderer->node(), attribute);
-}
Element* AccessibilityRenderObject::anchorElement() const
{
@@ -990,14 +972,6 @@ unsigned AccessibilityRenderObject::hierarchicalLevel() const
return level;
}
-
-String AccessibilityRenderObject::language() const
-{
- if (!m_renderer)
- return String();
-
- return AccessibilityObject::language(m_renderer->node());
-}
String AccessibilityRenderObject::textUnderElement() const
{
@@ -1030,38 +1004,17 @@ String AccessibilityRenderObject::textUnderElement() const
return String();
}
-bool AccessibilityRenderObject::hasIntValue() const
-{
- if (isHeading())
- return true;
-
- if (m_renderer->node() && isCheckboxOrRadio())
- return true;
+Node* AccessibilityRenderObject::node() const
+{
+ return m_renderer ? m_renderer->node() : 0;
+}
- return false;
-}
-
int AccessibilityRenderObject::intValue() const
{
- if (!m_renderer || isPasswordField())
- return 0;
-
- if (isHeading())
- return headingLevel();
-
- Node* node = m_renderer->node();
- if (!node || !isCheckboxOrRadio())
- return 0;
+ if (isCheckboxOrRadio())
+ return isChecked() ? 1 : 0;
- // If this is an ARIA checkbox or radio, check the aria-checked attribute rather than node()->checked()
- AccessibilityRole ariaRole = ariaRoleAttribute();
- if (ariaRole == RadioButtonRole || ariaRole == CheckBoxRole) {
- if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true"))
- return true;
- return false;
- }
-
- return static_cast<HTMLInputElement*>(node)->checked();
+ return AccessibilityObject::intValue();
}
String AccessibilityRenderObject::valueDescription() const
@@ -1122,9 +1075,11 @@ String AccessibilityRenderObject::stringValue() const
Element* selectedOption = 0;
if (selectedIndex >= 0 && selectedIndex < (int)listItems.size())
selectedOption = listItems[selectedIndex];
- String overridenDescription = AccessibilityObject::getAttribute(selectedOption, aria_labelAttr);
- if (!overridenDescription.isNull())
- return overridenDescription;
+ if (selectedOption) {
+ String overridenDescription = selectedOption->getAttribute(aria_labelAttr);
+ if (!overridenDescription.isNull())
+ return overridenDescription;
+ }
return toRenderMenuList(m_renderer)->text();
}
@@ -1364,9 +1319,11 @@ String AccessibilityRenderObject::accessibilityDescription() const
// Check if the HTML element has an aria-label for the webpage.
Element* documentElement = document->documentElement();
- const AtomicString& ariaLabel = AccessibilityObject::getAttribute(documentElement, aria_labelAttr);
- if (!ariaLabel.isEmpty())
- return ariaLabel;
+ if (documentElement) {
+ const AtomicString& ariaLabel = documentElement->getAttribute(aria_labelAttr);
+ if (!ariaLabel.isEmpty())
+ return ariaLabel;
+ }
Node* owner = document->ownerElement();
if (owner) {
@@ -1397,8 +1354,10 @@ IntRect AccessibilityRenderObject::boundingBoxRect() const
if (obj->node()) // If we are a continuation, we want to make sure to use the primary renderer.
obj = obj->node()->renderer();
+ // absoluteFocusRingQuads will query the hierarchy below this element, which for large webpages can be very slow.
+ // For a web area, which will have the most elements of any element, absoluteQuads should be used.
Vector<FloatQuad> quads;
- if (obj->isText())
+ if (obj->isText() || isWebArea())
obj->absoluteQuads(quads);
else
obj->absoluteFocusRingQuads(quads);
diff --git a/WebCore/accessibility/AccessibilityRenderObject.h b/WebCore/accessibility/AccessibilityRenderObject.h
index d4f798a..526324f 100644
--- a/WebCore/accessibility/AccessibilityRenderObject.h
+++ b/WebCore/accessibility/AccessibilityRenderObject.h
@@ -75,7 +75,6 @@ public:
virtual bool isTextControl() const;
virtual bool isNativeTextControl() const;
virtual bool isWebArea() const;
- virtual bool isCheckboxOrRadio() const;
virtual bool isFileUploadButton() const;
virtual bool isInputImage() const;
virtual bool isProgressIndicator() const;
@@ -106,14 +105,11 @@ public:
virtual bool isExpanded() const;
virtual void setIsExpanded(bool);
- const AtomicString& getAttribute(const QualifiedName&) const;
virtual bool canSetFocusAttribute() const;
virtual bool canSetTextRangeAttributes() const;
virtual bool canSetValueAttribute() const;
virtual bool canSetExpandedAttribute() const;
- virtual bool hasIntValue() const;
-
virtual void setAccessibleName(String&);
// Provides common logic used by all elements when determining isIgnored.
@@ -169,10 +165,7 @@ public:
void setRenderer(RenderObject* renderer) { m_renderer = renderer; }
RenderObject* renderer() const { return m_renderer; }
- Node* node() const
- {
- return m_renderer ? m_renderer->node() : 0;
- };
+ virtual Node* node() const;
RenderView* topRenderer() const;
RenderTextControl* textControl() const;
@@ -283,7 +276,6 @@ private:
bool isAllowedChildOfTree() const;
bool hasTextAlternative() const;
String positionalDescriptionForMSAA() const;
- virtual String language() const;
Element* menuElementForMenuButton() const;
Element* menuItemElementForMenu() const;
diff --git a/WebCore/accessibility/AccessibilityTable.cpp b/WebCore/accessibility/AccessibilityTable.cpp
index 437ac38..a0bb655 100644
--- a/WebCore/accessibility/AccessibilityTable.cpp
+++ b/WebCore/accessibility/AccessibilityTable.cpp
@@ -137,6 +137,9 @@ bool AccessibilityTable::isTableExposableThroughAccessibility()
unsigned borderedCellCount = 0;
unsigned backgroundDifferenceCellCount = 0;
+ Color alternatingRowColors[5];
+ int alternatingRowColorCount = 0;
+
int headersInFirstColumnCount = 0;
for (int row = 0; row < numRows; ++row) {
@@ -189,6 +192,19 @@ bool AccessibilityTable::isTableExposableThroughAccessibility()
// if we've found 10 "good" cells, we don't need to keep searching
if (borderedCellCount >= 10 || backgroundDifferenceCellCount >= 10)
return true;
+
+ // For the first 5 rows, cache the background color so we can check if this table has zebra-striped rows.
+ if (row < 5 && row == alternatingRowColorCount) {
+ RenderObject* renderRow = cell->parent();
+ if (!renderRow || !renderRow->isTableRow())
+ continue;
+ RenderStyle* rowRenderStyle = renderRow->style();
+ if (!rowRenderStyle)
+ continue;
+ Color rowColor = rowRenderStyle->visitedDependentColor(CSSPropertyBackgroundColor);
+ alternatingRowColors[alternatingRowColorCount] = rowColor;
+ alternatingRowColorCount++;
+ }
}
if (!row && headersInFirstRowCount == numCols && numCols > 1)
@@ -211,6 +227,20 @@ bool AccessibilityTable::isTableExposableThroughAccessibility()
if (backgroundDifferenceCellCount >= neededCellCount)
return true;
+ // Check if there is an alternating row background color indicating a zebra striped style pattern.
+ if (alternatingRowColorCount > 2) {
+ Color firstColor = alternatingRowColors[0];
+ for (int k = 1; k < alternatingRowColorCount; k++) {
+ // If an odd row was the same color as the first row, its not alternating.
+ if (k % 2 == 1 && alternatingRowColors[k] == firstColor)
+ return false;
+ // If an even row is not the same as the first row, its not alternating.
+ if (!(k % 2) && alternatingRowColors[k] != firstColor)
+ return false;
+ }
+ return true;
+ }
+
return false;
}
diff --git a/WebCore/accessibility/AccessibilityTableCell.cpp b/WebCore/accessibility/AccessibilityTableCell.cpp
index 7fadb88..28e66ad 100644
--- a/WebCore/accessibility/AccessibilityTableCell.cpp
+++ b/WebCore/accessibility/AccessibilityTableCell.cpp
@@ -73,7 +73,12 @@ AccessibilityObject* AccessibilityTableCell::parentTable() const
if (!m_renderer || !m_renderer->isTableCell())
return 0;
- return axObjectCache()->getOrCreate(toRenderTableCell(m_renderer)->table());
+ // Do not use getOrCreate. parentTable() can be called while the render tree is being modified
+ // by javascript, and creating a table element may try to access the render tree while in a bad state.
+ // By using only get() implies that the AXTable must be created before AXTableCells. This should
+ // always be the case when AT clients access a table.
+ // https://bugs.webkit.org/show_bug.cgi?id=42652
+ return axObjectCache()->get(toRenderTableCell(m_renderer)->table());
}
bool AccessibilityTableCell::isTableCell() const
diff --git a/WebCore/accessibility/AccessibilityTableColumn.cpp b/WebCore/accessibility/AccessibilityTableColumn.cpp
index 5872706..45137ff 100644
--- a/WebCore/accessibility/AccessibilityTableColumn.cpp
+++ b/WebCore/accessibility/AccessibilityTableColumn.cpp
@@ -130,6 +130,9 @@ AccessibilityObject* AccessibilityTableColumn::headerObjectForSection(RenderTabl
if (m_columnIndex >= numCols)
return 0;
+ if (!section->numRows())
+ return 0;
+
RenderTableCell* cell = 0;
// also account for cells that have a span
for (int testCol = m_columnIndex; testCol >= 0; --testCol) {