Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge rc to beta #14452

Merged
merged 4 commits into from
Dec 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions source/NVDAHelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@
import api
import globalVars
from logHandler import log
from utils.security import isWindowsLocked
import NVDAState

from utils.security import _isLockScreenModeActive

versionedLibPath = os.path.join(globalVars.appDir, 'lib')
if os.environ.get('PROCESSOR_ARCHITEW6432') == 'ARM64':
Expand Down Expand Up @@ -458,7 +457,7 @@ def nvdaControllerInternal_installAddonPackageFromPath(addonPath):
if globalVars.appArgs.secure:
log.debugWarning("Unable to install add-on into secure copy of NVDA.")
return
if isWindowsLocked():
if _isLockScreenModeActive():
log.debugWarning("Unable to install add-on while Windows is locked.")
return
import wx
Expand All @@ -473,7 +472,7 @@ def nvdaControllerInternal_openConfigDirectory():
if globalVars.appArgs.secure:
log.debugWarning("Unable to open user config directory for secure copy of NVDA.")
return
if isWindowsLocked():
if _isLockScreenModeActive():
log.debugWarning("Unable to open user config directory while Windows is locked.")
return
import systemUtils
Expand Down
13 changes: 11 additions & 2 deletions source/NVDAObjects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@
TreeInterceptor,
)
import braille
from utils.security import _isObjectBelowLockScreen
import vision
import globalPluginHandler
import brailleInput
import locationHelper
import aria
from winAPI.sessionTracking import isWindowsLocked
from winAPI.sessionTracking import _isLockScreenModeActive


class NVDAObjectTextInfo(textInfos.offsets.OffsetsTextInfo):
Expand Down Expand Up @@ -181,7 +182,7 @@ def _insertLockScreenObject(self, clsList: typing.List["NVDAObject"]) -> None:
Inserts LockScreenObject to the start of the clsList if Windows is locked.
"""
from .lockscreen import LockScreenObject
if isWindowsLocked():
if _isLockScreenModeActive():
# This must be resolved first to prevent object navigation outside of the lockscreen.
clsList.insert(0, LockScreenObject)

Expand Down Expand Up @@ -1437,3 +1438,11 @@ def getSelectedItemsCount(self,maxCount=2):
For performance, this method will only count up to the given maxCount number, and if there is one more above that, then sys.maxint is returned stating that many items are selected.
"""
return 0

#: Type definition for auto prop '_get_isBelowLockScreen'
isBelowLockScreen: bool

