utilities/downloadmanager/src/oma2downloadbackend.cpp
changeset 16 3c88a81ff781
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/downloadmanager/src/oma2downloadbackend.cpp	Fri Oct 15 17:30:59 2010 -0400
@@ -0,0 +1,723 @@
+/**
+   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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "oma2downloadbackend.h"
+#include "omaddparser.h"
+#include "downloadmanager.h"
+#include "download.h"
+#include "clientdownload.h"
+#include "downloadcore.h"
+#include "downloadevent.h"
+#include <QCoreApplication>
+#include <QFileInfo>
+
+#ifdef Q_OS_LINUX
+  #include <sys/statvfs.h>
+#endif
+
+#ifdef Q_OS_LINUX 
+static double freeSpace(const char *path)
+#else
+static double freeSpace(const char* /*path*/)
+#endif
+{
+#ifdef Q_OS_LINUX   
+    struct statvfs fiData;
+    if ((statvfs(path,&fiData)) < 0 ) 
+        return 0;
+    else {
+        qint64 blockSize = fiData.f_bsize/1024;
+        qint64 freeSize = (fiData.f_bavail)*blockSize;
+        freeSize = freeSize/1024;
+        return freeSize;
+    }
+#endif
+    return 0;
+}
+
+// Constants
+const char* const SuppressUserConfirmation_Never = "Never";
+
+// private implementation
+class OMA2DownloadBackendPrivate {
+    DM_DECLARE_PUBLIC(OMA2DownloadBackend);
+public:
+    OMA2DownloadBackendPrivate();
+    ~OMA2DownloadBackendPrivate();
+    DownloadCore *m_downloadCore;
+    ClientDownload *m_download;
+    OMADownloadDescParser *m_parser; // for parsing oma descriptor
+    OMADownloadDescriptor *m_downloadDesc;
+    bool m_isMediaDownload; // flag to indicate if media download is happening  
+    MediaDownloadList m_mediaDownloadList; // media downloads
+    int m_currDownloadIndex;
+    int m_currProductIndex;
+    qint64 m_dlCompletedSize;
+    QMap<int, int> m_mediaObjIdStateMap; // map to have the list of Media Objects' id and it's state.
+    QList<QVariant> m_childIds;
+    OMA2DownloadProduct *m_currProduct;
+    OMA2DownloadMediaObj *m_currMediaObj;
+};
+
+OMA2DownloadBackendPrivate::OMA2DownloadBackendPrivate():m_downloadCore(0)
+                                                        ,m_download(0)
+                                                        ,m_parser(0)
+                                                        ,m_downloadDesc(0)
+                                                        ,m_isMediaDownload(false)
+                                                        ,m_currDownloadIndex(-1)
+                                                        ,m_currProductIndex(0)
+                                                        ,m_dlCompletedSize(0)
+{ }
+
+OMA2DownloadBackendPrivate::~OMA2DownloadBackendPrivate()
+{
+    if (m_parser) {
+        delete m_parser;
+        m_parser = 0;
+        m_downloadDesc = 0;
+    }
+    // In case of persistent storage
+    if (m_downloadDesc) {
+        delete m_downloadDesc;
+        m_downloadDesc = 0;
+    }
+    
+    int count = m_mediaDownloadList.count();
+    for (int i = 0; i < count; i++)
+        delete m_mediaDownloadList[i];
+}
+
+OMA2DownloadBackend::OMA2DownloadBackend(DownloadCore *dlCore, ClientDownload *dl)
+    :DownloadBackend(dlCore, dl)
+{
+    DM_INITIALIZE(OMA2DownloadBackend);
+    priv->m_downloadCore = dlCore;
+    priv->m_download = dl;
+}
+
+OMA2DownloadBackend::~OMA2DownloadBackend()
+{
+    DM_UNINITIALIZE(OMA2DownloadBackend);
+}
+
+int OMA2DownloadBackend::pause()
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    if (priv->m_isMediaDownload) {
+        priv->m_mediaDownloadList[priv->m_currDownloadIndex]->pause();
+        setDownloadState(DlPaused);
+    }
+    return 0;
+}
+
+int OMA2DownloadBackend::resume()
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    if (priv->m_isMediaDownload)
+        return (priv->m_mediaDownloadList[priv->m_currDownloadIndex]->resume());
+
+    // Ready to download after the descriptor is parsed
+    // capability check on the descriptor information
+    if (checkDownloadDescriptor()) {
+        ProductList product = priv->m_downloadDesc->productList();
+        int count =  product[priv->m_currProductIndex]->mediaCount();
+        
+        for (int i=0; i < count; i++) {
+            QUrl baseUrl = priv->m_downloadCore->url();
+            QUrl relativeUrl = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjServer).toString();
+            QString url = baseUrl.resolved(relativeUrl).toString();
+            // create download for media object
+            // id's of media downloads are unique under its parent oma download
+            ClientDownload *dl = new ClientDownload(priv->m_download->downloadManager(), url, (i+1), Parallel
+                                                                                            , priv->m_download->id() );
+            if (NULL == dl)
+                return -1;
+            // functions for persistent storage
+            serializeData(dl, i);
+            setValueForChild(DownloadInfo::EUrl, url, dl->id());
+            setValueForChild(DownloadInfo::EDlState, DlCreated, dl->id());
+            long state;
+            getValue(DownloadInfo::EDlState, state);
+            priv->m_mediaObjIdStateMap[dl->id()] = state;
+            addtoDownloadList(dl);
+        }
+        setValue(DownloadInfo::EChildIdList, priv->m_childIds);
+        qint64 tSize = product[priv->m_currProductIndex]->albumSize();
+        setTotalSize(tSize);
+        priv->m_currDownloadIndex = 0;
+        priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start();
+        priv->m_isMediaDownload = true; 
+        return 0;         
+    }
+    return -1;
+}
+
+int OMA2DownloadBackend::cancel()
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    if (priv->m_isMediaDownload)
+        priv->m_mediaDownloadList[priv->m_currDownloadIndex]->cancel();
+    else
+       DownloadBackend::cancel();
+    return 0;
+}
+
+QVariant OMA2DownloadBackend::getAttribute(DownloadAttribute attr)
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    // 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
+    const int moIndex = 0;
+    QString text = "";
+    ProductList product;
+    if (priv->m_downloadDesc)
+        product = priv->m_downloadDesc->productList();
+    switch(attr) {
+    case OMADownloadDescriptorName:
+    {
+        if (product[priv->m_currProductIndex]) {
+            QString name = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString();
+            if (!name.isEmpty())
+                return name;
+            if (product[priv->m_currProductIndex]->mediaCount() > 0)
+                return product[priv->m_currProductIndex]->mediaObjList()[moIndex]->getAttribute(OMA2DownloadDescMediaObjName);
+            return text;
+        }  
+        return text;
+    }
+
+    case OMADownloadDescriptorType:
+    {
+        if (product[priv->m_currProductIndex]) {
+            if (product[priv->m_currProductIndex]->mediaCount() > 0)
+                return product[priv->m_currProductIndex]->mediaObjList()[moIndex]->getAttribute(OMA2DownloadDescMediaObjType);
+            return text;
+        }
+        return text;
+    }
+
+    case OMADownloadDescriptorSize:
+    {
+        qint64 size = 0;
+        if (product[priv->m_currProductIndex])
+            return product[priv->m_currProductIndex]->albumSize();
+        return size;
+    }
+
+    case OMADownloadDescriptorNextURL:
+    {
+        return priv->m_downloadDesc->getAttribute(OMADownloadDescNextURL);
+    }
+
+    case DlFileName:
+    {
+        if (!priv->m_isMediaDownload) {
+            QString url = priv->m_downloadCore->url();
+            QFileInfo fileUrl(url);
+            return QVariant(fileUrl.fileName());
+        }
+        // If the product tag doesn't have a name then display the media object's name in the download list.
+        // This is helpful for single OMA2 download and is done for better user readability
+        if (product[priv->m_currProductIndex]) {
+            QString name = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString();
+            if (!name.isEmpty())
+                return name;
+            if (product[priv->m_currProductIndex]->mediaCount() > 0)
+                return product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjName);
+            return text;
+        }  
+        return text;
+    }
+
+    case DlContentType:
+    {
+        if (!priv->m_isMediaDownload)
+            return DownloadBackend::getAttribute(DlContentType);
+        QString contentType = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlContentType).toString();
+        if (contentType != "")
+            return contentType;
+        QString mediaObjContentType;
+        getValueForChild(DownloadInfo::EContentType, mediaObjContentType, priv->m_childIds[priv->m_currDownloadIndex].toInt());
+        return mediaObjContentType;
+    }
+
+    default:
+        return DownloadBackend::getAttribute(attr);
+    }
+    return QVariant();
+}
+
+int OMA2DownloadBackend::setAttribute(DownloadAttribute attr, const QVariant& value)
+{
+    return DownloadBackend::setAttribute(attr, value);
+}
+
+// stores the data in storage
+void OMA2DownloadBackend::store(QByteArray /*data*/, bool /*lastChunk=false*/)
+{
+    return;
+}
+
+// deletes the storage
+void OMA2DownloadBackend::deleteStore()
+{
+    return;
+}
+
+// returns the size of stored data
+qint64 OMA2DownloadBackend::storedDataSize()
+{
+    return 0;
+}
+
+void OMA2DownloadBackend::bytesRecieved(qint64 /*bytesRecieved*/, qint64 /*bytesTotal*/)
+{
+     //Do nothing. This is here to avoid this signal to reach to base class' slot.
+     return;
+}
+
+void OMA2DownloadBackend::bytesUploaded(qint64 bytesUploaded, qint64 bytesTotal)
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    // once data is uploaded, cancel the transaction
+    if (bytesUploaded == bytesTotal)
+        priv->m_downloadCore->abort() ;
+
+}
+
+void OMA2DownloadBackend::handleFinished()
+{
+     DM_PRIVATE(OMA2DownloadBackend);
+     QString contentType = priv->m_downloadCore->contentType();
+     if (contentType == OMA2_CONTENT_TYPE) {
+         bool bSucceeded = parseDownloadDescriptor();
+         priv->m_downloadDesc = priv->m_parser->downloadDescriptor();
+         if (bSucceeded) {
+             ProductList product = priv->m_downloadDesc->productList();
+             int count =  product[priv->m_currProductIndex]->mediaCount();
+             if (count == 0) {
+                 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("906 Invalid descriptor"));
+                 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
+                 priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor"));
+                 setDownloadState(DlFailed);
+                 postEvent(Error, NULL);
+                 return;
+             }
+             for (int i=0; i < count; i++) {
+                 QString server = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjServer).toString();
+                 QString size = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjSize).toString();
+                 QString type = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjType).toString();
+                 if (server.isEmpty() || size.isEmpty() || type.isEmpty()) {
+                     QString string;
+                     string = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjInstallNotifyURI).toString();
+                     priv->m_downloadCore->post(string, QByteArray("905 Attribute Mismatch"));
+                     priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
+                     priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor"));
+                     setDownloadState(DlFailed);
+                     postEvent(Error, NULL);
+                     return;
+                 }
+             }
+             // if download is restarted OR suppressUserConfirmation is true, do not show descriptor
+             if (suppressUserConfirmation() || (DlDescriptorUpdated == downloadState())) {
+                 resume();
+             } else {
+                 setDownloadState(DlPaused);
+                 postEvent(OMADownloadDescriptorReady, NULL);
+             }
+         } else {
+             priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("906 Invalid descriptor"));
+             priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
+             priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor"));
+             setDownloadState(DlFailed);
+             postEvent(Error, NULL);
+        }
+    }
+}
+          
+bool OMA2DownloadBackend::parseDownloadDescriptor()
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    priv->m_parser = new OMADownloadDescParser();
+    QXmlInputSource source(priv->m_downloadCore->reply());
+    QXmlSimpleReader reader;
+    reader.setContentHandler(priv->m_parser);
+    reader.setErrorHandler(priv->m_parser);
+    return reader.parse(source);
+}
+
+// capability check on the descriptor
+bool OMA2DownloadBackend::checkDownloadDescriptor()
+{
+#ifdef Q_OS_LINUX
+    DM_PRIVATE(OMA2DownloadBackend); 
+    ProductList product = priv->m_downloadDesc->productList();
+    double fileSize = product[priv->m_currProductIndex]->albumSize();
+    double mbFactor = 1024*1024;
+    fileSize = fileSize/mbFactor; //fileSize in MB
+    double spaceLeft = freeSpace(ROOT_PATH); //spaze left in MB
+    
+    if (fileSize > spaceLeft) {
+        priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("901 Insufficient memory"));
+        priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
+        priv->m_downloadCore->setLastErrorString(tr("901 Insufficient Memory"));
+        setDownloadState(DlFailed);
+        postEvent(Error, NULL);
+        return false;       
+    } 
+#endif
+    return true;
+}
+
+bool OMA2DownloadBackend::event(QEvent *event)
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    ProductList product = priv->m_downloadDesc->productList();
+    DownloadEvent* downloadEvent =  dynamic_cast<DownloadEvent*>(event);
+    DEventType type = (DEventType)event->type();
+    switch(type) {
+    case Started:
+        break;
+    case HeaderReceived:
+    {
+        int dlId = ((DownloadEvent*)event)->getId();
+        if (downloadEvent) {
+            int statusCode = downloadEvent->getAttribute(HeaderReceivedStatusCode).toInt();
+            handleStatusCode(statusCode);
+        }
+        ClientDownload *dl = findDownload(dlId);
+        // Check the mismatch in total size returned by server with the size given in the descriptor.
+        //This piece of code is commented as-of-now. when needed in future , will be uncommented
+        /*qint64 totalSize = dl->getAttribute(DlTotalSize).toInt();
+        if(product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjSize).toInt() != totalSize) {
+            postInstallNotifyEvent("905 Attribut Mismatch");
+            priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed;
+        } */
+        // Check the mismatch in content type returned by server with the content type given in the descriptor.
+        QString contentType = dl->getAttribute(DlContentType).toString();
+        if(product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjType).toString() != contentType) {
+            postInstallNotifyEvent("905 Attribute Mismatch");
+            priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed;
+            if (priv->m_currDownloadIndex < product[priv->m_currProductIndex]->mediaCount()-1) {
+                priv->m_currDownloadIndex++;
+                priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start();
+            }
+       }        
+        break;
+    }
+
+    case Progress:
+    {        
+        QVariant curDlsize = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlDownloadedSize);
+        qint64 currentDlSize =  priv->m_dlCompletedSize + (curDlsize.toInt());
+        setDownloadedDataSize(currentDlSize);
+        setDownloadState(DlInprogress);
+        priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlInprogress;
+        setValueForChild(DownloadInfo::EDlState, DlInprogress, downloadEvent->getId());
+        postEvent(Progress, NULL);
+        break;
+    }
+    case Paused:
+    {
+        setDownloadState(DlPaused);
+        priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlPaused;
+        setValueForChild(DownloadInfo::EDlState, DlPaused, downloadEvent->getId());
+        postEvent(Paused, NULL);
+        break;
+    }
+    case NetworkLoss:
+    {
+        postEvent(NetworkLoss, NULL);
+        break;
+    }
+    case Cancelled:
+    {
+        postInstallNotifyEvent("902 User Cancelled");
+        priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlCancelled;
+        setValueForChild(DownloadInfo::EDlState, DlCancelled, downloadEvent->getId());
+        setDownloadState(DlCancelled);
+        postEvent(Cancelled, NULL);
+        break;
+    }
+    case Completed:
+    {
+        postInstallNotifyEvent("900 Success");
+        priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlCompleted;
+        setValueForChild(DownloadInfo::EDlState, DlCompleted, downloadEvent->getId());
+        QVariant curDlsize = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlDownloadedSize);
+        priv->m_dlCompletedSize = priv->m_dlCompletedSize + (curDlsize.toInt());
+        if (priv->m_currDownloadIndex < product[priv->m_currProductIndex]->mediaCount()-1) {
+            priv->m_currDownloadIndex++;
+            priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start();
+        } else if (priv->m_currDownloadIndex == product[priv->m_currProductIndex]->mediaCount()-1) 
+            verifyDownloads();
+        break;
+    }        
+    case Error:
+    {
+        priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError);
+        priv->m_downloadCore->setLastErrorString(tr("905 Attribute Mismatch"));
+        setDownloadState(DlFailed);
+        postEvent(Error, NULL);
+        priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed;
+        setValueForChild(DownloadInfo::EDlState, DlFailed, downloadEvent->getId());
+        break;
+    } 
+    default:
+        break;
+    }
+    return true;
+}
+
+void OMA2DownloadBackend::getChildren(QList<Download*>& list)
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    for (int i = 0; i < priv->m_mediaDownloadList.count(); i++) 
+        list.append(priv->m_mediaDownloadList[i]);
+
+}
+
+bool OMA2DownloadBackend::suppressUserConfirmation()
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+
+    ProductList productList = priv->m_downloadDesc->productList();
+    QString suppressValue = productList[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductSuppressConfirmation).toString();
+    QString suppressUserConfirmNever(SuppressUserConfirmation_Never);
+
+    // If suppressUserConfirmation attribute is present for Product tag, use it and don't check media objects
+    // for this attribute
+    if (!suppressValue.isEmpty()) {
+        if (suppressValue == suppressUserConfirmNever)
+            return false;
+        return true;
+    }
+    
+    int mediaCount = productList[priv->m_currProductIndex]->mediaCount();
+    // If suppressUserConfirmation is present and it is NOT "Never" for even a single media object,
+    // then treat this as true and do not display user confirmation.
+    QString suppressConfirmMediaObj = "";
+
+    for (int i=0; i<mediaCount; ++i) {
+        // If the mediaObject element in DD file has this attribute
+        suppressValue = productList[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjSuppressConfirmation).toString();
+        if (!suppressValue.isEmpty()) {
+            // Check if two or more mediObjects have different values for this attribute.
+            // If so, then this is an invalid case. Hence we ignore this attribute.
+            if (suppressConfirmMediaObj.isEmpty())
+                suppressConfirmMediaObj = suppressValue;
+            else if (suppressConfirmMediaObj != suppressValue) {
+                // Two mediaObjects have different values of suppressUserConfirmation attribute.
+                // Ignore this attribute.
+                return false;
+            }
+        }
+    }
+    
+    // If string is empty OR its value is "Never", return false.
+    if (suppressConfirmMediaObj.isEmpty() || (suppressConfirmMediaObj == suppressUserConfirmNever))
+        return false;
+    
+    return true;
+}
+
+void OMA2DownloadBackend::handleStatusCode(const int& statusCode)
+{
+    HttpStatusCode status = (HttpStatusCode)statusCode;
+    switch(status) {
+    case HttpPreconditionFailed:    // Precondition Failed
+    {
+        handlePreconditionFailed();
+        postEvent(DescriptorUpdated, NULL);
+        return;
+    }
+    
+    default:
+        return;
+    }
+}
+
+void OMA2DownloadBackend::handlePreconditionFailed()
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    QString updatedDDUri = priv->m_downloadDesc->getAttribute(OMA2DownloadDescUpdatedDDURI).toString();
+    if (updatedDDUri.isEmpty())
+        return;
+
+    DownloadManager* dlMgr = priv->m_download->downloadManager();
+    if (!dlMgr)
+        return;
+
+    // Delete all media objects
+    priv->m_isMediaDownload = false;
+    ProductList productList = priv->m_downloadDesc->productList();
+    int count =  productList[priv->m_currProductIndex]->mediaCount();
+
+    // Remove all media objects
+    for(int i=0; i<count; ++i) {
+        ClientDownload* dl = priv->m_mediaDownloadList[i];
+        QCoreApplication::removePostedEvents(this);
+        dl->unregisterEventReceiver(this);
+        priv->m_mediaDownloadList.removeOne(dl);
+        dlMgr->removeOne(dl);
+    }
+    
+    // start download of updated DD
+    priv->m_downloadCore->changeUrl(updatedDDUri);
+    priv->m_downloadCore->doDownload();
+    setDownloadState(DlDescriptorUpdated);
+}
+
+void OMA2DownloadBackend::addtoDownloadList(ClientDownload* dl)
+{
+    DM_PRIVATE(OMA2DownloadBackend); 
+    dl->registerEventReceiver(this);
+    priv->m_childIds.append(dl->id());
+    priv->m_mediaDownloadList.append(dl);
+}
+
+ClientDownload* OMA2DownloadBackend::findDownload(int id)
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    for (int i = 0; i < priv->m_mediaDownloadList.size(); ++i) {
+        if (priv->m_mediaDownloadList[i]->id() == id)
+            return priv->m_mediaDownloadList[i];
+    }
+    return 0; 
+}
+
+void OMA2DownloadBackend::postInstallNotifyEvent(const char* statusMessage)
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    ProductList product = priv->m_downloadDesc->productList();
+    QString string;
+    string = product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjInstallNotifyURI).toString();
+    priv->m_downloadCore->post(string, QByteArray(statusMessage));   
+}
+
+void OMA2DownloadBackend::verifyDownloads()
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    // go throught the mediaObjmap of id, state value pair and if any dl is failed then set the state of parent as paused.
+    ProductList product = priv->m_downloadDesc->productList();
+    int counter = 0;
+    for (int i=0; i < priv->m_childIds.count(); i++) {
+        if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlCompleted)
+            counter++;
+        else if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlFailed) {
+            setDownloadState(DlFailed);
+            postEvent(Error, NULL);
+            break;
+        }
+    }
+    if (counter == priv->m_childIds.count()) {
+        setDownloadState(DlCompleted);
+        postEvent(Completed, NULL);
+    }
+}
+
+int OMA2DownloadBackend::currentIndex()
+{
+    // If a download is in progress and closed,  a track in an album is either paused or created.
+    // This function as part of persistant storage,returns the index of the download which is either in paused or created state
+    DM_PRIVATE(OMA2DownloadBackend);
+    ProductList product = priv->m_downloadDesc->productList();
+    for (int i=0; i < priv->m_childIds.count(); i++) {
+        if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlPaused
+            || priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlCreated) {
+            priv->m_currDownloadIndex = i;
+            break;
+        }
+    }
+    return priv->m_currDownloadIndex;
+}
+
+void OMA2DownloadBackend::init()
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    priv->m_isMediaDownload = true; // since init() is called during restoring the persistent info, the flag should be set to true.
+
+    priv->m_downloadDesc = new OMADownloadDescriptor();
+    priv->m_currProduct = new OMA2DownloadProduct();
+    priv->m_downloadDesc->addProduct(priv->m_currProduct);
+    // populating the product map
+    QString productName;
+    getValue(DownloadInfo::EFileName, productName);
+    priv->m_currProduct->setAttribute("name", QVariant(productName));
+
+    QList<QVariant> id;
+    getValue(DownloadInfo::EChildIdList, id);
+    QString oma2ContentType,mediaObjName,mediaObjUrl,mediaObjContentType;
+    long mediaObjSize;
+    long state;
+    priv->m_currProductIndex = 0;
+    for(int i=0; i<id.size(); i++) {
+        //populating the mediaobj map
+        priv->m_currMediaObj = new OMA2DownloadMediaObj();
+        priv->m_currProduct->addMediaObject(priv->m_currMediaObj);
+        
+        // getting all the values related to media object for populating descriptor's mediaobj map        
+        getValueForChild(DownloadInfo::EFileName, mediaObjName, id[i].toInt());
+        getValueForChild(DownloadInfo::ETotalSize, mediaObjSize, id[i].toInt());
+        getValueForChild(DownloadInfo::EUrl, mediaObjUrl, id[i].toInt());
+        getValueForChild(DownloadInfo::EContentType, mediaObjContentType, id[i].toInt());
+        getValueForChild(DownloadInfo::EDlState, state, id[i].toInt());
+        priv->m_mediaObjIdStateMap[id[i].toInt()] = state;
+
+        // creaating downloads for the media objects
+        ClientDownload *dl = NULL;
+        if (state == DlCreated) {
+            dl = new ClientDownload(priv->m_download->downloadManager(), mediaObjUrl, id[i].toInt(), Parallel
+                                                                                                   , priv->m_download->id() );
+        }
+        else
+            dl = new ClientDownload(priv->m_download->downloadManager(), id[i].toInt(), priv->m_download->id());
+
+        setValueForChild(DownloadInfo::EDlState, priv->m_mediaObjIdStateMap[id[i].toInt()], id[i].toInt());
+        addtoDownloadList(dl);
+        // re-constructing descriptor's mediaobj map
+        priv->m_currMediaObj->setAttribute("name", QVariant(mediaObjName));
+        int size = mediaObjSize;
+        priv->m_currMediaObj->setAttribute("size", QVariant(size));
+        priv->m_currMediaObj->setAttribute("type", QVariant(mediaObjContentType));
+        priv->m_currMediaObj->setAttribute("server",QVariant(mediaObjUrl));
+    }
+    ProductList product = priv->m_downloadDesc->productList();
+    getValue(DownloadInfo::EDlState,state);
+    if(state == DlCompleted)
+        priv->m_currDownloadIndex = product[priv->m_currProductIndex]->mediaCount()-1;
+    else
+        priv->m_currDownloadIndex = currentIndex();
+}
+
+void OMA2DownloadBackend::serializeData(ClientDownload* dl, int index)
+{
+    DM_PRIVATE(OMA2DownloadBackend);
+    ProductList product = priv->m_downloadDesc->productList();
+    // set OMA2 parent values in QSettings.
+    QString productName = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString(); // contenttype,url being written in dlbackend's constructor
+    setValue(DownloadInfo::EFileName, productName);
+
+    // set minimal MediaObject attributes in QSettings like name, size, url and contentType as these are the ones required for persistent storage.
+    QString mediaObjName = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjName).toString();
+    setValueForChild(DownloadInfo::EFileName, mediaObjName, dl->id());
+    long mediaObjSize = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjSize).toInt();
+    setValueForChild(DownloadInfo::ETotalSize, mediaObjSize, dl->id());
+    QString mediaObjContentType = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjType).toString();
+    setValueForChild(DownloadInfo::EContentType, mediaObjContentType, dl->id());
+    QString destPath = (download()->attributes().value(DlDestPath)).toString();
+    setValueForChild(DownloadInfo::EFinalPath, destPath, dl->id());
+    setValueForChild(DownloadInfo::EETag, priv->m_downloadCore->entityTag(), dl->id()); //not getting set check later
+}