1
/* $Id: UIUpdateManager.cpp $ */
4
* VBox frontends: Qt4 GUI ("VirtualBox"):
5
* UIUpdateManager class implementation
9
* Copyright (C) 2006-2011 Oracle Corporation
11
* This file is part of VirtualBox Open Source Edition (OSE), as
12
* available from http://www.virtualbox.org. This file is free software;
13
* you can redistribute it and/or modify it under the terms of the GNU
14
* General Public License (GPL) as published by the Free Software
15
* Foundation, in version 2 as it comes in the "COPYING" file of the
16
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
/* Global includes: */
22
#include <QNetworkReply>
26
#include <VBox/version.h>
29
#include "UIUpdateManager.h"
30
#include "UINetworkManager.h"
31
#include "VBoxGlobal.h"
32
#include "UIMessageCenter.h"
33
#include "VBoxUtils.h"
34
#include "UIDownloaderExtensionPack.h"
35
#include "UIGlobalSettingsExtension.h"
38
/* Using declarations: */
39
using namespace VBoxGlobalDefs;
41
/* UIUpdateManager stuff: */
42
UIUpdateManager* UIUpdateManager::m_pInstance = 0;
45
void UIUpdateManager::schedule()
47
/* Ensure instance is NOT created: */
51
/* Create instance: */
56
void UIUpdateManager::shutdown()
58
/* Ensure instance is created: */
62
/* Delete instance: */
66
void UIUpdateManager::sltForceCheck()
70
/* Force call for new version check: */
71
sltCheckIfUpdateIsNecessary(true);
74
UIUpdateManager::UIUpdateManager()
75
: m_uTime(1 /* day */ * 24 /* hours */ * 60 /* minutes */ * 60 /* seconds */ * 1000 /* ms */)
77
/* Prepare instance: */
78
if (m_pInstance != this)
81
#ifdef VBOX_WITH_UPDATE_REQUEST
82
/* Ask updater to check for the first time: */
83
QTimer::singleShot(0, this, SLOT(sltCheckIfUpdateIsNecessary()));
84
#endif /* VBOX_WITH_UPDATE_REQUEST */
87
UIUpdateManager::~UIUpdateManager()
89
/* Cleanup instance: */
90
if (m_pInstance == this)
94
void UIUpdateManager::sltCheckIfUpdateIsNecessary(bool fForceCall /* = false */)
96
/* Load/decode curent update data: */
97
VBoxUpdateData currentData(vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_UpdateDate));
99
/* Check if update is really neessary: */
100
if (fForceCall || currentData.isNeedToCheck())
102
/* Check if update is necessary for VirtualBox itself: */
103
checkIfUpdateIsNecessary(fForceCall);
105
/* Check if update is necessary for VirtualBox extension pack: */
106
checkIfUpdateIsNecessaryForExtensionPack(fForceCall);
108
/* Encode/save new update data: */
109
VBoxUpdateData newData(currentData.periodIndex(), currentData.branchIndex());
110
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_UpdateDate, newData.data());
113
#ifdef VBOX_WITH_UPDATE_REQUEST
114
/* Ask updater to check for the next time: */
115
QTimer::singleShot(m_uTime, this, SLOT(sltCheckIfUpdateIsNecessary()));
116
#endif /* VBOX_WITH_UPDATE_REQUEST */
119
void UIUpdateManager::checkIfUpdateIsNecessary(bool fForceCall)
121
/* Creating VirtualBox version checker: */
122
UINewVersionChecker checker(fForceCall);
123
/* Start synchronous check: */
124
checker.checkForTheNewVersion();
127
void UIUpdateManager::checkIfUpdateIsNecessaryForExtensionPack(bool /* fForceCall */)
129
/* Check if updater instance already created: */
130
if (UIDownloaderExtensionPack::current())
133
/* Get extension pack information: */
134
CExtPack extPack = vboxGlobal().virtualBox().GetExtensionPackManager().Find(UI_ExtPackName);
135
/* Check if extension pack is really installed: */
136
if (extPack.isNull())
139
/* Get VirtualBox version: */
140
VBoxVersion vboxVersion(vboxGlobal().vboxVersionStringNormalized());
141
/* Get extension pack version: */
142
QString strExtPackVersion(extPack.GetVersion().remove(VBOX_BUILD_PUBLISHER));
143
VBoxVersion extPackVersion(strExtPackVersion);
144
/* Check if extension pack version less than required: */
145
if ((vboxVersion.z() % 2 != 0) /* Skip unstable VBox version */ ||
146
!(extPackVersion < vboxVersion) /* Ext Pack version more or equal to VBox version */)
149
/* Ask the user about extension pack downloading: */
150
if (!msgCenter().proposeDownloadExtensionPack(UI_ExtPackName, strExtPackVersion))
153
/* Run downloader for VirtualBox extension pack: */
154
UIDownloaderExtensionPack::download(this);
157
void UIUpdateManager::sltHandleDownloadedExtensionPack(const QString &strSource, const QString &strTarget)
159
/* Warn the user about extension pack was downloaded and saved, propose to install it: */
160
if (msgCenter().proposeInstallExtentionPack(UI_ExtPackName, strSource, QDir::toNativeSeparators(strTarget)))
161
UIGlobalSettingsExtension::doInstallation(strTarget, msgCenter().mainWindowShown(), NULL);
164
/* UINewVersionChecker stuff: */
165
UINewVersionChecker::UINewVersionChecker(bool fForceCall)
166
: m_url("http://update.virtualbox.org/query.php")
167
, m_fForceCall(fForceCall)
168
, m_pLoop(new QEventLoop(this))
172
void UINewVersionChecker::checkForTheNewVersion()
174
/* Calculate the count of checks left: */
176
QString strCount = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_UpdateCheckCount);
177
if (!strCount.isEmpty())
180
int c = strCount.toLongLong(&ok);
186
url.addQueryItem("platform", vboxGlobal().virtualBox().GetPackageType());
187
/* Check if branding is active: */
188
if (vboxGlobal().brandingIsActive())
190
/* Branding: Check whether we have a local branding file which tells us our version suffix "FOO"
191
(e.g. 3.06.54321_FOO) to identify this installation: */
192
url.addQueryItem("version", QString("%1_%2_%3").arg(vboxGlobal().virtualBox().GetVersion())
193
.arg(vboxGlobal().virtualBox().GetRevision())
194
.arg(vboxGlobal().brandingGetKey("VerSuffix")));
198
/* Use hard coded version set by VBOX_VERSION_STRING: */
199
url.addQueryItem("version", QString("%1_%2").arg(vboxGlobal().virtualBox().GetVersion())
200
.arg(vboxGlobal().virtualBox().GetRevision()));
202
url.addQueryItem("count", QString::number(cCount));
203
url.addQueryItem("branch", VBoxUpdateData(vboxGlobal().virtualBox().
204
GetExtraData(VBoxDefs::GUI_UpdateDate)).branchName());
205
QString strUserAgent(QString("VirtualBox %1 <%2>")
206
.arg(vboxGlobal().virtualBox().GetVersion())
207
.arg(vboxGlobal().platformInfo()));
209
/* Setup GET request: */
210
QNetworkRequest request;
212
request.setRawHeader("User-Agent", strUserAgent.toAscii());
213
QNetworkReply *pReply = gNetworkManager->get(request);
214
connect(pReply, SIGNAL(finished()), this, SLOT(sltHandleCheckReply()));
215
connect(pReply, SIGNAL(sslErrors(QList<QSslError>)), pReply, SLOT(ignoreSslErrors()));
217
/* Lock event loop: */
221
void UINewVersionChecker::sltHandleCheckReply()
223
/* Get corresponding network reply object: */
224
QNetworkReply *pReply = qobject_cast<QNetworkReply*>(sender());
225
/* And ask it for suicide: */
226
pReply->deleteLater();
228
/* Handle normal result: */
229
if (pReply->error() == QNetworkReply::NoError)
231
/* Deserialize incoming data: */
232
QString strResponseData(pReply->readAll());
234
/* Newer version of necessary package found: */
235
if (strResponseData.indexOf(QRegExp("^\\d+\\.\\d+\\.\\d+ \\S+$")) == 0)
237
QStringList response = strResponseData.split(" ", QString::SkipEmptyParts);
238
msgCenter().showUpdateSuccess(vboxGlobal().mainWindow(), response[0], response[1]);
240
/* No newer version of necessary package found: */
244
msgCenter().showUpdateNotFound(vboxGlobal().mainWindow());
247
/* Save left count of checks: */
249
QString strCount = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_UpdateCheckCount);
250
if (!strCount.isEmpty())
253
int c = strCount.toLongLong(&ok);
256
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_UpdateCheckCount, QString("%1").arg((qulonglong)cCount + 1));
262
msgCenter().showUpdateFailure(vboxGlobal().mainWindow(), pReply->errorString());
265
/* Unlock event loop: */