Esempio n. 1
0
nsresult
nsARIAGridCellAccessible::GetARIAState(PRUint32 *aState, PRUint32 *aExtraState)
{
  nsresult rv = nsHyperTextAccessibleWrap::GetARIAState(aState, aExtraState);
  NS_ENSURE_SUCCESS(rv, rv);

  // Return if the gridcell has aria-selected="true".
  if (*aState & nsIAccessibleStates::STATE_SELECTED)
    return NS_OK;

  // Check aria-selected="true" on the row.
  nsCOMPtr<nsIAccessible> row;
  GetParent(getter_AddRefs(row));
  if (nsAccUtils::Role(row) != nsIAccessibleRole::ROLE_ROW)
    return NS_OK;

  nsRefPtr<nsAccessible> acc = nsAccUtils::QueryAccessible(row);
  nsCOMPtr<nsIDOMNode> rowNode;
  acc->GetDOMNode(getter_AddRefs(rowNode));
  NS_ENSURE_STATE(rowNode);

  nsCOMPtr<nsIContent> rowContent(do_QueryInterface(rowNode));
  if (nsAccUtils::HasDefinedARIAToken(rowContent,
                                      nsAccessibilityAtoms::aria_selected) &&
      !rowContent->AttrValueIs(kNameSpaceID_None,
                               nsAccessibilityAtoms::aria_selected,
                               nsAccessibilityAtoms::_false, eCaseMatters)) {

    *aState |= nsIAccessibleStates::STATE_SELECTABLE |
      nsIAccessibleStates::STATE_SELECTED;
  }

  return NS_OK;
}
Esempio n. 2
0
NS_IMETHODIMP
nsHTMLTableAccessible::IsProbablyForLayout(PRBool *aIsProbablyForLayout)
{
  // Implement a heuristic to determine if table is most likely used for layout
  // XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells
  // at the beginning or end of a row/col, and especially when they occur at the edge of a table?
  // XXX expose this info via object attributes to AT-SPI

  // XXX For now debugging descriptions are always on via SHOW_LAYOUT_HEURISTIC
  // This will allow release trunk builds to be used by testers to refine the algorithm
  // Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release
#ifdef SHOW_LAYOUT_HEURISTIC
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \
  { *aIsProbablyForLayout = isLayout; \
    mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \
    mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; }
#else
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; }
#endif

  *aIsProbablyForLayout = PR_FALSE;

  if (IsDefunct())
    return NS_ERROR_FAILURE;

  nsDocAccessible *docAccessible = GetDocAccessible();
  if (docAccessible) {
    PRUint32 state, extState;
    docAccessible->GetState(&state, &extState);
    if (extState & nsIAccessibleStates::EXT_STATE_EDITABLE) {  // Need to see all elements while document is being edited
      RETURN_LAYOUT_ANSWER(PR_FALSE, "In editable document");
    }
  }

  // Check to see if an ARIA role overrides the role from native markup,
  // but for which we still expose table semantics (treegrid, for example).
  PRBool hasNonTableRole =
    (nsAccUtils::Role(this) != nsIAccessibleRole::ROLE_TABLE);
  if (hasNonTableRole) {
    RETURN_LAYOUT_ANSWER(PR_FALSE, "Has role attribute");
  }

  if (mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::role)) {
    // Role attribute is present, but overridden roles have already been dealt with.
    // Only landmarks and other roles that don't override the role from native
    // markup are left to deal with here.
    RETURN_LAYOUT_ANSWER(PR_FALSE, "Has role attribute, weak role, and role is table");
  }
  
  // Check for legitimate data table elements or attributes
  nsAutoString summary;
  if ((mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::summary, summary) &&
       !summary.IsEmpty()) || 
      HasDescendant(NS_LITERAL_STRING("caption"), PR_FALSE) ||
      HasDescendant(NS_LITERAL_STRING("th")) ||
      HasDescendant(NS_LITERAL_STRING("thead")) ||
      HasDescendant(NS_LITERAL_STRING("tfoot")) ||
      HasDescendant(NS_LITERAL_STRING("colgroup"))) {
    RETURN_LAYOUT_ANSWER(PR_FALSE, "Has caption, summary, th, thead, tfoot or colgroup -- legitimate table structures");
  }
  if (HasDescendant(NS_LITERAL_STRING("table"))) {
    RETURN_LAYOUT_ANSWER(PR_TRUE, "Has a nested table within it");
  }
  
  // If only 1 column or only 1 row, it's for layout
  PRInt32 columns, rows;
  GetColumnCount(&columns);
  if (columns <=1) {
    RETURN_LAYOUT_ANSWER(PR_TRUE, "Has only 1 column");
  }
  GetRowCount(&rows);
  if (rows <=1) {
    RETURN_LAYOUT_ANSWER(PR_TRUE, "Has only 1 row");
  }

  // Check for many columns
  if (columns >= 5) {
    RETURN_LAYOUT_ANSWER(PR_FALSE, ">=5 columns");
  }
  
  // Now we know there are 2-4 columns and 2 or more rows
  // Check to see if there are visible borders on the cells
  // XXX currently, we just check the first cell -- do we really need to do more?
  nsCOMPtr<nsIDOMElement> cellElement;
  nsresult rv = GetCellAt(0, 0, *getter_AddRefs(cellElement));
  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);

  nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
  NS_ENSURE_TRUE(cellContent, NS_ERROR_FAILURE);
  nsIFrame *cellFrame = cellContent->GetPrimaryFrame();
  if (!cellFrame) {
    return NS_OK;
  }
  nsMargin border;
  cellFrame->GetBorder(border);
  if (border.top && border.bottom && border.left && border.right) {
    RETURN_LAYOUT_ANSWER(PR_FALSE, "Has nonzero border-width on table cell");
  }

  /**
   * Rules for non-bordered tables with 2-4 columns and 2+ rows from here on forward
   */

  // Check for styled background color across the row
  // Alternating background color is a common way 
  nsCOMPtr<nsIDOMNodeList> nodeList;
  nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));    
  tableElt->GetElementsByTagName(NS_LITERAL_STRING("tr"), getter_AddRefs(nodeList));
  NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
  PRUint32 length;
  nodeList->GetLength(&length);
  nsAutoString color, lastRowColor;
  for (PRUint32 rowCount = 0; rowCount < length; rowCount ++) {
    nsCOMPtr<nsIDOMNode> rowNode;
    nodeList->Item(rowCount, getter_AddRefs(rowNode));
    nsCOMPtr<nsIContent> rowContent(do_QueryInterface(rowNode));

    nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
      nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), rowContent);
    NS_ENSURE_TRUE(styleDecl, NS_ERROR_FAILURE);

    lastRowColor = color;
    styleDecl->GetPropertyValue(NS_LITERAL_STRING("background-color"), color);
    if (rowCount > 0 && PR_FALSE == lastRowColor.Equals(color)) {
      RETURN_LAYOUT_ANSWER(PR_FALSE, "2 styles of row background color, non-bordered");
    }
  }

  // Check for many rows
  const PRInt32 kMaxLayoutRows = 20;
  if (rows > kMaxLayoutRows) { // A ton of rows, this is probably for data
    RETURN_LAYOUT_ANSWER(PR_FALSE, ">= kMaxLayoutRows (20) and non-bordered");
  }

  // Check for very wide table
  nsAutoString styledWidth;
  GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("width"), styledWidth);
  if (styledWidth.EqualsLiteral("100%")) {
    RETURN_LAYOUT_ANSWER(PR_TRUE, "<=4 columns and 100% width");
  }
  if (styledWidth.Find(NS_LITERAL_STRING("px"))) { // Hardcoded in pixels
    nsIFrame *tableFrame = GetFrame();
    NS_ENSURE_TRUE(tableFrame , NS_ERROR_FAILURE);
    nsSize tableSize  = tableFrame->GetSize();

    nsDocAccessible *docAccessible = GetDocAccessible();
    NS_ENSURE_TRUE(docAccessible, NS_ERROR_FAILURE);
    nsIFrame *docFrame = docAccessible->GetFrame();
    NS_ENSURE_TRUE(docFrame , NS_ERROR_FAILURE);

    nsSize docSize = docFrame->GetSize();
    if (docSize.width > 0) {
      PRInt32 percentageOfDocWidth = (100 * tableSize.width) / docSize.width;
      if (percentageOfDocWidth > 95) {
        // 3-4 columns, no borders, not a lot of rows, and 95% of the doc's width
        // Probably for layout
        RETURN_LAYOUT_ANSWER(PR_TRUE, "<=4 columns, width hardcoded in pixels and 95% of document width");
      }
    }
  }

  // Two column rules
  if (rows * columns <= 10) {
    RETURN_LAYOUT_ANSWER(PR_TRUE, "2-4 columns, 10 cells or less, non-bordered");
  }

  if (HasDescendant(NS_LITERAL_STRING("embed")) ||
      HasDescendant(NS_LITERAL_STRING("object")) ||
      HasDescendant(NS_LITERAL_STRING("applet")) ||
      HasDescendant(NS_LITERAL_STRING("iframe"))) {
    RETURN_LAYOUT_ANSWER(PR_TRUE, "Has no borders, and has iframe, object, applet or iframe, typical of advertisements");
  }

  RETURN_LAYOUT_ANSWER(PR_FALSE, "no layout factor strong enough, so will guess data");
}