Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing Apple Sandbox security-scoped bookmarks

I am creating a application which is reading files outside the application sandbox. I need the user's permission to read these files and I have got the security-scoped bookmarks to work, by making the user pick the path in a NSOpenPanel.

My problem is that I don't want the user to give me permission every time the application accesses the same path. I am saving the bookmarks in the NSApplicationSupportDirectory folder.

This works fine until the user restarts the computer, then it seems like the saved bookmarks become invalid. The bookmark data looks completely fine when loaded from the disk, but the application requires new security-scoped bookmarks to read the files even though the application is using a bookmark for the path which worked before the restart.

I am creating the bookmarks like this:

NSData * bookmark  = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&err];
NSURL* bookmarkUrl = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&err]

I am checking if the bookmark is accessible with the following:

[url startAccessingSecurityScopedResource];
[[NSFileManager defaultManager] contentsOfDirectoryAtURL:url includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsHiddenFiles error:&err]

if (err && err.code == NSFileReadNoPermissionError)
{
    NSLog(@"No URL access");
    res = NO;
}
else if(err)
{
    NSLog(@"URL validate unexpected error:%@", err);
    res = NO;
}

if (res)
{
    //Bookmark works!
}
[url stopAccessingSecurityScopedResource];

This works as long as I don't restart the Mac. I can quit the application and start it again and my bookmarks still work. But as soon as the Mac is restarted I get the NSFileReadNoPermissionError error even though I am using the saved bookmark that worked before I restarted.

Is there a way to create a bookmark that works when the Mac has been restarted?

like image 747
ThomasCle Avatar asked Jun 17 '14 07:06

ThomasCle


1 Answers

It turned out I had failed to have balance between start and stop invokations. As the documentation of startAccessingSecurityScopedResource states, this can make the booksmarks invalid:

Warning: You must balance every call to the startAccessingSecurityScopedResource method with a corresponding call to the stopAccessingSecurityScopedResource method. If you fail to relinquish your access when you no longer need a file-system resource, your app leaks kernel resources. If sufficient kernel resources are leaked, your app loses its ability to add file-system locations to its sandbox, such as via Powerbox or security-scoped bookmarks, until relaunched.

I also ended up storing the bookmarks in NSUserDefaults instead of a file in the NSApplicationSupportDirectory folder.

like image 50
ThomasCle Avatar answered Oct 29 '22 17:10

ThomasCle