diff --git a/accessible/base/HTMLMarkupMap.h b/accessible/base/HTMLMarkupMap.h
index 3dd2f34bd538..d85f4accf04c 100644
--- a/accessible/base/HTMLMarkupMap.h
+++ b/accessible/base/HTMLMarkupMap.h
@@ -8,6 +8,12 @@
MARKUPMAP(
a,
[](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
+ // An anchor element without an href attribute and without a click
+ // listener should be a generic.
+ if (!aElement->HasAttr(nsGkAtoms::href) &&
+ !nsCoreUtils::HasClickListener(aElement)) {
+ return new HyperTextAccessibleWrap(aElement, aContext->Document());
+ }
// Only some roles truly enjoy life as HTMLLinkAccessibles, for
// details see closed bug 494807.
const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aElement);
@@ -18,7 +24,7 @@ MARKUPMAP(
return new HTMLLinkAccessible(aElement, aContext->Document());
},
- roles::LINK)
+ 0)
MARKUPMAP(abbr, New_HyperText, 0)
diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp
index 79797feae9ed..37082a605914 100644
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -442,17 +442,33 @@ nsAccessibilityService::ListenersChanged(nsIArray* aEventChanges) {
content == document->DocumentNode()->GetRootElement())) {
acc = document;
}
+ if (!acc && content->IsElement() &&
+ content->AsElement()->IsHTMLElement(nsGkAtoms::area)) {
+ // For area accessibles, we have to recreate the entire image map,
+ // since the image map accessible manages the tree itself. The click
+ // listener change may require us to update the role for the
+ // accessible associated with the area element.
+ LocalAccessible* areaAcc =
+ document->GetAccessibleEvenIfNotInMap(content);
+ if (areaAcc && areaAcc->LocalParent()) {
+ document->RecreateAccessible(areaAcc->LocalParent()->GetContent());
+ }
+ }
if (!acc && nsCoreUtils::HasClickListener(content)) {
// Create an accessible for a inaccessible element having click event
// handler.
document->ContentInserted(content, content->GetNextSibling());
} else if (acc) {
- if (acc->IsHTMLLink() && !acc->AsHTMLLink()->IsLinked()) {
- // Notify of a LINKED state change if an HTML link gets a click
- // listener but does not have an href attribute.
- RefPtr linkedChangeEvent =
- new AccStateChangeEvent(acc, states::LINKED);
- document->FireDelayedEvent(linkedChangeEvent);
+ if ((acc->IsHTMLLink() && !acc->AsHTMLLink()->IsLinked()) ||
+ (content->IsElement() &&
+ content->AsElement()->IsHTMLElement(nsGkAtoms::a) &&
+ !acc->IsHTMLLink())) {
+ // An HTML link without an href attribute should have a generic
+ // role, unless it has a click listener. Since we might have gained
+ // or lost a click listener here, recreate the accessible so that we
+ // can create the correct type of accessible. If it was a link, it
+ // may no longer be one. If it wasn't, it may become one.
+ document->RecreateAccessible(content);
}
// A click listener change might mean losing or gaining an action.
diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp
index 51ef54a8794f..d6dff6016834 100644
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1803,6 +1803,33 @@ bool DocAccessible::UpdateAccessibleOnAttrChange(dom::Element* aElement,
return true;
}
+ if (aAttribute == nsGkAtoms::href &&
+ !nsCoreUtils::HasClickListener(aElement)) {
+ // If the href is added or removed for a or area elements without click
+ // listeners, we need to recreate the accessible since the role might have
+ // changed. Without an href or click listener, the accessible must be a
+ // generic.
+ if (aElement->IsHTMLElement(nsGkAtoms::a)) {
+ LocalAccessible* acc = GetAccessible(aElement);
+ if (!acc) {
+ return false;
+ }
+ if (acc->IsHTMLLink() != aElement->HasAttr(nsGkAtoms::href)) {
+ RecreateAccessible(aElement);
+ return true;
+ }
+ } else if (aElement->IsHTMLElement(nsGkAtoms::area)) {
+ // For area accessibles, we have to recreate the entire image map, since
+ // the image map accessible manages the tree itself.
+ LocalAccessible* areaAcc = GetAccessibleEvenIfNotInMap(aElement);
+ if (!areaAcc || !areaAcc->LocalParent()) {
+ return false;
+ }
+ RecreateAccessible(areaAcc->LocalParent()->GetContent());
+ return true;
+ }
+ }
+
if (aElement->IsHTMLElement(nsGkAtoms::img) && aAttribute == nsGkAtoms::alt) {
// If alt text changes on an img element, we may want to create or remove an
// accessible for that img.
diff --git a/accessible/html/HTMLImageMapAccessible.cpp b/accessible/html/HTMLImageMapAccessible.cpp
index f20974e9cf35..b5f307cb7031 100644
--- a/accessible/html/HTMLImageMapAccessible.cpp
+++ b/accessible/html/HTMLImageMapAccessible.cpp
@@ -9,6 +9,7 @@
#include "EventTree.h"
#include "Role.h"
+#include "nsCoreUtils.h"
#include "nsIFrame.h"
#include "nsImageFrame.h"
#include "nsImageMap.h"
@@ -105,6 +106,19 @@ HTMLAreaAccessible::HTMLAreaAccessible(nsIContent* aContent,
////////////////////////////////////////////////////////////////////////////////
// HTMLAreaAccessible: LocalAccessible
+role HTMLAreaAccessible::NativeRole() const {
+ // A link element without an href attribute and without a click listener
+ // should be reported as a generic.
+ if (mContent->IsElement()) {
+ dom::Element* element = mContent->AsElement();
+ if (!element->HasAttr(nsGkAtoms::href) &&
+ !nsCoreUtils::HasClickListener(element)) {
+ return roles::TEXT;
+ }
+ }
+ return HTMLLinkAccessible::NativeRole();
+}
+
ENameValueFlag HTMLAreaAccessible::NativeName(nsString& aName) const {
ENameValueFlag nameFlag = LocalAccessible::NativeName(aName);
if (!aName.IsEmpty()) return nameFlag;
diff --git a/accessible/html/HTMLImageMapAccessible.h b/accessible/html/HTMLImageMapAccessible.h
index 2dc1779ddd7a..15c56b44dede 100644
--- a/accessible/html/HTMLImageMapAccessible.h
+++ b/accessible/html/HTMLImageMapAccessible.h
@@ -61,6 +61,9 @@ class HTMLAreaAccessible final : public HTMLLinkAccessible {
return false;
}
+ // LocalAccessible
+ virtual role NativeRole() const override;
+
protected:
// LocalAccessible
virtual ENameValueFlag NativeName(nsString& aName) const override;
diff --git a/accessible/tests/browser/e10s/browser_caching_actions.js b/accessible/tests/browser/e10s/browser_caching_actions.js
index 8bf3542a0373..1407f3786218 100644
--- a/accessible/tests/browser/e10s/browser_caching_actions.js
+++ b/accessible/tests/browser/e10s/browser_caching_actions.js
@@ -92,6 +92,10 @@ addAccessibleTask(
src="http://example.com/a11y/accessible/tests/mochitest/moz.png">
+
+
+
+