Hi there,
I have two extension in my App, a Finder Sync and a Share Extension. Because these are disabled by default and automatically enabling them is, according to my extensive research, not possible, I want to provide an easy way for the user to enable the extensions when the app is opened. I am currently displaying a popup, with a button to open the preferences.
I have struggled with this a bit, by now I managed to open the main preferences window using
NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference")!)
which is rather suboptimal though, since the user has to select the extensions option manually and isn't directly redirected there.
What I have also found is that the menu of the FinderSyncExtension can be opened directly by using FIFinderSyncController.showExtensionManagementInterface()
which is unfortunately suboptimal as well, because it only shows the managment interface of the finder extension and not the overview of all extensions.
Is there any way to either enable the extensions programatically, or if not, is there a way to show the "Added Extensions" portion of the Extensions menu in the system preferences?
Post
Replies
Boosts
Views
Activity
Issue
When using the nio-ssh library to execute ssh commands in a daemonized context (built executable launched using launchctl with a config in /Library/LaunchDaemons) a ChannelError (operationUnsupported) is thrown.
I'm unsure if this is a problem just with nio-ssh or nio in general. Could it be that certain network operations aren't permitted from within a daemon?
Any information/help on this matter is greatly appreciated!
Related issue in the nio-ssh repository: https://github.com/apple/swift-nio-ssh/issues/166
Unfortunately there are no specific tags for these libraries (nio, nio-ssh) or for daemons, so I have used the Network tag instead.
Reproduction
Reproduction can be found here: https://github.com/eliaSchenker/nio-ssh-daemon-issue/tree/main
To run the reproduction follow these steps:
Build using Xcode (Product > Build)
Find the executable in the build folder (Product > Show Build Folder in Finder)
Move the executable to /Library/PrivilegedHelperTools
Create a daemon configuration in /Library/LaunchDaemons/nio-ssh-daemon.plist
<?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>Label</key>
<string>nio-ssh-daemon</string>
<key>ProgramArguments</key>
<array>
<string>/Library/PrivilegedHelperTools/nio-ssh-daemon</string>
<string>username:password@host</string>
<string>ls -la</string>
</array>
<key>KeepAlive</key>
<true/>
<key>ProcessType</key>
<string>Interactive</string>
<key>StandardOutPath</key>
<string>/Library/Logs/nio-ssh-daemon.out.log</string>
<key>StandardErrorPath</key>
<string>/Library/Logs/nio-ssh-daemon.err.log</string>
</dict>
</plist>
making sure to adjust the program arguments to include an host with username and password.
Load the daemon using
sudo launchctl load nio-ssh-daemon.plist
When opening Console.app, navigating to Log Reports and opening nio-ssh-daemon.out.log the logged error will be shown:
Creating bootstrap
Connecting channel
Creating child channel
Waiting for connection to close
Error in pipeline: operationUnsupported
An error occurred: commandExecFailed
If the executable is run manually without a daemon it will work correctly:
./nio.ssh-daemon username:password@host
The reproduction is a copy of the example in the repository (https://github.com/apple/swift-nio-ssh/tree/main/Sources/NIOSSHClient) with slight modifications to log errors instead of using try!.
Hi there,
Introduction
I have been working on a Finder Sync extension and I would now like to use it to access a file the user has selected. This has been causing me significant issues (and I believe that a lot of other developers have also experienced similar issues with the extension).
Because I plan to release my app on the App Store, I need both the main app and the finder sync app to be sandboxed
Some example code describing the issue
When the user executes the custom finder action in the context menu, I use the following code to extract and access the selected files:
guard let target = FIFinderSyncController.default().selectedItemURLs() else {
NSLog("Failed to obtain targeted URLs: %@")
return
}
do {
//Read content of the first selected file (example)
let text = try String(contentsOf: target[0], encoding: .utf8)
}catch {
print("Some error occurred: \(error)")
}
The problem
Though these files should have a sandbox exception (because they are selected by the user), they do not and I get the following error because I seemingly do not have the permission (even though I should have):
Error Domain=NSCocoaErrorDomain Code=257 "The file “myfile.txt” couldn’t be opened because you don’t have permission to view it."
I know from my thorough research (refer to links) that a lot of other people working with Finder Sync extensions have had this problem in the past and that Apple has not provided an official way to fix this.
So essentially I am asking if Apple is planning to fix this bug in the near future or, if not, whether there is a workaround for this problem (while still passing the App Store review) and while keeping the main functionality of a context-menu like Finder Sync Extension.
Useful links
My previous question concerning the transfer of URLs given in the Finder Sync Extension
I already asked a similar question on how to share some file URLs between my Finder Sync Extension and the Main App, to which I received a presumably working answer, which would work if this problem didn't exist. The solution to passing this access between extension and main app is to create a security scoped bookmark. This is not possible as long as I can't even access the files in the context of the extension itself.
Here is the link to this aforementioned question I posted last month:
Accessing a file in a sandboxed main app, which was selected in a Finder Sync Extension
Some people with the same issue (dating back as far as 2016
Someone on the Apple Developer Forum had a similar issue and the respondent suggested a multitude of hacky fixes:
Swift file reading permission error on macOS sandbox
Here is someone on StackOverflow from someone who had the exact same issue. Multiple people mentioned there that this was a bug in the operating system and have filed multiple bug reports, which were all unanswered by Apple:
Read and Write access for FinderSync extension in a sandboxed environment
FinderSync Extension runtime error: The file couldn’t be opened because you don’t have permission to view it
Hi there,
The Setup/My Goal
I have a very standard Finder Sync Extension, which extends the context menu of the finder. I also have a main application which uses the KeyboardShortcuts Package (Keyboard Shortcuts - Github) to record and save a user defined shortcut. This shortcut should execute the menu item of the Finder Sync Extension (therefore getting the selected files and processing them in some way) when used.
Currently I am using inter-process communication to send an event to the extension when the shortcut is executed by the user. You can find the Swift Class responsible for the communication between Finder Sync Extension and the Main App as an Attachment here: ProcessCommunicator.swift (although the communication works and this is more an issue of the finder sync extension behaviour than one of inter-process communication).
When the Finder Sync Extension receives the event, it executes the same function which is called when the user clicks the menu item like so (this event is registered in the initialisation function of the Finder Sync Extension):
processCommunicator = ProcessCommunicatorReceiver(appGroupIdentifier: "group.some.bundle.id.port")
processCommunicator?.on(id: 1, event: { _ in
self.executeSomeAction(nil)
return nil
})
The same action is called when the user clicks the menu item:
override func menu(for menuKind: FIMenuKind) -> NSMenu {
let menu = NSMenu()
if menuKind == FIMenuKind.contextualMenuForItems || menuKind == FIMenuKind.toolbarItemMenu {
menu.addItem(withTitle: text, action: #selector(executeSomeAction), keyEquivalent: "T")
}
return menu
}
The function executeSomeAction would look something like this
@IBAction func transfer(_ sender: AnyObject?) {
guard let target = finderSyncController.selectedItemURLs() else {
NSLog("Failed to obtain targeted URLs: %@")
return
}
// Process the selected items (target)
The Problem
When the function executeSomeAction is called from the process-communicator-event (sent by the main app), the selectedItemURLs is nil and therefore the function returns without doing anything.
If the function executeSomeAction is called by the menu item click event, the selectedItemURLs is an array of paths as expected.
Is there some restriction which prevents access to the user selected, when it’s not strictly clicked by the user or am I missing something here?
Other possible Solutions to my Issue
This whole inter-process communication is only needed because I need the shortcut event to be sent to the extension. I have noticed that in the initialisier of the menu item there is a keyEquivalent (-> shortcut)
menu.addItem(withTitle: text, action: #selector(executeSomeAction), /* HERE -->*/ keyEquivalent: "T")
This shortcut seems to be ignored by the system, as it neither appears next to the menu item, nor is functional. I am assuming that this is intended but if there is any way to make this work with the inbuilt system shortcut, instead of the communication-hack I am using currently, I would prefer to use this solution.
Summary
As said before, the selectedItemURLs is only defined if it is called from the menu item event, which eliminates the ability to do some custom processing with the selected files (in my case called by an event sent by another process)
Hello there
We have recently discovered an issue where extensions in an app bundle would not open if they are signed (using codesign, in our case). We are assuming that this is because they can either not be run by the main app (because of some signing/security issue) or that the system immediately kills them because they are incorrectly signed.
The setup
Simply create a main app containing any app extension (we have tried FinderSync and Share)
Archive and export the app using the xcodebuild command (though exporting it through Xcode works aswell)
Sign the app container (.app) and the extension (.appex file in Contents/PlugIns).
Open the app
The Extension won't be visible in the Preferences and is not running
The problem
If we do not sign the app extension, the main app and app extension start as expected (this not an option though, because notarization will fail when the app extension is not signed). If we sign the app extension, the app extension will not start (when running the main app). We assume that this is because macOSs Gatekeeper immediately kills them when started. But we are not sure why.
Demo Project
You can find a very simple demo project in the Github Repository linked below. This demo project only contains an almost empty main app, a completely default App Extension (everything is left as when generated, except the myFolderURL which was changed to / for testing purposes).
The demo project also contains two scripts, one which builds app and signs it completely (with app extension) and one which builds the app and signs everything but the App Extension. Both scripts export a .app file, and a zip file.
Make sure to insert the name of your Developer ID Application Certificate into the script (simply replace the XXXXXXX with the name of your certificate)
To reproduce our issue:
Run the unsigned app and open the preferences with the button to confirm that the app extension have been added.
delete the app (to make sure the app extension is not still in the preferences when testing the signed app)
Open the app with the signed extension and you'll see that upon opening the app and viewing the preferences that the app extension is not present in the list (and therefore not open). This can be tested using the Activity Monitor or 'top' command as well.
You can find the link to the github repository containing the demo project here (I could not directly insert the github link because of the question guidelines):
StackOverflow Question
Conclusion
To summarise: When signing an app extension (Finder Sync in the Demo), the extension does not open/gets killed when the extension is signed. If the extension is not signed everything works as intended. As said, we believe that either signing, notarising, or the gatekeeper might be the cause of this issue, probably this is some issue with our build/sign automation (the demo contains the scripts with our automation code). Can that be the case or are extensions handled differently and we are missing a step?
Hi there,
I have a Finder Sync extension, which adds a simply entry to the context menu of the finder. When this option is clicked, the selected files (URL objects) are sent to the main app using a URL Scheme. When I attempt to handle them there (e.g. read/write, access information about the file) I get a permission error. This only happens when using files from anything but the Downloads/Music/Pictures/Movies (all the folders which I already have given access to)
I know that this denying of permission when the user hasn't selected it is intended by the sandbox and that I can access them in the extension because they're selected, but this access gets lost as soon as I send them to the main app.
I simply can't find a way to send these paths to the main app without losing the aforementioned access, is there any way to do this, or am I forced to request full disk access from the user?
Hi there,
I have a share extension with the following configuration values:
For some reason the Share Extension only appears in the menu when I am on the desktop folder, though it is working fine with text and and web pages.
Has anyone experienced similar issue with the Share Extension?