Bug 1136563 - ARIA 1.1: Support role 'switch', r=surkov
authorMarco Zehe <mzehe@mozilla.com>
Thu, 26 Feb 2015 14:47:15 +0100
changeset 259810 fef52bcc6093723bc4e9630232b640ba8d4a6921
parent 259809 5ac8bf7b8ee321d496cac292578350d5b532c5cf
child 259811 9e73726c6d3096d9fce7cf9a5de825fb754323a0
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssurkov
bugs1136563
milestone39.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 1136563 - ARIA 1.1: Support role 'switch', r=surkov
accessible/base/ARIAMap.cpp
accessible/base/Role.h
accessible/base/RoleMap.h
accessible/interfaces/nsIAccessibleRole.idl
accessible/mac/mozAccessible.mm
accessible/tests/mochitest/actions/test_aria.html
accessible/tests/mochitest/events/test_aria_statechange.html
accessible/tests/mochitest/role.js
accessible/tests/mochitest/role/test_aria.html
accessible/tests/mochitest/states/test_aria.html
dom/base/nsGkAtomList.h
--- a/accessible/base/ARIAMap.cpp
+++ b/accessible/base/ARIAMap.cpp
@@ -535,16 +535,27 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     roles::STATUSBAR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     ePoliteLiveAttr,
     kGenericAccType,
     kNoReqStates
   },
+  { // switch
+    &nsGkAtoms::_switch,
+    roles::SWITCH,
+    kUseMapRole,
+    eNoValue,
+    eCheckUncheckAction,
+    eNoLiveAttr,
+    kGenericAccType,
+    kNoReqStates,
+    eARIACheckableBool
+  },
   { // tab
     &nsGkAtoms::tab,
     roles::PAGETAB,
     kUseMapRole,
     eNoValue,
     eSwitchAction,
     eNoLiveAttr,
     kGenericAccType,
--- a/accessible/base/Role.h
+++ b/accessible/base/Role.h
@@ -780,17 +780,22 @@ enum Role {
    */
   DEFINITION = 128,
 
   /**
    * Represent a keyboard or keypad key (ARIA role "key").
    */
   KEY = 129,
 
-  LAST_ROLE = KEY
+  /**
+   * Represent a switch control widget (ARIA role "switch").
+   */
+  SWITCH = 130,
+
+  LAST_ROLE = SWITCH
 };
 
 } // namespace role
 
 typedef enum mozilla::a11y::roles::Role role;
 
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/base/RoleMap.h
+++ b/accessible/base/RoleMap.h
@@ -1050,8 +1050,16 @@ ROLE(DEFINITION,
 
 ROLE(KEY,
      "key",
      ATK_ROLE_PUSH_BUTTON,
      NSAccessibilityButtonRole,
      ROLE_SYSTEM_PUSHBUTTON,
      ROLE_SYSTEM_PUSHBUTTON,
      eNameFromSubtreeRule)
+
+ROLE(SWITCH,
+     "switch",
+     ATK_ROLE_TOGGLE_BUTTON,
+     NSAccessibilityCheckBoxRole,
+     ROLE_SYSTEM_CHECKBUTTON,
+     IA2_ROLE_TOGGLE_BUTTON,
+     eNameFromSubtreeRule)
--- a/accessible/interfaces/nsIAccessibleRole.idl
+++ b/accessible/interfaces/nsIAccessibleRole.idl
@@ -3,17 +3,17 @@
  * 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 "nsISupports.idl"
 
 /**
  * Defines cross platform (Gecko) roles.
  */
-[scriptable, uuid(50db5e86-9a45-4637-a5c3-4ff148c33270)]
+[scriptable, uuid(76ce835f-ef86-47c0-ac7b-e871417f1b6e)]
 interface nsIAccessibleRole : nsISupports
 {
   /**
    * Used when accessible hans't strong defined role.
    */
   const unsigned long ROLE_NOTHING = 0;
 
   /**
@@ -773,9 +773,14 @@ interface nsIAccessibleRole : nsISupport
    * An HTML definition <dd>
    */
   const unsigned long ROLE_DEFINITION = 128;
 
   /**
    * A keyboard or keypad key.
    */
   const unsigned long ROLE_KEY = 129;
+
+  /**
+   * A switch control widget.
+   */
+  const unsigned long ROLE_SWITCH = 130;
 };
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -470,16 +470,19 @@ GetClosestInterestingAccessible(id anObj
       return @"AXDefinitionList"; // 10.6+ NSAccessibilityDefinitionListSubrole;
 
     case roles::TERM:
       return @"AXTerm";
 
     case roles::DEFINITION:
       return @"AXDefinition";
 
+    case roles::SWITCH:
+      return @"AXSwitch";
+
     default:
       break;
   }
 
   return nil;
 }
 
 - (NSString*)roleDescription
