fotaapplication/fotaserver/src/FotaDlClient.cpp
author hgs
Fri, 15 Oct 2010 11:46:45 +0530
changeset 73 ae69c2e8bc34
parent 51 2e64dc50f295
permissions -rw-r--r--
201041

/*
 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). 
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description:   Fota download client 
 *
 */
#include <XQConversions>
#include "FotaDlClient.h"
#include "FotaDlMgrClient.h"

// -----------------------------------------------------------------------------
// The constructor of this class
// -----------------------------------------------------------------------------
DownloadClient::DownloadClient(DownloadManagerClient* Observer)
    {
    FLOG(_L("DownloadClient::DownloadClient >>"));
    
    iFotaDlMgrClient = Observer;
    iTotalSize = -1;
    iSpaceChecked = 0;
    iDownload = NULL;
    iClientinterrupted = false;
    iClientError = ErrorNone;
    iContentType = TUnknownType;
    
    FLOG(_L("DownloadClient::DownloadClient <<"));
    }

// -----------------------------------------------------------------------------
// The destructor of this class 
// -----------------------------------------------------------------------------
DownloadClient::~DownloadClient()
    {
    FLOG(_L("DownloadClient::~DownloadClient >>"));

    if (iDownload)
        {
        disconnect(iDownload, SIGNAL(downloadEvent(DownloadEvent *)), this,
                SLOT(DownloadEventRecieved(DownloadEvent *)));

        //Do not delete iDownload as it is owned by download manager.
        //delete iDownload;
        iDownload = NULL;
        }
    //Don't delete as it is not owned
    iFotaDlMgrClient = NULL;

    FLOG(_L("DownloadClient::~DownloadClient <<"));
    }

// -----------------------------------------------------------------------------
// Creates a single download with the download manager
// -----------------------------------------------------------------------------
TInt DownloadClient::CreateDownload(const QString &url, DownloadType type)
    {
    FLOG(_L("DownloadClient::CreateDownload >>"));

    TInt ret = ENotOk;

    iDownload = iFotaDlMgrClient->Manager()->createDownload(url, type);

    if (iDownload)
        {
        connect(iDownload, SIGNAL(downloadEvent(DownloadEvent *)), this,
                SLOT(DownloadEventRecieved(DownloadEvent *)));
        ret = EOk;
        }
    else
        {
        FLOG(_L("Download creation is unsuccessful!"));
        }

    FLOG(_L("DownloadClient::CreateDownload, ret = %d <<"), ret);
    return ret;
    }

// -----------------------------------------------------------------------------
// Sets the required attributes for the single download.
// -----------------------------------------------------------------------------
TInt DownloadClient::SetDownloadAttributes()
    {
    FLOG(_L("DownloadClient::SetDownloadAttributes >>"));

    int ret(EOk);

    iDownload->setAttribute(ProgressInterval, 100);
    iDownload->setAttribute(Priority, High);

    //Setting the default path
    iDownload->setAttribute(DestinationPath, DefaultPath);

    iDownload->setAttribute(FileName, PackageName);

    FLOG(_L("DownloadClient::SetDownloadAttributes, ret = %d <<"), ret);

    return ret;
    }

// -----------------------------------------------------------------------------
// Starts the single download. Download should be created and attributes set before this.
// -----------------------------------------------------------------------------
TInt DownloadClient::Start()
    {
    FLOG(_L("DownloadClient::Start >>"));

    iClientinterrupted = false;
    iDownload->start();

    FLOG(_L("DownloadClient::Start <<"));
    return EOk;

    }

// -----------------------------------------------------------------------------
// Gets the attribute of the single download
// -----------------------------------------------------------------------------
inline QVariant DownloadClient::GetDownloadAttribute(DownloadAttribute attr)
    {
    FLOG(_L("DownloadClient::GetDownloadAttribute >>"));

    QVariant val;

    val = iDownload->attribute(attr);

    FLOG(_L("DownloadClient::GetDownloadAttribute<<"));
    return val;
    }

// -----------------------------------------------------------------------------
// Pauses the single download.
// -----------------------------------------------------------------------------
TInt DownloadClient::Pause(TClientErrorType aReason)
    {
    FLOG(_L("DownloadClient::Pause >>"));

    iClientinterrupted = true;
    iClientError = aReason;

    iDownload->pause();

    FLOG(_L("DownloadClient::Pause <<"));
    return EOk;
    }

