1/*
2 * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15#ifndef OCUPDATER_H
16#define OCUPDATER_H
17
18#include <QObject>
19#include <QUrl>
20#include <QTemporaryFile>
21#include <QTimer>
22
23#include "updater/updateinfo.h"
24#include "updater/updater.h"
25
26class QNetworkAccessManager;
27class QNetworkReply;
28
29namespace OCC {
30
31/**
32 * @brief Schedule update checks every couple of hours if the client runs.
33 * @ingroup gui
34 *
35 * This class schedules regular update checks. It also checks the config
36 * if update checks are wanted at all.
37 *
38 * To reflect that all platforms have their own update scheme, a little
39 * complex class design was set up:
40 *
41 * For Windows and Linux, the updaters are inherited from OCUpdater, while
42 * the MacOSX SparkleUpdater directly uses the class Updater. On windows,
43 * NSISUpdater starts the update if a new version of the client is available.
44 * On MacOSX, the sparkle framework handles the installation of the new
45 * version. On Linux, the update capabilities of the underlying linux distro
46 * are relied on, and thus the PassiveUpdateNotifier just shows a notification
47 * if there is a new version once at every start of the application.
48 *
49 * Simple class diagram of the updater:
50 *
51 * +---------------------------+
52 * +-----+ UpdaterScheduler +-----+
53 * | +------------+--------------+ |
54 * v v v
55 * +------------+ +---------------------+ +----------------+
56 * |NSISUpdater | |PassiveUpdateNotifier| | SparkleUpdater |
57 * +-+----------+ +---+-----------------+ +-----+----------+
58 * | | |
59 * | v +------------------+
60 * | +---------------+ v
61 * +-->| OCUpdater +------+
62 * +--------+------+ |
63 * | Updater |
64 * +-------------+
65 */
66
67class UpdaterScheduler : public QObject
68{
69 Q_OBJECT
70public:
71 UpdaterScheduler(QObject *parent);
72
73signals:
74 void updaterAnnouncement(const QString &title, const QString &msg);
75 void requestRestart();
76
77private slots:
78 void slotTimerFired();
79
80private:
81 QTimer _updateCheckTimer; /** Timer for the regular update check. */
82};
83
84/**
85 * @brief Class that uses an ownCloud proprietary XML format to fetch update information
86 * @ingroup gui
87 */
88class OCUpdater : public Updater
89{
90 Q_OBJECT
91public:
92 enum DownloadState { Unknown = 0,
93 CheckingServer,
94 UpToDate,
95 Downloading,
96 DownloadComplete,
97 DownloadFailed,
98 DownloadTimedOut,
99 UpdateOnlyAvailableThroughSystem };
100 explicit OCUpdater(const QUrl &url);
101
102 void setUpdateUrl(const QUrl &url);
103
104 bool performUpdate();
105
106 void checkForUpdate() Q_DECL_OVERRIDE;
107
108 QString statusString() const;
109 int downloadState() const;
110 void setDownloadState(DownloadState state);
111
112signals:
113 void downloadStateChanged();
114 void newUpdateAvailable(const QString &header, const QString &message);
115 void requestRestart();
116
117public slots:
118 // FIXME Maybe this should be in the NSISUpdater which should have been called WindowsUpdater
119 void slotStartInstaller();
120
121protected slots:
122 void backgroundCheckForUpdate() Q_DECL_OVERRIDE;
123
124private slots:
125 void slotOpenUpdateUrl();
126 void slotVersionInfoArrived();
127 void slotTimedOut();
128
129protected:
130 virtual void versionInfoArrived(const UpdateInfo &info) = 0;
131 bool updateSucceeded() const;
132 QNetworkAccessManager *qnam() const { return _accessManager; }
133 UpdateInfo updateInfo() const { return _updateInfo; }
134
135private:
136 QUrl _updateUrl;
137 int _state;
138 QNetworkAccessManager *_accessManager;
139 QTimer *_timeoutWatchdog; /** Timer to guard the timeout of an individual network request */
140 UpdateInfo _updateInfo;
141};
142
143/**
144 * @brief Windows Updater Using NSIS
145 * @ingroup gui
146 */
147class NSISUpdater : public OCUpdater
148{
149 Q_OBJECT
150public:
151 enum UpdateState { NoUpdate = 0,
152 UpdateAvailable,
153 UpdateFailed };
154 explicit NSISUpdater(const QUrl &url);
155 bool handleStartup() Q_DECL_OVERRIDE;
156private slots:
157 void slotSetSeenVersion();
158 void slotDownloadFinished();
159 void slotWriteFile();
160
161private:
162 NSISUpdater::UpdateState updateStateOnStart();
163 void showDialog(const UpdateInfo &info);
164 void versionInfoArrived(const UpdateInfo &info) Q_DECL_OVERRIDE;
165 QScopedPointer<QTemporaryFile> _file;
166 QString _targetFile;
167 bool _showFallbackMessage;
168};
169
170/**
171 * @brief Updater that only implements notification for use in settings
172 *
173 * The implementation does not show popups
174 *
175 * @ingroup gui
176 */
177class PassiveUpdateNotifier : public OCUpdater
178{
179 Q_OBJECT
180public:
181 explicit PassiveUpdateNotifier(const QUrl &url);
182 bool handleStartup() Q_DECL_OVERRIDE { return false; }
183 void backgroundCheckForUpdate() Q_DECL_OVERRIDE;
184
185private:
186 void versionInfoArrived(const UpdateInfo &info) Q_DECL_OVERRIDE;
187 QByteArray _runningAppVersion;
188};
189}
190
191#endif // OC_UPDATER
192