summaryrefslogtreecommitdiff
path: root/Source/WebCore/accessibility/AccessibilityTableColumn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/accessibility/AccessibilityTableColumn.cpp')
-rw-r--r--Source/WebCore/accessibility/AccessibilityTableColumn.cpp137
1 files changed, 84 insertions, 53 deletions
diff --git a/Source/WebCore/accessibility/AccessibilityTableColumn.cpp b/Source/WebCore/accessibility/AccessibilityTableColumn.cpp
index 6791c3320..1669a6fc0 100644
--- a/Source/WebCore/accessibility/AccessibilityTableColumn.cpp
+++ b/Source/WebCore/accessibility/AccessibilityTableColumn.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -31,6 +31,8 @@
#include "AXObjectCache.h"
#include "AccessibilityTableCell.h"
+#include "HTMLCollection.h"
+#include "HTMLElement.h"
#include "HTMLNames.h"
#include "RenderTable.h"
#include "RenderTableCell.h"
@@ -48,9 +50,9 @@ AccessibilityTableColumn::~AccessibilityTableColumn()
{
}
-PassRefPtr<AccessibilityTableColumn> AccessibilityTableColumn::create()
+Ref<AccessibilityTableColumn> AccessibilityTableColumn::create()
{
- return adoptRef(new AccessibilityTableColumn());
+ return adoptRef(*new AccessibilityTableColumn());
}
void AccessibilityTableColumn::setParent(AccessibilityObject* parent)
@@ -62,88 +64,115 @@ void AccessibilityTableColumn::setParent(AccessibilityObject* parent)
LayoutRect AccessibilityTableColumn::elementRect() const
{
- // this will be filled in when addChildren is called
- return m_columnRect;
+ // This used to be cached during the call to addChildren(), but calling elementRect()
+ // can invalidate elements, so its better to ask for this on demand.
+ LayoutRect columnRect;
+ AccessibilityChildrenVector childrenCopy = m_children;
+ for (const auto& cell : childrenCopy)
+ columnRect.unite(cell->elementRect());
+
+ return columnRect;
}
AccessibilityObject* AccessibilityTableColumn::headerObject()
{
if (!m_parent)
- return 0;
+ return nullptr;
RenderObject* renderer = m_parent->renderer();
if (!renderer)
- return 0;
-
- if (!m_parent->isAccessibilityTable())
- return 0;
+ return nullptr;
+ if (!is<AccessibilityTable>(*m_parent))
+ return nullptr;
+
+ auto& parentTable = downcast<AccessibilityTable>(*m_parent);
+ if (!parentTable.isExposableThroughAccessibility())
+ return nullptr;
- AccessibilityTable* parentTable = toAccessibilityTable(m_parent);
- if (parentTable->isAriaTable()) {
+ if (parentTable.isAriaTable()) {
for (const auto& cell : children()) {
if (cell->ariaRoleAttribute() == ColumnHeaderRole)
return cell.get();
}
- return 0;
+ return nullptr;
}
- if (!renderer->isTable())
- return 0;
+ if (!is<RenderTable>(*renderer))
+ return nullptr;
- RenderTable* table = toRenderTable(renderer);
-
- AccessibilityObject* headerObject = 0;
-
- // try the <thead> section first. this doesn't require th tags
- headerObject = headerObjectForSection(table->header(), false);
+ RenderTable& table = downcast<RenderTable>(*renderer);
- if (headerObject)
+ // try the <thead> section first. this doesn't require th tags
+ if (auto* headerObject = headerObjectForSection(table.header(), false))
return headerObject;
- // now try for <th> tags in the first body
- headerObject = headerObjectForSection(table->firstBody(), true);
-
- return headerObject;
+ RenderTableSection* bodySection = table.firstBody();
+ while (bodySection && bodySection->isAnonymous())
+ bodySection = table.sectionBelow(bodySection, SkipEmptySections);
+
+ // now try for <th> tags in the first body. If the first body is
+ return headerObjectForSection(bodySection, true);
}
AccessibilityObject* AccessibilityTableColumn::headerObjectForSection(RenderTableSection* section, bool thTagRequired)
{
if (!section)
- return 0;
+ return nullptr;
unsigned numCols = section->numColumns();
if (m_columnIndex >= numCols)
- return 0;
+ return nullptr;
if (!section->numRows())
- return 0;
+ return nullptr;
- RenderTableCell* cell = 0;
+ RenderTableCell* cell = nullptr;
// also account for cells that have a span
for (int testCol = m_columnIndex; testCol >= 0; --testCol) {
- RenderTableCell* testCell = section->primaryCellAt(0, testCol);
- if (!testCell)
- continue;
- // we've reached a cell that doesn't even overlap our column
- // it can't be our header
- if ((testCell->col() + (testCell->colSpan()-1)) < m_columnIndex)
+ // Run down the rows in case initial rows are invalid (like when a <caption> is used).
+ unsigned rowCount = section->numRows();
+ for (unsigned testRow = 0; testRow < rowCount; testRow++) {
+ RenderTableCell* testCell = section->primaryCellAt(testRow, testCol);
+ // No cell at this index, keep checking more rows and columns.
+ if (!testCell)
+ continue;
+
+ // If we've reached a cell that doesn't even overlap our column it can't be the header.
+ if ((testCell->col() + (testCell->colSpan()-1)) < m_columnIndex)
+ break;
+
+ Node* testCellNode = testCell->element();
+ // If the RenderTableCell doesn't have an element because its anonymous,
+ // try to see if we can find the original cell element to check if it has a <th> tag.
+ if (!testCellNode && testCell->isAnonymous()) {
+ if (Element* parentElement = testCell->parent() ? testCell->parent()->element() : nullptr) {
+ if (parentElement->hasTagName(trTag) && testCol < static_cast<int>(parentElement->countChildNodes()))
+ testCellNode = parentElement->traverseToChildAt(testCol);
+ }
+ }
+
+ if (!testCellNode)
+ continue;
+
+ // If th is required, but we found an element that doesn't have a th tag, we can stop looking.
+ if (thTagRequired && !testCellNode->hasTagName(thTag))
+ break;
+
+ cell = testCell;
break;
-
- if (!testCell->element())
- continue;
-
- if (thTagRequired && !testCell->element()->hasTagName(thTag))
- continue;
-
- cell = testCell;
+ }
}
if (!cell)
- return 0;
+ return nullptr;
- return axObjectCache()->getOrCreate(cell);
+ auto* cellObject = axObjectCache()->getOrCreate(cell);
+ if (!cellObject || cellObject->accessibilityIsIgnored())
+ return nullptr;
+
+ return cellObject;
}
bool AccessibilityTableColumn::computeAccessibilityIsIgnored() const
@@ -151,7 +180,7 @@ bool AccessibilityTableColumn::computeAccessibilityIsIgnored() const
if (!m_parent)
return true;
-#if PLATFORM(IOS) || PLATFORM(GTK) || PLATFORM(EFL)
+#if PLATFORM(IOS) || PLATFORM(GTK)
return true;
#endif
@@ -163,14 +192,17 @@ void AccessibilityTableColumn::addChildren()
ASSERT(!m_haveChildren);
m_haveChildren = true;
- if (!m_parent || !m_parent->isAccessibilityTable())
+ if (!is<AccessibilityTable>(m_parent))
+ return;
+
+ auto& parentTable = downcast<AccessibilityTable>(*m_parent);
+ if (!parentTable.isExposableThroughAccessibility())
return;
- AccessibilityTable* parentTable = toAccessibilityTable(m_parent);
- int numRows = parentTable->rowCount();
+ int numRows = parentTable.rowCount();
- for (int i = 0; i < numRows; i++) {
- AccessibilityTableCell* cell = parentTable->cellForColumnAndRow(m_columnIndex, i);
+ for (int i = 0; i < numRows; ++i) {
+ AccessibilityTableCell* cell = parentTable.cellForColumnAndRow(m_columnIndex, i);
if (!cell)
continue;
@@ -179,7 +211,6 @@ void AccessibilityTableColumn::addChildren()
continue;
m_children.append(cell);
- m_columnRect.unite(cell->elementRect());
}
}