Class AppUpdateCoordinator
- Namespace
- McServerLauncher.Services
- Assembly
- McServerLauncher.dll
Gets an update's package onto disk and proves it is the one the publisher made, in the order that makes a refusal cheap: everything that can say "no" is asked for before the download.
public sealed class AppUpdateCoordinator
- Inheritance
-
AppUpdateCoordinator
- Inherited Members
Remarks
This is the part of updating that decides whether the package is installed, taken out of
MainViewModel so it can be read — and tested — on its own. What stays in the view model is
what is about the screen: the text in the banner, stopping the servers, the fallback to the
release page. What is here never touches either.
The order is the design. The checksum and the signature are fetched first, so a release that lacks either is refused without costing the transfer of a ~35 MB installer. The checksum proves the download is whole. It comes from the same release as the package, so it proves nothing about who made it; the signature, checked against keys that do not live on GitHub, is what does, and it is just as mandatory (see UpdateSignature). A package that fails either check is deleted, so the next step cannot find it lying there.
None of the awaits here uses ConfigureAwait(false) on purpose: onPhase
is called back on the thread that started the update, which is the one allowed to change the
banner.
Constructors
AppUpdateCoordinator(IUpdateSource?, IReadOnlyList<string>?)
public AppUpdateCoordinator(IUpdateSource? source = null, IReadOnlyList<string>? trustedKeys = null)
Parameters
sourceIUpdateSourceWhere the files come from. The GitHub release by default.
trustedKeysIReadOnlyList<string>The public keys whose signature is accepted; the built-in ones when null. For tests: the real ones have no private half in the repository.
Methods
DiscardFolder(string)
Removes a folder an update downloaded into. Never throws: whatever stays is cleared at a later start (see DeleteOldPackages(string, DateTime)).
public static void DiscardFolder(string folder)
Parameters
folderstring
DownloadAndVerifyAsync(UpdateInfo, string, Action<Phase>?, CancellationToken)
Downloads the package of offer into folder and returns
it, with the checksum it matched, once the checksum and the signature both hold.
public Task<AppUpdateCoordinator.VerifiedPackage> DownloadAndVerifyAsync(UpdateService.UpdateInfo offer, string folder, Action<AppUpdateCoordinator.Phase>? onPhase = null, CancellationToken ct = default)
Parameters
offerUpdateService.UpdateInfoThe release being installed.
folderstringWhere the package is saved; see NewPackageFolder().
onPhaseAction<AppUpdateCoordinator.Phase>Told when each step starts. Called on the caller's context.
ctCancellationTokenCancels the download.
Returns
Exceptions
- UserFacingException
With a message for the user: the release has no readable checksum or signature, the download does not match the checksum, or the signature is not the publisher's.
NewPackageFolder()
A new folder name for one update to download into.
public static string NewPackageFolder()
Returns
Remarks
Random on every run: a fixed name in the temporary folder could be planted, or replaced, by another local process between the download and the moment the package runs. The folder is not created here; AtomicDownload creates it.