Feedback Assistant case: FB9545798
Installation and running
git clone git@github.com:birchill/10ten-ja-reader.git
cd 10ten-ja-reader
yarn install
npm run build:safari
Now open "xcode13/10ten Japanese Reader.xcodeproj".
For all four build targets, change the developer team to your own developer team.
Run the build target named "10ten Japanese Reader Extension (iOS)" on a real device (mine is an iPhone 11 Pro), selecting the app "Safari" to run the extension for.
Next, on your iPhone, go into Settings > General > Safari > Extensions and allow the extension named "10ten Japanese Reader".
Return to iOS Safari, refresh the current tab (if you want a consistent URL to test on, then let's choose https://ncode.syosetu.com/n4830bu/130/), and check the Share sheet.
Expected results
A Web Extension named "10ten Japanese Reader" or similar should appear in the Safari Share menu. You should be able to enable it, and something that looks like a hockey puck will immediately appear in the bottom-right of the web page.
Actual results
Although I was able to run this Web Extension just fine on iOS 15 beta 5, since updating to iOS 15 beta 6 (and the corresponding latest macOS and Xcode betas available at the time of writing), I have been unable to run the Web Extension. That is to say, it does not appear in the Share menu, even though it appears in Settings > General > Safari > Extensions and is allowed.
I have tried restarting both my Mac and my iPhone, and incrementing the build number, doing clean builds, etc., but nothing has helped.
I see no debug in Xcode that gives any clues, either.
Post
Replies
Boosts
Views
Activity
Host → App Extension
Passing messages from Host → App Extension is easy. Just call:
dispatchMessage(withName:toExtensionWithIdentifier:userInfo:completionHandler:) - https://developer.apple.com/documentation/safariservices/sfsafariapplication/2823941-dispatchmessage
... on the host, and listen for it in the App Extension using:
messageReceivedFromContainingApp(withName:userInfo:) - https://developer.apple.com/documentation/safariservices/sfsafariextensionhandling/2823944-messagereceivedfromcontainingapp
😌👌
App Extension → Host
Passing messages in the opposite direction is far harder.
The ability to communicate both ways between App Extension and Host was first introduced in the WWDC Talk What's New in Safari Extensions - https://developer.apple.com/videos/play/wwdc2019/720/ (16:55, 18:36). It says that both Host and App Extension need to be in the same App Group, and can then share UserDefaults and/or establish an XPCConnection.
The latest WWDC talk Meet Safari Web Extensions - https://developer.apple.com/videos/play/wwdc2020/10665/ confirms that these are still the only ways to share messages in this direction.
How to send messages over XPC
What I know
This is far from a basic task, so here are the resources I've found.
objc.io has an article on XPC, which the forums won't allow me to link to, that includes a helpful sample project - https://github.com/objcio/issue-14-xpc. However, it does not demonstrate message-passing between a Host and an Extension; just between Host and XPC Service.
Apple's Creating XPC Services - https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html guide
3-year-old unresolved Apple Developer Forum post asking the same thing as me - https://developer.apple.com/forums/thread/62932
There are two articles out there on how to create XPC Services in Swift, but I can't link them.
What I don't know
I've followed these instructions in the above-mentioned Apple Developer forum post:
Anyway, to add a contained XPC service to an extension is pretty straightforward — just use the standard Xcode “New / Target” menu item, select “XPC Service” from the panel, and finish that stuff. However, I'm not really sure what to do now that I have this XPC Service target set up. Moreover, another comment suggests that I might need to get launchd involved, which is another thing I don't know a thing about:
1) the container application needs to listen as an XPC server for connections from other tasks Far as I know (based on some excellent Quinn's advice), this, alas, is possible only if the container application happens to be a login item; otherwise the XPC system does not allow for that. I also don't follow the next part:
2) the extension, being sandboxed, cannot directly open an XPC connexion to the container application; nevertheless, it can contain its own XPC service: - to which a connexion is open automatically; - and which can open its own connexion to the container. At this point I think the task is beyond me and I could really use a sample project to study.
Please help
All I want is to send a message from my App Extension back to my Host app. This all seems desperately hard, and I can't find any sample code demonstrating how to pass messages both ways between Hosts and App Extensions over XPC. I think the WWDC sessions over the years really glossed over this and we could do with a proper end-to-end resource here.
Thank you for any help!
ENVIRONMENT
– macOS 10.15.5
– Xcode Version 11.5 (11E608c)
– Affects both:
1) Safari Version 13.1.1 (15609.2.9.1.2)
2) Safari Technology Preview Release 109 (Safari 14.0, WebKit 15610.1.17.2)
Merely running a Safari App Extension (not a Web Extension) on either Safari or Safari TP leads to the chosen browser crashing after one minute of runtime (see 1:20 of the video attached in Feedback Assistant, "safari_dies_after_a_minute.mp4"). This is true even if the whole content script is commented out. It is also true even if Safari doesn't visit a page at all (stays with just the "new tab" screen) open. So I would guess that it's related to the Xcode-managed debug session more than the content or actions of the App Extension itself.
Of note, waiting on a breakpoint in the App Extension does keep the session alive.
It goes without saying that it's incredibly frustrating trying to build this App Extension when I can only test it for one minute at a time!
Can provide more details as needed.
ENVIRONMENT
– macOS 10.15.5
– Xcode Version 11.5 (11E608c)
– Affects both:
1) Safari Version 13.1.1 (15609.2.9.1.2)
2) Safari Technology Preview Release 109 (Safari 14.0, WebKit 15610.1.17.2)
As demonstrated in the video attached to the Feedback Assistant post, "safari_cannot_reinstall_app_extension.mp4":
1) My App Extension with a comment-only content script can run happily in Safari TP the first time round.
2) Changing the content script in any way, however, causes subsequent installs of the App Extension to fail.
3) Re-enabling the Safari App Extension from Safari's preferences has no effect, nor does allowing unsigned extensions. The Safari App Extension simply cannot be installed again.
4) Cleaning the build is the only thing that allows the Safari App Extension to be installed again.
Could you please tell me how to surmount this issue? It doesn't seem to be expected working behaviour, and it's tediously slow to do a cold rebuild every time I change my content script. I'd expect to just be able to click 'run' in Xcode after any change to the content script and for the updated Safari App Extension to install without a problem.
I can see how to run my Safari App Extension in Safari – but the moment I stop my Xcode debugging session, close and reopen Safari, my extension is no longer listed in the Extensions tab in Safari’s preferences panel, and has disappeared from the menu bar. What’s the workflow to get my extension to just stay there even after I’ve quit Xcode?
App architecture
I am making a macOS Safari (native) App Extension. It's hosted by a macOS Cocoa app.
The App Extension links a static library, and also copies in a Cocoa Resource Bundle.
Aim (and expected behaviour)
The static library needs to read from this resource bundle at runtime.
For a regular macOS app (not an App Extension) that has no entitlements file (and thus, no sandboxing), I find that this file access works just fine.
The file access also works on iOS, for an app that has been accepted into the App Store. Of note, the iOS app doesn't list any Sandbox-related entitlements.
Observed behaviour
For the App Extension, when the static library tries to access the resource bundle at runtime, I receive an error upon file access.
I have no error message to share, unfortunately (I haven't worked out how to pass the error message up from the low-level C++ code in the library to the Obj-C code that abstracts it). I'll try to produce one if this issue doesn't indeed smell like a Sandbox issue, though C++ is foreign to me.
So is this definitely a Sandbox issue? Can I rule that out somehow whilst still being able to install the App Extension into Safari to test it? And if it is a Sandbox issue, is there any way I can give the static library access to the resource bundle whilst satisfying the Sandbox?
This is an initial writeup to see if the failure pattern rings any bells – I'm happy to provide an infinitely deeper level of detail if anything more needs probing.