Using custom supressable dialog to check for autotype capabilities. Added notification when user performs autotype on disabled systems

This commit is contained in:
Michael Starke
2018-11-12 17:46:05 +01:00
parent 2d27fcbbb0
commit 04ffcab15b
9 changed files with 97 additions and 14 deletions

View File

@@ -25,14 +25,14 @@
@interface DDHotKey (MPKeydata) @interface DDHotKey (MPKeydata)
@property (readonly, copy) NSData *keyData; @property (readonly, copy) NSData *keyData;
@property (readonly, copy, class) NSData *defaultHotKeyData;
/** /**
Use this method to retrieve the data, since deallocation of a hotkey unregisters it, this could yield unwanted behaviour! Use this method to retrieve the data, since deallocation of a hotkey unregisters it, this could yield unwanted behaviour!
@return data for the default hot key. @return data for the default hot key.
*/ */
+ (NSData *)hotKeyDataWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags; + (NSData *)hotKeyDataWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags;
+ (NSData *)defaultHotKeyData;
+ (instancetype)defaultHotKey; + (instancetype)defaultHotKey;
+ (instancetype)defaultHotKeyWithTask:(DDHotKeyTask)task; + (instancetype)defaultHotKeyWithTask:(DDHotKeyTask)task;
+ (instancetype)hotKeyWithKeyData:(NSData *)data task:(DDHotKeyTask)task; + (instancetype)hotKeyWithKeyData:(NSData *)data task:(DDHotKeyTask)task;

View File

@@ -40,6 +40,7 @@
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
- (void)checkForAccessibiltyPermissions; - (void)checkForAccessibiltyPermissions;
- (void)openAccessibiltyPreferences;
- (void)performAutotypeForEntry:(KPKEntry *)entry; - (void)performAutotypeForEntry:(KPKEntry *)entry;
- (void)performAutotypeForEntry:(KPKEntry *)entry overrideSequence:(NSString *)sequence; - (void)performAutotypeForEntry:(KPKEntry *)entry overrideSequence:(NSString *)sequence;

View File

