Bug 545467 - nsHTMLImageAccessible shouldn't allocate hash in dynamic memory, r=davidb

--HG--
rename : accessible/src/html/nsHTMLAreaAccessible.cpp => accessible/src/html/nsHTMLImageMapAccessible.cpp
rename : accessible/src/html/nsHTMLAreaAccessible.h => accessible/src/html/nsHTMLImageMapAccessible.h
This commit is contained in:
Alexander Surkov 2010-04-06 09:41:28 +09:00
parent e7503e900c
commit 1e89892691
8 changed files with 444 additions and 380 deletions

View File

@ -197,6 +197,7 @@ ACCESSIBILITY_ATOM(tabindex, "tabindex")
ACCESSIBILITY_ATOM(title, "title")
ACCESSIBILITY_ATOM(tooltiptext, "tooltiptext")
ACCESSIBILITY_ATOM(type, "type")
ACCESSIBILITY_ATOM(usemap, "usemap")
ACCESSIBILITY_ATOM(value, "value")
// Alphabetical list of object attributes

View File

@ -47,7 +47,7 @@
#include "nsIContentViewer.h"
#include "nsCURILoader.h"
#include "nsDocAccessible.h"
#include "nsHTMLImageAccessibleWrap.h"
#include "nsHTMLImageMapAccessible.h"
#include "nsHTMLLinkAccessible.h"
#include "nsHTMLSelectAccessible.h"
#include "nsHTMLTableAccessibleWrap.h"
@ -55,6 +55,7 @@
#include "nsHyperTextAccessibleWrap.h"
#include "nsIAccessibilityService.h"
#include "nsIAccessibleProvider.h"
#include "nsIDOMDocument.h"
#include "nsIDOMHTMLAreaElement.h"
#include "nsIDOMHTMLLegendElement.h"
@ -63,6 +64,7 @@
#include "nsIDOMHTMLOptionElement.h"
#include "nsIDOMWindow.h"
#include "nsIDOMXULElement.h"
#include "nsIHTMLDocument.h"
#include "nsIDocShell.h"
#include "nsIFrame.h"
#include "nsIInterfaceRequestorUtils.h"
@ -636,24 +638,46 @@ nsAccessibilityService::CreateHTMLComboboxAccessible(nsIDOMNode* aDOMNode, nsIWe
}
NS_IMETHODIMP
nsAccessibilityService::CreateHTMLImageAccessible(nsIFrame *aFrame, nsIAccessible **_retval)
nsAccessibilityService::CreateHTMLImageAccessible(nsIFrame *aFrame,
nsIAccessible **aAccessible)
{
NS_ENSURE_ARG_POINTER(aAccessible);
*aAccessible = nsnull;
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsIWeakReference> weakShell;
nsresult rv = GetInfo(aFrame, getter_AddRefs(weakShell), getter_AddRefs(node));
if (NS_FAILED(rv))
return rv;
*_retval = nsnull;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(node));
if (domElement) {
*_retval = new nsHTMLImageAccessibleWrap(node, weakShell);
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
NS_ENSURE_STATE(content);
nsCOMPtr<nsIHTMLDocument> htmlDoc =
do_QueryInterface(content->GetCurrentDoc());
nsCOMPtr<nsIDOMHTMLMapElement> mapElm;
if (htmlDoc) {
nsAutoString mapElmName;
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::usemap,
mapElmName);
if (!mapElmName.IsEmpty()) {
if (mapElmName.CharAt(0) == '#')
mapElmName.Cut(0,1);
mapElm = htmlDoc->GetImageMap(mapElmName);
}
}
if (! *_retval)
if (mapElm)
*aAccessible = new nsHTMLImageMapAccessible(node, weakShell, mapElm);
else
*aAccessible = new nsHTMLImageAccessibleWrap(node, weakShell);
if (!*aAccessible)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval);
NS_ADDREF(*aAccessible);
return NS_OK;
}

View File

@ -50,9 +50,9 @@ LIBXUL_LIBRARY = 1
CPPSRCS = \
nsHTMLAreaAccessible.cpp \
nsHTMLFormControlAccessible.cpp \
nsHTMLImageAccessible.cpp \
nsHTMLImageMapAccessible.cpp \
nsHTMLLinkAccessible.cpp \
nsHTMLSelectAccessible.cpp \
nsHTMLTableAccessible.cpp \

