nsresult
nsTextEquivUtils::AppendTextEquivFromContent(nsAccessible *aInitiatorAcc,
                                             nsIContent *aContent,
                                             nsAString *aString)
{
  // Prevent recursion which can cause infinite loops.
  if (gInitiatorAcc)
    return NS_OK;

  gInitiatorAcc = aInitiatorAcc;

  // If the given content is not visible or isn't accessible then go down
  // through the DOM subtree otherwise go down through accessible subtree and
  // calculate the flat string.
  nsIFrame *frame = aContent->GetPrimaryFrame();
  bool isVisible = frame && frame->GetStyleVisibility()->IsVisible();

  nsresult rv = NS_ERROR_FAILURE;
  bool goThroughDOMSubtree = true;

  if (isVisible) {
    nsAccessible* accessible =
      gInitiatorAcc->Document()->GetAccessible(aContent);
    if (accessible) {
      rv = AppendFromAccessible(accessible, aString);
      goThroughDOMSubtree = false;
    }
  }

  if (goThroughDOMSubtree)
    rv = AppendFromDOMNode(aContent, aString);

  gInitiatorAcc = nsnull;
  return rv;
}
nsresult
nsTextEquivUtils::AppendFromAccessibleChildren(nsAccessible *aAccessible,
                                               nsAString *aString)
{
  nsresult rv = NS_OK_NO_NAME_CLAUSE_HANDLED;

  PRInt32 childCount = aAccessible->GetChildCount();
  for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
    nsAccessible *child = aAccessible->GetChildAt(childIdx);
    rv = AppendFromAccessible(child, aString);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  return rv;
}
nsresult
nsTextEquivUtils::AppendFromAccessibleChildren(nsIAccessible *aAccessible,
                                               nsAString *aString)
{
  nsCOMPtr<nsIAccessible> accChild, accNextChild;
  aAccessible->GetFirstChild(getter_AddRefs(accChild));

  nsresult rv = NS_OK_NO_NAME_CLAUSE_HANDLED;
  while (accChild) {
    rv = AppendFromAccessible(accChild, aString);
    NS_ENSURE_SUCCESS(rv, rv);

    accChild->GetNextSibling(getter_AddRefs(accNextChild));
    accChild.swap(accNextChild);
  }

  return rv;
}
nsresult
nsTextEquivUtils::AppendTextEquivFromContent(nsIAccessible *aInitiatorAcc,
                                             nsIContent *aContent,
                                             nsAString *aString)
{
  // Prevent recursion which can cause infinite loops.
  if (gInitiatorAcc)
    return NS_OK;

  gInitiatorAcc = aInitiatorAcc;

  nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(aContent));
  nsCOMPtr<nsIPresShell> shell = nsCoreUtils::GetPresShellFor(DOMNode);
  if (!shell) {
    NS_ASSERTION(PR_TRUE, "There is no presshell!");
    gInitiatorAcc = nsnull;
    return NS_ERROR_UNEXPECTED;
  }

  // If the given content is not visible or isn't accessible then go down
  // through the DOM subtree otherwise go down through accessible subtree and
  // calculate the flat string.
  nsIFrame *frame = aContent->GetPrimaryFrame();
  PRBool isVisible = frame && frame->GetStyleVisibility()->IsVisible();

  nsresult rv = NS_ERROR_FAILURE;
  PRBool goThroughDOMSubtree = PR_TRUE;

  if (isVisible) {
    nsAccessible *accessible =
      GetAccService()->GetAccessibleInShell(DOMNode, shell);
    if (accessible) {
      rv = AppendFromAccessible(accessible, aString);
      goThroughDOMSubtree = PR_FALSE;
    }
  }

  if (goThroughDOMSubtree)
    rv = AppendFromDOMNode(aContent, aString);

  gInitiatorAcc = nsnull;
  return rv;
}