How to distribute an update for an nw.js app - nw.js

With the forthcoming demise of Chrome Web Store Apps, I have successfully transitioned my app to nw.js I was amazed at how easy it was and how it ran first time. About the only tricky thing I encountered was how to get my app icon showing on mac.
However I am somewhat worried about app updates. Does anyone know what happens to persistent data (indexed-DB etc) when a user updates a nw.js app with a new version that I publish to my web site for download?
Also if anyone can help me with how to achieve automatic updates. I mean the full works here. What code is needed to check for an update, what code do I need to write to deliver the update, what code is needed to install the update. Chrome did all of this for me and I know absolutely nothing about server side coding.

For mac there is a mac store support:
http://docs.nwjs.io/en/latest/For%20Users/Advanced/Support%20for%20Mac%20App%20Store/
IndexedDb, localstorage, etc. will persists until the app name will not change.
For automatic updates:
There is an ongoing pull request going on for auto updater.
https://github.com/nwjs/nw.js/pull/5722
Till then, the easiest way for auto update Your application code is to host your app code on the web and open the web page with nw.js.
If You want to autoupdate the nw.js itself then you will have to provide an installer for that and tell the user to download and run the installer if there is a new update.

The documentation (http://docs.nwjs.io/en/latest/For%20Users/Advanced/Autoupdates/#autoupdates) recommends node-webkit-updater and nwjs-autoupdater. Wherein node-webkit-updater the oldest solution, which is not maintained anymore. It's also has flaws (e.g. unpack via unsigned unzip and system specific apps)
As for the second one (nwjs-autoupdater), I personally do not like the idea to install golang just to have my NWJS app autoupdate...
As an alternative one can consider https://github.com/dsheiko/nw-autoupdater
It provides an API (like node-webkit-updater, but cleaner with use of async/await) to customize auto-update flow in one's app including download/install progress

Related

Manually update an windows app in kiosk mode doesn´t work

Manually triggering update of an app when running windows in assigned access (Kiosk mode) doesn´t work.
I have read others facing the same issue and it feels like there is a bug in windows Kiosk mode. But maybe there is some reason for this behaviour?
I have an app that I sideload using an appinstaller file (my app consist of both a uwp part and a consol part linked with a bridge connection). The app works well in Kiosk mode besides the update part. If I enable automatic updates and link to a specific folder on my computer the automatic updates will work and update my app from the specific folder. However this way to update requires two restarts before it is automatically updated. I want to be able to manually trigger the update from within the app itself somehow and have it updated instantly.
I have tried to update using packagemanager using the function below. This works well in desktop but will always freeze in bluscreen with progressring if I run it in an account in Kiosk mode (assigned access).
PackageManager pm = new PackageManager();
pm.AddPackageByAppInstallerFileAsync(new Uri("C:\\myLocalPath"), AddPackageByAppInstallerOptions.ForceTargetAppShutdown, pm.FindPackageVolume("C:\\"));
I have also tried to restart the app using the command below in order to trigger the automatic update without the need to restart the entire computer. This also works well in desktop but will freeze in bluscreen if I am in a Kiosk account.
AppRestartFailureReason result = await CoreApplication.RequestRestartAsync("Restart");
Restarting the entire computer two times and enabling automatic updates will update the app without problems. Why is it not possible to use one of the methods above? Is this a bug in windows kiosk mode or is this really intended??
The same issue is also reported here:
problem-when-restart-app-on-kiosk-mode-windows-10
and here:
intune-kiosk-blue-screen-spinner-after-uwp-app-res
See my answer to how I made this work here:
The same problem described on microsoft docs
I don´t feel very confident with the whole assigned access and package installation concept. It works at the moment for me but my feeling is that it is not very stable. Many different ways of creating almost the same thing. The problem is that there are differences between the results depending on how you get there. For instance two assigne access accounts don´t behave the same if you created them differently. Also adding and removing both apps and accounts leaves trash that you don´t see but can cause problems.At least this is my feeling.

Disable github software updates

I’m using GitHub desktop version 3.3.6.1 (the older WPF-based one).
It works fine but it annoys me by offering to update to a new electron based version.
I don’t want Electron. How do I disable automatic updates of github?
The app calls CheckForUpdateAsync method of ApplicationDeployment class but it’s unclear how to disable that.
Wireshark shows it connects to github-windows.s3.amazonaws.com, tried blocking that address with my hosts file but that didn’t help.

Uninstalling items installed by an .app when user deletes it, including SMJobBless helpers

The short version: is it possible to delete helper tools which were set up by the app (SMJobBless() etc.) when the app is deleted? If so, how?
The long version:
The Mac app we are developing unfortunately requires admin privileges to perform an occasional operation, and it also requires a background task to be live for other apps' plugins to connect to even when the app itself isn't running (this one can be unprivileged). The app will be signed with a Developer ID certificate, and distributed only outside the App Store.
We'd like the app to be a "good citizen" as far as possible, also on uninstall.
For the background task, we're using a login item, created using SMLoginItemSetEnabled(). This isn't amazing, because XPC messaging doesn't seem to work (we're using CFMessagePort instead - alternative suggestions welcome), but if the user deletes the app, the login item at least doesn't get loaded anymore on next login. I suspect there's still a trace of it somewhere in the system, but the executable inside the .app bundle is used, and when that disappears, the login item no longer runs.
For the occasional operation requiring admin rights, we've got a privileged helper tool which our app installs using SMJobBless(), and which implements a named XPC service, so the task spins up on demand when it receives a message from the main app. This is what Apple recommends and describes in its Even Better Authorization Sample.
The helper executable is copied to /Library/PrivilegedHelperTools/ by SMJobBless(), and the embedded launchd.plist ends up in /Library/LaunchDaemons/. Even though the OS has the information on which app "owns" the helper, it doesn't seem to uninstall it when the user deletes the app. Apple's sample is silent on uninstalling, other than the uninstall.sh script which is apparently intended to be used during development only. We don't need this helper while the app isn't running, so installing it as a full-blown launch daemon is slightly overkill, but we'd also like to avoid repeatedly annoying the user with the password prompt too. Besides, Apple advises against other forms of running code with admin privileges than SMJobBless() these days - for example SMJobSubmit() is marked deprecated.
So how do we clean up after ourselves?
I've found SMJobRemove(), but (a) when would we call that in our case - you can't run code on .app bundle deletion, or can you? and (b) it doesn't actually seem to clean up.
The only 2 things I can think of are not terribly satisfying:
Some kind of uninstaller app or script. But that seems pretty ugly too.
Don't worry about it and just leave a mess behind when the user deletes our app.
Update:
There have been some changes in this area with macOS 13.0 Ventura; there's an introduction to the new mechanism in the WWDC22 session 'What’s new in privacy'. The new SMAppService APIs support automatic cleanup for daemons, agents and login items. Unfortunately you'll of course still have to find a workaround for any older macOS versions you support.
Original answer:
There has been a similar question on the Apple Developer Forums at https://forums.developer.apple.com/thread/66821 - the recommendation by Apple is a manual uninstall mechanism, and consuming as few resources as possible if the user does not do this.
Apple DTS staff further recommended implementing a self-uninstall mechanism in the privileged launch daemon, to be triggered from the app via XPC. This is what we're going with.
I think the only solution you have right now is to use the uninstall shell code that you mentioned in order to physically remove the privileged helper from disk or to build an uninstaller for it. Either way you will have to ask the user to enter his/her password. This what all installers / uninstallers that require privileged access to the system do, and for a very good reason. That's why I avoid like the plague to use privileged helpers, but I understand that sometimes you really have to. I don't think it is good that you leave such a helper in the user's system, because it will reload next time the user starts up the computer.
I just checked ServiceManagement.h header and they state that SMJobRemove will be replaced by an API that will be made available through libxpc in the future. (Sometimes you really need to go to the headers to get extra info that the documentation does not give you.) Hopefully this promised replacement will uninstall it for us. However, I'd file a bug report and ask for that enhancement.
One solution you could consider is to include an uninstaller script or program in your .app bundle.
You can then pass the path of this small tool to your helper tool (via IPC) and have the execute the the uninstaller, thereby deleting itself. You will have to be careful that components are removed in the right order but it can be made to work.
You're correct that Apple does not provide an API to uninstall a helper tool installed with SMJobBless nor do they do so automatically. As for why macOS doesn't automatically do an uninstall, my educated guess is because macOS fundamentally doesn't have a unified concept of "install". While it's convention for apps to be located in /Applications (and a few other locations), it's perfectly valid for apps to be located and run from anywhere on the system including external drives and network drives. For example should macOS uninstall helper tools when apps disappear because the drive they're on is disconnected?
In terms of how to uninstall, doing so requires root permission and so realistically have the helper tool itself do the uninstall is the easiest option. You can have your app via XPC tell the helper to uninstall itself. Here's an example in Swift of how to do this; it's part of SwiftAuthorizationSample. The basic idea is:
Use the launchctl command line tool to unload the helper tool
Delete the helper tool executable
Delete the helper tool launchd plist
But there's a bit of additional complexity involved because launchctl won't let you unload a running process.

