Ubuntu Download Manager  0.9.0
A session-wide downloading service
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator
download_impl.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2013-2014 Canonical Ltd.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of version 3 of the GNU Lesser General Public
6  * License as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the
15  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  * Boston, MA 02110-1301, USA.
17  */
18 
20 #include "download_impl.h"
21 
22 namespace {
23  const QString CLICK_PACKAGE_PROPERTY = "ClickPackage";
24  const QString SHOW_INDICATOR_PROPERTY = "ShowInIndicator";
25  const QString TITLE_PROPERTY = "Title";
26 }
27 
28 namespace Ubuntu {
29 
30 namespace DownloadManager {
31 
32 using namespace Logging;
33 
34 DownloadImpl::DownloadImpl(const QDBusConnection& conn,
35  const QString& servicePath,
36  const QDBusObjectPath& objectPath,
37  QObject* parent)
38  : Download(parent),
39  _id(objectPath.path()),
40  _conn(conn),
41  _servicePath(servicePath) {
42 
43  _dbusInterface = new DownloadInterface(servicePath,
44  _id, conn);
45 
46  _propertiesInterface = new PropertiesInterface(servicePath,
47  _id, conn);
48 
49  // fwd all the signals but the error one
50  auto connected = connect(_dbusInterface, &DownloadInterface::canceled,
51  this, &Download::canceled);
52 
53  if (!connected) {
54  Logger::log(Logger::Critical,
55  "Could not connect to signal DownloadInterface::canceled");
56  }
57 
58  connected = connect(_dbusInterface, &DownloadInterface::finished,
59  this, &Download::finished);
60  if (!connected) {
61  Logger::log(Logger::Critical,
62  "Could not connect to signal &DownloadInterface::finished");
63  }
64 
65  connected = connect(_dbusInterface, &DownloadInterface::paused,
66  this, &Download::paused);
67  if (!connected) {
68  Logger::log(Logger::Critical,
69  "Could not connect to signal DownloadInterface::paused");
70  }
71 
72  connected = connect(_dbusInterface, &DownloadInterface::processing,
73  this, &Download::processing);
74  if (!connected) {
75  Logger::log(Logger::Critical,
76  "Could not connect to signal DownloadInterface::processing");
77  }
78 
79  connected = connect(_dbusInterface, static_cast<void(DownloadInterface::*)
80  (qulonglong, qulonglong)>(&DownloadInterface::progress),
81  this, static_cast<void(Download::*)
82  (qulonglong, qulonglong)>(&Download::progress));
83  if (!connected) {
84  Logger::log(Logger::Critical,
85  "Could not connect to signal &DownloadInterface::progress");
86  }
87 
88  connected = connect(_dbusInterface, &DownloadInterface::resumed,
89  this, &Download::resumed);
90  if (!connected) {
91  Logger::log(Logger::Critical,
92  "Could not connect to signal &DownloadInterface::resumed");
93  }
94 
95  connected = connect(_dbusInterface, &DownloadInterface::started,
96  this, &Download::started);
97  if (!connected) {
98  Logger::log(Logger::Critical,
99  "Could not connect to signal &DownloadInterface::started");
100  }
101 
102  // connect to the different type of errors that will later be converted to
103  // the error type to be used by the client.
104  connected = connect(_dbusInterface, &DownloadInterface::httpError,
105  this, &DownloadImpl::onHttpError);
106  if (!connected) {
107  Logger::log(Logger::Critical,
108  "Could not connect to signal &DownloadInterface::httpError");
109  }
110 
111  connected = connect(_dbusInterface, &DownloadInterface::networkError,
112  this, &DownloadImpl::onNetworkError);
113  if (!connected) {
114  Logger::log(Logger::Critical,
115  "Could not connect to signal &DownloadInterface::networkError");
116  }
117 
118  connected = connect(_dbusInterface, &DownloadInterface::processError,
119  this, &DownloadImpl::onProcessError);
120  if (!connected) {
121  Logger::log(Logger::Critical,
122  "Could not connect to signal &DownloadInterface::processError");
123  }
124 
125  connected = connect(_dbusInterface, &DownloadInterface::authError,
126  this, &DownloadImpl::onAuthError);
127  if (!connected) {
128  Logger::log(Logger::Critical,
129  "Could not connect to signal &DownloadInterface::authError");
130  }
131 
132  connected = connect(_propertiesInterface, &PropertiesInterface::PropertiesChanged,
133  this, &DownloadImpl::onPropertiesChanged);
134  if (!connected) {
135  Logger::log(Logger::Critical,
136  "Could not connect to signal &PropertiesInterface::PropertiesChanged");
137  }
138 }
139 
140 DownloadImpl::DownloadImpl(const QDBusConnection& conn, Error* err, QObject* parent)
141  : Download(parent),
142  _isError(true),
143  _lastError(err),
144  _conn(conn) {
145 }
146 
147 DownloadImpl::~DownloadImpl() {
148  delete _lastError;
149  delete _dbusInterface;
150  delete _propertiesInterface;
151 }
152 
153 void
154 DownloadImpl::setLastError(Error* err) {
155  Logger::log(Logger::Debug,
156  QString("Download{%1} setLastError(%2)").arg(_id).arg(
157  err->errorString()));
158  if (_lastError != nullptr) {
159  delete _lastError;
160  }
161  _lastError = err;
162  _isError = true;
163  emit Download::error(err);
164 }
165 
166 void
167 DownloadImpl::setLastError(const QDBusError& err) {
168  setLastError(new DBusError(err, this));
169 }
170 
171 void
172 DownloadImpl::start() {
173  Logger::log(Logger::Debug, QString("Download{%1} start())").arg(_id));
174  QDBusPendingCall call =
175  _dbusInterface->start();
176  auto watcher = new DownloadPCW(_conn, _servicePath,
177  call, this);
178  Q_UNUSED(watcher);
179 }
180 
181 void
182 DownloadImpl::pause() {
183  Logger::log(Logger::Debug, QString("Download{%1} pause())").arg(_id));
184  QDBusPendingCall call =
185  _dbusInterface->pause();
186  auto watcher = new DownloadPCW(_conn, _servicePath,
187  call, this);
188  Q_UNUSED(watcher);
189 }
190 
191 void
192 DownloadImpl::resume() {
193  Logger::log(Logger::Debug, QString("Download{%1} resume())").arg(_id));
194  QDBusPendingCall call =
195  _dbusInterface->resume();
196  auto watcher = new DownloadPCW(_conn, _servicePath,
197  call, this);
198  Q_UNUSED(watcher);
199 }
200 
201 void
202 DownloadImpl::cancel() {
203  Logger::log(Logger::Debug, QString("Download{%1} cancel())").arg(_id));
204  QDBusPendingCall call =
205  _dbusInterface->cancel();
206  auto watcher = new DownloadPCW(_conn, _servicePath,
207  call, this);
208  Q_UNUSED(watcher);
209 }
210 
211 void
212 DownloadImpl::allowMobileDownload(bool allowed) {
213  Logger::log(Logger::Debug,
214  QString("Download{%1} allowMobileDownload%2())").arg(_id).arg(allowed));
215  QDBusPendingReply<> reply =
216  _dbusInterface->allowGSMDownload(allowed);
217  // block, the call should be fast enough
218  reply.waitForFinished();
219  if (reply.isError()) {
220  Logger::log(Logger::Error, "Error when setting mobile data usage");
221  setLastError(reply.error());
222  }
223 }
224 
225 bool
226 DownloadImpl::isMobileDownloadAllowed() {
227  Logger::log(Logger::Debug,
228  QString("Download{%1} isMobileDownloadAllowed").arg(_id));
229  QDBusPendingReply<bool> reply =
230  _dbusInterface->isGSMDownloadAllowed();
231  // block, the call should be fast enough
232  reply.waitForFinished();
233  if (reply.isError()) {
234  Logger::log(Logger::Error, "Error when querying mobile data usage");
235  setLastError(reply.error());
236  return false;
237  } else {
238  auto result = reply.value();
239  return result;
240  }
241 }
242 
243 void
244 DownloadImpl::setDestinationDir(const QString& path) {
245  Logger::log(Logger::Debug, QString("Dowmload{%1} setDestinationDir(%2)")
246  .arg(_id).arg(path));
247  QDBusPendingReply<> reply =
248  _dbusInterface->setDestinationDir(path);
249  // block, the call should be fast enough
250  reply.waitForFinished();
251  if (reply.isError()) {
252  Logger::log(Logger::Error, "Error setting the download directory");
253  setLastError(reply.error());
254  }
255 }
256 
257 void
258 DownloadImpl::setHeaders(QMap<QString, QString> headers) {
259  Logger::log(Logger::Debug,
260  QString("Download {%1} setHeaders(%2)").arg(_id), headers);
261 
262  QDBusPendingReply<> reply =
263  _dbusInterface->setHeaders(headers);
264  // block, the call should be fast enough
265  reply.waitForFinished();
266  if (reply.isError()) {
267  Logger::log(Logger::Error, "Error setting the download headers");
268  setLastError(reply.error());
269  }
270 }
271 
272 QVariantMap
273 DownloadImpl::metadata() {
274  Logger::log(Logger::Debug, QString("Download{%1} metadata()").arg(_id));
275  QDBusPendingReply<QVariantMap> reply =
276  _dbusInterface->metadata();
277  // block the call is fast enough
278  reply.waitForFinished();
279  if (reply.isError()) {
280  Logger::log(Logger::Error, "Error querying the download metadata");
281  QVariantMap emptyResult;
282  setLastError(reply.error());
283  return emptyResult;
284  } else {
285  auto result = reply.value();
286  return result;
287  }
288 }
289 
290 void
291 DownloadImpl::setMetadata(QVariantMap map) {
292  Logger::log(Logger::Debug,
293  QString("Download {%1} setMetadata(%2)").arg(_id), map);
294 
295  QDBusPendingReply<> reply =
296  _dbusInterface->setMetadata(map);
297  // block, the call should be fast enough
298  reply.waitForFinished();
299  if (reply.isError()) {
300  qDebug() << "Error setting metadata";
301  Logger::log(Logger::Error, "Error setting the download metadata");
302  qDebug() << reply.error();
303  setLastError(reply.error());
304  }
305 }
306 
307 QMap<QString, QString>
308 DownloadImpl::headers() {
309  Logger::log(Logger::Debug, QString("Download{%1} headers()").arg(_id));
310  QDBusPendingReply<QMap<QString, QString> > reply =
311  _dbusInterface->headers();
312  // block, the call should be fast enough
313  reply.waitForFinished();
314  if (reply.isError()) {
315  Logger::log(Logger::Error, "Error querying the download headers");
316  setLastError(reply.error());
317  QMap<QString, QString> empty;
318  return empty;
319  } else {
320  auto result = reply.value();
321  return result;
322  }
323 }
324 
325 
326 void
327 DownloadImpl::setThrottle(qulonglong speed) {
328  Logger::log(Logger::Debug,
329  QString("Download{%1} setThrottle(%2)").arg(_id).arg(speed));
330  QDBusPendingReply<> reply =
331  _dbusInterface->setThrottle(speed);
332  // block, the call should be fast enough
333  reply.waitForFinished();
334  if (reply.isError()) {
335  Logger::log(Logger::Error, "Error setting the download throttle");
336  setLastError(reply.error());
337  }
338 }
339 
340 qulonglong
341 DownloadImpl::throttle() {
342  Logger::log(Logger::Debug, QString("Download{%1} throttle()").arg(_id));
343  QDBusPendingReply<qulonglong> reply =
344  _dbusInterface->throttle();
345  // block, the call is fast enough
346  reply.waitForFinished();
347  if (reply.isError()) {
348  Logger::log(Logger::Error, "Error querying the download throttle");
349  setLastError(reply.error());
350  return 0;
351  } else {
352  auto result = reply.value();
353  return result;
354  }
355 }
356 
357 QString
358 DownloadImpl::id() const {
359  return _id;
360 }
361 
362 qulonglong
363 DownloadImpl::progress() {
364  Logger::log(Logger::Debug, QString("Download{%1} progress()").arg(_id));
365  QDBusPendingReply<qulonglong> reply =
366  _dbusInterface->progress();
367  // block call should be fast enough
368  reply.waitForFinished();
369  if (reply.isError()) {
370  Logger::log(Logger::Error, "Error querying the download progress");
371  setLastError(reply.error());
372  return 0;
373  } else {
374  auto result = reply.value();
375  return result;
376  }
377 }
378 
379 qulonglong
380 DownloadImpl::totalSize() {
381  Logger::log(Logger::Debug, QString("Download{%1} totalSize()").arg(_id));
382  QDBusPendingReply<qulonglong> reply =
383  _dbusInterface->totalSize();
384  // block call should be fast enough
385  reply.waitForFinished();
386  if (reply.isError()) {
387  Logger::log(Logger::Error, "Error querying the download size");
388  setLastError(reply.error());
389  return 0;
390  } else {
391  auto result = reply.value();
392  return result;
393  }
394 }
395 
396 bool
397 DownloadImpl::isError() const {
398  return _isError;
399 }
400 
401 Error*
402 DownloadImpl::error() const {
403  return _lastError;
404 }
405 
406 QString
407 DownloadImpl::clickPackage() const {
408  return _dbusInterface->clickPackage();
409 }
410 
411 bool
412 DownloadImpl::showInIndicator() const {
413  return _dbusInterface->showInIndicator();
414 }
415 
416 QString
417 DownloadImpl::title() const {
418  return _dbusInterface->title();
419 }
420 
421 void
422 DownloadImpl::onHttpError(HttpErrorStruct errStruct) {
423  auto err = new HttpError(errStruct, this);
424  setLastError(err);
425 }
426 
427 void
428 DownloadImpl::onNetworkError(NetworkErrorStruct errStruct) {
429  auto err = new NetworkError(errStruct, this);
430  setLastError(err);
431 }
432 
433 void
434 DownloadImpl::onProcessError(ProcessErrorStruct errStruct) {
435  auto err = new ProcessError(errStruct, this);
436  setLastError(err);
437 }
438 
439 void
440 DownloadImpl::onAuthError(AuthErrorStruct errStruct) {
441  auto err = new AuthError(errStruct, this);
442  setLastError(err);
443 }
444 
445 void
446 DownloadImpl::onPropertiesChanged(const QString& interfaceName,
447  const QVariantMap& changedProperties,
448  const QStringList& invalidatedProperties) {
449  Q_UNUSED(invalidatedProperties);
450  // just take care of the property changes from the download interface
451  if (interfaceName == DownloadInterface::staticInterfaceName()) {
452  if (changedProperties.contains(CLICK_PACKAGE_PROPERTY)) {
453  emit clickPackagedChanged();
454  }
455 
456  if (changedProperties.contains(SHOW_INDICATOR_PROPERTY)) {
457  emit showInIndicatorChanged();
458  }
459 
460  if (changedProperties.contains(TITLE_PROPERTY)) {
461  emit titleChanged();
462  }
463  }
464 }
465 
466 } // DownloadManager
467 
468 } // Ubuntu
void finished(const QString &path)
Download(QObject *parent=0)
Definition: download.h:56
void PropertiesChanged(const QString &interface_name, const QVariantMap &changed_properties, const QStringList &invalidated_properties)
void processing(const QString &path)
virtual Error * error() const =0
virtual qulonglong progress()=0