forked from mirrors/gecko-dev
		
	 ff4c89901f
			
		
	
	
		ff4c89901f
		
	
	
	
	
		
			
			This revision implements HTMLLinkAccessible::NativeName, which, if the element is present in an SVG context, checks the xlink:title attribute for the name, as required by the accessible name specification. This revision also removes eight expected failures from the relevant web platform test meta file. Differential Revision: https://phabricator.services.mozilla.com/D203031
		
			
				
	
	
		
			140 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include "HTMLLinkAccessible.h"
 | |
| 
 | |
| #include "CacheConstants.h"
 | |
| #include "nsCoreUtils.h"
 | |
| #include "mozilla/a11y/Role.h"
 | |
| #include "States.h"
 | |
| 
 | |
| #include "nsContentUtils.h"
 | |
| #include "mozilla/a11y/DocAccessible.h"
 | |
| #include "mozilla/dom/Element.h"
 | |
| #include "mozilla/dom/MutationEventBinding.h"
 | |
| 
 | |
| using namespace mozilla;
 | |
| using namespace mozilla::a11y;
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| // HTMLLinkAccessible
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| HTMLLinkAccessible::HTMLLinkAccessible(nsIContent* aContent,
 | |
|                                        DocAccessible* aDoc)
 | |
|     : HyperTextAccessible(aContent, aDoc) {
 | |
|   mType = eHTMLLinkType;
 | |
| }
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| // nsIAccessible
 | |
| 
 | |
| role HTMLLinkAccessible::NativeRole() const { return roles::LINK; }
 | |
| 
 | |
| uint64_t HTMLLinkAccessible::NativeState() const {
 | |
|   return HyperTextAccessible::NativeState() & ~states::READONLY;
 | |
| }
 | |
| 
 | |
| uint64_t HTMLLinkAccessible::NativeLinkState() const {
 | |
|   dom::ElementState state = mContent->AsElement()->State();
 | |
|   if (state.HasState(dom::ElementState::UNVISITED)) {
 | |
|     return states::LINKED;
 | |
|   }
 | |
| 
 | |
|   if (state.HasState(dom::ElementState::VISITED)) {
 | |
|     return states::LINKED | states::TRAVERSED;
 | |
|   }
 | |
| 
 | |
|   // This is a either named anchor (a link with also a name attribute) or
 | |
|   // it doesn't have any attributes. Check if 'click' event handler is
 | |
|   // registered, otherwise bail out.
 | |
|   return nsCoreUtils::HasClickListener(mContent) ? states::LINKED : 0;
 | |
| }
 | |
| 
 | |
| uint64_t HTMLLinkAccessible::NativeInteractiveState() const {
 | |
|   uint64_t state = HyperTextAccessible::NativeInteractiveState();
 | |
| 
 | |
|   // This is how we indicate it is a named anchor. In other words, this anchor
 | |
|   // can be selected as a location :) There is no other better state to use to
 | |
|   // indicate this.
 | |
|   if (mContent->AsElement()->HasAttr(nsGkAtoms::name)) {
 | |
|     state |= states::SELECTABLE;
 | |
|   }
 | |
| 
 | |
|   return state;
 | |
| }
 | |
| 
 | |
| void HTMLLinkAccessible::Value(nsString& aValue) const {
 | |
|   aValue.Truncate();
 | |
| 
 | |
|   HyperTextAccessible::Value(aValue);
 | |
|   if (aValue.IsEmpty()) {
 | |
|     nsContentUtils::GetLinkLocation(mContent->AsElement(), aValue);
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool HTMLLinkAccessible::HasPrimaryAction() const {
 | |
|   return IsLinked() || HyperTextAccessible::HasPrimaryAction();
 | |
|   ;
 | |
| }
 | |
| 
 | |
| void HTMLLinkAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) {
 | |
|   aName.Truncate();
 | |
| 
 | |
|   if (!IsLinked()) {
 | |
|     HyperTextAccessible::ActionNameAt(aIndex, aName);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Action 0 (default action): Jump to link
 | |
|   if (aIndex == eAction_Jump) aName.AssignLiteral("jump");
 | |
| }
 | |
| 
 | |
| bool HTMLLinkAccessible::AttributeChangesState(nsAtom* aAttribute) {
 | |
|   return aAttribute == nsGkAtoms::href ||
 | |
|          HyperTextAccessible::AttributeChangesState(aAttribute);
 | |
| }
 | |
| 
 | |
| void HTMLLinkAccessible::DOMAttributeChanged(int32_t aNameSpaceID,
 | |
|                                              nsAtom* aAttribute,
 | |
|                                              int32_t aModType,
 | |
|                                              const nsAttrValue* aOldValue,
 | |
|                                              uint64_t aOldState) {
 | |
|   HyperTextAccessible::DOMAttributeChanged(aNameSpaceID, aAttribute, aModType,
 | |
|                                            aOldValue, aOldState);
 | |
| 
 | |
|   if (aAttribute == nsGkAtoms::href &&
 | |
|       (aModType == dom::MutationEvent_Binding::ADDITION ||
 | |
|        aModType == dom::MutationEvent_Binding::REMOVAL)) {
 | |
|     mDoc->QueueCacheUpdate(this, CacheDomain::Actions);
 | |
|   }
 | |
| }
 | |
| 
 | |
| ENameValueFlag HTMLLinkAccessible::NativeName(nsString& aName) const {
 | |
|   if (mContent->IsSVGElement()) {
 | |
|     mContent->AsElement()->GetAttr(kNameSpaceID_XLink, nsGkAtoms::title, aName);
 | |
|     if (!aName.IsEmpty()) {
 | |
|       return eNameOK;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return HyperTextAccessible::NativeName(aName);
 | |
| }
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| // HyperLinkAccessible
 | |
| 
 | |
| bool HTMLLinkAccessible::IsLink() const {
 | |
|   // Expose HyperLinkAccessible unconditionally.
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| // HTMLLinkAccessible
 | |
| 
 | |
| bool HTMLLinkAccessible::IsLinked() const {
 | |
|   dom::ElementState state = mContent->AsElement()->State();
 | |
|   return state.HasAtLeastOneOfStates(dom::ElementState::VISITED_OR_UNVISITED);
 | |
| }
 |