Can an OSX app store app install a browser extension

I'm working for a client that is getting an OSX app ready for release. They have a stand-alone app that installs browser extensions for the major browsers.
Their new version will be an app store app.
Is it possible to drive the process of installing a browser extension from an OSX app store app? From what I've seen, you have to lead the user to download the extension and then open it from the finder or from the browser's list of downloaded files.
This makes for a rather disjointed, error-prone installation process. The user can fail to download the file, can fail to open the file, or can fail to return to the app to complete the installation process. All of those things are bad, especially since this app is going to be free, with optional paid upgrades. If the user doesn't complete the installation process, my client loses them as a potential upgrade (paid) client.
As of v25 Google Chrome implemented security features which would prevent any extensions installed offline by a 3rd party application from being activated without first being approved by the user via a dialog prompt in the browser.
Mozilla had implemented similar security measures over a year prior with Firefox 8
It's likely been patched by now, but it was reported that you could bypass Firefox security measures and accomplish a silent extension installation by copying the extension directly into the Firefox extension directory and add a record of it to the browsers Sqlite3 database. The database record involves adding a boolean true value to a property which specifies if the add-on has been approved or not.
Later versions of Firefox switched to using JSON rather than the Sqlite database and a similar process was still possible.
If I understand your question correctly.. This is potentially feasible regardless of vendor security but impossible for any public production level application due to such security because it will never be stable.
Vendors have a high priority in locking processes like this done to prevent potentially malicious 3rd party code. Interested in the subject I came across a few possibilities. I can't guarantee whether or not any of these will work but perhaps it will lead you in the right direction..
I would try to do this will Applescript to automate the user actions or potentially guide the user through the process.
You can open the extension with
[[NSWorkspace sharedWorkspace] openFile:#"path/to/myextension.safariextz" withApplication:#"Safari"];
but that only gets you started.
An alternative possibility was mentioned here: https://stackoverflow.com/a/4393062/1922144
And then there was a discussion here that seems worth noting.. https://discussions.apple.com/thread/3067552?tstart=0
safari.msi /i /qn BypassDefaultBrowserCheck=true

Detecting and launching an external application from within a Windows Phone 7.1/7.5 application

I need to write an application that can detect if the "Bing - Get me there" application is installed on the current phone and if so, launch it.
Is this possible? The app would need to do this for other external applications as well, so a generic method or interface for this would be helpful.
Applications run in a sandbox on Windows Phone and there is no way to tell if other applications are installed unless you are writing both of them and you use a method to announce to other applications that you are installed and they know how to read that announcement.
2 approaches to such announcements would be:
Have both (all) apps synchronise with a web server and report which devices they have been installed on. The apps can the query which other apps have been installed on that device.
Have all apps write a file to a location where all apps can access. The only place to do this is the PicturesLibrary so you have to embed the identifier in the name of the image or in its contents and be able to query all images to identify the other installed apps. The user could manually delete any images you create in this way though.
Beware, neither method can tell if the other app has subsequently been uninstalled though so this is far from foolproof.
As far as I know, there's no way to do that.
Applications on Windows Phone run in complete isolation, and can not act with other applications, other than some highly specialized apps (i.e. for playing media).

Resources