Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: File Dialogs can't access Documents area in sandboxed Mac apps


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 11 - Last Post: Nov 21, 2014 3:40 PM Last Post By: Grant Beattie
Grant Beattie

Posts: 77
Registered: 11/29/01
File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 11, 2014 2:21 PM
When I run my OS X app in Normal configuration, the value returned from Ioutils::TPath::GetDocumentsPath() is:
/Users/MyUserName/Documents

I can set OpenDialog and SaveDialog InitialDirs to this value and when the app executes they open in the correct spot.

Now when I code-sign and sandbox my application (the AppStore case) the value returned from Ioutils::TPath::GetDocumentsPath() is:
Users/MyUserName/Library/Containers/MyApplication/Data/Documents

This is correct for a sandboxed app. I can set OpenDialog and SaveDialog InitialDirs to this value BUT when app executes that's not where they open. Instead they open in the spot shown above (Normal execution case).

I have an Entitlement set for "read/write access to file selected with the Open or Save dialog" = true. I don't think this is the issue. The InitialDir value holds the correct path in both the Normal case and AppStore case. I can read it back and verify it. The file Dialogs just seem to ignore the sandboxed path in the AppStore case and use the general users documents path instead of the sandboxed one.

Anyone able to successfully get their app dialogs to access the sandboxed documents area? And/or is there some other approach I should be taking? I don't see any other entitlements.

I see the same behaviour in Mountain Lion and Mavericks, Delphi and C++.

Edited by: Grant Beattie on Nov 20, 2014 6:37 AM
Grant Beattie

Posts: 77
Registered: 11/29/01
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 12, 2014 7:07 AM   in response to: Grant Beattie in response to: Grant Beattie
And maybe someone at Embarcadero should update
http://docwiki.embarcadero.com/RADStudio/XE7/en/Standard_RTL_Path_Functions_across_the_Supported_Target_Platforms
to mention that the paths on this page change when you sandbox your application. I admit I'm a newbie, but this really surprised me.

And just to be clear, I don't care whether my documents are stored in the user's documents area or the container, but I need open/save dialog functionality that matches the directories I'm given to use (at the startup of my program I copy some example files there from my bundle ... which by the way works fine).

Edited by: Grant Beattie on Nov 12, 2014 8:57 AM
Douglas Rudd

Posts: 314
Registered: 5/16/97
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 12, 2014 11:45 AM   in response to: Grant Beattie in response to: Grant Beattie
Here is a useful post:
http://www.cocoabuilder.com/archive/cocoa/323090-app-sandbox-container-or-data-directory.html
This is an Apple Sandboxing limitation.

Yes, the open/save panels automatically translate any locations form within the container to outside. Anything within the container is not intended for regular users to see.
Are you aware that, by default, all of ~/Library is hidden from the user, and it's basically expected that he won't go in that folder?

I assume all you want is just a good place for the user to save his files and retrieve them - it doesn't matter where it is.

It will be easier to put things in the regular Documents directory.

Using "Documents/" will work just as good:
procedure TForm8.Button1Click(Sender: TObject);
begin
 OpenDialog1.InitialDir:='Documents/';
 if OpenDialog1.Execute then
 begin
    Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
 end;
end;
 
procedure TForm8.Button2Click(Sender: TObject);
begin
   Savedialog1.InitialDir:= 'Documents/';
  if SaveDialog1.Execute then
   begin
     Memo1.Lines.SaveToFile(SaveDialog1.FileName);
   end;
Grant Beattie

Posts: 77
Registered: 11/29/01
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 12, 2014 3:15 PM   in response to: Douglas Rudd in response to: Douglas Rudd
Douglas Rudd wrote:
Here is a useful post:
http://www.cocoabuilder.com/archive/cocoa/323090-app-sandbox-container-or-data-directory.html
This is an Apple Sandboxing limitation.

An interesting take away: "Your app could generate “documents” which get stored on disk in the Documents folder, but provide its own UI for managing that data perhaps, rather than the standard open/save panel approach."

