src/platform/qt/AbstractUpdater.cpp (view raw)
1/* Copyright (c) 2013-2019 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "AbstractUpdater.h"
7
8#include <QNetworkAccessManager>
9#include <QNetworkReply>
10
11using namespace QGBA;
12
13AbstractUpdater::AbstractUpdater(QObject* parent)
14 : QObject(parent)
15 , m_netman(new QNetworkAccessManager(this))
16{
17}
18
19void AbstractUpdater::checkUpdate() {
20 QNetworkReply* reply = m_netman->get(QNetworkRequest(manifestLocation()));
21 chaseRedirects(reply, &AbstractUpdater::manifestDownloaded);
22}
23
24void AbstractUpdater::downloadUpdate() {
25 if (m_isUpdating) {
26 return;
27 }
28 if (m_manifest.isEmpty()) {
29 m_isUpdating = true;
30 checkUpdate();
31 return;
32 }
33 QUrl url = parseManifest(m_manifest);
34 if (!url.isValid()) {
35 emit updateDone(false);
36 return;
37 }
38 m_isUpdating = true;
39 QNetworkReply* reply = m_netman->get(QNetworkRequest(url));
40 chaseRedirects(reply, &AbstractUpdater::updateDownloaded);
41}
42
43void AbstractUpdater::chaseRedirects(QNetworkReply* reply, void (AbstractUpdater::*cb)(QNetworkReply*)) {
44 connect(reply, &QNetworkReply::finished, this, [this, reply, cb]() {
45 // TODO: check domains, etc
46 if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() / 100 == 3) {
47 QNetworkReply* newReply = m_netman->get(QNetworkRequest(reply->header(QNetworkRequest::LocationHeader).toString()));
48 chaseRedirects(newReply, cb);
49 } else {
50 (this->*cb)(reply);
51 }
52 });
53}
54
55void AbstractUpdater::manifestDownloaded(QNetworkReply* reply) {
56 m_manifest = reply->readAll();
57 QUrl url = parseManifest(m_manifest);
58 if (m_isUpdating) {
59 if (!url.isValid()) {
60 emit updateDone(false);
61 } else {
62 QNetworkReply* reply = m_netman->get(QNetworkRequest(url));
63 chaseRedirects(reply, &AbstractUpdater::updateDownloaded);
64 }
65 } else {
66 emit updateAvailable(url.isValid());
67 }
68}
69
70void AbstractUpdater::updateDownloaded(QNetworkReply* reply) {
71 m_isUpdating = false;
72 if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() / 100 != 2) {
73 emit updateDone(false);
74 return;
75 }
76 QFile f(destination());
77 if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
78 emit updateDone(false);
79 return;
80 }
81 while (true) {
82 QByteArray bytes = reply->read(4096);
83 if (!bytes.size()) {
84 break;
85 }
86 f.write(bytes);
87 }
88 emit updateDone(true);
89}