--- a/accessible/tests/mochitest/actions/test_aria.html
+++ b/accessible/tests/mochitest/actions/test_aria.html
@@ -81,16 +81,26 @@
           events: CLICK_EVENTS
         },
         {
           ID: "radio",
           actionName: "select",
           events: CLICK_EVENTS
         },
         {
+          ID: "switch_unchecked",
+          actionName: "check",
+          events: CLICK_EVENTS
+        },
+        {
+          ID: "switch_checked",
+          actionName: "uncheck",
+          events: CLICK_EVENTS
+        },
+        {
           ID: "tab",
           actionName: "switch",
           events: CLICK_EVENTS
         },
         {
           ID: "textbox",
           actionName: "activate",
           events: CLICK_EVENTS
@@ -161,16 +171,20 @@
     <div id="menuitemcheckbox" role="menuitemcheckbox">Menuitem checkbox</div>
     <div id="menuitemradio" role="menuitemradio">Menuitem radio</div>
   </div>
 
   <div role="radiogroup">
     <div id="radio" role="radio">Radio</div>
   </div>
 
+  <div id="switch_unchecked" role="switch">Switch</div>
+
+  <div id="switch_checked" role="switch" aria-checked="true">Switch</div>
+
   <div role="tablist">
     <div id="tab" role="tab">Tab</div>
   </div>
 
   <div id="textbox" role="textbox">Textbox</div>
 
   <div role="tree">
     <div id="treeitem" role="treeitem">Treeitem</div>
--- a/accessible/tests/mochitest/events/test_aria_statechange.html
+++ b/accessible/tests/mochitest/events/test_aria_statechange.html
@@ -102,27 +102,38 @@
     }
 
     function setChecked(aID, aValue)
     {
       this.__proto__ =
         new setAttrOfMixedType(aID, "aria-checked", STATE_CHECKED, aValue);
     }
 
+    function buildQueueForAttr(aList, aQueue, aID, aInvokerFunc)
+    {
+      for (var i = 0; i < aList.length; i++) {
+        for (var j = i + 1; j < aList.length; j++) {
+          // XXX: changes from/to "undefined"/"" shouldn't fire state change
+          // events, bug 472142.
+          aQueue.push(new aInvokerFunc(aID, aList[i]));
+          aQueue.push(new aInvokerFunc(aID, aList[j]));
+        }
+      }
+    }
+
     function buildQueueForAttrOfMixedType(aQueue, aID, aInvokerFunc)
     {
       var list = [ "", "undefined", "false", "true", "mixed" ];
-      for (var i = 0; i < list.length; i++) {
-        for (var j = i + 1; j < list.length; j++) {
-          // XXX: changes from/to "undefined"/"" shouldn't fire state change
-          // events, bug 472142.
-          aQueue.push(new aInvokerFunc(aID, list[i]));
-          aQueue.push(new aInvokerFunc(aID, list[j]));
-        }
-      }
+      buildQueueForAttr(list, aQueue, aID, aInvokerFunc);
+    }
+
+    function buildQueueForAttrOfBoolType(aQueue, aID, aInvokerFunc)
+    {
+      var list = [ "", "undefined", "false", "true" ];
+      buildQueueForAttr(list, aQueue, aID, aInvokerFunc);
     }
 
     function doTests()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new expandNode("section", true));
       gQueue.push(new expandNode("section", false));
@@ -130,16 +141,17 @@
       gQueue.push(new expandNode("div", false));
 
       gQueue.push(new busyify("aria_doc", true));
       gQueue.push(new busyify("aria_doc", false));
 
       buildQueueForAttrOfMixedType(gQueue, "pressable", setPressed);
       buildQueueForAttrOfMixedType(gQueue, "pressable_native", setPressed);
       buildQueueForAttrOfMixedType(gQueue, "checkable", setChecked);
