Bug 572394 - cache links within hypertext accessible, r=davidb, marcoz, sr=neil

--HG--
rename : accessible/src/base/nsAccIterator.cpp => accessible/src/base/AccIterator.cpp
rename : accessible/src/base/nsAccIterator.h => accessible/src/base/AccIterator.h
This commit is contained in:
Alexander Surkov 2010-06-21 22:08:27 +09:00
parent 85ccd4574e
commit add7533996
19 changed files with 617 additions and 220 deletions

View File

@ -44,36 +44,46 @@
/**
* A cross-platform interface that deals with text which contains hyperlinks.
* Each link is an embedded object representing exactly 1 character within
* the hypertext.
*
* Current implementation assumes every embedded object is a link.
*/
[scriptable, uuid(d56bd454-8ff3-4edc-b266-baeada00267b)]
[scriptable, uuid(b33684e2-090c-4e1d-a3d9-f4b46f4237b9)]
interface nsIAccessibleHyperText : nsISupports
{
/**
* Returns the number of links contained within this hypertext object.
* Return the number of links contained within this hypertext object.
*/
readonly attribute long linkCount;
/*
* Returns the link index at the given character index.
* Each link is an embedded object representing exactly 1 character within
* the hypertext.
/**
* Return link accessible at the given index.
*
* @param charIndex the 0-based character index.
* @param index [in] 0-based index of the link that is to be retrieved
*
* @returns long 0-based link's index.
* A return value of -1 indicates no link is present at that index.
* @return link accessible or null if there is no link at that index
*/
long getLinkIndex(in long charIndex);
nsIAccessibleHyperLink getLinkAt(in long index);
/**
* Retrieves the nsIAccessibleHyperLink object at the given link index.
* Return index of the given link.
*
* @param linkIndex 0-based index of the link that is to be retrieved.
* This can be retrieved via getLinkIndex (see above).
* @param link [in] link accessible the index is requested for
*
* @returns nsIAccessibleHyperLink Object representing the link properties
* or NS_ERROR_INVALID_ARG if there is no link at that index.
* @return index of the given link or null if there's no link within
* hypertext accessible
*/
nsIAccessibleHyperLink getLink(in long linkIndex);
long getLinkIndex(in nsIAccessibleHyperLink link);
/*
* Return link index at the given offset within hypertext accessible.
*
* @param offset [in] the 0-based character index
*
* @return 0-based link's index or -1 if no link is present at that
* offset
*/
long getLinkIndexAtOffset(in long offset);
};

View File