@@ -134,13 +134,47 @@ static MPAutotypeDaemon *_sharedInstance;
} }
- (void)checkForAccessibiltyPermissions { - (void)checkForAccessibiltyPermissions {
if(@available(macOS 10.14, *)) { if(!self.enabled) {
CFStringRef keys[] = { kAXTrustedCheckOptionPrompt }; return;
CFBooleanRef values[] = { kCFBooleanTrue };
CFDictionaryRef dictRef = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
AXIsProcessTrustedWithOptions(dictRef);
CFRelease(dictRef);
} }
BOOL hideAlert = NO;
if(nil != [NSUserDefaults.standardUserDefaults objectForKey:kMPSettingsKeyAutotypeHideAccessibiltyWarning]) {
hideAlert = [NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyAutotypeHideAccessibiltyWarning];
}
if(hideAlert || self.autotypeSupported) {
return;
}
else {
NSAlert *alert = [[NSAlert alloc] init];
alert.alertStyle = NSWarningAlertStyle;
alert.messageText = NSLocalizedString(@"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_MESSAGE_TEXT", @"Alert message displayed when Autotype performs self check and lacks accessibilty permissions");
alert.informativeText = NSLocalizedString(@"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_INFORMATIVE_TEXT", @"Alert informative text displayed when Autotype performs self check and lacks accessibilty permissions");
alert.showsSuppressionButton = YES;
alert.suppressionButton.title = NSLocalizedString(@"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_SUPPRESS_WARNING", @"Checkbox in dialog to set the selection as default file change strategy!");
[alert addButtonWithTitle:NSLocalizedString(@"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_BUTTON_OK", @"Button in dialog to leave autotype disabled and continiue!")];
[alert addButtonWithTitle:NSLocalizedString(@"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_BUTTON_OPEN_PREFERENCES", @"Button in dialog to open accessibilty preferences pane!")];
NSWindow *window = NSDocumentController.sharedDocumentController.currentDocument.windowForSheet;
[alert beginSheetModalForWindow:window completionHandler:^(NSModalResponse returnCode) {
BOOL suppressWarning = (alert.suppressionButton.state == NSOnState);
[NSUserDefaults.standardUserDefaults setBool:suppressWarning forKey:kMPSettingsKeyAutotypeHideAccessibiltyWarning];
switch(returnCode) {
case NSAlertFirstButtonReturn: {
/* ok, ignore */
break;
}
case NSAlertSecondButtonReturn:
/* open prefs */
[self openAccessibiltyPreferences];
break;
default:
break;
}
}];
}
}
- (void)openAccessibiltyPreferences {
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"]];
} }
#pragma mark - #pragma mark -
@@ -180,7 +214,17 @@ static MPAutotypeDaemon *_sharedInstance;
#pragma mark Autotype Execution #pragma mark Autotype Execution
- (void)_performAutotypeForEntry:(KPKEntry *)entryOrNil { - (void)_performAutotypeForEntry:(KPKEntry *)entryOrNil {
NSInteger pid = [NSProcessInfo processInfo].processIdentifier; if(!self.autotypeSupported) {
NSUserNotification *notification = [[NSUserNotification alloc] init];
notification.title = NSApp.applicationName;
notification.informativeText = NSLocalizedString(@"AUTOTYPE_NOTIFICATION_MACPASS_HAS_NO_ACCESSIBILTY_PERMISSIONS", "Notification: Autotype failed, MacPass has no permission to send key strokes");
notification.actionButtonTitle = NSLocalizedString(@"OPEN_PREFERENCES", "Action button in Notification to show the Accessibilty preferences");
notification.userInfo = @{ MPUserNotificationTypeKey: MPUserNotificationTypeShowAccessibiltyPreferences };
notification.showsButtons = YES;
[NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:notification];
return;
}
NSInteger pid = NSProcessInfo.processInfo.processIdentifier;
if(self.targetPID == pid) { if(self.targetPID == pid) {
return; // We do not perform Autotype on ourselves return; // We do not perform Autotype on ourselves
} }

View File

@@ -116,6 +116,7 @@
[self.autotypeStackView setVisibilityPriority:NSStackViewVisibilityPriorityMustHold forView:self.openPreferencesButton]; [self.autotypeStackView setVisibilityPriority:NSStackViewVisibilityPriorityMustHold forView:self.openPreferencesButton];
} }
/*
NSArray <NSControl *> *controls = @[ self.enableGlobalAutotypeCheckBox, NSArray <NSControl *> *controls = @[ self.enableGlobalAutotypeCheckBox,
self.hotKeyTextField, self.hotKeyTextField,
self.matchTitleCheckBox, self.matchTitleCheckBox,
@@ -126,10 +127,10 @@
for(NSControl *control in controls) { for(NSControl *control in controls) {
control.enabled = hasAutotypeSupport; control.enabled = hasAutotypeSupport;
} }
*/
} }
- (void)openAccessibiltyPreferences:(id)sender { - (void)openAccessibiltyPreferences:(id)sender {
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"]]; [MPAutotypeDaemon.defaultDaemon openAccessibiltyPreferences];
} }
@end @end

View File

@@ -50,8 +50,8 @@ APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideUsername;
APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHidePassword; APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHidePassword;
APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideNotes; APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideNotes;
APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideURL; APPKIT_EXTERN NSString *const kMPSettingsKeyLegacyHideURL;
/* Document/Key Location store */
/* Document/Key Location store */
APPKIT_EXTERN NSString *const kMPSettingsKeyLastDatabasePath; // Path to the last opened Database. Workaround if users have disabled the feature in the OS APPKIT_EXTERN NSString *const kMPSettingsKeyLastDatabasePath; // Path to the last opened Database. Workaround if users have disabled the feature in the OS
APPKIT_EXTERN NSString *const kMPSettingsKeyRememeberdKeysForDatabases; // NSDictionary of all db file urls and the corresponding key file url APPKIT_EXTERN NSString *const kMPSettingsKeyRememeberdKeysForDatabases; // NSDictionary of all db file urls and the corresponding key file url
APPKIT_EXTERN NSString *const kMPSettingsKeyRememberKeyFilesForDatabases; // YES if key files should be remembers APPKIT_EXTERN NSString *const kMPSettingsKeyRememberKeyFilesForDatabases; // YES if key files should be remembers
@@ -65,6 +65,7 @@ APPKIT_EXTERN NSString *const kMPSettingsKeyAutotypeMatchTitle; //
APPKIT_EXTERN NSString *const kMPSettingsKeyAutotypeMatchURL; // Autotype lookup includes entry URL APPKIT_EXTERN NSString *const kMPSettingsKeyAutotypeMatchURL; // Autotype lookup includes entry URL
APPKIT_EXTERN NSString *const kMPSettingsKeyAutotypeMatchHost; // Autotype lookup includes host part of entry URL APPKIT_EXTERN NSString *const kMPSettingsKeyAutotypeMatchHost; // Autotype lookup includes host part of entry URL
APPKIT_EXTERN NSString *const kMPSettingsKeyAutotypeMatchTags; // Autotype lookup includes tags for entries APPKIT_EXTERN NSString *const kMPSettingsKeyAutotypeMatchTags; // Autotype lookup includes tags for entries
APPKIT_EXTERN NSString *const kMPSettingsKeyAutotypeHideAccessibiltyWarning; // Do not show an alert, when MacPass has no support for Autotype
/* Search */ /* Search */
APPKIT_EXTERN NSString *const kMPSettingsKeyEntrySearchFilterContext; APPKIT_EXTERN NSString *const kMPSettingsKeyEntrySearchFilterContext;

