mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-08-24 14:15:47 -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
7 changed files with 76 additions and 14 deletions
|
@ -218,6 +218,15 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
|
||||||
|
|
||||||
if (hideWindow) {
|
if (hideWindow) {
|
||||||
#if defined(Q_OS_MACOS)
|
#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();
|
macUtils()->raiseLastActiveWindow();
|
||||||
m_plugin->hideOwnWindow();
|
m_plugin->hideOwnWindow();
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "AutoTypeMac.h"
|
#include "AutoTypeMac.h"
|
||||||
#include "gui/macutils/MacUtils.h"
|
#include "gui/macutils/MacUtils.h"
|
||||||
|
#include "gui/MessageBox.h"
|
||||||
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
|
@ -25,6 +26,10 @@
|
||||||
#define MAX_WINDOW_TITLE_LENGTH 1024
|
#define MAX_WINDOW_TITLE_LENGTH 1024
|
||||||
#define INVALID_KEYCODE 0xFFFF
|
#define INVALID_KEYCODE 0xFFFF
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool accessibilityChecked = false;
|
||||||
|
}
|
||||||
|
|
||||||
AutoTypePlatformMac::AutoTypePlatformMac()
|
AutoTypePlatformMac::AutoTypePlatformMac()
|
||||||
: m_hotkeyRef(nullptr)
|
: m_hotkeyRef(nullptr)
|
||||||
, m_hotkeyId({ 'kpx2', HOTKEY_ID })
|
, m_hotkeyId({ 'kpx2', HOTKEY_ID })
|
||||||
|
@ -33,14 +38,18 @@ AutoTypePlatformMac::AutoTypePlatformMac()
|
||||||
eventSpec.eventClass = kEventClassKeyboard;
|
eventSpec.eventClass = kEventClassKeyboard;
|
||||||
eventSpec.eventKind = kEventHotKeyPressed;
|
eventSpec.eventKind = kEventHotKeyPressed;
|
||||||
|
|
||||||
|
MessageBox::initializeButtonDefs();
|
||||||
::InstallApplicationEventHandler(AutoTypePlatformMac::hotkeyHandler, 1, &eventSpec, this, nullptr);
|
::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()
|
bool AutoTypePlatformMac::isAvailable()
|
||||||
{
|
{
|
||||||
|
// Accessibility permissions are requested upon first use, instead of on load
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,6 +479,21 @@ OSStatus AutoTypePlatformMac::hotkeyHandler(EventHandlerCallRef nextHandler, Eve
|
||||||
{
|
{
|
||||||
Q_UNUSED(nextHandler);
|
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);
|
AutoTypePlatformMac* self = static_cast<AutoTypePlatformMac*>(userData);
|
||||||
EventHotKeyID hotkeyId;
|
EventHotKeyID hotkeyId;
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
bool isHidden(pid_t pid);
|
bool isHidden(pid_t pid);
|
||||||
bool isDarkMode();
|
bool isDarkMode();
|
||||||
bool enableAccessibility();
|
bool enableAccessibility();
|
||||||
|
bool enableScreenRecording();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void lockDatabases();
|
void lockDatabases();
|
||||||
|
|
|
@ -37,5 +37,6 @@
|
||||||
- (bool) isDarkMode;
|
- (bool) isDarkMode;
|
||||||
- (void) userSwitchHandler:(NSNotification*) notification;
|
- (void) userSwitchHandler:(NSNotification*) notification;
|
||||||
- (bool) enableAccessibility;
|
- (bool) enableAccessibility;
|
||||||
|
- (bool) enableScreenRecording;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#import "AppKitImpl.h"
|
#import "AppKitImpl.h"
|
||||||
|
|
||||||
#import <AppKit/NSWorkspace.h>
|
#import <AppKit/NSWorkspace.h>
|
||||||
|
#import <CoreVideo/CVPixelBuffer.h>
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
|
@ -128,21 +129,36 @@ static const NSEventMask NSEventMaskKeyDown = NSKeyDownMask;
|
||||||
//
|
//
|
||||||
- (bool) enableAccessibility
|
- (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
|
// Request accessibility permissions for Auto-Type type on behalf of the user
|
||||||
NSDictionary* opts = @{static_cast<id>(kAXTrustedCheckOptionPrompt): @YES};
|
NSDictionary* opts = @{static_cast<id>(kAXTrustedCheckOptionPrompt): @YES};
|
||||||
return AXIsProcessTrustedWithOptions(static_cast<CFDictionaryRef>(opts));
|
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
|
@end
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -199,3 +215,8 @@ bool AppKit::enableAccessibility()
|
||||||
{
|
{
|
||||||
return [static_cast<id>(self) 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();
|
return m_appkit->enableAccessibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacUtils::enableScreenRecording()
|
||||||
|
{
|
||||||
|
return m_appkit->enableScreenRecording();
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
bool isHidden();
|
bool isHidden();
|
||||||
bool isDarkMode();
|
bool isDarkMode();
|
||||||
bool enableAccessibility();
|
bool enableAccessibility();
|
||||||
|
bool enableScreenRecording();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void lockDatabases();
|
void lockDatabases();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue