Bug 882767 - don't expose whitespace accessibles in context of grids, r=tbsaunde
authorAlexander Surkov <surkov.alexander@gmail.com>
Thu, 18 Jul 2013 11:09:45 -0400
changeset 139091 5d32adf0d68d2783ce769d358c61688ebf7c5011
parent 139090 0097d05cceea681dd440090d7af29473cf300dd5
child 139092 c1025190b208f45de84de28cdb046309c9fb2291
push id24977
push userryanvm@gmail.com
push dateFri, 19 Jul 2013 00:35:38 +0000
treeherdermozilla-central@0d0263a58f06 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs882767
milestone25.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 882767 - don't expose whitespace accessibles in context of grids, r=tbsaunde
accessible/src/base/nsAccessibilityService.cpp
accessible/src/base/nsCoreUtils.cpp
accessible/src/base/nsCoreUtils.h
accessible/src/base/nsTextEquivUtils.cpp
accessible/src/base/nsTextEquivUtils.h
accessible/src/generic/ARIAGridAccessible.cpp
accessible/src/generic/Accessible.h
accessible/src/html/HTMLTableAccessible.cpp
accessible/src/xul/XULListboxAccessible.cpp
accessible/src/xul/XULTreeGridAccessible.cpp
accessible/tests/mochitest/tree/test_aria_grid.html
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -866,17 +866,20 @@ nsAccessibilityService::GetOrCreateAcces
 
   // Attempt to create an accessible based on what we know.
   nsRefPtr<Accessible> newAcc;
 
   // Create accessible for visible text frames.
   if (content->IsNodeOfType(nsINode::eTEXT)) {
     nsAutoString text;
     frame->GetRenderedText(&text, nullptr, nullptr, 0, UINT32_MAX);
-    if (text.IsEmpty()) {
+    // Ignore not rendered text nodes and whitespace text nodes between table
+    // cells.
+    if (text.IsEmpty() ||
+        (aContext->IsTableRow() && nsCoreUtils::IsWhitespaceString(text))) {
       if (aIsSubtreeHidden)
         *aIsSubtreeHidden = true;
 
       return nullptr;
     }
 
     newAcc = CreateAccessibleByFrameType(frame, content, aContext);
     if (document->BindToDocument(newAcc, nullptr)) {
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -649,16 +649,30 @@ nsCoreUtils::ScrollTo(nsIPresShell* aPre
                       uint32_t aScrollType)
 {
   nsIPresShell::ScrollAxis vertical, horizontal;
   ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
   aPresShell->ScrollContentIntoView(aContent, vertical, horizontal,
                                     nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
 }
 
+bool
+nsCoreUtils::IsWhitespaceString(const nsSubstring& aString)
+{
+  nsSubstring::const_char_iterator iterBegin, iterEnd;
+
+  aString.BeginReading(iterBegin);
+  aString.EndReading(iterEnd);
+
+  while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
+    ++iterBegin;
+
+  return iterBegin == iterEnd;
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibleDOMStringList
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS1(nsAccessibleDOMStringList, nsIDOMDOMStringList)
 
 NS_IMETHODIMP
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -1,17 +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/. */
 
 #ifndef nsCoreUtils_h_
 #define nsCoreUtils_h_
 
-
 #include "nsIContent.h"
 #include "nsIBoxObject.h"
 #include "nsIPresShell.h"
 
 #include "nsIDOMDOMStringList.h"
 #include "nsPoint.h"
 #include "nsTArray.h"
 
@@ -289,16 +288,31 @@ public:
    * Return true if the given node is table header element.
    */
   static bool IsHTMLTableHeader(nsIContent *aContent)
   {
     return aContent->NodeInfo()->Equals(nsGkAtoms::th) ||
       aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope);
   }
 
+  /**
+   * Returns true if the given string is empty or contains whitespace symbols
+   * only. In contrast to nsWhitespaceTokenizer class it takes into account
+   * non-breaking space (0xa0).
+   */
+  static bool IsWhitespaceString(const nsSubstring& aString);
+
+  /**
+   * Returns true if the given character is whitespace symbol.
+   */
+  static bool IsWhitespace(PRUnichar aChar)
+  {
+    return aChar == ' ' || aChar == '\n' ||
+      aChar == '\r' || aChar == '\t' || aChar == 0xa0;
+  }
 };
 
 
 /**
  * nsIDOMDOMStringList implementation.
  */
 class nsAccessibleDOMStringList : public nsIDOMDOMStringList
 {
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -40,17 +40,17 @@ nsTextEquivUtils::GetNameFromSubtree(Acc
 
   sInitiatorAcc = aAccessible;
   if (GetRoleRule(aAccessible->Role()) == eNameFromSubtreeRule) {
     //XXX: is it necessary to care the accessible is not a document?
     if (aAccessible->IsContent()) {
       nsAutoString name;
       AppendFromAccessibleChildren(aAccessible, &name);
       name.CompressWhitespace();
-      if (!IsWhitespaceString(name))
+      if (!nsCoreUtils::IsWhitespaceString(name))
         aName = name;
     }
   }
 
   sInitiatorAcc = nullptr;
 
   return NS_OK;
 }
@@ -346,48 +346,27 @@ nsTextEquivUtils::AppendFromDOMNode(nsIC
 bool
 nsTextEquivUtils::AppendString(nsAString *aString,
                                const nsAString& aTextEquivalent)
 {
   if (aTextEquivalent.IsEmpty())
     return false;
 
   // Insert spaces to insure that words from controls aren't jammed together.
-  if (!aString->IsEmpty() && !IsWhitespace(aString->Last()))
+  if (!aString->IsEmpty() && !nsCoreUtils::IsWhitespace(aString->Last()))
     aString->Append(PRUnichar(' '));
 
   aString->Append(aTextEquivalent);
 
-  if (!IsWhitespace(aString->Last()))
+  if (!nsCoreUtils::IsWhitespace(aString->Last()))
     aString->Append(PRUnichar(' '));
 
   return true;
 }
 
-bool
-nsTextEquivUtils::IsWhitespaceString(const nsSubstring& aString)
-{
-  nsSubstring::const_char_iterator iterBegin, iterEnd;
-
-  aString.BeginReading(iterBegin);
-  aString.EndReading(iterEnd);
-
-  while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
-    ++iterBegin;
-
-  return iterBegin == iterEnd;
-}
-
-bool
-nsTextEquivUtils::IsWhitespace(PRUnichar aChar)
-{
-  return aChar == ' ' || aChar == '\n' ||
-    aChar == '\r' || aChar == '\t' || aChar == 0xa0;
-}
-
 uint32_t 
 nsTextEquivUtils::GetRoleRule(role aRole)
 {
 #define ROLE(geckoRole, stringRole, atkRole, \
              macRole, msaaRole, ia2Role, nameRule) \
   case roles::geckoRole: \
     return nameRule;
 
--- a/accessible/src/base/nsTextEquivUtils.h
+++ b/accessible/src/base/nsTextEquivUtils.h
@@ -133,26 +133,14 @@ private:
   /**
    * Concatenates strings and appends space between them. Returns true if
    * text equivalent string was appended.
    */
   static bool AppendString(nsAString *aString,
                              const nsAString& aTextEquivalent);
 
   /**
-   * Returns true if the given string is empty or contains whitespace symbols
-   * only. In contrast to nsWhitespaceTokenizer class it takes into account
-   * non-breaking space (0xa0).
-   */
-  static bool IsWhitespaceString(const nsSubstring& aString);
-
-  /**
-   * Returns true if the given character is whitespace symbol.
-   */
-  static bool IsWhitespace(PRUnichar aChar);
-
-  /**
    * Returns the rule (constant of ETextEquivRule) for a given role.
    */
   static uint32_t GetRoleRule(mozilla::a11y::roles::Role aRole);
 };
 
 #endif
--- a/accessible/src/generic/ARIAGridAccessible.cpp
+++ b/accessible/src/generic/ARIAGridAccessible.cpp
@@ -528,16 +528,17 @@ ARIAGridAccessible::SetARIASelected(Acce
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor
 
 ARIAGridCellAccessible::
   ARIAGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
 {
+  mGenericTypes |= eTableCell;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_ISUPPORTS_INHERITED1(ARIAGridCellAccessible,
                              HyperTextAccessible,
                              nsIAccessibleTableCell)
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -510,16 +510,17 @@ public:
   bool IsRoot() const { return mType == eRootType; }
   a11y::RootAccessible* AsRoot();
 
   bool IsSelect() const { return HasGenericType(eSelect); }
 
   bool IsTable() const { return HasGenericType(eTable); }
   virtual TableAccessible* AsTable() { return nullptr; }
 
+  bool IsTableCell() const { return HasGenericType(eTableCell); }
   virtual TableCellAccessible* AsTableCell() { return nullptr; }
   const TableCellAccessible* AsTableCell() const
     { return const_cast<Accessible*>(this)->AsTableCell(); }
 
   bool IsTableRow() const { return HasGenericType(eTableRow); }
 
   bool IsTextField() const { return mType == eHTMLTextFieldType; }
 
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -43,16 +43,17 @@ using namespace mozilla::a11y;
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableCellAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLTableCellAccessible::
   HTMLTableCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
 {
+  mGenericTypes |= eTableCell;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableCellAccessible: nsISupports implementation
 
 NS_IMPL_ISUPPORTS_INHERITED1(HTMLTableCellAccessible,
                              HyperTextAccessible,
                              nsIAccessibleTableCell)
--- a/accessible/src/xul/XULListboxAccessible.cpp
+++ b/accessible/src/xul/XULListboxAccessible.cpp
@@ -726,16 +726,17 @@ XULListitemAccessible::ContainerWidget()
 ////////////////////////////////////////////////////////////////////////////////
 // XULListCellAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULListCellAccessible::
   XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
 {
+  mGenericTypes |= eTableCell;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_ISUPPORTS_INHERITED1(XULListCellAccessible,
                              HyperTextAccessible,
                              nsIAccessibleTableCell)
--- a/accessible/src/xul/XULTreeGridAccessible.cpp
+++ b/accessible/src/xul/XULTreeGridAccessible.cpp
@@ -448,16 +448,17 @@ XULTreeGridCellAccessible::
                             XULTreeGridRowAccessible* aRowAcc,
                             nsITreeBoxObject* aTree, nsITreeView* aTreeView,
                             int32_t aRow, nsITreeColumn* aColumn) :
   LeafAccessible(aContent, aDoc), xpcAccessibleTableCell(this), mTree(aTree),
   mTreeView(aTreeView), mRow(aRow), mColumn(aColumn)
 {
   mParent = aRowAcc;
   mStateFlags |= eSharedNode;
+  mGenericTypes |= eTableCell;
 
   NS_ASSERTION(mTreeView, "mTreeView is null");
 
   int16_t type = -1;
   mColumn->GetType(&type);
   if (type == nsITreeColumn::TYPE_CHECKBOX)
     mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
   else
--- a/accessible/tests/mochitest/tree/test_aria_grid.html
+++ b/accessible/tests/mochitest/tree/test_aria_grid.html
@@ -146,16 +146,36 @@
               }
             ]
           }
         ]
       };
 
       testAccessibleTree("crazy_grid4", accTree);
 
+      //////////////////////////////////////////////////////////////////////////
+      // grids that could contain whitespace accessibles but shouldn't.
+
+      var accTree =
+        { TREE_TABLE: [
+          { ROW: [
+            { GRID_CELL: [
+              { TEXT_LEAF: [ ] }
+            ] },
+            { GRID_CELL: [
+              { TEXT_LEAF: [ ] }
+            ] },
+            { GRID_CELL: [
+              { TEXT_LEAF: [ ] }
+            ] }
+          ] },
+        ] };
+
+      testAccessibleTree("whitespaces-grid", accTree);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
@@ -222,10 +242,18 @@
                 <tr><td>cell4</td></tr>
               </table>
             </td>
           </tr>
         </table>
       </div>
     </div>
   </div>
+
+  <div role="treegrid" id="whitespaces-grid">
+    <div role="row" aria-selected="false" tabindex="-1">
+      <span role="gridcell">03:30PM-04:30PM</span>
+      <span role="gridcell" style="font-weight:bold;">test</span>
+      <span role="gridcell">a user1</span>
+    </div>
+  </div>
 </body>
 </html>