Sandboxing continued - no way around use of NSDocument to gain read/write access to files?

MichaelBothMichaelBoth AUMember ✭✭✭

I just wanted to check this aspect before proceeding with a bunch of code changes. There is this quote in the Sandboxing documents:
"Opening, Saving and Tracking Documents - If you are managing documents using any technology other than NSDocument, you should switch to it because of the built in support for the App Sandbox. NSDocument automatically works with PowerBox and provides support for keeping documents within your sandbox if the user moves them in Finder."

Currently we aren't using NSDocument, but rather are doing 'manual' handling of the particular files our application loads from and saves to (i.e. using File.ReadAllBytes, calling FSOpenSavePanelDelegate etc). I've found that I get an 'unauthorized access exception' in my sandboxed app, even with the "User Selected File" entitlement set to "Read/WriteAccess", when trying to open our files from the user's 'Document' directory. I am guessing this is happening precisely because of us not using NSDocument, and that there isn't any way around rewriting things to use NSDocument, is that correct?

Thanks

Mike

Best Answer

  • MichaelBothMichaelBoth AUMember ✭✭✭
    Accepted Answer

    For anyone that happens across this post, the use of a 'FSOpenSavePanelDelegate' is what was causing me problems; the special 'out of sandbox' access provided by a NSOpenPanel only occurs after the panel is closed and the file is selected. No such special access is granted to file operations within the delegate; so no more nice real-time checking / validation of user selections, it needs to be done after the panel is closed, and the panel then re-opened if the file isn't valid.

Answers

  • MichaelBothMichaelBoth AUMember ✭✭✭

    Can one of the Xamarin guys perhaps comment on this? Changing our app to use NSDocument will be quite a bit of work, so I'd like to pretty sure this is the only way forward for things to work when sandboxed before I start.

  • ChrisHamonsChrisHamons USXamarin Team Xamurai

    I don't know of any Xamarin applications that are sandboxed, nor have I written a sandboxed one, so my knowledge is solely based on "reading the docs from Apple".

    Reading "Powerbox and File System Access Outside of Your Container" states:

    Your sandboxed app can access file system locations outside of its container in the following three ways:

    • At the specific direction of the user
    • By using entitlements for specific file-system locations (described in Entitlements and System Resource Access)
    • When the file system location is in certain directories that are world readable

    and "Enabling User-Selected File Access" states:

    Xcode provides a pop-up menu, in the Summary tab of the target editor, with choices to enable read-only or read/write access to files and folders that the user explicitly selects. When you enable user-selected file access, you gain programmatic access to files and folders that the user opens using an NSOpenPanel object, and files the user saves using an NSSavePanel object.

    Certain other user interactions, such as dragging items to your app or choosing items from the Open Recent menu, automatically expand your sandbox to include those items. Similarly, when macOS resumes an app after a reboot, the sandbox is automatically expanded to include any items that are automatically opened.

    To enable user-selected file access in your app, use the Xcode target editor setting shown in Table 4-2.

    So it sounds like you could avoid swapping to NSDocument APIs if you force the user to select paths via NSOpenPanel / NSSavePanel?

  • DavidLilleyDavidLilley USMember ✭✭✭

    Just to add to this, I use NSOpenPanel and NSSavePanel to Access files and folders and indeed you can access them out of the sandboxed.

    Bear in mind just using NSOpenPanel and NSSavePanel will give you access for the time your app remains active, upon restart the permission is gone. However you can use Security-Scoped Bookmarks to save the permission and request again before use.

  • MichaelBothMichaelBoth AUMember ✭✭✭

    Chris and David - thanks. I've been through the same Apple documents, hence why I'm a bit puzzled why my code isn't working:

    • I have my App sandboxed with the "User Selected File" option set to 'Read/Write Access'
    • I allow the user to select a file to open using "NSOpenPanel"; in this case I'm testing selection of a file in the /Users/Shared/ folder
    • I use a FSOpenSavePanelDelegate, with the 'ValidateURL' member, to check some properties of the selected file; this I do via File.ReadAllBytes, but at this point I receive a "System.UnauthorizedAccessException: access to the path is denied"

    What I can get working is, with the entitlement of "Downloads Folder" set to 'Read/Write Access', opening of files. So it must be something to do with rights in the /User/Shared/ folder. We have some 'demonstration' files that, upon running the application for the first time, are copied to this folder (if they don't already exist); I guess this is the issue, and that the copying of files like this (from embedded resources in the EXE) will probably a no-no for App Store distribution anyway. Ok, another problem to solve!

  • MichaelBothMichaelBoth AUMember ✭✭✭
    Accepted Answer

    For anyone that happens across this post, the use of a 'FSOpenSavePanelDelegate' is what was causing me problems; the special 'out of sandbox' access provided by a NSOpenPanel only occurs after the panel is closed and the file is selected. No such special access is granted to file operations within the delegate; so no more nice real-time checking / validation of user selections, it needs to be done after the panel is closed, and the panel then re-opened if the file isn't valid.

  • ChrisHamonsChrisHamons USXamarin Team Xamurai

    That is an unfortunate design decision by Apple. I'd consider filing a Radar with them to complain, as that UX is suboptimal, but I don't have high hopes they will respond in a timely manor.

Sign In or Register to comment.