utilities/downloadmanager/src/downloadmanagerclient.cpp
author hgs
Fri, 15 Oct 2010 17:30:59 -0400
changeset 16 3c88a81ff781
permissions -rw-r--r--
201041

/**
   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 "downloadmanagerclient.h"
#include "backgrounddownloadmanager.h"
#include "backgrounddownload.h"
#include <serviceipc.h>
#include <QTimer>
#include <QtNetwork>

class DownloadManagerClientPrivate
{
    DM_DECLARE_PUBLIC(DownloadManagerClient);
public:
    DownloadManagerClientPrivate();
    ~DownloadManagerClientPrivate();
    QString m_clientName;
    bool m_isConnected;
    int m_error;
    WRT::ServiceFwIPC* m_session;
    DownloadManager* m_downloadManager;
    QTimer* m_timer;
};

DownloadManagerClientPrivate::DownloadManagerClientPrivate()
{
    m_clientName = "";
    m_isConnected = false;
    m_error = 0;
    m_session = 0;
    m_downloadManager = 0;
    m_timer = 0;
}

DownloadManagerClientPrivate::~DownloadManagerClientPrivate()
{
    if (m_timer) {
        if (m_timer->isActive())
            m_timer->stop();
        delete m_timer;
        m_timer = 0;
    }

    if (m_session) {
        m_session->disconnect();
        delete m_session;
        m_session = 0;
    }
}

DownloadManagerClient::DownloadManagerClient(DownloadManager* downloadManager)
{
    DM_INITIALIZE(DownloadManagerClient);
    priv->m_downloadManager = downloadManager;
    priv->m_timer = new QTimer;
    priv->m_clientName = downloadManager->getAttribute(DlMgrClientName).toString();
    priv->m_session = new WRT::ServiceFwIPC(this);
    connect(priv->m_session, SIGNAL(error(int aError)), this, SLOT(setServerError(int error)));
    connect(priv->m_timer, SIGNAL(timeout()), this, SLOT(getEvents()));

    // establish communication with server
    initServer();
}

DownloadManagerClient::~DownloadManagerClient()
{
    DM_UNINITIALIZE(DownloadManagerClient);
}

bool DownloadManagerClient::initServer()
{
    DM_PRIVATE(DownloadManagerClient);

    // start server (if required) and connect to it
    connectToServer();

    if (priv->m_isConnected) {
        // set startup details - proxy, download path, progress mode
        // and attach to downloads
        setStartupInfo();

        // start timer to get events from server
        priv->m_timer->start(EVENTS_REQUEST_INTERVAL);
        priv->m_downloadManager->postEvent(ConnectedToServer, NULL);
    }

    return priv->m_isConnected;
}

bool DownloadManagerClient::connectToServer()
{
    DM_PRIVATE(DownloadManagerClient);
    if (priv->m_session) {
        int retry(2);
        for (;;)
        {
            priv->m_isConnected = priv->m_session->connect(DMSERVER);
            if (priv->m_isConnected) {
                break;
            }
            else {
                if (!priv->m_session->startServer(DMSERVER, DMSERVEREXE)) {
                    // start server failed.
                    break;
                }
            }
            if (0==--retry) {
                break;
            }
        }
    }
    if (!priv->m_isConnected) {
        delete priv->m_session;
        priv->m_session = 0;
    }

    return priv->m_isConnected;
}

void DownloadManagerClient::setStartupInfo()
{
    DM_PRIVATE(DownloadManagerClient);
    if (!priv->m_isConnected)
        return;

    if (priv->m_downloadManager) {
        // get data from download manager
        QNetworkProxy* proxy = priv->m_downloadManager->proxy();
        QString dlPath = priv->m_downloadManager->getAttribute(DlMgrDestPath).toString();
        int progressMode = priv->m_downloadManager->getAttribute(DlMgrProgressMode).toInt();
        int persistantMode = priv->m_downloadManager->getAttribute(DlMgrPersistantMode).toInt();
        QString data;

        // client name
        data.append(encodeString(priv->m_clientName));

        // proxy info
        if (proxy) {
            data.append(DM_MSG_DELIMITER);
            data.append(QString::number(SetProxy));
            data.append(DM_FIELD_DELIMITER);
            data.append(encodeString(proxy->hostName()));
            data.append(DM_FIELD_DELIMITER);
            data.append(QString::number(proxy->port()));
        }

        // download path
        data.append(DM_MSG_DELIMITER);
        data.append(QString::number(SetDownloadManagerAttribute));
        data.append(DM_FIELD_DELIMITER);
        data.append(QString::number(DlMgrDestPath));
        data.append(DM_FIELD_DELIMITER);
        data.append(encodeString(dlPath));

        // progress mode (quiet/non-quiet)
        data.append(DM_MSG_DELIMITER);
        data.append(QString::number(SetDownloadManagerAttribute));
        data.append(DM_FIELD_DELIMITER);
        data.append(QString::number(DlMgrProgressMode));
        data.append(DM_FIELD_DELIMITER);
        data.append(encodeString(QString::number(progressMode)));

        // persistant mode (active / inactive)
        data.append(DM_MSG_DELIMITER);
        data.append(QString::number(SetDownloadManagerAttribute));
        data.append(DM_FIELD_DELIMITER);
        data.append(QString::number(DlMgrPersistantMode));
        data.append(DM_FIELD_DELIMITER);
        data.append(encodeString(QString::number(persistantMode)));

        // send to sever
        if (priv->m_session->sendSync(QString::number(StartupInfo), data.toAscii()))
            priv->m_session->readAll();
    }
}

void DownloadManagerClient::setProxy(const QString& proxyServer, const int port)
{
    DM_PRIVATE(DownloadManagerClient);
    if (!priv->m_isConnected) {
        if (!initServer())
            return;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(encodeString(proxyServer));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(port));

    // send to sever
    if (priv->m_session->sendSync(QString::number(SetProxy), data.toAscii()))
        priv->m_session->readAll();
    else
        setServerError(WRT::ServiceFwIPC::EIPCError);
}

int DownloadManagerClient::createDownload(const QString& url, DownloadType type)
{
    DM_PRIVATE(DownloadManagerClient);
    int downloadId(INVALID_DL_ID);
    if (!priv->m_isConnected) {
        if (!initServer())
            return downloadId;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(encodeString(url));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(type));

    // send to sever
    if (priv->m_session->sendSync(QString::number(CreateDownload), data.toAscii())) {
        // expected response is
        // list[0] -> downloadId
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 1)
            downloadId = list[0].toInt();
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return downloadId;
}

bool DownloadManagerClient::attachToDownload(int dlId)
{
    DM_PRIVATE(DownloadManagerClient);
    bool status(false);
    if (!priv->m_isConnected) {
        if (!initServer())
            return status;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(dlId));

    // send to sever
    if (priv->m_session->sendSync(QString::number(AttachToDownload), data.toAscii())) {
        // expected response is
	// list[1] -> status
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 1) {
            status = list[0].toInt();
	}
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
	
    return status;
}

void DownloadManagerClient::removeDownload(int downloadId)
{
    DM_PRIVATE(DownloadManagerClient);
    if (!priv->m_isConnected) {
        if (!initServer())
            return;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(downloadId));

    // send to sever
    if (priv->m_session->sendSync(QString::number(RemoveDownload), data.toAscii()))
        priv->m_session->readAll();
    else
        setServerError(WRT::ServiceFwIPC::EIPCError);
}

void DownloadManagerClient::pauseAll()
{
    DM_PRIVATE(DownloadManagerClient);
    if (!priv->m_isConnected) {
        if (!initServer())
            return;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));

    // send to sever
    if (priv->m_session->sendSync(QString::number(PauseAll), data.toAscii()))
        priv->m_session->readAll();
    else
        setServerError(WRT::ServiceFwIPC::EIPCError);
}

void DownloadManagerClient::resumeAll()
{
    DM_PRIVATE(DownloadManagerClient);
    if (!priv->m_isConnected) {
        if (!initServer())
            return;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));

    // send to sever
    if (priv->m_session->sendSync(QString::number(ResumeAll), data.toAscii()))
        priv->m_session->readAll();
    else
        setServerError(WRT::ServiceFwIPC::EIPCError);
}

void DownloadManagerClient::removeAll()
{
    DM_PRIVATE(DownloadManagerClient);
    if (!priv->m_isConnected) {
        if (!initServer())
            return;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));

    // send to sever
    if (priv->m_session->sendSync(QString::number(RemoveAll), data.toAscii()))
        priv->m_session->readAll();
    else
        setServerError(WRT::ServiceFwIPC::EIPCError);
}

QVariant DownloadManagerClient::getDownloadManagerAttribute(DownloadManagerAttribute attr)
{
    DM_PRIVATE(DownloadManagerClient);
    QVariant returnValue;
    if (!priv->m_isConnected) {
        if (!initServer())
            return returnValue;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(attr));

    // send to sever
    if (priv->m_session->sendSync(QString::number(GetDownloadManagerAttribute), data.toAscii())) {
        // expected response is
        // list[0] -> attribute
        // list[1] -> value
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 2) {
            if (list[0] == QString::number(attr))
                returnValue = QVariant(list[1]);
        }
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return returnValue;
}

int DownloadManagerClient::setDownloadManagerAttribute(DownloadManagerAttribute attr, const QVariant& value)
{
    DM_PRIVATE(DownloadManagerClient);
    int returnValue(-1);
    if (!priv->m_isConnected) {
        if (!initServer())
            return returnValue;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(attr));
    data.append(DM_FIELD_DELIMITER);
    data.append(encodeString(value.toString()));

    // send to sever
    if (priv->m_session->sendSync(QString::number(SetDownloadManagerAttribute), data.toAscii())) {
        // expected response is
        // list[0] -> attribute
        // list[1] -> returnValue
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 2) {
            if (list[0] == QString::number(attr))
                returnValue = list[1].toInt();
        }
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return returnValue;
}

int DownloadManagerClient::startDownload(int dlId)
{
    DM_PRIVATE(DownloadManagerClient);
    int returnValue(-1);
    if (!priv->m_isConnected) {
        if (!initServer())
            return returnValue;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(dlId));

    // send to sever
    if (priv->m_session->sendSync(QString::number(StartDownload), data.toAscii())) {
        // expected response is
        // list[0] -> downloadId
        // list[1] -> returnValue
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 2) {
            if (list[0] == QString::number(dlId))
                returnValue = list[1].toInt();
        }
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return returnValue;
}

int DownloadManagerClient::pauseDownload(int dlId)
{
    DM_PRIVATE(DownloadManagerClient);
    int returnValue(-1);
    if (!priv->m_isConnected) {
        if (!initServer())
            return returnValue;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(dlId));

    // send to sever
    if (priv->m_session->sendSync(QString::number(PauseDownload), data.toAscii())) {
        // expected response is
        // list[0] -> downloadId
        // list[1] -> returnValue
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 2) {
            if (list[0] == QString::number(dlId))
                returnValue = list[1].toInt();
        }
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return returnValue;
}

int DownloadManagerClient::resumeDownload(int dlId)
{
    DM_PRIVATE(DownloadManagerClient);
    int returnValue(-1);
    if (!priv->m_isConnected) {
        if (!initServer())
            return returnValue;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(dlId));

    // send to sever
    if (priv->m_session->sendSync(QString::number(ResumeDownload), data.toAscii())) {
        // expected response is
        // list[0] -> downloadId
        // list[1] -> returnValue
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 2) {
            if (list[0] == QString::number(dlId))
                returnValue = list[1].toInt();
        }
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return returnValue;
}

int DownloadManagerClient::cancelDownload(int dlId)
{
    DM_PRIVATE(DownloadManagerClient);
    int returnValue(-1);
    if (!priv->m_isConnected) {
        if (!initServer())
            return returnValue;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(dlId));

    // send to sever
    if (priv->m_session->sendSync(QString::number(CancelDownload), data.toAscii())) {
        // expected response is
        // list[0] -> downloadId
        // list[1] -> returnValue
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 2) {
            if (list[0] == QString::number(dlId))
                returnValue = list[1].toInt();
        }
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return returnValue;
}

QVariant DownloadManagerClient::getDownloadAttribute(int dlId, DownloadAttribute attr)
{
    DM_PRIVATE(DownloadManagerClient);
    QVariant returnValue;
    if (!priv->m_isConnected) {
        if (!initServer())
            return returnValue;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(dlId));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(attr));

    // send to sever
    if (priv->m_session->sendSync(QString::number(GetDownloadAttribute), data.toAscii())) {
        // expected response is
        // list[0] -> downloadId
        // list[1] -> attribute
        // list[2] -> value
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 3) {
            if ((list[0] == QString::number(dlId)) &&
                (list[1] == QString::number(attr)))
                returnValue = QVariant(list[2]);
        }
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return returnValue;
}

int DownloadManagerClient::setDownloadAttribute(int dlId, DownloadAttribute attr, const QVariant& value)
{
    DM_PRIVATE(DownloadManagerClient);
    int returnValue(-1);
    if (!priv->m_isConnected) {
        if (!initServer())
            return returnValue;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(dlId));
    data.append(DM_FIELD_DELIMITER);
    data.append(QString::number(attr));
    data.append(DM_FIELD_DELIMITER);
    data.append(encodeString(value.toString()));

    // send to sever
    if (priv->m_session->sendSync(QString::number(SetDownloadAttribute), data.toAscii())) {
        // expected response is
        // list[0] -> downloadId
        // list[1] -> attribute
        // list[2] -> returnValue
        QByteArray bytes = priv->m_session->readAll();
        QStringList list = QString(bytes).split(DM_FIELD_DELIMITER);
        if (list.count() == 3) {
            if ((list[0] == QString::number(dlId)) &&
                (list[1] == QString::number(attr)))
                returnValue = list[2].toInt();
        }
    }
    else
    {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
    return returnValue;
}

// poll server for events
void DownloadManagerClient::getEvents()
{
    DM_PRIVATE(DownloadManagerClient);
    if (!priv->m_isConnected) {
        if (!initServer())
            return;
    }

    // create string to send
    QString data;
    data.append(encodeString(priv->m_clientName));

    // send to sever
    if (priv->m_session->sendSync(QString::number(GetEvents), data.toAscii())) {
        // expected response has a list of downloadmanager and download events
        QString eventMsg = priv->m_session->readAll();
        if (!eventMsg.isEmpty())
            processEvents(eventMsg);

        // start timer for getting next set of events
        priv->m_timer->start(EVENTS_REQUEST_INTERVAL);
    }
    else {
        setServerError(WRT::ServiceFwIPC::EIPCError);
    }
}

// process Download and DownloadManager events
void DownloadManagerClient::processEvents(QString eventMsg)
{
    DM_PRIVATE(DownloadManagerClient);

    // Separate out the fields of an event
    QStringList list = eventMsg.split(DM_FIELD_DELIMITER);
    if (list.count() >= 2) {
        QString eventName = list[0];
        // // check type of event
        if (list[0] == QString::number(EventDownloadManager)) {
            // Download Manager event
            DEventType type = (DEventType)list[1].toInt();
            // post event
            priv->m_downloadManager->postEvent(type, NULL);
        }
        else if (list[0] == QString::number(EventDownload)) {
            // Download event
            int dlId = list[1].toInt();
            DEventType type = (DEventType)list[2].toInt();
            BackgroundDownload* dl = dynamic_cast<BackgroundDownload*>(priv->m_downloadManager->findDownload(dlId));
            // post event
            if (dl)
                dl->postEvent(type, NULL);
        }
    }
}

// encode string so that it does not contain any communication delimiter
QString DownloadManagerClient::encodeString(const QString& inputString)
{
    QByteArray bytes = QUrl::toPercentEncoding(inputString);
    return bytes.data();
}

// get server connection/communication error
int DownloadManagerClient::serverError()
{
    DM_PRIVATE(DownloadManagerClient);
    return priv->m_error;
}

// set server IPC error
void DownloadManagerClient::setServerError(int error)
{
    DM_PRIVATE(DownloadManagerClient);
    priv->m_error = error;
    // client could have died
    // mark client as disconnected so that it can reconnect again
    priv->m_isConnected = false;
    if (priv->m_timer->isActive())
        priv->m_timer->stop();
    priv->m_downloadManager->postEvent(DisconnectedFromServer, NULL);
    priv->m_downloadManager->postEvent(ServerError, NULL);
}