1 from comtypes import COMError
2 import eventHandler
3 from . import VirtualBuffer, VirtualBufferTextInfo, VBufStorage_findMatch_word
4 import controlTypes
5 import NVDAObjects.IAccessible.MSHTML
6 import winUser
7 import NVDAHelper
8 import ctypes
9 import IAccessibleHandler
10 import languageHandler
11 import oleacc
12 from logHandler import log
13 import textInfos
14 import api
15 import aria
16 import config
17 import watchdog
18
19 -class MSHTMLTextInfo(VirtualBufferTextInfo):
20
26
28 level=None
29 accRole=attrs.get('IAccessible::role',0)
30 accRole=int(accRole) if isinstance(accRole,basestring) and accRole.isdigit() else accRole
31 nodeName=attrs.get('IHTMLDOMNode::nodeName',"")
32 ariaRoles=attrs.get("HTMLAttrib::role", "").split(" ")
33
34
35 role=next((aria.ariaRolesToNVDARoles[ar] for ar in ariaRoles if ar in aria.ariaRolesToNVDARoles),controlTypes.ROLE_UNKNOWN)
36 if not role and nodeName:
37 role=NVDAObjects.IAccessible.MSHTML.nodeNamesToNVDARoles.get(nodeName,controlTypes.ROLE_UNKNOWN)
38 if not role:
39 role=IAccessibleHandler.IAccessibleRolesToNVDARoles.get(accRole,controlTypes.ROLE_UNKNOWN)
40 states=set(IAccessibleHandler.IAccessibleStatesToNVDAStates[x] for x in [1<<y for y in xrange(32)] if int(attrs.get('IAccessible::state_%s'%x,0)) and x in IAccessibleHandler.IAccessibleStatesToNVDAStates)
41
42 if nodeName=="A" and role==controlTypes.ROLE_LINK and controlTypes.STATE_LINKED not in states:
43 role=controlTypes.ROLE_TEXTFRAME
44 if 'IHTMLElement::isContentEditable' in attrs:
45 states.add(controlTypes.STATE_EDITABLE)
46 if 'HTMLAttrib::onclick' in attrs or 'HTMLAttrib::onmousedown' in attrs or 'HTMLAttrib::onmouseup' in attrs:
47 states.add(controlTypes.STATE_CLICKABLE)
48 if attrs.get('HTMLAttrib::aria-required','false')=='true':
49 states.add(controlTypes.STATE_REQUIRED)
50 name=None
51 ariaLabelledBy=attrs.get('HTMLAttrib::aria-labelledBy')
52 if ariaLabelledBy:
53 try:
54 labelNode=self.obj.rootNVDAObject.HTMLNode.document.getElementById(ariaLabelledBy)
55 except (COMError,NameError):
56 labelNode=None
57 if labelNode:
58 try:
59 name=self.obj.makeTextInfo(NVDAObjects.IAccessible.MSHTML.MSHTML(HTMLNode=labelNode)).text
60 except:
61 pass
62 description=None
63 ariaDescribedBy=attrs.get('HTMLAttrib::aria-describedBy')
64 if ariaDescribedBy:
65 try:
66 descNode=self.obj.rootNVDAObject.HTMLNode.document.getElementById(ariaDescribedBy)
67 except (COMError,NameError):
68 descNode=None
69 if descNode:
70 try:
71 description=self.obj.makeTextInfo(NVDAObjects.IAccessible.MSHTML.MSHTML(HTMLNode=descNode)).text
72 except:
73 pass
74 ariaSort=attrs.get('HTMLAttrib::aria-sort')
75 state=aria.ariaSortValuesToNVDAStates.get(ariaSort)
76 if state is not None:
77 states.add(state)
78 ariaSelected=attrs.get('HTMLAttrib::aria-selected')
79 if ariaSelected=="true":
80 states.add(controlTypes.STATE_SELECTED)
81 elif ariaSelected=="false":
82 states.discard(controlTypes.STATE_SELECTED)
83 ariaExpanded=attrs.get('HTMLAttrib::aria-expanded')
84 if ariaExpanded=="true":
85 states.add(controlTypes.STATE_EXPANDED)
86 elif ariaExpanded=="false":
87 states.add(controlTypes.STATE_COLLAPSED)
88 if attrs.get('HTMLAttrib::aria-invalid','false')=='true':
89 states.add(controlTypes.STATE_INVALID)
90 if attrs.get('HTMLAttrib::aria-multiline','false')=='true':
91 states.add(controlTypes.STATE_MULTILINE)
92 if attrs.get('HTMLAttrib::aria-dropeffect','none')!='none':
93 states.add(controlTypes.STATE_DROPTARGET)
94 ariaGrabbed=attrs.get('HTMLAttrib::aria-grabbed',None)
95 if ariaGrabbed=='false':
96 states.add(controlTypes.STATE_DRAGGABLE)
97 elif ariaGrabbed=='true':
98 states.add(controlTypes.STATE_DRAGGING)
99 if nodeName=="TEXTAREA":
100 states.add(controlTypes.STATE_MULTILINE)
101 if "H1"<=nodeName<="H6":
102 level=nodeName[1:]
103 if nodeName in ("UL","OL","DL"):
104 states.add(controlTypes.STATE_READONLY)
105 if role==controlTypes.ROLE_UNKNOWN:
106 role=controlTypes.ROLE_TEXTFRAME
107 if role==controlTypes.ROLE_GRAPHIC:
108
109
110 states.discard(controlTypes.STATE_UNAVAILABLE)
111
112 landmark=next((ar for ar in ariaRoles if ar in aria.landmarkRoles),None)
113 ariaLevel=attrs.get('HTMLAttrib::aria-level',None)
114 ariaLevel=int(ariaLevel) if ariaLevel is not None else None
115 if ariaLevel:
116 level=ariaLevel
117 if role:
118 attrs['role']=role
119 attrs['states']=states
120 if level:
121 attrs["level"] = level
122 if landmark:
123 attrs["landmark"]=landmark
124 if name:
125 attrs["name"]=name
126 if description:
127 attrs["description"]=description
128 return super(MSHTMLTextInfo,self)._normalizeControlField(attrs)
129
131
132 TextInfo=MSHTMLTextInfo
133
136
138 initialPos = super(MSHTML,self)._getInitialCaretPos()
139 if initialPos:
140 return initialPos
141 try:
142 url=getattr(self.rootNVDAObject.HTMLNode.document,'url',"").split('#')
143 except COMError as e:
144 log.debugWarning("Error getting URL from document: %s" % e)
145 return None
146 if not url or len(url)!=2:
147 return None
148 anchorName=url[-1]
149 if not anchorName:
150 return None
151 return self._getNVDAObjectByAnchorName(anchorName)
152
181
183 if self.isLoading:
184 return True
185 root=self.rootNVDAObject
186 if not root:
187 return False
188 try:
189 if not root.IAccessibleRole:
190
191 return False
192 except watchdog.CallCancelled:
193
194
195 return False
196 states=root.states
197 if not winUser.isWindow(root.windowHandle) or controlTypes.STATE_EDITABLE in states:
198 return False
199 return True
200
206
208 if not isinstance(obj,NVDAObjects.IAccessible.MSHTML.MSHTML):
209 raise LookupError
210 docHandle=obj.windowHandle
211 ID=obj.HTMLNodeUniqueNumber
212 return docHandle,ID
213
215 if nodeType=="link":
216 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LINK],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_LINKED:[1]}
217 elif nodeType=="visitedLink":
218 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LINK],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_TRAVERSED:[1]}
219 elif nodeType=="unvisitedLink":
220 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LINK],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_LINKED:[1],"IAccessible::state_%d"%oleacc.STATE_SYSTEM_TRAVERSED:[None]}
221 elif nodeType=="formField":
222 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON,oleacc.ROLE_SYSTEM_RADIOBUTTON,oleacc.ROLE_SYSTEM_CHECKBUTTON,oleacc.ROLE_SYSTEM_COMBOBOX,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_OUTLINE,oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
223 elif nodeType=="button":
224 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
225 elif nodeType=="edit":
226 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
227 elif nodeType=="radioButton":
228 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_RADIOBUTTON],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
229 elif nodeType=="comboBox":
230 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_COMBOBOX],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
231 elif nodeType=="checkBox":
232 attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_CHECKBUTTON],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
233 elif nodeType=="table":
234 attrs={"IHTMLDOMNode::nodeName":["TABLE"]}
235 if not config.conf["documentFormatting"]["includeLayoutTables"]:
236 attrs["table-layout"]=[None]
237 elif nodeType.startswith("heading") and nodeType[7:].isdigit():
238 attrs = {"IHTMLDOMNode::nodeName": ["H%s" % nodeType[7:]]}
239 elif nodeType == "heading":
240 attrs = {"IHTMLDOMNode::nodeName": ["H1", "H2", "H3", "H4", "H5", "H6"]}
241 elif nodeType == "list":
242 attrs = {"IHTMLDOMNode::nodeName": ["UL","OL","DL"]}
243 elif nodeType == "listItem":
244 attrs = {"IHTMLDOMNode::nodeName": ["LI","DD","DT"]}
245 elif nodeType == "blockQuote":
246 attrs = {"IHTMLDOMNode::nodeName": ["BLOCKQUOTE"]}
247 elif nodeType == "graphic":
248 attrs = {"IHTMLDOMNode::nodeName": ["IMG"]}
249 elif nodeType == "frame":
250 attrs = {"IHTMLDOMNode::nodeName": ["FRAME","IFRAME"]}
251 elif nodeType=="focusable":
252 attrs={"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
253 elif nodeType=="landmark":
254 attrs={"HTMLAttrib::role":[VBufStorage_findMatch_word(lr) for lr in aria.landmarkRoles]}
255 elif nodeType == "embeddedObject":
256 attrs = {"IHTMLDOMNode::nodeName": ["OBJECT","EMBED","APPLET"]}
257 else:
258 return None
259 return attrs
260
272
274 if not HTMLDocument:
275 HTMLDocument=self.rootNVDAObject.HTMLNode.document
276 HTMLNode=HTMLDocument.getElementById(name)
277 if not HTMLNode:
278 log.debugWarning("GetElementById can't find node with ID %s"%name)
279 return None
280 obj=NVDAObjects.IAccessible.MSHTML.MSHTML(HTMLNode=HTMLNode)
281 return obj
282
284 try:
285 return self.rootNVDAObject.HTMLNode.document.url
286 except COMError:
287 return None
288
290 try:
291 if not reason and not self.passThrough and obj.HTMLNodeName == "INPUT" and obj.HTMLNode.type == "file":
292
293
294
295 return False
296 except COMError:
297 pass
298 return super(MSHTML, self).shouldPassThrough(obj, reason)
299