def _calculateDescriptionFrom(self, attrs: textInfos.ControlField) -> controlTypes.DescriptionFrom: """Overridable calculation of DescriptionFrom Match behaviour of NVDAObjects.IAccessible.mozilla.Mozilla._get_descriptionFrom @param attrs: source attributes for the TextInfo @return: the origin for accDescription. @remarks: Firefox does not yet have a 'IAccessible2::attribute_description-from' (IA2 attribute "description-from"). We can infer that the origin of accDescription is 'aria-description' because Firefox will include a 'IAccessible2::attribute_description' (IA2 attribute "description") when the aria-description HTML attribute is used. If 'IAccessible2::attribute_description' matches the accDescription value, we can infer that aria-description was the original source. """ IA2Attr_desc = attrs.get("IAccessible2::attribute_description") accDesc = attrs.get("description") if not IA2Attr_desc or accDesc != IA2Attr_desc: return controlTypes.DescriptionFrom.UNKNOWN else: return controlTypes.DescriptionFrom.ARIA_DESCRIPTION
def _getNormalizedCurrentAttrs( attrs: textInfos.ControlField) -> typing.Dict[str, typing.Any]: valForCurrent = attrs.get("IAccessible2::attribute_current", "false") try: isCurrent = controlTypes.IsCurrent(valForCurrent) except ValueError: log.debugWarning(f"Unknown isCurrent value: {valForCurrent}") isCurrent = controlTypes.IsCurrent.NO if isCurrent != controlTypes.IsCurrent.NO: return {'current': isCurrent} return {}
def _normalizeControlField(self, attrs: textInfos.ControlField): # noqa: C901 level = None isCurrent = self._getIsCurrentAttribute(attrs) if isCurrent != controlTypes.IsCurrent.NO: attrs['current'] = isCurrent placeholder = self._getPlaceholderAttribute( attrs, 'HTMLAttrib::aria-placeholder') if placeholder: attrs['placeholder'] = placeholder nodeName = attrs.get('IHTMLDOMNode::nodeName', "") roleAttrib = attrs.get("HTMLAttrib::role", "") ariaRoles = [ar for ar in roleAttrib.split(" ") if ar] #choose role #Priority is aria role -> HTML tag name -> IAccessible role role = next((aria.ariaRolesToNVDARoles[ar] for ar in ariaRoles if ar in aria.ariaRolesToNVDARoles), controlTypes.Role.UNKNOWN) if role == controlTypes.Role.UNKNOWN and nodeName: role = NVDAObjects.IAccessible.MSHTML.nodeNamesToNVDARoles.get( nodeName, controlTypes.Role.UNKNOWN) if role == controlTypes.Role.UNKNOWN: role = IAccessibleHandler.NVDARoleFromAttr( attrs.get('IAccessible::role')) roleText = attrs.get('HTMLAttrib::aria-roledescription') if roleText: attrs['roleText'] = roleText states = IAccessibleHandler.getStatesSetFromIAccessibleAttrs(attrs) role, states = controlTypes.transformRoleStates(role, states) if attrs.get('HTMLAttrib::longdesc'): states.add(controlTypes.State.HASLONGDESC) #IE exposes destination anchors as links, this is wrong if nodeName == "A" and role == controlTypes.Role.LINK and controlTypes.State.LINKED not in states: role = controlTypes.Role.TEXTFRAME if 'IHTMLElement::isContentEditable' in attrs: states.add(controlTypes.State.EDITABLE) if 'HTMLAttrib::onclick' in attrs or 'HTMLAttrib::onmousedown' in attrs or 'HTMLAttrib::onmouseup' in attrs: states.add(controlTypes.State.CLICKABLE) if 'HTMLAttrib::required' in attrs or attrs.get( 'HTMLAttrib::aria-required', 'false') == 'true': states.add(controlTypes.State.REQUIRED) description = None ariaDescribedBy = attrs.get('HTMLAttrib::aria-describedby') if ariaDescribedBy: ariaDescribedByIds = ariaDescribedBy.split() description = "" for ariaDescribedById in ariaDescribedByIds: descNode = None try: descNode = self.obj.rootNVDAObject.HTMLNode.document.getElementById( ariaDescribedById) except (COMError, NameError): descNode = None if not descNode: try: descNode = NVDAObjects.IAccessible.MSHTML.locateHTMLElementByID( self.obj.rootNVDAObject.HTMLNode.document, ariaDescribedById) except (COMError, NameError): descNode = None if descNode: try: description = description + " " + self.obj.makeTextInfo( NVDAObjects.IAccessible.MSHTML.MSHTML( HTMLNode=descNode)).text except: pass ariaSort = attrs.get('HTMLAttrib::aria-sort') state = aria.ariaSortValuesToNVDAStates.get(ariaSort) if state is not None: states.add(state) ariaSelected = attrs.get('HTMLAttrib::aria-selected') if ariaSelected == "true": states.add(controlTypes.State.SELECTED) elif ariaSelected == "false": states.discard(controlTypes.State.SELECTED) ariaExpanded = attrs.get('HTMLAttrib::aria-expanded') if ariaExpanded == "true": states.add(controlTypes.State.EXPANDED) elif ariaExpanded == "false": states.add(controlTypes.State.COLLAPSED) if attrs.get('HTMLAttrib::aria-invalid', 'false') == 'true': states.add(controlTypes.State.INVALID_ENTRY) if attrs.get('HTMLAttrib::aria-multiline', 'false') == 'true': states.add(controlTypes.State.MULTILINE) if attrs.get('HTMLAttrib::aria-dropeffect', 'none') != 'none': states.add(controlTypes.State.DROPTARGET) ariaGrabbed = attrs.get('HTMLAttrib::aria-grabbed', None) if ariaGrabbed == 'false': states.add(controlTypes.State.DRAGGABLE) elif ariaGrabbed == 'true': states.add(controlTypes.State.DRAGGING) if nodeName == "TEXTAREA": states.add(controlTypes.State.MULTILINE) if "H1" <= nodeName <= "H6": level = nodeName[1:] if nodeName in ("UL", "OL", "DL"): states.add(controlTypes.State.READONLY) if role == controlTypes.Role.UNKNOWN: role = controlTypes.Role.TEXTFRAME if role == controlTypes.Role.GRAPHIC: # MSHTML puts the unavailable state on all graphics when the showing of graphics is disabled. # This is rather annoying and irrelevant to our users, so discard it. states.discard(controlTypes.State.UNAVAILABLE) lRole = aria.htmlNodeNameToAriaRoles.get(nodeName.lower()) if lRole: ariaRoles.append(lRole) # If the first role is a landmark role, use it. landmark = ariaRoles[ 0] if ariaRoles and ariaRoles[0] in aria.landmarkRoles else None ariaLevel = attrs.get('HTMLAttrib::aria-level', None) ariaLevel = int(ariaLevel) if ariaLevel is not None else None if ariaLevel: level = ariaLevel if role: attrs['role'] = role attrs['states'] = states if level: attrs["level"] = level if landmark: attrs["landmark"] = landmark if description: attrs["description"] = description return super(MSHTMLTextInfo, self)._normalizeControlField(attrs)