RFR 7199674: (props) user.home property does not return an accessible location in sandboxed environment [macosx]

David DeHaven david.dehaven at oracle.com
Tue Sep 10 22:36:32 UTC 2013

> I use user.home to do things like:
> String userHomePath = System.getProperty("user.home");
> myFileDialog.setDirectory(userHomePath + "/Documents");

This will continue to work fine. Like I said, user.home is the Data directory inside the app container which is a shadow of the users home folder, complete with symlinks to common user directories (such as Documents, Movies, Music, etc..). Sandboxd and powerbox manage all the translations behind the scene.

> In my app, the user selects where he wants to export individual files, such as CSVs and PDFs. These are files he'll use outside of my app.
> If user.home points to the app's sandbox Container, it will break this usage.  Opening a file dialog to /Users/Bob/Library/Containers/my.app/Data/Documents will definitely confuse the user and if they save a file there, they will never be able to find it later from outside of my app.

The user won't know the difference, all they'll see is ~/Documents as provided by powerbox.

Fun fact: The reason powerbox isn't hackable is it runs in a separate process...

> Yes, I understand the whole sandboxing concept. I'm not asking for unrestricted access to the file system. I use the "com.apple.security.files.user-selected.read-write" entitlement so that the user can select where he wants to save files, and I want to present him with a standard, well-known, default location for that (like ~/Documents). 
> If user.home doesn't point to the user's actual home folder (i.e. NSHomeDirectoryForUser), it makes creating a standard, well-known location path (like ~/Documents) much more difficult.  (And IMHO, it breaks the definition of the user.home property: "User home directory", not "App home directory".)

Powerbox solves exactly that problem... and yes, yes it is users home folder, from the perspective of a sandboxed application!

Here's some code to prove it actually works since you don't seem to believe me:
    @autorelease {
        NSOpenPanel *panel = [NSOpenPanel openPanel];
        panel.allowsMultipleSelection = NO;
        panel.canChooseDirectories = NO;

        NSString *home = NSHomeDirectory();
        NSString *docs = [home stringByAppendingPathComponent:@"Downloads"];
        NSLog(@"home: %@", home);
        NSLog(@"docs: %@", docs);

        [panel setDirectoryURL:[NSURL fileURLWithPath:docs]];
        [panel beginWithCompletionHandler:^(NSInteger result) {
            NSLog(@"panel result: %ld", result);
            if (result == NSFileHandlingPanelOKButton) {
                NSLog(@"panel selected file: %@", [[panel URLs] objectAtIndex:0]);

Example run:
2013-09-10 15:30:52.630 BlahText[11480:303] home: /Users/daved/Library/Containers/com.blah.SomeApp/Data
2013-09-10 15:30:52.631 BlahText[11480:303] docs: /Users/daved/Library/Containers/com.blah.SomeApp/Data/Documents
2013-09-10 15:30:59.180 BlahText[11480:303] panel result: 1
2013-09-10 15:30:59.180 BlahText[11480:303] panel selected file: file://localhost/Users/daved/Documents/Some%20Document.txt

And the open panel opens displaying the contents of my Documents folder, the user will never see the app container path unless you explicitly report it to them.


More information about the core-libs-dev mailing list