Bug 421066 - Implement all nsIAccessibleHyperLink methods for XUL:label elements that are used as links, r=ginn.chen, a=beltzner

This commit is contained in:
surkov.alexander@gmail.com 2008-03-18 04:37:12 -07:00
parent fec1f1442c
commit e4e19beac8
8 changed files with 435 additions and 227 deletions

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* John Gaunt (jgaunt@netscape.com)
* Alexander Surkov <surkov.alexander@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -93,11 +94,11 @@ nsLeafAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
return NS_OK;
}
//----------------
////////////////////////////////////////////////////////////////////////////////
// nsLinkableAccessible
//----------------
nsLinkableAccessible::nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
nsLinkableAccessible::
nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
nsHyperTextAccessibleWrap(aNode, aShell),
mActionContent(nsnull),
mIsLink(PR_FALSE),
@ -107,74 +108,69 @@ nsLinkableAccessible::nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference*
NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsHyperTextAccessibleWrap)
NS_IMETHODIMP nsLinkableAccessible::TakeFocus()
{
if (mActionContent && mActionContent->IsFocusable()) {
nsCOMPtr<nsIDOMNSHTMLElement> htmlElement(do_QueryInterface(mActionContent));
if (htmlElement) {
// HTML Elements also set the caret position
// in order to affect tabbing order
return htmlElement->Focus();
}
NS_WARNING("Has action content that is not an HTML element");
}
////////////////////////////////////////////////////////////////////////////////
// nsLinkableAccessible. nsIAccessible
NS_IMETHODIMP
nsLinkableAccessible::TakeFocus()
{
nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->TakeFocus();
return NS_OK;
}
/* long GetState (); */
NS_IMETHODIMP
nsLinkableAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
nsresult rv = nsHyperTextAccessibleWrap::GetState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
if (!mDOMNode)
return NS_OK;
if (mIsLink) {
*aState |= nsIAccessibleStates::STATE_LINKED;
nsCOMPtr<nsILink> link = do_QueryInterface(mActionContent);
if (link) {
nsLinkState linkState;
link->GetLinkState(linkState);
if (linkState == eLinkState_Visited) {
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
}
}
nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
if (actionAcc && (State(actionAcc) & nsIAccessibleStates::STATE_TRAVERSED))
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
}
return NS_OK;
}
NS_IMETHODIMP nsLinkableAccessible::GetValue(nsAString& aValue)
NS_IMETHODIMP
nsLinkableAccessible::GetValue(nsAString& aValue)
{
aValue.Truncate();
nsHyperTextAccessible::GetValue(aValue);
if (!aValue.IsEmpty())
return NS_OK;
if (mIsLink) {
nsCOMPtr<nsIDOMNode> linkNode(do_QueryInterface(mActionContent));
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
if (linkNode && presShell)
return presShell->GetLinkLocation(linkNode, aValue);
nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->GetValue(aValue);
}
return NS_ERROR_NOT_IMPLEMENTED;
}
/* PRUint8 getAccNumActions (); */
NS_IMETHODIMP nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
NS_IMETHODIMP
nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
{
NS_ENSURE_ARG_POINTER(aNumActions);
*aNumActions = mActionContent ? 1 : 0;
return NS_OK;
}
/* nsAString GetActionName (in PRUint8 Aindex); */
NS_IMETHODIMP nsLinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
NS_IMETHODIMP
nsLinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
{
// Action 0 (default action): Jump to link
aName.Truncate();
// Action 0 (default action): Jump to link
if (aIndex == eAction_Jump) {
if (mIsLink) {
aName.AssignLiteral("jump");
@ -189,105 +185,124 @@ NS_IMETHODIMP nsLinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aNa
return NS_ERROR_INVALID_ARG;
}
/* void accDoAction (in PRUint8 index); */
NS_IMETHODIMP nsLinkableAccessible::DoAction(PRUint8 index)
NS_IMETHODIMP
nsLinkableAccessible::DoAction(PRUint8 aIndex)
{
// Action 0 (default action): Jump to link
if (index == eAction_Jump) {
if (mActionContent) {
return DoCommand(mActionContent);
}
}
nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->DoAction(aIndex);
return NS_ERROR_INVALID_ARG;
}
NS_IMETHODIMP nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
NS_IMETHODIMP
nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
{
if (mActionContent) {
nsCOMPtr<nsIDOMNode> actionNode(do_QueryInterface(mActionContent));
if (actionNode && mDOMNode != actionNode) {
nsCOMPtr<nsIAccessible> accessible;
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
accService->GetAccessibleInWeakShell(actionNode, mWeakShell,
getter_AddRefs(accessible));
if (accessible) {
accessible->GetKeyboardShortcut(aKeyboardShortcut);
}
return NS_OK;
}
}
aKeyboardShortcut.Truncate();
nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
if (actionAcc)
return actionAcc->GetKeyboardShortcut(aKeyboardShortcut);
return nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
}
void nsLinkableAccessible::CacheActionContent()
////////////////////////////////////////////////////////////////////////////////
// nsLinkableAccessible. nsIAccessibleHyperLink
NS_IMETHODIMP
nsLinkableAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
{
for (nsCOMPtr<nsIContent> walkUpContent(do_QueryInterface(mDOMNode));
walkUpContent;
walkUpContent = walkUpContent->GetParent()) {
PRBool isOnclick = nsAccUtils::HasListener(walkUpContent, NS_LITERAL_STRING("click"));
nsIAtom *tag = walkUpContent->Tag();
if ((tag == nsAccessibilityAtoms::a || tag == nsAccessibilityAtoms::area) &&
walkUpContent->IsNodeOfType(nsINode::eHTML)) {
nsCOMPtr<nsILink> link = do_QueryInterface(walkUpContent);
if (link) {
// Currently we do not expose <link> tags, because they are not typically
// in <body> and rendered.
// We do not yet support xlinks
nsCOMPtr<nsIURI> uri;
link->GetHrefURI(getter_AddRefs(uri));
if (uri) {
mActionContent = walkUpContent;
mIsLink = PR_TRUE;
break;
}
}
if (SameCOMIdentity(mDOMNode, walkUpContent)) {
// This is the element that caused the creation of a linkable accessible
// Don't let it keep walking up, otherwise we may report the wrong container
// as the action node
mActionContent = walkUpContent;
mIsOnclick = isOnclick;
break;
}
}
if (isOnclick) {
mActionContent = walkUpContent;
mIsOnclick = PR_TRUE;
break;
if (mIsLink) {
nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
if (actionAcc) {
nsCOMPtr<nsIAccessibleHyperLink> hyperLinkAcc =
do_QueryInterface(actionAcc);
NS_ASSERTION(hyperLinkAcc,
"nsIAccessibleHyperLink isn't implemented.");
if (hyperLinkAcc)
return hyperLinkAcc->GetURI(aIndex, aURI);
}
}
return NS_ERROR_INVALID_ARG;
}
// nsIAccessibleHyperLink::GetURI()
NS_IMETHODIMP nsLinkableAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
{
// XXX Also implement this for nsHTMLImageAccessible file names
*aURI = nsnull;
if (aIndex != 0 || !mIsLink || !SameCOMIdentity(mDOMNode, mActionContent)) {
return NS_ERROR_FAILURE;
}
////////////////////////////////////////////////////////////////////////////////
// nsLinkableAccessible. nsPIAccessNode
nsCOMPtr<nsILink> link(do_QueryInterface(mActionContent));
if (link) {
return link->GetHrefURI(aURI);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsLinkableAccessible::Init()
NS_IMETHODIMP
nsLinkableAccessible::Init()
{
CacheActionContent();
return nsHyperTextAccessibleWrap::Init();
}
NS_IMETHODIMP nsLinkableAccessible::Shutdown()
NS_IMETHODIMP
nsLinkableAccessible::Shutdown()
{
mActionContent = nsnull;
return nsHyperTextAccessibleWrap::Shutdown();
}
////////////////////////////////////////////////////////////////////////////////
// nsLinkableAccessible
void
nsLinkableAccessible::CacheActionContent()
{
nsCOMPtr<nsIContent> walkUpContent(do_QueryInterface(mDOMNode));
PRBool isOnclick = nsAccUtils::HasListener(walkUpContent,
NS_LITERAL_STRING("click"));
if (isOnclick) {
mActionContent = walkUpContent;
mIsOnclick = PR_TRUE;
return;
}
while ((walkUpContent = walkUpContent->GetParent())) {
isOnclick = nsAccUtils::HasListener(walkUpContent,
NS_LITERAL_STRING("click"));
nsCOMPtr<nsIDOMNode> walkUpNode(do_QueryInterface(walkUpContent));
nsCOMPtr<nsIAccessible> walkUpAcc;
GetAccService()->GetAccessibleInWeakShell(walkUpNode, mWeakShell,
getter_AddRefs(walkUpAcc));
if (walkUpAcc && Role(walkUpAcc) == nsIAccessibleRole::ROLE_LINK) {
mIsLink = PR_TRUE;
mActionContent = walkUpContent;
return;
}
if (isOnclick) {
mActionContent = walkUpContent;
mIsOnclick = PR_TRUE;
return;
}
}
}
already_AddRefed<nsIAccessible>
nsLinkableAccessible::GetActionAccessible()
{
// Return accessible for the action content if it's different from node of
// this accessible. If the action accessible is not null then it is used to
// redirect methods calls otherwise we use method implementation from the
// base class.
nsCOMPtr<nsIDOMNode> actionNode(do_QueryInterface(mActionContent));
if (!actionNode || mDOMNode == actionNode)
return nsnull;
nsIAccessible *accessible = nsnull;
GetAccService()->GetAccessibleInWeakShell(actionNode, mWeakShell,
&accessible);
return accessible;
}
//---------------------
// nsEnumRoleAccessible
//---------------------

View File

@ -78,7 +78,10 @@ public:
enum { eAction_Jump = 0 };
nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessible
NS_IMETHOD GetNumActions(PRUint8 *_retval);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 index);
@ -86,12 +89,25 @@ public:
NS_IMETHOD GetValue(nsAString& _retval);
NS_IMETHOD TakeFocus();
NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
// nsIHyperLinkAccessible
NS_IMETHOD GetURI(PRInt32 i, nsIURI **aURI);
// nsPIAccessNode
NS_IMETHOD Init();
NS_IMETHOD Shutdown();
protected:
/**
* Return an accessible for cached action node.
*/
already_AddRefed<nsIAccessible> GetActionAccessible();
/**
* Cache action node.
*/
virtual void CacheActionContent();
nsCOMPtr<nsIContent> mActionContent;
PRPackedBool mIsLink;
PRPackedBool mIsOnclick;

View File

@ -37,7 +37,6 @@
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLAreaAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsIServiceManager.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLAreaElement.h"
@ -46,32 +45,36 @@
#include "nsIImageMap.h"
// --- area -----
////////////////////////////////////////////////////////////////////////////////
// nsHTMLAreaAccessible
nsHTMLAreaAccessible::nsHTMLAreaAccessible(nsIDOMNode *aDomNode, nsIAccessible *aParent, nsIWeakReference* aShell):
nsLinkableAccessible(aDomNode, aShell)
nsHTMLAreaAccessible::
nsHTMLAreaAccessible(nsIDOMNode *aDomNode, nsIAccessible *aParent,
nsIWeakReference* aShell):
nsHTMLLinkAccessible(aDomNode, aShell)
{
}
// Expose nsIAccessibleHyperLink unconditionally
NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLAreaAccessible, nsLinkableAccessible,
nsIAccessibleHyperLink)
////////////////////////////////////////////////////////////////////////////////
// nsIAccessible
/* wstring getName (); */
NS_IMETHODIMP nsHTMLAreaAccessible::GetName(nsAString & aName)
NS_IMETHODIMP
nsHTMLAreaAccessible::GetName(nsAString & aName)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content) {
return NS_ERROR_FAILURE;
}
aName.Truncate();
if (IsDefunct())
return NS_ERROR_FAILURE;
if (mRoleMapEntry) {
nsresult rv = nsAccessible::GetName(aName);
if (!aName.IsEmpty()) {
return rv;
}
NS_ENSURE_SUCCESS(rv, rv);
if (!aName.IsEmpty())
return NS_OK;
}
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::alt,
aName) &&
!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::title,
@ -82,47 +85,49 @@ NS_IMETHODIMP nsHTMLAreaAccessible::GetName(nsAString & aName)
return NS_OK;
}
/* unsigned long getRole (); */
NS_IMETHODIMP nsHTMLAreaAccessible::GetRole(PRUint32 *_retval)
NS_IMETHODIMP
nsHTMLAreaAccessible::GetDescription(nsAString& aDescription)
{
*_retval = nsIAccessibleRole::ROLE_LINK;
return NS_OK;
}
aDescription.Truncate();
/* wstring getDescription (); */
NS_IMETHODIMP nsHTMLAreaAccessible::GetDescription(nsAString& _retval)
{
// Still to do - follow IE's standard here
nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mDOMNode));
if (area)
area->GetShape(_retval);
area->GetShape(aDescription);
return NS_OK;
}
/* nsIAccessible getFirstChild (); */
NS_IMETHODIMP nsHTMLAreaAccessible::GetFirstChild(nsIAccessible **_retval)
NS_IMETHODIMP
nsHTMLAreaAccessible::GetFirstChild(nsIAccessible **aChild)
{
*_retval = nsnull;
NS_ENSURE_ARG_POINTER(aChild);
*aChild = nsnull;
return NS_OK;
}
/* nsIAccessible getLastChild (); */
NS_IMETHODIMP nsHTMLAreaAccessible::GetLastChild(nsIAccessible **_retval)
NS_IMETHODIMP
nsHTMLAreaAccessible::GetLastChild(nsIAccessible **aChild)
{
*_retval = nsnull;
NS_ENSURE_ARG_POINTER(aChild);
*aChild = nsnull;
return NS_OK;
}
/* long getAccChildCount (); */
NS_IMETHODIMP nsHTMLAreaAccessible::GetChildCount(PRInt32 *_retval)
NS_IMETHODIMP
nsHTMLAreaAccessible::GetChildCount(PRInt32 *aCount)
{
*_retval = 0;
NS_ENSURE_ARG_POINTER(aCount);
*aCount = 0;
return NS_OK;
}
/* void accGetBounds (out long x, out long y, out long width, out long height); */
NS_IMETHODIMP nsHTMLAreaAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
NS_IMETHODIMP
nsHTMLAreaAccessible::GetBounds(PRInt32 *x, PRInt32 *y,
PRInt32 *width, PRInt32 *height)
{
// Essentially this uses GetRect on mAreas of nsImageMap from nsImageFrame

View File

@ -39,27 +39,26 @@
#ifndef _nsHTMLAreaAccessible_H_
#define _nsHTMLAreaAccessible_H_
#include "nsBaseWidgetAccessible.h"
#include "nsHTMLLinkAccessible.h"
/* Accessible for image map areas - must be child of image
*/
class nsHTMLAreaAccessible : public nsLinkableAccessible
class nsHTMLAreaAccessible : public nsHTMLLinkAccessible
{
public:
nsHTMLAreaAccessible(nsIDOMNode *domNode, nsIAccessible *accParent,
nsIWeakReference* aShell);
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessible
NS_IMETHOD GetName(nsAString & _retval);
NS_IMETHOD GetRole(PRUint32 *_retval);
NS_IMETHOD GetName(nsAString & aName);
NS_IMETHOD GetDescription(nsAString& aDescription);
NS_IMETHOD GetFirstChild(nsIAccessible **_retval);
NS_IMETHOD GetLastChild(nsIAccessible **_retval);
NS_IMETHOD GetChildCount(PRInt32 *_retval);
NS_IMETHOD GetDescription(nsAString& _retval);
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
NS_IMETHOD GetChildAtPoint(PRInt32 aX, PRInt32 aY, nsIAccessible **aAccessible)
{ NS_ENSURE_ARG_POINTER(aAccessible); NS_ADDREF(*aAccessible = this); return NS_OK; } // Don't walk into these

View File

@ -20,7 +20,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Author: Aaron Leventhal (aaronl@netscape.com)
* Aaron Leventhal <aleventh@us.ibm.com> (original author)
* Alexander Surkov <surkov.alexander@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -37,38 +38,50 @@
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLLinkAccessible.h"
#include "nsAccessibilityAtoms.h"
#include "nsIAccessibleEvent.h"
#include "nsINameSpaceManager.h"
NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLinkAccessible, nsLinkableAccessible)
#include "nsILink.h"
nsHTMLLinkAccessible::nsHTMLLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
nsLinkableAccessible(aDomNode, aShell)
////////////////////////////////////////////////////////////////////////////////
// nsHTMLLinkAccessible
nsHTMLLinkAccessible::nsHTMLLinkAccessible(nsIDOMNode* aDomNode,
nsIWeakReference* aShell):
nsHyperTextAccessibleWrap(aDomNode, aShell)
{
}
/* wstring getName (); */
NS_IMETHODIMP nsHTMLLinkAccessible::GetName(nsAString& aName)
// Expose nsIAccessibleHyperLink unconditionally
NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLLinkAccessible, nsHyperTextAccessibleWrap,
nsIAccessibleHyperLink)
////////////////////////////////////////////////////////////////////////////////
// nsIAccessible
NS_IMETHODIMP
nsHTMLLinkAccessible::GetName(nsAString& aName)
{
if (!mActionContent)
aName.Truncate();
if (IsDefunct())
return NS_ERROR_FAILURE;
return AppendFlatStringFromSubtree(mActionContent, &aName);
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
return AppendFlatStringFromSubtree(content, &aName);
}
/* unsigned long getRole (); */
NS_IMETHODIMP nsHTMLLinkAccessible::GetRole(PRUint32 *_retval)
NS_IMETHODIMP
nsHTMLLinkAccessible::GetRole(PRUint32 *aRole)
{
*_retval = nsIAccessibleRole::ROLE_LINK;
NS_ENSURE_ARG_POINTER(aRole);
*aRole = nsIAccessibleRole::ROLE_LINK;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
nsresult rv = nsLinkableAccessible::GetState(aState, aExtraState);
nsresult rv = nsHyperTextAccessibleWrap::GetState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
if (!mDOMNode)
return NS_OK;
@ -84,5 +97,85 @@ nsHTMLLinkAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
*aState |= nsIAccessibleStates::STATE_SELECTABLE;
}
*aState |= nsIAccessibleStates::STATE_LINKED;
nsCOMPtr<nsILink> link = do_QueryInterface(mDOMNode);
NS_ENSURE_STATE(link);
nsLinkState linkState;
link->GetLinkState(linkState);
if (linkState == eLinkState_Visited)
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkAccessible::GetValue(nsAString& aValue)
{
aValue.Truncate();
nsresult rv = nsHyperTextAccessible::GetValue(aValue);
NS_ENSURE_SUCCESS(rv, rv);
if (!aValue.IsEmpty())
return NS_OK;
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
if (mDOMNode && presShell)
return presShell->GetLinkLocation(mDOMNode, aValue);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkAccessible::GetNumActions(PRUint8 *aNumActions)
{
NS_ENSURE_ARG_POINTER(aNumActions);
*aNumActions = 1;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
{
// Action 0 (default action): Jump to link
aName.Truncate();
if (aIndex != eAction_Jump)
return NS_ERROR_INVALID_ARG;
aName.AssignLiteral("jump");
return NS_OK;
}
NS_IMETHODIMP
nsHTMLLinkAccessible::DoAction(PRUint8 aIndex)
{
// Action 0 (default action): Jump to link
if (aIndex != eAction_Jump)
return NS_ERROR_INVALID_ARG;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
return DoCommand(content);
}
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleHyperLink
NS_IMETHODIMP
nsHTMLLinkAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
*aURI = nsnull;
if (aIndex != 0)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsILink> link(do_QueryInterface(mDOMNode));
NS_ENSURE_STATE(link);
return link->GetHrefURI(aURI);
}

View File

@ -20,7 +20,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Author: Aaron Leventhal (aaronl@netscape.com)
* Aaron Leventhal <aleventh@us.ibm.com> (original author)
* Alexander Surkov <surkov.alexander@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -39,19 +40,30 @@
#ifndef _nsHTMLLinkAccessible_H_
#define _nsHTMLLinkAccessible_H_
#include "nsBaseWidgetAccessible.h"
#include "nsHyperTextAccessibleWrap.h"
class nsHTMLLinkAccessible : public nsLinkableAccessible
class nsHTMLLinkAccessible : public nsHyperTextAccessibleWrap
{
NS_DECL_ISUPPORTS_INHERITED
public:
nsHTMLLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessible
NS_IMETHOD GetName(nsAString& _retval);
NS_IMETHOD GetRole(PRUint32 *_retval);
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetValue(nsAString& aValue);
NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 aIndex);
// nsIAccessibleHyperLink
NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
protected:
enum { eAction_Jump = 0 };
};
#endif

