ImageAccessible.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "ImageAccessible.h"
  6. #include "nsAccUtils.h"
  7. #include "Role.h"
  8. #include "AccIterator.h"
  9. #include "States.h"
  10. #include "imgIContainer.h"
  11. #include "imgIRequest.h"
  12. #include "nsGenericHTMLElement.h"
  13. #include "nsIDocument.h"
  14. #include "nsIImageLoadingContent.h"
  15. #include "nsIPresShell.h"
  16. #include "nsIServiceManager.h"
  17. #include "nsIDOMHTMLImageElement.h"
  18. #include "nsIPersistentProperties2.h"
  19. #include "nsPIDOMWindow.h"
  20. #include "nsIURI.h"
  21. using namespace mozilla::a11y;
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // ImageAccessible
  24. ////////////////////////////////////////////////////////////////////////////////
  25. ImageAccessible::
  26. ImageAccessible(nsIContent* aContent, DocAccessible* aDoc) :
  27. LinkableAccessible(aContent, aDoc)
  28. {
  29. mType = eImageType;
  30. }
  31. ImageAccessible::~ImageAccessible()
  32. {
  33. }
  34. ////////////////////////////////////////////////////////////////////////////////
  35. // Accessible public
  36. uint64_t
  37. ImageAccessible::NativeState()
  38. {
  39. // The state is a bitfield, get our inherited state, then logically OR it with
  40. // states::ANIMATED if this is an animated image.
  41. uint64_t state = LinkableAccessible::NativeState();
  42. nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mContent));
  43. nsCOMPtr<imgIRequest> imageRequest;
  44. if (content)
  45. content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
  46. getter_AddRefs(imageRequest));
  47. nsCOMPtr<imgIContainer> imgContainer;
  48. if (imageRequest)
  49. imageRequest->GetImage(getter_AddRefs(imgContainer));
  50. if (imgContainer) {
  51. bool animated;
  52. imgContainer->GetAnimated(&animated);
  53. if (animated)
  54. state |= states::ANIMATED;
  55. }
  56. return state;
  57. }
  58. ENameValueFlag
  59. ImageAccessible::NativeName(nsString& aName)
  60. {
  61. bool hasAltAttrib =
  62. mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName);
  63. if (!aName.IsEmpty())
  64. return eNameOK;
  65. ENameValueFlag nameFlag = Accessible::NativeName(aName);
  66. if (!aName.IsEmpty())
  67. return nameFlag;
  68. // No accessible name but empty 'alt' attribute is present. If further name
  69. // computation algorithm doesn't provide non empty name then it means
  70. // an empty 'alt' attribute was used to indicate a decorative image (see
  71. // Accessible::Name() method for details).
  72. return hasAltAttrib ? eNoNameOnPurpose : eNameOK;
  73. }
  74. role
  75. ImageAccessible::NativeRole()
  76. {
  77. return roles::GRAPHIC;
  78. }
  79. ////////////////////////////////////////////////////////////////////////////////
  80. // Accessible
  81. uint8_t
  82. ImageAccessible::ActionCount()
  83. {
  84. uint8_t actionCount = LinkableAccessible::ActionCount();
  85. return HasLongDesc() ? actionCount + 1 : actionCount;
  86. }
  87. void
  88. ImageAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
  89. {
  90. aName.Truncate();
  91. if (IsLongDescIndex(aIndex) && HasLongDesc())
  92. aName.AssignLiteral("showlongdesc");
  93. else
  94. LinkableAccessible::ActionNameAt(aIndex, aName);
  95. }
  96. bool
  97. ImageAccessible::DoAction(uint8_t aIndex)
  98. {
  99. // Get the long description uri and open in a new window.
  100. if (!IsLongDescIndex(aIndex))
  101. return LinkableAccessible::DoAction(aIndex);
  102. nsCOMPtr<nsIURI> uri = GetLongDescURI();
  103. if (!uri)
  104. return false;
  105. nsAutoCString utf8spec;
  106. uri->GetSpec(utf8spec);
  107. NS_ConvertUTF8toUTF16 spec(utf8spec);
  108. nsIDocument* document = mContent->OwnerDoc();
  109. nsCOMPtr<nsPIDOMWindowOuter> piWindow = document->GetWindow();
  110. if (!piWindow)
  111. return false;
  112. nsCOMPtr<nsPIDOMWindowOuter> tmp;
  113. return NS_SUCCEEDED(piWindow->Open(spec, EmptyString(), EmptyString(),
  114. /* aLoadInfo = */ nullptr,
  115. /* aForceNoOpener = */ false,
  116. getter_AddRefs(tmp)));
  117. }
  118. ////////////////////////////////////////////////////////////////////////////////
  119. // ImageAccessible
  120. nsIntPoint
  121. ImageAccessible::Position(uint32_t aCoordType)
  122. {
  123. nsIntRect rect = Bounds();
  124. nsAccUtils::ConvertScreenCoordsTo(&rect.x, &rect.y, aCoordType, this);
  125. return rect.TopLeft();
  126. }
  127. nsIntSize
  128. ImageAccessible::Size()
  129. {
  130. return Bounds().Size();
  131. }
  132. // Accessible
  133. already_AddRefed<nsIPersistentProperties>
  134. ImageAccessible::NativeAttributes()
  135. {
  136. nsCOMPtr<nsIPersistentProperties> attributes =
  137. LinkableAccessible::NativeAttributes();
  138. nsAutoString src;
  139. mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
  140. if (!src.IsEmpty())
  141. nsAccUtils::SetAccAttr(attributes, nsGkAtoms::src, src);
  142. return attributes.forget();
  143. }
  144. ////////////////////////////////////////////////////////////////////////////////
  145. // Private methods
  146. already_AddRefed<nsIURI>
  147. ImageAccessible::GetLongDescURI() const
  148. {
  149. if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::longdesc)) {
  150. // To check if longdesc contains an invalid url.
  151. nsAutoString longdesc;
  152. mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::longdesc, longdesc);
  153. if (longdesc.FindChar(' ') != -1 || longdesc.FindChar('\t') != -1 ||
  154. longdesc.FindChar('\r') != -1 || longdesc.FindChar('\n') != -1) {
  155. return nullptr;
  156. }
  157. nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
  158. nsCOMPtr<nsIURI> uri;
  159. nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri), longdesc,
  160. mContent->OwnerDoc(), baseURI);
  161. return uri.forget();
  162. }
  163. DocAccessible* document = Document();
  164. if (document) {
  165. IDRefsIterator iter(document, mContent, nsGkAtoms::aria_describedby);
  166. while (nsIContent* target = iter.NextElem()) {
  167. if ((target->IsHTMLElement(nsGkAtoms::a) ||
  168. target->IsHTMLElement(nsGkAtoms::area)) &&
  169. target->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) {
  170. nsGenericHTMLElement* element =
  171. nsGenericHTMLElement::FromContent(target);
  172. nsCOMPtr<nsIURI> uri;
  173. element->GetURIAttr(nsGkAtoms::href, nullptr, getter_AddRefs(uri));
  174. return uri.forget();
  175. }
  176. }
  177. }
  178. return nullptr;
  179. }
  180. bool
  181. ImageAccessible::IsLongDescIndex(uint8_t aIndex)
  182. {
  183. return aIndex == LinkableAccessible::ActionCount();
  184. }