mirror of
https://github.com/MacPass/MacPass.git
synced 2026-01-31 09:28:25 +00:00
Moved accessibilty permission checks into MPAutotypeDoctor. Added screen capture permission test.
This commit is contained in:
@@ -35,6 +35,7 @@
|
|||||||
4C17F109184E6B6C00E85625 /* 30_TerminalTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C17F107184E6B6C00E85625 /* 30_TerminalTemplate.pdf */; };
|
4C17F109184E6B6C00E85625 /* 30_TerminalTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C17F107184E6B6C00E85625 /* 30_TerminalTemplate.pdf */; };
|
||||||
4C1BDF2B1E4392640012A3F0 /* MPPluginDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1BDF291E4392640012A3F0 /* MPPluginDataViewController.m */; };
|
4C1BDF2B1E4392640012A3F0 /* MPPluginDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1BDF291E4392640012A3F0 /* MPPluginDataViewController.m */; };
|
||||||
4C1E9885185F71A800943563 /* MPContextBarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E9884185F71A800943563 /* MPContextBarViewController.m */; };
|
4C1E9885185F71A800943563 /* MPContextBarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E9884185F71A800943563 /* MPContextBarViewController.m */; };
|
||||||
|
4C1ECAE322CCD30F00F46069 /* MPAutotypeDoctor.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1ECAE222CCD30F00F46069 /* MPAutotypeDoctor.m */; };
|
||||||
4C1F7FA21E3A12E600D6A40E /* MPModifiedKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1F7FA11E3A12E600D6A40E /* MPModifiedKey.m */; };
|
4C1F7FA21E3A12E600D6A40E /* MPModifiedKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1F7FA11E3A12E600D6A40E /* MPModifiedKey.m */; };
|
||||||
4C1FA07B18231900003A3F8C /* MPDocument+Autotype.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1FA07A18231900003A3F8C /* MPDocument+Autotype.m */; };
|
4C1FA07B18231900003A3F8C /* MPDocument+Autotype.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1FA07A18231900003A3F8C /* MPDocument+Autotype.m */; };
|
||||||
4C224B4217DFCB2400FF6AEE /* MPNumericalInputFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C224B4117DFCB2400FF6AEE /* MPNumericalInputFormatter.m */; };
|
4C224B4217DFCB2400FF6AEE /* MPNumericalInputFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C224B4117DFCB2400FF6AEE /* MPNumericalInputFormatter.m */; };
|
||||||
@@ -394,6 +395,8 @@
|
|||||||
4C1D56382271F4BC00C3E594 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/PluginRepositoryBrowserView.strings; sourceTree = "<group>"; };
|
4C1D56382271F4BC00C3E594 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/PluginRepositoryBrowserView.strings; sourceTree = "<group>"; };
|
||||||
4C1E9883185F71A800943563 /* MPContextBarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPContextBarViewController.h; sourceTree = "<group>"; };
|
4C1E9883185F71A800943563 /* MPContextBarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPContextBarViewController.h; sourceTree = "<group>"; };
|
||||||
4C1E9884185F71A800943563 /* MPContextBarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPContextBarViewController.m; sourceTree = "<group>"; };
|
4C1E9884185F71A800943563 /* MPContextBarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPContextBarViewController.m; sourceTree = "<group>"; };
|
||||||
|
4C1ECAE122CCD30F00F46069 /* MPAutotypeDoctor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPAutotypeDoctor.h; sourceTree = "<group>"; };
|
||||||
|
4C1ECAE222CCD30F00F46069 /* MPAutotypeDoctor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPAutotypeDoctor.m; sourceTree = "<group>"; };
|
||||||
4C1F7FA01E3A12E600D6A40E /* MPModifiedKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPModifiedKey.h; sourceTree = "<group>"; };
|
4C1F7FA01E3A12E600D6A40E /* MPModifiedKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPModifiedKey.h; sourceTree = "<group>"; };
|
||||||
4C1F7FA11E3A12E600D6A40E /* MPModifiedKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPModifiedKey.m; sourceTree = "<group>"; };
|
4C1F7FA11E3A12E600D6A40E /* MPModifiedKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPModifiedKey.m; sourceTree = "<group>"; };
|
||||||
4C1FA07A18231900003A3F8C /* MPDocument+Autotype.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPDocument+Autotype.m"; sourceTree = "<group>"; };
|
4C1FA07A18231900003A3F8C /* MPDocument+Autotype.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPDocument+Autotype.m"; sourceTree = "<group>"; };
|
||||||
@@ -1534,6 +1537,8 @@
|
|||||||
4C3499FF218852160055AF45 /* MPKeyTyper.m */,
|
4C3499FF218852160055AF45 /* MPKeyTyper.m */,
|
||||||
4C1F7FA01E3A12E600D6A40E /* MPModifiedKey.h */,
|
4C1F7FA01E3A12E600D6A40E /* MPModifiedKey.h */,
|
||||||
4C1F7FA11E3A12E600D6A40E /* MPModifiedKey.m */,
|
4C1F7FA11E3A12E600D6A40E /* MPModifiedKey.m */,
|
||||||
|
4C1ECAE122CCD30F00F46069 /* MPAutotypeDoctor.h */,
|
||||||
|
4C1ECAE222CCD30F00F46069 /* MPAutotypeDoctor.m */,
|
||||||
);
|
);
|
||||||
name = Autotype;
|
name = Autotype;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1990,6 +1995,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
4C1ECAE322CCD30F00F46069 /* MPAutotypeDoctor.m in Sources */,
|
||||||
4CD034AC1BFE113B003C002C /* MPPluginHost.m in Sources */,
|
4CD034AC1BFE113B003C002C /* MPPluginHost.m in Sources */,
|
||||||
4C77E37315B84A240093A587 /* main.m in Sources */,
|
4C77E37315B84A240093A587 /* main.m in Sources */,
|
||||||
4C0F04402147A6FA000B8568 /* MPCustomFieldTableView.m in Sources */,
|
4C0F04402147A6FA000B8568 /* MPCustomFieldTableView.m in Sources */,
|
||||||
|
|||||||
@@ -26,29 +26,28 @@
|
|||||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="1">
|
<customView translatesAutoresizingMaskIntoConstraints="NO" id="1">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="400" height="463"/>
|
<rect key="frame" x="0.0" y="0.0" width="400" height="421"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<box autoresizesSubviews="NO" verticalHuggingPriority="500" borderType="line" title="Autotype" translatesAutoresizingMaskIntoConstraints="NO" id="P9N-HM-wER">
|
<box autoresizesSubviews="NO" verticalHuggingPriority="500" borderType="line" title="Autotype" translatesAutoresizingMaskIntoConstraints="NO" id="P9N-HM-wER">
|
||||||
<rect key="frame" x="17" y="115" width="366" height="328"/>
|
<rect key="frame" x="17" y="115" width="366" height="286"/>
|
||||||
<view key="contentView" id="faU-Ok-HJ3">
|
<view key="contentView" id="faU-Ok-HJ3">
|
||||||
<rect key="frame" x="3" y="3" width="360" height="310"/>
|
<rect key="frame" x="3" y="3" width="360" height="268"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<stackView orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" translatesAutoresizingMaskIntoConstraints="NO" id="j52-9L-k7c">
|
<stackView orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" translatesAutoresizingMaskIntoConstraints="NO" id="j52-9L-k7c">
|
||||||
<rect key="frame" x="16" y="17" width="328" height="283"/>
|
<rect key="frame" x="16" y="17" width="328" height="241"/>
|
||||||
<beginningViews>
|
<beginningViews>
|
||||||
<textField verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="328" translatesAutoresizingMaskIntoConstraints="NO" id="hMJ-Mo-xOM">
|
<textField verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="328" translatesAutoresizingMaskIntoConstraints="NO" id="hMJ-Mo-xOM">
|
||||||
<rect key="frame" x="-2" y="227" width="332" height="56"/>
|
<rect key="frame" x="-2" y="227" width="150" height="14"/>
|
||||||
<textFieldCell key="cell" controlSize="small" id="H37-ku-aTc">
|
<textFieldCell key="cell" controlSize="small" title="ReportFromAutotypeDoctor" id="H37-ku-aTc">
|
||||||
<font key="font" metaFont="smallSystem"/>
|
<font key="font" metaFont="smallSystem"/>
|
||||||
<string key="title">Autotype is not available, because MacPass is not allowed to control your computer. To enable Autotype, go to the Security and Privacy Preferences and add MacPass to the Accessibilty group. Changes require a restart of MacPass.</string>
|
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jai-b6-Qv4">
|
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jai-b6-Qv4">
|
||||||
<rect key="frame" x="-6" y="191" width="160" height="32"/>
|
<rect key="frame" x="-6" y="191" width="177" height="32"/>
|
||||||
<buttonCell key="cell" type="push" title="Open Preferences…" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="NP0-R3-m6n">
|
<buttonCell key="cell" type="push" title="Run Autotype Doctor…" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="NP0-R3-m6n">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
</buttonCell>
|
</buttonCell>
|
||||||
|
|||||||
@@ -370,10 +370,6 @@ typedef NS_OPTIONS(NSInteger, MPAppStartupState) {
|
|||||||
if(showWelcomeScreen) {
|
if(showWelcomeScreen) {
|
||||||
[self showWelcomeWindow];
|
[self showWelcomeWindow];
|
||||||
}
|
}
|
||||||
/* run check for accessibilty after the windowserver should have presented the UI */
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
||||||
[MPAutotypeDaemon.defaultDaemon checkForAccessibiltyPermissions];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -35,13 +35,9 @@
|
|||||||
@property (weak) IBOutlet NSPopUpButton *matchSelectionButton;
|
@property (weak) IBOutlet NSPopUpButton *matchSelectionButton;
|
||||||
@property (readonly, strong) DDHotKey *registredHotKey;
|
@property (readonly, strong) DDHotKey *registredHotKey;
|
||||||
@property (readonly, strong, class) MPAutotypeDaemon *defaultDaemon;
|
@property (readonly, strong, class) MPAutotypeDaemon *defaultDaemon;
|
||||||
@property (nonatomic, readonly) BOOL autotypeSupported; // YES if the system allows for Autotype. NO if the user has denied this.
|
|
||||||
|
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
|
||||||
- (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;
|
||||||
- (void)selectAutotypeCandiate:(MPAutotypeContext *)context;
|
- (void)selectAutotypeCandiate:(MPAutotypeContext *)context;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#import "MPSettingsHelper.h"
|
#import "MPSettingsHelper.h"
|
||||||
#import "MPAutotypeCandidateSelectionViewController.h"
|
#import "MPAutotypeCandidateSelectionViewController.h"
|
||||||
#import "MPUserNotificationCenterDelegate.h"
|
#import "MPUserNotificationCenterDelegate.h"
|
||||||
|
#import "MPAutotypeDoctor.h"
|
||||||
|
|
||||||
#import "MPPluginHost.h"
|
#import "MPPluginHost.h"
|
||||||
#import "MPPlugin.h"
|
#import "MPPlugin.h"
|
||||||
@@ -57,12 +58,11 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey";
|
|||||||
@property (strong) NSRunningApplication *previousApplication; // The application that was active before we got invoked
|
@property (strong) NSRunningApplication *previousApplication; // The application that was active before we got invoked
|
||||||
@property (assign) NSTimeInterval userActionRequested;
|
@property (assign) NSTimeInterval userActionRequested;
|
||||||
@property (strong) id applicationActivationObserver;
|
@property (strong) id applicationActivationObserver;
|
||||||
|
@property BOOL shouldRunAutotypeDoctor;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation MPAutotypeDaemon
|
@implementation MPAutotypeDaemon
|
||||||
|
|
||||||
@dynamic autotypeSupported;
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark Lifecylce
|
#pragma mark Lifecylce
|
||||||
|
|
||||||
@@ -87,6 +87,8 @@ static MPAutotypeDaemon *_sharedInstance;
|
|||||||
_enabled = NO;
|
_enabled = NO;
|
||||||
_targetPID = -1;
|
_targetPID = -1;
|
||||||
_userActionRequested = NSDate.distantPast.timeIntervalSinceReferenceDate;
|
_userActionRequested = NSDate.distantPast.timeIntervalSinceReferenceDate;
|
||||||
|
_shouldRunAutotypeDoctor = NO;
|
||||||
|
BOOL test = MPAutotypeDoctor.defaultDoctor.hasScreenRecordingPermissions;
|
||||||
[self bind:NSStringFromSelector(@selector(enabled))
|
[self bind:NSStringFromSelector(@selector(enabled))
|
||||||
toObject:NSUserDefaultsController.sharedUserDefaultsController
|
toObject:NSUserDefaultsController.sharedUserDefaultsController
|
||||||
withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyEnableGlobalAutotype]
|
withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyEnableGlobalAutotype]
|
||||||
@@ -117,13 +119,6 @@ static MPAutotypeDaemon *_sharedInstance;
|
|||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark Properties
|
#pragma mark Properties
|
||||||
- (BOOL)autotypeSupported {
|
|
||||||
if(@available(macOS 10.14, *)) {
|
|
||||||
return AXIsProcessTrusted();
|
|
||||||
}
|
|
||||||
/* macOS 10.13 and lower allows us to send key events regardless of accessibilty trust */
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)setEnabled:(BOOL)enabled {
|
- (void)setEnabled:(BOOL)enabled {
|
||||||
if(_enabled != enabled) {
|
if(_enabled != enabled) {
|
||||||
@@ -142,52 +137,6 @@ static MPAutotypeDaemon *_sharedInstance;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)checkForAccessibiltyPermissions {
|
|
||||||
if(!self.enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.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 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)openAccessibiltyPreferences {
|
|
||||||
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"]];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark Autotype Invocation
|
#pragma mark Autotype Invocation
|
||||||
- (void)performAutotypeForEntry:(KPKEntry *)entry {
|
- (void)performAutotypeForEntry:(KPKEntry *)entry {
|
||||||
@@ -225,6 +174,10 @@ static MPAutotypeDaemon *_sharedInstance;
|
|||||||
#pragma mark Autotype Execution
|
#pragma mark Autotype Execution
|
||||||
|
|
||||||
- (void)_performAutotypeForEntry:(KPKEntry *)entryOrNil {
|
- (void)_performAutotypeForEntry:(KPKEntry *)entryOrNil {
|
||||||
|
if(self.shouldRunAutotypeDoctor) {
|
||||||
|
[MPAutotypeDoctor.defaultDoctor showPermissionCheckReport];
|
||||||
|
}
|
||||||
|
|
||||||
/*if(!self.autotypeSupported) {
|
/*if(!self.autotypeSupported) {
|
||||||
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
NSUserNotification *notification = [[NSUserNotification alloc] init];
|
||||||
notification.title = NSApp.applicationName;
|
notification.title = NSApp.applicationName;
|
||||||
|
|||||||
31
MacPass/MPAutotypeDoctor.h
Normal file
31
MacPass/MPAutotypeDoctor.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// MPAutotypeDoctor.h
|
||||||
|
// MacPass
|
||||||
|
//
|
||||||
|
// Created by Michael Starke on 03.07.19.
|
||||||
|
// Copyright © 2019 HicknHack Software GmbH. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef NS_OPTIONS(NSUInteger, MPAutotypeIssue) {
|
||||||
|
MPAutotypeIssueNoAccessibiltyPermission,
|
||||||
|
MPAutotypeIssueNoScreenRecordingPermission
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface MPAutotypeDoctor : NSObject
|
||||||
|
|
||||||
|
@property (class, readonly, strong) MPAutotypeDoctor *defaultDoctor;
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) BOOL hasAccessibiltyPermissions; // 10.14 requires accessibilty access to send key strokes to other applications
|
||||||
|
@property (nonatomic, readonly) BOOL hasScreenRecordingPermissions; // 10.15 requires screen recording permissions to get window names from other processes
|
||||||
|
@property (nonatomic, readonly, copy) NSString *localizedErrorDescription; // If any issues are present, this property holds alocalized error description
|
||||||
|
|
||||||
|
- (BOOL)checkPermissionsWithoutUserFeedback;
|
||||||
|
- (void)showPermissionCheckReport;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
114
MacPass/MPAutotypeDoctor.m
Normal file
114
MacPass/MPAutotypeDoctor.m
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
//
|
||||||
|
// MPAutotypeDoctor.m
|
||||||
|
// MacPass
|
||||||
|
//
|
||||||
|
// Created by Michael Starke on 03.07.19.
|
||||||
|
// Copyright © 2019 HicknHack Software GmbH. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPAutotypeDoctor.h"
|
||||||
|
#import "MPSettingsHelper.h"
|
||||||
|
#import "NSApplication+MPAdditions.h"
|
||||||
|
|
||||||
|
@interface MPAutotypeDoctor ()
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MPAutotypeDoctor
|
||||||
|
|
||||||
|
+ (MPAutotypeDoctor *)defaultDoctor {
|
||||||
|
static MPAutotypeDoctor *instance;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
instance = [[MPAutotypeDoctor alloc] init];
|
||||||
|
});
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasScreenRecordingPermissions {
|
||||||
|
/* 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
|
||||||
|
*/
|
||||||
|
CGImageRef screenshot = CGWindowListCreateImage(
|
||||||
|
CGRectMake(0, 0, 1, 1),
|
||||||
|
kCGWindowListOptionOnScreenOnly,
|
||||||
|
kCGNullWindowID,
|
||||||
|
kCGWindowImageDefault);
|
||||||
|
if(!screenshot) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasAccessibiltyPermissions {
|
||||||
|
if(@available(macOS 10.14, *)) {
|
||||||
|
return AXIsProcessTrusted();
|
||||||
|
}
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)openAccessibiltyPreferences {
|
||||||
|
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)checkForWindowTitlePermissions {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
#import "MPIntegrationPreferencesController.h"
|
#import "MPIntegrationPreferencesController.h"
|
||||||
#import "MPSettingsHelper.h"
|
#import "MPSettingsHelper.h"
|
||||||
#import "MPIconHelper.h"
|
#import "MPIconHelper.h"
|
||||||
#import "MPAutotypeDaemon.h"
|
#import "MPAutotypeDoctor.h"
|
||||||
|
|
||||||
#import "DDHotKeyCenter.h"
|
#import "DDHotKeyCenter.h"
|
||||||
#import "DDHotKey+MacPassAdditions.h"
|
#import "DDHotKey+MacPassAdditions.h"
|
||||||
@@ -105,7 +105,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)_updateAccessabilityWarning {
|
- (void)_updateAccessabilityWarning {
|
||||||
BOOL hasAutotypeSupport = MPAutotypeDaemon.defaultDaemon.autotypeSupported;
|
|
||||||
|
BOOL hasAutotypeSupport = MPAutotypeDoctor.defaultDoctor.hasAccessibiltyPermissions;
|
||||||
|
|
||||||
if(hasAutotypeSupport) {
|
if(hasAutotypeSupport) {
|
||||||
[self.autotypeStackView setVisibilityPriority:NSStackViewVisibilityPriorityNotVisible forView:self.autotypeWarningTextField];
|
[self.autotypeStackView setVisibilityPriority:NSStackViewVisibilityPriorityNotVisible forView:self.autotypeWarningTextField];
|
||||||
@@ -118,6 +119,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)openAccessibiltyPreferences:(id)sender {
|
- (void)openAccessibiltyPreferences:(id)sender {
|
||||||
[MPAutotypeDaemon.defaultDaemon openAccessibiltyPreferences];
|
[MPAutotypeDoctor.defaultDoctor showPermissionCheckReport];
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#import "MPUserNotificationCenterDelegate.h"
|
#import "MPUserNotificationCenterDelegate.h"
|
||||||
#import "MPDocumentController.h"
|
#import "MPDocumentController.h"
|
||||||
#import "MPAutotypeDaemon.h"
|
#import "MPAutotypeDoctor.h"
|
||||||
|
|
||||||
NSString *const MPUserNotificationTypeKey = @"MPUserNotificationTypeKey";
|
NSString *const MPUserNotificationTypeKey = @"MPUserNotificationTypeKey";
|
||||||
NSString *const MPUserNotificationTypeAutotypeFeedback = @"MPUserNotificationTypeAutotypeFeedback";
|
NSString *const MPUserNotificationTypeAutotypeFeedback = @"MPUserNotificationTypeAutotypeFeedback";
|
||||||
@@ -46,7 +46,7 @@ NSString *const MPUserNotificationTypeShowAccessibiltyPreferences = @"MPUserNoti
|
|||||||
[((MPDocumentController*)NSDocumentController.sharedDocumentController) reopenLastDocument];
|
[((MPDocumentController*)NSDocumentController.sharedDocumentController) reopenLastDocument];
|
||||||
}
|
}
|
||||||
else if([notificationType isEqualToString:MPUserNotificationTypeShowAccessibiltyPreferences]) {
|
else if([notificationType isEqualToString:MPUserNotificationTypeShowAccessibiltyPreferences]) {
|
||||||
[MPAutotypeDaemon.defaultDaemon openAccessibiltyPreferences];
|
[MPAutotypeDoctor.defaultDoctor showPermissionCheckReport];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user