Kill me now. This has occurred to me but was thinking there must be a correct approach rather than rolling my own. I'm looking for that magic combination of where the user gets to use the open and save dialogs like the rest of the Mac apps and I can access the data from within my code too (obviously). It's also not lost on me that some of these conversations are 2 years old.

Douglas Rudd wrote:
I assume all you want is just a good place for the user to save his files and retrieve them - it doesn't matter where it is.
Using "Documents/" will work just as good:

I will investigate further, but at first glance I will say close but no cigar. I can update this post as I get more time. Aside from the open and save dialogs I do need to create at least one directory (preferably more) so that I don't pollute the Docs area root with all the users files. Also at startup, the first time, I need to copy some example files (and so on) from my bundle.

So, in a nutshell and to summarize, files and directories I access programatically using things like Ioutils::TFile::Copy(), CreateDir(), and even TIniFile all go where expected and always work well.
- in Normal Configuration they go in /Users/username/Documents,
- and in the App Store configuration they go in the Library/Containers area.
(I have some fopen/fputc/fclose stuff too that I haven't verified sandboxed yet).

TOpenDialog and TSaveDialog seem to use /Users/username/Documents seemingly regardless of what I put in InitialDir within reason. I can just leave InitialDir blank and get the same result.

I cannot create a directory in /Users/username/Documents, (I think that's only in the sandboxed case but that's what I need). I can create a directory in the container in the sandboxed case. I will double check.

EDIT: I can create a directory in the proper path /Users/username/Documents in Normal config, but using Documents/ gets me nowhere. Not sure what your original intent was there. I think InitialDir is not really using Documents/ but perhaps you didn't mean that literally. From within the sandbox I cannot get the value /Users/username/Documents unless I carve up the path to remove the "libray" and "containers" parts and I'm sure that's going to change in the future knowing Apple. If I could get the "username" that would help. Still don't know of I could do anything from the sandbox.

So although using "Documents/" seems like a good idea, I can't do what I want there from within the sandbox. None of my startup stuff or runtime stuff works there. Only the dialogs.

I tried to make some headway with NSOpenPanel but I'm not there yet. I'm talking through my hat here but there seems to be some issue with this PowerBox thing and firemonkey's implementation or use of the open and save dialogs.

Again I will try and correct this post for any mistakes as I find them.

Edited by: Grant Beattie on Nov 12, 2014 3:58 PM
Grant Beattie

Posts: 77
Registered: 11/29/01
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 13, 2014 12:32 PM   in response to: Grant Beattie in response to: Grant Beattie
So I verified some of the access restrictions and how the TOpenDialog and TSaveDialog abuse them (or us depending on your point of view).

If I explicitly try and access, for example, "/Users/username/Documents/Test.txt" from within a sandboxed app (ignoring for a moment that that path is not obtainable through traditional means),

Memo1->Lines->LoadFromFile("/Users/username/Documents/Test.txt");


then I get "Operation not permitted." However if I do something like Douglas is doing above and access the very same file using,

if( SaveDialog1->Execute() )
    Memo1->Lines->SaveToFile(SaveDialog1->FileName);


Then I can go back later and access the file directly using

Memo1->Lines->LoadFromFile("/Users/username/Documents/Test.txt");


So for sure the permission has been granted by the user using the dialog. This matches documentation I have read. So as interesting as this is, it doesn't help me with my objectives (accessing the same files area as the dialogs, but programatically and before the user is involved at all). You know, basic computer programming stuff. ;-)

Also I'm pretty sure using "Documents/" does nothing constructive. I can leave InitialDir blank and get the same functionality. In the sandbox I end up writing to an area I can't get to with the dialogs. I did a bunch of experiments and saved the various responses to a file for posterity.

So my options are:

- Try and get something useful out of NSPanel.
- Write my own file picker.
- Wait for Embarcadero to fix the problem or give us another path forward.
- ?
Douglas Rudd

Posts: 314
Registered: 5/16/97
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 13, 2014 1:16 PM   in response to: Grant Beattie in response to: Grant Beattie
If I create the folder first, either programmatically or in Finder, then I can put that in InitialDir and the open dialog will go there.
OpenDialog1.InitialDir:= 'Documents/MySpecialFolder/';
Grant Beattie

Posts: 77
Registered: 11/29/01
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 13, 2014 1:38 PM   in response to: Douglas Rudd in response to: Douglas Rudd
Douglas Rudd wrote:
If I create the folder first, either programmatically or in Finder, then I can put that in InitialDir and the open dialog will go there.
OpenDialog1.InitialDir:= 'Documents/MySpecialFolder/';

First of all, thanks a lot for sticking it out with me. How are you creating the folder programmatically? Without supplying some realistic path I can't seem to make it (other than in the bundle).

I might try focusing on this angle. As goofy as TOpenDialog is (versus my apps permissions) I actually prefer placing my files in the vanilla user docs area. Also it gives the user the option of placing on the desktop or external drive. I mean once my files go into the container, they'll never find them if they want to copy them to a thumb drive or something.

Curious that I don't see this functionality: http://i.stack.imgur.com/2aIxw.png

Edited by: Grant Beattie on Nov 13, 2014 3:58 PM
Douglas Rudd

Posts: 314
Registered: 5/16/97
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 13, 2014 6:54 PM   in response to: Grant Beattie in response to: Grant Beattie
I was wrong. You cant create it programmatically. I did it with finder.
Info I have been reading verifies all the things you have been saying.

Because your app cant put any files anywhere were you can set the Opendialog.InitialDir anyway. And the sandbox docs say that there is no way for your app to get a filename from the user unless the user browses there himself. Some said the user cant even type in a path in an edit box and use it.

Previously, you said:
My code needs to copy some files from my bundle into the/any user Docs area at startup, the first time it runs. And I need to alter the content of one or more of those files, all with no user intervention.

According to Apple, this is impossible.
Grant Beattie

Posts: 77
Registered: 11/29/01
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 14, 2014 6:23 AM   in response to: Douglas Rudd in response to: Douglas Rudd
If only we could get this functionality

http://i.stack.imgur.com/2aIxw.png

Then I can do the file copy after some user intervention. From what I can tell "our" open dialog only gives us access to one file and only for that session. Again I'm guessing Embarcadero is using an outdated API for their file dialogs.

So failing that I guess if I could improve the non-sandboxed experience as much as possible. That means trying to fix the thing that started this whole mess.

http://i.imgur.com/omQVPrd.png

The empty file list.

But again it seems to be the fault of the open dialog. I guess the only way forward is to get TNSOpenPanel/NSOpenPanel going somehow or living with the issues.

---

Another thing I need to look at too is what the behaviour is if I take the same app and download it from the web. I've run into surprises before when testing an app the way a user would receive it rather than in the IDE/PAServer areas.

Edited by: Grant Beattie on Nov 14, 2014 6:44 AM
Grant Beattie

Posts: 77
Registered: 11/29/01
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 17, 2014 10:33 AM   in response to: Grant Beattie in response to: Grant Beattie
It looks like XE7 Update 1 might solve a few issues with sandboxing (build/deploy only), perhaps the Dylib contents out of order thing (fingers crossed) ... although JWWalker's "hack" seems to work OK.

EDIT: No improvement that I could find. I'm now (still) using the "fixed" dylibs from XE7 original release.

I started working on NSOpenPanel. Theoretically I can use this to pop open a dialog when my app runs and then the user can choose where to put the example files. I get some "URL" string back that I can save and that allows me to reach out of the sandbox to where the user wants the data. I'm a long way off but first steps are promising. It would be nice if Embarcadero provided a component for this because everything I've been doing so far is really tedious.

EDIT: This seems to do what I/we want. The user can select a path in the "global" Documents area (or wherever they like). I need to save the user's desired folder in some bookmark so that my application can get to it next invocation.

---

Edited by: Grant Beattie on Nov 18, 2014 11:28 AM
Grant Beattie

Posts: 77
Registered: 11/29/01
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 19, 2014 11:35 AM   in response to: Grant Beattie in response to: Grant Beattie
I started playing with NSOpenPanel and curiously I'm getting the same behaviour as TOpenPanel. That is, when my app is sandboxed the panel should (be able) to open in the Documents area within the sandbox (within the container)... you know, the same area as my application can (only) access !! However, both TOpenPanel and TNSOpenPanel open in the Users/username/Documents area instead. I will have more to say including examples later, but for TOpenPanel I am setting InitialDir to the Documents area inside the container. No effect. For NSOpenPanel I am using openPanel->setDirectoryURL (or theNSString equivalent) to the Documents area within the container. Again no effect.

However I did want to mention that I think I figured out a way to manually add entitlements to the OSX app. The file Project1.entitlements found in the OSX32\Release directory is created at build time by adding up the values in Project->Options->Entitlement List with the template found in the project root. So for instance I added com.apple.security.files.bookmarks.app-scope to it here. Thus the template Entitlement.TemplateOSX32.xml goes from this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<%appSandboxKeys%>
</dict>
</plist>


To this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<%appSandboxKeys%>
   <key>com.apple.security.files.bookmarks.app-scope</key>
	<true/>
</dict>
</plist>


And my final Project1.entitlements becomes:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
		<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.files.user-selected.read-write</key>
	<true/>
 
   <key>com.apple.security.files.bookmarks.app-scope</key>
	<true/>
 
</dict>
</plist>


I hadn't seen anyone mention this anywhere so I thought I would mention it.

Edited by: Grant Beattie on Nov 19, 2014 12:00 PM

Edited by: Grant Beattie on Nov 19, 2014 12:30 PM
Grant Beattie

Posts: 77
Registered: 11/29/01
Re: File Dialogs can't access Documents area in sandboxed Mac apps  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 21, 2014 3:13 PM   in response to: Grant Beattie in response to: Grant Beattie
Regarding the original issue in the top post of this thread ... I'm going to have to say I think this is by Apple "design". I use the term loosely.

They don't want to have the user messing around in the container, certainly not knowing of it's whereabouts limits the user's access to the files therein in case they wanted to copy them elsewhere for posterity (lacking an in-app export option for even a simple backup).

Also, since the user hasn't granted any permission to the app to access the vanilla Documents area or anywhere else outside the container, we are left with using NSOpen panel, tweaked to ask the user for access to a directory and then setting the working area there.

Then Firemonkey fails miserably at saving bookmarks such that said access can exist between program invocations. In fact substantial parts of the Mac API are missing even though their absence was noted years ago. It's totally broken. Unless this API is created somehow you are left with asking for permission every application run, or skipping the sandbox and living with the issues that come up then... such as the goofed up OpenDialog file list.

And also regarding the problems with TOpenDialog not showing the filelist when running in a non-sandboxed app. I think this is some kind of permission thing too. Unless the user clicks on something you can't see the files when TOpenDialog starts. NSOpenPanel has a similar issue (file list blank) except that it seems to remember the permissions between "openings". I suspect that has to do with my implementation. Embarcadero probably tears the whole OpenDialog down when the user is dismisses it, so therefore it starts fresh every time.

This is ultra disappointing considering Embarcadero plows ahead with new platforms and features when some of the basic Mac API is left incomplete. People saw this in XE3!

I leave for your consideration some of the required elements missing and noted in the following report:

http://qc.embarcadero.com/wc/qcmain.aspx?d=113852

And finally one other goofy thing about TOpenDialog versus NSOpenPanel. When you get permission to access a file using TOpenDialog that the only permission you get. NSOpenPanel can give you access to a directory such that you can create additional files, say myfile.txt and myfile.bak for instance.

Edited by: Grant Beattie on Nov 21, 2014 3:37 PM
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02