@ -868,21 +868,11 @@ getChildCountCB(AtkObject *aAtkObj)
return 0;
}
PRInt32 count = 0;
nsCOMPtr<nsIAccessibleHyperText> hyperText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), getter_AddRefs(hyperText));
if (hyperText) {
// If HyperText, then number of links matches number of children
hyperText->GetLinkCount(&count);
}
else {
nsCOMPtr<nsIAccessibleText> accText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText));
if (!accText) { // Accessible text that is not a HyperText has no children
accWrap->GetChildCount(&count);
}
}
return count;
// Links within hypertext accessible play role of accessible children in
// ATK since every embedded object is a link and text accessibles are
// ignored.
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap);
return hyperText ? hyperText->GetLinkCount() : accWrap->GetChildCount();
}
AtkObject *
@ -898,25 +888,12 @@ refChildCB(AtkObject *aAtkObj, gint aChildIndex)
return nsnull;
}
nsCOMPtr<nsIAccessible> accChild;
nsCOMPtr<nsIAccessibleHyperText> hyperText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), getter_AddRefs(hyperText));
if (hyperText) {
// If HyperText, then number of links matches number of children.
// XXX Fix this so it is not O(n^2) to walk through the children
// (bug 566328).
nsCOMPtr<nsIAccessibleHyperLink> hyperLink;
hyperText->GetLink(aChildIndex, getter_AddRefs(hyperLink));
accChild = do_QueryInterface(hyperLink);
}
else {
nsCOMPtr<nsIAccessibleText> accText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText));
if (!accText) { // Accessible Text that is not HyperText has no children
accWrap->GetChildAt(aChildIndex, getter_AddRefs(accChild));
}
}
// Links within hypertext accessible play role of accessible children in
// ATK since every embedded object is a link and text accessibles are
// ignored.
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap);
nsAccessible* accChild = hyperText ? hyperText->GetLinkAt(aChildIndex) :
accWrap->GetChildAt(aChildIndex);
if (!accChild)
return nsnull;
@ -947,21 +924,12 @@ getIndexInParentCB(AtkObject *aAtkObj)
return -1; // No parent
}
PRInt32 currentIndex = 0;
PRInt32 childCount = parent->GetChildCount();
for (PRInt32 idx = 0; idx < childCount; idx++) {
nsAccessible *sibling = parent->GetChildAt(idx);
if (sibling == accWrap) {
return currentIndex;
}
if (nsAccUtils::IsEmbeddedObject(sibling)) {
++ currentIndex;
}
}
return -1;
// Links within hypertext accessible play role of accessible children in
// ATK since every embedded object is a link and text accessibles are
// ignored.
nsRefPtr<nsHyperTextAccessible> hyperTextParent(do_QueryObject(parent));
return hyperTextParent ?
hyperTextParent->GetLinkIndex(accWrap) : parent->GetIndexOf(accWrap);
}
static void TranslateStates(PRUint32 aState, const AtkStateMap *aStateMap,

View File

@ -40,7 +40,7 @@
#include "nsMaiInterfaceHypertext.h"
#include "nsIAccessibleDocument.h"
#include "nsAccessNode.h"
#include "nsHyperTextAccessible.h"
void
hypertextInterfaceInitCB(AtkHypertextIface *aIface)
@ -59,18 +59,14 @@ getLinkCB(AtkHypertext *aText, gint aLinkIndex)
if (!accWrap)
return nsnull;
nsCOMPtr<nsIAccessibleHyperText> hyperText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText),
getter_AddRefs(hyperText));
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap);
NS_ENSURE_TRUE(hyperText, nsnull);
nsCOMPtr<nsIAccessibleHyperLink> hyperLink;
nsresult rv = hyperText->GetLink(aLinkIndex, getter_AddRefs(hyperLink));
if (NS_FAILED(rv) || !hyperLink)
nsAccessible* hyperLink = hyperText->GetLinkAt(aLinkIndex);
if (!hyperLink)
return nsnull;
nsCOMPtr<nsIAccessible> hyperLinkAcc(do_QueryInterface(hyperLink));
AtkObject *hyperLinkAtkObj = nsAccessibleWrap::GetAtkObject(hyperLinkAcc);
AtkObject* hyperLinkAtkObj = nsAccessibleWrap::GetAtkObject(hyperLink);
nsAccessibleWrap *accChild = GetAccessibleWrap(hyperLinkAtkObj);
NS_ENSURE_TRUE(accChild, nsnull);
@ -86,16 +82,10 @@ getLinkCountCB(AtkHypertext *aText)
if (!accWrap)
return -1;
nsCOMPtr<nsIAccessibleHyperText> hyperText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText),
getter_AddRefs(hyperText));
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap);
NS_ENSURE_TRUE(hyperText, -1);
PRInt32 count = -1;
nsresult rv = hyperText->GetLinkCount(&count);
NS_ENSURE_SUCCESS(rv, -1);
return count;
return hyperText->GetLinkCount();
}
gint
@ -105,13 +95,11 @@ getLinkIndexCB(AtkHypertext *aText, gint aCharIndex)
if (!accWrap)
return -1;
nsCOMPtr<nsIAccessibleHyperText> hyperText;
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText),
getter_AddRefs(hyperText));
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap);
NS_ENSURE_TRUE(hyperText, -1);
PRInt32 index = -1;
nsresult rv = hyperText->GetLinkIndex(aCharIndex, &index);
nsresult rv = hyperText->GetLinkIndexAtOffset(aCharIndex, &index);
NS_ENSURE_SUCCESS(rv, -1);
return index;

View File

@ -0,0 +1,118 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "AccCollector.h"
#include "nsAccessible.h"
////////////////////////////////////////////////////////////////////////////////
// nsAccCollector
////////////////////////////////////////////////////////////////////////////////
AccCollector::
AccCollector(nsAccessible* aRoot, filters::FilterFuncPtr aFilterFunc) :
mFilterFunc(aFilterFunc), mRoot(aRoot), mRootChildIdx(0)
{
}
AccCollector::~AccCollector()
{
}
PRUint32
AccCollector::Count()
{
EnsureNGetIndex(nsnull);
return mObjects.Length();
}
nsAccessible*
AccCollector::GetAccessibleAt(PRUint32 aIndex)
{
nsAccessible *accessible = mObjects.SafeElementAt(aIndex, nsnull);
if (accessible)
return accessible;
return EnsureNGetObject(aIndex);
}
PRInt32
AccCollector::GetIndexAt(nsAccessible *aAccessible)
{
PRInt32 index = mObjects.IndexOf(aAccessible);
if (index != -1)
return index;
return EnsureNGetIndex(aAccessible);
}
////////////////////////////////////////////////////////////////////////////////
// nsAccCollector protected
nsAccessible*
AccCollector::EnsureNGetObject(PRUint32 aIndex)
{
PRInt32 childCount = mRoot->GetChildCount();
while (mRootChildIdx < childCount) {
nsAccessible* child = mRoot->GetChildAt(mRootChildIdx++);
if (!mFilterFunc(child))
continue;
mObjects.AppendElement(child);
if (mObjects.Length() - 1 == aIndex)
return mObjects[aIndex];
}
return nsnull;
}
PRInt32
AccCollector::EnsureNGetIndex(nsAccessible* aAccessible)
{
PRInt32 childCount = mRoot->GetChildCount();
while (mRootChildIdx < childCount) {
nsAccessible* child = mRoot->GetChildAt(mRootChildIdx++);
if (!mFilterFunc(child))
continue;
mObjects.AppendElement(child);
if (child == aAccessible)
return mObjects.Length() - 1;
}
return -1;
}

