Bug 1480058 part 1: Expose states for aria-selected/aria-multiselectable on XUL tab/tabs. r?surkov draft
authorJames Teh <jteh@mozilla.com>
Thu, 02 Aug 2018 16:25:09 +1000
changeset 827111 f6267cbaefca09a412bf409c7ccdb30075fe9ced
parent 826132 b1c100e2b29a8e671678eb537ba69badc249c2fe
child 827112 011c0263f2015b267c0607d88f080629b087ae29
push id118470
push userbmo:jteh@mozilla.com
push dateTue, 07 Aug 2018 05:07:07 +0000
reviewerssurkov
bugs1480058
milestone63.0a1
Bug 1480058 part 1: Expose states for aria-selected/aria-multiselectable on XUL tab/tabs. r?surkov MozReview-Commit-ID: JeV5vBffQIq
accessible/tests/mochitest/states/test_aria.xul
accessible/xul/XULTabAccessible.cpp
accessible/xul/XULTabAccessible.h
--- a/accessible/tests/mochitest/states/test_aria.xul
+++ b/accessible/tests/mochitest/states/test_aria.xul
@@ -19,16 +19,24 @@
   <script type="application/javascript">
   <![CDATA[
     function doTest()
     {
       // aria-pressed
       testStates("pressed_button", STATE_PRESSED, 0, STATE_CHECKABLE);
       testStates("pressed_menu_button", STATE_PRESSED | STATE_HASPOPUP, 0, STATE_CHECKABLE);
 
+      testStates("tabs", STATE_MULTISELECTABLE);
+      // Make sure XUL selection works, since aria-selected defaults to false.
+      testStates("tab1", STATE_SELECTED);
+      // aria-selected="true".
+      testStates("tab2", STATE_SELECTED);
+      // Neither.
+      testStates("tab3", 0, 0, STATE_SELECTED);
+
       SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
@@ -48,13 +56,21 @@
 
     <vbox flex="1">
       <button id="pressed_button" aria-pressed="true" label="I am pressed" />
       <button id="pressed_menu_button" aria-pressed="true" label="I am pressed" type="menu-button">
         <menupopup>
           <menuitem label="I am a menu item" />
         </menupopup>
       </button>
+
+      <tabbox>
+        <tabs id="tabs" aria-multiselectable="true">
+          <tab id="tab1" label="tab1" selected="true"/>
+          <tab id="tab2" label="tab2" aria-selected="true"/>
+          <tab id="tab3" label="tab3"/>
+        </tabs>
+      </tabbox>
     </vbox>
   </hbox>
 
 </window>
 
--- a/accessible/xul/XULTabAccessible.cpp
+++ b/accessible/xul/XULTabAccessible.cpp
@@ -1,15 +1,16 @@
 /* -*- 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 "XULTabAccessible.h"
 
+#include "ARIAMap.h"
 #include "nsAccUtils.h"
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 
 // NOTE: alphabetically ordered
 #include "nsIDocument.h"
 #include "nsIDOMXULSelectCntrlEl.h"
@@ -118,16 +119,27 @@ XULTabAccessible::RelationByType(Relatio
   tabsElm->GetRelatedElement(GetNode(), getter_AddRefs(tabpanelElement));
   if (!tabpanelElement)
     return rel;
 
   rel.AppendTarget(mDoc, tabpanelElement);
   return rel;
 }
 
+void
+XULTabAccessible::ApplyARIAState(uint64_t* aState) const
+{
+  HyperTextAccessibleWrap::ApplyARIAState(aState);
+  // XUL tab has an implicit ARIA role of tab, so support aria-selected.
+  // Don't use aria::MapToState because that will set the SELECTABLE state
+  // even if the tab is disabled.
+  if (nsAccUtils::IsARIASelected(this)) {
+    *aState |= states::SELECTED;
+  }
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTabsAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULTabsAccessible::
   XULTabsAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   XULSelectControlAccessible(aContent, aDoc)
@@ -154,16 +166,26 @@ XULTabsAccessible::Value(nsString& aValu
 
 ENameValueFlag
 XULTabsAccessible::NativeName(nsString& aName) const
 {
   // no name
   return eNameOK;
 }
 
+void
+XULTabsAccessible::ApplyARIAState(uint64_t* aState) const
+{
+  XULSelectControlAccessible::ApplyARIAState(aState);
+  // XUL tabs has an implicit ARIA role of tablist, so support
+  // aria-multiselectable.
+  MOZ_ASSERT(Elm());
+  aria::MapToState(aria::eARIAMultiSelectable, Elm(), aState);
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTabpanelsAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 role
 XULTabpanelsAccessible::NativeRole() const
 {
--- a/accessible/xul/XULTabAccessible.h
+++ b/accessible/xul/XULTabAccessible.h
@@ -24,16 +24,17 @@ public:
 
   XULTabAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // Accessible
   virtual a11y::role NativeRole() const override;
   virtual uint64_t NativeState() const override;
   virtual uint64_t NativeInteractiveState() const override;
   virtual Relation RelationByType(RelationType aType) const override;
+  virtual void ApplyARIAState(uint64_t* aState) const override;
 
   // ActionAccessible
   virtual uint8_t ActionCount() const override;
   virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
   virtual bool DoAction(uint8_t aIndex) const override;
 };
 
 
@@ -43,16 +44,17 @@ public:
 class XULTabsAccessible : public XULSelectControlAccessible
 {
 public:
   XULTabsAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // Accessible
   virtual void Value(nsString& aValue) const override;
   virtual a11y::role NativeRole() const override;
+  virtual void ApplyARIAState(uint64_t* aState) const override;
 
   // ActionAccessible
   virtual uint8_t ActionCount() const override;
 
 protected:
   // Accessible
   virtual ENameValueFlag NativeName(nsString& aName) const override;
 };