// -----------------------------------------------------------------------------
// Resumes the single download.
// -----------------------------------------------------------------------------
TInt DownloadClient::Resume()
    {
    FLOG(_L("DownloadClient::Resume >>"));

    int ret(ENotOk);
    iSpaceChecked = true;

    if (!iDownload)
        {
        QList<Download*> dls =
                iFotaDlMgrClient->Manager()->currentDownloads();
        int count = dls.count();
        FLOG(_L("Number of current downloads = %d"), count);

        if (count)
            {
            iDownload = dls[0];
            FLOG(_L("Connecting to download event"));
            connect(iDownload, SIGNAL(downloadEvent(DownloadEvent *)), this,
                    SLOT(DownloadEventRecieved(DownloadEvent *)));
            FLOG(_L("Connecting to download events done"));
            }

        }
    iClientinterrupted = false;
    iClientError = ErrorNone;

    if (iDownload)
        {
        FLOG(_L("B4 Download Start"));
        iDownload->start();
        ret = EOk;
        FLOG(_L("After Download Start"));
        }

    FLOG(_L("DownloadClient::Resume, ret = %d <<"), ret);
    return ret;
    }

// -----------------------------------------------------------------------------
// Cancels the single download.
// -----------------------------------------------------------------------------
TInt DownloadClient::Cancel(TClientErrorType aReason)
    {
    FLOG(_L("DownloadClient::Cancel >>"));

    iClientinterrupted = true;
    iClientError = aReason;

    iDownload->cancel();

    FLOG(_L("DownloadClient::Cancel <<"));
    return EOk;
    }

// -----------------------------------------------------------------------------
// Restarts the single download. This is equivalent to cancel and start on Download.
// -----------------------------------------------------------------------------
TInt DownloadClient::Restart()
    {
    FLOG(_L("DownloadClient::Restart >>"));

    QString path(NULL);
    int size = iTotalSize;
    TFreeSpace avail = iFotaDlMgrClient->GetSuitablePath(size, path);

    if (avail == EFitsToReservation || avail == EFitsToFileSystem)
        {
        //FLOG(_L("Space is available for download at %S"), TPtrC (reinterpret_cast<const TText*> (path.constData()),path.length()));
        
        if (iContentType == TOmaDL10Download)
            {
            ReadDescriptorData();
            }
        Resume();
        }
    else
        {
        FLOG(_L("Space not available. Download is stopped!"));
        TRAP_IGNORE(iFotaDlMgrClient->ShowDialogL(EFwDLNeedMoreMemory, size));
        }

    FLOG(_L("DownloadClient::Restart >>"));

    return EOk;
    }

