Bug 1625870 - Support figure and figcaption is OSX. r=morgan
☠☠ backed out by 050c45257373 ☠ ☠
authorEitan Isaacson <eitan@monotonous.org>
Tue, 28 Apr 2020 18:04:00 +0000
changeset 526527 b9710246d416d866b79c9c3d09005a6866b635f2
parent 526526 8866eea63b5726295da916e79214ca9c0f8a5bd9
child 526528 792842055c97c61848b5f5e0ebfd4da1b9afcce4
push id37358
push useropoprus@mozilla.com
push dateWed, 29 Apr 2020 03:05:14 +0000
treeherdermozilla-central@6bb8423186c1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmorgan
bugs1625870
milestone77.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1625870 - Support figure and figcaption is OSX. r=morgan Differential Revision: https://phabricator.services.mozilla.com/D72509
accessible/base/RoleMap.h
accessible/html/HTMLFormControlAccessible.cpp
accessible/mac/mozAccessible.mm
accessible/tests/browser/mac/browser_roles_elements.js
--- a/accessible/base/RoleMap.h
+++ b/accessible/base/RoleMap.h
@@ -943,17 +943,17 @@ ROLE(ENTRY,
      ROLE_SYSTEM_TEXT,
      ROLE_SYSTEM_TEXT,
      java::SessionAccessibility::CLASSNAME_EDITTEXT,
      eNameFromValueRule)
 
 ROLE(CAPTION,
      "caption",
      ATK_ROLE_CAPTION,
-     NSAccessibilityStaticTextRole,
+     NSAccessibilityGroupRole,
      USE_ROLE_STRING,
      IA2_ROLE_CAPTION,
      java::SessionAccessibility::CLASSNAME_VIEW,
      eNameFromSubtreeIfReqRule)
 
 ROLE(NON_NATIVE_DOCUMENT,
      "non-native document",
      ATK_ROLE_DOCUMENT_FRAME,
--- a/accessible/html/HTMLFormControlAccessible.cpp
+++ b/accessible/html/HTMLFormControlAccessible.cpp
@@ -633,16 +633,17 @@ HTMLFigureAccessible::HTMLFigureAccessib
 ENameValueFlag HTMLFigureAccessible::NativeName(nsString& aName) const {
   ENameValueFlag nameFlag = HyperTextAccessibleWrap::NativeName(aName);
   if (!aName.IsEmpty()) return nameFlag;
 
   nsIContent* captionContent = Caption();
   if (captionContent)
     nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
 
+  aName.CompressWhitespace();
   return eNameOK;
 }
 
 Relation HTMLFigureAccessible::RelationByType(RelationType aType) const {
   Relation rel = HyperTextAccessibleWrap::RelationByType(aType);
   if (aType == RelationType::LABELLED_BY) rel.AppendTarget(mDoc, Caption());
 
   return rel;
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -596,50 +596,57 @@ static const uint64_t kCacheInitialized 
 }
 
 - (NSString*)accessibilityActionDescription:(NSString*)action {
   // by default we return whatever the MacOS API know about.
   // if you have custom actions, override.
   return NSAccessibilityActionDescription(action);
 }
 
+- (BOOL)providesLabelNotTitle {
+  // These accessible types are the exception to the rule of label vs. title:
+  // They may be named explicitly, but they still provide a label not a title.
+  return mRole == roles::GROUPING || mRole == roles::RADIO_GROUP || mRole == roles::FIGURE ||
+         mRole == roles::GRAPHIC;
+}
+
 - (NSString*)accessibilityLabel {
   AccessibleWrap* accWrap = [self getGeckoAccessible];
   ProxyAccessible* proxy = [self getProxyAccessible];
   if (!accWrap && !proxy) {
     return nil;
   }
 
   nsAutoString name;
 
   /* If our accessible is:
    * 1. Named by invisible text, or
    * 2. Has more than one labeling relation, or
-   * 3. Is a grouping
+   * 3. Is a special role defined in providesLabelNotTitle
    *   ... return its name as a label (AXDescription).
    */
   if (accWrap) {
     ENameValueFlag flag = accWrap->Name(name);
     if (flag == eNameFromSubtree) {
       return nil;
     }
 
-    if (mRole != roles::GROUPING && mRole != roles::RADIO_GROUP) {
+    if (![self providesLabelNotTitle]) {
       Relation rel = accWrap->RelationByType(RelationType::LABELLED_BY);
       if (rel.Next() && !rel.Next()) {
         return nil;
       }
     }
   } else if (proxy) {
     uint32_t flag = proxy->Name(name);
     if (flag == eNameFromSubtree) {
       return nil;
     }
 
-    if (mRole != roles::GROUPING && mRole != roles::RADIO_GROUP) {
+    if (![self providesLabelNotTitle]) {
       nsTArray<ProxyAccessible*> rels = proxy->RelationByType(RelationType::LABELLED_BY);
       if (rels.Length() == 1) {
         return nil;
       }
     }
   }
 
   return nsCocoaUtils::ToNSString(name);
@@ -1123,18 +1130,18 @@ struct RoleDescrComparator {
   }
 
   return NSAccessibilityRoleDescription([self role], subrole);
 }
 
 - (NSString*)title {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
-  // If this is a grouping we provide the name in the label (AXDescription).
-  if (mRole == roles::GROUPING || mRole == roles::RADIO_GROUP) {
+  // In some special cases we provide the name in the label (AXDescription).
+  if ([self providesLabelNotTitle]) {
     return nil;
   }
 
   nsAutoString title;
   if (AccessibleWrap* accWrap = [self getGeckoAccessible])
     accWrap->Name(title);
   else if (ProxyAccessible* proxy = [self getProxyAccessible])
     proxy->Name(title);
--- a/accessible/tests/browser/mac/browser_roles_elements.js
+++ b/accessible/tests/browser/mac/browser_roles_elements.js
@@ -22,8 +22,62 @@ addAccessibleTask(`<hr id="hr" />`, (bro
     "AXRole for hr is AXSplitter"
   );
   is(
     hr.getAttributeValue("AXSubrole"),
     "AXContentSeparator",
     "Subrole for hr is AXContentSeparator"
   );
 });
+
+addAccessibleTask(
+  `
+  <figure id="figure">
+    <img id="img" src="http://example.com/a11y/accessible/tests/mochitest/moz.png" alt="Logo">
+    <p>Non-image figure content</p>
+    <figcaption id="figcaption">Old Mozilla logo</figcaption>
+  </figure>`,
+  (browser, accDoc) => {
+    let figure = getNativeInterface(accDoc, "figure");
+    ok(!figure.getAttributeValue("AXTitle"), "Figure should not have a title");
+    is(
+      figure.getAttributeValue("AXDescription"),
+      "Old Mozilla logo",
+      "Correct figure label"
+    );
+    is(figure.getAttributeValue("AXRole"), "AXGroup", "Correct figure role");
+    is(
+      figure.getAttributeValue("AXRoleDescription"),
+      "figure",
+      "Correct figure role description"
+    );
+
+    let img = getNativeInterface(accDoc, "img");
+    ok(!img.getAttributeValue("AXTitle"), "img should not have a title");
+    is(img.getAttributeValue("AXDescription"), "Logo", "Correct img label");
+    is(img.getAttributeValue("AXRole"), "AXImage", "Correct img role");
+    is(
+      img.getAttributeValue("AXRoleDescription"),
+      "image",
+      "Correct img role description"
+    );
+
+    let figcaption = getNativeInterface(accDoc, "figcaption");
+    ok(
+      !figcaption.getAttributeValue("AXTitle"),
+      "figcaption should not have a title"
+    );
+    ok(
+      !figcaption.getAttributeValue("AXDescription"),
+      "figcaption should not have a label"
+    );
+    is(
+      figcaption.getAttributeValue("AXRole"),
+      "AXGroup",
+      "Correct figcaption role"
+    );
+    is(
+      figcaption.getAttributeValue("AXRoleDescription"),
+      "group",
+      "Correct figcaption role description"
+    );
+  }
+);