objective-cmacososx-lionnsopenpanelappstore-sandbox

Trouble creating Security-Scoped Bookmark


I'm converting my Lion app to use the App Sandbox. I'm trying to make use of the security-scoped bookmarks feature introduced in 10.7.3 to allow persistent access to a folder. The code I have below returns a nil bookmark, and produces the following log message: XPC couldn't look up the Mach service for scoped bookmarks agent.

I set the User Selected File Access entitlement to Read/Write Access, and also tried with and without the surrounding ..AccessingSecurityScopedResource calls.

I think I'm doing everything right according to the documentation, so I'd appreciate any pointers. The code was working to retrieve a plain URL before I began sandboxing the app.

NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setCanChooseFiles:NO];
[openPanel setCanChooseDirectories:YES];
[openPanel setAllowsMultipleSelection:NO];

NSInteger result = [openPanel runModal];

if( result == NSFileHandlingPanelCancelButton ) {
    return;
}

NSArray *urls = [openPanel URLs];

if( urls != nil && [urls count] == 1 ) {
    NSURL *url = [urls objectAtIndex:0];

    NSData *bookmark = nil;
    NSError *error = nil;
    bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
             includingResourceValuesForKeys:nil
                              relativeToURL:nil // Make it app-scoped
                                      error:&error];
    if (error) {
        NSLog(@"Error creating bookmark for URL (%@): %@", url, error);
        [NSApp presentError:error];
    }

    NSLog(@"bookmark: %@", bookmark);
}

Update (x3)

Now that I got it working, I can verify that the calls to -startAccessingSecurityScopedResource and -stopAccessingSecurityScopedResource are not necessary in the code above, since the Powerbox grants access to the resource after the user selects it in the NSOpenPanel.

If you're creating a bookmark from another security-scoped URL, such as making a document-scoped bookmark from an app-scoped bookmark created in another app session, then you need to get access to the file first.


Solution

  • It turns out I was missing a crucial entitlement, not listed in the UI, but listed in the documentation:

    com.apple.security.files.bookmarks.app-scope
    

    Update 12/18/2018

    According to this Twitter thread, this entitlement may not be required anymore. Thanks @pkamb for alerting me to this.