Catalina - data sharing with sandboxing

Hi there,

I am sharing some data between a Xojo macOS desktop app and a macOS screensaver written in Xcode.

The macOS app writes some data in /Application Support/com.mycomp.myapp/prefs.json
The screensaver reads this prefs.json and uses the data to build graphics.

This is working fine in Mojave but doesn’t work anymore in Catalina.

The screensaver is placed in the resource folder of the app and everything was notarized and codesigned using App Wrapper.
The screensaver is installed by the desktop app (using file.Launch).

I though I could solve this using an « application group », but this option is not available for screensavers.
It seems application preferences can not be used by other applications.

Some issues:
-The screensavers are running in a special legacyScreenSaver sandbox in Catalina.
-When my obj-c wants to get the NSApplicationSupportDirectory it’s not the Application Support folder I’m getting within the Xojo app using SpecialFolder.Application.

SpecialFolder.ApplicationData: /Users/UserName/Library/Application Support

NSApplicationSupportDirectory: /Users/UserName/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support

So my question is: how can I share data between 2 sandboxed apps ?

Thanks !

AFAIK Application Groups is the approved mechanism for sharing data between Sandboxed apps; but as you’ve found this doesn’t work in Catalina, you know for the users Security.

My honest advice at this point is to ask on the Apple Developer Forum, you might be lucky and get someone from Apple who sees your post and can advise you on what to do. Alternatively you can use one of your DTS incidents to arrange a consultation with some Apple engineers.

If this change is intentional; my guess is that someone in Apple decided that Screensavers don’t need to communicate with other apps, and therefore my guess is that you’ll need to the whole thing in the Screensaver.

You could use shared memory to exchange data; but that creates it’s own set of complications.

There is a temporary entitlement for this, but it was meant for upgrading a non-sandboxed app into the app sandbox and generally Apple don’t approve it’s use on the Mac App Store. You can try it, make sure when you submit to the Mac App Store, you explain why (in detail) it’s needed, but you are at the mercy of the reviewer as to whether you can use this or not.

My wife and I are considering trying to arrange a sit down with some Apple engineers, as I’ve been struggling with some things that used to be simple; but now I get the feeling that I’m fighting with the system more and more. I have decided that I want to talk directly to the horse (as per say) and understand how exactly they (currently) intend certain things to be used. The state of the documentation is terrible, with many examples not being updated in the last 3~4 years, which simply don’t work or when followed appear to work on dev machine, but fall face flat on some customers machines, which causes much embarrassment and frustration for me and my customers.

[quote=469017:@Olivier Colard]…

SpecialFolder.ApplicationData: /Users/UserName/Library/Application Support

NSApplicationSupportDirectory: /Users/UserName/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support

So my question is: how can I share data between 2 sandboxed apps ?

Thanks ![/quote]

Hm… just wondering, you say that your Xojo app is sandboxed but ApplicationData is not pointing to a folder within /Users/UserName/Library/Containers. ?

It should be in containers as well!

Maybe you have a different kind of issue here?

I’ll try that. Is what you call DTS the same as TSI: ? I never used it.

[quote=469045:@Oliver Osswald]It should be in containers as well!

[/quote]
Oliver, you’re right, but I was just pointing out the differences and that, because of this, I can’t share data between the two apps.

I have a workaround but I don’t like it: I can let the user select manually, from the screensaver options, the ApplicationData folder of the desktop app. But that means letting them go thru the user’s library folder structure, which is not always easy for them and, anyway, might change again in a future macOS release.

Another option would be to update the screensaver itself, when installing, writing the right path in a document in the .saver package, but I’m not sure it would pass the MAS approval, or if it would just break the notarized screensaver…

Yup; I’ve never used it either. I know a couple of devs who have and it seems like a most reliable way to get a solid result from Apple. You get one or two with your developer license.

Application Groups also work with unsandboxed applications; so what you’re seeing is either a bug or a deliberate change for “Security”.