View File

@@ -56,6 +56,7 @@ NSString *const kMPSettingsKeyAutotypeMatchTitle = @"Autoty
NSString *const kMPSettingsKeyAutotypeMatchURL = @"AutotypeMatchURL"; NSString *const kMPSettingsKeyAutotypeMatchURL = @"AutotypeMatchURL";
NSString *const kMPSettingsKeyAutotypeMatchHost = @"AutotypeMatchHost"; NSString *const kMPSettingsKeyAutotypeMatchHost = @"AutotypeMatchHost";
NSString *const kMPSettingsKeyAutotypeMatchTags = @"AutotypeMatchTags"; NSString *const kMPSettingsKeyAutotypeMatchTags = @"AutotypeMatchTags";
NSString *const kMPSettingsKeyAutotypeHideAccessibiltyWarning = @"AutotypeHideAccessibiltyWarning";
NSString *const kMPSettingsKeyEntrySearchFilterContext = @"EntrySearchFilterContext"; NSString *const kMPSettingsKeyEntrySearchFilterContext = @"EntrySearchFilterContext";

View File

@@ -25,6 +25,7 @@
FOUNDATION_EXTERN NSString *const MPUserNotificationTypeKey; FOUNDATION_EXTERN NSString *const MPUserNotificationTypeKey;
FOUNDATION_EXTERN NSString *const MPUserNotificationTypeAutotypeFeedback; FOUNDATION_EXTERN NSString *const MPUserNotificationTypeAutotypeFeedback;
FOUNDATION_EXTERN NSString *const MPUserNotificationTypeAutotypeOpenDocumentRequest; FOUNDATION_EXTERN NSString *const MPUserNotificationTypeAutotypeOpenDocumentRequest;
FOUNDATION_EXTERN NSString *const MPUserNotificationTypeShowAccessibiltyPreferences;
@interface MPUserNotificationCenterDelegate : NSObject <NSUserNotificationCenterDelegate> @interface MPUserNotificationCenterDelegate : NSObject <NSUserNotificationCenterDelegate>

View File

@@ -22,10 +22,12 @@
#import "MPUserNotificationCenterDelegate.h" #import "MPUserNotificationCenterDelegate.h"
#import "MPDocumentController.h" #import "MPDocumentController.h"
#import "MPAutotypeDaemon.h"
NSString *const MPUserNotificationTypeKey = @"MPUserNotificationTypeKey"; NSString *const MPUserNotificationTypeKey = @"MPUserNotificationTypeKey";
NSString *const MPUserNotificationTypeAutotypeFeedback = @"MPUserNotificationTypeAutotypeFeedback"; NSString *const MPUserNotificationTypeAutotypeFeedback = @"MPUserNotificationTypeAutotypeFeedback";
NSString *const MPUserNotificationTypeAutotypeOpenDocumentRequest = @"MPUserNotificationTypeAutotypeOpenDocumentRequest"; NSString *const MPUserNotificationTypeAutotypeOpenDocumentRequest = @"MPUserNotificationTypeAutotypeOpenDocumentRequest";
NSString *const MPUserNotificationTypeShowAccessibiltyPreferences = @"MPUserNotificationTypeShowAccessibiltyPreferences";
@implementation MPUserNotificationCenterDelegate @implementation MPUserNotificationCenterDelegate
@@ -39,13 +41,24 @@ NSString *const MPUserNotificationTypeAutotypeOpenDocumentRequest = @"MPUserNoti
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { - (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
NSDictionary *userInfo = notification.userInfo; NSDictionary *userInfo = notification.userInfo;
if([userInfo[MPUserNotificationTypeKey] isEqualToString:MPUserNotificationTypeAutotypeOpenDocumentRequest]) { NSString *notificationType = userInfo[MPUserNotificationTypeKey];
if([notificationType isEqualToString:MPUserNotificationTypeAutotypeOpenDocumentRequest]) {
[((MPDocumentController*)NSDocumentController.sharedDocumentController) reopenLastDocument]; [((MPDocumentController*)NSDocumentController.sharedDocumentController) reopenLastDocument];
} }
else if([notificationType isEqualToString:MPUserNotificationTypeShowAccessibiltyPreferences]) {
[MPAutotypeDaemon.defaultDaemon openAccessibiltyPreferences];
}
} }
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification { - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification {
return [notification.userInfo[MPUserNotificationTypeKey] isEqualToString:MPUserNotificationTypeAutotypeFeedback]; NSString *notificationType = notification.userInfo[MPUserNotificationTypeKey];
if([notificationType isEqualToString:MPUserNotificationTypeAutotypeFeedback]) {
return YES;
}
if([notificationType isEqualToString:MPUserNotificationTypeShowAccessibiltyPreferences]) {
return YES;
}
return NO;
} }

