Issues embedding Finder Sync extension via electron-builder - swift

I have an Electron application that integrates with OS X Finder via a Finder Sync extension. Overall, the application has three parts:
Electron application
Swift Application
FinderSync extension
The Electron application is the main entry point. On start up, it creates a child process that runs the Swift application. The Swift application has embedded in it, the FinderSync extension. The Swift app and FinderSync extension communicate over ICP so that the FinderSync extension can get the correct information for badges and context menus.
I build everything with electron-builder. It ends up with a structure like:
- MyElectronApp.app
- Contents
- PlugIn
- MyExtension.appex
- MacOS
- MySwiftApp.app
- Contents
- PlugIn
- MyExtension.appdex
- (All the other app contents)
When I install the application and when I run it, I see this in Console.app
rejecting; Ignoring mis-configured plugin at [/Applications/MyElectronApp.app/Contents/MacOS/mySwiftApp.app/Contents/PlugIns/myFinderExtension.appex]: plug-ins must be sandboxed
The plugin is marked as sandboxed, This is for the inner instance of the plugin. I do not get this for upper one.
When I launch the application, I can see that my plugin is running in the Finder Extensions Preference Pane. If I toggle the extension in the Preference Pane, I can see in Console.app that the extension and Swift app are communicating with each other. But I do not see my context menu or badges in Finder.
I do see this in the logs for my Swift application and Finder Extension:
LSExceptions shared instance invalidated for timeout.
The extension is Sandboxed and the Swift app is not. It took me awhile to get those entitlements "correct". I have the plugin listed twice in the Electron app. I found that if I didn't put it in the top level PlugIn directory, then it would not be registered with the OS. When I query pluginkit, I see that the first instance of the extension is running. The extension and the Swift app have the same application group so they can do IPC.
At this point, I'm not really sure what I can do. It seems that the plugin launches with the Electron app and not when I launch Swift app from within Electron.
To get to this point, I worked through code signing issues and sandbox issues. I am not using a provisioning profile. I do have a developer certificate from Apple that I use for signing.
Any help would be greatly appreciated. If there was an article where they published a Finder extension with electron-builder, that would be great as well.
Below are some other files:
electron-builder entitlements file:
...
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<false/>
</dict>
...
electron-build settings in package.json
"build": {
"appId": "com.myapp",
"productName": "My App",
"copyright": "Copyright © 2020 ${author}",
"files": [
"./index.js",
"./modules/**/*",
"./iconSmallTemplate.ico"
],
"extraResources": [
{
"from": "./resources/",
"to": "./",
"filter": [
"**/*"
]
}
],
"mac": {
"appId": "com.myapp.mac",
"category": "public.app-category.productivity",
"type": "development",
"identity": "Apple Development: ME (#####)",
"extraFiles": [
{
"from": "mySwiftApp.app",
"to": "MacOS/mySwiftApp.app"
},
{
"from": "myFinderExtension.appex",
"to": "PlugIns/myFinderExtension.appex"
}
]
}
}

Related

vscode extension: how to prevent development-related fields automatically added to package.json

A few times in vscode extension development vscode has automatically added information to the extension's package.json that obviously seems related to development and debugging that extension.
Note: that the Marketplace Released version of the extension is also installed in the same workspaces used for debugging in the extensionHost. Could that be the issue?
The following fields were automatically added to the extension's package.json:
"identifier": {
"value": "ArturoDent.find-and-transform",
"_lower": "arturodent.find-and-transform"
},
"isBuiltin": false,
"isUserBuiltin": false,
"isUnderDevelopment": true,
"extensionLocation": {
"$mid": 1,
"fsPath": "c:\\Users\\Mark\\find-and-transform",
"_sep": 1,
"external": "file:///c%3A/Users/Mark/find-and-transform",
"path": "/c:/Users/Mark/find-and-transform",
"scheme": "file"
},
"targetPlatform": "undefined",
I missed looking for these changes and published the extension to the Marketplace and it understandably causes problems for users. The extension never loads for example, probably looking in that location from my development machine.
I do a lot of extension development and have only seen this info automatically added a few times.
Is there a way to prevent that info from being added? Or change my workflow so it doesn't happen again?
A closely related issue was reported at vscode extension test run modifies package.json after 1.67.0, where extra metdata was being written to package.json without warning and causing all kinds of problems.
The current SO question above here had nothing to do with running tests (as in the github issue) but only with debugging and was quite sporadic and difficult to make recur - but the same metadata was being written to package.json.
I have filed a new issue on this: Extraneous data written to package.json while debugging an extension that writes to package.json

