Bug 1403231 - Create accessibles for the XUL "image" element using the tag name instead of the XBL role. r=surkov
This also adds the lookup infrastructure required for converting other XUL elements to this method of creating accessibles.
MozReview-Commit-ID: GAO63iUNMAn
new file mode 100644
--- /dev/null
+++ b/accessible/base/XULMap.h
@@ -0,0 +1,5 @@
+/* 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/. */
+
+XULMAP(image, New_MaybeImageOrToolbarButtonAccessible)
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -245,16 +245,34 @@ static Accessible*
New_HTMLTableHeaderCellIfScope(nsIContent* aContent, Accessible* aContext)
{
if (aContext->IsTableRow() && aContext->GetContent() == aContent->GetParent() &&
aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope))
return new HTMLTableHeaderCellAccessibleWrap(aContent, aContext->Document());
return nullptr;
}
+#ifdef MOZ_XUL
+static Accessible*
+New_MaybeImageOrToolbarButtonAccessible(nsIContent* aContent,
+ Accessible* aContext)
+{
+ if (aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::onclick)) {
+ return new XULToolbarButtonAccessible(aContent, aContext->Document());
+ }
+
+ // Don't include nameless images in accessible tree.
+ if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext)) {
+ return nullptr;
+ }
+
+ return new ImageAccessibleWrap(aContent, aContext->Document());
+}
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// Markup maps array.
#define Attr(name, value) \
{ &nsGkAtoms::name, &nsGkAtoms::value }
#define AttrFromDOM(name, DOMAttrName) \
{ &nsGkAtoms::name, nullptr, &nsGkAtoms::DOMAttrName }
@@ -264,32 +282,47 @@ New_HTMLTableHeaderCellIfScope(nsIConten
#define MARKUPMAP(atom, new_func, r, ... ) \
{ &nsGkAtoms::atom, new_func, static_cast<a11y::role>(r), { __VA_ARGS__ } },
static const MarkupMapInfo sMarkupMapList[] = {
#include "MarkupMap.h"
};
+#ifdef MOZ_XUL
+#define XULMAP(atom, new_func) \
+ { &nsGkAtoms::atom, new_func },
+
+static const XULMapInfo sXULMapList[] = {
+ #include "XULMap.h"
+};
+#endif
+
#undef Attr
#undef AttrFromDOM
#undef AttrFromDOMIf
#undef MARKUPMAP
+#ifdef MOZ_XUL
+#undef XULMAP
+#endif
////////////////////////////////////////////////////////////////////////////////
// nsAccessibilityService
////////////////////////////////////////////////////////////////////////////////
nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nullptr;
ApplicationAccessible* nsAccessibilityService::gApplicationAccessible = nullptr;
xpcAccessibleApplication* nsAccessibilityService::gXPCApplicationAccessible = nullptr;
uint32_t nsAccessibilityService::gConsumers = 0;
nsAccessibilityService::nsAccessibilityService() :
DocManager(), FocusManager(), mMarkupMaps(ArrayLength(sMarkupMapList))
+#ifdef MOZ_XUL
+ , mXULMaps(ArrayLength(sXULMapList))
+#endif
{
}
nsAccessibilityService::~nsAccessibilityService()
{
NS_ASSERTION(IsShutdown(), "Accessibility wasn't shutdown!");
gAccessibilityService = nullptr;
}
@@ -1157,19 +1190,29 @@ nsAccessibilityService::CreateAccessible
if (deckFrame && deckFrame->GetSelectedBox() != frame) {
if (aIsSubtreeHidden)
*aIsSubtreeHidden = true;
return nullptr;
}
}
+#ifdef MOZ_XUL
+ // Prefer to use XUL to decide if and what kind of accessible to create.
+ const XULMapInfo* xulMap = mXULMaps.Get(content->NodeInfo()->NameAtom());
+ if (xulMap && xulMap->new_func) {
+ newAcc = xulMap->new_func(content, aContext);
+ }
+#endif
+
// XBL bindings may use @role attribute to point the accessible type
// they belong to.
- newAcc = CreateAccessibleByType(content, document);
+ if (!newAcc) {
+ newAcc = CreateAccessibleByType(content, document);
+ }
// Any XUL box can be used as tabpanel, make sure we create a proper
// accessible for it.
if (!newAcc && aContext->IsXULTabpanels() &&
content->GetParent() == aContext->GetContent()) {
LayoutFrameType frameType = frame->Type();
if (frameType == LayoutFrameType::Box ||
frameType == LayoutFrameType::Scroll) {
@@ -1271,16 +1314,21 @@ nsAccessibilityService::Init()
if (!eventListenerService)
return false;
eventListenerService->AddListenerChangeListener(this);
for (uint32_t i = 0; i < ArrayLength(sMarkupMapList); i++)
mMarkupMaps.Put(*sMarkupMapList[i].tag, &sMarkupMapList[i]);
+#ifdef MOZ_XUL
+ for (uint32_t i = 0; i < ArrayLength(sXULMapList); i++)
+ mXULMaps.Put(*sXULMapList[i].tag, &sXULMapList[i]);
+#endif
+
#ifdef A11Y_LOG
logging::CheckEnv();
#endif
gAccessibilityService = this;
NS_ADDREF(gAccessibilityService); // will release in Shutdown()
if (XRE_IsParentProcess()) {
@@ -1416,29 +1464,16 @@ nsAccessibilityService::CreateAccessible
accessible = new XULTabpanelsAccessible(aContent, aDoc);
} else if (role.EqualsLiteral("xul:dropmarker")) {
accessible = new XULDropmarkerAccessible(aContent, aDoc);
} else if (role.EqualsLiteral("xul:groupbox")) {
accessible = new XULGroupboxAccessible(aContent, aDoc);
- } else if (role.EqualsLiteral("xul:image")) {
- if (aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::onclick)) {
- accessible = new XULToolbarButtonAccessible(aContent, aDoc);
-
- } else {
- // Don't include nameless images in accessible tree.
- if (!aContent->HasAttr(kNameSpaceID_None,
- nsGkAtoms::tooltiptext))
- return nullptr;
-
- accessible = new ImageAccessibleWrap(aContent, aDoc);
- }
-
} else if (role.EqualsLiteral("xul:link")) {
accessible = new XULLinkAccessible(aContent, aDoc);
} else if (role.EqualsLiteral("xul:listbox")) {
accessible = new XULListboxAccessibleWrap(aContent, aDoc);
} else if (role.EqualsLiteral("xul:listcell")) {
// Only create cells if there's more than one per row.
--- a/accessible/base/nsAccessibilityService.h
+++ b/accessible/base/nsAccessibilityService.h
@@ -62,16 +62,23 @@ struct MarkupAttrInfo {
struct MarkupMapInfo {
nsStaticAtom** tag;
New_Accessible* new_func;
a11y::role role;
MarkupAttrInfo attrs[4];
};
+#ifdef MOZ_XUL
+struct XULMapInfo {
+ nsStaticAtom** tag;
+ New_Accessible* new_func;
+};
+#endif
+
} // namespace a11y
} // namespace mozilla
class nsAccessibilityService final : public mozilla::a11y::DocManager,
public mozilla::a11y::FocusManager,
public mozilla::a11y::SelectionManager,
public nsIListenerChangeListener,
public nsIObserver
@@ -306,16 +313,19 @@ private:
static mozilla::a11y::xpcAccessibleApplication* gXPCApplicationAccessible;
/**
* Contains a set of accessibility service consumers.
*/
static uint32_t gConsumers;
nsDataHashtable<nsPtrHashKey<const nsAtom>, const mozilla::a11y::MarkupMapInfo*> mMarkupMaps;
+#ifdef MOZ_XUL
+ nsDataHashtable<nsPtrHashKey<const nsAtom>, const mozilla::a11y::XULMapInfo*> mXULMaps;
+#endif
friend nsAccessibilityService* GetAccService();
friend nsAccessibilityService* GetOrCreateAccService(uint32_t);
friend void MaybeShutdownAccService(uint32_t);
friend mozilla::a11y::FocusManager* mozilla::a11y::FocusMgr();
friend mozilla::a11y::SelectionManager* mozilla::a11y::SelectionMgr();
friend mozilla::a11y::ApplicationAccessible* mozilla::a11y::ApplicationAcc();
friend mozilla::a11y::xpcAccessibleApplication* mozilla::a11y::XPCApplicationAcc();