View File

@ -0,0 +1,94 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef AccCollector_h_
#define AccCollector_h_
#include "filters.h"
#include "nscore.h"
#include "nsTArray.h"
/**
* Collect accessible children complying with filter function. Provides quick
* access to accessible by index.
*/
class AccCollector
{
public:
AccCollector(nsAccessible* aRoot, filters::FilterFuncPtr aFilterFunc);
virtual ~AccCollector();
/**
* Return accessible count within the collection.
*/
PRUint32 Count();
/**
* Return an accessible from the collection at the given index.
*/
nsAccessible* GetAccessibleAt(PRUint32 aIndex);
/**
* Return index of the given accessible within the collection.
*/
PRInt32 GetIndexAt(nsAccessible* aAccessible);
protected:
/**
* Ensure accessible at the given index is stored and return it.
*/
nsAccessible* EnsureNGetObject(PRUint32 aIndex);
/**
* Ensure index for the given accessible is stored and return it.
*/
PRInt32 EnsureNGetIndex(nsAccessible* aAccessible);
filters::FilterFuncPtr mFilterFunc;
nsAccessible* mRoot;
PRInt32 mRootChildIdx;
nsTArray<nsAccessible*> mObjects;
private:
AccCollector();
AccCollector(const AccCollector&);
AccCollector& operator =(const AccCollector&);
};
#endif

View File