View File

@ -1,158 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Author: Aaron Leventhal (aaronl@netscape.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"),
* 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 "nsHTMLAreaAccessible.h"
#include "nsIServiceManager.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLAreaElement.h"
#include "nsIFrame.h"
#include "nsIImageFrame.h"
#include "nsIImageMap.h"
////////////////////////////////////////////////////////////////////////////////
// nsHTMLAreaAccessible
////////////////////////////////////////////////////////////////////////////////
nsHTMLAreaAccessible::
nsHTMLAreaAccessible(nsIDOMNode *aDomNode, nsIAccessible *aParent,
nsIWeakReference* aShell):
nsHTMLLinkAccessible(aDomNode, aShell)
{
}
////////////////////////////////////////////////////////////////////////////////
// nsIAccessible
nsresult
nsHTMLAreaAccessible::GetNameInternal(nsAString & aName)
{
nsresult rv = nsAccessible::GetNameInternal(aName);
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)) {
return GetValue(aName);
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaAccessible::GetDescription(nsAString& aDescription)
{
aDescription.Truncate();
// Still to do - follow IE's standard here
nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mDOMNode));
if (area)
area->GetShape(aDescription);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaAccessible::GetBounds(PRInt32 *x, PRInt32 *y,
PRInt32 *width, PRInt32 *height)
{
nsresult rv;
// Essentially this uses GetRect on mAreas of nsImageMap from nsImageFrame
*x = *y = *width = *height = 0;
nsPresContext *presContext = GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
nsCOMPtr<nsIContent> ourContent(do_QueryInterface(mDOMNode));
NS_ENSURE_TRUE(ourContent, NS_ERROR_FAILURE);
nsIFrame *frame = GetFrame();
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
nsIImageFrame *imageFrame = do_QueryFrame(frame);
nsCOMPtr<nsIImageMap> map;
imageFrame->GetImageMap(presContext, getter_AddRefs(map));
NS_ENSURE_TRUE(map, NS_ERROR_FAILURE);
nsRect rect;
nsIntRect orgRectPixels;
rv = map->GetBoundsForAreaContent(ourContent, rect);
NS_ENSURE_SUCCESS(rv, rv);
*x = presContext->AppUnitsToDevPixels(rect.x);
*y = presContext->AppUnitsToDevPixels(rect.y);
// XXX Areas are screwy; they return their rects as a pair of points, one pair
// stored into the width and height.
*width = presContext->AppUnitsToDevPixels(rect.width - rect.x);
*height = presContext->AppUnitsToDevPixels(rect.height - rect.y);
// Put coords in absolute screen coords
orgRectPixels = frame->GetScreenRectExternal();
*x += orgRectPixels.x;
*y += orgRectPixels.y;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsAccessible public implementation
nsresult
nsHTMLAreaAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
PRBool aDeepestChild,
nsIAccessible **aChild)
{
// Don't walk into area accessibles.
NS_ADDREF(*aChild = this);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsAccessible protected implementation
void
nsHTMLAreaAccessible::CacheChildren()
{
// No children for aria accessible.
}

View File

@ -41,11 +41,8 @@
#include "nsHTMLImageAccessible.h"
#include "nsAccessibilityAtoms.h"
#include "nsHTMLAreaAccessible.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIDocument.h"
#include "nsIHTMLDocument.h"
#include "nsIImageLoadingContent.h"
#include "nsILink.h"
#include "nsIPresShell.h"
@ -54,45 +51,21 @@
#include "nsIDOMDocument.h"
#include "nsPIDOMWindow.h"
// --- image -----
const PRUint32 kDefaultImageCacheSize = 256;
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageAccessible
////////////////////////////////////////////////////////////////////////////////
nsHTMLImageAccessible::nsHTMLImageAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell):
nsLinkableAccessible(aDOMNode, aShell), mAccessNodeCache(nsnull)
{
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aDOMNode));
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (!shell)
return;
nsIDocument *doc = shell->GetDocument();
nsAutoString mapElementName;
if (doc && element) {
nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(doc));
element->GetAttribute(NS_LITERAL_STRING("usemap"),mapElementName);
if (htmlDoc && !mapElementName.IsEmpty()) {
if (mapElementName.CharAt(0) == '#')
mapElementName.Cut(0,1);
mMapElement = htmlDoc->GetImageMap(mapElementName);
}
}
if (mMapElement) {
mAccessNodeCache = new nsAccessNodeHashtable();
mAccessNodeCache->Init(kDefaultImageCacheSize);
}
nsHTMLImageAccessible::
nsHTMLImageAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell) :
nsLinkableAccessible(aDOMNode, aShell)
{
}
NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLImageAccessible, nsAccessible,
nsIAccessibleImage)
////////////////////////////////////////////////////////////////////////////////
// nsIAccessible
// nsAccessible public
nsresult
nsHTMLImageAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
@ -150,34 +123,12 @@ nsHTMLImageAccessible::GetNameInternal(nsAString& aName)
nsresult
nsHTMLImageAccessible::GetRoleInternal(PRUint32 *aRole)
{
*aRole = mMapElement ? nsIAccessibleRole::ROLE_IMAGE_MAP :
nsIAccessibleRole::ROLE_GRAPHIC;
*aRole = nsIAccessibleRole::ROLE_GRAPHIC;
return NS_OK;
}
void
nsHTMLImageAccessible::CacheChildren()
{
nsCOMPtr<nsIDOMHTMLCollection> mapAreas = GetAreaCollection();
if (!mapAreas)
return;
PRUint32 areaCount = 0;
mapAreas->GetLength(&areaCount);
nsCOMPtr<nsIAccessible> areaAccessible;
nsRefPtr<nsAccessible> areaAcc;
for (PRUint32 areaIdx = 0; areaIdx < areaCount; areaIdx++) {
areaAccessible = GetAreaAccessible(mapAreas, areaIdx);
if (!areaAccessible)
return;
areaAcc = nsAccUtils::QueryObject<nsAccessible>(areaAccessible);
mChildren.AppendElement(areaAcc);
areaAcc->SetParent(this);
}
}
////////////////////////////////////////////////////////////////////////////////
// nsIAccessible
NS_IMETHODIMP
nsHTMLImageAccessible::GetNumActions(PRUint8 *aNumActions)
@ -239,66 +190,6 @@ nsHTMLImageAccessible::DoAction(PRUint8 aIndex)
return nsLinkableAccessible::DoAction(aIndex);
}
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleHyperLink
NS_IMETHODIMP
nsHTMLImageAccessible::GetAnchorCount(PRInt32 *aAnchorCount)
{
NS_ENSURE_ARG_POINTER(aAnchorCount);
if (!mMapElement)
return nsLinkableAccessible::GetAnchorCount(aAnchorCount);
return GetChildCount(aAnchorCount);
}
NS_IMETHODIMP
nsHTMLImageAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
*aURI = nsnull;
if (!mMapElement)
return nsLinkableAccessible::GetURI(aIndex, aURI);
nsCOMPtr<nsIDOMHTMLCollection> mapAreas = GetAreaCollection();
if (!mapAreas)
return NS_OK;
nsCOMPtr<nsIDOMNode> domNode;
mapAreas->Item(aIndex, getter_AddRefs(domNode));
if (!domNode)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIContent> link(do_QueryInterface(domNode));
if (link)
*aURI = link->GetHrefURI().get();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLImageAccessible::GetAnchor(PRInt32 aIndex, nsIAccessible **aAccessible)
{
NS_ENSURE_ARG_POINTER(aAccessible);
*aAccessible = nsnull;
if (!mMapElement)
return nsLinkableAccessible::GetAnchor(aIndex, aAccessible);
nsCOMPtr<nsIDOMHTMLCollection> mapAreas = GetAreaCollection();
if (mapAreas) {
nsCOMPtr<nsIAccessible> accessible;
accessible = GetAreaAccessible(mapAreas, aIndex);
if (!accessible)
return NS_ERROR_INVALID_ARG;
NS_ADDREF(*aAccessible = accessible);
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIAccessibleImage
@ -321,26 +212,7 @@ nsHTMLImageAccessible::GetImageSize(PRInt32 *aWidth, PRInt32 *aHeight)
return GetBounds(&x, &y, aWidth, aHeight);
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageAccessible. nsAccessNode
nsresult
nsHTMLImageAccessible::Shutdown()
{
nsLinkableAccessible::Shutdown();
if (mAccessNodeCache) {
ClearCache(*mAccessNodeCache);
delete mAccessNodeCache;
mAccessNodeCache = nsnull;
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageAccessible
// nsAccessible
nsresult
nsHTMLImageAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
{
@ -360,51 +232,6 @@ nsHTMLImageAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
return NS_OK;
}
already_AddRefed<nsIDOMHTMLCollection>
nsHTMLImageAccessible::GetAreaCollection()
{
if (!mMapElement)
return nsnull;
nsIDOMHTMLCollection *mapAreas = nsnull;
nsresult rv = mMapElement->GetAreas(&mapAreas);
if (NS_FAILED(rv))
return nsnull;
return mapAreas;
}
already_AddRefed<nsIAccessible>
nsHTMLImageAccessible::GetAreaAccessible(nsIDOMHTMLCollection *aAreaCollection,
PRInt32 aAreaNum)
{
if (!aAreaCollection)
return nsnull;
nsCOMPtr<nsIDOMNode> domNode;
aAreaCollection->Item(aAreaNum,getter_AddRefs(domNode));
if (!domNode)
return nsnull;
void* key = reinterpret_cast<void*>(aAreaNum);
nsRefPtr<nsAccessNode> accessNode = mAccessNodeCache->GetWeak(key);
if (!accessNode) {
accessNode = new nsHTMLAreaAccessible(domNode, this, mWeakShell);
if (!accessNode)
return nsnull;
nsresult rv = accessNode->Init();
if (NS_FAILED(rv))
return nsnull;
mAccessNodeCache->Put(key, accessNode);
}
nsCOMPtr<nsIAccessible> accessible = do_QueryInterface(accessNode);
return accessible.forget();
}
////////////////////////////////////////////////////////////////////////////////
// Private methods

View File

@ -40,7 +40,6 @@
#define _nsHTMLImageAccessible_H_
#include "nsBaseWidgetAccessible.h"
#include "nsIDOMHTMLMapElement.h"
#include "nsIAccessibleImage.h"
/* Accessible for supporting images
@ -51,51 +50,26 @@
class nsHTMLImageAccessible : public nsLinkableAccessible,
public nsIAccessibleImage
{
NS_DECL_ISUPPORTS_INHERITED
public:
nsHTMLImageAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIAccessible
NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 index);
// nsIAccessibleHyperLink
NS_IMETHOD GetAnchorCount(PRInt32 *aAnchorCount);
NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
NS_IMETHOD GetAnchor(PRInt32 aIndex, nsIAccessible **aAccessible);
// nsIAccessibleImage
NS_DECL_NSIACCESSIBLEIMAGE
// nsAccessNode
virtual nsresult Shutdown();
// nsAccessible
virtual nsresult GetNameInternal(nsAString& aName);
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
protected:
// nsAccessible
virtual void CacheChildren();
// nsHTMLImageAccessible
already_AddRefed<nsIDOMHTMLCollection> GetAreaCollection();
already_AddRefed<nsIAccessible>
GetAreaAccessible(nsIDOMHTMLCollection* aAreaNodes, PRInt32 aAreaNum);
// Reference on linked map element if any.
nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
// Cache of area accessibles. We do not use common cache because images can
// share area elements but we need to have separate area accessibles for
// each image accessible.
nsAccessNodeHashtable *mAccessNodeCache;
private:
/**
* Determine if this image accessible has a longdesc attribute.

View File

@ -0,0 +1,339 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Leventhal <aaronl@netscape.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"),
* 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 "nsHTMLImageMapAccessible.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIServiceManager.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLAreaElement.h"
#include "nsIFrame.h"
#include "nsIImageFrame.h"
#include "nsIImageMap.h"
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageMapAccessible
////////////////////////////////////////////////////////////////////////////////
const PRUint32 kDefaultImageMapCacheSize = 256;
nsHTMLImageMapAccessible::
nsHTMLImageMapAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
nsIDOMHTMLMapElement *aMapElm) :
nsHTMLImageAccessibleWrap(aDOMNode, aShell), mMapElement(aMapElm)
{
mAreaAccCache.Init(kDefaultImageMapCacheSize);
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageMapAccessible: nsISupports and cycle collector
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLImageMapAccessible)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLImageMapAccessible,
nsAccessible)
CycleCollectorTraverseCache(tmp->mAreaAccCache, &cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLImageMapAccessible,
nsAccessible)
ClearCache(tmp->mAreaAccCache);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsHTMLImageMapAccessible)
NS_INTERFACE_MAP_END_INHERITING(nsHTMLImageAccessible)
NS_IMPL_ADDREF_INHERITED(nsHTMLImageMapAccessible, nsHTMLImageAccessible)
NS_IMPL_RELEASE_INHERITED(nsHTMLImageMapAccessible, nsHTMLImageAccessible)
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageMapAccessible: nsIAccessibleHyperLink
NS_IMETHODIMP
nsHTMLImageMapAccessible::GetAnchorCount(PRInt32 *aAnchorCount)
{
NS_ENSURE_ARG_POINTER(aAnchorCount);
return GetChildCount(aAnchorCount);
}
NS_IMETHODIMP
nsHTMLImageMapAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
*aURI = nsnull;
nsCOMPtr<nsIDOMHTMLCollection> mapAreas = GetAreaCollection();
if (!mapAreas)
return NS_OK;
nsCOMPtr<nsIDOMNode> domNode;
mapAreas->Item(aIndex, getter_AddRefs(domNode));
if (!domNode)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIContent> link(do_QueryInterface(domNode));
if (link)
*aURI = link->GetHrefURI().get();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLImageMapAccessible::GetAnchor(PRInt32 aIndex, nsIAccessible **aAccessible)
{
NS_ENSURE_ARG_POINTER(aAccessible);
*aAccessible = nsnull;
nsCOMPtr<nsIDOMHTMLCollection> mapAreas = GetAreaCollection();
if (mapAreas) {
nsRefPtr<nsIAccessible> accessible = GetAreaAccessible(mapAreas, aIndex);
if (!accessible)
return NS_ERROR_INVALID_ARG;
NS_ADDREF(*aAccessible = accessible);
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageAccessible: nsAccessNode
nsresult
nsHTMLImageMapAccessible::Shutdown()
{
nsLinkableAccessible::Shutdown();
ClearCache(mAreaAccCache);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageMapAccessible: nsAccessible public
nsresult
nsHTMLImageMapAccessible::GetRoleInternal(PRUint32 *aRole)
{
*aRole = nsIAccessibleRole::ROLE_IMAGE_MAP;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageMapAccessible: nsAccessible protected
void
nsHTMLImageMapAccessible::CacheChildren()
{
nsCOMPtr<nsIDOMHTMLCollection> mapAreas = GetAreaCollection();
if (!mapAreas)
return;
PRUint32 areaCount = 0;
mapAreas->GetLength(&areaCount);
nsRefPtr<nsAccessible> areaAcc;
for (PRUint32 areaIdx = 0; areaIdx < areaCount; areaIdx++) {
areaAcc = GetAreaAccessible(mapAreas, areaIdx);
if (!areaAcc)
return;
mChildren.AppendElement(areaAcc);
areaAcc->SetParent(this);
}
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLImageAccessible
already_AddRefed<nsIDOMHTMLCollection>
nsHTMLImageMapAccessible::GetAreaCollection()
{
if (!mMapElement)
return nsnull;
nsIDOMHTMLCollection *mapAreas = nsnull;
mMapElement->GetAreas(&mapAreas);
return mapAreas;
}
already_AddRefed<nsAccessible>
nsHTMLImageMapAccessible::GetAreaAccessible(nsIDOMHTMLCollection *aAreaCollection,
PRInt32 aAreaNum)
{
if (!aAreaCollection)
return nsnull;
nsCOMPtr<nsIDOMNode> domNode;
aAreaCollection->Item(aAreaNum,getter_AddRefs(domNode));
if (!domNode)
return nsnull;
void *key = reinterpret_cast<void*>(aAreaNum);
nsRefPtr<nsAccessible> accessible = mAreaAccCache.GetWeak(key);
if (!accessible) {
accessible = new nsHTMLAreaAccessible(domNode, this, mWeakShell);
if (!accessible)
return nsnull;
nsresult rv = accessible->Init();
if (NS_FAILED(rv)) {
accessible->Shutdown();
return nsnull;
}
mAreaAccCache.Put(key, accessible);
}
return accessible.forget();
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLAreaAccessible
////////////////////////////////////////////////////////////////////////////////
nsHTMLAreaAccessible::
nsHTMLAreaAccessible(nsIDOMNode *aDomNode, nsIAccessible *aParent,
nsIWeakReference* aShell):
nsHTMLLinkAccessible(aDomNode, aShell)
{
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLAreaAccessible: nsIAccessible
nsresult
nsHTMLAreaAccessible::GetNameInternal(nsAString & aName)
{
nsresult rv = nsAccessible::GetNameInternal(aName);
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)) {
return GetValue(aName);
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaAccessible::GetDescription(nsAString& aDescription)
{
aDescription.Truncate();
// Still to do - follow IE's standard here
nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mDOMNode));
if (area)
area->GetShape(aDescription);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLAreaAccessible::GetBounds(PRInt32 *x, PRInt32 *y,
PRInt32 *width, PRInt32 *height)
{
nsresult rv;
// Essentially this uses GetRect on mAreas of nsImageMap from nsImageFrame
*x = *y = *width = *height = 0;
nsPresContext *presContext = GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
nsCOMPtr<nsIContent> ourContent(do_QueryInterface(mDOMNode));
NS_ENSURE_TRUE(ourContent, NS_ERROR_FAILURE);
nsIFrame *frame = GetFrame();
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
nsIImageFrame *imageFrame = do_QueryFrame(frame);
nsCOMPtr<nsIImageMap> map;
imageFrame->GetImageMap(presContext, getter_AddRefs(map));
NS_ENSURE_TRUE(map, NS_ERROR_FAILURE);
nsRect rect;
nsIntRect orgRectPixels;
rv = map->GetBoundsForAreaContent(ourContent, rect);
NS_ENSURE_SUCCESS(rv, rv);
*x = presContext->AppUnitsToDevPixels(rect.x);
*y = presContext->AppUnitsToDevPixels(rect.y);
// XXX Areas are screwy; they return their rects as a pair of points, one pair
// stored into the width and height.
*width = presContext->AppUnitsToDevPixels(rect.width - rect.x);
*height = presContext->AppUnitsToDevPixels(rect.height - rect.y);
// Put coords in absolute screen coords
orgRectPixels = frame->GetScreenRectExternal();
*x += orgRectPixels.x;
*y += orgRectPixels.y;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLAreaAccessible: nsAccessible public
nsresult
nsHTMLAreaAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
PRBool aDeepestChild,
nsIAccessible **aChild)
{
// Don't walk into area accessibles.
NS_ADDREF(*aChild = this);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsHTMLAreaAccessible: nsAccessible protected
void
nsHTMLAreaAccessible::CacheChildren()
{
// No children for aria accessible.
}

View File

@ -20,7 +20,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Author: Aaron Leventhal (aaronl@netscape.com)
* Aaron Leventhal <aaronl@netscape.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"),
@ -40,6 +41,62 @@
#define _nsHTMLAreaAccessible_H_
#include "nsHTMLLinkAccessible.h"
#include "nsHTMLImageAccessibleWrap.h"
#include "nsIDOMHTMLMapElement.h"
/**
* Used for HTML image maps.
*/
class nsHTMLImageMapAccessible : public nsHTMLImageAccessibleWrap
{
public:
nsHTMLImageMapAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell,
nsIDOMHTMLMapElement *aMapElm);
// nsISupports and cycle collector
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLImageMapAccessible,
nsAccessible)
// nsIAccessibleHyperLink
NS_IMETHOD GetAnchorCount(PRInt32 *aAnchorCount);
NS_IMETHOD GetURI(PRInt32 aIndex, nsIURI **aURI);
NS_IMETHOD GetAnchor(PRInt32 aIndex, nsIAccessible **aAccessible);
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
protected:
// nsAccessNode
virtual nsresult Shutdown();
// nsAccessible
virtual void CacheChildren();
// nsHTMLImageAccessible
/**
* Return collection of HTML area elements associated with the image map.
*/
already_AddRefed<nsIDOMHTMLCollection> GetAreaCollection();
/**
* Return an accessible for HTML area element at the given index.
*/
already_AddRefed<nsAccessible>
GetAreaAccessible(nsIDOMHTMLCollection* aAreaNodes, PRInt32 aAreaNum);
private:
// Reference on linked map element if any.
nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
// Cache of area accessibles. We do not use common cache because images can
// share area elements but we need to have separate area accessibles for
// each image accessible.
nsAccessibleHashtable mAreaAccCache;
};
/**
* Accessible for image map areas - must be child of image.