From 02c5ccaae127507145a164619a717753df4ba1ea Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Fri, 9 Dec 2022 21:12:33 -0800 Subject: [PATCH] Sandbox: Rework several blocking actions Several actions have been reworked to be non-blocking, as their operation should still occur in the main thread, but should not block the thread they are called from, as they are not required to continue processing there. End of secure access has also been made non-blocking, as it is usually only called when an input is done accessing a given file or folder, so it should be important to return quickly, as the input is likely about to terminate, and other things are waiting for it to return. Also remove a nested block call for the storage access, as it is within an existing serializing block, so it shouldn't need to be nested. Signed-off-by: Christopher Snowhill --- Utils/SandboxBroker.m | 86 +++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/Utils/SandboxBroker.m b/Utils/SandboxBroker.m index 8db77fde2..7683f2876 100644 --- a/Utils/SandboxBroker.m +++ b/Utils/SandboxBroker.m @@ -218,10 +218,18 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc } } +static inline void dispatch_async_reentrant(dispatch_queue_t queue, dispatch_block_t block) { + if(dispatch_queue_get_label(queue) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)) { + block(); + } else { + dispatch_async(queue, block); + } +} + - (void)addFolderIfMissing:(NSURL *)folderUrl { if(![folderUrl isFileURL]) return; - dispatch_sync_reentrant(dispatch_get_main_queue(), ^{ + dispatch_async_reentrant(dispatch_get_main_queue(), ^{ SandboxEntry *_entry = nil; for(SandboxEntry *entry in self->storage) { @@ -263,7 +271,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc NSURL *url = [SandboxBroker urlWithoutFragment:fileUrl]; - dispatch_sync_reentrant(dispatch_get_main_queue(), ^{ + dispatch_async_reentrant(dispatch_get_main_queue(), ^{ SandboxEntry *_entry = nil; for(SandboxEntry *entry in self->storage) { @@ -322,49 +330,47 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc } if(!_entry) { - dispatch_sync_reentrant(dispatch_get_main_queue(), ^{ - static BOOL warnedYet = NO; + static BOOL warnedYet = NO; - if(!warnedYet) { - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:NSLocalizedString(@"GrantPathTitle", @"Title of file dialog for granting folder access")]; - [alert setInformativeText:NSLocalizedString(@"GrantPathMessage", @"Message to new users regarding file permissions")]; - [alert addButtonWithTitle:NSLocalizedString(@"GrantPathOK", @"OK button text")]; - [alert addButtonWithTitle:NSLocalizedString(@"GrantPathStopWarning", @"Button to stop warnings for session")]; + if(!warnedYet) { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:NSLocalizedString(@"GrantPathTitle", @"Title of file dialog for granting folder access")]; + [alert setInformativeText:NSLocalizedString(@"GrantPathMessage", @"Message to new users regarding file permissions")]; + [alert addButtonWithTitle:NSLocalizedString(@"GrantPathOK", @"OK button text")]; + [alert addButtonWithTitle:NSLocalizedString(@"GrantPathStopWarning", @"Button to stop warnings for session")]; + + if([alert runModal] == NSAlertSecondButtonReturn) { + warnedYet = YES; + } + } - if([alert runModal] == NSAlertSecondButtonReturn) { - warnedYet = YES; - } + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setAllowsMultipleSelection:NO]; + [panel setCanChooseDirectories:YES]; + [panel setCanChooseFiles:NO]; + [panel setFloatingPanel:YES]; + [panel setDirectoryURL:folderUrl]; + [panel setTitle:NSLocalizedString(@"GrantPathTitle", @"Title of file dialog for granting folder access")]; + NSInteger result = [panel runModal]; + if(result == NSModalResponseOK) { + NSURL *folderUrl = [panel URL]; + NSError *err = nil; + NSData *bookmark = [folderUrl bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&err]; + if(!bookmark && err) { + ALog(@"Failed to add bookmark for URL: %@, with error: %@", folderUrl, [err localizedDescription]); + return; } - NSOpenPanel *panel = [NSOpenPanel openPanel]; - [panel setAllowsMultipleSelection:NO]; - [panel setCanChooseDirectories:YES]; - [panel setCanChooseFiles:NO]; - [panel setFloatingPanel:YES]; - [panel setDirectoryURL:folderUrl]; - [panel setTitle:NSLocalizedString(@"GrantPathTitle", @"Title of file dialog for granting folder access")]; - NSInteger result = [panel runModal]; - if(result == NSModalResponseOK) { - NSURL *folderUrl = [panel URL]; - NSError *err = nil; - NSData *bookmark = [folderUrl bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&err]; - if(!bookmark && err) { - ALog(@"Failed to add bookmark for URL: %@, with error: %@", folderUrl, [err localizedDescription]); - return; - } + NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer]; - NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer]; + SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext]; - SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext]; - - if(token) { - token.path = [folderUrl path]; - token.bookmark = bookmark; - [SandboxBroker cleanupFolderAccess]; - } + if(token) { + token.path = [folderUrl path]; + token.bookmark = bookmark; + [SandboxBroker cleanupFolderAccess]; } - }); + } } }); } @@ -376,7 +382,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SandboxToken"]; request.sortDescriptors = @[sortDescriptor]; - [pc.viewContext performBlockAndWait:^{ + [pc.viewContext performBlock:^{ NSError *error = nil; NSArray *results = [pc.viewContext executeFetchRequest:request error:&error]; NSMutableArray *resultsCopy = nil; @@ -455,7 +461,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc SandboxEntry *entry = CFBridgingRelease(handle); if(!entry) return; - dispatch_sync_reentrant(dispatch_get_main_queue(), ^{ + dispatch_async_reentrant(dispatch_get_main_queue(), ^{ if(entry.refCount > 1) { entry.refCount -= 1; } else {