mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-03-20 21:26:33 -04:00
macOS: Check for Auto-Type permissions on use instead of at launch
* Fix #3689 - link the use of Auto-Type with the permissions required to use it
This commit is contained in:
parent
440331d319
commit
7ba9fcc0e5
@ -218,6 +218,15 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
|
||||
|
||||
if (hideWindow) {
|
||||
#if defined(Q_OS_MACOS)
|
||||
// Check for accessibility permission
|
||||
if (!macUtils()->enableAccessibility()) {
|
||||
MessageBox::information(nullptr,
|
||||
tr("Permission Required"),
|
||||
tr("KeePassXC requires the Accessibility permission in order to perform entry "
|
||||
"level Auto-Type. If you already granted permission, you may have to restart "
|
||||
"KeePassXC."));
|
||||
return;
|
||||
}
|
||||
macUtils()->raiseLastActiveWindow();
|
||||
m_plugin->hideOwnWindow();
|
||||
#else
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "AutoTypeMac.h"
|
||||
#include "gui/macutils/MacUtils.h"
|
||||
#include "gui/MessageBox.h"
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
@ -25,6 +26,10 @@
|
||||
#define MAX_WINDOW_TITLE_LENGTH 1024
|
||||
#define INVALID_KEYCODE 0xFFFF
|
||||
|
||||
namespace {
|
||||
bool accessibilityChecked = false;
|
||||
}
|
||||
|
||||
AutoTypePlatformMac::AutoTypePlatformMac()
|
||||
: m_hotkeyRef(nullptr)
|
||||
, m_hotkeyId({ 'kpx2', HOTKEY_ID })
|
||||
@ -33,14 +38,18 @@ AutoTypePlatformMac::AutoTypePlatformMac()
|
||||
eventSpec.eventClass = kEventClassKeyboard;
|
||||
eventSpec.eventKind = kEventHotKeyPressed;
|
||||
|
||||
MessageBox::initializeButtonDefs();
|
||||
::InstallApplicationEventHandler(AutoTypePlatformMac::hotkeyHandler, 1, &eventSpec, this, nullptr);
|
||||
}
|
||||
|
||||
//
|
||||
// Keepassx requires mac os 10.7
|
||||
//
|
||||
/**
|
||||
* Determine if Auto-Type is available
|
||||
*
|
||||
* @return always return true
|
||||
*/
|
||||
bool AutoTypePlatformMac::isAvailable()
|
||||
{
|
||||
// Accessibility permissions are requested upon first use, instead of on load
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -470,6 +479,21 @@ OSStatus AutoTypePlatformMac::hotkeyHandler(EventHandlerCallRef nextHandler, Eve
|
||||
{
|
||||
Q_UNUSED(nextHandler);
|
||||
|
||||
// Determine if the user has given proper permissions to KeePassXC to perform Auto-Type
|
||||
if (!accessibilityChecked) {
|
||||
if (macUtils()->enableAccessibility() && macUtils()->enableScreenRecording()) {
|
||||
accessibilityChecked = true;
|
||||
} else {
|
||||
// Does not have required permissions to Auto-Type, ignore the keypress
|
||||
MessageBox::information(nullptr,
|
||||
tr("Permission Required"),
|
||||
tr("KeePassXC requires the Accessibility and Screen Recorder permission in order to perform global "
|
||||
"Auto-Type. Screen Recording is necessary to use the window title to find entries. If you "
|
||||
"already granted permission, you may have to restart KeePassXC."));
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
|
||||
AutoTypePlatformMac* self = static_cast<AutoTypePlatformMac*>(userData);
|
||||
EventHotKeyID hotkeyId;
|
||||
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
bool isHidden(pid_t pid);
|
||||
bool isDarkMode();
|
||||
bool enableAccessibility();
|
||||
bool enableScreenRecording();
|
||||
|
||||
signals:
|
||||
void lockDatabases();
|
||||
|
@ -37,5 +37,6 @@
|
||||
- (bool) isDarkMode;
|
||||
- (void) userSwitchHandler:(NSNotification*) notification;
|
||||
- (bool) enableAccessibility;
|
||||
- (bool) enableScreenRecording;
|
||||
|
||||
@end
|
||||
|
@ -19,6 +19,7 @@
|
||||
#import "AppKitImpl.h"
|
||||
|
||||
#import <AppKit/NSWorkspace.h>
|
||||
#import <CoreVideo/CVPixelBuffer.h>
|
||||
#import <Availability.h>
|
||||
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||
@ -128,21 +129,36 @@ static const NSEventMask NSEventMaskKeyDown = NSKeyDownMask;
|
||||
//
|
||||
- (bool) enableAccessibility
|
||||
{
|
||||
// Request a 1 pixel screenshot to trigger the permissions
|
||||
// required for screen reader access. These are necessary
|
||||
// for Auto-Type to find the window titles in macOS 10.15+
|
||||
CGImageRef screenshot = CGWindowListCreateImage(
|
||||
CGRectMake(0, 0, 1, 1),
|
||||
kCGWindowListOptionOnScreenOnly,
|
||||
kCGNullWindowID,
|
||||
kCGWindowImageDefault);
|
||||
CFRelease(screenshot);
|
||||
|
||||
// Request accessibility permissions for Auto-Type type on behalf of the user
|
||||
NSDictionary* opts = @{static_cast<id>(kAXTrustedCheckOptionPrompt): @YES};
|
||||
return AXIsProcessTrustedWithOptions(static_cast<CFDictionaryRef>(opts));
|
||||
}
|
||||
|
||||
//
|
||||
// Check if screen recording is enabled, may show an popup asking for permissions
|
||||
//
|
||||
- (bool) enableScreenRecording
|
||||
{
|
||||
if (@available(macOS 10.15, *)) {
|
||||
// Request screen recording permission on macOS 10.15+
|
||||
// This is necessary to get the current window title
|
||||
CGDisplayStreamRef stream = CGDisplayStreamCreate(CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil,
|
||||
^(CGDisplayStreamFrameStatus status, uint64_t displayTime,
|
||||
IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
|
||||
Q_UNUSED(status);
|
||||
Q_UNUSED(displayTime);
|
||||
Q_UNUSED(frameSurface);
|
||||
Q_UNUSED(updateRef);
|
||||
});
|
||||
if (stream) {
|
||||
CFRelease(stream);
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
@ -198,4 +214,9 @@ bool AppKit::isDarkMode()
|
||||
bool AppKit::enableAccessibility()
|
||||
{
|
||||
return [static_cast<id>(self) enableAccessibility];
|
||||
}
|
||||
}
|
||||
|
||||
bool AppKit::enableScreenRecording()
|
||||
{
|
||||
return [static_cast<id>(self) enableScreenRecording];
|
||||
}
|
||||
|
@ -80,3 +80,8 @@ bool MacUtils::enableAccessibility()
|
||||
{
|
||||
return m_appkit->enableAccessibility();
|
||||
}
|
||||
|
||||
bool MacUtils::enableScreenRecording()
|
||||
{
|
||||
return m_appkit->enableScreenRecording();
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
bool isHidden();
|
||||
bool isDarkMode();
|
||||
bool enableAccessibility();
|
||||
bool enableScreenRecording();
|
||||
|
||||
signals:
|
||||
void lockDatabases();
|
||||
|
Loading…
x
Reference in New Issue
Block a user