From 51ffdb2a531e6b017e1f9d094d7c594a0fe985ad Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 14 Jan 2025 12:58:38 +0800 Subject: [PATCH 1/5] mac-crafter: Update Sparkle version to 2.6.4 Signed-off-by: Claudio Cambra --- admin/osx/mac-crafter/Sources/main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/osx/mac-crafter/Sources/main.swift b/admin/osx/mac-crafter/Sources/main.swift index 654954ec96..f7d723b80e 100644 --- a/admin/osx/mac-crafter/Sources/main.swift +++ b/admin/osx/mac-crafter/Sources/main.swift @@ -60,7 +60,7 @@ struct Build: ParsableCommand { @Option(name: [.long], help: "Sparkle download URL.") var sparkleDownloadUrl = - "https://github.com/sparkle-project/Sparkle/releases/download/1.27.3/Sparkle-1.27.3.tar.xz" + "https://github.com/sparkle-project/Sparkle/releases/download/2.6.4/Sparkle-2.6.4.tar.xz" @Option(name: [.long], help: "Git clone command; include options such as depth.") var gitCloneCommand = "git clone --depth=1" From 2cce2636efca77ec36a3577ba493a92ee1a4edd3 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 14 Jan 2025 13:02:00 +0800 Subject: [PATCH 2/5] updater: Replace SUUpdater with SPUStandardUpdaterController Signed-off-by: Claudio Cambra --- src/gui/updater/sparkleupdater_mac.mm | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/gui/updater/sparkleupdater_mac.mm b/src/gui/updater/sparkleupdater_mac.mm index 062ca31a3d..49285c3175 100644 --- a/src/gui/updater/sparkleupdater_mac.mm +++ b/src/gui/updater/sparkleupdater_mac.mm @@ -15,7 +15,6 @@ #include #include -#include #include #include "common/utility.h" @@ -34,7 +33,7 @@ public: ~SparkleInterface() { - [updater release]; + [updaterController release]; [delegate release]; } @@ -45,7 +44,7 @@ public: emit q->statusChanged(); } - SUUpdater* updater; + SPUStandardUpdaterController *updaterController; NCSparkleUpdaterDelegate *delegate; private: @@ -250,27 +249,25 @@ SparkleUpdater::SparkleUpdater(const QUrl& appCastUrl) _interface->delegate = [[NCSparkleUpdaterDelegate alloc] initWithOwner:_interface.get()]; [_interface->delegate retain]; - _interface->updater = [SUUpdater sharedUpdater]; - [_interface->updater setDelegate:_interface->delegate]; - [_interface->updater setAutomaticallyChecksForUpdates:YES]; - [_interface->updater setAutomaticallyDownloadsUpdates:NO]; - [_interface->updater setSendsSystemProfile:NO]; - [_interface->updater resetUpdateCycle]; - [_interface->updater retain]; + _interface->updaterController = + [[SPUStandardUpdaterController alloc] initWithStartingUpdater:YES + updaterDelegate:_interface->delegate + userDriverDelegate:nil]; + [_interface->updaterController retain]; setUpdateUrl(appCastUrl); // Sparkle 1.8 required const auto userAgentString = QString::fromUtf8(Utility::userAgentString()); - NSString *userAgent = userAgentString.toNSString(); - [_interface->updater setUserAgentString: userAgent]; + NSString *const userAgent = userAgentString.toNSString(); + _interface->updaterController.updater.userAgentString = userAgent; } SparkleUpdater::~SparkleUpdater() = default; void SparkleUpdater::setUpdateUrl(const QUrl &url) { - [_interface->updater setFeedURL:url.toNSURL()]; + _interface->updaterController.updater.feedURL = url.toNSURL(); } bool SparkleUpdater::autoUpdaterAllowed() @@ -295,7 +292,7 @@ void SparkleUpdater::checkForUpdate() { qCInfo(OCC::lcUpdater) << "Checking for updates."; if (autoUpdaterAllowed()) { - [_interface->updater checkForUpdates: NSApp]; + [_interface->updaterController.updater checkForUpdates]; } } @@ -303,7 +300,7 @@ void SparkleUpdater::backgroundCheckForUpdate() { if (autoUpdaterAllowed() && !ConfigFile().skipUpdateCheck()) { qCInfo(OCC::lcUpdater) << "launching background check"; - [_interface->updater checkForUpdatesInBackground]; + [_interface->updaterController.updater checkForUpdatesInBackground]; } else { qCInfo(OCC::lcUpdater) << "not launching background check, auto updater not allowed or update check skipped in config"; } From bbde9bb2377d52c2540b2b70b74d12109a1df68a Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 14 Jan 2025 13:03:57 +0800 Subject: [PATCH 3/5] updater: Refactor NCSparkleUpdaterDelegate to conform to SPUUpdaterDelegate Signed-off-by: Claudio Cambra --- src/gui/updater/sparkleupdater_mac.mm | 75 +++++++++++++-------------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/src/gui/updater/sparkleupdater_mac.mm b/src/gui/updater/sparkleupdater_mac.mm index 49285c3175..55925c1973 100644 --- a/src/gui/updater/sparkleupdater_mac.mm +++ b/src/gui/updater/sparkleupdater_mac.mm @@ -52,12 +52,11 @@ private: }; -@interface NCSparkleUpdaterDelegate : NSObject +@interface NCSparkleUpdaterDelegate : NSObject @property (readwrite, assign) OCC::SparkleUpdater::SparkleInterface *owner; - (instancetype)initWithOwner:(OCC::SparkleUpdater::SparkleInterface *)owner; -- (BOOL)updaterMayCheckForUpdates:(SUUpdater *)bundle; @end @@ -74,21 +73,15 @@ private: - (BOOL)backgroundUpdateChecksAllowed { - BOOL allowUpdateCheck = OCC::ConfigFile().skipUpdateCheck() ? NO : YES; + const BOOL allowUpdateCheck = OCC::ConfigFile().skipUpdateCheck() ? NO : YES; qCInfo(OCC::lcUpdater) << "Updater may check for updates:" << (allowUpdateCheck ? "YES" : "NO"); return allowUpdateCheck; } -- (BOOL)updaterMayCheckForUpdates:(SUUpdater *)bundle -{ - Q_UNUSED(bundle) - return [self backgroundUpdateChecksAllowed]; -} - -- (BOOL)updaterShouldShowUpdateAlertForScheduledUpdate:(SUUpdater *)updater forItem:(SUAppcastItem *)item +- (BOOL)updater:(nonnull SPUUpdater *)updater mayPerformUpdateCheck:(SPUUpdateCheck)updateCheck error:(NSError **)error { Q_UNUSED(updater) - Q_UNUSED(item) + Q_UNUSED(updateCheck) return [self backgroundUpdateChecksAllowed]; } @@ -99,12 +92,12 @@ private: } // Sent when a valid update is found by the update driver. -- (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update +- (void)updater:(nonnull SPUUpdater *)updater didFindValidUpdate:(nonnull SUAppcastItem *)item { Q_UNUSED(updater) - Q_UNUSED(update) + Q_UNUSED(item) - const auto versionQstring = QString::fromNSString(update.displayVersionString); + const auto versionQstring = QString::fromNSString(item.displayVersionString); const auto message = QObject::tr("Found a valid update: version %1", "%1 is version number").arg(versionQstring); [self notifyStateChange:OCC::SparkleUpdater::State::AwaitingUserInput @@ -112,7 +105,7 @@ private: } // Sent when a valid update is not found. -- (void)updaterDidNotFindUpdate:(SUUpdater *)updater +- (void)updaterDidNotFindUpdate:(nonnull SPUUpdater *)updater { Q_UNUSED(updater) [self notifyStateChange:OCC::SparkleUpdater::State::Idle @@ -120,7 +113,7 @@ private: } // Sent immediately before installing the specified update. -- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update +- (void)updater:(nonnull SPUUpdater *)updater willInstallUpdate:(nonnull SUAppcastItem *)update { Q_UNUSED(updater) @@ -131,7 +124,7 @@ private: displayStatus:message]; } -- (void)updater:(SUUpdater *)updater didAbortWithError:(NSError *)error +- (void)updater:(nonnull SPUUpdater *)updater didAbortWithError:(nonnull NSError *)error { Q_UNUSED(updater) @@ -141,7 +134,7 @@ private: displayStatus:message]; } -- (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast +- (void)updater:(nonnull SPUUpdater *)updater didFinishLoadingAppcast:(nonnull SUAppcast *)appcast { Q_UNUSED(updater) Q_UNUSED(appcast) @@ -149,30 +142,32 @@ private: displayStatus:QObject::tr("Finished loading appcast.")]; } -- (void)updater:(SUUpdater *)updater didDismissUpdateAlertPermanently:(BOOL)permanently forItem:(nonnull SUAppcastItem *)item -{ - Q_UNUSED(updater) - - const auto permanencyString = permanently ? QObject::tr("Permanently") : QObject::tr("Temporarily"); - const auto versionQstring = QString::fromNSString(item.displayVersionString); - const auto message = QObject::tr("%1 dismissed %2 update", "%1 is permanently or temporarily, %2 is version number").arg(permanencyString, versionQstring); - - [self notifyStateChange:OCC::SparkleUpdater::State::Idle - displayStatus:message]; -} - -- (void)updater:(nonnull SUUpdater *)updater userDidSkipThisVersion:(nonnull SUAppcastItem *)item +- (void)updater:(nonnull SPUUpdater *)updater +userDidMakeChoice:(SPUUserUpdateChoice)choice + forUpdate:(nonnull SUAppcastItem *)item + state:(nonnull SPUUserUpdateState *)state { Q_UNUSED(updater) const auto versionQstring = QString::fromNSString(item.displayVersionString); - const auto message = QObject::tr("Update version %1 will not be applied as it was chosen to be skipped.", "%1 is version number").arg(versionQstring); + QString message; - [self notifyStateChange:OCC::SparkleUpdater::State::Idle - displayStatus:message]; + switch(choice) { + case SPUUserUpdateChoiceSkip: + message = QObject::tr("Update version %1 will not be applied as it was chosen to be skipped.", "%1 is version number").arg(versionQstring); + break; + case SPUUserUpdateChoiceInstall: + message = QObject::tr("Update version %1 will be installed.", "%1 is version number").arg(versionQstring); + break; + case SPUUserUpdateChoiceDismiss: + message = QObject::tr("Update version %1 will not be applied as it was dismissed.", "%1 is version number").arg(versionQstring); + break; + } + + [self notifyStateChange:OCC::SparkleUpdater::State::Idle displayStatus:message]; } -- (void)updater:(nonnull SUUpdater *)updater willDownloadUpdate:(nonnull SUAppcastItem *)item withRequest:(nonnull NSMutableURLRequest *)request +- (void)updater:(nonnull SPUUpdater *)updater willDownloadUpdate:(nonnull SUAppcastItem *)item withRequest:(nonnull NSMutableURLRequest *)request { Q_UNUSED(updater) Q_UNUSED(request) @@ -184,7 +179,7 @@ private: displayStatus:message]; } -- (void)updater:(nonnull SUUpdater *)updater didDownloadUpdate:(nonnull SUAppcastItem *)item +- (void)updater:(nonnull SPUUpdater *)updater didDownloadUpdate:(nonnull SUAppcastItem *)item { Q_UNUSED(updater) @@ -195,7 +190,7 @@ private: displayStatus:message]; } -- (void)updater:(nonnull SUUpdater *)updater failedToDownloadUpdate:(nonnull SUAppcastItem *)item error:(nonnull NSError *)error +- (void)updater:(nonnull SPUUpdater *)updater failedToDownloadUpdate:(nonnull SUAppcastItem *)item error:(nonnull NSError *)error { Q_UNUSED(updater) @@ -207,7 +202,7 @@ private: displayStatus:message]; } -- (void)updater:(nonnull SUUpdater *)updater willExtractUpdate:(nonnull SUAppcastItem *)item +- (void)updater:(nonnull SPUUpdater *)updater willExtractUpdate:(nonnull SUAppcastItem *)item { Q_UNUSED(updater) @@ -218,7 +213,7 @@ private: displayStatus:message]; } -- (void)updater:(nonnull SUUpdater *)updater didExtractUpdate:(nonnull SUAppcastItem *)item +- (void)updater:(nonnull SPUUpdater *)updater didExtractUpdate:(nonnull SUAppcastItem *)item { Q_UNUSED(updater) @@ -229,7 +224,7 @@ private: displayStatus:message]; } -- (void)userDidCancelDownload:(SUUpdater *)updater +- (void)userDidCancelDownload:(SPUUpdater *)updater { Q_UNUSED(updater); [self notifyStateChange:OCC::SparkleUpdater::State::Idle From d16efb07279452cce5957850f9dadbb58033e77e Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 14 Jan 2025 13:43:58 +0800 Subject: [PATCH 4/5] mac-crafter: Apply code-signing procedure on Sparkle as recommended by Sparkle docs Signed-off-by: Claudio Cambra --- .../mac-crafter/Sources/Utils/Codesign.swift | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/admin/osx/mac-crafter/Sources/Utils/Codesign.swift b/admin/osx/mac-crafter/Sources/Utils/Codesign.swift index f262ff39d7..1f43d3e49a 100644 --- a/admin/osx/mac-crafter/Sources/Utils/Codesign.swift +++ b/admin/osx/mac-crafter/Sources/Utils/Codesign.swift @@ -126,17 +126,31 @@ func codesignClientAppBundle( // We need to strip these out manually. let sparkleFrameworkPath = "\(frameworksPath)/Sparkle.framework" - if FileManager.default.fileExists(atPath: "\(sparkleFrameworkPath)/Resources/Autoupdate.app") { - print("Code-signing Sparkle autoupdater app (without entitlements)...") - - try recursivelyCodesign( - path: "\(sparkleFrameworkPath)/Resources/Autoupdate.app", + if FileManager.default.fileExists(atPath: sparkleFrameworkPath) { + print("Code-signing Sparkle...") + try codesign( identity: codeSignIdentity, - options: "--timestamp --force --verbose=4 --options runtime --deep" + path: "\(sparkleFrameworkPath)/Versions/B/XPCServices/Installer.xpc", + options: "-f -o runtime" + ) + try codesign( + identity: codeSignIdentity, + path: "\(sparkleFrameworkPath)/Versions/B/XPCServices/Downloader.xpc", + options: "-f -o runtime --preserve-metadata=entitlements" + ) + try codesign( + identity: codeSignIdentity, + path: "\(sparkleFrameworkPath)/Versions/B/Autoupdate", + options: "-f -o runtime" + ) + try codesign( + identity: codeSignIdentity, + path: "\(sparkleFrameworkPath)/Versions/B/Updater.app", + options: "-f -o runtime" + ) + try codesign( + identity: codeSignIdentity, path: sparkleFrameworkPath, options: "-f -o runtime" ) - - print("Re-codesigning Sparkle library...") - try codesign(identity: codeSignIdentity, path: "\(sparkleFrameworkPath)/Sparkle") } else { print("Build does not have Sparkle, skipping.") } From 12dee2fb16c6a11b79d9721172da287674cd0589 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 14 Jan 2025 13:44:38 +0800 Subject: [PATCH 5/5] updater: Provide feedURL via non-deprecated delegate method Signed-off-by: Claudio Cambra --- src/gui/updater/sparkleupdater_mac.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gui/updater/sparkleupdater_mac.mm b/src/gui/updater/sparkleupdater_mac.mm index 55925c1973..ef167d9555 100644 --- a/src/gui/updater/sparkleupdater_mac.mm +++ b/src/gui/updater/sparkleupdater_mac.mm @@ -55,6 +55,7 @@ private: @interface NCSparkleUpdaterDelegate : NSObject @property (readwrite, assign) OCC::SparkleUpdater::SparkleInterface *owner; +@property (readwrite, retain) NSString *feedURLString; - (instancetype)initWithOwner:(OCC::SparkleUpdater::SparkleInterface *)owner; @@ -231,6 +232,12 @@ userDidMakeChoice:(SPUUserUpdateChoice)choice displayStatus:QObject::tr("Update download cancelled.")]; } +- (NSString *)feedURLStringForUpdater:(SPUUpdater *)updater +{ + Q_UNUSED(updater) + return self.feedURLString; +} + @end @@ -262,7 +269,7 @@ SparkleUpdater::~SparkleUpdater() = default; void SparkleUpdater::setUpdateUrl(const QUrl &url) { - _interface->updaterController.updater.feedURL = url.toNSURL(); + _interface->delegate.feedURLString = url.toNSURL().absoluteString; } bool SparkleUpdater::autoUpdaterAllowed()