diff -r 6aeb7a756187 -r 3c88a81ff781 utilities/downloadmanager/src/downloadbackend.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utilities/downloadmanager/src/downloadbackend.cpp Fri Oct 15 17:30:59 2010 -0400 @@ -0,0 +1,486 @@ +/** + This file is part of CWRT package ** + + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU (Lesser) General Public License as + published by the Free Software Foundation, version 2.1 of the License. + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + (Lesser) General Public License for more details. You should have + received a copy of the GNU (Lesser) General Public License along + with this program. If not, see . +*/ + +#include "clientdownload.h" +#include "downloadmanager.h" +#include "downloadbackend.h" +#include "downloadcore.h" +#include "downloadfactory.h" +#include "downloadstore.h" +#include +#include + +//private implementation +class DownloadBackendPrivate +{ + DM_DECLARE_PUBLIC(DownloadBackend); +public: + DownloadBackendPrivate(); + ~DownloadBackendPrivate(); + + DownloadCore *m_downloadCore; // not owned + ClientDownload *m_download; //// not owned, only reference + DownloadInfo *m_dlInfo; // not owned + qint64 m_totalSize; // total size of the download + qint64 m_currentDownloadedSize; // current downloaded size + qint64 m_lastPausedSize; + DownloadState m_downloadState; // state of the download + bool m_infoDeleted; // flag to indicate the info deletion + QDateTime m_startTime; // download start/resumed time + QDateTime m_endTime; // download completed time + int m_progressCounter; +}; + +DownloadBackendPrivate::DownloadBackendPrivate() +{ + m_downloadCore = 0; + m_download = 0; + m_dlInfo = 0; + m_totalSize = 0; + m_currentDownloadedSize = 0; + m_lastPausedSize =0; + m_infoDeleted = false; + m_progressCounter = 1; +} + +DownloadBackendPrivate::~DownloadBackendPrivate() +{ +#if 0 //m_downloadCore may be stale. + if(m_downloadCore) + { + // cancel if there is any transaction + m_downloadCore->abort(); + } +#endif +} + +DownloadBackend::DownloadBackend(DownloadCore *dlCore, ClientDownload* dl) +{ + DM_INITIALIZE(DownloadBackend); + priv->m_downloadCore = dlCore; + priv->m_download = dl; + priv->m_dlInfo = dl->downloadInfo(); + // connect all the signals from network + connect(dlCore, SIGNAL(downloadProgress(qint64 , qint64 )), this, SLOT(bytesRecieved(qint64 , qint64 ))); + connect(dlCore, SIGNAL(finished()), this, SLOT(handleFinished())); + connect(dlCore, SIGNAL(metaDataChanged()), this, SLOT(headerReceived())); + connect(dlCore, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError))); + connect(dlCore, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(bytesUploaded(qint64, qint64))); + + // save the content type and url + setValue(DownloadInfo::EContentType, priv->m_downloadCore->contentType()); + setValue(DownloadInfo::EUrl, priv->m_downloadCore->url()); + setValue(DownloadInfo::EETag, priv->m_downloadCore->entityTag()); + postEvent(Started, NULL); +} + +DownloadBackend::~DownloadBackend() +{ + DM_UNINITIALIZE(DownloadBackend); +} + +int DownloadBackend::pause() +{ + DM_PRIVATE(DownloadBackend); + setDownloadState(DlPaused); + priv->m_downloadCore->abort(); + return 0; +} + +int DownloadBackend::resume() +{ + DM_PRIVATE(DownloadBackend); + setDownloadState(DlInprogress); + // save the content type and url + setValue(DownloadInfo::EUrl, priv->m_downloadCore->url()); + setValue(DownloadInfo::EContentType, priv->m_downloadCore->contentType()); + priv->m_lastPausedSize = priv->m_currentDownloadedSize; + priv->m_downloadCore->resumeDownload(priv->m_currentDownloadedSize); + priv->m_startTime = QDateTime::currentDateTime(); + postEvent(Progress, NULL); + return 0; +} + +int DownloadBackend::cancel() +{ + DM_PRIVATE(DownloadBackend); + setDownloadState(DlCancelled); + // cancel the transaction + priv->m_downloadCore->abort(); + // delete the temporary storage + deleteStore(); + // reset the states + priv->m_totalSize = 0; + priv->m_currentDownloadedSize = 0; + priv->m_lastPausedSize = 0; + return 0; +} + +QVariant DownloadBackend::getAttribute(DownloadAttribute attr) +{ + DM_PRIVATE(DownloadBackend); + switch(attr) + { + case DlDownloadedSize: + { + return QVariant(priv->m_currentDownloadedSize); + } + case DlTotalSize: + { + return QVariant(priv->m_totalSize); + } + case DlDownloadState: + { + return QVariant(priv->m_downloadState); + } + case DlSourceUrl: + { + return QVariant(priv->m_downloadCore->url()); + } + case DlContentType: + { + return QVariant(priv->m_downloadCore->contentType()); + } + case DlStartTime: + { + return QVariant(priv->m_startTime); + } + case DlEndTime: + { + if (priv->m_downloadState == DlCompleted) + return priv->m_endTime; + else + return QVariant(); + } + case DlElapsedTime: + { + if (priv->m_downloadState == DlCompleted) + return QVariant((priv->m_endTime.toTime_t()-priv->m_startTime.toTime_t())); + + if (priv->m_downloadState != DlInprogress) + return QVariant(); + QDateTime currentTime = QDateTime::currentDateTime(); + uint timeElasped = currentTime.toTime_t() - priv->m_startTime.toTime_t(); + return QVariant(timeElasped); + } + case DlRemainingTime: + { + if (priv->m_downloadState != DlInprogress) + return QVariant(); + QDateTime currentTime = QDateTime::currentDateTime(); + uint timeElasped = currentTime.toTime_t() - priv->m_startTime.toTime_t(); + // total bytes recieved since last start/resume + qint64 totalBytesRecieved = priv->m_currentDownloadedSize - priv->m_lastPausedSize; + qint64 remainingSize = priv->m_totalSize - priv->m_currentDownloadedSize; + if (totalBytesRecieved > 0) + return QVariant((timeElasped*remainingSize)/totalBytesRecieved); + else + return QVariant(); + } + case DlSpeed: + { + if (priv->m_downloadState != DlInprogress) + return QVariant(); + QDateTime currentTime = QDateTime::currentDateTime(); + uint timeElasped = currentTime.toTime_t() - priv->m_startTime.toTime_t(); + qint64 totalBytesRecieved = priv->m_currentDownloadedSize - priv->m_lastPausedSize; + if (timeElasped > 0) + return QVariant(totalBytesRecieved/timeElasped); + else + return QVariant(); + } + case DlPercentage: + { + if (priv->m_totalSize > 0) + return QVariant((priv->m_currentDownloadedSize*100)/priv->m_totalSize); + else + return QVariant(); + } + case DlLastError: + { + return QVariant(priv->m_downloadCore->lastError()); + } + case DlLastErrorString: + { + return QVariant(priv->m_downloadCore->lastErrorString()); + } + default: + { + break; + } + } + return QVariant(); + +} + +int DownloadBackend::setAttribute(DownloadAttribute /*attr*/, const QVariant& /*value*/) +{ + return -1; +} + +void DownloadBackend::bytesRecieved(qint64 bytesRecieved, qint64 bytesTotal) +{ + DM_PRIVATE(DownloadBackend); + if((priv->m_downloadState == DlFailed) || (bytesRecieved == 0)) + { + return; + } + + // in case of resumed downloads, we recieve total size remained to download + setTotalSize(priv->m_lastPausedSize + bytesTotal); + priv->m_currentDownloadedSize = priv->m_lastPausedSize + bytesRecieved; + setDownloadState(DlInprogress); + // store the recieved chunk + store(priv->m_downloadCore->reply()->readAll(), false); + postEvent(Progress, NULL); +} + +void DownloadBackend::handleFinished() +{ + DM_PRIVATE(DownloadBackend); + + DownloadState state = priv->m_downloadState; + if( state == DlFailed ) + { + postEvent(Failed, NULL); + return; + } + if( state == DlPaused ) + { + postEvent(Paused, NULL); + return; + } + if( state == DlCancelled ) + { + postEvent(Cancelled, NULL); + return; + } + if(priv->m_currentDownloadedSize < priv->m_totalSize) + { + // all packets are not recieved, so it is not last chunk + // should be some network problem + store(priv->m_downloadCore->reply()->readAll(), false); + postEvent(NetworkLoss, NULL); + } + else + { + //finish is successful + store(priv->m_downloadCore->reply()->readAll(), true); + //finish is successful + setDownloadState(DlCompleted); + priv->m_endTime = QDateTime::currentDateTime(); + postEvent(Completed, NULL); + } +} + +void DownloadBackend::error(QNetworkReply::NetworkError code) +{ + DM_PRIVATE(DownloadBackend); + if((code == QNetworkReply::OperationCanceledError) && (priv->m_downloadState == DlCancelled)) + { + return; + } + if(code == QNetworkReply::OperationCanceledError) + { + // this means user has paused the download + setDownloadState(DlPaused); + } + else if(code != QNetworkReply::NoError) + { + priv->m_downloadCore->setLastError(code); + if(priv->m_downloadCore->reply()) + { + priv->m_downloadCore->setLastErrorString(priv->m_downloadCore->reply()->errorString()); + } + setDownloadState(DlFailed); + postEvent(Error, NULL); + } +} + +void DownloadBackend::postEvent(DEventType type, DlEventAttributeMap* attrMap) +{ + DM_PRIVATE(DownloadBackend); + // The client if it doesn't want progress events then it can set the DownloadMgrProgress mode as quiet + // If it wants progress events at regular intervals then it has to specify the KiloBytes at which it requires the progress event. + // By default, the DownloadMgrProgress Mode is non-quiet with progress events being sent at every 5KB downloaded. + DownloadMgrProgressMode mode = (DownloadMgrProgressMode)(priv->m_download->downloadManager()->getAttribute(DlMgrProgressMode)).toInt(); + if ((mode == Quiet) && (type == Progress)) + return; + + qlonglong kBytes = priv->m_download->getAttribute(DlProgressInterval).toLongLong() * 1024; + if (mode == NonQuiet && type == Progress) + { + if ((priv->m_currentDownloadedSize/(kBytes * priv->m_progressCounter)) > 0) + { + priv->m_progressCounter++; + postDownloadEvent(type, attrMap); + } + } + else + postDownloadEvent(type, attrMap); +} + +DownloadState DownloadBackend::downloadState(void) +{ + DM_PRIVATE(DownloadBackend); + return priv->m_downloadState; +} + +void DownloadBackend::setDownloadState(DownloadState state) +{ + DM_PRIVATE(DownloadBackend); + priv->m_downloadState = state; + // save the download state + setValue(DownloadInfo::EDlState, priv->m_downloadState); + if((state == DlFailed) || (state == DlCompleted) || (state == DlCancelled)) + { + // remove dl info + deleteInfo(); + } +} + +void DownloadBackend::setDownloadedDataSize(qint64 size) +{ + DM_PRIVATE(DownloadBackend); + priv->m_currentDownloadedSize = size; + return; +} + +void DownloadBackend::setTotalSize(qint64 size) +{ + DM_PRIVATE(DownloadBackend); + priv->m_totalSize = size; + setValue(DownloadInfo::ETotalSize, priv->m_totalSize); + return; +} + +void DownloadBackend::setStartTime() +{ + DM_PRIVATE(DownloadBackend); + priv->m_startTime = QDateTime::currentDateTime(); +} + +ClientDownload* DownloadBackend::download(void) +{ + DM_PRIVATE(DownloadBackend); + return priv->m_download; +} + +/* Helper functions to access download info */ + +int DownloadBackend::setValue(DownloadInfo::Key aKey, const QString& aStrValue) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->setValue(priv->m_download->id(), aKey, aStrValue, priv->m_download->parentId()); +} + +int DownloadBackend::setValueForChild(DownloadInfo::Key aKey, const QString& aStrValue, int aChildId) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->setValueForChild(priv->m_download->id(), aKey, aStrValue, aChildId); +} + +int DownloadBackend::setValue(DownloadInfo::Key aKey, long aIntValue) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->setValue(priv->m_download->id(), aKey, aIntValue, priv->m_download->parentId()); +} + +int DownloadBackend::setValueForChild(DownloadInfo::Key aKey, long aIntValue, int aChildId) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->setValueForChild(priv->m_download->id(), aKey, aIntValue, aChildId); +} + +int DownloadBackend::setValue(DownloadInfo::Key aKey, const QList& aChildIds) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->setValue(priv->m_download->id(), aKey, aChildIds); +} + +int DownloadBackend::getValue(DownloadInfo::Key aKey, QString& aStrValue) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->getValue(priv->m_download->id(), aKey, aStrValue, priv->m_download->parentId()); +} + +int DownloadBackend::getValueForChild(DownloadInfo::Key aKey, QString& aStrValue, int aChildId) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->getValueForChild(priv->m_download->id(), aKey, aStrValue, aChildId); +} + +int DownloadBackend::getValue(DownloadInfo::Key aKey, long& aIntValue) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->getValue(priv->m_download->id(), aKey, aIntValue, priv->m_download->parentId()); +} + +int DownloadBackend::getValueForChild(DownloadInfo::Key aKey, long& aIntValue, int aChildId) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->getValueForChild(priv->m_download->id(), aKey, aIntValue, aChildId); + +} + +int DownloadBackend::getValue(DownloadInfo::Key aKey, QList& aChildIds) +{ + DM_PRIVATE(DownloadBackend); + if(priv->m_infoDeleted) + return 0; + return priv->m_dlInfo->getValue(priv->m_download->id(), aKey, aChildIds); +} + +int DownloadBackend::deleteInfo() +{ + DM_PRIVATE(DownloadBackend); + if ((InActive == priv->m_download->downloadManager()->getAttribute(DlMgrPersistantMode)) + && (DlCompleted == priv->m_downloadState)) + return 0; + priv->m_infoDeleted = true; + return priv->m_dlInfo->remove(priv->m_download->id(), priv->m_download->parentId()); +} +void DownloadBackend::postDownloadEvent(DEventType type, DlEventAttributeMap* attrMap) +{ + DM_PRIVATE(DownloadBackend); + EventReceiverList list = priv->m_download->eventReceivers(); + for(int i=0; im_download->id()); + QCoreApplication::postEvent(list[i], event); + } + } +}