def _get_isBelowLockScreen(self) -> bool:
if not _isLockScreenModeActive():
return False
return _isObjectBelowLockScreen(self)
19 changes: 17 additions & 2 deletions source/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,23 @@ def setReviewPosition(
@param isCaret: Whether the review position is changed due to caret following.
@param isMouse: Whether the review position is changed due to mouse following.
"""
if objectBelowLockScreenAndWindowsIsLocked(reviewPosition.obj):
return False
reviewObj = reviewPosition.obj

if isinstance(reviewObj, treeInterceptorHandler.DocumentTreeInterceptor):
# reviewPosition.obj can be a number of classes, e.g.
# CursorManager, DocumentWithTableNavigation, EditableText.
# We can only handle the NVDAObject case.
reviewObj = reviewObj.rootNVDAObject

if isinstance(reviewObj, NVDAObjects.NVDAObject):
# reviewPosition.obj can be a number of classes, e.g.
# CursorManager, DocumentWithTableNavigation, EditableText.
# We can only handle the NVDAObject case.
if objectBelowLockScreenAndWindowsIsLocked(reviewObj):
return False
else:
log.debug(f"Unhandled reviewObj type {type(reviewObj)} when checking security of reviewObj")

globalVars.reviewPosition=reviewPosition.copy()
globalVars.reviewPositionObj=reviewPosition.obj
if clearNavigatorObject: globalVars.navigatorObject=None
Expand Down
10 changes: 5 additions & 5 deletions source/appModules/lockapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
from NVDAObjects.UIA import UIA
import NVDAState
from utils.security import getSafeScripts
from winAPI.sessionTracking import isWindowsLocked
from winAPI.sessionTracking import _isLockScreenModeActive

"""App module for the Windows 10 and 11 lock screen.

The lock screen allows other windows to be opened, so security related functions
are done at a higher level than the lockapp app module.
Refer to usages of `winAPI.sessionTracking.isWindowsLocked`.
Refer to usages of `winAPI.sessionTracking._isLockScreenModeActive`.
"""


Expand Down Expand Up @@ -60,11 +60,11 @@ def chooseNVDAObjectOverlayClasses(
if isinstance(obj,UIA) and obj.role==controlTypes.Role.PANE and obj.UIAElement.cachedClassName=="LockAppContainer":
clsList.insert(0,LockAppContainer)

if not isWindowsLocked():
if not _isLockScreenModeActive():
log.debugWarning(
"LockApp is being initialized but NVDA does not expect Windows to be locked. "
"DynamicNVDAObjectType may have failed to apply LockScreenObject. "
"This means Windows session tracking has failed or NVDA is yet to receive lock event. "
"This means session lock state tracking has failed. "
)
clsList.insert(0, LockScreenObject)

Expand All @@ -83,7 +83,7 @@ def _inputCaptor(self, gesture: inputCore.InputGesture) -> bool:
if not scriptShouldRun:
log.error(
"scriptHandler failed to block script when Windows is locked. "
"This means Windows session tracking has failed. "
"This means session lock state tracking has failed. "
)
return scriptShouldRun

Expand Down
30 changes: 26 additions & 4 deletions source/baseObject.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2007-2020 NV Access Limited, Christopher Toth, Babbage B.V., Julien Cochuyt
# Copyright (C) 2007-2022 NV Access Limited, Christopher Toth, Babbage B.V., Julien Cochuyt
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

"""Contains the base classes that many of NVDA's classes such as NVDAObjects, virtualBuffers, appModules, synthDrivers inherit from. These base classes provide such things as auto properties, and methods and properties for scripting and key binding.
"""

from typing import (
Any,
Callable,
Optional,
Set,
Union,
)
import weakref
import garbageHandler
from logHandler import log
from abc import ABCMeta, abstractproperty

GetterReturnT = Any
GetterMethodT = Callable[["AutoPropertyObject"], GetterReturnT]


class Getter(object):

def __init__(self,fget, abstract=False):
self.fget=fget
if abstract:
self._abstract = self.__isabstractmethod__ = abstract

def __get__(self,instance,owner):
def __get__(
self,
instance: Union[Any, None, "AutoPropertyObject"],
owner,
) -> Union[GetterReturnT, "Getter"]:
if isinstance(self.fget, classmethod):
return self.fget.__get__(instance, owner)()
elif instance is None:
Expand All @@ -31,16 +46,22 @@ def setter(self,func):
def deleter(self,func):
return (abstractproperty if self._abstract else property)(fget=self.fget,fdel=func)


class CachingGetter(Getter):

def __get__(self, instance, owner):
def __get__(
self,
instance: Union[Any, None, "AutoPropertyObject"],
owner,
) -> Union[GetterReturnT, "CachingGetter"]:
if isinstance(self.fget, classmethod):
log.warning("Class properties do not support caching")
return self.fget.__get__(instance, owner)()
elif instance is None:
return self
return instance._getPropertyViaCache(self.fget)


class AutoPropertyType(ABCMeta):

def __init__(self,name,bases,dict):
Expand Down Expand Up @@ -125,6 +146,7 @@ class AutoPropertyObject(garbageHandler.TrackedObject, metaclass=AutoPropertyTyp
#: @type: bool
cachePropertiesByDefault = False

_propertyCache: Set[GetterMethodT]

def __new__(cls, *args, **kwargs):
self = super(AutoPropertyObject, cls).__new__(cls)
Expand All @@ -134,7 +156,7 @@ def __new__(cls, *args, **kwargs):
self.__instances[self]=None
return self

def _getPropertyViaCache(self,getterMethod=None):
def _getPropertyViaCache(self, getterMethod: Optional[GetterMethodT] = None) -> GetterReturnT:
if not getterMethod:
raise ValueError("getterMethod is None")
missing=False
Expand Down
8 changes: 4 additions & 4 deletions source/brailleViewer/brailleViewerGui.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import fonts
import inputCore
import gui.contextHelp
from utils.security import isWindowsLocked, postSessionLockStateChanged
from utils.security import _isLockScreenModeActive, postSessionLockStateChanged

BRAILLE_UNICODE_PATTERNS_START = 0x2800
BRAILLE_SPACE_CHARACTER = chr(BRAILLE_UNICODE_PATTERNS_START)
Expand Down Expand Up @@ -398,7 +398,7 @@ def _createControls(self, sizer: wx.Sizer, parent: wx.Control) -> None:
self._shouldShowOnStartupCheckBox.SetValue(config.conf["brailleViewer"]["showBrailleViewerAtStartup"])
self._shouldShowOnStartupCheckBox.Bind(wx.EVT_CHECKBOX, self._onShouldShowOnStartupChanged)
optionsSizer.Add(self._shouldShowOnStartupCheckBox)
if isWindowsLocked():
if _isLockScreenModeActive():
self._shouldShowOnStartupCheckBox.Disable()

# Translators: The label for a setting in the braille viewer that controls
Expand All @@ -415,11 +415,11 @@ def _createControls(self, sizer: wx.Sizer, parent: wx.Control) -> None:
sizer.Add(optionsSizer, flag=wx.EXPAND | wx.TOP, border=5)

def _onShouldShowOnStartupChanged(self, evt: wx.CommandEvent):
if not isWindowsLocked():
if not _isLockScreenModeActive():
config.conf["brailleViewer"]["showBrailleViewerAtStartup"] = self._shouldShowOnStartupCheckBox.IsChecked()

def _onShouldHoverRouteToCellCheckBoxChanged(self, evt: wx.CommandEvent):
if not isWindowsLocked():
if not _isLockScreenModeActive():
config.conf["brailleViewer"]["shouldHoverRouteToCell"] = self._shouldHoverRouteToCellCheckBox.IsChecked()
self._updateMouseOverBinding(self._shouldHoverRouteToCellCheckBox.IsChecked())

Expand Down
10 changes: 7 additions & 3 deletions source/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,13 +454,13 @@ class _TrackNVDAInitialization:
regardless of lock state.
Security checks may cause the desktop object to not be set if NVDA starts on the lock screen.
As such, during initialization, NVDA should behave as if Windows is unlocked,
i.e. winAPI.sessionTracking.isWindowsLocked should return False.
i.e. winAPI.sessionTracking._isLockScreenModeActive should return False.

TODO: move to NVDAState module
"""

_isNVDAInitialized = False
"""When False, isWindowsLocked is forced to return False.
"""When False, _isLockScreenModeActive is forced to return False.
"""

@staticmethod
Expand Down Expand Up @@ -729,7 +729,8 @@ def run(self):
mouseHandler.pumpAll()
braille.pumpAll()
vision.pumpAll()
except:
sessionTracking.pumpAll()
except Exception:
log.exception("errors in this core pump cycle")
baseObject.AutoPropertyObject.invalidateCaches()
watchdog.asleep()
Expand All @@ -752,6 +753,9 @@ def run(self):
log.debug("initializing updateCheck")
updateCheck.initialize()

from winAPI import sessionTracking
sessionTracking.initialize()

_TrackNVDAInitialization.markInitializationComplete()

log.info("NVDA initialized")
Expand Down
3 changes: 2 additions & 1 deletion source/globalVars.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from typing_extensions import Literal

if TYPE_CHECKING:
import documentBase # noqa: F401 used for type checking only
import NVDAObjects # noqa: F401 used for type checking only


Expand Down Expand Up @@ -93,7 +94,7 @@ class DefaultAppArgs(argparse.Namespace):
navigatorObject: Optional['NVDAObjects.NVDAObject'] = None
"""Deprecated, use ``setNavigatorObject|getNavigatorObject`` from `api` instead"""

reviewPosition: Optional["NVDAObjects.NVDAObject"] = None
reviewPosition: Optional["documentBase.TextContainerObject"] = None
"""Deprecated, use ``getReviewPosition|setReviewPosition`` from `api` instead"""

reviewPositionObj: Optional["NVDAObjects.NVDAObject"] = None
Expand Down
13 changes: 10 additions & 3 deletions source/nvda.pyw
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,20 @@ if mutex is None:
sys.exit(1)


if _isSecureDesktop():
def _serviceDebugEnabled() -> bool:
import winreg
try:
k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\NVDA")
if not winreg.QueryValueEx(k, u"serviceDebug")[0]:
globalVars.appArgs.secure = True
if winreg.QueryValueEx(k, "serviceDebug")[0]:
return True
except WindowsError:
# Expected state by default, serviceDebug parameter not set
pass
return False


if _isSecureDesktop():
if not _serviceDebugEnabled():
globalVars.appArgs.secure = True
globalVars.appArgs.changeScreenReaderFlag = False
globalVars.appArgs.minimal = True
Expand Down
4 changes: 2 additions & 2 deletions source/scriptHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ def getGlobalMapScripts(gesture: "inputCore.InputGesture") -> List["inputCore.In

def findScript(gesture: "inputCore.InputGesture") -> Optional[_ScriptFunctionT]:
from utils.security import getSafeScripts
from winAPI.sessionTracking import isWindowsLocked
from winAPI.sessionTracking import _isLockScreenModeActive
foundScript = _findScript(gesture)
if (
foundScript is not None
and isWindowsLocked()
and _isLockScreenModeActive()
and foundScript not in getSafeScripts()
):
return None
Expand Down
6 changes: 3 additions & 3 deletions source/speechViewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from logHandler import log
from speech import SpeechSequence
import gui.contextHelp
from utils.security import isWindowsLocked, postSessionLockStateChanged
from utils.security import _isLockScreenModeActive, postSessionLockStateChanged


# Inherit from wx.Frame because these windows show in the alt+tab menu (where miniFrame does not)
Expand Down Expand Up @@ -102,7 +102,7 @@ def _createControls(self, sizer, parent):
wx.EVT_CHECKBOX,
self.onShouldShowOnStartupChanged
)
if isWindowsLocked():
if _isLockScreenModeActive():
self.shouldShowOnStartupCheckBox.Disable()

def _onDialogActivated(self, evt):
Expand All @@ -119,7 +119,7 @@ def onClose(self, evt):
deactivate()

def onShouldShowOnStartupChanged(self, evt: wx.CommandEvent):
if not isWindowsLocked():
if not _isLockScreenModeActive():
config.conf["speechViewer"]["showSpeechViewerAtStartup"] = self.shouldShowOnStartupCheckBox.IsChecked()

_isDestroyed: bool
Expand Down
Loading