From 027d0840edd46aaffb606b4e712e3b85dccc528e Mon Sep 17 00:00:00 2001 From: Patrick Wardle Date: Sun, 24 Sep 2017 20:29:24 -1000 Subject: [PATCH] v1.1.2 --- Installer/Configure.m | 5 ++- Installer/Info.plist | 4 +- LoginItem/AVMonitor.h | 4 +- LoginItem/AVMonitor.m | 44 ++++++++++++-------- LoginItem/Info.plist | 4 +- LoginItem/RemeberWindowController.m | 27 ++++++++++--- LoginItem/StatusBarMenu.m | 11 +++-- MainApp/Info.plist | 4 +- MainApp/Rules.xib | 4 ++ OverSightXPC/Enumerator.h | 2 +- OverSightXPC/Enumerator.m | 63 ++++++++++++++++++++++++++--- OverSightXPC/Info.plist | 4 +- OverSightXPC/OverSightXPC.m | 4 +- Shared/Utilities.h | 3 ++ Shared/Utilities.m | 7 ++++ Shared/XPCProtocol.h | 2 +- 16 files changed, 145 insertions(+), 47 deletions(-) diff --git a/Installer/Configure.m b/Installer/Configure.m index 76732f7..c4840b5 100644 --- a/Installer/Configure.m +++ b/Installer/Configure.m @@ -41,7 +41,7 @@ #endif //stop - // ->kill login item/XPC service + // ->kill main app/login item/XPC service [self stop]; //uninstall @@ -315,6 +315,9 @@ bail: //stop -(void)stop { + //kill main app + execTask(PKILL, @[[APP_NAME stringByDeletingPathExtension]], YES); + //kill helper app execTask(PKILL, @[APP_HELPER], YES); diff --git a/Installer/Info.plist b/Installer/Info.plist index 967a6cd..a9b7be4 100644 --- a/Installer/Info.plist +++ b/Installer/Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.1 + 1.1.2 CFBundleSignature ???? CFBundleVersion - 1.1.1 + 1.1.2 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright diff --git a/LoginItem/AVMonitor.h b/LoginItem/AVMonitor.h index f9aefe5..2116e46 100644 --- a/LoginItem/AVMonitor.h +++ b/LoginItem/AVMonitor.h @@ -46,8 +46,8 @@ //monitor thread @property(nonatomic, retain)NSThread* videoMonitorThread; -//remember popup/window controller -@property(nonatomic, retain)RememberWindowController* rememberWindowController; +//popup windows +@property(nonatomic, retain)NSMutableArray* rememberPopups; //last event @property(nonatomic, retain)NSDictionary* lastEvent; diff --git a/LoginItem/AVMonitor.m b/LoginItem/AVMonitor.m index 728b09d..8d8b3e6 100644 --- a/LoginItem/AVMonitor.m +++ b/LoginItem/AVMonitor.m @@ -21,10 +21,10 @@ @synthesize lastEvent; @synthesize whiteList; @synthesize audioActive; +@synthesize rememberPopups; @synthesize activationAlerts; @synthesize lastNotification; @synthesize videoMonitorThread; -@synthesize rememberWindowController; //init -(id)init @@ -36,6 +36,9 @@ //alloc activationAlerts = [NSMutableDictionary dictionary]; + //alloc + rememberPopups = [NSMutableArray array]; + //load whitelist [self loadWhitelist]; } @@ -568,10 +571,10 @@ bail: //set allowed classes [xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil] - forSelector: @selector(getVideoProcs:) argumentIndex: 0 ofReply: YES]; + forSelector: @selector(getVideoProcs:reply:) argumentIndex: 0 ofReply: YES]; //invoke XPC service - [[xpcConnection remoteObjectProxy] getVideoProcs:^(NSMutableArray* videoProcesses) + [[xpcConnection remoteObjectProxy] getVideoProcs:NO reply:^(NSMutableArray* videoProcesses) { //close connection [xpcConnection invalidate]; @@ -1279,7 +1282,7 @@ bail: #endif //delay, then close - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ //close [NSUserNotificationCenter.defaultUserNotificationCenter removeDeliveredNotification:notification]; @@ -1319,6 +1322,9 @@ bail: //log msg NSMutableString* logMessage = nil; + //remember popup/window controller + RememberWindowController* rememberWindowController = nil; + //always (manually) load preferences preferences = [NSDictionary dictionaryWithContentsOfFile:[APP_PREFERENCES stringByExpandingTildeInPath]]; @@ -1442,29 +1448,33 @@ bail: //bail goto bail; } - - //alloc/init settings window - if(nil == self.rememberWindowController) - { - //alloc/init - rememberWindowController = [[RememberWindowController alloc] initWithWindowNibName:@"RememberPopup"]; - } + + //alloc/init + rememberWindowController = [[RememberWindowController alloc] initWithWindowNibName:@"RememberPopup"]; //center window - [[self.rememberWindowController window] center]; + [[rememberWindowController window] center]; //show it - [self.rememberWindowController showWindow:self]; + [rememberWindowController showWindow:self]; //manually configure // ->invoke here as the outlets will be set - [self.rememberWindowController configure:notification avMonitor:self]; + [rememberWindowController configure:notification avMonitor:self]; //make it key window - [self.rememberWindowController.window makeKeyAndOrderFront:self]; + [rememberWindowController.window makeKeyAndOrderFront:self]; //make window front [NSApp activateIgnoringOtherApps:YES]; + + //save reference to window + // ->otherwise memory is freed/window not shown :/ + @synchronized (self) + { + //save + [self.rememberPopups addObject:rememberWindowController]; + } } //when user clicks 'block' @@ -1620,7 +1630,7 @@ bail: //set classes // ->arrays/numbers ok to vend [xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSNumber class], nil] - forSelector: @selector(getVideoProcs:) argumentIndex: 0 ofReply: YES]; + forSelector: @selector(getVideoProcs:reply:) argumentIndex: 0 ofReply: YES]; //resume [xpcConnection resume]; @@ -1637,7 +1647,7 @@ bail: //invoke XPC service to get (new) video procs // ->will generate user notifications for any new processes - [[xpcConnection remoteObjectProxy] getVideoProcs:^(NSMutableArray* videoProcesses) + [[xpcConnection remoteObjectProxy] getVideoProcs:YES reply:^(NSMutableArray* videoProcesses) { //dbg msg #ifdef DEBUG diff --git a/LoginItem/Info.plist b/LoginItem/Info.plist index 9ca51ab..a11238c 100644 --- a/LoginItem/Info.plist +++ b/LoginItem/Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.1 + 1.1.2 CFBundleSignature ???? CFBundleVersion - 1.1.1 + 1.1.2 LSUIElement LSMinimumSystemVersion diff --git a/LoginItem/RemeberWindowController.m b/LoginItem/RemeberWindowController.m index 7b8b84a..b854cad 100644 --- a/LoginItem/RemeberWindowController.m +++ b/LoginItem/RemeberWindowController.m @@ -20,8 +20,6 @@ @synthesize avMonitor; @synthesize processPath; -//@synthesize versionLabel; - //automatically called when nib is loaded // ->center window -(void)awakeFromNib @@ -31,7 +29,7 @@ } //automatically invoked when window is loaded -// ->set to white +// ->set to window to white -(void)windowDidLoad { //super @@ -40,9 +38,6 @@ //make white [self.window setBackgroundColor: NSColor.whiteColor]; - //set version sting - //[self.versionLabel setStringValue:[NSString stringWithFormat:@"version: %@", getAppVersion()]]; - return; } @@ -156,4 +151,24 @@ bail: return; } + +//automatically invoked when window is closing +// ->remove self from array +-(void)windowWillClose:(NSNotification *)notification +{ + //dbg msg + #ifdef DEBUG + logMsg(LOG_DEBUG, @"window is closing, will remove array reference"); + #endif + + //sync to remove + @synchronized (self.avMonitor) { + + //remove + [self.avMonitor.rememberPopups removeObject:self]; + } + + return; +} + @end diff --git a/LoginItem/StatusBarMenu.m b/LoginItem/StatusBarMenu.m index f8b98d0..7c38979 100644 --- a/LoginItem/StatusBarMenu.m +++ b/LoginItem/StatusBarMenu.m @@ -8,11 +8,11 @@ #import "Consts.h" #import "Logging.h" +#import "Utilities.h" #import "AppDelegate.h" #import "XPCProtocol.h" #import "StatusBarMenu.h" - #import #import @@ -239,14 +239,17 @@ //resume [xpcConnection resume]; - //tell XPC about audio status - // ->for example, when audio is active, will stop baselining + //tell XPC to exit [[xpcConnection remoteObjectProxy] exit]; //give it a sec for XPC msg to go thru - // ->can't wait on XPC since its killing itself! + // ->don't wait on XPC since its killing itself! [NSThread sleepForTimeInterval:0.10f]; + //kill main (preference) app + // ->might be open, and looks odd if its still present + execTask(PKILL, @[[APP_NAME stringByDeletingPathExtension]], YES); + //bye! [[NSApplication sharedApplication] terminate:nil]; diff --git a/MainApp/Info.plist b/MainApp/Info.plist index 50fdb7f..26919b0 100644 --- a/MainApp/Info.plist +++ b/MainApp/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.1 + 1.1.2 CFBundleSignature ???? CFBundleVersion - 1.1.1 + 1.1.2 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) LSUIElement diff --git a/MainApp/Rules.xib b/MainApp/Rules.xib index cdc4387..c5204fc 100644 --- a/MainApp/Rules.xib +++ b/MainApp/Rules.xib @@ -144,8 +144,12 @@ + + + + diff --git a/OverSightXPC/Enumerator.h b/OverSightXPC/Enumerator.h index b0d6150..88df0f1 100644 --- a/OverSightXPC/Enumerator.h +++ b/OverSightXPC/Enumerator.h @@ -64,7 +64,7 @@ -(NSMutableArray*)enumAudioProcs; //enumerate all (recent) process that appear to be using video --(NSMutableArray*)enumVideoProcs; +-(NSMutableArray*)enumVideoProcs:(BOOL)polling; //set status of audio -(void)updateAudioStatus:(BOOL)isEnabled; diff --git a/OverSightXPC/Enumerator.m b/OverSightXPC/Enumerator.m index 22d27e7..36087ee 100644 --- a/OverSightXPC/Enumerator.m +++ b/OverSightXPC/Enumerator.m @@ -161,7 +161,7 @@ static NSArray* ignoredProcs = nil; } //enumerate all (recent) process that appear to be using video --(NSMutableArray*)enumVideoProcs +-(NSMutableArray*)enumVideoProcs:(BOOL)polling { //current procs NSMutableArray* videoProcs = nil; @@ -176,6 +176,9 @@ static NSArray* ignoredProcs = nil; //pid of camera assistant process pid_t cameraAssistant = 0; + //'frontmost' application + pid_t activeApp = -1; + //alloc candidateVideoProcs = [NSMutableArray array]; @@ -237,6 +240,30 @@ static NSArray* ignoredProcs = nil; //update self.machSendersVideo = currentSenders; + + //didn't find any? + // ->when not polling, add foreground process (and sample it below) + if( (0 == candidateVideoProcs.count) && + (YES != polling)) + { + //dbg msg + #ifdef DEBUG + logMsg(LOG_DEBUG, @"didn't find any candidate video apps, and not polling, so will grab (and sample) active application"); + #endif + + //get active app + activeApp = frontmostApplication(); + if(-1 != activeApp) + { + //dbg msg + #ifdef DEBUG + logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found active application: %d", activeApp]); + #endif + + //add it + [candidateVideoProcs addObject:[NSNumber numberWithInt:activeApp]]; + } + } //invoke 'sample' to confirm that candidates are using CMIO/video inputs // ->note, will skip FaceTime.app on macOS Sierra, as it doesn't do CMIO stuff directly @@ -278,6 +305,9 @@ bail: //pid of coreaudio process pid_t coreAudio = 0; + //'frontmost' application + pid_t activeApp = -1; + //alloc array newSenders = [NSMutableArray array]; @@ -439,9 +469,9 @@ bail: logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found %lu candidate audio procs: %@", (unsigned long)candidateAudioProcs.count, candidateAudioProcs]); #endif - //only once candidate? + //only one candidate? // ->all set, so assign, then bail here - if(candidateAudioProcs.count <= 1) + if(1 == candidateAudioProcs.count) { //assign audioProcs = candidateAudioProcs; @@ -449,8 +479,31 @@ bail: //bail goto bail; } - - //got more than one candidate + + //still none + // ->add active app as candiate (and sample it, below) + if(0 == candidateAudioProcs.count) + { + //dbg msg + #ifdef DEBUG + logMsg(LOG_DEBUG, @"didn't find any candidate audio apps, will grab (and sample) active application"); + #endif + + //get active app + activeApp = frontmostApplication(); + if(-1 != activeApp) + { + //dbg msg + #ifdef DEBUG + logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found active application: %d", activeApp]); + #endif + + //add it + [candidateAudioProcs addObject:[NSNumber numberWithInt:activeApp]]; + } + } + + //got one or more candidate application // ->invoke 'sample' to determine which candidate is using CMIO/video inputs // note: will skip FaceTime.app on macOS Sierra, as it doesn't do CMIO stuff directly audioProcs = [self sampleCandidates:candidateAudioProcs]; diff --git a/OverSightXPC/Info.plist b/OverSightXPC/Info.plist index 355b99d..ba51a3b 100644 --- a/OverSightXPC/Info.plist +++ b/OverSightXPC/Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 1.1.1 + 1.1.2 CFBundleSignature ???? CFBundleVersion - 1.1.1 + 1.1.2 NSHumanReadableCopyright Copyright (c) 2017 Objective-See. All rights reserved. XPCService diff --git a/OverSightXPC/OverSightXPC.m b/OverSightXPC/OverSightXPC.m index d08699e..4da7fa8 100644 --- a/OverSightXPC/OverSightXPC.m +++ b/OverSightXPC/OverSightXPC.m @@ -33,10 +33,10 @@ } //call into emumerate to get (new) video proc --(void)getVideoProcs:(void (^)(NSMutableArray *))reply +-(void)getVideoProcs:(BOOL)polling reply:(void (^)(NSMutableArray *))reply { //reply w/ video procs - reply([[Enumerator sharedManager] enumVideoProcs]); + reply([[Enumerator sharedManager] enumVideoProcs:polling]); return; } diff --git a/Shared/Utilities.h b/Shared/Utilities.h index fddc5e8..5a1f60b 100644 --- a/Shared/Utilities.h +++ b/Shared/Utilities.h @@ -80,4 +80,7 @@ pid_t findProcess(NSString* processName); //convert a textview to a clickable hyperlink void makeTextViewHyperlink(NSTextField* textField, NSURL* url); +//get active application +pid_t frontmostApplication(); + #endif diff --git a/Shared/Utilities.m b/Shared/Utilities.m index 68dd864..02f32ff 100644 --- a/Shared/Utilities.m +++ b/Shared/Utilities.m @@ -1127,3 +1127,10 @@ void makeTextViewHyperlink(NSTextField* textField, NSURL* url) return; } +//get frontmost (active) app +pid_t frontmostApplication() +{ + //get/ret + return NSWorkspace.sharedWorkspace.frontmostApplication.processIdentifier; +} + diff --git a/Shared/XPCProtocol.h b/Shared/XPCProtocol.h index 0db74c1..5f37554 100644 --- a/Shared/XPCProtocol.h +++ b/Shared/XPCProtocol.h @@ -18,7 +18,7 @@ -(void)getAudioProcs:(void (^)(NSMutableArray *))reply; //get (new) video procs --(void)getVideoProcs:(void (^)(NSMutableArray *))reply; +-(void)getVideoProcs:(BOOL)polling reply:(void (^)(NSMutableArray *))reply; //update status video // ->allows enumerator to stop baselining (when active), etc