+      buildQueueForAttrOfBoolType(gQueue, "checkableBool", setChecked);
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
@@ -161,16 +173,21 @@
      title="mixed state change event is fired for focused accessible only"
     Mozilla Bug 467143
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
      title="Pressed state is not exposed on a button element with aria-pressed attribute"
     Mozilla Bug 989958
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
+     title="Support ARIA 1.1 switch role"
+    Mozilla Bug 1136563
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <!-- aria-expanded -->
@@ -181,10 +198,11 @@
   <div id="aria_doc" role="document" tabindex="0">A document</div>
 
   <!-- aria-pressed -->
   <div id="pressable" role="button"></div>
   <button id="pressable_native"></button>
 
   <!-- aria-checked -->
   <div id="checkable" role="checkbox"></div>
+  <div id="checkableBool" role="switch"></div>
 </body>
 </html>
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -65,16 +65,17 @@ const ROLE_ROW = nsIAccessibleRole.ROLE_
 const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
 const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;
 const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
 const ROLE_SEPARATOR = nsIAccessibleRole.ROLE_SEPARATOR;
 const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
 const ROLE_SPINBUTTON = nsIAccessibleRole.ROLE_SPINBUTTON;
 const ROLE_STATICTEXT = nsIAccessibleRole.ROLE_STATICTEXT;
 const ROLE_STATUSBAR = nsIAccessibleRole.ROLE_STATUSBAR;
+const ROLE_SWITCH = nsIAccessibleRole.ROLE_SWITCH;
 const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
 const ROLE_TERM = nsIAccessibleRole.ROLE_TERM;
 const ROLE_TEXT_CONTAINER = nsIAccessibleRole.ROLE_TEXT_CONTAINER;
 const ROLE_TEXT_LEAF = nsIAccessibleRole.ROLE_TEXT_LEAF;
 const ROLE_TOGGLE_BUTTON = nsIAccessibleRole.ROLE_TOGGLE_BUTTON;
 const ROLE_TOOLBAR = nsIAccessibleRole.ROLE_TOOLBAR;
 const ROLE_TOOLTIP = nsIAccessibleRole.ROLE_TOOLTIP;
 const ROLE_TREE_TABLE = nsIAccessibleRole.ROLE_TREE_TABLE;
--- a/accessible/tests/mochitest/role/test_aria.html
+++ b/accessible/tests/mochitest/role/test_aria.html
@@ -55,16 +55,17 @@
       testRole("aria_region", ROLE_PANE);
       testRole("aria_row", ROLE_ROW);
       testRole("aria_rowheader", ROLE_ROWHEADER);
       testRole("aria_scrollbar", ROLE_SCROLLBAR);
       testRole("aria_separator", ROLE_SEPARATOR);
       testRole("aria_slider", ROLE_SLIDER);
       testRole("aria_spinbutton", ROLE_SPINBUTTON);
       testRole("aria_status", ROLE_STATUSBAR);
+      testRole("aria_switch", ROLE_SWITCH);
       testRole("aria_tab", ROLE_PAGETAB);
       testRole("aria_tablist", ROLE_PAGETABLIST);
       testRole("aria_tabpanel", ROLE_PROPERTYPAGE);
       testRole("aria_textbox", ROLE_ENTRY);
       testRole("aria_timer", ROLE_TEXT_CONTAINER); // weak role
       testRole("aria_toolbar", ROLE_TOOLBAR);
       testRole("aria_tooltip", ROLE_TOOLTIP);
       testRole("aria_tree", ROLE_OUTLINE);
@@ -173,16 +174,21 @@
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=725432">
     Bug 725432
   </a>
   <a target="_blank"
      title="Map ARIA role FORM"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=735645">
     Bug 735645
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
+     title="Support ARIA 1.1 switch role"
+    Bug 1136563
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <span id="aria_alert" role="alert"/>
   <span id="aria_alertdialog" role="alertdialog"/>
   <span id="aria_application" role="application"/>
