Bug 742657 - move nsAccUtils::GetRoleMapEntry(nsINode *aNode) into nsARIAMap, r=tbsaunde, f=surkov

This commit is contained in:
pcheng@gmx.com 2012-04-16 18:24:23 +09:00
parent 58735a46be
commit c5469403d7
9 changed files with 76 additions and 78 deletions

View File

@ -39,11 +39,14 @@
#include "nsARIAMap.h"
#include "nsCoreUtils.h"
#include "Role.h"
#include "States.h"
#include "nsIContent.h"
#include "nsWhitespaceTokenizer.h"
using namespace mozilla;
using namespace mozilla::a11y;
using namespace mozilla::a11y::aria;
@ -62,7 +65,7 @@ using namespace mozilla::a11y::aria;
* banner, contentinfo, main, navigation, note, search, secondary, seealso, breadcrumbs
*/
nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
static nsRoleMapEntry sWAIRoleMaps[] =
{
{
"alert",
@ -586,9 +589,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
}
};
PRUint32 nsARIAMap::gWAIRoleMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIRoleMap);
nsRoleMapEntry nsARIAMap::gLandmarkRoleMap = {
static nsRoleMapEntry sLandmarkRoleMap = {
"",
roles::NOTHING,
kUseNativeRole,
@ -667,3 +668,39 @@ nsAttributeCharacteristics nsARIAMap::gWAIUnivAttrMap[] = {
};
PRUint32 nsARIAMap::gWAIUnivAttrMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIUnivAttrMap);
nsRoleMapEntry*
aria::GetRoleMap(nsINode* aNode)
{
nsIContent* content = nsCoreUtils::GetRoleContent(aNode);
nsAutoString roleString;
if (!content ||
!content->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roleString) ||
roleString.IsEmpty()) {
// We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
return nsnull;
}
nsWhitespaceTokenizer tokenizer(roleString);
while (tokenizer.hasMoreTokens()) {
// Do a binary search through table for the next role in role list
NS_LossyConvertUTF16toASCII role(tokenizer.nextToken());
PRUint32 low = 0;
PRUint32 high = ArrayLength(sWAIRoleMaps);
while (low < high) {
PRUint32 idx = (low + high) / 2;
PRInt32 compare = strcmp(role.get(), sWAIRoleMaps[idx].roleString);
if (compare == 0)
return sWAIRoleMaps + idx;
if (compare < 0)
high = idx;
else
low = idx + 1;
}
}
// Always use some entry if there is a non-empty role string
// To ensure an accessible object is created
return &sLandmarkRoleMap;
}

View File

