Setting NSSavePanel's directoryURL property to a directory inside a sandboxed app container does not work (actually sets the directoryURL to the "real" Documents directory.

Setting NSSavePanel's directoryURL property to a directory inside a sandboxed app container does not work (actually sets the directoryURL to the "real" Documents directory.


NSURL *containerDocsDir = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;



//...code here..
//set the default save location for a savepanel..
savePanel.directoryURL = containerDocsDir;


This is a problem. If a Service takes a directory as input to set a default save location for a file that is to be saved by NSSavepanel, it won't behave as expected.

Replies

The powerbox is designed to bridge the "real" world with the sandbox world. You don't want people navigating around inside your container. They will scramble your app for sure that way.

Well, consider this:


1) A sandboxed app provides a user interface that allows users to choose files inside the "Sandboxed container" documents directory.

2) That same sandboxed app shows the Services menu. And now we have a Service that accepts a directory as a Send type.

3) So the user fires the Service via the Services menu, then the Service provider gets the directory sent by the user as input and sets up a Save panel to use this directory as the default save location for some action.


NSSavePanel doesn't honor the 'real path' of the directory, which seems wrong. In my testing, the Service provider and the app launching the Service are the same app. So in this case, I don't need a save panel to write to the directory, but another app may pass the sandboxed app a location where a save panel is required. Having a separate code path to check if the directory is in a sandboxed container seems silly.


In any case, this is the user's Mac. And if the user is savvy enough to navigate inside a sandboxed container's Documents directory and chooses to fire a Service from a Finder window (or another app) I feel like the directory path should be honored. But maybe I'm crazy.

The "Documents" folder inside the container is meant to be a private area for the app itself, not the user. You could use it à la iOS with a custom file browser, omitting the Finder altogether.


Otherwise, you are living in really dangerous land. The Finder, powerbox, services, sandboxed app all cross the sandbox barrier multiple times. What you are asking is essentially the opposite of what most people have traditionally wanted from these bridging gateways.


I don't really understand what you are doing, so I can't give specific tips. But, in general, I would say that your sandbox container is owned by the app and shouldn't never have the user, or especially some other app, digging around in it. If you need to exchange data (with either the user or other apps), use the user-level folders dedicated to that purpose. It sounds like the powerbox is trying to help you do that. Otherwise, your app is going to get scrambled.

>The "Documents" folder inside the container is meant to be a private area for the app itself, not the user. You could use it à la iOS with a custom file browser, omitting the Finder altogether.


By that definition, the "Documents" folder in a sandboxed app virtually is no different than the Application Support directory. I think it's okay to use it that way In any case, sometimes apps want to allow users to drag and drop files to them, to move files into a directory that the app manages and/or use Services on their files that happen to be in this directory (the only directory a sandboxed app can write to without showing a permissions dialog). The purpose of the files in this directory inside my sandboxed container is defined by my app and the user.


Anyway I didn't create this thread to argue about what my app is doing. You seem to be making excuses for what I consider to be a bug. I don't see why NSSavePanel would redirect the path of a sandboxed container's Documents folder to the "real" documents directory. This actually seems like a way a malicious developer could trick the user into accessing a directory that doesn't belong to him.


1) Create a sandboxed app. Make a documents folder in code (so a Documents folder in the sandboxed container).

2) Have the sandboxed app create a folder named "Chicken" inside the documents directory of the sandboxed container.

3) Create a folder named "Chicken" in the real documents directory in Finder.

4) In the sandboxed app, show an NSSavePanel and set the directoryURL to the Chicken URL (of the sandboxed container).

5) See that the directoryURL in the save panel shown points to "Chicken" in the real Documents folder.


This is what I noticed in debug mode. Maybe I had navigated to the "real directory" and state restoration brought it back on a previous launch; didn't have time to test it thoroughly.


I'm no security nut, the user still has to hit "Save" in the save panel to write to "Chicken" but the behavior doesn't really make sense. Just have the save panel point to the directoryURL that it was told. That's the fix. I almost don't want to mention it because I fear Apple will take away the directoryURL property entirely or throw up a permissions dialog on top of the save panel, something like:

This app wants to set the save location to your folder named "Ciicken". Confirm or Deny


A dialog asking for permission on top of the save panel (which is a dialog asking for permission).


Really, i'm just trying to use the same code path (to handle implementing a Service that can *write* anywhere the *user* wants me to write via NSSavePanel. My app also happens to use the Service it provides itself when fired on files in my own sandboxed container. And *I know* I don't need the save panel to write in this directory, but it just seems silly that I'm *not allowed* to use it.

You can consider it to be a bug all you want. Go ahead and file a bug report. It won't be fixed - ever. How does that help?


I am not making excuses for anything. I am just trying to suggest better ways to use these directories. Most users have no clue the sandbox even exists. They don't know there are multiple document directories. The powerbox save/open panels are for user files. It is reasonable to assume that if you ask the system for the "documents" folder for the "user" that it should return what the user expects. That is what it is doing. You could argue that the API needs a new "sandbox" domain that would behave the way you want.


Apple already considers the ability to read and write arbitrary files to be a security risk. That is why there is a special entitlement for it.


It is not possible for the "user" to specify this folder at all. It is in a hidden directory. Your app is the one that is specifying this folder and attempting to suggest it for the user. If you want to write to this folder, just do it. There's nothing stopping you.

>Apple already considers the ability to read and write arbitrary files to be a security risk. That is why there is a special entitlement for it.


I'm not reading and writing arbitrary files though. The user explicitly gave my app permission to do something via the Services menu. When the user passes a file to a service (if the service accepts file types) he has granted permission.


>It is not possible for the "user" to specify this folder at all. It is in a hidden directory.


This technically isn't true (for now). The user can use "Go to Folder" in Finder and go to the path or even view the contents of the Library folder on macOS (yes, the user *can* still unhide the Library folder and add it to the Finder sidebar). And if you expand a save panel (or use the path pop up button) the user could dig all the way to any sandboxed app's container and move files in and out as he pleases. Just setting directoryURL doesn't work.

Yes. I know that. But Apple's APIs do not assume that any customers know about those shortcuts. I suggest that you review how users are going to be interacting with your app. In addition to not knowing about shift-command-., most users have no idea what a "service" is either. You can pass files between apps and services all day long. That's not the issue. You are trying to involve a very specific part of the user/sandbox interface in your file passing. That is simply not going to work. You can beat your head against the wall for weeks trying to make it work. All you will get is failure and a concussion. Just re-do UX and be done with it.

>Yes. I know that. But Apple's APIs do not assume that any customers know about those shortcuts. I suggest that you review how users are going to be interacting with your app. In addition to not knowing about shift-command-., most users have no idea what a "service" is either.


Lots of users use Services. A small percentage but they are important users, perhaps the most important users (they are interested in productive computing).


>You can beat your head against the wall for weeks trying to make it work. All you will get is failure and a concussion. Just re-do UX and be done with it.


No doubt about that. The behavior of the save panel here just doesn't seem to make sense to me. I usually post here for a couple reasons:

1) See if anyone from Apple will weigh in. because a large majority of bug reports can go unanswered for years.

2) See if someone else ran into something similar and knows of a workaround.


Not head beating for weeks on this issue. But figured I'd just put it out here, to talk.

Sometimes Apple engineers do chime in. Sometimes I even try to spout off in hopes of annoying one of them enough to jump in and correct me. But no luck this time.


If you have a question that can only be answered by Apple, you can always file a DTS request.