1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/generic/ImageAccessible.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,228 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "ImageAccessible.h" 1.10 + 1.11 +#include "nsAccUtils.h" 1.12 +#include "Role.h" 1.13 +#include "AccIterator.h" 1.14 +#include "States.h" 1.15 + 1.16 +#include "imgIContainer.h" 1.17 +#include "imgIRequest.h" 1.18 +#include "nsGenericHTMLElement.h" 1.19 +#include "nsIDocument.h" 1.20 +#include "nsIImageLoadingContent.h" 1.21 +#include "nsIPresShell.h" 1.22 +#include "nsIServiceManager.h" 1.23 +#include "nsIDOMHTMLImageElement.h" 1.24 +#include "nsIPersistentProperties2.h" 1.25 +#include "nsPIDOMWindow.h" 1.26 +#include "nsIURI.h" 1.27 + 1.28 +using namespace mozilla::a11y; 1.29 + 1.30 +//////////////////////////////////////////////////////////////////////////////// 1.31 +// ImageAccessible 1.32 +//////////////////////////////////////////////////////////////////////////////// 1.33 + 1.34 +ImageAccessible:: 1.35 + ImageAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.36 + LinkableAccessible(aContent, aDoc) 1.37 +{ 1.38 + mType = eImageType; 1.39 +} 1.40 + 1.41 +NS_IMPL_ISUPPORTS_INHERITED(ImageAccessible, Accessible, 1.42 + nsIAccessibleImage) 1.43 + 1.44 +//////////////////////////////////////////////////////////////////////////////// 1.45 +// Accessible public 1.46 + 1.47 +uint64_t 1.48 +ImageAccessible::NativeState() 1.49 +{ 1.50 + // The state is a bitfield, get our inherited state, then logically OR it with 1.51 + // states::ANIMATED if this is an animated image. 1.52 + 1.53 + uint64_t state = LinkableAccessible::NativeState(); 1.54 + 1.55 + nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mContent)); 1.56 + nsCOMPtr<imgIRequest> imageRequest; 1.57 + 1.58 + if (content) 1.59 + content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, 1.60 + getter_AddRefs(imageRequest)); 1.61 + 1.62 + nsCOMPtr<imgIContainer> imgContainer; 1.63 + if (imageRequest) 1.64 + imageRequest->GetImage(getter_AddRefs(imgContainer)); 1.65 + 1.66 + if (imgContainer) { 1.67 + bool animated; 1.68 + imgContainer->GetAnimated(&animated); 1.69 + if (animated) 1.70 + state |= states::ANIMATED; 1.71 + } 1.72 + 1.73 + return state; 1.74 +} 1.75 + 1.76 +ENameValueFlag 1.77 +ImageAccessible::NativeName(nsString& aName) 1.78 +{ 1.79 + bool hasAltAttrib = 1.80 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName); 1.81 + if (!aName.IsEmpty()) 1.82 + return eNameOK; 1.83 + 1.84 + ENameValueFlag nameFlag = Accessible::NativeName(aName); 1.85 + if (!aName.IsEmpty()) 1.86 + return nameFlag; 1.87 + 1.88 + // No accessible name but empty 'alt' attribute is present. If further name 1.89 + // computation algorithm doesn't provide non empty name then it means 1.90 + // an empty 'alt' attribute was used to indicate a decorative image (see 1.91 + // Accessible::Name() method for details). 1.92 + return hasAltAttrib ? eNoNameOnPurpose : eNameOK; 1.93 +} 1.94 + 1.95 +role 1.96 +ImageAccessible::NativeRole() 1.97 +{ 1.98 + return roles::GRAPHIC; 1.99 +} 1.100 + 1.101 +//////////////////////////////////////////////////////////////////////////////// 1.102 +// nsIAccessible 1.103 + 1.104 +uint8_t 1.105 +ImageAccessible::ActionCount() 1.106 +{ 1.107 + uint8_t actionCount = LinkableAccessible::ActionCount(); 1.108 + return HasLongDesc() ? actionCount + 1 : actionCount; 1.109 +} 1.110 + 1.111 +NS_IMETHODIMP 1.112 +ImageAccessible::GetActionName(uint8_t aIndex, nsAString& aName) 1.113 +{ 1.114 + aName.Truncate(); 1.115 + 1.116 + if (IsDefunct()) 1.117 + return NS_ERROR_FAILURE; 1.118 + 1.119 + if (IsLongDescIndex(aIndex) && HasLongDesc()) { 1.120 + aName.AssignLiteral("showlongdesc"); 1.121 + return NS_OK; 1.122 + } 1.123 + return LinkableAccessible::GetActionName(aIndex, aName); 1.124 +} 1.125 + 1.126 +NS_IMETHODIMP 1.127 +ImageAccessible::DoAction(uint8_t aIndex) 1.128 +{ 1.129 + if (IsDefunct()) 1.130 + return NS_ERROR_FAILURE; 1.131 + 1.132 + // Get the long description uri and open in a new window. 1.133 + if (!IsLongDescIndex(aIndex)) 1.134 + return LinkableAccessible::DoAction(aIndex); 1.135 + 1.136 + nsCOMPtr<nsIURI> uri = GetLongDescURI(); 1.137 + if (!uri) 1.138 + return NS_ERROR_INVALID_ARG; 1.139 + 1.140 + nsAutoCString utf8spec; 1.141 + uri->GetSpec(utf8spec); 1.142 + NS_ConvertUTF8toUTF16 spec(utf8spec); 1.143 + 1.144 + nsIDocument* document = mContent->OwnerDoc(); 1.145 + nsCOMPtr<nsPIDOMWindow> piWindow = document->GetWindow(); 1.146 + nsCOMPtr<nsIDOMWindow> win = do_QueryInterface(piWindow); 1.147 + NS_ENSURE_STATE(win); 1.148 + 1.149 + nsCOMPtr<nsIDOMWindow> tmp; 1.150 + return win->Open(spec, EmptyString(), EmptyString(), 1.151 + getter_AddRefs(tmp)); 1.152 +} 1.153 + 1.154 +//////////////////////////////////////////////////////////////////////////////// 1.155 +// nsIAccessibleImage 1.156 + 1.157 +NS_IMETHODIMP 1.158 +ImageAccessible::GetImagePosition(uint32_t aCoordType, int32_t* aX, int32_t* aY) 1.159 +{ 1.160 + int32_t width, height; 1.161 + nsresult rv = GetBounds(aX, aY, &width, &height); 1.162 + if (NS_FAILED(rv)) 1.163 + return rv; 1.164 + 1.165 + nsAccUtils::ConvertScreenCoordsTo(aX, aY, aCoordType, this); 1.166 + return NS_OK; 1.167 +} 1.168 + 1.169 +NS_IMETHODIMP 1.170 +ImageAccessible::GetImageSize(int32_t* aWidth, int32_t* aHeight) 1.171 +{ 1.172 + int32_t x, y; 1.173 + return GetBounds(&x, &y, aWidth, aHeight); 1.174 +} 1.175 + 1.176 +// Accessible 1.177 +already_AddRefed<nsIPersistentProperties> 1.178 +ImageAccessible::NativeAttributes() 1.179 +{ 1.180 + nsCOMPtr<nsIPersistentProperties> attributes = 1.181 + LinkableAccessible::NativeAttributes(); 1.182 + 1.183 + nsAutoString src; 1.184 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src); 1.185 + if (!src.IsEmpty()) 1.186 + nsAccUtils::SetAccAttr(attributes, nsGkAtoms::src, src); 1.187 + 1.188 + return attributes.forget(); 1.189 +} 1.190 + 1.191 +//////////////////////////////////////////////////////////////////////////////// 1.192 +// Private methods 1.193 + 1.194 +already_AddRefed<nsIURI> 1.195 +ImageAccessible::GetLongDescURI() const 1.196 +{ 1.197 + if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::longdesc)) { 1.198 + nsGenericHTMLElement* element = 1.199 + nsGenericHTMLElement::FromContent(mContent); 1.200 + if (element) { 1.201 + nsCOMPtr<nsIURI> uri; 1.202 + element->GetURIAttr(nsGkAtoms::longdesc, nullptr, getter_AddRefs(uri)); 1.203 + return uri.forget(); 1.204 + } 1.205 + } 1.206 + 1.207 + DocAccessible* document = Document(); 1.208 + if (document) { 1.209 + IDRefsIterator iter(document, mContent, nsGkAtoms::aria_describedby); 1.210 + while (nsIContent* target = iter.NextElem()) { 1.211 + if ((target->IsHTML(nsGkAtoms::a) || target->IsHTML(nsGkAtoms::area)) && 1.212 + target->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) { 1.213 + nsGenericHTMLElement* element = 1.214 + nsGenericHTMLElement::FromContent(target); 1.215 + 1.216 + nsCOMPtr<nsIURI> uri; 1.217 + element->GetURIAttr(nsGkAtoms::href, nullptr, getter_AddRefs(uri)); 1.218 + return uri.forget(); 1.219 + } 1.220 + } 1.221 + } 1.222 + 1.223 + return nullptr; 1.224 +} 1.225 + 1.226 +bool 1.227 +ImageAccessible::IsLongDescIndex(uint8_t aIndex) 1.228 +{ 1.229 + return aIndex == LinkableAccessible::ActionCount(); 1.230 +} 1.231 +