// -----------------------------------------------------------------------------
// The slot which receives all the single download events.
// -----------------------------------------------------------------------------
bool DownloadClient::DownloadEventRecieved(DownloadEvent *event)
    {
    FLOG(_L("DownloadClient::event >>"));

    DownloadEvent::Event type = (DownloadEvent::Event) event->type();
    bool eventHandled = false;
    int err0(NoError);

    FLOG(_L("Download Event Type: %d"), type);

    switch (type)
        {
        case DownloadEvent::Started:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::Started"));
            iProgress = true;
            iDlState = Download::Created;

            eventHandled = true;
            break;
            }

        case DownloadEvent::HeadersReceived:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::HeadersReceived"));
            iProgress = true;
            iDlState = Download::Created;

            QString contenttype =
                    GetDownloadAttribute(ContentType).toString();
            HBufC* s_contenttype = XQConversions::qStringToS60Desc(contenttype);
            FLOG(_L("Content type received is %S"), s_contenttype);
            delete s_contenttype;

            iContentType = CheckContentType(contenttype);

            if (iContentType == THttpDownload)
                {
                FLOG(_L("Content type: Http; checking the size of download"));
                if (!iSpaceChecked)
                    {

                    iTotalSize = GetDownloadAttribute(TotalSize).toInt();

                    FLOG(_L("Size of the firmware update as received is %d"),
                            iTotalSize);

                    if (iTotalSize > 0)
                        {
                        QString path(NULL);

                        TFreeSpace avail = iFotaDlMgrClient->GetSuitablePath(
                                iTotalSize, path);

                        if (avail == EFitsToReservation || avail
                                == EFitsToFileSystem)
                            {
                            //FLOG(_L("Space is available for download at %S"),TPtrC (reinterpret_cast<const TText*> (path.constData()),path.length()));
                            iFotaDlMgrClient->DeleteDiskReservation(path);
                            iDownload->setAttribute(DestinationPath, path);
                            }
                        else
                            {
                            FLOG(
                                    _L("Space not available. Download is stopped!"));
                            Pause(NeedMoreMemory);
                            TRAP_IGNORE(iFotaDlMgrClient->ShowDialogL(EFwDLNeedMoreMemory));
                            break;
                            }

                        iSpaceChecked = true;
                        iFotaDlMgrClient->StartDownloadProgress(
                                QString::null, QString::null, iTotalSize);
                        }
                    }
                }
            else if (iContentType == TUnknownType)
                {
                FLOG(_L("Content type unknown; hence cancelling download !"));
                Cancel(InvalidContentType);
                }

            eventHandled = true;
            break;
            }

        case DownloadEvent::InProgress:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::InProgress"));

            iProgress = true;
            iDlState = Download::InProgress;
            UpdateDownloadProgress();

            eventHandled = true;
            break;
            }

        case DownloadEvent::Completed:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::Completed"));
            iProgress = false;
            iDlState = Download::Completed;
            iTotalSize = 0;
            UpdateDownloadProgress();

            eventHandled = true;
            break;
            }

        case DownloadEvent::Paused:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::Paused"));
            iProgress = false;
            iDlState = Download::Paused;

            eventHandled = true;
            break;
            }
        case DownloadEvent::Failed:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::Failed"));
            iProgress = false;
            iDlState = Download::Failed;

            eventHandled = true;
            break;
            }
        case DownloadEvent::Cancelled:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::Cancelled"));
            iProgress = false;
            iDlState = Download::Cancelled;

            eventHandled = true;
            break;
            }

        case DownloadEvent::NetworkLoss:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::NetworkLoss"));
            iProgress = false;
            iDlState = Download::Paused;

            eventHandled = true;
            break;
            }

        case DownloadEvent::Error:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::Error"));
            iProgress = false;
           // iDlState = (Download::State) GetDownloadAttribute(State).toInt();
            iDlState = Download::Failed;
            eventHandled = true;
            break;
            }

        case DownloadEvent::DescriptorReady:
            {
            FLOG(_L("DownloadEventRecieved - DownloadEvent::DescriptorReady"));
            iProgress = true;
            iDlState = Download::InProgress;
            iContentType = TOmaDL10Download;

            iTotalSize = GetDownloadAttribute(DescriptorSize).toInt();
            QString path(NULL);
            if (iTotalSize > 0)
                {

                TFreeSpace avail = iFotaDlMgrClient->GetSuitablePath(
                        iTotalSize, path);

                if (avail == EFitsToReservation || avail == EFitsToFileSystem)
                    {
                    //FLOG(_L("Space is available for download at %S"), TPtrC (reinterpret_cast<const TText*> (path.constData()),path.length()));
                    iFotaDlMgrClient->DeleteDiskReservation(path);
                    }
                else
                    {
                    FLOG(_L("Space not available. Download is stopped!"));
                    TRAP_IGNORE(iFotaDlMgrClient->ShowDialogL(EFwDLNeedMoreMemory));
                    break;
                    }
                }
            ReadDescriptorData();
            Resume();
            SetSubDownloadAttributes();

            eventHandled = true;
            break;
            }
        case DownloadEvent::CreatingConnection:
            {
            FLOG(
                    _L("DownloadEventRecieved - DownloadEvent::CreatingConnection"));
            iProgress = true;
            iDlState = Download::InProgress;

            eventHandled = true;
            break;
            }
        case DownloadEvent::ConnectionNeeded:
        case DownloadEvent::ConnectionDisconnected:
            {
            FLOG(
                    _L("DownloadEventRecieved - DownloadEvent::ConnectionNeeded/ConnectionDisconnected"));
            iProgress = false;
            iDlState = Download::Paused;
            err0 = ConnectionFailed;
            eventHandled = true;
            break;
            }

        default:
            {
            FLOG(_L("DownloadEventRecieved - Skipped this event: %d"), type);
            break;
            }
        }

    if (iProgress == false)
        {

        if (iClientinterrupted)
            {
            //Client has requested for cancellation. Hence provide the same error code
            err0 = iClientError;
            HandleClientInterrupt(iDlState, err0);
            }
        else
            {
            //Download Manager has cancelled download. Hence provide the last error code.
            if (err0 == NoError)
                err0 = GetDownloadAttribute(LastError).toInt();

            HandleDownloadComplete(iDlState, err0);
            }

        }

    FLOG(_L("DownloadClient::event <<"));

    return eventHandled;
    }