For me personally I want a sit down with the people who’re in charge of the most problematic API I am using. I’ve been using it since 2008, so I want to understand what their current trend of thought is in how it should be used (because so much is not working as it used to do so). I also want to make sure that they understand how critical it is to me (and potentially others), as I’ve got a horrible feeling that the people in charge of this API care for the Phone only, which makes what I’m doing WAY out of their scope.[quote=469061:@Olivier Colard]Another option would be to update the screensaver itself, when installing, writing the right path in a document in the .saver package, but I’m not sure it would pass the MAS approval, or if it would just break the notarized screensaver…[/quote]
Won’t work going forwards; you’re breaking the code signature and I have it on good authority that Apple is going to be switching to scanning the code signature each and every time the application is launched, which means app launching is going to get a whole lot slower as this requires recreating hashes, a round trip to Apple’s Notarization servers and Apple’s Time Stamp servers. Apple employees may not notice the delay, but every other Mac user in the world will.

It also means that your screensaver must store this file reference as a Security-Scoped Bodgemark, and like you say it not potentially work in the future.

So I had a thought, I wonder if it’s how App Wrapper code signed your application. I would like you to try something for me.

  1. Sign your screensaver independently from your main application.
  2. Add it to your application.
  3. In the “Other” section of App Wrapper, there’s a section for fine grained control over files. Click the “Add” button and navigate through the Application bundle to find your screensaver.
  4. Tell App Wrapper to ignore the screensaver.
  5. On the General pane of App Wrapper, unselect “Blackbird” as I can’t recall right now if I fixed a bug in Blackbird with ignoring files or not.
  6. Wrap your application and try it again.

I’m seeing the same results Oliver is when saving a file to SpecialFolder.ApplicationData in Catalina. Is the new location of ~/Library/Containers/com.companyname.appname/Data/Library/Application Support/ correct? Xojo documentation still says that SpecialFolder.ApplicationData will point to /Users/UserName/Library/Application Support.

Wrapping/Signing will probably be another problem, but I first need to solve the data sharing issue.
The first problem remains that the screensaver needs to read data from

/Users/UserName/Library/Application Support/com.mycomp.myapp/
and that NSApplicationSupportDirectory returns

/Users/UserName/Library/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver/Data/Library/Application Support

I’m wondering if hard-coding a part of the path would be an issue.
I could generate the path as

  NSString * identifier = @« com.gate61.xxx/xxx.html";
  NSString * url = [NSString stringWithFormat:@"file:///users/%@/Library/Application Support/%@", NSUserName(), identifier];

It works on my dev system but I’m not sure it will be safe with a hard-coded path portion.

@Anthony Black and @Olivier Colard : what you see is a feature of the Sandbox.

Thanks Beatrix. I know that but as this post title says, the problem is that it’s not possible to share data in ApplicationData anymore with Catalina.

Why not try to use IPCSocket ?

Joe Ranieri posted the code in Xojo, as well as C++. It should be possible to port that to Objective C. It is for Windows, but with some chance, it will work on Mac.
https://forum.xojo.com/20033-ipcsocket-protocol-info/p1#p168010

There was also a long conversation precisely about using it in sandboxed applications:
https://forum.xojo.com/37478-ipcsocket-and-the-app-sandbox/0

[quote=469500:@Michel Bujardet]Why not try to use IPCSocket ?

[/quote]
Good idea, but this requires both apps to be running.
One of my apps is a screensaver, the other one is a desktop app which is not always running.

I’m not sure it’s possible to integrate IPC in a screen saver and I’m not sure what happens when the mac goes into screensaver mode.

The hollow tree message strategy will work only if you can leave the data somewhere with one app, and pick up later on with the other one.

It would seem the file is out of the picture.

Perhaps preferences can be used. I have used CFPreferencesMBS in one of my apps, to put things there and read it later.

Since CFPreferences are documented, you must be able to address them in XCode as well.

This is typical of a Sandboxed application.

Either the screensaver of the configuration application, can use a temporary entitlement with a hard-coded path to a relative location. So functionality wise, there is a mechanism to allow this, but then so is Application Groups.

If using a temporary relative path works, be warned that App Store reviewers will often reject first for seeing a temporary entitlement (as they were only meant to be for a transitional period), but if it means that your app can work again, try it.

Shared memory, but it will lose data on a machine restart until one of the apps restores the data.

Preferences are now also sandboxed in macOS (and iOS) with exceptions for app extensions and app groups: .

Maybe I’ll try to submit the app on new year’s eve, the reviewers may be on a good day…

It really seems the only and recommended way is to use app groups, but the app groups are not available for screensavers.
In fact, there is not a single capability available for screensavers (« capabilities are not supported for screensavers »).