Marble

HttpDownloadManager.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
4// SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
5// SPDX-FileCopyrightText: 2008, 2009 Jens-Michael Hoffmann <jensmh@gmx.de>
6//
7
8#include "HttpDownloadManager.h"
9
10#include <QCoreApplication>
11#include <QList>
12#include <QMap>
13#include <QNetworkAccessManager>
14#include <QTimer>
15
16#include "DownloadPolicy.h"
17#include "DownloadQueueSet.h"
18#include "HttpJob.h"
19#include "MarbleDebug.h"
20#include "StoragePolicy.h"
21
22using namespace Marble;
23
24// Time before a failed download job is requeued in ms
25const quint32 requeueTime = 60000;
26
27class Q_DECL_HIDDEN HttpDownloadManager::Private
28{
29public:
30 Private(HttpDownloadManager *parent, StoragePolicy *policy);
31 ~Private();
32
33 void connectDefaultQueueSets();
34 void connectQueueSet(DownloadQueueSet *);
35 bool hasDownloadPolicy(const DownloadPolicy &policy) const;
36 void finishJob(const QByteArray &, const QString &, const QString &id);
37 void requeue();
38 void startRetryTimer();
39
40 DownloadQueueSet *findQueues(const QString &hostName, const DownloadUsage usage);
41
42 HttpDownloadManager *m_downloadManager;
43 QTimer m_requeueTimer;
44 /**
45 * Contains per download policy a queue set containing of
46 * - a queue where jobs are waiting for being activated (=downloaded)
47 * - a queue containing currently being downloaded
48 * - a queue for retries of failed downloads */
51 StoragePolicy *const m_storagePolicy;
52 QNetworkAccessManager m_networkAccessManager;
53 bool m_acceptJobs;
54};
55
56HttpDownloadManager::Private::Private(HttpDownloadManager *parent, StoragePolicy *policy)
57 : m_downloadManager(parent)
58 , m_requeueTimer()
59 , m_storagePolicy(policy)
60 , m_networkAccessManager()
61 , m_acceptJobs(true)
62{
63 // setup default download policy and associated queue set
64 DownloadPolicy defaultBrowsePolicy;
65 defaultBrowsePolicy.setMaximumConnections(20);
66 m_defaultQueueSets[DownloadBrowse] = new DownloadQueueSet(defaultBrowsePolicy);
67 DownloadPolicy defaultBulkDownloadPolicy;
68 defaultBulkDownloadPolicy.setMaximumConnections(2);
69 m_defaultQueueSets[DownloadBulk] = new DownloadQueueSet(defaultBulkDownloadPolicy);
70}
71
72HttpDownloadManager::Private::~Private()
73{
74 QMap<DownloadUsage, DownloadQueueSet *>::iterator pos = m_defaultQueueSets.begin();
75 QMap<DownloadUsage, DownloadQueueSet *>::iterator const end = m_defaultQueueSets.end();
76 for (; pos != end; ++pos)
77 delete pos.value();
78}
79
80DownloadQueueSet *HttpDownloadManager::Private::findQueues(const QString &hostName, const DownloadUsage usage)
81{
82 DownloadQueueSet *result = nullptr;
83 QList<QPair<DownloadPolicyKey, DownloadQueueSet *>>::iterator pos = m_queueSets.begin();
84 QList<QPair<DownloadPolicyKey, DownloadQueueSet *>>::iterator const end = m_queueSets.end();
85 for (; pos != end; ++pos) {
86 if ((*pos).first.matches(hostName, usage)) {
87 result = (*pos).second;
88 break;
89 }
90 }
91 if (!result) {
92 mDebug() << "No download policy found for" << hostName << usage << ", using default policy.";
93 result = m_defaultQueueSets[usage];
94 }
95 return result;
96}
97
99 : d(new Private(this, policy))
100{
101 d->m_requeueTimer.setInterval(requeueTime);
102 connect(&d->m_requeueTimer, SIGNAL(timeout()), this, SLOT(requeue()));
103 d->connectDefaultQueueSets();
104}
105
110
112{
113 /*
114 PORT_QT6
115 d->m_networkAccessManager.setNetworkAccessible( enable ? QNetworkAccessManager::Accessible : QNetworkAccessManager::NotAccessible );
116 */
117 d->m_acceptJobs = enable;
118 QList<QPair<DownloadPolicyKey, DownloadQueueSet *>>::iterator pos = d->m_queueSets.begin();
119 QList<QPair<DownloadPolicyKey, DownloadQueueSet *>>::iterator const end = d->m_queueSets.end();
120 for (; pos != end; ++pos) {
121 pos->second->purgeJobs();
122 }
123}
124
125void HttpDownloadManager::addDownloadPolicy(const DownloadPolicy &policy)
126{
127 if (d->hasDownloadPolicy(policy))
128 return;
129 auto const queueSet = new DownloadQueueSet(policy, this);
130 d->connectQueueSet(queueSet);
131 d->m_queueSets.append(QPair<DownloadPolicyKey, DownloadQueueSet *>(queueSet->downloadPolicy().key(), queueSet));
132}
133
134void HttpDownloadManager::addJob(const QUrl &sourceUrl, const QString &destFileName, const QString &id, const DownloadUsage usage)
135{
136 if (!d->m_acceptJobs) {
137 mDebug() << "Working offline, not adding job";
138 return;
139 }
140
141 DownloadQueueSet *const queueSet = d->findQueues(sourceUrl.host(), usage);
142 if (queueSet->canAcceptJob(sourceUrl, destFileName)) {
143 auto const job = new HttpJob(sourceUrl, destFileName, id, &d->m_networkAccessManager);
144 job->setUserAgentPluginId(QStringLiteral("QNamNetworkPlugin"));
145 job->setDownloadUsage(usage);
146 mDebug() << "adding job " << sourceUrl;
147 queueSet->addJob(job);
148 }
149}
150
151void HttpDownloadManager::Private::finishJob(const QByteArray &data, const QString &destinationFileName, const QString &id)
152{
153 mDebug() << "emitting downloadComplete( QByteArray, " << id << ")";
154 Q_EMIT m_downloadManager->downloadComplete(data, id);
155 if (m_storagePolicy) {
156 const bool saved = m_storagePolicy->updateFile(destinationFileName, data);
157 if (saved) {
158 mDebug() << "emitting downloadComplete( " << destinationFileName << ", " << id << ")";
159 Q_EMIT m_downloadManager->downloadComplete(destinationFileName, id);
160 } else {
161 qWarning() << "Could not save:" << destinationFileName;
162 }
163 }
164}
165
166void HttpDownloadManager::Private::requeue()
167{
168 m_requeueTimer.stop();
169
170 QList<QPair<DownloadPolicyKey, DownloadQueueSet *>>::iterator pos = m_queueSets.begin();
171 QList<QPair<DownloadPolicyKey, DownloadQueueSet *>>::iterator const end = m_queueSets.end();
172 for (; pos != end; ++pos) {
173 (*pos).second->retryJobs();
174 }
175}
176
177void HttpDownloadManager::Private::startRetryTimer()
178{
179 if (!m_requeueTimer.isActive())
180 m_requeueTimer.start();
181}
182
183void HttpDownloadManager::Private::connectDefaultQueueSets()
184{
186 QMap<DownloadUsage, DownloadQueueSet *>::iterator const end = m_defaultQueueSets.end();
187 for (; pos != end; ++pos)
188 connectQueueSet(pos.value());
189}
190
191void HttpDownloadManager::Private::connectQueueSet(DownloadQueueSet *queueSet)
192{
193 connect(queueSet, SIGNAL(jobFinished(QByteArray, QString, QString)), m_downloadManager, SLOT(finishJob(QByteArray, QString, QString)));
194 connect(queueSet, SIGNAL(jobRetry()), m_downloadManager, SLOT(startRetryTimer()));
195 connect(queueSet, SIGNAL(jobRedirected(QUrl, QString, QString, DownloadUsage)), m_downloadManager, SLOT(addJob(QUrl, QString, QString, DownloadUsage)));
196 // relay jobAdded/jobRemoved signals (interesting for progress bar)
197 connect(queueSet, SIGNAL(jobAdded()), m_downloadManager, SIGNAL(jobAdded()));
198 connect(queueSet, SIGNAL(jobRemoved()), m_downloadManager, SIGNAL(jobRemoved()));
199 connect(queueSet, SIGNAL(progressChanged(int, int)), m_downloadManager, SIGNAL(progressChanged(int, int)));
200}
201
202bool HttpDownloadManager::Private::hasDownloadPolicy(const DownloadPolicy &policy) const
203{
204 bool found = false;
205 QList<QPair<DownloadPolicyKey, DownloadQueueSet *>>::const_iterator pos = m_queueSets.constBegin();
206 QList<QPair<DownloadPolicyKey, DownloadQueueSet *>>::const_iterator const end = m_queueSets.constEnd();
207 for (; pos != end; ++pos) {
208 if ((*pos).second->downloadPolicy() == policy) {
209 found = true;
210 break;
211 }
212 }
213 return found;
214}
215
216QByteArray HttpDownloadManager::userAgent(const QString &platform, const QString &component)
217{
218 QString result(QStringLiteral("Mozilla/5.0 (compatible; Marble/%1; %2; %3; %4; %5)"));
219 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
220 QString const device = smallScreen ? QStringLiteral("MobileDevice") : QStringLiteral("DesktopDevice");
222 result = result.arg(QString::fromLatin1(MARBLE_VERSION_STRING), device, platform, component, app);
223 return result.toLatin1();
224}
225
226#include "moc_HttpDownloadManager.cpp"
This class manages scheduled downloads.
void jobRemoved()
Signal is emitted when a job is removed from the queue.
void setDownloadEnabled(const bool enable)
Switches loading on/off, useful for offline mode.
void jobAdded()
Signal is emitted when a new job is added to the queue.
~HttpDownloadManager() override
Destroys the http download manager.
HttpDownloadManager(StoragePolicy *policy)
Creates a new http download manager.
void addJob(const QUrl &sourceUrl, const QString &destFilename, const QString &id, const DownloadUsage usage)
Adds a new job with a sourceUrl, destination file name and given id.
void progressChanged(int active, int queued)
A job was queued, activated or removed (finished, failed)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
Binds a QML item to a specific geodetic location in screen coordinates.
DownloadUsage
This enum is used to describe the type of download.
@ DownloadBrowse
Browsing mode, normal operation of Marble, like a web browser.
@ DownloadBulk
Bulk download, for example "File/Download region".
iterator begin()
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString fromLatin1(QByteArrayView str)
void setInterval(int msec)
QString host(ComponentFormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:02:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.