Marble

HttpDownloadManager.cpp
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2006-2007 Torsten Rahn <[email protected]>
9 // Copyright 2007 Inge Wallin <[email protected]>
10 // Copyright 2008,2009 Jens-Michael Hoffmann <[email protected]>
11 //
12 
13 #include "HttpDownloadManager.h"
14 
15 #include <QList>
16 #include <QMap>
17 #include <QTimer>
18 #include <QNetworkAccessManager>
19 
20 #include "DownloadPolicy.h"
21 #include "DownloadQueueSet.h"
22 #include "HttpJob.h"
23 #include "MarbleDebug.h"
24 #include "StoragePolicy.h"
25 
26 using namespace Marble;
27 
28 // Time before a failed download job is requeued in ms
29 const quint32 requeueTime = 60000;
30 
31 class Q_DECL_HIDDEN HttpDownloadManager::Private
32 {
33  public:
34  Private( HttpDownloadManager* parent, StoragePolicy *policy );
35  ~Private();
36 
37  void connectDefaultQueueSets();
38  void connectQueueSet( DownloadQueueSet * );
39  bool hasDownloadPolicy( const DownloadPolicy& policy ) const;
40  void finishJob( const QByteArray&, const QString&, const QString& id );
41  void requeue();
42  void startRetryTimer();
43 
44  DownloadQueueSet *findQueues( const QString& hostName, const DownloadUsage usage );
45 
46  HttpDownloadManager* m_downloadManager;
47  QTimer m_requeueTimer;
54  QMap<DownloadUsage, DownloadQueueSet *> m_defaultQueueSets;
55  StoragePolicy *const m_storagePolicy;
56  QNetworkAccessManager m_networkAccessManager;
57  bool m_acceptJobs;
58 
59 };
60 
61 HttpDownloadManager::Private::Private(HttpDownloadManager *parent, StoragePolicy *policy )
62  : m_downloadManager( parent ),
63  m_requeueTimer(),
64  m_storagePolicy( policy ),
65  m_networkAccessManager(),
66  m_acceptJobs( true )
67 {
68  // setup default download policy and associated queue set
69  DownloadPolicy defaultBrowsePolicy;
70  defaultBrowsePolicy.setMaximumConnections( 20 );
71  m_defaultQueueSets[ DownloadBrowse ] = new DownloadQueueSet( defaultBrowsePolicy );
72  DownloadPolicy defaultBulkDownloadPolicy;
73  defaultBulkDownloadPolicy.setMaximumConnections( 2 );
74  m_defaultQueueSets[ DownloadBulk ] = new DownloadQueueSet( defaultBulkDownloadPolicy );
75 }
76 
77 HttpDownloadManager::Private::~Private()
78 {
79  QMap<DownloadUsage, DownloadQueueSet *>::iterator pos = m_defaultQueueSets.begin();
80  QMap<DownloadUsage, DownloadQueueSet *>::iterator const end = m_defaultQueueSets.end();
81  for (; pos != end; ++pos )
82  delete pos.value();
83 }
84 
85 DownloadQueueSet *HttpDownloadManager::Private::findQueues( const QString& hostName,
86  const DownloadUsage usage )
87 {
88  DownloadQueueSet * result = nullptr;
89  QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::iterator pos = m_queueSets.begin();
90  QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::iterator const end = m_queueSets.end();
91  for (; pos != end; ++pos ) {
92  if ( (*pos).first.matches( hostName, usage )) {
93  result = (*pos).second;
94  break;
95  }
96  }
97  if ( !result ) {
98  mDebug() << "No download policy found for" << hostName << usage
99  << ", using default policy.";
100  result = m_defaultQueueSets[ usage ];
101  }
102  return result;
103 }
104 
105 
107  : d( new Private( this, policy ) )
108 {
109  d->m_requeueTimer.setInterval( requeueTime );
110  connect( &d->m_requeueTimer, SIGNAL(timeout()), this, SLOT(requeue()) );
111  d->connectDefaultQueueSets();
112 }
113 
115 {
116  delete d;
117 }
118 
120 {
121  d->m_networkAccessManager.setNetworkAccessible( enable ? QNetworkAccessManager::Accessible : QNetworkAccessManager::NotAccessible );
122  d->m_acceptJobs = enable;
123  QList<QPair<DownloadPolicyKey, DownloadQueueSet *> >::iterator pos = d->m_queueSets.begin();
124  QList<QPair<DownloadPolicyKey, DownloadQueueSet *> >::iterator const end = d->m_queueSets.end();
125  for (; pos != end; ++pos ) {
126  pos->second->purgeJobs();
127  }
128 
129 }
130 
131 void HttpDownloadManager::addDownloadPolicy( const DownloadPolicy& policy )
132 {
133  if ( d->hasDownloadPolicy( policy ))
134  return;
135  DownloadQueueSet * const queueSet = new DownloadQueueSet( policy, this );
136  d->connectQueueSet( queueSet );
137  d->m_queueSets.append( QPair<DownloadPolicyKey, DownloadQueueSet *>
138  ( queueSet->downloadPolicy().key(), queueSet ));
139 }
140 
141 void HttpDownloadManager::addJob( const QUrl& sourceUrl, const QString& destFileName,
142  const QString &id, const DownloadUsage usage )
143 {
144  if ( !d->m_acceptJobs ) {
145  mDebug() << Q_FUNC_INFO << "Working offline, not adding job";
146  return;
147  }
148 
149  DownloadQueueSet * const queueSet = d->findQueues( sourceUrl.host(), usage );
150  if ( queueSet->canAcceptJob( sourceUrl, destFileName )) {
151  HttpJob * const job = new HttpJob( sourceUrl, destFileName, id, &d->m_networkAccessManager );
152  job->setUserAgentPluginId( "QNamNetworkPlugin" );
153  job->setDownloadUsage( usage );
154  mDebug() << "adding job " << sourceUrl;
155  queueSet->addJob( job );
156  }
157 }
158 
159 void HttpDownloadManager::Private::finishJob( const QByteArray& data, const QString& destinationFileName,
160  const QString& id )
161 {
162  mDebug() << "emitting downloadComplete( QByteArray, " << id << ")";
163  emit m_downloadManager->downloadComplete( data, id );
164  if ( m_storagePolicy ) {
165  const bool saved = m_storagePolicy->updateFile( destinationFileName, data );
166  if ( saved ) {
167  mDebug() << "emitting downloadComplete( " << destinationFileName << ", " << id << ")";
168  emit m_downloadManager->downloadComplete( destinationFileName, id );
169  } else {
170  qWarning() << "Could not save:" << destinationFileName;
171  }
172  }
173 }
174 
175 void HttpDownloadManager::Private::requeue()
176 {
177  m_requeueTimer.stop();
178 
179  QList<QPair<DownloadPolicyKey, DownloadQueueSet *> >::iterator pos = m_queueSets.begin();
180  QList<QPair<DownloadPolicyKey, DownloadQueueSet *> >::iterator const end = m_queueSets.end();
181  for (; pos != end; ++pos ) {
182  (*pos).second->retryJobs();
183  }
184 }
185 
186 void HttpDownloadManager::Private::startRetryTimer()
187 {
188  if ( !m_requeueTimer.isActive() )
189  m_requeueTimer.start();
190 }
191 
192 void HttpDownloadManager::Private::connectDefaultQueueSets()
193 {
194  QMap<DownloadUsage, DownloadQueueSet *>::iterator pos = m_defaultQueueSets.begin();
195  QMap<DownloadUsage, DownloadQueueSet *>::iterator const end = m_defaultQueueSets.end();
196  for (; pos != end; ++pos )
197  connectQueueSet( pos.value() );
198 }
199 
200 void HttpDownloadManager::Private::connectQueueSet( DownloadQueueSet * queueSet )
201 {
202  connect( queueSet, SIGNAL(jobFinished(QByteArray,QString,QString)),
203  m_downloadManager, SLOT(finishJob(QByteArray,QString,QString)));
204  connect( queueSet, SIGNAL(jobRetry()), m_downloadManager, SLOT(startRetryTimer()));
205  connect( queueSet, SIGNAL(jobRedirected(QUrl,QString,QString,DownloadUsage)),
206  m_downloadManager, SLOT(addJob(QUrl,QString,QString,DownloadUsage)));
207  // relay jobAdded/jobRemoved signals (interesting for progress bar)
208  connect( queueSet, SIGNAL(jobAdded()), m_downloadManager, SIGNAL(jobAdded()));
209  connect( queueSet, SIGNAL(jobRemoved()), m_downloadManager, SIGNAL(jobRemoved()));
210  connect( queueSet, SIGNAL(progressChanged(int,int)), m_downloadManager, SIGNAL(progressChanged(int,int)) );
211 }
212 
213 bool HttpDownloadManager::Private::hasDownloadPolicy( const DownloadPolicy& policy ) const
214 {
215  bool found = false;
216  QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::const_iterator pos = m_queueSets.constBegin();
217  QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::const_iterator const end = m_queueSets.constEnd();
218  for (; pos != end; ++pos ) {
219  if ( (*pos).second->downloadPolicy() == policy ) {
220  found = true;
221  break;
222  }
223  }
224  return found;
225 }
226 
227 QByteArray HttpDownloadManager::userAgent(const QString &platform, const QString &component)
228 {
229  QString result( "Mozilla/5.0 (compatible; Marble/%1; %2; %3; %4)" );
230  bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
231  QString const device = smallScreen ? "MobileDevice" : "DesktopDevice";
232  result = result.arg( MARBLE_VERSION_STRING, device, platform, component);
233  return result.toLatin1();
234 }
235 
236 #include "moc_HttpDownloadManager.cpp"
HttpDownloadManager(StoragePolicy *policy)
Creates a new http download manager.
~HttpDownloadManager() override
Destroys the 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.
DownloadUsage
This enum is used to describe the type of download.
Definition: MarbleGlobal.h:152
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
Browsing mode, normal operation of Marble, like a web browser.
Definition: MarbleGlobal.h:154
void progressChanged(int active, int queued)
A job was queued, activated or removed (finished, failed)
Life of a HttpJob
QPoint pos() const const
int result() const const
void jobAdded()
Signal is emitted when a new job is added to the queue.
QList::iterator end()
const QList< QKeySequence > & end()
QByteArray toLatin1() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void jobRemoved()
Signal is emitted when a job is removed from the queue.
QList::const_iterator constEnd() const const
QList::const_iterator constBegin() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:36
QList::iterator begin()
Bulk download, for example "File/Download region".
Definition: MarbleGlobal.h:153
This class manages scheduled downloads.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Dec 3 2020 23:21:27 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.