LCOV - code coverage report
Current view: top level - accessible/base - nsAccUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 218 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsAccUtils.h"
       7             : 
       8             : #include "Accessible-inl.h"
       9             : #include "ARIAMap.h"
      10             : #include "nsAccessibilityService.h"
      11             : #include "nsCoreUtils.h"
      12             : #include "DocAccessible.h"
      13             : #include "HyperTextAccessible.h"
      14             : #include "nsIAccessibleTypes.h"
      15             : #include "Role.h"
      16             : #include "States.h"
      17             : #include "TextLeafAccessible.h"
      18             : 
      19             : #include "nsIDOMXULContainerElement.h"
      20             : #include "nsIPersistentProperties2.h"
      21             : #include "mozilla/dom/Element.h"
      22             : 
      23             : using namespace mozilla;
      24             : using namespace mozilla::a11y;
      25             : 
      26             : void
      27           0 : nsAccUtils::GetAccAttr(nsIPersistentProperties *aAttributes,
      28             :                        nsIAtom *aAttrName, nsAString& aAttrValue)
      29             : {
      30           0 :   aAttrValue.Truncate();
      31             : 
      32           0 :   aAttributes->GetStringProperty(nsAtomCString(aAttrName), aAttrValue);
      33           0 : }
      34             : 
      35             : void
      36           0 : nsAccUtils::SetAccAttr(nsIPersistentProperties *aAttributes,
      37             :                        nsIAtom *aAttrName, const nsAString& aAttrValue)
      38             : {
      39           0 :   nsAutoString oldValue;
      40           0 :   aAttributes->SetStringProperty(nsAtomCString(aAttrName), aAttrValue, oldValue);
      41           0 : }
      42             : 
      43             : void
      44           0 : nsAccUtils::SetAccAttr(nsIPersistentProperties *aAttributes,
      45             :                        nsIAtom* aAttrName, nsIAtom* aAttrValue)
      46             : {
      47           0 :   nsAutoString oldValue;
      48           0 :   aAttributes->SetStringProperty(nsAtomCString(aAttrName),
      49           0 :                                  nsAtomString(aAttrValue), oldValue);
      50           0 : }
      51             : 
      52             : void
      53           0 : nsAccUtils::SetAccGroupAttrs(nsIPersistentProperties *aAttributes,
      54             :                              int32_t aLevel, int32_t aSetSize,
      55             :                              int32_t aPosInSet)
      56             : {
      57           0 :   nsAutoString value;
      58             : 
      59           0 :   if (aLevel) {
      60           0 :     value.AppendInt(aLevel);
      61           0 :     SetAccAttr(aAttributes, nsGkAtoms::level, value);
      62             :   }
      63             : 
      64           0 :   if (aSetSize && aPosInSet) {
      65           0 :     value.Truncate();
      66           0 :     value.AppendInt(aPosInSet);
      67           0 :     SetAccAttr(aAttributes, nsGkAtoms::posinset, value);
      68             : 
      69           0 :     value.Truncate();
      70           0 :     value.AppendInt(aSetSize);
      71           0 :     SetAccAttr(aAttributes, nsGkAtoms::setsize, value);
      72             :   }
      73           0 : }
      74             : 
      75             : int32_t
      76           0 : nsAccUtils::GetDefaultLevel(Accessible* aAccessible)
      77             : {
      78           0 :   roles::Role role = aAccessible->Role();
      79             : 
      80           0 :   if (role == roles::OUTLINEITEM)
      81           0 :     return 1;
      82             : 
      83           0 :   if (role == roles::ROW) {
      84           0 :     Accessible* parent = aAccessible->Parent();
      85             :     // It is a row inside flatten treegrid. Group level is always 1 until it
      86             :     // is overriden by aria-level attribute.
      87           0 :     if (parent && parent->Role() == roles::TREE_TABLE)
      88           0 :       return 1;
      89             :   }
      90             : 
      91           0 :   return 0;
      92             : }
      93             : 
      94             : int32_t
      95           0 : nsAccUtils::GetARIAOrDefaultLevel(Accessible* aAccessible)
      96             : {
      97           0 :   int32_t level = 0;
      98           0 :   nsCoreUtils::GetUIntAttr(aAccessible->GetContent(),
      99           0 :                            nsGkAtoms::aria_level, &level);
     100             : 
     101           0 :   if (level != 0)
     102           0 :     return level;
     103             : 
     104           0 :   return GetDefaultLevel(aAccessible);
     105             : }
     106             : 
     107             : int32_t
     108           0 : nsAccUtils::GetLevelForXULContainerItem(nsIContent *aContent)
     109             : {
     110           0 :   nsCOMPtr<nsIDOMXULContainerItemElement> item(do_QueryInterface(aContent));
     111           0 :   if (!item)
     112           0 :     return 0;
     113             : 
     114           0 :   nsCOMPtr<nsIDOMXULContainerElement> container;
     115           0 :   item->GetParentContainer(getter_AddRefs(container));
     116           0 :   if (!container)
     117           0 :     return 0;
     118             : 
     119             :   // Get level of the item.
     120           0 :   int32_t level = -1;
     121           0 :   while (container) {
     122           0 :     level++;
     123             : 
     124           0 :     nsCOMPtr<nsIDOMXULContainerElement> parentContainer;
     125           0 :     container->GetParentContainer(getter_AddRefs(parentContainer));
     126           0 :     parentContainer.swap(container);
     127             :   }
     128             : 
     129           0 :   return level;
     130             : }
     131             : 
     132             : void
     133           0 : nsAccUtils::SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
     134             :                                        nsIContent* aStartContent,
     135             :                                        dom::Element* aTopEl)
     136             : {
     137           0 :   nsAutoString live, relevant, busy;
     138           0 :   nsIContent* ancestor = aStartContent;
     139           0 :   while (ancestor) {
     140             : 
     141             :     // container-relevant attribute
     142           0 :     if (relevant.IsEmpty() &&
     143           0 :         HasDefinedARIAToken(ancestor, nsGkAtoms::aria_relevant) &&
     144           0 :         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_relevant, relevant))
     145           0 :       SetAccAttr(aAttributes, nsGkAtoms::containerRelevant, relevant);
     146             : 
     147             :     // container-live, and container-live-role attributes
     148           0 :     if (live.IsEmpty()) {
     149           0 :       const nsRoleMapEntry* role = nullptr;
     150           0 :       if (ancestor->IsElement()) {
     151           0 :         role = aria::GetRoleMap(ancestor->AsElement());
     152             :       }
     153           0 :       if (HasDefinedARIAToken(ancestor, nsGkAtoms::aria_live)) {
     154           0 :         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_live, live);
     155           0 :       } else if (role) {
     156           0 :         GetLiveAttrValue(role->liveAttRule, live);
     157             :       }
     158           0 :       if (!live.IsEmpty()) {
     159           0 :         SetAccAttr(aAttributes, nsGkAtoms::containerLive, live);
     160           0 :         if (role) {
     161             :           SetAccAttr(aAttributes, nsGkAtoms::containerLiveRole,
     162           0 :                      role->ARIARoleString());
     163             :         }
     164             :       }
     165             :     }
     166             : 
     167             :     // container-atomic attribute
     168           0 :     if (ancestor->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_atomic,
     169             :                               nsGkAtoms::_true, eCaseMatters)) {
     170           0 :       SetAccAttr(aAttributes, nsGkAtoms::containerAtomic,
     171           0 :                  NS_LITERAL_STRING("true"));
     172             :     }
     173             : 
     174             :     // container-busy attribute
     175           0 :     if (busy.IsEmpty() &&
     176           0 :         HasDefinedARIAToken(ancestor, nsGkAtoms::aria_busy) &&
     177           0 :         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_busy, busy))
     178           0 :       SetAccAttr(aAttributes, nsGkAtoms::containerBusy, busy);
     179             : 
     180           0 :     if (ancestor == aTopEl)
     181           0 :       break;
     182             : 
     183           0 :     ancestor = ancestor->GetParent();
     184           0 :     if (!ancestor)
     185           0 :       ancestor = aTopEl; // Use <body>/<frameset>
     186             :   }
     187           0 : }
     188             : 
     189             : bool
     190           0 : nsAccUtils::HasDefinedARIAToken(nsIContent *aContent, nsIAtom *aAtom)
     191             : {
     192           0 :   NS_ASSERTION(aContent, "aContent is null in call to HasDefinedARIAToken!");
     193             : 
     194           0 :   if (!aContent->HasAttr(kNameSpaceID_None, aAtom) ||
     195           0 :       aContent->AttrValueIs(kNameSpaceID_None, aAtom,
     196           0 :                             nsGkAtoms::_empty, eCaseMatters) ||
     197           0 :       aContent->AttrValueIs(kNameSpaceID_None, aAtom,
     198             :                             nsGkAtoms::_undefined, eCaseMatters)) {
     199           0 :         return false;
     200             :   }
     201           0 :   return true;
     202             : }
     203             : 
     204             : nsIAtom*
     205           0 : nsAccUtils::GetARIAToken(dom::Element* aElement, nsIAtom* aAttr)
     206             : {
     207           0 :   if (!HasDefinedARIAToken(aElement, aAttr))
     208           0 :     return nsGkAtoms::_empty;
     209             : 
     210             :   static nsIContent::AttrValuesArray tokens[] =
     211             :     { &nsGkAtoms::_false, &nsGkAtoms::_true,
     212             :       &nsGkAtoms::mixed, nullptr};
     213             : 
     214             :   int32_t idx = aElement->FindAttrValueIn(kNameSpaceID_None,
     215           0 :                                           aAttr, tokens, eCaseMatters);
     216           0 :   if (idx >= 0)
     217           0 :     return *(tokens[idx]);
     218             : 
     219           0 :   return nullptr;
     220             : }
     221             : 
     222             : Accessible*
     223           0 : nsAccUtils::GetSelectableContainer(Accessible* aAccessible, uint64_t aState)
     224             : {
     225           0 :   if (!aAccessible)
     226           0 :     return nullptr;
     227             : 
     228           0 :   if (!(aState & states::SELECTABLE))
     229           0 :     return nullptr;
     230             : 
     231           0 :   Accessible* parent = aAccessible;
     232           0 :   while ((parent = parent->Parent()) && !parent->IsSelect()) {
     233           0 :     if (parent->Role() == roles::PANE)
     234           0 :       return nullptr;
     235             :   }
     236           0 :   return parent;
     237             : }
     238             : 
     239             : bool
     240           0 : nsAccUtils::IsARIASelected(Accessible* aAccessible)
     241             : {
     242             :   return aAccessible->GetContent()->
     243           0 :     AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_selected,
     244           0 :                 nsGkAtoms::_true, eCaseMatters);
     245             : }
     246             : 
     247             : Accessible*
     248           0 : nsAccUtils::TableFor(Accessible* aRow)
     249             : {
     250           0 :   if (aRow) {
     251           0 :     Accessible* table = aRow->Parent();
     252           0 :     if (table) {
     253           0 :       roles::Role tableRole = table->Role();
     254           0 :       if (tableRole == roles::GROUPING) { // if there's a rowgroup.
     255           0 :         table = table->Parent();
     256           0 :         if (table)
     257           0 :           tableRole = table->Role();
     258             :       }
     259             : 
     260           0 :       return (tableRole == roles::TABLE || tableRole == roles::TREE_TABLE ||
     261           0 :               tableRole == roles::MATHML_TABLE) ? table : nullptr;
     262             :     }
     263             :   }
     264             : 
     265           0 :   return nullptr;
     266             : }
     267             : 
     268             : HyperTextAccessible*
     269           0 : nsAccUtils::GetTextContainer(nsINode* aNode)
     270             : {
     271             :   // Get text accessible containing the result node.
     272             :   DocAccessible* doc =
     273           0 :     GetAccService()->GetDocAccessible(aNode->OwnerDoc());
     274             :   Accessible* accessible =
     275           0 :     doc ? doc->GetAccessibleOrContainer(aNode) : nullptr;
     276           0 :   if (!accessible)
     277           0 :     return nullptr;
     278             : 
     279           0 :   do {
     280           0 :     HyperTextAccessible* textAcc = accessible->AsHyperText();
     281           0 :     if (textAcc)
     282           0 :       return textAcc;
     283             : 
     284           0 :     accessible = accessible->Parent();
     285           0 :   } while (accessible);
     286             : 
     287           0 :   return nullptr;
     288             : }
     289             : 
     290             : nsIntPoint
     291           0 : nsAccUtils::ConvertToScreenCoords(int32_t aX, int32_t aY,
     292             :                                   uint32_t aCoordinateType,
     293             :                                   Accessible* aAccessible)
     294             : {
     295           0 :   nsIntPoint coords(aX, aY);
     296             : 
     297           0 :   switch (aCoordinateType) {
     298             :     case nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE:
     299           0 :       break;
     300             : 
     301             :     case nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE:
     302             :     {
     303           0 :       coords += nsCoreUtils::GetScreenCoordsForWindow(aAccessible->GetNode());
     304           0 :       break;
     305             :     }
     306             : 
     307             :     case nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE:
     308             :     {
     309           0 :       coords += GetScreenCoordsForParent(aAccessible);
     310           0 :       break;
     311             :     }
     312             : 
     313             :     default:
     314           0 :       NS_NOTREACHED("invalid coord type!");
     315             :   }
     316             : 
     317           0 :   return coords;
     318             : }
     319             : 
     320             : void
     321           0 : nsAccUtils::ConvertScreenCoordsTo(int32_t *aX, int32_t *aY,
     322             :                                   uint32_t aCoordinateType,
     323             :                                   Accessible* aAccessible)
     324             : {
     325           0 :   switch (aCoordinateType) {
     326             :     case nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE:
     327           0 :       break;
     328             : 
     329             :     case nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE:
     330             :     {
     331           0 :       nsIntPoint coords = nsCoreUtils::GetScreenCoordsForWindow(aAccessible->GetNode());
     332           0 :       *aX -= coords.x;
     333           0 :       *aY -= coords.y;
     334           0 :       break;
     335             :     }
     336             : 
     337             :     case nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE:
     338             :     {
     339           0 :       nsIntPoint coords = GetScreenCoordsForParent(aAccessible);
     340           0 :       *aX -= coords.x;
     341           0 :       *aY -= coords.y;
     342           0 :       break;
     343             :     }
     344             : 
     345             :     default:
     346           0 :     NS_NOTREACHED("invalid coord type!");
     347             :   }
     348           0 : }
     349             : 
     350             : nsIntPoint
     351           0 : nsAccUtils::GetScreenCoordsForParent(Accessible* aAccessible)
     352             : {
     353           0 :   Accessible* parent = aAccessible->Parent();
     354           0 :   if (!parent)
     355           0 :     return nsIntPoint(0, 0);
     356             : 
     357           0 :   nsIFrame *parentFrame = parent->GetFrame();
     358           0 :   if (!parentFrame)
     359           0 :     return nsIntPoint(0, 0);
     360             : 
     361           0 :   nsRect rect = parentFrame->GetScreenRectInAppUnits();
     362           0 :   return nsPoint(rect.x, rect.y).
     363           0 :     ToNearestPixels(parentFrame->PresContext()->AppUnitsPerDevPixel());
     364             : }
     365             : 
     366             : bool
     367           0 : nsAccUtils::GetLiveAttrValue(uint32_t aRule, nsAString& aValue)
     368             : {
     369           0 :   switch (aRule) {
     370             :     case eOffLiveAttr:
     371           0 :       aValue = NS_LITERAL_STRING("off");
     372           0 :       return true;
     373             :     case ePoliteLiveAttr:
     374           0 :       aValue = NS_LITERAL_STRING("polite");
     375           0 :       return true;
     376             :   }
     377             : 
     378           0 :   return false;
     379             : }
     380             : 
     381             : #ifdef DEBUG
     382             : 
     383             : bool
     384           0 : nsAccUtils::IsTextInterfaceSupportCorrect(Accessible* aAccessible)
     385             : {
     386             :   // Don't test for accessible docs, it makes us create accessibles too
     387             :   // early and fire mutation events before we need to
     388           0 :   if (aAccessible->IsDoc())
     389           0 :     return true;
     390             : 
     391           0 :   bool foundText = false;
     392           0 :   uint32_t childCount = aAccessible->ChildCount();
     393           0 :   for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
     394           0 :     Accessible* child = aAccessible->GetChildAt(childIdx);
     395           0 :     if (child->IsText()) {
     396           0 :       foundText = true;
     397           0 :       break;
     398             :     }
     399             :   }
     400             : 
     401           0 :   return !foundText || aAccessible->IsHyperText();
     402             : }
     403             : #endif
     404             : 
     405             : uint32_t
     406           0 : nsAccUtils::TextLength(Accessible* aAccessible)
     407             : {
     408           0 :   if (!aAccessible->IsText()) {
     409           0 :     return 1;
     410             :   }
     411             : 
     412           0 :   TextLeafAccessible* textLeaf = aAccessible->AsTextLeaf();
     413           0 :   if (textLeaf)
     414           0 :     return textLeaf->Text().Length();
     415             : 
     416             :   // For list bullets (or anything other accessible which would compute its own
     417             :   // text. They don't have their own frame.
     418             :   // XXX In the future, list bullets may have frame and anon content, so
     419             :   // we should be able to remove this at that point
     420           0 :   nsAutoString text;
     421           0 :   aAccessible->AppendTextTo(text); // Get all the text
     422           0 :   return text.Length();
     423             : }
     424             : 
     425             : bool
     426           0 : nsAccUtils::MustPrune(Accessible* aAccessible)
     427             : {
     428           0 :   roles::Role role = aAccessible->Role();
     429             : 
     430             :   // Don't prune the tree for certain roles if the tree is more complex than
     431             :   // a single text leaf.
     432             :   return
     433           0 :     (role == roles::MENUITEM ||
     434           0 :      role == roles::COMBOBOX_OPTION ||
     435           0 :      role == roles::OPTION ||
     436           0 :      role == roles::ENTRY ||
     437           0 :      role == roles::FLAT_EQUATION ||
     438           0 :      role == roles::PASSWORD_TEXT ||
     439           0 :      role == roles::PUSHBUTTON ||
     440           0 :      role == roles::TOGGLE_BUTTON ||
     441           0 :      role == roles::GRAPHIC ||
     442           0 :      role == roles::SLIDER ||
     443           0 :      role == roles::PROGRESSBAR ||
     444           0 :      role == roles::SEPARATOR) &&
     445           0 :     aAccessible->ContentChildCount() == 1 &&
     446           0 :     aAccessible->ContentChildAt(0)->IsTextLeaf();
     447             : }

Generated by: LCOV version 1.13