1/* 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30#include "AccessibilityTableCell.h" 31 32#include "AXObjectCache.h" 33#include "HTMLNames.h" 34#include "RenderObject.h" 35#include "RenderTableCell.h" 36 37using namespace std; 38 39namespace WebCore { 40 41using namespace HTMLNames; 42 43AccessibilityTableCell::AccessibilityTableCell(RenderObject* renderer) 44 : AccessibilityRenderObject(renderer) 45{ 46} 47 48AccessibilityTableCell::~AccessibilityTableCell() 49{ 50} 51 52PassRefPtr<AccessibilityTableCell> AccessibilityTableCell::create(RenderObject* renderer) 53{ 54 return adoptRef(new AccessibilityTableCell(renderer)); 55} 56 57bool AccessibilityTableCell::computeAccessibilityIsIgnored() const 58{ 59 AccessibilityObjectInclusion decision = defaultObjectInclusion(); 60 if (decision == IncludeObject) 61 return false; 62 if (decision == IgnoreObject) 63 return true; 64 65 if (!isTableCell()) 66 return AccessibilityRenderObject::computeAccessibilityIsIgnored(); 67 68 return false; 69} 70 71AccessibilityObject* AccessibilityTableCell::parentTable() const 72{ 73 if (!m_renderer || !m_renderer->isTableCell()) 74 return 0; 75 76 // If the document no longer exists, we might not have an axObjectCache. 77 if (!axObjectCache()) 78 return 0; 79 80 // Do not use getOrCreate. parentTable() can be called while the render tree is being modified 81 // by javascript, and creating a table element may try to access the render tree while in a bad state. 82 // By using only get() implies that the AXTable must be created before AXTableCells. This should 83 // always be the case when AT clients access a table. 84 // https://bugs.webkit.org/show_bug.cgi?id=42652 85 return axObjectCache()->get(toRenderTableCell(m_renderer)->table()); 86} 87 88bool AccessibilityTableCell::isTableCell() const 89{ 90 AccessibilityObject* parent = parentObjectUnignored(); 91 if (!parent || !parent->isTableRow()) 92 return false; 93 94 return true; 95} 96 97AccessibilityRole AccessibilityTableCell::determineAccessibilityRole() 98{ 99 // Always call determineAccessibleRole so that the ARIA role is set. 100 // Even though this object reports a Cell role, the ARIA role will be used 101 // to determine if it's a column header. 102 AccessibilityRole defaultRole = AccessibilityRenderObject::determineAccessibilityRole(); 103 if (!isTableCell()) 104 return defaultRole; 105 106 return CellRole; 107} 108 109void AccessibilityTableCell::rowIndexRange(pair<unsigned, unsigned>& rowRange) 110{ 111 if (!m_renderer || !m_renderer->isTableCell()) 112 return; 113 114 RenderTableCell* renderCell = toRenderTableCell(m_renderer); 115 rowRange.first = renderCell->rowIndex(); 116 rowRange.second = renderCell->rowSpan(); 117 118 // since our table might have multiple sections, we have to offset our row appropriately 119 RenderTableSection* section = renderCell->section(); 120 RenderTable* table = renderCell->table(); 121 if (!table || !section) 122 return; 123 124 RenderTableSection* tableSection = table->topSection(); 125 unsigned rowOffset = 0; 126 while (tableSection) { 127 if (tableSection == section) 128 break; 129 rowOffset += tableSection->numRows(); 130 tableSection = table->sectionBelow(tableSection, SkipEmptySections); 131 } 132 133 rowRange.first += rowOffset; 134} 135 136void AccessibilityTableCell::columnIndexRange(pair<unsigned, unsigned>& columnRange) 137{ 138 if (!m_renderer || !m_renderer->isTableCell()) 139 return; 140 141 RenderTableCell* renderCell = toRenderTableCell(m_renderer); 142 columnRange.first = renderCell->col(); 143 columnRange.second = renderCell->colSpan(); 144} 145 146AccessibilityObject* AccessibilityTableCell::titleUIElement() const 147{ 148 // Try to find if the first cell in this row is a <th>. If it is, 149 // then it can act as the title ui element. (This is only in the 150 // case when the table is not appearing as an AXTable.) 151 if (isTableCell() || !m_renderer || !m_renderer->isTableCell()) 152 return 0; 153 154 // Table cells that are th cannot have title ui elements, since by definition 155 // they are title ui elements 156 Node* node = m_renderer->node(); 157 if (node && node->hasTagName(thTag)) 158 return 0; 159 160 RenderTableCell* renderCell = toRenderTableCell(m_renderer); 161 162 // If this cell is in the first column, there is no need to continue. 163 int col = renderCell->col(); 164 if (!col) 165 return 0; 166 167 int row = renderCell->rowIndex(); 168 169 RenderTableSection* section = renderCell->section(); 170 if (!section) 171 return 0; 172 173 RenderTableCell* headerCell = section->primaryCellAt(row, 0); 174 if (!headerCell || headerCell == renderCell) 175 return 0; 176 177 Node* cellElement = headerCell->node(); 178 if (!cellElement || !cellElement->hasTagName(thTag)) 179 return 0; 180 181 return axObjectCache()->getOrCreate(headerCell); 182} 183 184} // namespace WebCore 185