diff options
Diffstat (limited to 'accessible/html/HTMLLinkAccessible.cpp')
-rw-r--r-- | accessible/html/HTMLLinkAccessible.cpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/accessible/html/HTMLLinkAccessible.cpp b/accessible/html/HTMLLinkAccessible.cpp new file mode 100644 index 0000000000..a6b952dcf3 --- /dev/null +++ b/accessible/html/HTMLLinkAccessible.cpp @@ -0,0 +1,118 @@ +/* -*- 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 "nsCoreUtils.h" +#include "DocAccessible.h" +#include "Role.h" +#include "States.h" + +#include "nsContentUtils.h" +#include "mozilla/EventStates.h" +#include "mozilla/dom/Element.h" + +using namespace mozilla; +using namespace mozilla::a11y; + +//////////////////////////////////////////////////////////////////////////////// +// HTMLLinkAccessible +//////////////////////////////////////////////////////////////////////////////// + +HTMLLinkAccessible::HTMLLinkAccessible(nsIContent* aContent, + DocAccessible* aDoc) + : HyperTextAccessibleWrap(aContent, aDoc) { + mType = eHTMLLinkType; +} + +//////////////////////////////////////////////////////////////////////////////// +// nsIAccessible + +role HTMLLinkAccessible::NativeRole() const { return roles::LINK; } + +uint64_t HTMLLinkAccessible::NativeState() const { + return HyperTextAccessibleWrap::NativeState() & ~states::READONLY; +} + +uint64_t HTMLLinkAccessible::NativeLinkState() const { + EventStates eventState = mContent->AsElement()->State(); + if (eventState.HasState(NS_EVENT_STATE_UNVISITED)) return states::LINKED; + + if (eventState.HasState(NS_EVENT_STATE_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 = HyperTextAccessibleWrap::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(kNameSpaceID_None, 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); +} + +uint8_t HTMLLinkAccessible::ActionCount() const { + return IsLinked() ? 1 : HyperTextAccessible::ActionCount(); +} + +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::DoAction(uint8_t aIndex) const { + if (!IsLinked()) return HyperTextAccessible::DoAction(aIndex); + + // Action 0 (default action): Jump to link + if (aIndex != eAction_Jump) return false; + + DoCommand(); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// HyperLinkAccessible + +bool HTMLLinkAccessible::IsLink() const { + // Expose HyperLinkAccessible unconditionally. + return true; +} + +already_AddRefed<nsIURI> HTMLLinkAccessible::AnchorURIAt( + uint32_t aAnchorIndex) const { + return aAnchorIndex == 0 ? mContent->GetHrefURI() : nullptr; +} + +//////////////////////////////////////////////////////////////////////////////// +// HTMLLinkAccessible + +bool HTMLLinkAccessible::IsLinked() const { + EventStates state = mContent->AsElement()->State(); + return state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED | + NS_EVENT_STATE_UNVISITED); +} |