Skip to content

Commit f7b9bd7

Browse files
committed
fix(webAccess): restore iframe URL matching on NVDA >= 2024.3 via NVDAObject fallback
NVDA 2024.3 (commit 9afb6fc5b) changed Gecko IA2 iframe object resolution, so NVDAObjectAtStart can be None for some iframe-related nodes and URL-based zone matching may fail. Add a safe fallback in NodeField.getNVDAObject() using controlIdentifier + getNVDAObjectFromEvent, and harden NodeField.url against missing objects to keep submodule loading behavior retrocompatible.
1 parent baaa9d0 commit f7b9bd7

1 file changed

Lines changed: 40 additions & 6 deletions

File tree

addon/globalPlugins/webAccess/nodeHandler.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@
3939
import controlTypes
4040
from logHandler import log
4141
import mouseHandler
42-
from NVDAHelper.localLib import VBuf_getTextInRange
42+
import NVDAObjects.IAccessible
43+
import NVDAHelper
44+
45+
# NVDA <= 2025.x: source/NVDAHelper.py exposes VBuf_getTextInRange directly.
46+
# NVDA >= 2026.1 (commit 9cc7ed6a6): NVDAHelper is a package and localLib contains declarations.
47+
if hasattr(NVDAHelper, "VBuf_getTextInRange"):
48+
VBuf_getTextInRange = NVDAHelper.VBuf_getTextInRange
49+
elif hasattr(NVDAHelper, "localLib") and hasattr(NVDAHelper.localLib, "VBuf_getTextInRange"):
50+
VBuf_getTextInRange = NVDAHelper.localLib.VBuf_getTextInRange
51+
else:
52+
from NVDAHelper.localLib import VBuf_getTextInRange
4353
import textInfos
4454
import treeInterceptorHandler
4555
import ui
@@ -521,13 +531,16 @@ def url(self):
521531
return None
522532
url = None
523533
obj = self.getNVDAObject()
524-
while obj.role != self.role:
534+
while obj is not None and obj.role != self.role:
525535
try:
526536
obj = obj.parent
527537
except Exception:
528-
break
529-
else:
530-
url = obj.IAccessibleObject.accValue(obj.IAccessibleChildID)
538+
obj = None
539+
if obj is not None:
540+
try:
541+
url = obj.IAccessibleObject.accValue(obj.IAccessibleChildID)
542+
except Exception:
543+
url = None
531544
self._url = url
532545
return url
533546

@@ -888,7 +901,28 @@ def sayAll(self):
888901
def getNVDAObject(self):
889902
if not self.isReady():
890903
return None
891-
return self.getTextInfo().NVDAObjectAtStart
904+
info = self.getTextInfo()
905+
if info is None:
906+
return None
907+
obj = info.NVDAObjectAtStart
908+
if obj is not None:
909+
return obj
910+
try:
911+
docHandle, objId = self.controlIdentifier
912+
except Exception:
913+
return None
914+
if not docHandle or not objId:
915+
return None
916+
try:
917+
# NVDA commit 9afb6fc5b (introduced in 2024.3) changed Gecko IA2 object
918+
# resolution for iframes, and NVDAObjectAtStart can be None in some cases.
919+
# Legacy pre-2024.3 fallback path: event-based resolution.
920+
# This keeps URL-based matching retrocompatible for iframe-driven submodules.
921+
return NVDAObjects.IAccessible.getNVDAObjectFromEvent(
922+
docHandle, winUser.OBJID_CLIENT, objId
923+
)
924+
except Exception:
925+
return None
892926

893927
def mouseMove(self):
894928
if not self.checkNodeManager():

0 commit comments

Comments
 (0)