Introduced Autotype doctor in preparation for macOS 10.15.

This change removes the test for autotype on startup and will only check for permissoins when the pereferences are shown or when (gloabal)autotype is performed.
This commit is contained in:
Michael Starke
2019-07-09 15:39:23 +02:00
parent b1cb776e14
commit 32899cb707
23 changed files with 429 additions and 138 deletions

View File

@@ -9,9 +9,35 @@
#import "MPAutotypeDoctor.h"
#import "MPSettingsHelper.h"
#import "NSApplication+MPAdditions.h"
#import "MPAutotypeDoctorReportViewController.h"
#import "NSError+Messages.h"
@interface MPAutotypeDoctor ()
@interface MPReportItem : NSObject
@property (copy) NSString *statusDescription;
@property (copy) NSString *label;
@property (copy) NSString *actionLabel;
@property BOOL isOK;
@property (weak) id target;
@end
@implementation MPReportItem
- (instancetype)init {
self = [super init];
if(self) {
_isOK = NO;
}
return self;
}
@end
@interface MPAutotypeDoctor () <NSWindowDelegate>
@property (strong) NSWindow *reportWindow;
@end
@implementation MPAutotypeDoctor
@@ -25,90 +51,83 @@
return instance;
}
- (BOOL)hasScreenRecordingPermissions {
- (BOOL)hasNecessaryAutotypePermissions {
if(![self hasAccessibiltyPermissions:NULL]) {
return NO;
}
if(![self hasScreenRecordingPermissions:NULL]) {
return NO;
}
return YES;
}
- (BOOL)hasScreenRecordingPermissions:(NSError *__autoreleasing*)error {
BOOL canRecordScreen = YES;
/* macos 10.14 and lower do not require screen recording permission to get window titles */
if(@available(macos 10.15, *)) {
/*
To minimize the intrusion just make a 1px image of the upper left corner
This way there is no possibilty to access any private data
This way there is no real possibilty to access any private data
*/
CGImageRef screenshot = CGWindowListCreateImage(
CGRectMake(0, 0, 1, 1),
kCGWindowListOptionOnScreenOnly,
kCGNullWindowID,
kCGWindowImageDefault);
if(!screenshot) {
return NO;
BOOL canRecordScreen = !screenshot;
if(!canRecordScreen && error) {
*error = [NSError errorInDomain:MPAutotypeErrorDomain withCode:MPErrorAutotypeIsMissingScreenRecordingPermissions description:NSLocalizedString(@"ERROR_NO_PERMISSION_TO_RECORD_SCREEN", "Error description for missing screen recording permissions")];
}
}
return YES;
return canRecordScreen;
}
- (BOOL)hasAccessibiltyPermissions {
if(@available(macOS 10.14, *)) {
return AXIsProcessTrusted();
}
- (BOOL)hasAccessibiltyPermissions:(NSError *__autoreleasing*)error {
BOOL isTrusted = YES;
/* macOS 10.13 and lower allows us to send key events regardless of accessibilty trust */
return YES;
}
- (NSString *)localizedErrorDescription {
return @"TODO";
}
- (void)showPermissionCheckReport {
// TODO
}
- (BOOL)checkPermissionsWithoutUserFeedback {
// TODO
return YES;
}
- (void)checkForAccessibiltyPermissions {
if(NSApplication.sharedApplication.isRunningTests) {
return; // Do not display pop-up when running tests
}
BOOL hideAlert = NO;
if(nil != [NSUserDefaults.standardUserDefaults objectForKey:kMPSettingsKeyAutotypeHideAccessibiltyWarning]) {
hideAlert = [NSUserDefaults.standardUserDefaults boolForKey:kMPSettingsKeyAutotypeHideAccessibiltyWarning];
}
if(hideAlert || self.hasAccessibiltyPermissions) {
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 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!")];
NSModalResponse returnCode = [alert runModal];
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;
if(@available(macOS 10.14, *)) {
isTrusted = AXIsProcessTrusted();
if(!isTrusted && error) {
*error = [NSError errorInDomain:MPAutotypeErrorDomain withCode:MPErrorAutotypeIsMissingAccessibiltyPermissions description:NSLocalizedString(@"ERROR_NO_ACCESSIBILTY_PERMISSIONS", "Error description for missing accessibilty permissions")];
}
}
return isTrusted;
}
- (void)openAccessibiltyPreferences {
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"]];
}
- (void)checkForWindowTitlePermissions {
- (void)openScreenRecordingPreferences {
//TODO fix this in macOS 10.15 to use the correct URL
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security"]];
}
- (void)openAutomationPreferences {
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Automation"]];
}
- (void)runChecksAndPresentResults {
if(!self.reportWindow) {
self.reportWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskResizable
backing:NSBackingStoreBuffered
defer:NO];
self.reportWindow.releasedWhenClosed = NO;
self.reportWindow.title = NSLocalizedString(@"AUTOTYPE_DOCTOR_RESULTS_WINDOW_TITLE", @"Window title for the stand-alone password creator window");
self.reportWindow.delegate = self;
}
MPAutotypeDoctorReportViewController *vc = [[MPAutotypeDoctorReportViewController alloc] init];
self.reportWindow.contentViewController = vc;
[self.reportWindow center];
[self.reportWindow makeKeyAndOrderFront:vc];
}
- (void)windowWillClose:(NSNotification *)notification {
if(notification.object == self.reportWindow) {
self.reportWindow = nil;
}
}
@end