From 5b65bbf8e5da2eacf8508e54641b85db44fa9061 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 3 Jun 2015 09:04:12 +0200 Subject: App: Do a regular check for updates, currently hardcoded every two hours. --- src/gui/updater/ocupdater.cpp | 12 ++++++++++-- src/gui/updater/updater.cpp | 5 +++++ src/gui/updater/updater.h | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src/gui/updater') diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index 04c2ef5c5..c009fc724 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -65,8 +65,16 @@ bool OCUpdater::performUpdate() void OCUpdater::backgroundCheckForUpdate() { - // FIXME - checkForUpdate(); + int dlState = downloadState(); + + if( dlState == Unknown || + dlState == UpToDate || + dlState == DownloadComplete || + dlState == DownloadFailed || + dlState == DownloadTimedOut ) { + // how about UpdateOnlyAvailableThroughSystem? + checkForUpdate(); + } } QString OCUpdater::statusString() const diff --git a/src/gui/updater/updater.cpp b/src/gui/updater/updater.cpp index 85db07b30..f530191b9 100644 --- a/src/gui/updater/updater.cpp +++ b/src/gui/updater/updater.cpp @@ -125,4 +125,9 @@ QString Updater::clientVersion() return QString::fromLatin1(MIRALL_STRINGIFY(MIRALL_VERSION_FULL)); } +int Updater::downloadState() const +{ + return instance()->downloadState(); +} + } // namespace OCC diff --git a/src/gui/updater/updater.h b/src/gui/updater/updater.h index 4dddeb3b5..746120a19 100644 --- a/src/gui/updater/updater.h +++ b/src/gui/updater/updater.h @@ -33,6 +33,8 @@ public: virtual void checkForUpdate() = 0; virtual void backgroundCheckForUpdate() = 0; + int downloadState() const; + virtual bool handleStartup() = 0; protected: -- cgit v1.2.3 From c8cb604c18d6bce0a1bc12260a24ad6c85d33403 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 3 Jun 2015 20:43:31 +0200 Subject: Updater: Do a tray notification if a new update is available. --- src/gui/updater/ocupdater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gui/updater') diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index c009fc724..fe4080137 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -69,7 +69,7 @@ void OCUpdater::backgroundCheckForUpdate() if( dlState == Unknown || dlState == UpToDate || - dlState == DownloadComplete || + /* dlState == DownloadComplete || <- are we checking if a previous download was successful already? */ dlState == DownloadFailed || dlState == DownloadTimedOut ) { // how about UpdateOnlyAvailableThroughSystem? -- cgit v1.2.3 From adc239c9d05f5c91d74cb52ad55b8fa220f19435 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 20 Jul 2015 12:10:54 +0200 Subject: UpdateCheck: Clean up Application class and move most to updater. Add the update timer also to the update class and remove all the proxy slots from the Application class. --- src/gui/updater/ocupdater.cpp | 54 +++++++++++++++++++++++++++++++++---------- src/gui/updater/ocupdater.h | 7 ++++-- src/gui/updater/updater.cpp | 1 + 3 files changed, 48 insertions(+), 14 deletions(-) (limited to 'src/gui/updater') diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index fe4080137..35b9c6b2f 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -42,8 +42,19 @@ OCUpdater::OCUpdater(const QUrl &url, QObject *parent) : , _updateUrl(url) , _state(Unknown) , _accessManager(new AccessManager(this)) - , _timer(new QTimer(this)) + , _timeoutWatchdog(new QTimer(this)) + , _updateCheckTimer(new QTimer(this)) { + // at startup, do a check in any case. + QTimer::singleShot( 3000, this, SLOT( backgroundCheckForUpdate())); + + // connect the timer to the check slot + connect( _updateCheckTimer, SIGNAL(timeout()), this, SLOT(backgroundCheckForUpdate())); + // and set the timer regular interval which is usually large, like 10 hours. + ConfigFile cfg; + auto checkInterval = cfg.updateCheckInterval(); + qDebug() << "Setting up regular update check every " << checkInterval /1000/60 << "seconds"; + _updateCheckTimer->setInterval(checkInterval); // check every couple of hours as defined in config } bool OCUpdater::performUpdate() @@ -67,14 +78,29 @@ void OCUpdater::backgroundCheckForUpdate() { int dlState = downloadState(); - if( dlState == Unknown || - dlState == UpToDate || - /* dlState == DownloadComplete || <- are we checking if a previous download was successful already? */ - dlState == DownloadFailed || - dlState == DownloadTimedOut ) { - // how about UpdateOnlyAvailableThroughSystem? - checkForUpdate(); - } + ConfigFile cfg; + + if( cfg.skipUpdateCheck() ) { + qDebug() << Q_FUNC_INFO << "Skipping update check because of config file"; + return; + } + + // do the real update check depending on the internal state of updater. + switch( dlState ) { + case Unknown: + case UpToDate: + case DownloadFailed: + case DownloadTimedOut: + qDebug() << Q_FUNC_INFO << "checking for available update"; + checkForUpdate(); + break; + case DownloadComplete: + qDebug() << "Update is downloaded, skip new check."; + break; + case UpdateOnlyAvailableThroughSystem: + qDebug() << "Update is only available through system, skip check."; + break; + } } QString OCUpdater::statusString() const @@ -112,6 +138,10 @@ void OCUpdater::setDownloadState(DownloadState state) { _state = state; emit downloadStateChanged(); + + if( _state == OCUpdater::DownloadComplete ) { + emit newUpdateAvailable(tr("Update Check"), statusString() ); + } } void OCUpdater::slotStartInstaller() @@ -128,8 +158,8 @@ void OCUpdater::slotStartInstaller() void OCUpdater::checkForUpdate() { QNetworkReply *reply = _accessManager->get(QNetworkRequest(_updateUrl)); - connect(_timer, SIGNAL(timeout()), this, SLOT(slotTimedOut())); - _timer->start(30*1000); + connect(_timeoutWatchdog, SIGNAL(timeout()), this, SLOT(slotTimedOut())); + _timeoutWatchdog->start(30*1000); connect(reply, SIGNAL(finished()), this, SLOT(slotVersionInfoArrived())); setDownloadState(CheckingServer); @@ -152,7 +182,7 @@ bool OCUpdater::updateSucceeded() const void OCUpdater::slotVersionInfoArrived() { - _timer->stop(); + _timeoutWatchdog->stop(); QNetworkReply *reply = qobject_cast(sender()); if( reply->error() != QNetworkReply::NoError ) { qDebug() << "Failed to reach version check url: " << reply->errorString(); diff --git a/src/gui/updater/ocupdater.h b/src/gui/updater/ocupdater.h index 9843a30a1..aed84f279 100644 --- a/src/gui/updater/ocupdater.h +++ b/src/gui/updater/ocupdater.h @@ -42,7 +42,6 @@ public: bool performUpdate(); void checkForUpdate() Q_DECL_OVERRIDE; - void backgroundCheckForUpdate() Q_DECL_OVERRIDE; QString statusString() const; int downloadState() const; @@ -50,11 +49,14 @@ public: signals: void downloadStateChanged(); + void newUpdateAvailable(const QString& header, const QString& message); public slots: void slotStartInstaller(); private slots: + void backgroundCheckForUpdate() Q_DECL_OVERRIDE; + void slotOpenUpdateUrl(); void slotVersionInfoArrived(); void slotTimedOut(); @@ -68,7 +70,8 @@ private: QUrl _updateUrl; int _state; QNetworkAccessManager *_accessManager; - QTimer *_timer; + QTimer *_timeoutWatchdog; /** Timer to guard the timeout of an individual network request */ + QTimer *_updateCheckTimer; /** Timer for the regular update check. */ UpdateInfo _updateInfo; }; diff --git a/src/gui/updater/updater.cpp b/src/gui/updater/updater.cpp index f530191b9..d9d0a669d 100644 --- a/src/gui/updater/updater.cpp +++ b/src/gui/updater/updater.cpp @@ -96,6 +96,7 @@ Updater *Updater::create() #else return new PassiveUpdateNotifier(QUrl(updateBaseUrl)); #endif + } -- cgit v1.2.3 From 0a08a51a41ef1c2c481f54a276d7b67c9962cf6c Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 20 Jul 2015 15:32:27 +0200 Subject: Updater: really do not forget to start the updater timer. --- src/gui/updater/ocupdater.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/gui/updater') diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index 35b9c6b2f..a2882e09c 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -53,8 +53,9 @@ OCUpdater::OCUpdater(const QUrl &url, QObject *parent) : // and set the timer regular interval which is usually large, like 10 hours. ConfigFile cfg; auto checkInterval = cfg.updateCheckInterval(); - qDebug() << "Setting up regular update check every " << checkInterval /1000/60 << "seconds"; + qDebug() << "Setting up regular update check every " << checkInterval /1000/60 << "minutes "; _updateCheckTimer->setInterval(checkInterval); // check every couple of hours as defined in config + _updateCheckTimer->start(); } bool OCUpdater::performUpdate() -- cgit v1.2.3 From 320cc1c7dde97cf6ebbb10830acedd4f67fe32cf Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 20 Jul 2015 15:33:17 +0200 Subject: Updater: Avoid to show the update notification to often. If the update is only available through the system, the notification is only shown once. --- src/gui/updater/ocupdater.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/gui/updater') diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index a2882e09c..6dd661c4f 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -137,10 +137,15 @@ int OCUpdater::downloadState() const void OCUpdater::setDownloadState(DownloadState state) { + auto oldState = _state; _state = state; emit downloadStateChanged(); - if( _state == OCUpdater::DownloadComplete ) { + // show the notification if the download is complete (on every check) + // or once for system based updates. + if( _state == OCUpdater::DownloadComplete || + (oldState != OCUpdater::UpdateOnlyAvailableThroughSystem + && _state == OCUpdater::UpdateOnlyAvailableThroughSystem) ) { emit newUpdateAvailable(tr("Update Check"), statusString() ); } } -- cgit v1.2.3 From 89b8555aa707789b4a37bdfcc80c0cc47f28f65c Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 20 Jul 2015 15:33:44 +0200 Subject: PassiveUpdateNotifier: Fix condition on when to show the update. --- src/gui/updater/ocupdater.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/gui/updater') diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index 6dd661c4f..97f8a0685 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -399,10 +399,11 @@ PassiveUpdateNotifier::PassiveUpdateNotifier(const QUrl &url, QObject *parent) void PassiveUpdateNotifier::versionInfoArrived(const UpdateInfo &info) { + qint64 currentVer = Helper::currentVersionToInt(); + qint64 remoteVer = Helper::stringVersionToInt(info.version()); + if( info.version().isEmpty() || - Helper::stringVersionToInt(info.version()) - >= Helper::currentVersionToInt() ) - { + currentVer >= remoteVer ) { qDebug() << "Client is on latest version!"; setDownloadState(UpToDate); } else { -- cgit v1.2.3 From c34641f4f7013ded6b73f43a9a6b22aac8c7c80a Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 22 Jul 2015 13:44:19 +0200 Subject: Updater: Added a class UpdaterSchedule. It schedules the regular update checks. Keeps Application and other classes easy. --- src/gui/updater/ocupdater.cpp | 63 ++++++++++++++++++++++++++++++------------- src/gui/updater/ocupdater.h | 54 +++++++++++++++++++++++++++++++++++-- 2 files changed, 97 insertions(+), 20 deletions(-) (limited to 'src/gui/updater') diff --git a/src/gui/updater/ocupdater.cpp b/src/gui/updater/ocupdater.cpp index 97f8a0685..8aecbb167 100644 --- a/src/gui/updater/ocupdater.cpp +++ b/src/gui/updater/ocupdater.cpp @@ -37,25 +37,59 @@ static const char seenVersionC[] = "Updater/seenVersion"; static const char autoUpdateFailedVersionC[] = "Updater/autoUpdateFailedVersion"; static const char autoUpdateAttemptedC[] = "Updater/autoUpdateAttempted"; + +UpdaterScheduler::UpdaterScheduler(QObject *parent) : + QObject(parent) +{ + connect( &_updateCheckTimer, SIGNAL(timeout()), + this, SLOT(slotTimerFired()) ); + + // Note: the sparkle-updater is not an OCUpdater and thus the dynamic_cast + // returns NULL. Clever detail. + if (OCUpdater *updater = dynamic_cast(Updater::instance())) { + connect(updater, SIGNAL(newUpdateAvailable(QString,QString)), + this, SIGNAL(updaterAnnouncement(QString,QString)) ); + } + + // at startup, do a check in any case. + QTimer::singleShot(3000, this, SLOT(slotTimerFired())); + + ConfigFile cfg; + auto checkInterval = cfg.updateCheckInterval(); + _updateCheckTimer.start(checkInterval); +} + +void UpdaterScheduler::slotTimerFired() +{ + ConfigFile cfg; + + // re-set the check interval if it changed in the config file meanwhile + auto checkInterval = cfg.updateCheckInterval(); + if( checkInterval != _updateCheckTimer.interval() ) { + _updateCheckTimer.setInterval(checkInterval); + qDebug() << "Setting new update check interval " << checkInterval; + } + + // consider the skipUpdateCheck flag in the config. + if( cfg.skipUpdateCheck() ) { + qDebug() << Q_FUNC_INFO << "Skipping update check because of config file"; + return; + } + + Updater::instance()->backgroundCheckForUpdate(); +} + + +/* ----------------------------------------------------------------- */ + OCUpdater::OCUpdater(const QUrl &url, QObject *parent) : QObject(parent) , _updateUrl(url) , _state(Unknown) , _accessManager(new AccessManager(this)) , _timeoutWatchdog(new QTimer(this)) - , _updateCheckTimer(new QTimer(this)) { - // at startup, do a check in any case. - QTimer::singleShot( 3000, this, SLOT( backgroundCheckForUpdate())); - // connect the timer to the check slot - connect( _updateCheckTimer, SIGNAL(timeout()), this, SLOT(backgroundCheckForUpdate())); - // and set the timer regular interval which is usually large, like 10 hours. - ConfigFile cfg; - auto checkInterval = cfg.updateCheckInterval(); - qDebug() << "Setting up regular update check every " << checkInterval /1000/60 << "minutes "; - _updateCheckTimer->setInterval(checkInterval); // check every couple of hours as defined in config - _updateCheckTimer->start(); } bool OCUpdater::performUpdate() @@ -79,13 +113,6 @@ void OCUpdater::backgroundCheckForUpdate() { int dlState = downloadState(); - ConfigFile cfg; - - if( cfg.skipUpdateCheck() ) { - qDebug() << Q_FUNC_INFO << "Skipping update check because of config file"; - return; - } - // do the real update check depending on the internal state of updater. switch( dlState ) { case Unknown: diff --git a/src/gui/updater/ocupdater.h b/src/gui/updater/ocupdater.h index aed84f279..8425ef2b0 100644 --- a/src/gui/updater/ocupdater.h +++ b/src/gui/updater/ocupdater.h @@ -18,16 +18,67 @@ #include #include #include +#include #include "updater/updateinfo.h" #include "updater/updater.h" class QNetworkAccessManager; class QNetworkReply; -class QTimer; namespace OCC { +/** @short Schedule update checks every couple of hours if the client runs. + * + * This class schedules regular update checks. It also checks the config + * if update checks are wanted at all. + * + * To reflect that all platforms have its own update scheme, a little + * complex class design was set up: + * + * For Windows and Linux, the updaters are inherited from OCUpdater, while + * the MacOSX SparkleUpdater directly uses the class Updater. On windows, + * NSISUpdater starts the update if a new version of the client is available. + * On MacOSX, the sparkle framework handles the installation of the new + * version. On Linux, the update capabilities by the underlying linux distro + * is relied on, and thus the PassiveUpdateNotifier just shows a notification + * if there is a new version once at every start of the application. + * + * Simple class diagram of the updater: + * + * +---------------------------+ + * +-----+ UpdaterScheduler +-----+ + * | +------------+--------------+ | + * v v v + * +------------+ +---------------------+ +----------------+ + * |NSISUpdater | |PassiveUpdateNotifier| | SparkleUpdater | + * +-+----------+ +---+-----------------+ +-----+----------+ + * | | | + * | v +------------------+ + * | +---------------+ v + * +-->| OCUpdater +------+ + * +--------+------+ | + * | Updater | + * +-------------+ + */ + +class UpdaterScheduler : public QObject +{ + Q_OBJECT +public: + UpdaterScheduler(QObject *parent); + +signals: + void updaterAnnouncement(const QString& title, const QString& msg); + +private slots: + void slotTimerFired(); + +private: + QTimer _updateCheckTimer; /** Timer for the regular update check. */ + +}; + /** @short Class that uses an ownCloud propritary XML format to fetch update information */ class OCUpdater : public QObject, public Updater { @@ -71,7 +122,6 @@ private: int _state; QNetworkAccessManager *_accessManager; QTimer *_timeoutWatchdog; /** Timer to guard the timeout of an individual network request */ - QTimer *_updateCheckTimer; /** Timer for the regular update check. */ UpdateInfo _updateInfo; }; -- cgit v1.2.3