How to run a system event AppleScript from a hardened macOS app?

I've developed SOL, an open-source macOS launcher.
Inside of SOL, I added the ability to run AppleScript commands, one of these commands allows me to lock the computer:
{
iconImage: Assets.LockIcon,
name: 'Lock',
type: ItemType.CONFIGURATION,
callback: () => {
solNative.executeAppleScript(
`tell application "System Events" to keystroke "q" using {control down, command down}`,
)
},
},
I have also added the correct entitlements for the hardened runtime (it is distributed only via DeveloperID and not via app store, so hardened runtime is the only capability needed)
<key>com.apple.security.temporary-exception.apple-events</key>
<array>
<string>com.apple.systemevents</string>
<string>com.apple.systempreferences</string>
</array>
The problem is: when I run the app via XCode it works fine, but once the app is packaged and distributed via DeveloperID signed binary, then the lock AppleScript stops working.
Looking at System Preferences I can see the app is still registered and has automation access:
Why does the script stop working? If I remove the permission and re-add it then it starts working again. Does it have to do with the binary? Or is there some permission model I am missing? I had a similar problem with folder access with a different app, so could it be something similar (a security feature I'm not aware of?)
EDIT 1:
Looking through the console.app logs there is also no error message.
EDIT 2:
I just managed to reproduce the issue while attached to XCode and log the output of calling the AppleScript:
Optional({
NSAppleScriptErrorAppName = "System Events";
NSAppleScriptErrorBriefMessage = "Sol is not allowed to send keystrokes.";
NSAppleScriptErrorMessage = "System Events got an error: Sol is not allowed to send keystrokes.";
NSAppleScriptErrorNumber = 1002;
NSAppleScriptErrorRange = "NSRange: {36, 48}";
})
But the app does have accessibility permissions but this still happens? 🥴
EDIT 3:
I just tried removing the app from the accessibility panel and re-adding it, and now the script works again. I killed the app and started it again, and it still works. So my guess right now, is that it has something to do with the binary. Maybe if I replace it with a new version then the accessibility setting doesn't work anymore?
After much gathering at hints all over the internet, I've come to the conclusion that the problem lies in having different binaries.
It makes sense that macOS does some binary check to make sure the application has not been swaped. I had therefore two binaries in my machine a "release" one, which was DeveloperID signed. And the XCode debug one, which uses a development certificate. So both are different and therefore do not pass the binary check.
The brute force solution is not to have a release version installed in my machine. Another solution would be to have the debug binary have a different bundle ID (com.ospfranco.sol), so that macOS allows both the release binary and the debug binary to have accessibility access.

Running Debug using Flutter Flavor?

I'm trying to run the debug mode on visual studio code (click "run and debug") for my flutter app, but when I do I'm facing the following issue:
The Xcode project defines schemes: release, private.
Exception: You must specify a --flavor option to select one of the available schemes.
So I have these two "flavours" but I'm not sure how to specify which to use. Normally, running the app through the terminal would require me to specify it as such: flutter run --flavor private but I'm not sure how to do the same for debug. Is there an equivalent command for debug mode?
Would appreciate some help, thanks in advance!
This answer will only be what you're looking for if you created your flavors (and schemas) correctly (check this for reference: Flavors in Flutter by Flutter Explained channel) and if you are using android studio, since it is there were I solved it.
After having followed the video or any other correct explanation or set of steps, it is true that you cannot run the debugger nor have any of the DevTools attached if you run your app through a command. For example in my case, one of my flavors is named 'staging' so the command I ran would be:
flutter run --flavor staging -t lib/main_staging.dart
But by doing so, yes, you can run your app, but you won't see any of the previously mentioned tools attached. What I did (and this is the answer) is this:
and then added the additional args (in my case I wanted to run the 'staging' flavor or schema, as you already may have noticed) so:
After that, I got rid of this exception
Exception: You must specify a --flavor option to select one of the available schemes.
That is: the exception did not show again when hitting either one of these two buttons ('Run' or 'Debug'):
And that would be it. After that, I was able to see the debugger working as well as the DevTools.
In your launch.json file configurations, you can use this format for your iOS app to run:
{
"name": "production",
"request": "launch",
"type": "dart",
"args": [
"-t",
"lib/main_prod.dart",
"--flavor",
"prod"
]
}
you have to add
"args":[ "-- flavor", "flavor_name" ]
in your .vscode > launch.json to obtain something like this:
"configurations": [
{
"name": "flutterApp",
"request": "launch",
"type": "dart",
"args": [
"--flavor",
"dev",
]
},
then you need to launch the debugger from here selecting the correct configuration:
otherwise it will not work
I encountered this, and had multiple schemes. In order to resolve it in addition to adding:
--flavor {scheme name}
to my run command, I also had to create a duplicate build configuration named
Debug-{scheme name}
You can do this by navigating to your project Runner in xCode, then
Editor->Add Configuration-> Duplicate Debug (or your desired build),
then name in the format {Configuration}-{scheme name}
Build Config Image
yes , you have to add arguments in launch.json file configurations
"args":[
"-- flavor",
"flavor_name"
]
N.B: you will get this json file in .vscode folder of your project
In Xcode I had to create the missing scheme and go to Manage Schemes and mark as shared.

How to protect the source code of Flutter Web deployed to Firebase Hosting?

I made a Flutter Website and I deployed to Firebase Hosting, if I inspect the page on Google Chrome, in "Sources" tab it's possible get the source code of the website.
Is there any way to protect the source code, not having the entire code exposed like this?
If you look at the source file you will see that it is compiled/minified.
// snippet
var r
var q=d
try{if(a[b]===s){r=a[b]=q
r=a[b]=d()}else r=a[b]}finally{if(r===q)a[b]=null
a[c]=function(){return this[b]}}return r}}function lazy(a,b,c,d){var s=a
a[b]=s
What you are seeing are the sourcemaps which show a developer friendly view of the compiled/minified code. I don't see any options for turning sourcemaps off.
Something to keep in mind is that you are shipping a client side app. Once code is on other computers there is not much you can do to prevent them from reverse engineering it.
As described in this page, you need to build your web app using the flutter build web command, then deploy what you find in the ./build/web folder, to Firebase.
It seems that your are hosting your entire app directory.
You need to build your website with 'flutter build web'.
Then 'firebase deploy' the build/web directory.
You need to specify in your firebase.json at the route of the project :
{
"hosting": {
"site": "YOUR_WEBSITE_NAME",
"public": "build/web/",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}

Deployed web app still prints all commented out prints statements in Chrome javascript console Flutter

Today I started diving into deploying my web app to Firebase Hosting.
I so commented out all the print statements in my code, run flutter clean, then flutter build web and then deployed it to firebase.
Now, it all goes smooth except that in Chrome's Javascript console I still get all the prints.
I tried to deploy with no files in the build folder and effectively I got the 404 screen when refreshed the browser, so I'm guessing it has not to do with firebase cache.
What else should I try?
Thank you very much.
my firebase.json is:
{
"database": {
"rules": "database.rules.json"
},
"hosting": {
"site": "fixit-demo-web",
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
},
"storage": {
"rules": "storage.rules"
}
}
Found the solution here Firebase Hosting Flutter Web App not clearing Cache of first deploy
I was missing to give one and update the version in my index.html file.