utilities/downloadmanager/src/oma2downloadbackend.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 "oma2downloadbackend.h"
       
    18 #include "omaddparser.h"
       
    19 #include "downloadmanager.h"
       
    20 #include "download.h"
       
    21 #include "clientdownload.h"
       
    22 #include "downloadcore.h"
       
    23 #include "downloadevent.h"
       
    24 #include <QCoreApplication>
       
    25 #include <QFileInfo>
       
    26 
       
    27 #ifdef Q_OS_LINUX
       
    28   #include <sys/statvfs.h>
       
    29 #endif
       
    30 
       
    31 #ifdef Q_OS_LINUX 
       
    32 static double freeSpace(const char *path)
       
    33 #else
       
    34 static double freeSpace(const char* /*path*/)
       
    35 #endif
       
    36 {
       
    37 #ifdef Q_OS_LINUX   
       
    38     struct statvfs fiData;
       
    39     if ((statvfs(path,&fiData)) < 0 ) 
       
    40         return 0;
       
    41     else {
       
    42         qint64 blockSize = fiData.f_bsize/1024;
       
    43         qint64 freeSize = (fiData.f_bavail)*blockSize;
       
    44         freeSize = freeSize/1024;
       
    45         return freeSize;
       
    46     }
       
    47 #endif
       
    48     return 0;
       
    49 }
       
    50 
       
    51 // Constants
       
    52 const char* const SuppressUserConfirmation_Never = "Never";
       
    53 
       
    54 // private implementation
       
    55 class OMA2DownloadBackendPrivate {
       
    56     DM_DECLARE_PUBLIC(OMA2DownloadBackend);
       
    57 public:
       
    58     OMA2DownloadBackendPrivate();
       
    59     ~OMA2DownloadBackendPrivate();
       
    60     DownloadCore *m_downloadCore;
       
    61     ClientDownload *m_download;
       
    62     OMADownloadDescParser *m_parser; // for parsing oma descriptor
       
    63     OMADownloadDescriptor *m_downloadDesc;
       
    64     bool m_isMediaDownload; // flag to indicate if media download is happening  
       
    65     MediaDownloadList m_mediaDownloadList; // media downloads
       
    66     int m_currDownloadIndex;
       
    67     int m_currProductIndex;
       
    68     qint64 m_dlCompletedSize;
       
    69     QMap<int, int> m_mediaObjIdStateMap; // map to have the list of Media Objects' id and it's state.
       
    70     QList<QVariant> m_childIds;
       
    71     OMA2DownloadProduct *m_currProduct;
       
    72     OMA2DownloadMediaObj *m_currMediaObj;
       
    73 };
       
    74 
       
    75 OMA2DownloadBackendPrivate::OMA2DownloadBackendPrivate():m_downloadCore(0)
       
    76                                                         ,m_download(0)
       
    77                                                         ,m_parser(0)
       
    78                                                         ,m_downloadDesc(0)
       
    79                                                         ,m_isMediaDownload(false)
       
    80                                                         ,m_currDownloadIndex(-1)
       
    81                                                         ,m_currProductIndex(0)
       
    82                                                         ,m_dlCompletedSize(0)
       
    83 { }
       
    84 
       
    85 OMA2DownloadBackendPrivate::~OMA2DownloadBackendPrivate()
       
    86 {
       
    87     if (m_parser) {
       
    88         delete m_parser;
       
    89         m_parser = 0;
       
    90         m_downloadDesc = 0;
       
    91     }
       
    92     // In case of persistent storage
       
    93     if (m_downloadDesc) {
       
    94         delete m_downloadDesc;
       
    95         m_downloadDesc = 0;
       
    96     }
       
    97     
       
    98     int count = m_mediaDownloadList.count();
       
    99     for (int i = 0; i < count; i++)
       
   100         delete m_mediaDownloadList[i];
       
   101 }
       
   102 
       
   103 OMA2DownloadBackend::OMA2DownloadBackend(DownloadCore *dlCore, ClientDownload *dl)
       
   104     :DownloadBackend(dlCore, dl)
       
   105 {
       
   106     DM_INITIALIZE(OMA2DownloadBackend);
       
   107     priv->m_downloadCore = dlCore;
       
   108     priv->m_download = dl;
       
   109 }
       
   110 
       
   111 OMA2DownloadBackend::~OMA2DownloadBackend()
       
   112 {
       
   113     DM_UNINITIALIZE(OMA2DownloadBackend);
       
   114 }
       
   115 
       
   116 int OMA2DownloadBackend::pause()
       
   117 {
       
   118     DM_PRIVATE(OMA2DownloadBackend);
       
   119     if (priv->m_isMediaDownload) {
       
   120         priv->m_mediaDownloadList[priv->m_currDownloadIndex]->pause();
       
   121         setDownloadState(DlPaused);
       
   122     }
       
   123     return 0;
       
   124 }
       
   125 
       
   126 int OMA2DownloadBackend::resume()
       
   127 {
       
   128     DM_PRIVATE(OMA2DownloadBackend);
       
   129     if (priv->m_isMediaDownload)
       
   130         return (priv->m_mediaDownloadList[priv->m_currDownloadIndex]->resume());
       
   131 
       
   132     // Ready to download after the descriptor is parsed
       
   133     // capability check on the descriptor information
       
   134     if (checkDownloadDescriptor()) {
       
   135         ProductList product = priv->m_downloadDesc->productList();
       
   136         int count =  product[priv->m_currProductIndex]->mediaCount();
       
   137         
       
   138         for (int i=0; i < count; i++) {
       
   139             QUrl baseUrl = priv->m_downloadCore->url();
       
   140             QUrl relativeUrl = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjServer).toString();
       
   141             QString url = baseUrl.resolved(relativeUrl).toString();
       
   142             // create download for media object
       
   143             // id's of media downloads are unique under its parent oma download
       
   144             ClientDownload *dl = new ClientDownload(priv->m_download->downloadManager(), url, (i+1), Parallel
       
   145                                                                                             , priv->m_download->id() );
       
   146             if (NULL == dl)
       
   147                 return -1;
       
   148             // functions for persistent storage
       
   149             serializeData(dl, i);
       
   150             setValueForChild(DownloadInfo::EUrl, url, dl->id());
       
   151             setValueForChild(DownloadInfo::EDlState, DlCreated, dl->id());
       
   152             long state;
       
   153             getValue(DownloadInfo::EDlState, state);
       
   154             priv->m_mediaObjIdStateMap[dl->id()] = state;
       
   155             addtoDownloadList(dl);
       
   156         }
       
   157         setValue(DownloadInfo::EChildIdList, priv->m_childIds);
       
   158         qint64 tSize = product[priv->m_currProductIndex]->albumSize();
       
   159         setTotalSize(tSize);
       
   160         priv->m_currDownloadIndex = 0;
       
   161         priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start();
       
   162         priv->m_isMediaDownload = true; 
       
   163         return 0;         
       
   164     }
       
   165     return -1;
       
   166 }
       
   167 
       
   168 int OMA2DownloadBackend::cancel()
       
   169 {
       
   170     DM_PRIVATE(OMA2DownloadBackend);
       
   171     if (priv->m_isMediaDownload)
       
   172         priv->m_mediaDownloadList[priv->m_currDownloadIndex]->cancel();
       
   173     else
       
   174        DownloadBackend::cancel();
       
   175     return 0;
       
   176 }
       
   177 
       
   178 QVariant OMA2DownloadBackend::getAttribute(DownloadAttribute attr)
       
   179 {
       
   180     DM_PRIVATE(OMA2DownloadBackend);
       
   181     // moIndex is zero because when product name is empty the name of 0th Mediaobject should be shown in dd and also the type is of the 0th Mediaobject
       
   182     const int moIndex = 0;
       
   183     QString text = "";
       
   184     ProductList product;
       
   185     if (priv->m_downloadDesc)
       
   186         product = priv->m_downloadDesc->productList();
       
   187     switch(attr) {
       
   188     case OMADownloadDescriptorName:
       
   189     {
       
   190         if (product[priv->m_currProductIndex]) {
       
   191             QString name = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString();
       
   192             if (!name.isEmpty())
       
   193                 return name;
       
   194             if (product[priv->m_currProductIndex]->mediaCount() > 0)
       
   195                 return product[priv->m_currProductIndex]->mediaObjList()[moIndex]->getAttribute(OMA2DownloadDescMediaObjName);
       
   196             return text;
       
   197         }  
       
   198         return text;
       
   199     }
       
   200 
       
   201     case OMADownloadDescriptorType:
       
   202     {
       
   203         if (product[priv->m_currProductIndex]) {
       
   204             if (product[priv->m_currProductIndex]->mediaCount() > 0)
       
   205                 return product[priv->m_currProductIndex]->mediaObjList()[moIndex]->getAttribute(OMA2DownloadDescMediaObjType);
       
   206             return text;
       
   207         }
       
   208         return text;
       
   209     }
       
   210 
       
   211     case OMADownloadDescriptorSize:
       
   212     {
       
   213         qint64 size = 0;
       
   214         if (product[priv->m_currProductIndex])
       
   215             return product[priv->m_currProductIndex]->albumSize();
       
   216         return size;
       
   217     }
       
   218 
       
   219     case OMADownloadDescriptorNextURL:
       
   220     {
       
   221         return priv->m_downloadDesc->getAttribute(OMADownloadDescNextURL);
       
   222     }
       
   223 
       
   224     case DlFileName:
       
   225     {
       
   226         if (!priv->m_isMediaDownload) {
       
   227             QString url = priv->m_downloadCore->url();
       
   228             QFileInfo fileUrl(url);
       
   229             return QVariant(fileUrl.fileName());
       
   230         }
       
   231         // If the product tag doesn't have a name then display the media object's name in the download list.
       
   232         // This is helpful for single OMA2 download and is done for better user readability
       
   233         if (product[priv->m_currProductIndex]) {
       
   234             QString name = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString();
       
   235             if (!name.isEmpty())
       
   236                 return name;
       
   237             if (product[priv->m_currProductIndex]->mediaCount() > 0)
       
   238                 return product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjName);
       
   239             return text;
       
   240         }  
       
   241         return text;
       
   242     }
       
   243 
       
   244     case DlContentType:
       
   245     {
       
   246         if (!priv->m_isMediaDownload)
       
   247             return DownloadBackend::getAttribute(DlContentType);
       
   248         QString contentType = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlContentType).toString();
       
   249         if (contentType != "")
       
   250             return contentType;
       
   251         QString mediaObjContentType;
       
   252         getValueForChild(DownloadInfo::EContentType, mediaObjContentType, priv->m_childIds[priv->m_currDownloadIndex].toInt());
       
   253         return mediaObjContentType;
       
   254     }
       
   255 
       
   256     default:
       
   257         return DownloadBackend::getAttribute(attr);
       
   258     }
       
   259     return QVariant();
       
   260 }
       
   261 
       
   262 int OMA2DownloadBackend::setAttribute(DownloadAttribute attr, const QVariant& value)
       
   263 {
       
   264     return DownloadBackend::setAttribute(attr, value);
       
   265 }
       
   266 
       
   267 // stores the data in storage
       
   268 void OMA2DownloadBackend::store(QByteArray /*data*/, bool /*lastChunk=false*/)
       
   269 {
       
   270     return;
       
   271 }
       
   272 
       
   273 // deletes the storage
       
   274 void OMA2DownloadBackend::deleteStore()
       
   275 {
       
   276     return;
       
   277 }
       
   278 
       
   279 // returns the size of stored data
       
   280 qint64 OMA2DownloadBackend::storedDataSize()
       
   281 {
       
   282     return 0;
       
   283 }
       
   284 
       
   285 void OMA2DownloadBackend::bytesRecieved(qint64 /*bytesRecieved*/, qint64 /*bytesTotal*/)
       
   286 {
       
   287      //Do nothing. This is here to avoid this signal to reach to base class' slot.
       
   288      return;
       
   289 }
       
   290 
       
   291 void OMA2DownloadBackend::bytesUploaded(qint64 bytesUploaded, qint64 bytesTotal)
       
   292 {
       
   293     DM_PRIVATE(OMA2DownloadBackend);
       
   294     // once data is uploaded, cancel the transaction
       
   295     if (bytesUploaded == bytesTotal)
       
   296         priv->m_downloadCore->abort() ;
       
   297 
       
   298 }
       
   299 
       
   300 void OMA2DownloadBackend::handleFinished()
       
   301 {
       
   302      DM_PRIVATE(OMA2DownloadBackend);
       
   303      QString contentType = priv->m_downloadCore->contentType();
       
   304      if (contentType == OMA2_CONTENT_TYPE) {
       
   305          bool bSucceeded = parseDownloadDescriptor();
       
   306          priv->m_downloadDesc = priv->m_parser->downloadDescriptor();
       
   307          if (bSucceeded) {
       
   308              ProductList product = priv->m_downloadDesc->productList();
       
   309              int count =  product[priv->m_currProductIndex]->mediaCount();
       
   310              if (count == 0) {
       
   311                  priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("906 Invalid descriptor"));
       
   312                  priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
       
   313                  priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor"));
       
   314                  setDownloadState(DlFailed);
       
   315                  postEvent(Error, NULL);
       
   316                  return;
       
   317              }
       
   318              for (int i=0; i < count; i++) {
       
   319                  QString server = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjServer).toString();
       
   320                  QString size = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjSize).toString();
       
   321                  QString type = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjType).toString();
       
   322                  if (server.isEmpty() || size.isEmpty() || type.isEmpty()) {
       
   323                      QString string;
       
   324                      string = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjInstallNotifyURI).toString();
       
   325                      priv->m_downloadCore->post(string, QByteArray("905 Attribute Mismatch"));
       
   326                      priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
       
   327                      priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor"));
       
   328                      setDownloadState(DlFailed);
       
   329                      postEvent(Error, NULL);
       
   330                      return;
       
   331                  }
       
   332              }
       
   333              // if download is restarted OR suppressUserConfirmation is true, do not show descriptor
       
   334              if (suppressUserConfirmation() || (DlDescriptorUpdated == downloadState())) {
       
   335                  resume();
       
   336              } else {
       
   337                  setDownloadState(DlPaused);
       
   338                  postEvent(OMADownloadDescriptorReady, NULL);
       
   339              }
       
   340          } else {
       
   341              priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("906 Invalid descriptor"));
       
   342              priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
       
   343              priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor"));
       
   344              setDownloadState(DlFailed);
       
   345              postEvent(Error, NULL);
       
   346         }
       
   347     }
       
   348 }
       
   349           
       
   350 bool OMA2DownloadBackend::parseDownloadDescriptor()
       
   351 {
       
   352     DM_PRIVATE(OMA2DownloadBackend);
       
   353     priv->m_parser = new OMADownloadDescParser();
       
   354     QXmlInputSource source(priv->m_downloadCore->reply());
       
   355     QXmlSimpleReader reader;
       
   356     reader.setContentHandler(priv->m_parser);
       
   357     reader.setErrorHandler(priv->m_parser);
       
   358     return reader.parse(source);
       
   359 }
       
   360 
       
   361 // capability check on the descriptor
       
   362 bool OMA2DownloadBackend::checkDownloadDescriptor()
       
   363 {
       
   364 #ifdef Q_OS_LINUX
       
   365     DM_PRIVATE(OMA2DownloadBackend); 
       
   366     ProductList product = priv->m_downloadDesc->productList();
       
   367     double fileSize = product[priv->m_currProductIndex]->albumSize();
       
   368     double mbFactor = 1024*1024;
       
   369     fileSize = fileSize/mbFactor; //fileSize in MB
       
   370     double spaceLeft = freeSpace(ROOT_PATH); //spaze left in MB
       
   371     
       
   372     if (fileSize > spaceLeft) {
       
   373         priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("901 Insufficient memory"));
       
   374         priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
       
   375         priv->m_downloadCore->setLastErrorString(tr("901 Insufficient Memory"));
       
   376         setDownloadState(DlFailed);
       
   377         postEvent(Error, NULL);
       
   378         return false;       
       
   379     } 
       
   380 #endif
       
   381     return true;
       
   382 }
       
   383 
       
   384 bool OMA2DownloadBackend::event(QEvent *event)
       
   385 {
       
   386     DM_PRIVATE(OMA2DownloadBackend);
       
   387     ProductList product = priv->m_downloadDesc->productList();
       
   388     DownloadEvent* downloadEvent =  dynamic_cast<DownloadEvent*>(event);
       
   389     DEventType type = (DEventType)event->type();
       
   390     switch(type) {
       
   391     case Started:
       
   392         break;
       
   393     case HeaderReceived:
       
   394     {
       
   395         int dlId = ((DownloadEvent*)event)->getId();
       
   396         if (downloadEvent) {
       
   397             int statusCode = downloadEvent->getAttribute(HeaderReceivedStatusCode).toInt();
       
   398             handleStatusCode(statusCode);
       
   399         }
       
   400         ClientDownload *dl = findDownload(dlId);
       
   401         // Check the mismatch in total size returned by server with the size given in the descriptor.
       
   402         //This piece of code is commented as-of-now. when needed in future , will be uncommented
       
   403         /*qint64 totalSize = dl->getAttribute(DlTotalSize).toInt();
       
   404         if(product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjSize).toInt() != totalSize) {
       
   405             postInstallNotifyEvent("905 Attribut Mismatch");
       
   406             priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed;
       
   407         } */
       
   408         // Check the mismatch in content type returned by server with the content type given in the descriptor.
       
   409         QString contentType = dl->getAttribute(DlContentType).toString();
       
   410         if(product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjType).toString() != contentType) {
       
   411             postInstallNotifyEvent("905 Attribute Mismatch");
       
   412             priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed;
       
   413             if (priv->m_currDownloadIndex < product[priv->m_currProductIndex]->mediaCount()-1) {
       
   414                 priv->m_currDownloadIndex++;
       
   415                 priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start();
       
   416             }
       
   417        }        
       
   418         break;
       
   419     }
       
   420 
       
   421     case Progress:
       
   422     {        
       
   423         QVariant curDlsize = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlDownloadedSize);
       
   424         qint64 currentDlSize =  priv->m_dlCompletedSize + (curDlsize.toInt());
       
   425         setDownloadedDataSize(currentDlSize);
       
   426         setDownloadState(DlInprogress);
       
   427         priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlInprogress;
       
   428         setValueForChild(DownloadInfo::EDlState, DlInprogress, downloadEvent->getId());
       
   429         postEvent(Progress, NULL);
       
   430         break;
       
   431     }
       
   432     case Paused:
       
   433     {
       
   434         setDownloadState(DlPaused);
       
   435         priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlPaused;
       
   436         setValueForChild(DownloadInfo::EDlState, DlPaused, downloadEvent->getId());
       
   437         postEvent(Paused, NULL);
       
   438         break;
       
   439     }
       
   440     case NetworkLoss:
       
   441     {
       
   442         postEvent(NetworkLoss, NULL);
       
   443         break;
       
   444     }
       
   445     case Cancelled:
       
   446     {
       
   447         postInstallNotifyEvent("902 User Cancelled");
       
   448         priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlCancelled;
       
   449         setValueForChild(DownloadInfo::EDlState, DlCancelled, downloadEvent->getId());
       
   450         setDownloadState(DlCancelled);
       
   451         postEvent(Cancelled, NULL);
       
   452         break;
       
   453     }
       
   454     case Completed:
       
   455     {
       
   456         postInstallNotifyEvent("900 Success");
       
   457         priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlCompleted;
       
   458         setValueForChild(DownloadInfo::EDlState, DlCompleted, downloadEvent->getId());
       
   459         QVariant curDlsize = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlDownloadedSize);
       
   460         priv->m_dlCompletedSize = priv->m_dlCompletedSize + (curDlsize.toInt());
       
   461         if (priv->m_currDownloadIndex < product[priv->m_currProductIndex]->mediaCount()-1) {
       
   462             priv->m_currDownloadIndex++;
       
   463             priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start();
       
   464         } else if (priv->m_currDownloadIndex == product[priv->m_currProductIndex]->mediaCount()-1) 
       
   465             verifyDownloads();
       
   466         break;
       
   467     }        
       
   468     case Error:
       
   469     {
       
   470         priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
       
   471         priv->m_downloadCore->setLastErrorString(tr("905 Attribute Mismatch"));
       
   472         setDownloadState(DlFailed);
       
   473         postEvent(Error, NULL);
       
   474         priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed;
       
   475         setValueForChild(DownloadInfo::EDlState, DlFailed, downloadEvent->getId());
       
   476         break;
       
   477     } 
       
   478     default:
       
   479         break;
       
   480     }
       
   481     return true;
       
   482 }
       
   483 
       
   484 void OMA2DownloadBackend::getChildren(QList<Download*>& list)
       
   485 {
       
   486     DM_PRIVATE(OMA2DownloadBackend);
       
   487     for (int i = 0; i < priv->m_mediaDownloadList.count(); i++) 
       
   488         list.append(priv->m_mediaDownloadList[i]);
       
   489 
       
   490 }
       
   491 
       
   492 bool OMA2DownloadBackend::suppressUserConfirmation()
       
   493 {
       
   494     DM_PRIVATE(OMA2DownloadBackend);
       
   495 
       
   496     ProductList productList = priv->m_downloadDesc->productList();
       
   497     QString suppressValue = productList[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductSuppressConfirmation).toString();
       
   498     QString suppressUserConfirmNever(SuppressUserConfirmation_Never);
       
   499 
       
   500     // If suppressUserConfirmation attribute is present for Product tag, use it and don't check media objects
       
   501     // for this attribute
       
   502     if (!suppressValue.isEmpty()) {
       
   503         if (suppressValue == suppressUserConfirmNever)
       
   504             return false;
       
   505         return true;
       
   506     }
       
   507     
       
   508     int mediaCount = productList[priv->m_currProductIndex]->mediaCount();
       
   509     // If suppressUserConfirmation is present and it is NOT "Never" for even a single media object,
       
   510     // then treat this as true and do not display user confirmation.
       
   511     QString suppressConfirmMediaObj = "";
       
   512 
       
   513     for (int i=0; i<mediaCount; ++i) {
       
   514         // If the mediaObject element in DD file has this attribute
       
   515         suppressValue = productList[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjSuppressConfirmation).toString();
       
   516         if (!suppressValue.isEmpty()) {
       
   517             // Check if two or more mediObjects have different values for this attribute.
       
   518             // If so, then this is an invalid case. Hence we ignore this attribute.
       
   519             if (suppressConfirmMediaObj.isEmpty())
       
   520                 suppressConfirmMediaObj = suppressValue;
       
   521             else if (suppressConfirmMediaObj != suppressValue) {
       
   522                 // Two mediaObjects have different values of suppressUserConfirmation attribute.
       
   523                 // Ignore this attribute.
       
   524                 return false;
       
   525             }
       
   526         }
       
   527     }
       
   528     
       
   529     // If string is empty OR its value is "Never", return false.
       
   530     if (suppressConfirmMediaObj.isEmpty() || (suppressConfirmMediaObj == suppressUserConfirmNever))
       
   531         return false;
       
   532     
       
   533     return true;
       
   534 }
       
   535 
       
   536 void OMA2DownloadBackend::handleStatusCode(const int& statusCode)
       
   537 {
       
   538     HttpStatusCode status = (HttpStatusCode)statusCode;
       
   539     switch(status) {
       
   540     case HttpPreconditionFailed:    // Precondition Failed
       
   541     {
       
   542         handlePreconditionFailed();
       
   543         postEvent(DescriptorUpdated, NULL);
       
   544         return;
       
   545     }
       
   546     
       
   547     default:
       
   548         return;
       
   549     }
       
   550 }
       
   551 
       
   552 void OMA2DownloadBackend::handlePreconditionFailed()
       
   553 {
       
   554     DM_PRIVATE(OMA2DownloadBackend);
       
   555     QString updatedDDUri = priv->m_downloadDesc->getAttribute(OMA2DownloadDescUpdatedDDURI).toString();
       
   556     if (updatedDDUri.isEmpty())
       
   557         return;
       
   558 
       
   559     DownloadManager* dlMgr = priv->m_download->downloadManager();
       
   560     if (!dlMgr)
       
   561         return;
       
   562 
       
   563     // Delete all media objects
       
   564     priv->m_isMediaDownload = false;
       
   565     ProductList productList = priv->m_downloadDesc->productList();
       
   566     int count =  productList[priv->m_currProductIndex]->mediaCount();
       
   567 
       
   568     // Remove all media objects
       
   569     for(int i=0; i<count; ++i) {
       
   570         ClientDownload* dl = priv->m_mediaDownloadList[i];
       
   571         QCoreApplication::removePostedEvents(this);
       
   572         dl->unregisterEventReceiver(this);
       
   573         priv->m_mediaDownloadList.removeOne(dl);
       
   574         dlMgr->removeOne(dl);
       
   575     }
       
   576     
       
   577     // start download of updated DD
       
   578     priv->m_downloadCore->changeUrl(updatedDDUri);
       
   579     priv->m_downloadCore->doDownload();
       
   580     setDownloadState(DlDescriptorUpdated);
       
   581 }
       
   582 
       
   583 void OMA2DownloadBackend::addtoDownloadList(ClientDownload* dl)
       
   584 {
       
   585     DM_PRIVATE(OMA2DownloadBackend); 
       
   586     dl->registerEventReceiver(this);
       
   587     priv->m_childIds.append(dl->id());
       
   588     priv->m_mediaDownloadList.append(dl);
       
   589 }
       
   590 
       
   591 ClientDownload* OMA2DownloadBackend::findDownload(int id)
       
   592 {
       
   593     DM_PRIVATE(OMA2DownloadBackend);
       
   594     for (int i = 0; i < priv->m_mediaDownloadList.size(); ++i) {
       
   595         if (priv->m_mediaDownloadList[i]->id() == id)
       
   596             return priv->m_mediaDownloadList[i];
       
   597     }
       
   598     return 0; 
       
   599 }
       
   600 
       
   601 void OMA2DownloadBackend::postInstallNotifyEvent(const char* statusMessage)
       
   602 {
       
   603     DM_PRIVATE(OMA2DownloadBackend);
       
   604     ProductList product = priv->m_downloadDesc->productList();
       
   605     QString string;
       
   606     string = product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjInstallNotifyURI).toString();
       
   607     priv->m_downloadCore->post(string, QByteArray(statusMessage));   
       
   608 }
       
   609 
       
   610 void OMA2DownloadBackend::verifyDownloads()
       
   611 {
       
   612     DM_PRIVATE(OMA2DownloadBackend);
       
   613     // go throught the mediaObjmap of id, state value pair and if any dl is failed then set the state of parent as paused.
       
   614     ProductList product = priv->m_downloadDesc->productList();
       
   615     int counter = 0;
       
   616     for (int i=0; i < priv->m_childIds.count(); i++) {
       
   617         if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlCompleted)
       
   618             counter++;
       
   619         else if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlFailed) {
       
   620             setDownloadState(DlFailed);
       
   621             postEvent(Error, NULL);
       
   622             break;
       
   623         }
       
   624     }
       
   625     if (counter == priv->m_childIds.count()) {
       
   626         setDownloadState(DlCompleted);
       
   627         postEvent(Completed, NULL);
       
   628     }
       
   629 }
       
   630 
       
   631 int OMA2DownloadBackend::currentIndex()
       
   632 {
       
   633     // If a download is in progress and closed,  a track in an album is either paused or created.
       
   634     // This function as part of persistant storage,returns the index of the download which is either in paused or created state
       
   635     DM_PRIVATE(OMA2DownloadBackend);
       
   636     ProductList product = priv->m_downloadDesc->productList();
       
   637     for (int i=0; i < priv->m_childIds.count(); i++) {
       
   638         if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlPaused
       
   639             || priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlCreated) {
       
   640             priv->m_currDownloadIndex = i;
       
   641             break;
       
   642         }
       
   643     }
       
   644     return priv->m_currDownloadIndex;
       
   645 }
       
   646 
       
   647 void OMA2DownloadBackend::init()
       
   648 {
       
   649     DM_PRIVATE(OMA2DownloadBackend);
       
   650     priv->m_isMediaDownload = true; // since init() is called during restoring the persistent info, the flag should be set to true.
       
   651 
       
   652     priv->m_downloadDesc = new OMADownloadDescriptor();
       
   653     priv->m_currProduct = new OMA2DownloadProduct();
       
   654     priv->m_downloadDesc->addProduct(priv->m_currProduct);
       
   655     // populating the product map
       
   656     QString productName;
       
   657     getValue(DownloadInfo::EFileName, productName);
       
   658     priv->m_currProduct->setAttribute("name", QVariant(productName));
       
   659 
       
   660     QList<QVariant> id;
       
   661     getValue(DownloadInfo::EChildIdList, id);
       
   662     QString oma2ContentType,mediaObjName,mediaObjUrl,mediaObjContentType;
       
   663     long mediaObjSize;
       
   664     long state;
       
   665     priv->m_currProductIndex = 0;
       
   666     for(int i=0; i<id.size(); i++) {
       
   667         //populating the mediaobj map
       
   668         priv->m_currMediaObj = new OMA2DownloadMediaObj();
       
   669         priv->m_currProduct->addMediaObject(priv->m_currMediaObj);
       
   670         
       
   671         // getting all the values related to media object for populating descriptor's mediaobj map        
       
   672         getValueForChild(DownloadInfo::EFileName, mediaObjName, id[i].toInt());
       
   673         getValueForChild(DownloadInfo::ETotalSize, mediaObjSize, id[i].toInt());
       
   674         getValueForChild(DownloadInfo::EUrl, mediaObjUrl, id[i].toInt());
       
   675         getValueForChild(DownloadInfo::EContentType, mediaObjContentType, id[i].toInt());
       
   676         getValueForChild(DownloadInfo::EDlState, state, id[i].toInt());
       
   677         priv->m_mediaObjIdStateMap[id[i].toInt()] = state;
       
   678 
       
   679         // creaating downloads for the media objects
       
   680         ClientDownload *dl = NULL;
       
   681         if (state == DlCreated) {
       
   682             dl = new ClientDownload(priv->m_download->downloadManager(), mediaObjUrl, id[i].toInt(), Parallel
       
   683                                                                                                    , priv->m_download->id() );
       
   684         }
       
   685         else
       
   686             dl = new ClientDownload(priv->m_download->downloadManager(), id[i].toInt(), priv->m_download->id());
       
   687 
       
   688         setValueForChild(DownloadInfo::EDlState, priv->m_mediaObjIdStateMap[id[i].toInt()], id[i].toInt());
       
   689         addtoDownloadList(dl);
       
   690         // re-constructing descriptor's mediaobj map
       
   691         priv->m_currMediaObj->setAttribute("name", QVariant(mediaObjName));
       
   692         int size = mediaObjSize;
       
   693         priv->m_currMediaObj->setAttribute("size", QVariant(size));
       
   694         priv->m_currMediaObj->setAttribute("type", QVariant(mediaObjContentType));
       
   695         priv->m_currMediaObj->setAttribute("server",QVariant(mediaObjUrl));
       
   696     }
       
   697     ProductList product = priv->m_downloadDesc->productList();
       
   698     getValue(DownloadInfo::EDlState,state);
       
   699     if(state == DlCompleted)
       
   700         priv->m_currDownloadIndex = product[priv->m_currProductIndex]->mediaCount()-1;
       
   701     else
       
   702         priv->m_currDownloadIndex = currentIndex();
       
   703 }
       
   704 
       
   705 void OMA2DownloadBackend::serializeData(ClientDownload* dl, int index)
       
   706 {
       
   707     DM_PRIVATE(OMA2DownloadBackend);
       
   708     ProductList product = priv->m_downloadDesc->productList();
       
   709     // set OMA2 parent values in QSettings.
       
   710     QString productName = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString(); // contenttype,url being written in dlbackend's constructor
       
   711     setValue(DownloadInfo::EFileName, productName);
       
   712 
       
   713     // set minimal MediaObject attributes in QSettings like name, size, url and contentType as these are the ones required for persistent storage.
       
   714     QString mediaObjName = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjName).toString();
       
   715     setValueForChild(DownloadInfo::EFileName, mediaObjName, dl->id());
       
   716     long mediaObjSize = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjSize).toInt();
       
   717     setValueForChild(DownloadInfo::ETotalSize, mediaObjSize, dl->id());
       
   718     QString mediaObjContentType = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjType).toString();
       
   719     setValueForChild(DownloadInfo::EContentType, mediaObjContentType, dl->id());
       
   720     QString destPath = (download()->attributes().value(DlDestPath)).toString();
       
   721     setValueForChild(DownloadInfo::EFinalPath, destPath, dl->id());
       
   722     setValueForChild(DownloadInfo::EETag, priv->m_downloadCore->entityTag(), dl->id()); //not getting set check later
       
   723 }