NS_IMETHODIMP
nsXULTabpanelAccessible::GetRelationByType(PRUint32 aRelationType,
                                           nsIAccessibleRelation **aRelation)
{
  nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType, aRelation);
  NS_ENSURE_SUCCESS(rv, rv);

  if (aRelationType != nsIAccessibleRelation::RELATION_LABELLED_BY)
    return NS_OK;

  // Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible.
  nsCOMPtr<nsIDOMXULRelatedElement> tabpanelsElm =
    do_QueryInterface(mContent->GetParent());
  if (!tabpanelsElm)
    return NS_OK;

  nsCOMPtr<nsIDOMNode> DOMNode(GetDOMNode());
  nsCOMPtr<nsIDOMNode> tabNode;
  tabpanelsElm->GetRelatedElement(DOMNode, getter_AddRefs(tabNode));
  if (!tabNode)
    return NS_OK;

  nsCOMPtr<nsIContent> tabContent(do_QueryInterface(tabNode));
  return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
                                          tabContent);
}
NS_IMETHODIMP
nsXULTabpanelAccessible::GetRelationByType(PRUint32 aRelationType,
                                           nsIAccessibleRelation **aRelation)
{
  nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType, aRelation);
  NS_ENSURE_SUCCESS(rv, rv);

  if (aRelationType != nsIAccessibleRelation::RELATION_LABELLED_BY)
    return NS_OK;

  // Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible.
  nsCOMPtr<nsIAccessible> tabBoxAcc;
  GetParent(getter_AddRefs(tabBoxAcc));
  NS_ENSURE_TRUE(nsAccUtils::Role(tabBoxAcc) == nsIAccessibleRole::ROLE_PANE,
                 NS_ERROR_FAILURE);

  PRInt32 tabpanelIndex = -1;
  nsCOMPtr<nsIAccessible> tabsAcc;

  PRBool isTabpanelFound = PR_FALSE;
  nsCOMPtr<nsIAccessible> childAcc;
  tabBoxAcc->GetFirstChild(getter_AddRefs(childAcc));
  while (childAcc && (!tabsAcc || !isTabpanelFound)) {
    if (nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PAGETABLIST)
      tabsAcc = childAcc;

    if (!isTabpanelFound &&
        nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PROPERTYPAGE)
      tabpanelIndex++;

    if (childAcc == this)
      isTabpanelFound = PR_TRUE;

    nsCOMPtr<nsIAccessible> acc;
    childAcc->GetNextSibling(getter_AddRefs(acc));
    childAcc.swap(acc);
  }

  if (!tabsAcc || tabpanelIndex == -1)
    return NS_OK;

  nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
  nsIAtom *atomID = content->GetID();

  nsCOMPtr<nsIAccessible> foundTabAcc;
  tabsAcc->GetFirstChild(getter_AddRefs(childAcc));
  while (childAcc) {
    if (nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PAGETAB) {
      if (atomID) {
        nsCOMPtr<nsIAccessNode> tabAccNode(do_QueryInterface(childAcc));
        nsCOMPtr<nsIDOMNode> tabNode;
        tabAccNode->GetDOMNode(getter_AddRefs(tabNode));
        nsCOMPtr<nsIContent> tabContent(do_QueryInterface(tabNode));
        NS_ENSURE_TRUE(tabContent, NS_ERROR_FAILURE);

        if (tabContent->AttrValueIs(kNameSpaceID_None,
                                    nsAccessibilityAtoms::linkedPanel, atomID,
                                    eCaseMatters)) {
          return nsRelUtils::AddTarget(aRelationType, aRelation, childAcc);
        }
      }

      if (tabpanelIndex == 0) {
        foundTabAcc = childAcc;
        if (!atomID)
          break;
      }

      tabpanelIndex--;
    }

    nsCOMPtr<nsIAccessible> acc;
    childAcc->GetNextSibling(getter_AddRefs(acc));
    childAcc.swap(acc);
  }

  return nsRelUtils::AddTarget(aRelationType, aRelation, foundTabAcc);
}