<commit_before>/*
 * Copyright (C) 2008 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 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
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "modules/accessibility/AXTableCell.h"

#include "core/layout/LayoutTableCell.h"
#include "modules/accessibility/AXObjectCacheImpl.h"


namespace blink {

using namespace HTMLNames;

AXTableCell::AXTableCell(LayoutObject* layoutObject, AXObjectCacheImpl* axObjectCache)
    : AXLayoutObject(layoutObject, axObjectCache)
{
}

AXTableCell::~AXTableCell()
{
}

PassRefPtr<AXTableCell> AXTableCell::create(LayoutObject* layoutObject, AXObjectCacheImpl* axObjectCache)
{
    return adoptRef(new AXTableCell(layoutObject, axObjectCache));
}

bool AXTableCell::isTableHeaderCell() const
{
    return node() && node()->hasTagName(thTag);
}

bool AXTableCell::isRowHeaderCell() const
{
    const AtomicString& scope = getAttribute(scopeAttr);
    return equalIgnoringCase(scope, "row") || equalIgnoringCase(scope, "rowgroup");
}

bool AXTableCell::isColumnHeaderCell() const
{
    const AtomicString& scope = getAttribute(scopeAttr);
    return equalIgnoringCase(scope, "col") || equalIgnoringCase(scope, "colgroup");
}

bool AXTableCell::computeAccessibilityIsIgnored() const
{
    AXObjectInclusion decision = defaultObjectInclusion();
    if (decision == IncludeObject)
        return false;
    if (decision == IgnoreObject)
        return true;

    if (!isTableCell())
        return AXLayoutObject::computeAccessibilityIsIgnored();

    return false;
}

AXObject* AXTableCell::parentTable() const
{
    if (!m_layoutObject || !m_layoutObject->isTableCell())
        return 0;

    // If the document no longer exists, we might not have an axObjectCache.
    if (!axObjectCache())
        return 0;

    // Do not use getOrCreate. parentTable() can be called while the layout tree is being modified
    // by javascript, and creating a table element may try to access the layout 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(toLayoutTableCell(m_layoutObject)->table());
}

bool AXTableCell::isTableCell() const
{
    AXObject* parent = parentObjectUnignored();
    if (!parent || !parent->isTableRow())
        return false;

    return true;
}

static AccessibilityRole decideRoleFromSibling(Node* siblingNode)
{
    if (!siblingNode)
        return CellRole;
    if (siblingNode->hasTagName(thTag))
        return ColumnHeaderRole;
    if (siblingNode->hasTagName(tdTag))
        return RowHeaderRole;
    return CellRole;
}

AccessibilityRole AXTableCell::scanToDecideHeaderRole()
{
    if (!isTableHeaderCell())
        return CellRole;

    // Check scope attribute first.
    if (isRowHeaderCell())
        return RowHeaderRole;

    if (isColumnHeaderCell())
        return ColumnHeaderRole;

    // Check the previous cell and the next cell on the same row.
    LayoutTableCell* layoutCell = toLayoutTableCell(m_layoutObject);
    AccessibilityRole headerRole = CellRole;

    // if header is preceded by header cells on the same row, then it is a
    // column header. If it is preceded by other cells then it's a row header.
    if (LayoutTableCell* cell = layoutCell->previousCell()) {
        Node* siblingNode = cell->node();
        headerRole = decideRoleFromSibling(siblingNode);
        if (headerRole != CellRole)
            return headerRole;
    }
    // if header is followed by header cells on the same row, then it is a
    // column header. If it is followed by other cells then it's a row header.
    if (LayoutTableCell* cell = layoutCell->nextCell()) {
        Node* siblingNode = cell->node();
        headerRole = decideRoleFromSibling(siblingNode);
        if (headerRole != CellRole)
            return headerRole;
    }
    // If there are no other cells on that row, then it is a column header.
    return ColumnHeaderRole;
}

AccessibilityRole AXTableCell::determineAccessibilityRole()
{
    if (!isTableCell())
        return AXLayoutObject::determineAccessibilityRole();

    return scanToDecideHeaderRole();
}

void AXTableCell::rowIndexRange(pair<unsigned, unsigned>& rowRange)
{
    if (!m_layoutObject || !m_layoutObject->isTableCell())
        return;
<commit_msg>Slightly upgrade decideRoleFromSibling() in AXTableCell<commit_after>/*
 * Copyright (C) 2008 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 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
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "modules/accessibility/AXTableCell.h"

#include "core/layout/LayoutTableCell.h"
#include "modules/accessibility/AXObjectCacheImpl.h"


namespace blink {

using namespace HTMLNames;

AXTableCell::AXTableCell(LayoutObject* layoutObject, AXObjectCacheImpl* axObjectCache)
    : AXLayoutObject(layoutObject, axObjectCache)
{
}

AXTableCell::~AXTableCell()
{
}

PassRefPtr<AXTableCell> AXTableCell::create(LayoutObject* layoutObject, AXObjectCacheImpl* axObjectCache)
{
    return adoptRef(new AXTableCell(layoutObject, axObjectCache));
}

bool AXTableCell::isTableHeaderCell() const
{
    return node() && node()->hasTagName(thTag);
}

bool AXTableCell::isRowHeaderCell() const
{
    const AtomicString& scope = getAttribute(scopeAttr);
    return equalIgnoringCase(scope, "row") || equalIgnoringCase(scope, "rowgroup");
}

bool AXTableCell::isColumnHeaderCell() const
{
    const AtomicString& scope = getAttribute(scopeAttr);
    return equalIgnoringCase(scope, "col") || equalIgnoringCase(scope, "colgroup");
}

bool AXTableCell::computeAccessibilityIsIgnored() const
{
    AXObjectInclusion decision = defaultObjectInclusion();
    if (decision == IncludeObject)
        return false;
    if (decision == IgnoreObject)
        return true;

    if (!isTableCell())
        return AXLayoutObject::computeAccessibilityIsIgnored();

    return false;
}

AXObject* AXTableCell::parentTable() const
{
    if (!m_layoutObject || !m_layoutObject->isTableCell())
        return 0;

    // If the document no longer exists, we might not have an axObjectCache.
    if (!axObjectCache())
        return 0;

    // Do not use getOrCreate. parentTable() can be called while the layout tree is being modified
    // by javascript, and creating a table element may try to access the layout 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(toLayoutTableCell(m_layoutObject)->table());
}

bool AXTableCell::isTableCell() const
{
    AXObject* parent = parentObjectUnignored();
    if (!parent || !parent->isTableRow())
        return false;

    return true;
}

static AccessibilityRole decideRoleFromSibling(LayoutTableCell* siblingCell)
{
    if (!siblingCell)
        return CellRole;

    if (Node* siblingNode = siblingCell->node()) {
        if (siblingNode->hasTagName(thTag))
            return ColumnHeaderRole;
        if (siblingNode->hasTagName(tdTag))
            return RowHeaderRole;
    }

    return CellRole;
}

AccessibilityRole AXTableCell::scanToDecideHeaderRole()
{
    if (!isTableHeaderCell())
        return CellRole;

    // Check scope attribute first.
    if (isRowHeaderCell())
        return RowHeaderRole;

    if (isColumnHeaderCell())
        return ColumnHeaderRole;

    // Check the previous cell and the next cell on the same row.
    LayoutTableCell* layoutCell = toLayoutTableCell(m_layoutObject);
    AccessibilityRole headerRole = CellRole;

    // if header is preceded by header cells on the same row, then it is a
    // column header. If it is preceded by other cells then it's a row header.
    if ((headerRole = decideRoleFromSibling(layoutCell->previousCell())) != CellRole)
        return headerRole;

    // if header is followed by header cells on the same row, then it is a
    // column header. If it is followed by other cells then it's a row header.
    if ((headerRole = decideRoleFromSibling(layoutCell->nextCell())) != CellRole)
        return headerRole;

    // If there are no other cells on that row, then it is a column header.
    return ColumnHeaderRole;
}

AccessibilityRole AXTableCell::determineAccessibilityRole()
{
    if (!isTableCell())
        return AXLayoutObject::determineAccessibilityRole();

    return scanToDecideHeaderRole();
}

void AXTableCell::rowIndexRange(pair<unsigned, unsigned>& rowRange)
{
    if (!m_layoutObject || !m_layoutObject->isTableCell())
        return;

{'fraction_non_alphanumeric': 0.08542279093895902, 'fraction_numerical': 0.0024208888120352758, 'mean_word_length': 3.9116772823779193, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 30, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5537661', 'n_tokens_mistral': 3287, 'n_tokens_neox': 3081, 'n_words': 1146}