@@ -220,16 +226,17 @@
   <span id="aria_region" role="region"/>
   <span id="aria_row" role="row"/>
   <span id="aria_rowheader" role="rowheader"/>
   <span id="aria_scrollbar" role="scrollbar"/>
   <span id="aria_separator" role="separator"/>
   <span id="aria_slider" role="slider"/>
   <span id="aria_spinbutton" role="spinbutton"/>
   <span id="aria_status" role="status"/>
+  <span id="aria_switch" role="switch"/>
   <span id="aria_tab" role="tab"/>
   <span id="aria_tablist" role="tablist"/>
   <span id="aria_tabpanel" role="tabpanel"/>
   <span id="aria_textbox" role="textbox"/>
   <span id="aria_timer" role="timer"/>
   <span id="aria_toolbar" role="toolbar"/>
   <span id="aria_tooltip" role="tooltip"/>
   <span id="aria_tree" role="tree"/>
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -87,16 +87,18 @@
         testStates(checkboxElem, 0, 0, STATE_CHECKED);
         checkboxElem.indeterminate = true;
         testStates(checkboxElem, STATE_MIXED, 0);
       }
 
       // aria-checked
       testStates("aria_checked_checkbox", STATE_CHECKED);
       testStates("aria_mixed_checkbox", STATE_MIXED);
+      testStates("aria_checked_switch", STATE_CHECKED);
+      testStates("aria_mixed_switch", 0, 0, STATE_MIXED); // unsupported
 
       // test disabled group and all its descendants to see if they are
       // disabled, too. See bug 429285.
       testAriaDisabledTree("group");
 
       // aria-modal
       testStates("aria_modal", 0, EXT_STATE_MODAL);
       testStates("aria_modal_false", 0, 0, 0, EXT_STATE_MODAL);
@@ -345,16 +347,21 @@
      title="ARIA grid should be editable by default">
     Mozilla Bug 835121
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=989958"
      title="Pressed state is not exposed on a button element with aria-pressed attribute"
     Mozilla Bug 989958
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136563"
+     title="Support ARIA 1.1 switch role"
+    Mozilla Bug 1136563
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="textbox_autocomplete_inline" role="textbox" aria-autocomplete="inline"></div>
   <div id="textbox_autocomplete_list" role="textbox" aria-autocomplete="list"></div>
@@ -378,16 +385,25 @@
 
   <div id="aria_checked_checkbox" role="checkbox" aria-checked="true">
     I agree
   </div>
 
   <div id="aria_mixed_checkbox" role="checkbox" aria-checked="mixed">
     I might agree
   </div>
+
+  <div id="aria_checked_switch" role="switch" aria-checked="true">
+    I am switched on
+  </div>
+
+  <div id="aria_mixed_switch" role="switch" aria-checked="mixed">
+    I am unsupported
+  </div>
+
   <div id="aria_modal" aria-modal="true">modal stuff</div>
   <div id="aria_modal_false" aria-modal="false">non modal stuff</div>div>
   <div id="aria_multiline_textbox" role="textbox" aria-multiline="true"></div>
   <div id="aria_multiselectable_listbox" role="listbox" aria-multiselectable="true"></div>
   <div id="aria_pressed_button" role="button" aria-pressed="true">Button</div>
   <button id="aria_pressed_native_button" aria-pressed="true">Button</button>
 
   <div id="aria_readonly_textbox"
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2291,16 +2291,17 @@ GK_ATOM(progressbar, "progressbar")
 GK_ATOM(region, "region")
 GK_ATOM(rowgroup, "rowgroup")
 GK_ATOM(rowheader, "rowheader")
 GK_ATOM(select1, "select1")
 GK_ATOM(setsize, "setsize")
 GK_ATOM(spelling, "spelling")
 GK_ATOM(spinbutton, "spinbutton")
 GK_ATOM(status, "status")
+GK_ATOM(_switch, "switch")
 GK_ATOM(tableCellIndex, "table-cell-index")
 GK_ATOM(tablist, "tablist")
 GK_ATOM(textIndent, "text-indent")
 GK_ATOM(textInputType, "text-input-type")
 GK_ATOM(textLineThroughColor, "text-line-through-color")
 GK_ATOM(textLineThroughStyle, "text-line-through-style")
 GK_ATOM(textPosition, "text-position")
 GK_ATOM(textUnderlineColor, "text-underline-color")