View File

@@ -31,6 +31,21 @@
/* Action to add an entry via template */ /* Action to add an entry via template */
"ADD_TREMPLATE_ENTRY" = "Create Template Entry"; "ADD_TREMPLATE_ENTRY" = "Create Template Entry";
/* Button in dialog to leave autotype disabled and continiue! */
"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_BUTTON_OK" = "Keep Autotype disabled.";
/* Button in dialog to open accessibilty preferences pane! */
"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_BUTTON_OPEN_PREFERENCES" = "Open Accessibilty Preferences…";
/* Alert informative text displayed when Autotype performs self check and lacks accessibilty permissions */
"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_INFORMATIVE_TEXT" = "The system prevents MacPass from sending key strokes to other Applications. To enable Autotype please grant MacPass Accessibilty rights in the privacy preferences.";
/* Alert message displayed when Autotype performs self check and lacks accessibilty permissions */
"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_MESSAGE_TEXT" = "MacPass cannot perform Autotype";
/* Checkbox in dialog to set the selection as default file change strategy! */
"ALERT_AUTOTYPE_MISSING_ACCESSIBILTY_PERMISSIONS_SUPPRESS_WARNING" = "Do not show this warning again.";
/* Alert informative text when plugins or their settings change and require a restart */ /* Alert informative text when plugins or their settings change and require a restart */
"ALERT_INFORMATIVE_TEXT_PLUGINS_CHANGED_SUGGEST_RESTART" = "Changes to plugins and global plugin settings take only effect after restart. Restart MacPass now?"; "ALERT_INFORMATIVE_TEXT_PLUGINS_CHANGED_SUGGEST_RESTART" = "Changes to plugins and global plugin settings take only effect after restart. Restart MacPass now?";
@@ -80,6 +95,9 @@
/* Disable autotype menu item */ /* Disable autotype menu item */
"AUTOTYPE_NO" = "Disable Autotype"; "AUTOTYPE_NO" = "Disable Autotype";
/* Notification: Autotype failed, MacPass has no permission to send key strokes */
"AUTOTYPE_NOTIFICATION_MACPASS_HAS_NO_ACCESSIBILTY_PERMISSIONS" = "Autotype disabled because of missing accessibilty access.";
/* Notification: Autotype failed, no documents are open */ /* Notification: Autotype failed, no documents are open */
"AUTOTYPE_OVERLAY_NO_DOCUMENTS" = "Please open a database file to use Global Autotype!"; "AUTOTYPE_OVERLAY_NO_DOCUMENTS" = "Please open a database file to use Global Autotype!";
@@ -408,6 +426,9 @@
/* Action button in Notification to open a document */ /* Action button in Notification to open a document */
"OPEN_DOCUMENT" = "Open Document"; "OPEN_DOCUMENT" = "Open Document";
/* Action button in Notification to show the Accessibilty preferences */
"OPEN_PREFERENCES" = "Open Accessiblity Preferences…";
/* Menu item to open the URL with the default application */ /* Menu item to open the URL with the default application */
"OPEN_URL" = "Open URL"; "OPEN_URL" = "Open URL";