Marble

HttpDownloadManager.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <[email protected]>
4 // SPDX-FileCopyrightText: 2007 Inge Wallin <[email protected]>
5 // SPDX-FileCopyrightText: 2008, 2009 Jens-Michael Hoffmann <[email protected]>
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 
22 using namespace Marble;
23 
24 // Time before a failed download job is requeued in ms
25 const quint32 requeueTime = 60000;
26 
27 class 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 */
50  QMap<DownloadUsage, DownloadQueueSet *> m_defaultQueueSets;
51  StoragePolicy *const m_storagePolicy;
52  QNetworkAccessManager m_networkAccessManager;
53  bool m_acceptJobs;
54 
55 };
56 
57 HttpDownloadManager::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 
73 HttpDownloadManager::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 
81 DownloadQueueSet *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 
111 {
112  delete d;
113 }
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 
127 void 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 );
133  d->m_queueSets.append( QPair<DownloadPolicyKey, DownloadQueueSet *>
134  ( queueSet->downloadPolicy().key(), queueSet ));
135 }
136 
137 void HttpDownloadManager::addJob( const QUrl& sourceUrl, const QString& destFileName,
138  const QString &id, const DownloadUsage usage )
139 {
140  if ( !d->m_acceptJobs ) {
141  mDebug() << Q_FUNC_INFO << "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 
155 void 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 
171 void 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 
182 void HttpDownloadManager::Private::startRetryTimer()
183 {
184  if ( !m_requeueTimer.isActive() )
185  m_requeueTimer.start();
186 }
187 
188 void HttpDownloadManager::Private::connectDefaultQueueSets()
189 {
190  QMap<DownloadUsage, DownloadQueueSet *>::iterator pos = m_defaultQueueSets.begin();
191  QMap<DownloadUsage, DownloadQueueSet *>::iterator const end = m_defaultQueueSets.end();
192  for (; pos != end; ++pos )
193  connectQueueSet( pos.value() );
194 }
195 
196 void HttpDownloadManager::Private::connectQueueSet( DownloadQueueSet * queueSet )
197 {
198  connect( queueSet, SIGNAL(jobFinished(QByteArray,QString,QString)),
199  m_downloadManager, SLOT(finishJob(QByteArray,QString,QString)));
200  connect( queueSet, SIGNAL(jobRetry()), m_downloadManager, SLOT(startRetryTimer()));
201  connect( queueSet, SIGNAL(jobRedirected(QUrl,QString,QString,DownloadUsage)),
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 
209 bool 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 
223 QByteArray 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"
@ DownloadBrowse
Browsing mode, normal operation of Marble, like a web browser.
Definition: MarbleGlobal.h:155
This class manages scheduled downloads.
DownloadUsage
This enum is used to describe the type of download.
Definition: MarbleGlobal.h:153
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
~HttpDownloadManager() override
Destroys the http download manager.
Binds a QML item to a specific geodetic location in screen coordinates.
void setDownloadEnabled(const bool enable)
Switches loading on/off, useful for offline mode.
QString host(QUrl::ComponentFormattingOptions options) const const
QList::iterator begin()
@ DownloadBulk
Bulk download, for example "File/Download region".
Definition: MarbleGlobal.h:154
HttpDownloadManager(StoragePolicy *policy)
Creates a new http download manager.
const QList< QKeySequence > & end()
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
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.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Sep 25 2023 03:50:19 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.