@ -45,6 +45,7 @@
class nsIAtom;
class nsIContent;
class nsINode;
////////////////////////////////////////////////////////////////////////////////
// Value constants
@ -210,18 +211,6 @@ struct nsRoleMapEntry
*/
struct nsARIAMap
{
/**
* Array of supported ARIA role map entries and its length.
*/
static nsRoleMapEntry gWAIRoleMap[];
static PRUint32 gWAIRoleMapLength;
/**
* Landmark role map entry. Used when specified ARIA role isn't mapped to
* accessibility API.
*/
static nsRoleMapEntry gLandmarkRoleMap;
/**
* Empty role map entry. Used by accessibility service to create an accessible
* if the accessible can't use role of used accessible class. For example,
@ -257,4 +246,22 @@ struct nsARIAMap
}
};
namespace mozilla {
namespace a11y {
namespace aria {
/**
* Get the role map entry for a given DOM node. This will use the first
* ARIA role if the role attribute provides a space delimited list of roles.
*
* @param aNode [in] the DOM node to get the role map entry for
* @return a pointer to the role map entry for the ARIA role, or nsnull
* if none
*/
nsRoleMapEntry* GetRoleMap(nsINode* aNode);
} // namespace aria
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -41,6 +41,7 @@
#include "nsAccessibilityService.h"
#include "nsAccUtils.h"
#include "nsApplicationAccessible.h"
#include "nsARIAMap.h"
#include "nsRootAccessibleWrap.h"
#include "States.h"
@ -402,7 +403,7 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
docAcc->Shutdown();
return nsnull;
}
docAcc->SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aDocument));
docAcc->SetRoleMapEntry(aria::GetRoleMap(aDocument));
// Bind the document to the tree.
if (isRootDoc) {

View File

@ -174,7 +174,7 @@ nsAccUtils::SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
// container-live, and container-live-role attributes
if (live.IsEmpty()) {
nsRoleMapEntry *role = GetRoleMapEntry(ancestor);
nsRoleMapEntry* role = aria::GetRoleMap(ancestor);
if (nsAccUtils::HasDefinedARIAToken(ancestor,
nsGkAtoms::aria_live)) {
ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_live,
@ -418,45 +418,6 @@ nsAccUtils::GetScreenCoordsForParent(nsAccessNode *aAccessNode)
return nsIntPoint(parentRect.x, parentRect.y);
}
nsRoleMapEntry*
nsAccUtils::GetRoleMapEntry(nsINode *aNode)
{
nsIContent *content = nsCoreUtils::GetRoleContent(aNode);
nsAutoString roleString;
if (!content ||
!content->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roleString) ||
roleString.IsEmpty()) {
// We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
return nsnull;
}
nsWhitespaceTokenizer tokenizer(roleString);
while (tokenizer.hasMoreTokens()) {
// Do a binary search through table for the next role in role list
NS_LossyConvertUTF16toASCII role(tokenizer.nextToken());
PRUint32 low = 0;
PRUint32 high = nsARIAMap::gWAIRoleMapLength;
while (low < high) {
PRUint32 index = (low + high) / 2;
PRInt32 compare = PL_strcmp(role.get(), nsARIAMap::gWAIRoleMap[index].roleString);
if (compare == 0) {
// The role attribute maps to an entry in the role table
return &nsARIAMap::gWAIRoleMap[index];
}
if (compare < 0) {
high = index;
}
else {
low = index + 1;
}
}
}
// Always use some entry if there is a non-empty role string
// To ensure an accessible object is created
return &nsARIAMap::gLandmarkRoleMap;
}
PRUint8
nsAccUtils::GetAttributeCharacteristics(nsIAtom* aAtom)
{

View File

@ -249,16 +249,6 @@ public:
*/
static nsIntPoint GetScreenCoordsForParent(nsAccessNode *aAccessNode);
/**
* Get the role map entry for a given DOM node. This will use the first
* ARIA role if the role attribute provides a space delimited list of roles.
*
* @param aNode [in] the DOM node to get the role map entry for
* @return a pointer to the role map entry for the ARIA role, or nsnull
* if none
*/
static nsRoleMapEntry *GetRoleMapEntry(nsINode *aNode);
/**
* Return the role of the given accessible.
*/

View File

@ -1075,12 +1075,12 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
}
newAcc = new nsHyperTextAccessibleWrap(content, docAcc);
if (docAcc->BindToDocument(newAcc, nsAccUtils::GetRoleMapEntry(aNode)))
if (docAcc->BindToDocument(newAcc, aria::GetRoleMap(aNode)))
return newAcc;
return nsnull;
}
nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aNode);
if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation")) {
// Ignore presentation role if element is focusable (focus event shouldn't
// be ever lost and should be sensible).
@ -1127,8 +1127,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
}
#ifdef DEBUG
nsRoleMapEntry *tableRoleMapEntry =
nsAccUtils::GetRoleMapEntry(tableContent);
nsRoleMapEntry* tableRoleMapEntry = aria::GetRoleMap(tableContent);
NS_ASSERTION(tableRoleMapEntry &&
!nsCRT::strcmp(tableRoleMapEntry->roleString, "presentation"),
"No accessible for parent table and it didn't have role of presentation");
@ -1667,7 +1666,7 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame* aFrame,
if (tag == nsGkAtoms::a) {
// Only some roles truly enjoy life as nsHTMLLinkAccessibles, for details
// see closed bug 494807.
nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aContent);
nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent);
if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
roleMapEntry->role != roles::LINK) {
nsAccessible* accessible = new nsHyperTextAccessibleWrap(aContent, aDoc);

View File

@ -276,7 +276,7 @@ public:
* @param aRoleMapEntry The ARIA nsRoleMapEntry* for the accessible, or
* nsnull if none.
*/
virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry);
virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
/**
* Update the children cache.
@ -836,8 +836,11 @@ protected:
nsAutoPtr<AccGroupInfo> mGroupInfo;
friend class AccGroupInfo;
nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
/**
* Non-null indicates author-supplied role; possibly state & value as well
*/
nsRoleMapEntry* mRoleMapEntry;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessible,

View File

@ -285,7 +285,7 @@ nsDocAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
// Allow use of ARIA role from outer to override
nsIContent *ownerContent = parentDoc->FindContentForSubDocument(mDocument);
if (ownerContent) {
nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(ownerContent);
nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(ownerContent);
if (roleMapEntry)
mRoleMapEntry = roleMapEntry; // Override
}
@ -1698,7 +1698,7 @@ nsDocAccessible::UpdateAccessibleOnAttrChange(dom::Element* aElement,
// It is common for js libraries to set the role on the body element after
// the document has loaded. In this case we just update the role map entry.
if (mContent == aElement) {
SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aElement));
SetRoleMapEntry(aria::GetRoleMap(aElement));
return true;
}

View File

@ -143,7 +143,7 @@ nsHTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
nsAccessible* area = mChildren.SafeElementAt(idx);
if (!area || area->GetContent() != areaContent) {
nsRefPtr<nsAccessible> area = new nsHTMLAreaAccessible(areaContent, mDoc);
if (!mDoc->BindToDocument(area, nsAccUtils::GetRoleMapEntry(areaContent)))
if (!mDoc->BindToDocument(area, aria::GetRoleMap(areaContent)))
break;
if (!InsertChildAt(idx, area)) {