"Related item" file not written due to Sandbox

Hello,

I'm developing an application which is basically downloading and saving subtitles for video files.

A user select a video file (either with an NSOpenPanel or drag an dropping it into the app) and I download and save subtitle file in the same folder of the video file using the same file name but with "srt" as extension (example: if the video file name is "movie_1.mp4" the subtitle file will be "movie_1.srt").

According to the sandbox specs such a behavior should be allowed.


Here what I did:

- Enabled the sandboxing for the app

- enabled com.apple.security.network.client entitlements (which is working fine)

- enabled com.apple.security.files.user-selected.read-write

- Added the following configuration to my Info.plist: (adding both mp4 and srt doc types, and fligging srt as related item)

<key>CFBundleDocumentTypes</key>

<array>

<dict>

<key>CFBundleTypeExtensions</key>

<array>

<string>mp4</string>

<string>mpeg4</string>

<string>m4v</string>

</array>

<key>CFBundleTypeName</key>

<string>MPEG-4 File</string>

<key>CFBundleTypeRole</key>

<string>Viewer</string>

</dict>

<dict>

<key>CFBundleTypeExtensions</key>

<array>

<string>srt</string>

</array>

<key>CFBundleTypeName</key>

<string>SRT File</string>

<key>CFBundleTypeRole</key>

<string>None</string>

<key>NSIsRelatedItemType</key>

<true/>

</dict>

</array>


Then I created a class that implement the NSFilePresenter protocol returning:

- presentedItemURL: the desired URL of the .srt file

- primaryPresentedItemURL: the URL of the video file for which I'd like to save the subtitles


then the code that should write the file is (I tried pretty much all the methods supported by NSFileCoordinator):


let presenter: NSFilePresenter <= class implementing the NSFilePresenter protocol given as input to the function

let data: NSData <= data containing the subtitle given as an input to the function

var error: NSError? = nil

let coord = NSFileCoordinator(filePresenter: presenter)

coord.coordinateReadingItemAtURL(presenter.presentedItemURL!, options: NSFileCoordinatorReadingOptions(), writingItemAtURL: presenter.presentedItemURL!, options: NSFileCoordinatorWritingOptions(), error: &error, byAccessor: { (readUrl: NSURL!, writeURL: NSURL!) in

print("attempt to write file: \(presenter.primaryPresentedItemURL!!.path)")

data?.writeToFile(gerSubtitlesFilePath(path, format: format), atomically: true)

return

})


the block is executed (I can see the print in the logs) but no file is written nor any error or warning is rised


I tried as well all the various coord.coordinateWritingItemAtURL methods as well witout success


What am I missing?

Accepted Reply

Ok, I managed to solve my issue.... 2 things were missing/wrong:

1) right after creating an istance of an object implementing the protocol NSFilePresenter I have to register it calling the class method "addFilePresenter" of NSFileCoordinator like this "NSFileCoordinator.addFilePresenter(filePresenter)"

2) in the info.plist in the doc type flagged as NSIsRelatedItemType=true the key "CFBundleTypeRole" must be "Editor" (and not "None" as it was in my case)


Settled this everything is working fine

Replies

Unfortunately, from inside a sandbox you can only write to the exact URL selected by the user, which includes the file extension. You could try running the save panel again to save the subtitle file separately, but that's not the best user experience. Does the user absolutely need to have access to the subtitle files? If not, you could put them inside your sandbox container, to which you're allowed unlimited access.


If you have any questions, I'll be happy to help further.

Hi,

thx for the response.

According to: https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html

In the section: related item

it is said: "The related items feature of App Sandbox lets your app access files that have the same name as a user-chosen file, but a different extension. This feature consists of two parts: a list of related extensions in the application’s Info.plist file and code to tell the sandbox what you’re doing."


This is exactly what I'm trying to accomplish! I followed the instructions in the page but I'm still unable to write the .srt file

That document you linked to says you need a special entitlement to access the related items feature. It doesn't say exactly what entitlement that is, though, so maybe look into that.

To be 100% precise it says "With the appropriate entitlement", not necessarely a specific entitlement for this functionality.

Anyway I already considered the possibility that I was missing the correct entitlement but after reading the entire list of the available entitlements I wasn't able to find one that seems "related items" related. Therefore I kept using com.apple.security.files.user-selected.read-write

"With the appropriate entitlement" seems to me to be too vague and pretty unclear. Honestly, it could mean either way and we wouldn't be able to tell. But since you couldn't find another entitlement, maybe it is just automatically bundled with the user-selected-files entitlement. So at this point, since there doesn't seem much troubleshooting left to be done, how about file a bug to let Apple know that related items doesn't seem to be working?

Ok, I managed to solve my issue.... 2 things were missing/wrong:

1) right after creating an istance of an object implementing the protocol NSFilePresenter I have to register it calling the class method "addFilePresenter" of NSFileCoordinator like this "NSFileCoordinator.addFilePresenter(filePresenter)"

2) in the info.plist in the doc type flagged as NSIsRelatedItemType=true the key "CFBundleTypeRole" must be "Editor" (and not "None" as it was in my case)


Settled this everything is working fine