utilities/downloadmanager/src/downloadbackend.cpp
changeset 16 3c88a81ff781
equal deleted inserted replaced
14:6aeb7a756187 16:3c88a81ff781
       
     1 /**
       
     2    This file is part of CWRT package **
       
     3 
       
     4    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). **
       
     5 
       
     6    This program is free software: you can redistribute it and/or modify
       
     7    it under the terms of the GNU (Lesser) General Public License as 
       
     8    published by the Free Software Foundation, version 2.1 of the License. 
       
     9    This program is distributed in the hope that it will be useful, but
       
    10    WITHOUT ANY WARRANTY; without even the implied warranty of 
       
    11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
       
    12    (Lesser) General Public License for more details. You should have 
       
    13    received a copy of the GNU (Lesser) General Public License along 
       
    14    with this program. If not, see <http://www.gnu.org/licenses/>.
       
    15 */
       
    16 
       
    17 #include "clientdownload.h"
       
    18 #include "downloadmanager.h"
       
    19 #include "downloadbackend.h"
       
    20 #include "downloadcore.h"
       
    21 #include "downloadfactory.h"
       
    22 #include "downloadstore.h"
       
    23 #include <QCoreApplication>
       
    24 #include <QDateTime>
       
    25 
       
    26 //private implementation
       
    27 class DownloadBackendPrivate
       
    28 {
       
    29     DM_DECLARE_PUBLIC(DownloadBackend);
       
    30 public:
       
    31     DownloadBackendPrivate();
       
    32     ~DownloadBackendPrivate();
       
    33 
       
    34     DownloadCore *m_downloadCore; // not owned
       
    35     ClientDownload *m_download; //// not owned, only reference 
       
    36     DownloadInfo *m_dlInfo; // not owned
       
    37     qint64 m_totalSize; // total size of the download
       
    38     qint64 m_currentDownloadedSize; // current downloaded size
       
    39     qint64 m_lastPausedSize;
       
    40     DownloadState m_downloadState; // state of the download
       
    41     bool m_infoDeleted; // flag to indicate the info deletion    
       
    42     QDateTime m_startTime; // download start/resumed time
       
    43     QDateTime m_endTime; // download completed time
       
    44     int m_progressCounter;
       
    45 };  
       
    46 
       
    47 DownloadBackendPrivate::DownloadBackendPrivate()
       
    48 {
       
    49     m_downloadCore = 0;
       
    50     m_download = 0;
       
    51     m_dlInfo = 0;
       
    52     m_totalSize = 0;
       
    53     m_currentDownloadedSize = 0;
       
    54     m_lastPausedSize =0;
       
    55     m_infoDeleted = false;
       
    56     m_progressCounter = 1;
       
    57 }
       
    58 
       
    59 DownloadBackendPrivate::~DownloadBackendPrivate()
       
    60 {
       
    61 #if 0 //m_downloadCore may be stale.
       
    62     if(m_downloadCore)
       
    63     {     
       
    64         // cancel if there is any transaction
       
    65         m_downloadCore->abort();
       
    66     }
       
    67 #endif
       
    68 }
       
    69 
       
    70 DownloadBackend::DownloadBackend(DownloadCore *dlCore, ClientDownload* dl)
       
    71 {
       
    72     DM_INITIALIZE(DownloadBackend);
       
    73     priv->m_downloadCore = dlCore;
       
    74     priv->m_download = dl;
       
    75     priv->m_dlInfo = dl->downloadInfo();
       
    76     // connect all the signals from network
       
    77     connect(dlCore, SIGNAL(downloadProgress(qint64 , qint64 )), this, SLOT(bytesRecieved(qint64 , qint64 )));
       
    78     connect(dlCore, SIGNAL(finished()), this, SLOT(handleFinished()));
       
    79     connect(dlCore, SIGNAL(metaDataChanged()), this, SLOT(headerReceived()));
       
    80     connect(dlCore, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
       
    81     connect(dlCore, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(bytesUploaded(qint64, qint64)));
       
    82 
       
    83     // save the content type and url
       
    84     setValue(DownloadInfo::EContentType, priv->m_downloadCore->contentType()); 
       
    85     setValue(DownloadInfo::EUrl, priv->m_downloadCore->url()); 
       
    86     setValue(DownloadInfo::EETag, priv->m_downloadCore->entityTag());
       
    87     postEvent(Started, NULL);
       
    88 }
       
    89 
       
    90 DownloadBackend::~DownloadBackend()
       
    91 {
       
    92     DM_UNINITIALIZE(DownloadBackend);
       
    93 }
       
    94 
       
    95 int DownloadBackend::pause()
       
    96 {
       
    97     DM_PRIVATE(DownloadBackend);
       
    98     setDownloadState(DlPaused);
       
    99     priv->m_downloadCore->abort();
       
   100     return 0;
       
   101 }
       
   102 
       
   103 int DownloadBackend::resume()
       
   104 {
       
   105     DM_PRIVATE(DownloadBackend);
       
   106     setDownloadState(DlInprogress);
       
   107     // save the content type and url
       
   108     setValue(DownloadInfo::EUrl, priv->m_downloadCore->url());
       
   109     setValue(DownloadInfo::EContentType, priv->m_downloadCore->contentType());
       
   110     priv->m_lastPausedSize = priv->m_currentDownloadedSize;
       
   111     priv->m_downloadCore->resumeDownload(priv->m_currentDownloadedSize);
       
   112     priv->m_startTime = QDateTime::currentDateTime();
       
   113     postEvent(Progress, NULL);
       
   114     return 0;
       
   115 }
       
   116 
       
   117 int DownloadBackend::cancel()
       
   118 {
       
   119     DM_PRIVATE(DownloadBackend);   
       
   120     setDownloadState(DlCancelled);
       
   121     // cancel the transaction
       
   122     priv->m_downloadCore->abort();
       
   123     // delete the temporary storage
       
   124     deleteStore();
       
   125     // reset the states
       
   126     priv->m_totalSize = 0;
       
   127     priv->m_currentDownloadedSize = 0;
       
   128     priv->m_lastPausedSize = 0;
       
   129     return 0;
       
   130 }
       
   131 
       
   132 QVariant DownloadBackend::getAttribute(DownloadAttribute attr)
       
   133 {
       
   134     DM_PRIVATE(DownloadBackend); 
       
   135     switch(attr)
       
   136     {
       
   137          case DlDownloadedSize:
       
   138          {
       
   139              return QVariant(priv->m_currentDownloadedSize);
       
   140          }
       
   141          case DlTotalSize:
       
   142          {
       
   143              return QVariant(priv->m_totalSize);
       
   144          }
       
   145          case DlDownloadState:
       
   146          {
       
   147              return QVariant(priv->m_downloadState);
       
   148          }
       
   149          case DlSourceUrl:
       
   150          {
       
   151              return QVariant(priv->m_downloadCore->url());
       
   152          }
       
   153          case DlContentType:
       
   154          {
       
   155              return QVariant(priv->m_downloadCore->contentType());
       
   156          }
       
   157          case DlStartTime:
       
   158          {
       
   159              return QVariant(priv->m_startTime);
       
   160          }
       
   161          case DlEndTime:
       
   162          {
       
   163              if (priv->m_downloadState == DlCompleted)
       
   164                  return priv->m_endTime;
       
   165              else 
       
   166                  return QVariant();
       
   167          }
       
   168          case DlElapsedTime:
       
   169          {
       
   170              if (priv->m_downloadState == DlCompleted)
       
   171                  return QVariant((priv->m_endTime.toTime_t()-priv->m_startTime.toTime_t()));
       
   172 
       
   173              if (priv->m_downloadState != DlInprogress)
       
   174                  return QVariant();
       
   175              QDateTime currentTime = QDateTime::currentDateTime();
       
   176              uint timeElasped = currentTime.toTime_t() - priv->m_startTime.toTime_t();
       
   177              return QVariant(timeElasped);
       
   178          }
       
   179          case DlRemainingTime:
       
   180          {
       
   181              if (priv->m_downloadState != DlInprogress)
       
   182                  return QVariant();
       
   183              QDateTime currentTime = QDateTime::currentDateTime();
       
   184              uint timeElasped = currentTime.toTime_t() - priv->m_startTime.toTime_t();
       
   185              // total bytes recieved since last start/resume
       
   186              qint64 totalBytesRecieved = priv->m_currentDownloadedSize - priv->m_lastPausedSize;
       
   187              qint64 remainingSize = priv->m_totalSize - priv->m_currentDownloadedSize;
       
   188              if (totalBytesRecieved > 0)
       
   189                  return QVariant((timeElasped*remainingSize)/totalBytesRecieved);
       
   190              else
       
   191                  return QVariant();
       
   192          }
       
   193          case DlSpeed:
       
   194          {
       
   195              if (priv->m_downloadState != DlInprogress)
       
   196                  return QVariant();
       
   197              QDateTime currentTime = QDateTime::currentDateTime();
       
   198              uint timeElasped = currentTime.toTime_t() - priv->m_startTime.toTime_t();
       
   199              qint64 totalBytesRecieved = priv->m_currentDownloadedSize - priv->m_lastPausedSize;
       
   200              if (timeElasped > 0)
       
   201                  return QVariant(totalBytesRecieved/timeElasped);
       
   202              else
       
   203                  return QVariant();
       
   204          }
       
   205          case DlPercentage:
       
   206          {
       
   207              if (priv->m_totalSize > 0)
       
   208                  return QVariant((priv->m_currentDownloadedSize*100)/priv->m_totalSize);
       
   209              else
       
   210                  return QVariant();
       
   211          }
       
   212          case DlLastError:
       
   213          {
       
   214              return QVariant(priv->m_downloadCore->lastError());
       
   215          }
       
   216          case DlLastErrorString:
       
   217          {
       
   218              return QVariant(priv->m_downloadCore->lastErrorString());
       
   219          }
       
   220          default:
       
   221          {
       
   222              break;
       
   223          }
       
   224      }
       
   225     return QVariant();
       
   226      
       
   227 }
       
   228 
       
   229 int DownloadBackend::setAttribute(DownloadAttribute /*attr*/, const QVariant& /*value*/)
       
   230 {
       
   231     return -1;
       
   232 }
       
   233 
       
   234 void DownloadBackend::bytesRecieved(qint64 bytesRecieved, qint64 bytesTotal)
       
   235 {
       
   236     DM_PRIVATE(DownloadBackend);
       
   237     if((priv->m_downloadState == DlFailed) || (bytesRecieved == 0))
       
   238     {
       
   239         return;
       
   240     }
       
   241  
       
   242     // in case of resumed downloads, we recieve total size remained to download
       
   243     setTotalSize(priv->m_lastPausedSize + bytesTotal);
       
   244     priv->m_currentDownloadedSize = priv->m_lastPausedSize + bytesRecieved;
       
   245     setDownloadState(DlInprogress);
       
   246     // store the recieved chunk
       
   247     store(priv->m_downloadCore->reply()->readAll(), false); 
       
   248     postEvent(Progress, NULL);
       
   249 }
       
   250 
       
   251 void DownloadBackend::handleFinished()
       
   252 {
       
   253     DM_PRIVATE(DownloadBackend);
       
   254 
       
   255     DownloadState state = priv->m_downloadState;
       
   256     if( state == DlFailed )
       
   257     {
       
   258         postEvent(Failed, NULL);  
       
   259         return;
       
   260     }
       
   261     if( state == DlPaused )
       
   262     {
       
   263         postEvent(Paused, NULL);  
       
   264         return;
       
   265     }
       
   266     if( state == DlCancelled )
       
   267     {
       
   268         postEvent(Cancelled, NULL);  
       
   269         return;
       
   270     }
       
   271     if(priv->m_currentDownloadedSize < priv->m_totalSize)
       
   272     {
       
   273         // all packets are not recieved, so it is not last chunk 
       
   274         // should be some network problem
       
   275         store(priv->m_downloadCore->reply()->readAll(), false); 
       
   276         postEvent(NetworkLoss, NULL);
       
   277     }
       
   278     else
       
   279     {
       
   280         //finish is successful
       
   281         store(priv->m_downloadCore->reply()->readAll(), true);
       
   282         //finish is successful
       
   283         setDownloadState(DlCompleted);
       
   284         priv->m_endTime = QDateTime::currentDateTime();
       
   285         postEvent(Completed, NULL);
       
   286     } 
       
   287 }
       
   288 
       
   289 void DownloadBackend::error(QNetworkReply::NetworkError code)
       
   290 {
       
   291     DM_PRIVATE(DownloadBackend);
       
   292     if((code == QNetworkReply::OperationCanceledError) && (priv->m_downloadState == DlCancelled))
       
   293     { 
       
   294         return;
       
   295     }   
       
   296     if(code == QNetworkReply::OperationCanceledError) 
       
   297     {
       
   298         // this means user has paused the download
       
   299         setDownloadState(DlPaused);
       
   300     }   
       
   301     else if(code != QNetworkReply::NoError)
       
   302     {
       
   303         priv->m_downloadCore->setLastError(code);
       
   304         if(priv->m_downloadCore->reply())
       
   305         {
       
   306             priv->m_downloadCore->setLastErrorString(priv->m_downloadCore->reply()->errorString());
       
   307         }
       
   308         setDownloadState(DlFailed);
       
   309         postEvent(Error, NULL);
       
   310     }
       
   311 }
       
   312 
       
   313 void DownloadBackend::postEvent(DEventType type, DlEventAttributeMap* attrMap)
       
   314 {
       
   315     DM_PRIVATE(DownloadBackend);
       
   316     // The client if it doesn't want progress events then it can set the DownloadMgrProgress mode as quiet
       
   317     // If it wants progress events at regular intervals then it has to specify the KiloBytes at which it requires the progress event.
       
   318     // By default, the DownloadMgrProgress Mode is non-quiet with progress events being sent at every 5KB downloaded. 
       
   319     DownloadMgrProgressMode mode = (DownloadMgrProgressMode)(priv->m_download->downloadManager()->getAttribute(DlMgrProgressMode)).toInt();
       
   320     if ((mode == Quiet) && (type == Progress))
       
   321         return;
       
   322 
       
   323     qlonglong kBytes = priv->m_download->getAttribute(DlProgressInterval).toLongLong() * 1024;
       
   324     if (mode == NonQuiet && type == Progress)
       
   325     {
       
   326         if ((priv->m_currentDownloadedSize/(kBytes * priv->m_progressCounter)) > 0)
       
   327         {
       
   328             priv->m_progressCounter++;
       
   329             postDownloadEvent(type, attrMap);
       
   330         }
       
   331     }
       
   332     else
       
   333         postDownloadEvent(type, attrMap);
       
   334 }
       
   335 
       
   336 DownloadState DownloadBackend::downloadState(void)
       
   337 {
       
   338     DM_PRIVATE(DownloadBackend);
       
   339     return priv->m_downloadState;
       
   340 }
       
   341 
       
   342 void DownloadBackend::setDownloadState(DownloadState state)
       
   343 {
       
   344     DM_PRIVATE(DownloadBackend);
       
   345     priv->m_downloadState = state;
       
   346     // save the download state
       
   347     setValue(DownloadInfo::EDlState, priv->m_downloadState);
       
   348     if((state == DlFailed) || (state == DlCompleted) || (state == DlCancelled))
       
   349     {
       
   350         // remove dl info
       
   351             deleteInfo();
       
   352     }
       
   353 }
       
   354 
       
   355 void DownloadBackend::setDownloadedDataSize(qint64 size)
       
   356 {
       
   357     DM_PRIVATE(DownloadBackend);
       
   358     priv->m_currentDownloadedSize = size;
       
   359     return;
       
   360 }
       
   361 
       
   362 void DownloadBackend::setTotalSize(qint64 size)
       
   363 {
       
   364     DM_PRIVATE(DownloadBackend);
       
   365     priv->m_totalSize = size;
       
   366     setValue(DownloadInfo::ETotalSize, priv->m_totalSize);
       
   367     return;
       
   368 }
       
   369 
       
   370 void DownloadBackend::setStartTime()
       
   371 {
       
   372     DM_PRIVATE(DownloadBackend);
       
   373     priv->m_startTime = QDateTime::currentDateTime();
       
   374 }
       
   375 
       
   376 ClientDownload* DownloadBackend::download(void)
       
   377 {
       
   378     DM_PRIVATE(DownloadBackend);
       
   379     return priv->m_download;
       
   380 }
       
   381 
       
   382 /* Helper functions to access download info */
       
   383 
       
   384 int DownloadBackend::setValue(DownloadInfo::Key aKey, const QString& aStrValue)
       
   385 {
       
   386     DM_PRIVATE(DownloadBackend);
       
   387     if(priv->m_infoDeleted)
       
   388         return 0;
       
   389     return priv->m_dlInfo->setValue(priv->m_download->id(), aKey, aStrValue, priv->m_download->parentId());
       
   390 }
       
   391 
       
   392 int DownloadBackend::setValueForChild(DownloadInfo::Key aKey, const QString& aStrValue, int aChildId)
       
   393 {
       
   394     DM_PRIVATE(DownloadBackend);
       
   395     if(priv->m_infoDeleted)
       
   396         return 0;
       
   397     return priv->m_dlInfo->setValueForChild(priv->m_download->id(), aKey, aStrValue, aChildId);
       
   398 }
       
   399 
       
   400 int DownloadBackend::setValue(DownloadInfo::Key aKey, long aIntValue)
       
   401 {
       
   402     DM_PRIVATE(DownloadBackend);
       
   403     if(priv->m_infoDeleted)
       
   404         return 0;
       
   405     return priv->m_dlInfo->setValue(priv->m_download->id(), aKey, aIntValue, priv->m_download->parentId());
       
   406 }
       
   407 
       
   408 int DownloadBackend::setValueForChild(DownloadInfo::Key aKey, long aIntValue, int aChildId)
       
   409 {
       
   410     DM_PRIVATE(DownloadBackend);
       
   411     if(priv->m_infoDeleted)
       
   412         return 0;
       
   413     return priv->m_dlInfo->setValueForChild(priv->m_download->id(), aKey, aIntValue, aChildId);
       
   414 }
       
   415 
       
   416 int DownloadBackend::setValue(DownloadInfo::Key aKey, const QList<QVariant>& aChildIds)
       
   417 {
       
   418     DM_PRIVATE(DownloadBackend);
       
   419     if(priv->m_infoDeleted)
       
   420         return 0;
       
   421     return priv->m_dlInfo->setValue(priv->m_download->id(), aKey, aChildIds);
       
   422 }
       
   423 
       
   424 int DownloadBackend::getValue(DownloadInfo::Key aKey, QString& aStrValue)
       
   425 {
       
   426     DM_PRIVATE(DownloadBackend);
       
   427     if(priv->m_infoDeleted)
       
   428         return 0;
       
   429     return priv->m_dlInfo->getValue(priv->m_download->id(), aKey, aStrValue, priv->m_download->parentId());
       
   430 }
       
   431 
       
   432 int DownloadBackend::getValueForChild(DownloadInfo::Key aKey, QString& aStrValue, int aChildId)
       
   433 {
       
   434     DM_PRIVATE(DownloadBackend);
       
   435     if(priv->m_infoDeleted)
       
   436         return 0;
       
   437     return priv->m_dlInfo->getValueForChild(priv->m_download->id(), aKey, aStrValue, aChildId);
       
   438 }
       
   439 
       
   440 int DownloadBackend::getValue(DownloadInfo::Key aKey, long& aIntValue)
       
   441 {
       
   442     DM_PRIVATE(DownloadBackend);
       
   443     if(priv->m_infoDeleted)
       
   444         return 0;
       
   445     return priv->m_dlInfo->getValue(priv->m_download->id(), aKey, aIntValue, priv->m_download->parentId());
       
   446 }
       
   447 
       
   448 int DownloadBackend::getValueForChild(DownloadInfo::Key aKey, long& aIntValue, int aChildId)
       
   449 {
       
   450     DM_PRIVATE(DownloadBackend);
       
   451     if(priv->m_infoDeleted)
       
   452         return 0;
       
   453     return priv->m_dlInfo->getValueForChild(priv->m_download->id(), aKey, aIntValue, aChildId);
       
   454  
       
   455 }
       
   456 
       
   457 int DownloadBackend::getValue(DownloadInfo::Key aKey, QList<QVariant>& aChildIds)
       
   458 {
       
   459     DM_PRIVATE(DownloadBackend);
       
   460     if(priv->m_infoDeleted)
       
   461         return 0;
       
   462     return priv->m_dlInfo->getValue(priv->m_download->id(), aKey, aChildIds);
       
   463 }
       
   464 
       
   465 int DownloadBackend::deleteInfo()
       
   466 {
       
   467     DM_PRIVATE(DownloadBackend);
       
   468     if ((InActive == priv->m_download->downloadManager()->getAttribute(DlMgrPersistantMode))
       
   469         && (DlCompleted == priv->m_downloadState))
       
   470         return 0;
       
   471     priv->m_infoDeleted = true;
       
   472     return priv->m_dlInfo->remove(priv->m_download->id(), priv->m_download->parentId()); 
       
   473 }
       
   474 void DownloadBackend::postDownloadEvent(DEventType type, DlEventAttributeMap* attrMap)
       
   475 {
       
   476     DM_PRIVATE(DownloadBackend);
       
   477     EventReceiverList list = priv->m_download->eventReceivers();
       
   478     for(int i=0; i<list.size(); i++)
       
   479     {
       
   480         if(list[i])
       
   481         {
       
   482             DownloadEvent *event = new DownloadEvent(type, attrMap, priv->m_download->id());
       
   483             QCoreApplication::postEvent(list[i], event);
       
   484         }
       
   485     }
       
   486 }