View File

@ -45,6 +45,7 @@
#include "nsINameSpaceManager.h"
#include "nsString.h"
#include "nsXULTextAccessible.h"
#include "nsNetUtil.h"
/**
* For XUL descriptions and labels
@ -138,62 +139,118 @@ NS_IMETHODIMP nsXULTooltipAccessible::GetRole(PRUint32 *_retval)
return NS_OK;
}
/**
* For XUL text links
*/
nsXULLinkAccessible::nsXULLinkAccessible(nsIDOMNode *aDomNode, nsIWeakReference *aShell):
nsLinkableAccessible(aDomNode, aShell)
////////////////////////////////////////////////////////////////////////////////
// nsXULLinkAccessible
nsXULLinkAccessible::
nsXULLinkAccessible(nsIDOMNode *aDomNode, nsIWeakReference *aShell):
nsHyperTextAccessibleWrap(aDomNode, aShell)
{
}
NS_IMETHODIMP nsXULLinkAccessible::GetValue(nsAString& aValue)
{
if (mIsLink) {
mActionContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::href, aValue);
return NS_OK;
}
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////////////
// nsXULLinkAccessible. nsIAccessible
NS_IMETHODIMP
nsXULLinkAccessible::GetValue(nsAString& aValue)
{
aValue.Truncate();
if (IsDefunct())
return NS_ERROR_FAILURE;
NS_IMETHODIMP nsXULLinkAccessible::GetName(nsAString& aName)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content) {
return NS_ERROR_FAILURE; // Node shut down
}
if (!content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value,
aName)) {
// if the value doesn't exist, flatten the inner content as the name (for descriptions)
return AppendFlatStringFromSubtree(content, &aName);
}
// otherwise, use the value attribute as the name (for labels)
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::href, aValue);
return NS_OK;
}
NS_IMETHODIMP nsXULLinkAccessible::GetRole(PRUint32 *aRole)
NS_IMETHODIMP
nsXULLinkAccessible::GetName(nsAString& aName)
{
// We used to say ROLE_BUTTON if there was no href, but then screen readers
// would tell users to hit the space bar for activation, which is wrong for a link
aName.Truncate();
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::value, aName);
if (!aName.IsEmpty())
return NS_OK;
return AppendFlatStringFromSubtree(content, &aName);
}
NS_IMETHODIMP
nsXULLinkAccessible::GetRole(PRUint32 *aRole)
{
NS_ENSURE_ARG_POINTER(aRole);
*aRole = nsIAccessibleRole::ROLE_LINK;
return NS_OK;
}
void nsXULLinkAccessible::CacheActionContent()
{
// not a link if no content
nsCOMPtr<nsIContent> mTempContent = do_QueryInterface(mDOMNode);
if (!mTempContent) {
return;
}
// not a link if there is no href attribute or not on a <link> tag
if (mTempContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::href) ||
mTempContent->Tag() == nsAccessibilityAtoms::link) {
mIsLink = PR_TRUE;
mActionContent = mTempContent;
}
else if (nsAccUtils::HasListener(mTempContent, NS_LITERAL_STRING("click"))) {
mIsOnclick = PR_TRUE;
mActionContent = mTempContent;
}
NS_IMETHODIMP
nsXULLinkAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
nsresult rv = nsHyperTextAccessibleWrap::GetState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
*aState |= nsIAccessibleStates::STATE_LINKED;
return NS_OK;
}
NS_IMETHODIMP
nsXULLinkAccessible::GetNumActions(PRUint8 *aNumActions)
{
NS_ENSURE_ARG_POINTER(aNumActions);
*aNumActions = 1;
return NS_OK;
}
NS_IMETHODIMP
nsXULLinkAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
{
aName.Truncate();
if (aIndex != eAction_Jump)
return NS_ERROR_INVALID_ARG;
aName.AssignLiteral("jump");
return NS_OK;
}
NS_IMETHODIMP
nsXULLinkAccessible::DoAction(PRUint8 aIndex)
{
if (aIndex != eAction_Jump)
return NS_ERROR_INVALID_ARG;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
return DoCommand(content);
}
////////////////////////////////////////////////////////////////////////////////
// nsXULLinkAccessible. nsIAccessibleHyperLink
NS_IMETHODIMP
nsXULLinkAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
*aURI = nsnull;
if (aIndex != 0)
return NS_ERROR_INVALID_ARG;
nsAutoString href;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::href, href);
nsCOMPtr<nsIDocument> document = content->GetOwnerDoc();
return NS_NewURI(aURI, href,
document ? document->GetDocumentCharacterSet().get() : nsnull);
}

View File

@ -68,17 +68,28 @@ public:
NS_IMETHOD GetRole(PRUint32 *_retval);
};
class nsXULLinkAccessible : public nsLinkableAccessible
class nsXULLinkAccessible : public nsHyperTextAccessibleWrap
{
public:
nsXULLinkAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
NS_IMETHOD GetName(nsAString& _retval);
// nsIAccessible
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetValue(nsAString& _retval);
NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
NS_IMETHOD GetValue(nsAString& aValue);
NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 aIndex);
// nsIAccessibleHyperLink
NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
protected:
void CacheActionContent();
enum { eAction_Jump = 0 };
};
#endif