diff options
Diffstat (limited to 'launcher/updater')
20 files changed, 536 insertions, 598 deletions
diff --git a/launcher/updater/DownloadTask_test.cpp b/launcher/updater/DownloadTask_test.cpp deleted file mode 100644 index deba2632..00000000 --- a/launcher/updater/DownloadTask_test.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include <QTest> -#include <QSignalSpy> - -#include "updater/GoUpdate.h" -#include "updater/DownloadTask.h" -#include "updater/UpdateChecker.h" -#include <FileSystem.h> - -using namespace GoUpdate; - -FileSourceList encodeBaseFile(const char *suffix) -{ - auto base = QDir::currentPath(); - QUrl localFile = QUrl::fromLocalFile(base + suffix); - QString localUrlString = localFile.toString(QUrl::FullyEncoded); - auto item = FileSource("http", localUrlString); - return FileSourceList({item}); -} - -Q_DECLARE_METATYPE(VersionFileList) -Q_DECLARE_METATYPE(Operation) - -QDebug operator<<(QDebug dbg, const FileSource &f) -{ - dbg.nospace() << "FileSource(type=" << f.type << " url=" << f.url - << " comp=" << f.compressionType << ")"; - return dbg.maybeSpace(); -} - -QDebug operator<<(QDebug dbg, const VersionFileEntry &v) -{ - dbg.nospace() << "VersionFileEntry(path=" << v.path << " mode=" << v.mode - << " md5=" << v.md5 << " sources=" << v.sources << ")"; - return dbg.maybeSpace(); -} - -QDebug operator<<(QDebug dbg, const Operation::Type &t) -{ - switch (t) - { - case Operation::OP_REPLACE: - dbg << "OP_COPY"; - break; - case Operation::OP_DELETE: - dbg << "OP_DELETE"; - break; - } - return dbg.maybeSpace(); -} - -QDebug operator<<(QDebug dbg, const Operation &u) -{ - dbg.nospace() << "Operation(type=" << u.type << " file=" << u.source - << " dest=" << u.destination << " mode=" << u.destinationMode << ")"; - return dbg.maybeSpace(); -} - -class DownloadTaskTest : public QObject -{ - Q_OBJECT -private -slots: - void initTestCase() - { - } - void cleanupTestCase() - { - } - - void test_parseVersionInfo_data() - { - QFile f1(QFINDTESTDATA("testdata/1.json")); - f1.open(QFile::ReadOnly); - QByteArray data1 = f1.readAll(); - f1.close(); - - QFile f2(QFINDTESTDATA("testdata/2.json")); - f2.open(QFile::ReadOnly); - QByteArray data2 = f2.readAll(); - f2.close(); - - QTest::addColumn<QByteArray>("data"); - QTest::addColumn<VersionFileList>("list"); - QTest::addColumn<QString>("error"); - QTest::addColumn<bool>("ret"); - - QTest::newRow("one") - << data1 - << (VersionFileList() - << VersionFileEntry{"fileOne", - 493, - encodeBaseFile("/data/fileOneA"), - "9eb84090956c484e32cb6c08455a667b"} - << VersionFileEntry{"fileTwo", - 644, - encodeBaseFile("/data/fileTwo"), - "38f94f54fa3eb72b0ea836538c10b043"} - << VersionFileEntry{"fileThree", - 750, - encodeBaseFile("/data/fileThree"), - "f12df554b21e320be6471d7154130e70"}) - << QString() << true; - QTest::newRow("two") - << data2 - << (VersionFileList() - << VersionFileEntry{"fileOne", - 493, - encodeBaseFile("/data/fileOneB"), - "42915a71277c9016668cce7b82c6b577"} - << VersionFileEntry{"fileTwo", - 644, - encodeBaseFile("/data/fileTwo"), - "38f94f54fa3eb72b0ea836538c10b043"}) - << QString() << true; - } - void test_parseVersionInfo() - { - QFETCH(QByteArray, data); - QFETCH(VersionFileList, list); - QFETCH(QString, error); - QFETCH(bool, ret); - - VersionFileList outList; - QString outError; - bool outRet = parseVersionInfo(data, outList, outError); - QCOMPARE(outRet, ret); - QCOMPARE(outList, list); - QCOMPARE(outError, error); - } - - void test_processFileLists_data() - { - QTest::addColumn<QString>("tempFolder"); - QTest::addColumn<VersionFileList>("currentVersion"); - QTest::addColumn<VersionFileList>("newVersion"); - QTest::addColumn<OperationList>("expectedOperations"); - - QTemporaryDir tempFolderObj; - QString tempFolder = tempFolderObj.path(); - // update fileOne, keep fileTwo, remove fileThree - QTest::newRow("test 1") - << tempFolder << (VersionFileList() - << VersionFileEntry{ - QFINDTESTDATA("testdata/fileOne"), 493, - FileSourceList() - << FileSource( - "http", "http://host/path/fileOne-1"), - "9eb84090956c484e32cb6c08455a667b"} - << VersionFileEntry{ - QFINDTESTDATA("testdata/fileTwo"), 644, - FileSourceList() - << FileSource( - "http", "http://host/path/fileTwo-1"), - "38f94f54fa3eb72b0ea836538c10b043"} - << VersionFileEntry{ - QFINDTESTDATA("testdata/fileThree"), 420, - FileSourceList() - << FileSource( - "http", "http://host/path/fileThree-1"), - "f12df554b21e320be6471d7154130e70"}) - << (VersionFileList() - << VersionFileEntry{ - QFINDTESTDATA("testdata/fileOne"), 493, - FileSourceList() - << FileSource("http", - "http://host/path/fileOne-2"), - "42915a71277c9016668cce7b82c6b577"} - << VersionFileEntry{ - QFINDTESTDATA("testdata/fileTwo"), 644, - FileSourceList() - << FileSource("http", - "http://host/path/fileTwo-2"), - "38f94f54fa3eb72b0ea836538c10b043"}) - << (OperationList() - << Operation::DeleteOp(QFINDTESTDATA("testdata/fileThree")) - << Operation::CopyOp( - FS::PathCombine(tempFolder, - QFINDTESTDATA("data/fileOne").replace("/", "_")), - QFINDTESTDATA("data/fileOne"), 493)); - } - void test_processFileLists() - { - QFETCH(QString, tempFolder); - QFETCH(VersionFileList, currentVersion); - QFETCH(VersionFileList, newVersion); - QFETCH(OperationList, expectedOperations); - - OperationList operations; - - shared_qobject_ptr<QNetworkAccessManager> network = new QNetworkAccessManager(); - processFileLists(currentVersion, newVersion, QDir::currentPath(), tempFolder, new NetJob("Dummy", network), operations); - qDebug() << (operations == expectedOperations); - qDebug() << operations; - qDebug() << expectedOperations; - QCOMPARE(operations, expectedOperations); - } -}; - -extern "C" -{ - QTEST_GUILESS_MAIN(DownloadTaskTest) -} - -#include "DownloadTask_test.moc" diff --git a/launcher/updater/ExternalUpdater.h b/launcher/updater/ExternalUpdater.h new file mode 100644 index 00000000..a053e081 --- /dev/null +++ b/launcher/updater/ExternalUpdater.h @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (C) 2022 Kenneth Chew <kenneth.c0@protonmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef LAUNCHER_EXTERNALUPDATER_H +#define LAUNCHER_EXTERNALUPDATER_H + +#include <QObject> + +/*! + * A base class for an updater that uses an external library. + * This class contains basic functions to control the updater. + * + * To implement the updater on a new platform, create a new class that inherits from this class and + * implement the pure virtual functions. + * + * The initializer of the new class should have the side effect of starting the automatic updater. That is, + * once the class is initialized, the program should automatically check for updates if necessary. + */ +class ExternalUpdater : public QObject +{ + Q_OBJECT + +public: + /*! + * Check for updates manually, showing the user a progress bar and an alert if no updates are found. + */ + virtual void checkForUpdates() = 0; + + /*! + * Indicates whether or not to check for updates automatically. + */ + virtual bool getAutomaticallyChecksForUpdates() = 0; + + /*! + * Indicates the current automatic update check interval in seconds. + */ + virtual double getUpdateCheckInterval() = 0; + + /*! + * Indicates whether or not beta updates should be checked for in addition to regular releases. + */ + virtual bool getBetaAllowed() = 0; + + /*! + * Set whether or not to check for updates automatically. + */ + virtual void setAutomaticallyChecksForUpdates(bool check) = 0; + + /*! + * Set the current automatic update check interval in seconds. + */ + virtual void setUpdateCheckInterval(double seconds) = 0; + + /*! + * Set whether or not beta updates should be checked for in addition to regular releases. + */ + virtual void setBetaAllowed(bool allowed) = 0; + +signals: + /*! + * Emits whenever the user's ability to check for updates changes. + * + * As per Sparkle documentation, "An update check can be made by the user when an update session isn’t in progress, + * or when an update or its progress is being shown to the user. A user cannot check for updates when data (such + * as the feed or an update) is still being downloaded automatically in the background. + * + * This property is suitable to use for menu item validation for seeing if checkForUpdates can be invoked." + */ + void canCheckForUpdatesChanged(bool canCheck); +}; + +#endif //LAUNCHER_EXTERNALUPDATER_H diff --git a/launcher/updater/MacSparkleUpdater.h b/launcher/updater/MacSparkleUpdater.h new file mode 100644 index 00000000..d50dbd68 --- /dev/null +++ b/launcher/updater/MacSparkleUpdater.h @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (C) 2022 Kenneth Chew <kenneth.c0@protonmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef LAUNCHER_MACSPARKLEUPDATER_H +#define LAUNCHER_MACSPARKLEUPDATER_H + +#include <QObject> +#include <QSet> +#include "ExternalUpdater.h" + +/*! + * An implementation for the updater on macOS that uses the Sparkle framework. + */ +class MacSparkleUpdater : public ExternalUpdater +{ + Q_OBJECT + +public: + /*! + * Start the Sparkle updater, which automatically checks for updates if necessary. + */ + MacSparkleUpdater(); + ~MacSparkleUpdater() override; + + /*! + * Check for updates manually, showing the user a progress bar and an alert if no updates are found. + */ + void checkForUpdates() override; + + /*! + * Indicates whether or not to check for updates automatically. + */ + bool getAutomaticallyChecksForUpdates() override; + + /*! + * Indicates the current automatic update check interval in seconds. + */ + double getUpdateCheckInterval() override; + + /*! + * Indicates the set of Sparkle channels the updater is allowed to find new updates from. + */ + QSet<QString> getAllowedChannels(); + + /*! + * Indicates whether or not beta updates should be checked for in addition to regular releases. + */ + bool getBetaAllowed() override; + + /*! + * Set whether or not to check for updates automatically. + * + * As per Sparkle documentation, "By default, Sparkle asks users on second launch for permission if they want + * automatic update checks enabled and sets this property based on their response. If SUEnableAutomaticChecks is + * set in the Info.plist, this permission request is not performed however. + * + * Setting this property will persist in the host bundle’s user defaults. Only set this property if you need + * dynamic behavior (e.g. user preferences). + * + * The update schedule cycle will be reset in a short delay after the property’s new value is set. This is to allow + * reverting this property without kicking off a schedule change immediately." + */ + void setAutomaticallyChecksForUpdates(bool check) override; + + /*! + * Set the current automatic update check interval in seconds. + * + * As per Sparkle documentation, "Setting this property will persist in the host bundle’s user defaults. For this + * reason, only set this property if you need dynamic behavior (eg user preferences). Otherwise prefer to set + * SUScheduledCheckInterval directly in your Info.plist. + * + * The update schedule cycle will be reset in a short delay after the property’s new value is set. This is to allow + * reverting this property without kicking off a schedule change immediately." + */ + void setUpdateCheckInterval(double seconds) override; + + /*! + * Clears all allowed Sparkle channels, returning to the default updater channel behavior. + */ + void clearAllowedChannels(); + + /*! + * Set a single Sparkle channel the updater is allowed to find new updates from. + * + * Items in the default channel can always be found, regardless of this setting. If an empty string is passed, + * return to the default behavior. + */ + void setAllowedChannel(const QString& channel); + + /*! + * Set a set of Sparkle channels the updater is allowed to find new updates from. + * + * Items in the default channel can always be found, regardless of this setting. If an empty set is passed, + * return to the default behavior. + */ + void setAllowedChannels(const QSet<QString>& channels); + + /*! + * Set whether or not beta updates should be checked for in addition to regular releases. + */ + void setBetaAllowed(bool allowed) override; + +private: + class Private; + + Private *priv; + + void loadChannelsFromSettings(); +}; + +#endif //LAUNCHER_MACSPARKLEUPDATER_H diff --git a/launcher/updater/MacSparkleUpdater.mm b/launcher/updater/MacSparkleUpdater.mm new file mode 100644 index 00000000..ca6da55a --- /dev/null +++ b/launcher/updater/MacSparkleUpdater.mm @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (C) 2022 Kenneth Chew <kenneth.c0@protonmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "MacSparkleUpdater.h" + +#include "Application.h" + +#include <Cocoa/Cocoa.h> +#include <Sparkle/Sparkle.h> + +@interface UpdaterObserver : NSObject + +@property(nonatomic, readonly) SPUUpdater* updater; + +/// A callback to run when the state of `canCheckForUpdates` for the `updater` changes. +@property(nonatomic, copy) void (^callback) (bool); + +- (id)initWithUpdater:(SPUUpdater*)updater; + +@end + +@implementation UpdaterObserver + +- (id)initWithUpdater:(SPUUpdater*)updater +{ + self = [super init]; + _updater = updater; + [self addObserver:self forKeyPath:@"updater.canCheckForUpdates" options:NSKeyValueObservingOptionNew context:nil]; + + return self; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary<NSKeyValueChangeKey, id> *)change + context:(void *)context +{ + if ([keyPath isEqualToString:@"updater.canCheckForUpdates"]) + { + bool canCheck = [change[NSKeyValueChangeNewKey] boolValue]; + self.callback(canCheck); + } +} + +@end + + +@interface UpdaterDelegate : NSObject <SPUUpdaterDelegate> + +@property(nonatomic, copy) NSSet<NSString *> *allowedChannels; + +@end + +@implementation UpdaterDelegate + +- (NSSet<NSString *> *)allowedChannelsForUpdater:(SPUUpdater *)updater +{ + return _allowedChannels; +} + +@end + + +class MacSparkleUpdater::Private +{ +public: + SPUStandardUpdaterController *updaterController; + UpdaterObserver *updaterObserver; + UpdaterDelegate *updaterDelegate; + NSAutoreleasePool *autoReleasePool; +}; + +MacSparkleUpdater::MacSparkleUpdater() +{ + priv = new MacSparkleUpdater::Private(); + + // Enable Cocoa's memory management. + NSApplicationLoad(); + priv->autoReleasePool = [[NSAutoreleasePool alloc] init]; + + // Delegate is used for setting/getting allowed update channels. + priv->updaterDelegate = [[UpdaterDelegate alloc] init]; + + // Controller is the interface for actually doing the updates. + priv->updaterController = [[SPUStandardUpdaterController alloc] initWithStartingUpdater:true + updaterDelegate:priv->updaterDelegate + userDriverDelegate:nil]; + + priv->updaterObserver = [[UpdaterObserver alloc] initWithUpdater:priv->updaterController.updater]; + // Use KVO to run a callback that emits a Qt signal when `canCheckForUpdates` changes, so the UI can respond accordingly. + priv->updaterObserver.callback = ^(bool canCheck) { + emit canCheckForUpdatesChanged(canCheck); + }; + + loadChannelsFromSettings(); +} + +MacSparkleUpdater::~MacSparkleUpdater() +{ + [priv->updaterObserver removeObserver:priv->updaterObserver forKeyPath:@"updater.canCheckForUpdates"]; + + [priv->updaterController release]; + [priv->updaterObserver release]; + [priv->updaterDelegate release]; + [priv->autoReleasePool release]; + delete priv; +} + +void MacSparkleUpdater::checkForUpdates() +{ + [priv->updaterController checkForUpdates:nil]; +} + +bool MacSparkleUpdater::getAutomaticallyChecksForUpdates() +{ + return priv->updaterController.updater.automaticallyChecksForUpdates; +} + +double MacSparkleUpdater::getUpdateCheckInterval() +{ + return priv->updaterController.updater.updateCheckInterval; +} + +QSet<QString> MacSparkleUpdater::getAllowedChannels() +{ + // Convert NSSet<NSString> -> QSet<QString> + __block QSet<QString> channels; + [priv->updaterDelegate.allowedChannels enumerateObjectsUsingBlock:^(NSString *channel, BOOL *stop) + { + channels.insert(QString::fromNSString(channel)); + }]; + return channels; +} + +bool MacSparkleUpdater::getBetaAllowed() +{ + return getAllowedChannels().contains("beta"); +} + +void MacSparkleUpdater::setAutomaticallyChecksForUpdates(bool check) +{ + priv->updaterController.updater.automaticallyChecksForUpdates = check ? YES : NO; // make clang-tidy happy +} + +void MacSparkleUpdater::setUpdateCheckInterval(double seconds) +{ + priv->updaterController.updater.updateCheckInterval = seconds; +} + +void MacSparkleUpdater::clearAllowedChannels() +{ + priv->updaterDelegate.allowedChannels = [NSSet set]; + APPLICATION->settings()->set("UpdateChannel", ""); +} + +void MacSparkleUpdater::setAllowedChannel(const QString &channel) +{ + if (channel.isEmpty()) + { + clearAllowedChannels(); + return; + } + + NSSet<NSString *> *nsChannels = [NSSet setWithObject:channel.toNSString()]; + priv->updaterDelegate.allowedChannels = nsChannels; + APPLICATION->settings()->set("UpdateChannel", channel); +} + +void MacSparkleUpdater::setAllowedChannels(const QSet<QString> &channels) +{ + if (channels.isEmpty()) + { + clearAllowedChannels(); + return; + } + + QString channelsConfig = ""; + // Convert QSet<QString> -> NSSet<NSString> + NSMutableSet<NSString *> *nsChannels = [NSMutableSet setWithCapacity:channels.count()]; + foreach (const QString channel, channels) + { + [nsChannels addObject:channel.toNSString()]; + channelsConfig += channel + " "; + } + + priv->updaterDelegate.allowedChannels = nsChannels; + APPLICATION->settings()->set("UpdateChannel", channelsConfig.trimmed()); +} + +void MacSparkleUpdater::setBetaAllowed(bool allowed) +{ + if (allowed) + { + setAllowedChannel("beta"); + } + else + { + clearAllowedChannels(); + } +} + +void MacSparkleUpdater::loadChannelsFromSettings() +{ + QStringList channelList = APPLICATION->settings()->get("UpdateChannel").toString().split(" "); + QSet<QString> channels(channelList.begin(), channelList.end()); + setAllowedChannels(channels); +} diff --git a/launcher/updater/UpdateChecker.cpp b/launcher/updater/UpdateChecker.cpp index efdb6093..78d979ff 100644 --- a/launcher/updater/UpdateChecker.cpp +++ b/launcher/updater/UpdateChecker.cpp @@ -24,14 +24,16 @@ #define CHANLIST_FORMAT 0 #include "BuildConfig.h" -#include "sys.h" -UpdateChecker::UpdateChecker(shared_qobject_ptr<QNetworkAccessManager> nam, QString channelUrl, QString currentChannel, int currentBuild) +UpdateChecker::UpdateChecker(shared_qobject_ptr<QNetworkAccessManager> nam, QString channelUrl, QString currentChannel) { m_network = nam; m_channelUrl = channelUrl; m_currentChannel = currentChannel; - m_currentBuild = currentBuild; + +#ifdef Q_OS_MAC + m_externalUpdater = new MacSparkleUpdater(); +#endif } QList<UpdateChecker::ChannelListEntry> UpdateChecker::getChannelList() const @@ -44,71 +46,95 @@ bool UpdateChecker::hasChannels() const return !m_channels.isEmpty(); } -void UpdateChecker::checkForUpdate(QString updateChannel, bool notifyNoUpdate) +ExternalUpdater* UpdateChecker::getExternalUpdater() { - qDebug() << "Checking for updates."; - - // If the channel list hasn't loaded yet, load it and defer checking for updates until - // later. - if (!m_chanListLoaded) - { - qDebug() << "Channel list isn't loaded yet. Loading channel list and deferring update check."; - m_checkUpdateWaiting = true; - m_deferredUpdateChannel = updateChannel; - updateChanList(notifyNoUpdate); - return; - } + return m_externalUpdater; +} - if (m_updateChecking) +void UpdateChecker::checkForUpdate(const QString& updateChannel, bool notifyNoUpdate) +{ + if (m_externalUpdater) { - qDebug() << "Ignoring update check request. Already checking for updates."; - return; + m_externalUpdater->setBetaAllowed(updateChannel == "beta"); + if (notifyNoUpdate) + { + qDebug() << "Checking for updates."; + m_externalUpdater->checkForUpdates(); + } else + { + // The updater library already handles automatic update checks. + return; + } } - - // Find the desired channel within the channel list and get its repo URL. If if cannot be - // found, error. - QString stableUrl; - m_newRepoUrl = ""; - for (ChannelListEntry entry : m_channels) + else { - qDebug() << "channelEntry = " << entry.id; - if(entry.id == "stable") { - stableUrl = entry.url; + qDebug() << "Checking for updates."; + // If the channel list hasn't loaded yet, load it and defer checking for updates until + // later. + if (!m_chanListLoaded) + { + qDebug() << "Channel list isn't loaded yet. Loading channel list and deferring update check."; + m_checkUpdateWaiting = true; + m_deferredUpdateChannel = updateChannel; + updateChanList(notifyNoUpdate); + return; } - if (entry.id == updateChannel) { - m_newRepoUrl = entry.url; - qDebug() << "is intended update channel: " << entry.id; + + if (m_updateChecking) + { + qDebug() << "Ignoring update check request. Already checking for updates."; + return; } - if (entry.id == m_currentChannel) { - m_currentRepoUrl = entry.url; - qDebug() << "is current update channel: " << entry.id; + + // Find the desired channel within the channel list and get its repo URL. If if cannot be + // found, error. + QString stableUrl; + m_newRepoUrl = ""; + for (ChannelListEntry entry: m_channels) + { + qDebug() << "channelEntry = " << entry.id; + if (entry.id == "stable") + { + stableUrl = entry.url; + } + if (entry.id == updateChannel) + { + m_newRepoUrl = entry.url; + qDebug() << "is intended update channel: " << entry.id; + } + if (entry.id == m_currentChannel) + { + m_currentRepoUrl = entry.url; + qDebug() << "is current update channel: " << entry.id; + } } - } - qDebug() << "m_repoUrl = " << m_newRepoUrl; + qDebug() << "m_repoUrl = " << m_newRepoUrl; - if (m_newRepoUrl.isEmpty()) { - qWarning() << "m_repoUrl was empty. defaulting to 'stable': " << stableUrl; - m_newRepoUrl = stableUrl; - } + if (m_newRepoUrl.isEmpty()) + { + qWarning() << "m_repoUrl was empty. defaulting to 'stable': " << stableUrl; + m_newRepoUrl = stableUrl; + } - // If nothing applies, error - if (m_newRepoUrl.isEmpty()) - { - qCritical() << "failed to select any update repository for: " << updateChannel; - emit updateCheckFailed(); - return; - } + // If nothing applies, error + if (m_newRepoUrl.isEmpty()) + { + qCritical() << "failed to select any update repository for: " << updateChannel; + emit updateCheckFailed(); + return; + } - m_updateChecking = true; + m_updateChecking = true; - QUrl indexUrl = QUrl(m_newRepoUrl).resolved(QUrl("index.json")); + QUrl indexUrl = QUrl(m_newRepoUrl).resolved(QUrl("index.json")); - indexJob = new NetJob("GoUpdate Repository Index", m_network); - indexJob->addNetAction(Net::Download::makeByteArray(indexUrl, &indexData)); - connect(indexJob.get(), &NetJob::succeeded, [this, notifyNoUpdate](){ updateCheckFinished(notifyNoUpdate); }); - connect(indexJob.get(), &NetJob::failed, this, &UpdateChecker::updateCheckFailed); - indexJob->start(); + indexJob = new NetJob("GoUpdate Repository Index", m_network); + indexJob->addNetAction(Net::Download::makeByteArray(indexUrl, &indexData)); + connect(indexJob.get(), &NetJob::succeeded, [this, notifyNoUpdate]() { updateCheckFinished(notifyNoUpdate); }); + connect(indexJob.get(), &NetJob::failed, this, &UpdateChecker::updateCheckFailed); + indexJob->start(); + } } void UpdateChecker::updateCheckFinished(bool notifyNoUpdate) diff --git a/launcher/updater/UpdateChecker.h b/launcher/updater/UpdateChecker.h index 13ee4efd..42ef318b 100644 --- a/launcher/updater/UpdateChecker.h +++ b/launcher/updater/UpdateChecker.h @@ -17,14 +17,19 @@ #include "net/NetJob.h" #include "GoUpdate.h" +#include "ExternalUpdater.h" + +#ifdef Q_OS_MAC +#include "MacSparkleUpdater.h" +#endif class UpdateChecker : public QObject { Q_OBJECT |