@ -35,20 +35,22 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsAccIterator.h"
#include "AccIterator.h"
#include "nsAccessible.h"
////////////////////////////////////////////////////////////////////////////////
// nsAccIterator
nsAccIterator::nsAccIterator(nsAccessible *aAccessible,
AccIteratorFilterFuncPtr aFilterFunc,
IterationType aIterationType) :
AccIterator::AccIterator(nsAccessible *aAccessible,
filters::FilterFuncPtr aFilterFunc,
IterationType aIterationType) :
mFilterFunc(aFilterFunc), mIsDeep(aIterationType != eFlatNav)
{
mState = new IteratorState(aAccessible);
}
nsAccIterator::~nsAccIterator()
AccIterator::~AccIterator()
{
while (mState) {
IteratorState *tmp = mState;
@ -58,7 +60,7 @@ nsAccIterator::~nsAccIterator()
}
nsAccessible*
nsAccIterator::GetNext()
AccIterator::GetNext()
{
while (mState) {
nsAccessible *child = mState->mParent->GetChildAt(mState->mIndex++);
@ -86,8 +88,8 @@ nsAccIterator::GetNext()
////////////////////////////////////////////////////////////////////////////////
// nsAccIterator::IteratorState
nsAccIterator::IteratorState::IteratorState(nsAccessible *aParent,
IteratorState *mParentState) :
AccIterator::IteratorState::IteratorState(nsAccessible *aParent,
IteratorState *mParentState) :
mParent(aParent), mIndex(0), mParentState(mParentState)
{
}

View File

@ -38,19 +38,14 @@
#ifndef nsAccIterator_h_
#define nsAccIterator_h_
#include "nsAccessible.h"
#include "nsAccUtils.h"
/**
* Return true if the traversed accessible complies with filter.
*/
typedef PRBool (*AccIteratorFilterFuncPtr) (nsAccessible *);
#include "filters.h"
#include "nscore.h"
/**
* Allows to iterate through accessible children or subtree complying with
* filter function.
*/
class nsAccIterator
class AccIterator
{
public:
/**
@ -69,9 +64,9 @@ public:
eTreeNav
};
nsAccIterator(nsAccessible *aRoot, AccIteratorFilterFuncPtr aFilterFunc,
IterationType aIterationType = eFlatNav);
~nsAccIterator();
AccIterator(nsAccessible* aRoot, filters::FilterFuncPtr aFilterFunc,
IterationType aIterationType = eFlatNav);
~AccIterator();
/**
* Return next accessible complying with filter function. Return the first
@ -79,33 +74,10 @@ public:
*/
nsAccessible *GetNext();
/**
* Predefined filters.
*/
static PRBool GetSelected(nsAccessible *aAccessible)
{
return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTED;
}
static PRBool GetSelectable(nsAccessible *aAccessible)
{
return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTABLE;
}
static PRBool GetRow(nsAccessible *aAccessible)
{
return nsAccUtils::Role(aAccessible) == nsIAccessibleRole::ROLE_ROW;
}
static PRBool GetCell(nsAccessible *aAccessible)
{
PRUint32 role = nsAccUtils::Role(aAccessible);
return role == nsIAccessibleRole::ROLE_GRID_CELL ||
role == nsIAccessibleRole::ROLE_ROWHEADER ||
role == nsIAccessibleRole::ROLE_COLUMNHEADER;
}
private:
nsAccIterator();
nsAccIterator(const nsAccIterator&);
nsAccIterator& operator =(const nsAccIterator&);
AccIterator();
AccIterator(const AccIterator&);
AccIterator& operator =(const AccIterator&);
struct IteratorState
{
@ -116,7 +88,7 @@ private:
IteratorState *mParentState;
};
AccIteratorFilterFuncPtr mFilterFunc;
filters::FilterFuncPtr mFilterFunc;
PRBool mIsDeep;
IteratorState *mState;
};

View File

@ -48,10 +48,12 @@ LIBXUL_LIBRARY = 1
CPPSRCS = \
AccCollector.cpp \
AccIterator.cpp \
filters.cpp \
nsAccDocManager.cpp \
nsAccessNode.cpp \
nsAccEvent.cpp \
nsAccIterator.cpp \
nsARIAGridAccessible.cpp \
nsARIAMap.cpp \
nsDocAccessible.cpp \

View File

@ -0,0 +1,74 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "filters.h"
#include "nsAccessible.h"
#include "nsAccUtils.h"
bool
filters::GetSelected(nsAccessible* aAccessible)
{
return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTED;
}
bool
filters::GetSelectable(nsAccessible* aAccessible)
{
return nsAccUtils::State(aAccessible) & nsIAccessibleStates::STATE_SELECTABLE;
}
bool
filters::GetRow(nsAccessible* aAccessible)
{
return nsAccUtils::Role(aAccessible) == nsIAccessibleRole::ROLE_ROW;
}
bool
filters::GetCell(nsAccessible* aAccessible)
{
PRUint32 role = nsAccUtils::Role(aAccessible);
return role == nsIAccessibleRole::ROLE_GRID_CELL ||
role == nsIAccessibleRole::ROLE_ROWHEADER ||
role == nsIAccessibleRole::ROLE_COLUMNHEADER;
}
bool
filters::GetEmbeddedObject(nsAccessible* aAccessible)
{
return nsAccUtils::IsEmbeddedObject(aAccessible);
}

View File

@ -0,0 +1,60 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef a11yFilters_h_
#define a11yFilters_h_
class nsAccessible;
/**
* Predefined filters used for nsAccIterator and nsAccCollector.
*/
namespace filters {
/**
* Return true if the traversed accessible complies with filter.
*/
typedef bool (*FilterFuncPtr) (nsAccessible*);
bool GetSelected(nsAccessible* aAccessible);
bool GetSelectable(nsAccessible* aAccessible);
bool GetRow(nsAccessible* aAccessible);
bool GetCell(nsAccessible* aAccessible);
bool GetEmbeddedObject(nsAccessible* aAccessible);
}
#endif

View File

@ -38,7 +38,8 @@
#include "nsARIAGridAccessible.h"
#include "nsAccIterator.h"
#include "AccIterator.h"
#include "nsAccUtils.h"
#include "nsIMutableArray.h"
#include "nsComponentManagerUtils.h"
@ -101,10 +102,10 @@ nsARIAGridAccessible::GetColumnCount(PRInt32 *acolumnCount)
if (IsDefunct())
return NS_ERROR_FAILURE;
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = rowIter.GetNext();
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = nsnull;
while ((cell = cellIter.GetNext()))
@ -122,7 +123,7 @@ nsARIAGridAccessible::GetRowCount(PRInt32 *arowCount)
if (IsDefunct())
return NS_ERROR_FAILURE;
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
while (rowIter.GetNext())
(*arowCount)++;
@ -292,7 +293,7 @@ nsARIAGridAccessible::IsColumnSelected(PRInt32 aColumn, PRBool *aIsSelected)
NS_ENSURE_ARG(IsValidColumn(aColumn));
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = rowIter.GetNext();
if (!row)
return NS_OK;
@ -325,7 +326,7 @@ nsARIAGridAccessible::IsRowSelected(PRInt32 aRow, PRBool *aIsSelected)
NS_ENSURE_ARG(row);
if (!nsAccUtils::IsARIASelected(row)) {
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = nsnull;
while ((cell = cellIter.GetNext())) {
if (!nsAccUtils::IsARIASelected(cell))
@ -374,7 +375,7 @@ nsARIAGridAccessible::GetSelectedCellCount(PRUint32* aCount)
PRInt32 colCount = 0;
GetColumnCount(&colCount);
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = nsnull;
while ((row = rowIter.GetNext())) {
@ -383,7 +384,7 @@ nsARIAGridAccessible::GetSelectedCellCount(PRUint32* aCount)
continue;
}
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = nsnull;
while ((cell = cellIter.GetNext())) {
@ -410,7 +411,7 @@ nsARIAGridAccessible::GetSelectedRowCount(PRUint32* aCount)
if (IsDefunct())
return NS_ERROR_FAILURE;
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = nsnull;
while ((row = rowIter.GetNext())) {
@ -419,7 +420,7 @@ nsARIAGridAccessible::GetSelectedRowCount(PRUint32* aCount)
continue;
}
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = cellIter.GetNext();
if (!cell)
continue;
@ -453,11 +454,11 @@ nsARIAGridAccessible::GetSelectedCells(nsIArray **aCells)
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = nsnull;
while (row = rowIter.GetNext()) {
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = nsnull;
if (nsAccUtils::IsARIASelected(row)) {
@ -497,7 +498,7 @@ nsARIAGridAccessible::GetSelectedCellIndices(PRUint32 *aCellsCount,
nsTArray<PRInt32> selCells(rowCount * colCount);
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = nsnull;
for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
@ -508,7 +509,7 @@ nsARIAGridAccessible::GetSelectedCellIndices(PRUint32 *aCellsCount,
continue;
}
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = nsnull;
for (PRInt32 colIdx = 0; cell = cellIter.GetNext(); colIdx++) {
@ -557,7 +558,7 @@ nsARIAGridAccessible::GetSelectedRowIndices(PRUint32 *arowCount,
nsTArray<PRInt32> selRows(rowCount);
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = nsnull;
for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
@ -566,7 +567,7 @@ nsARIAGridAccessible::GetSelectedRowIndices(PRUint32 *arowCount,
continue;
}
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = cellIter.GetNext();
if (!cell)
continue;
@ -603,7 +604,7 @@ nsARIAGridAccessible::SelectRow(PRInt32 aRow)
if (IsDefunct())
return NS_ERROR_FAILURE;
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = nsnull;
for (PRInt32 rowIdx = 0; row = rowIter.GetNext(); rowIdx++) {
@ -622,7 +623,7 @@ nsARIAGridAccessible::SelectColumn(PRInt32 aColumn)
if (IsDefunct())
return NS_ERROR_FAILURE;
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = nsnull;
while ((row = rowIter.GetNext())) {
@ -661,7 +662,7 @@ nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn)
if (IsDefunct())
return NS_ERROR_FAILURE;
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = nsnull;
while ((row = rowIter.GetNext())) {
@ -730,7 +731,7 @@ nsARIAGridAccessible::GetRowAt(PRInt32 aRow)
{
PRInt32 rowIdx = aRow;
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = rowIter.GetNext();
while (rowIdx != 0 && (row = rowIter.GetNext()))
@ -744,7 +745,7 @@ nsARIAGridAccessible::GetCellInRowAt(nsAccessible *aRow, PRInt32 aColumn)
{
PRInt32 colIdx = aColumn;
nsAccIterator cellIter(aRow, nsAccIterator::GetCell);
AccIterator cellIter(aRow, filters::GetCell);
nsAccessible *cell = cellIter.GetNext();
while (colIdx != 0 && (cell = cellIter.GetNext()))
colIdx--;
@ -784,7 +785,7 @@ nsARIAGridAccessible::SetARIASelected(nsAccessible *aAccessible,
// If the given accessible is row that was unselected then remove
// aria-selected from cell accessible.
if (role == nsIAccessibleRole::ROLE_ROW) {
nsAccIterator cellIter(aAccessible, nsAccIterator::GetCell);
AccIterator cellIter(aAccessible, filters::GetCell);
nsAccessible *cell = nsnull;
while ((cell = cellIter.GetNext())) {
@ -807,7 +808,7 @@ nsARIAGridAccessible::SetARIASelected(nsAccessible *aAccessible,
rv = SetARIASelected(row, PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = nsnull;
while ((cell = cellIter.GetNext())) {
if (cell != aAccessible) {
@ -833,7 +834,7 @@ nsARIAGridAccessible::GetSelectedColumnsArray(PRUint32 *acolumnCount,
if (IsDefunct())
return NS_ERROR_FAILURE;
nsAccIterator rowIter(this, nsAccIterator::GetRow);
AccIterator rowIter(this, filters::GetRow);
nsAccessible *row = rowIter.GetNext();
if (!row)
return NS_OK;
@ -856,7 +857,7 @@ nsARIAGridAccessible::GetSelectedColumnsArray(PRUint32 *acolumnCount,
PRInt32 colIdx = 0;
nsAccIterator cellIter(row, nsAccIterator::GetCell);
AccIterator cellIter(row, filters::GetCell);
nsAccessible *cell = nsnull;
for (colIdx = 0; cell = cellIter.GetNext(); colIdx++) {
if (isColSelArray.SafeElementAt(colIdx, PR_FALSE) &&

View File

@ -52,7 +52,6 @@
#include "nsIDOMNode.h"
#include "nsINameSpaceManager.h"
#include "nsIStringBundle.h"
#include "nsRefPtrHashtable.h"
#include "nsWeakReference.h"
class nsAccessNode;

View File

@ -41,7 +41,7 @@
#include "nsIXBLAccessible.h"
#include "nsAccIterator.h"
#include "AccIterator.h"
#include "nsAccUtils.h"
#include "nsARIAMap.h"
#include "nsDocAccessible.h"
@ -2378,7 +2378,7 @@ NS_IMETHODIMP nsAccessible::GetSelectedChildren(nsIArray **aSelectedAccessibles)
do_CreateInstance(NS_ARRAY_CONTRACTID);
NS_ENSURE_STATE(selectedAccessibles);
nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
nsIAccessible *selected = nsnull;
while ((selected = iter.GetNext()))
selectedAccessibles->AppendElement(selected, PR_FALSE);
@ -2403,7 +2403,7 @@ NS_IMETHODIMP nsAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aSelect
return NS_ERROR_INVALID_ARG;
}
nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
nsAccessible *selected = nsnull;
PRInt32 count = 0;
@ -2423,7 +2423,7 @@ NS_IMETHODIMP nsAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
NS_ENSURE_ARG_POINTER(aSelectionCount);
*aSelectionCount = 0;
nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
nsAccessible *selected = nsnull;
while ((selected = iter.GetNext()))
++(*aSelectionCount);
@ -2485,7 +2485,7 @@ NS_IMETHODIMP nsAccessible::IsChildSelected(PRInt32 aIndex, PRBool *aIsSelected)
NS_IMETHODIMP
nsAccessible::ClearSelection()
{
nsAccIterator iter(this, nsAccIterator::GetSelected, nsAccIterator::eTreeNav);
AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
nsAccessible *selected = nsnull;
while ((selected = iter.GetNext()))
selected->SetSelected(PR_FALSE);
@ -2495,7 +2495,7 @@ nsAccessible::ClearSelection()
NS_IMETHODIMP nsAccessible::SelectAllSelection(PRBool *_retval)
{
nsAccIterator iter(this, nsAccIterator::GetSelectable, nsAccIterator::eTreeNav);
AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
nsAccessible *selectable = nsnull;
while((selectable = iter.GetNext()))
selectable->SetSelected(PR_TRUE);

View File

@ -50,6 +50,7 @@
#include "nsStringGlue.h"
#include "nsTArray.h"
#include "nsRefPtrHashtable.h"
class nsAccessible;
class nsAccEvent;

View File

@ -1321,27 +1321,25 @@ nsHyperTextAccessible::GetOffsetAtPoint(PRInt32 aX, PRInt32 aY,
return NS_OK; // Not found, will return -1
}
// ------- nsIAccessibleHyperText ---------------
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleHyperText
NS_IMETHODIMP
nsHyperTextAccessible::GetLinkCount(PRInt32 *aLinkCount)
{
NS_ENSURE_ARG_POINTER(aLinkCount);
*aLinkCount = 0;
if (IsDefunct())
return NS_ERROR_FAILURE;
PRInt32 childCount = GetChildCount();
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
nsAccessible *childAcc = mChildren[childIdx];
if (nsAccUtils::IsEmbeddedObject(childAcc))
++*aLinkCount;
}
*aLinkCount = GetLinkCount();
return NS_OK;
}
NS_IMETHODIMP
nsHyperTextAccessible::GetLink(PRInt32 aLinkIndex, nsIAccessibleHyperLink **aLink)
nsHyperTextAccessible::GetLinkAt(PRInt32 aIndex, nsIAccessibleHyperLink** aLink)
{
NS_ENSURE_ARG_POINTER(aLink);
*aLink = nsnull;
@ -1349,20 +1347,30 @@ nsHyperTextAccessible::GetLink(PRInt32 aLinkIndex, nsIAccessibleHyperLink **aLin
if (IsDefunct())
return NS_ERROR_FAILURE;
PRInt32 linkIndex = aLinkIndex;
nsAccessible* link = GetLinkAt(aIndex);
if (link)
CallQueryInterface(link, aLink);
PRInt32 childCount = GetChildCount();
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
nsAccessible *childAcc = mChildren[childIdx];
if (nsAccUtils::IsEmbeddedObject(childAcc) && linkIndex-- == 0)
return CallQueryInterface(childAcc, aLink);
}
return NS_ERROR_INVALID_ARG;
return NS_OK;
}
NS_IMETHODIMP
nsHyperTextAccessible::GetLinkIndex(PRInt32 aCharIndex, PRInt32 *aLinkIndex)
nsHyperTextAccessible::GetLinkIndex(nsIAccessibleHyperLink* aLink,
PRInt32* aIndex)
{
NS_ENSURE_ARG_POINTER(aLink);
if (IsDefunct())
return NS_ERROR_FAILURE;
nsRefPtr<nsAccessible> link(do_QueryObject(aLink));
*aIndex = GetLinkIndex(link);
return NS_OK;
}
NS_IMETHODIMP
nsHyperTextAccessible::GetLinkIndexAtOffset(PRInt32 aCharIndex,
PRInt32* aLinkIndex)
{
NS_ENSURE_ARG_POINTER(aLinkIndex);
*aLinkIndex = -1; // API says this magic value means 'not found'
@ -2029,6 +2037,19 @@ nsHyperTextAccessible::ScrollSubstringToPoint(PRInt32 aStartIndex,
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsAccessible public
void
nsHyperTextAccessible::InvalidateChildren()
{
mLinks = nsnull;
nsAccessibleWrap::InvalidateChildren();
}
////////////////////////////////////////////////////////////////////////////////
// nsHyperTextAccessible public static
nsresult nsHyperTextAccessible::ContentToRenderedOffset(nsIFrame *aFrame, PRInt32 aContentOffset,
PRUint32 *aRenderedOffset)
{
@ -2086,6 +2107,17 @@ nsresult nsHyperTextAccessible::RenderedToContentOffset(nsIFrame *aFrame, PRUint
////////////////////////////////////////////////////////////////////////////////
// nsHyperTextAccessible protected
AccCollector*
nsHyperTextAccessible::GetLinkCollector()
{
if (IsDefunct())
return nsnull;
if (!mLinks)
mLinks = new AccCollector(this, filters::GetEmbeddedObject);
return mLinks;
}
nsAccessible *
nsHyperTextAccessible::GetAccessibleAtOffset(PRInt32 aOffset, PRInt32 *aAccIdx,
PRInt32 *aStartOffset,

View File

@ -40,10 +40,12 @@
#ifndef _nsHyperTextAccessible_H_
#define _nsHyperTextAccessible_H_
#include "nsAccessibleWrap.h"
#include "nsIAccessibleText.h"
#include "nsIAccessibleHyperText.h"
#include "nsIAccessibleEditableText.h"
#include "AccCollector.h"
#include "nsAccessibleWrap.h"
#include "nsTextAttrs.h"
#include "nsFrameSelection.h"
@ -87,6 +89,10 @@ public:
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
virtual void InvalidateChildren();
// nsHyperTextAccessible
// Convert content offset to rendered text offset
static nsresult ContentToRenderedOffset(nsIFrame *aFrame, PRInt32 aContentOffset,
PRUint32 *aRenderedOffset);
@ -95,6 +101,33 @@ public:
static nsresult RenderedToContentOffset(nsIFrame *aFrame, PRUint32 aRenderedOffset,
PRInt32 *aContentOffset);
/**
* Return link count within this hypertext accessible.
*/
inline PRUint32 GetLinkCount()
{
AccCollector* links = GetLinkCollector();
return links ? links->Count() : 0;
}
/**
* Return link accessible at the given index.
*/
inline nsAccessible* GetLinkAt(PRUint32 aIndex)
{
AccCollector* links = GetLinkCollector();
return links ? links->GetAccessibleAt(aIndex) : nsnull;
}
/**
* Return index for the given link accessible.
*/
inline PRInt32 GetLinkIndex(nsAccessible* aLink)
{
AccCollector* links = GetLinkCollector();
return links ? links->GetIndexAt(aLink) : -1;
}
/**
* Turn a DOM Node and offset into a character offset into this hypertext.
* Will look for closest match when the DOM node does not have an accessible
@ -154,9 +187,13 @@ public:
PRInt32 *aEndOffset);
protected:
// nsHyperTextAccessible
/**
* Return link collection, create it if necessary.
*/
AccCollector* GetLinkCollector();
/*
* This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
* @param aType, eGetBefore, eGetAt, eGetAfter
@ -305,6 +342,9 @@ protected:
PRInt32 *aStartOffset,
PRInt32 *aEndOffset,
nsIPersistentProperties *aAttributes);
private:
nsAutoPtr<AccCollector> mLinks;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsHyperTextAccessible,

View File

@ -42,11 +42,7 @@
#include "AccessibleHypertext_i.c"
#include "nsIAccessibleHypertext.h"
#include "nsIWinAccessNode.h"
#include "nsAccessNodeWrap.h"
#include "nsCOMPtr.h"
#include "nsHyperTextAccessible.h"
// IUnknown
@ -75,16 +71,11 @@ CAccessibleHypertext::get_nHyperlinks(long *aHyperlinkCount)
__try {
*aHyperlinkCount = 0;
nsCOMPtr<nsIAccessibleHyperText> hyperAcc(do_QueryInterface(this));
if (!hyperAcc)
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(this);
if (!hyperText)
return E_FAIL;
PRInt32 count = 0;
nsresult rv = hyperAcc->GetLinkCount(&count);
if (NS_FAILED(rv))
return GetHRESULT(rv);
*aHyperlinkCount = count;
*aHyperlinkCount = hyperText->GetLinkCount();
return S_OK;
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
@ -98,22 +89,18 @@ CAccessibleHypertext::get_hyperlink(long aLinkIndex,
__try {
*aHyperlink = NULL;
nsCOMPtr<nsIAccessibleHyperText> hyperAcc(do_QueryInterface(this));
if (!hyperAcc)
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(this);
if (!hyperText)
return E_FAIL;
nsCOMPtr<nsIAccessibleHyperLink> hyperLink;
nsresult rv = hyperAcc->GetLink(aLinkIndex, getter_AddRefs(hyperLink));
if (NS_FAILED(rv))
return GetHRESULT(rv);
nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(hyperLink));
nsAccessible* hyperLink = hyperText->GetLinkAt(aLinkIndex);
nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryObject(hyperLink));
if (!winAccessNode)
return E_FAIL;
void *instancePtr = NULL;
rv = winAccessNode->QueryNativeInterface(IID_IAccessibleHyperlink,
&instancePtr);
nsresult rv = winAccessNode->QueryNativeInterface(IID_IAccessibleHyperlink,
&instancePtr);
if (NS_FAILED(rv))
return E_FAIL;
@ -135,7 +122,7 @@ __try {
return E_FAIL;
PRInt32 index = 0;
nsresult rv = hyperAcc->GetLinkIndex(aCharIndex, &index);
nsresult rv = hyperAcc->GetLinkIndexAtOffset(aCharIndex, &index);
if (NS_FAILED(rv))
return GetHRESULT(rv);

View File

@ -68,6 +68,9 @@ public:
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_hyperlinkIndex(
/* [in] */ long charIndex,
/* [retval][out] */ long *hyperlinkIndex);
// nsISupports
NS_IMETHOD QueryInterface(const nsIID& uuid, void** result) = 0;
};
#endif

View File

@ -20,23 +20,41 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
function testThis(aID, aCharIndex, aExpectedLinkIndex, aName)
{
is(gParagraphAcc.getLinkIndex(aCharIndex), aExpectedLinkIndex,
"Wrong link index for ID " + aID + "!");
var linkAcc = null;
try {
linkAcc = gParagraphAcc.getLink(aExpectedLinkIndex);
} catch(e) { }
is(gParagraphAcc.getLinkIndexAtOffset(aCharIndex), aExpectedLinkIndex,
"Wrong link index at offset " + aCharIndex + " for ID " + aID + "!");
var linkAcc = gParagraphAcc.getLinkAt(aExpectedLinkIndex);
ok(linkAcc, "No accessible for link " + aID + "!");
var linkIndex = gParagraphAcc.getLinkIndex(linkAcc);
is(linkIndex, aExpectedLinkIndex, "Wrong link index for " + aID + "!");
// Just test the link's name to make sure we get the right one.
is(linkAcc.getAnchor(0).name, aName, "Wrong name for " + aID + "!");
}
const kLinksCount = 128;
function prepareTest()
{
var container = document.getElementById("p3");
for (var jdx = 0; jdx < kLinksCount; jdx++) {
var a = document.createElement("a");
a.setAttribute("href", "mozilla.org");
a.textContent = "mozilla";
container.appendChild(a);
var span = document.createElement("span");
span.textContent = " text ";
container.appendChild(span);
}
window.setTimeout(doTest, 0);
}
function doTest()
{
gParagraphAcc = getAccessible("testParagraph", [nsIAccessibleHyperText]);
// Test link count
gParagraphAcc = getAccessible("testParagraph", [nsIAccessibleHyperText]);
is(gParagraphAcc.linkCount, 7, "Wrong link count for paragraph!");
// normal hyperlink
@ -60,16 +78,42 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
// Named anchor
testThis("namedAnchor", 193, 6, "This should never be of state_linked");
// Paragraph with link
var p2 = getAccessible("p2", [nsIAccessibleHyperText]);
var link = p2.getLinkAt(0);
is(link, p2.getChildAt(0), "Wrong link for p2");
is(p2.linkCount, 1, "Wrong link count for p2");
// getLinkAt and getLinkIndex.
var container = document.getElementById("p3");
var htAcc = getAccessible(container, [nsIAccessibleHyperText]);
for (var jdx = 0; jdx < kLinksCount; jdx++) {
var link = htAcc.getLinkAt(jdx);
ok(link, "No link at index " + jdx + " for 'p3'");
var linkIdx = htAcc.getLinkIndex(link);
is(linkIdx, jdx, "Wrong link index for 'p3'!");
};
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
addA11yLoadEvent(prepareTest);
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">Mozilla Bug 418368</a>
<a target="_blank"
title="Create tests for NSIAccessibleHyperlink interface"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">
Mozilla Bug 418368
</a><br>
<a target="_blank"
title="Cache links within hypertext accessible"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=572394">
Mozilla Bug 572394
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -104,5 +148,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
>Named anchor, must not have "linked" state for it to be exposed correctly:<br
><a id="namedAnchor" name="named_anchor">This should never be of state_linked</a>
</p>
<p id="p2"><a href="http://mozilla.org">mozilla.org</a></p>
<p id="p3"></p>
</body>
</html>