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 <QList>
11#include <QMap>
12#include <QTimer>
13#include <QNetworkAccessManager>
14#include <QCoreApplication>
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{
29 public:
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};
56
57HttpDownloadManager::Private::Private(HttpDownloadManager *parent, StoragePolicy *policy )
58 : m_downloadManager( parent ),
59 m_requeueTimer(),
60 m_storagePolicy( policy ),
61 m_networkAccessManager(),
62 m_acceptJobs( true )
63{
64 // setup default download policy and associated queue set
65 DownloadPolicy defaultBrowsePolicy;
66 defaultBrowsePolicy.setMaximumConnections( 20 );
67 m_defaultQueueSets[ DownloadBrowse ] = new DownloadQueueSet( defaultBrowsePolicy );
68 DownloadPolicy defaultBulkDownloadPolicy;
69 defaultBulkDownloadPolicy.setMaximumConnections( 2 );
70 m_defaultQueueSets[ DownloadBulk ] = new DownloadQueueSet( defaultBulkDownloadPolicy );
71}
72
73HttpDownloadManager::Private::~Private()
74{
75 QMap<DownloadUsage, DownloadQueueSet *>::iterator pos = m_defaultQueueSets.begin();
76 QMap<DownloadUsage, DownloadQueueSet *>::iterator const end = m_defaultQueueSets.end();
77 for (; pos != end; ++pos )
78 delete pos.value();
79}
80
81DownloadQueueSet *HttpDownloadManager::Private::findQueues( const QString& hostName,
82 const DownloadUsage usage )
83{
84 DownloadQueueSet * result = nullptr;
85 QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::iterator pos = m_queueSets.begin();
86 QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::iterator const end = m_queueSets.end();
87 for (; pos != end; ++pos ) {
88 if ( (*pos).first.matches( hostName, usage )) {
89 result = (*pos).second;
90 break;
91 }
92 }
93 if ( !result ) {
94 mDebug() << "No download policy found for" << hostName << usage
95 << ", using default policy.";
96 result = m_defaultQueueSets[ usage ];
97 }
98 return result;
99}
100
101
103 : d( new Private( this, policy ) )
104{
105 d->m_requeueTimer.setInterval( requeueTime );
106 connect( &d->m_requeueTimer, SIGNAL(timeout()), this, SLOT(requeue()) );
107 d->connectDefaultQueueSets();
108}
109
114
116{
117 d->m_networkAccessManager.setNetworkAccessible( enable ? QNetworkAccessManager::Accessible : QNetworkAccessManager::NotAccessible );
118 d->m_acceptJobs = enable;
119 QList<QPair<DownloadPolicyKey, DownloadQueueSet *> >::iterator pos = d->m_queueSets.begin();
120 QList<QPair<DownloadPolicyKey, DownloadQueueSet *> >::iterator const end = d->m_queueSets.end();
121 for (; pos != end; ++pos ) {
122 pos->second->purgeJobs();
123 }
124
125}
126
127void HttpDownloadManager::addDownloadPolicy( const DownloadPolicy& policy )
128{
129 if ( d->hasDownloadPolicy( policy ))
130 return;
131 DownloadQueueSet * const queueSet = new DownloadQueueSet( policy, this );
132 d->connectQueueSet( queueSet );
134 ( queueSet->downloadPolicy().key(), queueSet ));
135}
136
137void HttpDownloadManager::addJob( const QUrl& sourceUrl, const QString& destFileName,
138 const QString &id, const DownloadUsage usage )
139{
140 if ( !d->m_acceptJobs ) {
141 mDebug() << "Working offline, not adding job";
142 return;
143 }
144
145 DownloadQueueSet * const queueSet = d->findQueues( sourceUrl.host(), usage );
146 if ( queueSet->canAcceptJob( sourceUrl, destFileName )) {
147 HttpJob * const job = new HttpJob( sourceUrl, destFileName, id, &d->m_networkAccessManager );
148 job->setUserAgentPluginId( "QNamNetworkPlugin" );
149 job->setDownloadUsage( usage );
150 mDebug() << "adding job " << sourceUrl;
151 queueSet->addJob( job );
152 }
153}
154
155void HttpDownloadManager::Private::finishJob( const QByteArray& data, const QString& destinationFileName,
156 const QString& id )
157{
158 mDebug() << "emitting downloadComplete( QByteArray, " << id << ")";
159 emit m_downloadManager->downloadComplete( data, id );
160 if ( m_storagePolicy ) {
161 const bool saved = m_storagePolicy->updateFile( destinationFileName, data );
162 if ( saved ) {
163 mDebug() << "emitting downloadComplete( " << destinationFileName << ", " << id << ")";
164 emit m_downloadManager->downloadComplete( destinationFileName, id );
165 } else {
166 qWarning() << "Could not save:" << destinationFileName;
167 }
168 }
169}
170
171void HttpDownloadManager::Private::requeue()
172{
173 m_requeueTimer.stop();
174
175 QList<QPair<DownloadPolicyKey, DownloadQueueSet *> >::iterator pos = m_queueSets.begin();
176 QList<QPair<DownloadPolicyKey, DownloadQueueSet *> >::iterator const end = m_queueSets.end();
177 for (; pos != end; ++pos ) {
178 (*pos).second->retryJobs();
179 }
180}
181
182void HttpDownloadManager::Private::startRetryTimer()
183{
184 if ( !m_requeueTimer.isActive() )
185 m_requeueTimer.start();
186}
187
188void HttpDownloadManager::Private::connectDefaultQueueSets()
189{
191 QMap<DownloadUsage, DownloadQueueSet *>::iterator const end = m_defaultQueueSets.end();
192 for (; pos != end; ++pos )
193 connectQueueSet( pos.value() );
194}
195
196void HttpDownloadManager::Private::connectQueueSet( DownloadQueueSet * queueSet )
197{
199 m_downloadManager, SLOT(finishJob(QByteArray,QString,QString)));
200 connect( queueSet, SIGNAL(jobRetry()), m_downloadManager, SLOT(startRetryTimer()));
202 m_downloadManager, SLOT(addJob(QUrl,QString,QString,DownloadUsage)));
203 // relay jobAdded/jobRemoved signals (interesting for progress bar)
204 connect( queueSet, SIGNAL(jobAdded()), m_downloadManager, SIGNAL(jobAdded()));
205 connect( queueSet, SIGNAL(jobRemoved()), m_downloadManager, SIGNAL(jobRemoved()));
206 connect( queueSet, SIGNAL(progressChanged(int,int)), m_downloadManager, SIGNAL(progressChanged(int,int)) );
207}
208
209bool HttpDownloadManager::Private::hasDownloadPolicy( const DownloadPolicy& policy ) const
210{
211 bool found = false;
212 QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::const_iterator pos = m_queueSets.constBegin();
213 QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::const_iterator const end = m_queueSets.constEnd();
214 for (; pos != end; ++pos ) {
215 if ( (*pos).second->downloadPolicy() == policy ) {
216 found = true;
217 break;
218 }
219 }
220 return found;
221}
222
223QByteArray HttpDownloadManager::userAgent(const QString &platform, const QString &component)
224{
225 QString result( "Mozilla/5.0 (compatible; Marble/%1; %2; %3; %4; %5)" );
226 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
227 QString const device = smallScreen ? "MobileDevice" : "DesktopDevice";
229 result = result.arg( MARBLE_VERSION_STRING, device, platform, component, app);
230 return result.toLatin1();
231}
232
233#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)
const QList< QKeySequence > & end()
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()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
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 Tue Mar 26 2024 11:18:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.