// -----------------------------------------------------------------------------
// Called to update the progress of download to fota server. This fetches the percentage
// of download from download manager.
// -----------------------------------------------------------------------------
inline void DownloadClient::UpdateDownloadProgress()
    {
    FLOG(_L("DownloadClient::UpdateDownloadProgress >>"));

    // Remaining size calculation
    int prog = GetDownloadAttribute(Percentage).toInt();
    iFotaDlMgrClient->UpdateDownloadProgress(prog);

    FLOG(_L("DownloadClient::UpdateDownloadProgress, progress = %d <<"), prog);
    }

// -----------------------------------------------------------------------------
// Called to read the OMA DL1.0 download descriptor. This will update the fota server with size and version.
// -----------------------------------------------------------------------------
void DownloadClient::ReadDescriptorData()
    {
    FLOG(_L("DownloadClient::ReadDescriptorData >>"));

    QString name = GetDownloadAttribute(DescriptorName).toString(); // "name" in OMA dd
    QString version = GetDownloadAttribute(DescriptorVersion).toString(); // "version" in OMA dd
    QString type = GetDownloadAttribute(DescriptorType).toString(); // "type" in OMA dd
    int size = GetDownloadAttribute(DescriptorSize).toInt(); // "size" in OMA dd
    QString vendor = GetDownloadAttribute(DescriptorVendor).toString(); // "vendor" in OMA dd
    QString description =
            GetDownloadAttribute(DescriptorDescription).toString(); // "description" in OMA dd
    QString nxturl = GetDownloadAttribute(DescriptorNextURL).toString(); // "nextURL" in OMA dd

    TDownloadType gottype = CheckContentType(type);

    if (gottype == THttpDownload)
        {
        iFotaDlMgrClient->StartDownloadProgress(name, version, size);
        }
    else
        {
        FLOG(
                _L("The content type in descriptor is not appropriate! Hence cancelling download"));
        Cancel(InvalidContentType);
        }

    FLOG(_L("DownloadClient::ReadDescriptorData <<"));
    }

// -----------------------------------------------------------------------------
// Called when download is complete, either successfully or unsuccessfully.
// The arguments to this function is read to know the actual status.
// -----------------------------------------------------------------------------
void DownloadClient::HandleDownloadComplete(Download::State dlstate, int err0)
    {
    FLOG(_L("DownloadClient::HandleDownloadComplete, idlstate = %d, err0 = %d>>"), dlstate, err0);

    iFotaDlMgrClient->HandleDownloadEvent(dlstate, err0);

    FLOG(_L("DownloadClient::HandleDownloadComplete <<"));
    }

// -----------------------------------------------------------------------------
// Called to handle the post download interrupt operation when client cancels/pauses download.
// -----------------------------------------------------------------------------
void DownloadClient::HandleClientInterrupt(Download::State dlstate, int err0)
    {
    FLOG(_L("DownloadClient::HandleClientInterrupt, idlstate = %d, err0 = %d >>"), dlstate, err0);

    iFotaDlMgrClient->HandleClientInterrupt(dlstate, err0);

    FLOG(_L("DownloadClient::HandleClientInterrupt <<"));
    }

// -----------------------------------------------------------------------------
// Called to validate the content type of the download as received in header.
// -----------------------------------------------------------------------------
TDownloadType DownloadClient::CheckContentType(const QString aContent)
    {
    FLOG(_L("DownloadClient::CheckContentType >>"));

    TDownloadType type(TUnknownType);

    QString semicollon(";");
    QString contenttype = aContent;

    int index = aContent.indexOf(semicollon, 0);

    if (index > 0)
        {
        contenttype.chop(aContent.length() - index);
        }

    if (contenttype.compare(ContentTypeHttp) == 0)
        type = THttpDownload;
    else if (contenttype.compare(ContentTypeOmaDl) == 0)
        type = TOmaDL10Download;

    FLOG(_L("DownloadClient::CheckContentType, type = %d<<"), type);

    return type;
    }

void DownloadClient::SetSubDownloadAttributes()
    {
    FLOG(_L("DownloadClient::SetSubDownloadAttributes >>"));

    QList<Download*> dls = iDownload->subDownloads();

    if (dls.count() > 0)
        {
        Download* subdl = dls[0];

        subdl->setAttribute(FileName, PackageName);
        }
    else
        {
        FLOG(_L("Error: There are no sub downloads!"));
        }

    FLOG(_L("DownloadClient::SetSubDownloadAttributes <<"));
    }

//End of file