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.") } 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" diff --git a/src/gui/updater/sparkleupdater_mac.mm b/src/gui/updater/sparkleupdater_mac.mm index 062ca31a3d..ef167d9555 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: @@ -53,12 +52,12 @@ private: }; -@interface NCSparkleUpdaterDelegate : NSObject +@interface NCSparkleUpdaterDelegate : NSObject @property (readwrite, assign) OCC::SparkleUpdater::SparkleInterface *owner; +@property (readwrite, retain) NSString *feedURLString; - (instancetype)initWithOwner:(OCC::SparkleUpdater::SparkleInterface *)owner; -- (BOOL)updaterMayCheckForUpdates:(SUUpdater *)bundle; @end @@ -75,21 +74,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]; } @@ -100,12 +93,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 @@ -113,7 +106,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 @@ -121,7 +114,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) @@ -132,7 +125,7 @@ private: displayStatus:message]; } -- (void)updater:(SUUpdater *)updater didAbortWithError:(NSError *)error +- (void)updater:(nonnull SPUUpdater *)updater didAbortWithError:(nonnull NSError *)error { Q_UNUSED(updater) @@ -142,7 +135,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) @@ -150,30 +143,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) @@ -185,7 +180,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) @@ -196,7 +191,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) @@ -208,7 +203,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) @@ -219,7 +214,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) @@ -230,13 +225,19 @@ private: displayStatus:message]; } -- (void)userDidCancelDownload:(SUUpdater *)updater +- (void)userDidCancelDownload:(SPUUpdater *)updater { Q_UNUSED(updater); [self notifyStateChange:OCC::SparkleUpdater::State::Idle displayStatus:QObject::tr("Update download cancelled.")]; } +- (NSString *)feedURLStringForUpdater:(SPUUpdater *)updater +{ + Q_UNUSED(updater) + return self.feedURLString; +} + @end @@ -250,27 +251,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->delegate.feedURLString = url.toNSURL().absoluteString; } bool SparkleUpdater::autoUpdaterAllowed() @@ -295,7 +294,7 @@ void SparkleUpdater::checkForUpdate() { qCInfo(OCC::lcUpdater) << "Checking for updates."; if (autoUpdaterAllowed()) { - [_interface->updater checkForUpdates: NSApp]; + [_interface->updaterController.updater checkForUpdates]; } } @@ -303,7 +302,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"; }