Ubuntu Download Manager  1.0.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::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(_dbusInterface, &DownloadInterface::hashError,
133  this, &DownloadImpl::onHashError);
134  if (!connected) {
135  Logger::log(Logger::Critical,
136  "Could not connect to signal &DownloadInterface::authError");
137  }
138 
139  connected = connect(_propertiesInterface, &PropertiesInterface::PropertiesChanged,
140  this, &DownloadImpl::onPropertiesChanged);
141  if (!connected) {
142  Logger::log(Logger::Critical,
143  "Could not connect to signal &PropertiesInterface::PropertiesChanged");
144  }
145 }
146 
147 DownloadImpl::DownloadImpl(const QDBusConnection& conn, Error* err, QObject* parent)
148  : Download(parent),
149  _isError(true),
150  _lastError(err),
151  _conn(conn) {
152 }
153 
154 DownloadImpl::~DownloadImpl() {
155  delete _lastError;
156  delete _dbusInterface;
157  delete _propertiesInterface;
158 }
159 
160 void
161 DownloadImpl::setLastError(Error* err) {
162  Logger::log(Logger::Debug,
163  QString("Download{%1} setLastError(%2)").arg(_id).arg(
164  err->errorString()));
165  if (_lastError != nullptr) {
166  delete _lastError;
167  }
168  _lastError = err;
169  _isError = true;
170  emit Download::error(err);
171 }
172 
173 void
174 DownloadImpl::setLastError(const QDBusError& err) {
175  setLastError(new DBusError(err, this));
176 }
177 
178 void
179 DownloadImpl::start() {
180  Logger::log(Logger::Debug, QString("Download{%1} start())").arg(_id));
181  QDBusPendingCall call =
182  _dbusInterface->start();
183  auto watcher = new DownloadPCW(_conn, _servicePath,
184  call, this);
185  Q_UNUSED(watcher);
186 }
187 
188 void
189 DownloadImpl::pause() {
190  Logger::log(Logger::Debug, QString("Download{%1} pause())").arg(_id));
191  QDBusPendingCall call =
192  _dbusInterface->pause();
193  auto watcher = new DownloadPCW(_conn, _servicePath,
194  call, this);
195  Q_UNUSED(watcher);
196 }
197 
198 void
199 DownloadImpl::resume() {
200  Logger::log(Logger::Debug, QString("Download{%1} resume())").arg(_id));
201  QDBusPendingCall call =
202  _dbusInterface->resume();
203  auto watcher = new DownloadPCW(_conn, _servicePath,
204  call, this);
205  Q_UNUSED(watcher);
206 }
207 
208 void
209 DownloadImpl::cancel() {
210  Logger::log(Logger::Debug, QString("Download{%1} cancel())").arg(_id));
211  QDBusPendingCall call =
212  _dbusInterface->cancel();
213  auto watcher = new DownloadPCW(_conn, _servicePath,
214  call, this);
215  Q_UNUSED(watcher);
216 }
217 
218 void
219 DownloadImpl::allowMobileDownload(bool allowed) {
220  Logger::log(Logger::Debug,
221  QString("Download{%1} allowMobileDownload%2())").arg(_id).arg(allowed));
222  QDBusPendingReply<> reply =
223  _dbusInterface->allowGSMDownload(allowed);
224  // block, the call should be fast enough
225  reply.waitForFinished();
226  if (reply.isError()) {
227  Logger::log(Logger::Error, "Error when setting mobile data usage");
228  setLastError(reply.error());
229  }
230 }
231 
232 bool
233 DownloadImpl::isMobileDownloadAllowed() {
234  Logger::log(Logger::Debug,
235  QString("Download{%1} isMobileDownloadAllowed").arg(_id));
236  QDBusPendingReply<bool> reply =
237  _dbusInterface->isGSMDownloadAllowed();
238  // block, the call should be fast enough
239  reply.waitForFinished();
240  if (reply.isError()) {
241  Logger::log(Logger::Error, "Error when querying mobile data usage");
242  setLastError(reply.error());
243  return false;
244  } else {
245  auto result = reply.value();
246  return result;
247  }
248 }
249 
250 void
251 DownloadImpl::setDestinationDir(const QString& path) {
252  Logger::log(Logger::Debug, QString("Dowmload{%1} setDestinationDir(%2)")
253  .arg(_id).arg(path));
254  QDBusPendingReply<> reply =
255  _dbusInterface->setDestinationDir(path);
256  // block, the call should be fast enough
257  reply.waitForFinished();
258  if (reply.isError()) {
259  Logger::log(Logger::Error, "Error setting the download directory");
260  setLastError(reply.error());
261  }
262 }
263 
264 void
265 DownloadImpl::setHeaders(QMap<QString, QString> headers) {
266  Logger::log(Logger::Debug,
267  QString("Download {%1} setHeaders(%2)").arg(_id), headers);
268 
269  QDBusPendingReply<> reply =
270  _dbusInterface->setHeaders(headers);
271  // block, the call should be fast enough
272  reply.waitForFinished();
273  if (reply.isError()) {
274  Logger::log(Logger::Error, "Error setting the download headers");
275  setLastError(reply.error());
276  }
277 }
278 
279 QVariantMap
280 DownloadImpl::metadata() {
281  Logger::log(Logger::Debug, QString("Download{%1} metadata()").arg(_id));
282  QDBusPendingReply<QVariantMap> reply =
283  _dbusInterface->metadata();
284  // block the call is fast enough
285  reply.waitForFinished();
286  if (reply.isError()) {
287  Logger::log(Logger::Error, "Error querying the download metadata");
288  QVariantMap emptyResult;
289  setLastError(reply.error());
290  return emptyResult;
291  } else {
292  auto result = reply.value();
293  return result;
294  }
295 }
296 
297 void
298 DownloadImpl::setMetadata(QVariantMap map) {
299  Logger::log(Logger::Debug,
300  QString("Download {%1} setMetadata(%2)").arg(_id), map);
301 
302  QDBusPendingReply<> reply =
303  _dbusInterface->setMetadata(map);
304  // block, the call should be fast enough
305  reply.waitForFinished();
306  if (reply.isError()) {
307  qDebug() << "Error setting metadata";
308  Logger::log(Logger::Error, "Error setting the download metadata");
309  qDebug() << reply.error();
310  setLastError(reply.error());
311  }
312 }
313 
314 QMap<QString, QString>
315 DownloadImpl::headers() {
316  Logger::log(Logger::Debug, QString("Download{%1} headers()").arg(_id));
317  QDBusPendingReply<QMap<QString, QString> > reply =
318  _dbusInterface->headers();
319  // block, the call should be fast enough
320  reply.waitForFinished();
321  if (reply.isError()) {
322  Logger::log(Logger::Error, "Error querying the download headers");
323  setLastError(reply.error());
324  QMap<QString, QString> empty;
325  return empty;
326  } else {
327  auto result = reply.value();
328  return result;
329  }
330 }
331 
332 
333 void
334 DownloadImpl::setThrottle(qulonglong speed) {
335  Logger::log(Logger::Debug,
336  QString("Download{%1} setThrottle(%2)").arg(_id).arg(speed));
337  QDBusPendingReply<> reply =
338  _dbusInterface->setThrottle(speed);
339  // block, the call should be fast enough
340  reply.waitForFinished();
341  if (reply.isError()) {
342  Logger::log(Logger::Error, "Error setting the download throttle");
343  setLastError(reply.error());
344  }
345 }
346 
347 qulonglong
348 DownloadImpl::throttle() {
349  Logger::log(Logger::Debug, QString("Download{%1} throttle()").arg(_id));
350  QDBusPendingReply<qulonglong> reply =
351  _dbusInterface->throttle();
352  // block, the call is fast enough
353  reply.waitForFinished();
354  if (reply.isError()) {
355  Logger::log(Logger::Error, "Error querying the download throttle");
356  setLastError(reply.error());
357  return 0;
358  } else {
359  auto result = reply.value();
360  return result;
361  }
362 }
363 
364 QString
365 DownloadImpl::id() const {
366  return _id;
367 }
368 
369 qulonglong
370 DownloadImpl::progress() {
371  Logger::log(Logger::Debug, QString("Download{%1} progress()").arg(_id));
372  QDBusPendingReply<qulonglong> reply =
373  _dbusInterface->progress();
374  // block call should be fast enough
375  reply.waitForFinished();
376  if (reply.isError()) {
377  Logger::log(Logger::Error, "Error querying the download progress");
378  setLastError(reply.error());
379  return 0;
380  } else {
381  auto result = reply.value();
382  return result;
383  }
384 }
385 
386 qulonglong
387 DownloadImpl::totalSize() {
388  Logger::log(Logger::Debug, QString("Download{%1} totalSize()").arg(_id));
389  QDBusPendingReply<qulonglong> reply =
390  _dbusInterface->totalSize();
391  // block call should be fast enough
392  reply.waitForFinished();
393  if (reply.isError()) {
394  Logger::log(Logger::Error, "Error querying the download size");
395  setLastError(reply.error());
396  return 0;
397  } else {
398  auto result = reply.value();
399  return result;
400  }
401 }
402 
403 bool
404 DownloadImpl::isError() const {
405  return _isError;
406 }
407 
408 Error*
409 DownloadImpl::error() const {
410  return _lastError;
411 }
412 
413 QString
414 DownloadImpl::clickPackage() const {
415  return _dbusInterface->clickPackage();
416 }
417 
418 bool
419 DownloadImpl::showInIndicator() const {
420  return _dbusInterface->showInIndicator();
421 }
422 
423 QString
424 DownloadImpl::title() const {
425  return _dbusInterface->title();
426 }
427 
428 void
429 DownloadImpl::onHttpError(HttpErrorStruct errStruct) {
430  auto err = new HttpError(errStruct, this);
431  setLastError(err);
432 }
433 
434 void
435 DownloadImpl::onNetworkError(NetworkErrorStruct errStruct) {
436  auto err = new NetworkError(errStruct, this);
437  setLastError(err);
438 }
439 
440 void
441 DownloadImpl::onProcessError(ProcessErrorStruct errStruct) {
442  auto err = new ProcessError(errStruct, this);
443  setLastError(err);
444 }
445 
446 void
447 DownloadImpl::onAuthError(AuthErrorStruct errStruct) {
448  auto err = new AuthError(errStruct, this);
449  setLastError(err);
450 }
451 
452 void
453 DownloadImpl::onHashError(HashErrorStruct errStruct) {
454  auto err = new HashError(errStruct, this);
455  setLastError(err);
456 }
457 
458 void
459 DownloadImpl::onPropertiesChanged(const QString& interfaceName,
460  const QVariantMap& changedProperties,
461  const QStringList& invalidatedProperties) {
462  Q_UNUSED(invalidatedProperties);
463  // just take care of the property changes from the download interface
464  if (interfaceName == DownloadInterface::staticInterfaceName()) {
465  if (changedProperties.contains(CLICK_PACKAGE_PROPERTY)) {
466  emit clickPackagedChanged();
467  }
468 
469  if (changedProperties.contains(SHOW_INDICATOR_PROPERTY)) {
470  emit showInIndicatorChanged();
471  }
472 
473  if (changedProperties.contains(TITLE_PROPERTY)) {
474  emit titleChanged();
475  }
476  }
477 }
478 
479 } // DownloadManager
480 
481 } // 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