Ubuntu Download Manager  1.2.0
A session-wide downloading service
download_impl.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2013-2015 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::finished,
66  this, &DownloadImpl::onFinished);
67  if (!connected) {
68  Logger::log(Logger::Critical,
69  "Could not connect to signal &DownloadInterface::finished");
70  }
71 
72  connected = connect(_dbusInterface, &DownloadInterface::paused,
73  this, &Download::paused);
74  if (!connected) {
75  Logger::log(Logger::Critical,
76  "Could not connect to signal DownloadInterface::paused");
77  }
78 
79  connected = connect(_dbusInterface, &DownloadInterface::processing,
80  this, &Download::processing);
81  if (!connected) {
82  Logger::log(Logger::Critical,
83  "Could not connect to signal DownloadInterface::processing");
84  }
85 
86  connected = connect(_dbusInterface, static_cast<void(DownloadInterface::*)
87  (qulonglong, qulonglong)>(&DownloadInterface::progress),
88  this, static_cast<void(Download::*)
89  (qulonglong, qulonglong)>(&Download::progress));
90  if (!connected) {
91  Logger::log(Logger::Critical,
92  "Could not connect to signal &DownloadInterface::progress");
93  }
94 
95  connected = connect(_dbusInterface, &DownloadInterface::resumed,
96  this, &Download::resumed);
97  if (!connected) {
98  Logger::log(Logger::Critical,
99  "Could not connect to signal &DownloadInterface::resumed");
100  }
101 
102  connected = connect(_dbusInterface, &DownloadInterface::started,
103  this, &Download::started);
104  if (!connected) {
105  Logger::log(Logger::Critical,
106  "Could not connect to signal &DownloadInterface::started");
107  }
108 
109  // connect to the different type of errors that will later be converted to
110  // the error type to be used by the client.
111  connected = connect(_dbusInterface, &DownloadInterface::httpError,
112  this, &DownloadImpl::onHttpError);
113  if (!connected) {
114  Logger::log(Logger::Critical,
115  "Could not connect to signal &DownloadInterface::httpError");
116  }
117 
118  connected = connect(_dbusInterface, &DownloadInterface::networkError,
119  this, &DownloadImpl::onNetworkError);
120  if (!connected) {
121  Logger::log(Logger::Critical,
122  "Could not connect to signal &DownloadInterface::networkError");
123  }
124 
125  connected = connect(_dbusInterface, &DownloadInterface::processError,
126  this, &DownloadImpl::onProcessError);
127  if (!connected) {
128  Logger::log(Logger::Critical,
129  "Could not connect to signal &DownloadInterface::processError");
130  }
131 
132  connected = connect(_dbusInterface, &DownloadInterface::authError,
133  this, &DownloadImpl::onAuthError);
134  if (!connected) {
135  Logger::log(Logger::Critical,
136  "Could not connect to signal &DownloadInterface::authError");
137  }
138 
139  connected = connect(_dbusInterface, &DownloadInterface::hashError,
140  this, &DownloadImpl::onHashError);
141  if (!connected) {
142  Logger::log(Logger::Critical,
143  "Could not connect to signal &DownloadInterface::authError");
144  }
145 
146  connected = connect(_propertiesInterface, &PropertiesInterface::PropertiesChanged,
147  this, &DownloadImpl::onPropertiesChanged);
148  if (!connected) {
149  Logger::log(Logger::Critical,
150  "Could not connect to signal &PropertiesInterface::PropertiesChanged");
151  }
152 }
153 
154 DownloadImpl::DownloadImpl(const QDBusConnection& conn, Error* err, QObject* parent)
155  : Download(parent),
156  _isError(true),
157  _lastError(err),
158  _conn(conn) {
159 }
160 
161 DownloadImpl::~DownloadImpl() {
162  delete _lastError;
163  delete _dbusInterface;
164  delete _propertiesInterface;
165 }
166 
167 void
168 DownloadImpl::setLastError(Error* err) {
169  Logger::log(Logger::Debug,
170  QString("Download{%1} setLastError(%2)").arg(_id).arg(
171  err->errorString()));
172  if (_lastError != nullptr) {
173  delete _lastError;
174  }
175  _lastError = err;
176  _isError = true;
177  emit Download::error(err);
178 }
179 
180 void
181 DownloadImpl::setLastError(const QDBusError& err) {
182  setLastError(new DBusError(err, this));
183 }
184 
185 void
186 DownloadImpl::start() {
187  Logger::log(Logger::Debug, QString("Download{%1} start())").arg(_id));
188  QDBusPendingCall call =
189  _dbusInterface->start();
190  auto watcher = new DownloadPCW(_conn, _servicePath,
191  call, this);
192  Q_UNUSED(watcher);
193 }
194 
195 void
196 DownloadImpl::pause() {
197  Logger::log(Logger::Debug, QString("Download{%1} pause())").arg(_id));
198  QDBusPendingCall call =
199  _dbusInterface->pause();
200  auto watcher = new DownloadPCW(_conn, _servicePath,
201  call, this);
202  Q_UNUSED(watcher);
203 }
204 
205 void
206 DownloadImpl::resume() {
207  Logger::log(Logger::Debug, QString("Download{%1} resume())").arg(_id));
208  QDBusPendingCall call =
209  _dbusInterface->resume();
210  auto watcher = new DownloadPCW(_conn, _servicePath,
211  call, this);
212  Q_UNUSED(watcher);
213 }
214 
215 void
216 DownloadImpl::cancel() {
217  Logger::log(Logger::Debug, QString("Download{%1} cancel())").arg(_id));
218  QDBusPendingCall call =
219  _dbusInterface->cancel();
220  auto watcher = new DownloadPCW(_conn, _servicePath,
221  call, this);
222  Q_UNUSED(watcher);
223 }
224 
225 void
226 DownloadImpl::collected() {
227  Logger::log(Logger::Debug, QString("Download{%1} collected()").arg(_id));
228  QDBusPendingReply<> reply =
229  _dbusInterface->collected();
230  // block, the call should be fast enough
231  reply.waitForFinished();
232  if (reply.isError()) {
233  Logger::log(Logger::Error, "Error when setting download collected");
234  setLastError(reply.error());
235  }
236 }
237 
238 void
239 DownloadImpl::allowMobileDownload(bool allowed) {
240  Logger::log(Logger::Debug,
241  QString("Download{%1} allowMobileDownload%2())").arg(_id).arg(allowed));
242  QDBusPendingReply<> reply =
243  _dbusInterface->allowGSMDownload(allowed);
244  // block, the call should be fast enough
245  reply.waitForFinished();
246  if (reply.isError()) {
247  Logger::log(Logger::Error, "Error when setting mobile data usage");
248  setLastError(reply.error());
249  }
250 }
251 
252 bool
253 DownloadImpl::isMobileDownloadAllowed() {
254  Logger::log(Logger::Debug,
255  QString("Download{%1} isMobileDownloadAllowed").arg(_id));
256  QDBusPendingReply<bool> reply =
257  _dbusInterface->isGSMDownloadAllowed();
258  // block, the call should be fast enough
259  reply.waitForFinished();
260  if (reply.isError()) {
261  Logger::log(Logger::Error, "Error when querying mobile data usage");
262  setLastError(reply.error());
263  return false;
264  } else {
265  auto result = reply.value();
266  return result;
267  }
268 }
269 
270 void
271 DownloadImpl::setDestinationDir(const QString& path) {
272  Logger::log(Logger::Debug, QString("Dowmload{%1} setDestinationDir(%2)")
273  .arg(_id).arg(path));
274  QDBusPendingReply<> reply =
275  _dbusInterface->setDestinationDir(path);
276  // block, the call should be fast enough
277  reply.waitForFinished();
278  if (reply.isError()) {
279  Logger::log(Logger::Error, "Error setting the download directory");
280  setLastError(reply.error());
281  }
282 }
283 
284 void
285 DownloadImpl::setHeaders(QMap<QString, QString> headers) {
286  Logger::log(Logger::Debug,
287  QString("Download {%1} setHeaders(%2)").arg(_id), headers);
288 
289  QDBusPendingReply<> reply =
290  _dbusInterface->setHeaders(headers);
291  // block, the call should be fast enough
292  reply.waitForFinished();
293  if (reply.isError()) {
294  Logger::log(Logger::Error, "Error setting the download headers");
295  setLastError(reply.error());
296  }
297 }
298 
299 QVariantMap
300 DownloadImpl::metadata() {
301  Logger::log(Logger::Debug, QString("Download{%1} metadata()").arg(_id));
302  QDBusPendingReply<QVariantMap> reply =
303  _dbusInterface->metadata();
304  // block the call is fast enough
305  reply.waitForFinished();
306  if (reply.isError()) {
307  Logger::log(Logger::Error, "Error querying the download metadata");
308  QVariantMap emptyResult;
309  setLastError(reply.error());
310  return emptyResult;
311  } else {
312  auto result = reply.value();
313  return result;
314  }
315 }
316 
317 void
318 DownloadImpl::setMetadata(QVariantMap map) {
319  Logger::log(Logger::Debug,
320  QString("Download {%1} setMetadata(%2)").arg(_id), map);
321 
322  QDBusPendingReply<> reply =
323  _dbusInterface->setMetadata(map);
324  // block, the call should be fast enough
325  reply.waitForFinished();
326  if (reply.isError()) {
327  Logger::log(Logger::Error, "Error setting the download metadata");
328  setLastError(reply.error());
329  }
330 }
331 
332 QMap<QString, QString>
333 DownloadImpl::headers() {
334  Logger::log(Logger::Debug, QString("Download{%1} headers()").arg(_id));
335  QDBusPendingReply<QMap<QString, QString> > reply =
336  _dbusInterface->headers();
337  // block, the call should be fast enough
338  reply.waitForFinished();
339  if (reply.isError()) {
340  Logger::log(Logger::Error, "Error querying the download headers");
341  setLastError(reply.error());
342  QMap<QString, QString> empty;
343  return empty;
344  } else {
345  auto result = reply.value();
346  return result;
347  }
348 }
349 
350 
351 void
352 DownloadImpl::setThrottle(qulonglong speed) {
353  Logger::log(Logger::Debug,
354  QString("Download{%1} setThrottle(%2)").arg(_id).arg(speed));
355  QDBusPendingReply<> reply =
356  _dbusInterface->setThrottle(speed);
357  // block, the call should be fast enough
358  reply.waitForFinished();
359  if (reply.isError()) {
360  Logger::log(Logger::Error, "Error setting the download throttle");
361  setLastError(reply.error());
362  }
363 }
364 
365 qulonglong
366 DownloadImpl::throttle() {
367  Logger::log(Logger::Debug, QString("Download{%1} throttle()").arg(_id));
368  QDBusPendingReply<qulonglong> reply =
369  _dbusInterface->throttle();
370  // block, the call is fast enough
371  reply.waitForFinished();
372  if (reply.isError()) {
373  Logger::log(Logger::Error, "Error querying the download throttle");
374  setLastError(reply.error());
375  return 0;
376  } else {
377  auto result = reply.value();
378  return result;
379  }
380 }
381 
382 QString
383 DownloadImpl::filePath() {
384  Logger::log(Logger::Debug, QString("Download{%1} filePath()").arg(_id));
385  QDBusPendingReply<QString> reply =
386  _dbusInterface->filePath();
387  // block, the call is fast enough
388  reply.waitForFinished();
389  if (reply.isError()) {
390  Logger::log(Logger::Error, "Error querying the download file path");
391  setLastError(reply.error());
392  return "";
393  } else {
394  auto result = reply.value();
395  return result;
396  }
397 }
398 
400 DownloadImpl::state() {
401  Logger::log(Logger::Debug, QString("Download{%1} state()").arg(_id));
402  QDBusPendingReply<int> reply =
403  _dbusInterface->state();
404  // block, the call is fast enough
405  reply.waitForFinished();
406  if (reply.isError()) {
407  Logger::log(Logger::Error, "Error querying the download state");
408  setLastError(reply.error());
409  return Download::ERROR;
410  } else {
411  auto result = static_cast<Download::State>(reply.value());
412  return result;
413  }
414 }
415 
416 QString
417 DownloadImpl::id() const {
418  return _id;
419 }
420 
421 qulonglong
422 DownloadImpl::progress() {
423  Logger::log(Logger::Debug, QString("Download{%1} progress()").arg(_id));
424  QDBusPendingReply<qulonglong> reply =
425  _dbusInterface->progress();
426  // block call should be fast enough
427  reply.waitForFinished();
428  if (reply.isError()) {
429  Logger::log(Logger::Error, "Error querying the download progress");
430  setLastError(reply.error());
431  return 0;
432  } else {
433  auto result = reply.value();
434  return result;
435  }
436 }
437 
438 qulonglong
439 DownloadImpl::totalSize() {
440  Logger::log(Logger::Debug, QString("Download{%1} totalSize()").arg(_id));
441  QDBusPendingReply<qulonglong> reply =
442  _dbusInterface->totalSize();
443  // block call should be fast enough
444  reply.waitForFinished();
445  if (reply.isError()) {
446  Logger::log(Logger::Error, "Error querying the download size");
447  setLastError(reply.error());
448  return 0;
449  } else {
450  auto result = reply.value();
451  return result;
452  }
453 }
454 
455 bool
456 DownloadImpl::isError() const {
457  return _isError;
458 }
459 
460 Error*
461 DownloadImpl::error() const {
462  return _lastError;
463 }
464 
465 QString
466 DownloadImpl::clickPackage() const {
467  return _dbusInterface->clickPackage();
468 }
469 
470 bool
471 DownloadImpl::showInIndicator() const {
472  return _dbusInterface->showInIndicator();
473 }
474 
475 QString
476 DownloadImpl::title() const {
477  return _dbusInterface->title();
478 }
479 
480 QString
481 DownloadImpl::destinationApp() const {
482  return _dbusInterface->destinationApp();
483 }
484 
485 void
486 DownloadImpl::onHttpError(HttpErrorStruct errStruct) {
487  auto err = new HttpError(errStruct, this);
488  setLastError(err);
489 }
490 
491 void
492 DownloadImpl::onNetworkError(NetworkErrorStruct errStruct) {
493  auto err = new NetworkError(errStruct, this);
494  setLastError(err);
495 }
496 
497 void
498 DownloadImpl::onProcessError(ProcessErrorStruct errStruct) {
499  auto err = new ProcessError(errStruct, this);
500  setLastError(err);
501 }
502 
503 void
504 DownloadImpl::onAuthError(AuthErrorStruct errStruct) {
505  auto err = new AuthError(errStruct, this);
506  setLastError(err);
507 }
508 
509 void
510 DownloadImpl::onHashError(HashErrorStruct errStruct) {
511  auto err = new HashError(errStruct, this);
512  setLastError(err);
513 }
514 
515 void
516 DownloadImpl::onPropertiesChanged(const QString& interfaceName,
517  const QVariantMap& changedProperties,
518  const QStringList& invalidatedProperties) {
519  Q_UNUSED(invalidatedProperties);
520  // just take care of the property changes from the download interface
521  if (interfaceName == DownloadInterface::staticInterfaceName()) {
522  if (changedProperties.contains(CLICK_PACKAGE_PROPERTY)) {
523  emit clickPackagedChanged();
524  }
525 
526  if (changedProperties.contains(SHOW_INDICATOR_PROPERTY)) {
527  emit showInIndicatorChanged();
528  }
529 
530  if (changedProperties.contains(TITLE_PROPERTY)) {
531  emit titleChanged();
532  }
533  }
534 }
535 
536 void DownloadImpl::onFinished(const QString &path) {
537  Q_UNUSED(path);
538  // Inform UDM that we've received the finished signal, so the download
539  // can be considered completely finished.
540  collected();
541 }
542 
543 } // DownloadManager
544 
545 } // Ubuntu
void finished(const QString &path)
Download(QObject *parent=0)
Definition: download.h:57
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