videofeeds/mrssplugin/src/CIptvRssDownload.cpp
changeset 0 96612d01cf9f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videofeeds/mrssplugin/src/CIptvRssDownload.cpp	Mon Jan 18 20:21:12 2010 +0200
@@ -0,0 +1,1335 @@
+/*
+* Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+*
+*/
+
+
+
+
+#include <e32std.h>
+#include <sysutil.h>
+#include "IptvDebug.h"
+#include <bautils.h>
+#include "CIptvTimer.h"
+#include "CIptvRssDownload.h"
+#include "CIptvRssPlugin.h"
+#include "CIptvEpgService.h"
+#include "CIptv3XmlContentHandler.h"
+#include "ciptvxmldatetime.h"
+
+// 0x10281F1E is the uid of the IptvUtil dll. This is taken
+// into use by reason following:
+// There can be two simultaneous RSS downloads ongoing at the
+// same time; one for search and one for vod. Download manager
+// prevents simultaneous downloads if uid given during Connect
+// is already active. That's why we take another uid into use
+// to allow search operations to run simultaneously with the
+// normal vod update.
+const TUid KIptvSearchUid = { 0x10281F1E };
+
+const TInt KIptvMaxTimeoutInSeconds( 60 );
+const TInt KIptvMaxPauseInSeconds( 10 );
+
+const TInt KIptvTime_1_second( 1000000 );
+const TInt KIptvTime_200_microsecond( 200 );
+
+// ======== MEMBER FUNCTIONS ========
+
+// --------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::ConstructL()
+    {
+    iTimer = CIptvTimer::NewL( CActive::EPriorityUserInput, *this );
+    }
+
+// --------------------------------------------------------------------------
+// Two-phased constructor.
+// Create instance of concrete interface implementation
+// --------------------------------------------------------------------------
+//
+CIptvRssDownload* CIptvRssDownload::NewL(
+    CIptvRssPlugin& aPlugin,
+    RFs& aFs,
+    CIptvXmlContentHandler& aXmlContentHandler )
+    {
+    CIptvRssDownload* self = new( ELeave ) CIptvRssDownload(
+        aPlugin,
+        aFs,
+        aXmlContentHandler );
+    CleanupStack::PushL( self );
+
+    self->ConstructL();
+
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// Destructor
+// --------------------------------------------------------------------------
+//
+CIptvRssDownload::~CIptvRssDownload()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::~CIptvRssDownload" );
+
+    if ( iTimer )
+        {
+        if ( iTimer->IsActive() )
+            {
+            iTimer->Cancel();
+            }
+        delete iTimer;
+        iTimer = NULL;
+        }
+
+    Disconnect();
+
+    iService = NULL;
+
+    delete iDlDeleteTimer;
+    delete iFileName;
+    delete iUri;
+    delete iETag;
+
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::~CIptvRssDownload exit" );
+    }
+
+// --------------------------------------------------------------------------
+// C++ default constructor
+// --------------------------------------------------------------------------
+//
+CIptvRssDownload::CIptvRssDownload(
+    CIptvRssPlugin& aPlugin,
+    RFs& aFs,
+    CIptvXmlContentHandler& aXmlContentHandler ) :
+    iService( NULL ),
+    iPlugin( aPlugin ),
+    iThumbnail( EFalse ),
+    iDownloadId( 0 ),
+    iTimer( NULL ),
+    iConnected( EFalse ),
+    iState( ENormal ),
+    iPauseCounter( 0 ),
+    iFs( aFs ),
+    iXmlContentHandler( aXmlContentHandler )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// Start download.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::DownloadL(
+    const TDesC8& aUri,
+    const TDesC& aFileName,
+    TBool aThumbnail,
+    const TDesC& aETag,
+    const TTime& aLastUpdated )
+    {
+    if ( iState != ENormal && iState != EFinished )
+        {
+        IPTVLOGSTRING_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::DownloadL Busy Leave" );
+        User::Leave( KErrAlreadyExists );
+        }
+    if ( ( 0 == aFileName.Length() ) || ( 0 == aUri.Length() ) )
+        {
+        IPTVLOGSTRING_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::DownloadL Argument Leave" );
+        User::Leave( KErrArgument );
+        }
+    ChangeState( ENormal );
+
+#ifdef _DEBUG
+
+    // Debug print filename.
+    TBuf<KIptvMaxPath> debugFileName;
+    debugFileName.Copy( aFileName );
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::DownloadL aFileName :         %S",
+        &debugFileName );
+
+    // Debug print Uri.
+    TBuf<KIptvUrlMaxLength> debugUri;
+    debugUri.Copy( aUri );
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::DownloadL aUri :              %S",
+        &debugUri );
+
+#endif
+
+    // When header information is given, fist dowload will fetch these values
+    // for check. Thumbnail file must also exist to enable check.
+    iWaitingContentTypeCheck =
+        ( ( 0 != aETag.CompareC( KIptvEmptyDes ) ) ||
+          ( TTime( 0LL ) != aLastUpdated ) )  &&
+        !iDisableLastModifiedCheck &&
+        ( !aThumbnail || BaflUtils::FileExists( iFs, aFileName ) );
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::DownloadL Content type check: %d",
+        iWaitingContentTypeCheck );
+
+    // Store argument data for further use.
+    if ( iUri )
+        {
+        delete iUri;
+        iUri = NULL;
+        }
+    iUri = HBufC8::NewL( aUri.Length() );
+    iUri->Des().Copy( aUri );
+
+    if ( iFileName )
+        {
+        delete iFileName;
+        iFileName = NULL;
+        }
+    iFileName = HBufC::NewL( aFileName.Length() );
+    iFileName->Des().Copy( aFileName );
+
+    if ( iETag )
+        {
+        delete iETag;
+        iETag = NULL;
+        }
+    if ( 0 < aETag.Length() )
+        {
+        iETag = HBufC::NewL( aETag.Length() );
+        iETag->Des().Copy( aETag );
+        }
+
+    iLastUpdated = aLastUpdated;
+    iThumbnail = aThumbnail;
+
+    // When no check, old thumbnail can be removed at once.
+    if ( iThumbnail && iFileName && !iWaitingContentTypeCheck )
+        {
+        iPlugin.RemoveIconFromList( iFileName, ETrue );
+        }
+
+    // Create new download.
+    RHttpDownload& download =
+        iDownloadManager.CreateDownloadL( aUri );
+
+    // Set download attributes.
+    download.SetBoolAttribute( EDlAttrNoContentTypeCheck, !iWaitingContentTypeCheck );
+    SetAuthenticationInformationL( download );
+    if ( !iWaitingContentTypeCheck )
+        {
+        // Content check will not require filename and DownloadManager would anyway
+        // delete it.
+        download.SetStringAttribute( EDlAttrDestFilename, aFileName );
+        }
+
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::DownloadL Using IAP: %d",
+        iService->iIap );
+    User::LeaveIfError(
+        iDownloadManager.SetIntAttribute( EDlMgrIap, iService->iIap ) );
+
+    // Start download.
+    User::LeaveIfError( download.Start() );
+    download.GetIntAttribute( EDlAttrId, iDownloadId );
+    iDownloadIdValid = ETrue;
+    }
+
+// --------------------------------------------------------------------------
+// Restart download.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::DownloadL()
+    {
+    if ( iState != ENormal && iState != EFinished )
+        {
+        IPTVLOGSTRING_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::DownloadL Busy Leave" );
+        User::Leave( KErrAlreadyExists );
+        }
+    if ( !iFileName || !iUri )
+        {
+        IPTVLOGSTRING_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::DownloadL Argument Leave" );
+        User::Leave( KErrArgument );
+        }
+    ChangeState( ENormal );
+
+#ifdef _DEBUG
+
+    // Debug print filename.
+    TBuf<KIptvMaxPath> debugFileName;
+    debugFileName.Copy( iFileName->Des() );
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::DownloadL aFileName :         %S",
+        &debugFileName );
+
+#endif
+
+    iWaitingContentTypeCheck = EFalse;
+
+    // Create new download.
+    RHttpDownload& download =
+        iDownloadManager.CreateDownloadL( iUri->Des() );
+
+    // Set download attributes.
+    download.SetBoolAttribute( EDlAttrNoContentTypeCheck, ETrue );
+    SetAuthenticationInformationL( download );
+    download.SetStringAttribute( EDlAttrDestFilename, iFileName->Des() );
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::DownloadL Using IAP: %d",
+        iService->iIap );
+    User::LeaveIfError(
+        iDownloadManager.SetIntAttribute( EDlMgrIap, iService->iIap ) );
+
+    // Start download.
+    User::LeaveIfError( download.Start() );
+    download.GetIntAttribute( EDlAttrId, iDownloadId );
+    iDownloadIdValid = ETrue;
+    }
+
+// --------------------------------------------------------------------------
+// From MHttpDownloadMgrObserver.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::HandleDMgrEventL(
+    RHttpDownload& aDownload,
+    THttpDownloadEvent aEvent )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL" );
+
+    // In EThumbnail and ENoDiskSpace states we do not need to do anything
+    // for new events. We are just waiting for our timer to step in.
+    // When iTimer is NULL, we are shutting down.
+    if ( ( iState == EThumbnail ) || ( iState == ENoDiskSpace ) || !iTimer || iDlDeleteTimer )
+        {
+        return;
+        }
+
+    //lint -e{961} Else block not needed, default is no operation.
+    if ( iState == EPause )
+        {
+        iTimer->Cancel();
+        ChangeState( ENormal );
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL PAUSED %d SECONDS, NOW CONTINUING!",
+            iPauseCounter );
+        iPauseCounter = 0;
+        }
+    else if ( iState == EWaiting )
+        {
+        iTimer->Cancel();
+        ChangeState( ENormal );
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL WAITED EVENTS FROM DL-MANAGER %d SECONDS",
+            iPauseCounter );
+        iPauseCounter = 0;
+        }
+    else if ( iState == ETimeout )
+        {
+        if ( aEvent.iDownloadState == EHttpDlCreated )
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL download state was EHttpDlCreated." );
+            ChangeState( ENormal );
+            iPauseCounter = 0;
+            }
+        else
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL iState == ETimeout -> return" );
+            return;
+            }
+        }
+
+    TInt32 fileSizeReported = 0;
+    aDownload.GetIntAttribute( EDlAttrUserData, fileSizeReported );
+
+    // We keep checking file size until it is available in EDlAttrLength.
+    if ( fileSizeReported == 0 )
+        {
+        TInt32 fullSize = 0;
+
+        aDownload.GetIntAttribute( EDlAttrLength, fullSize );
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL  Full size: %d", fullSize );
+
+        if ( fullSize > 0 )
+            {
+            aDownload.SetIntAttribute( EDlAttrUserData, ETrue );
+
+            // For thumbnails, we check if size of file exceeds the maximum
+            // allowed. If it does, the file is not downloaded at all.
+            if ( iThumbnail && fullSize > KIptvRssMaxThumbnailSize )
+                {
+                IPTVLOGSTRING3_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL Thumbnail too big %d, max size %d, download cancelled!!!",
+                    fullSize,
+                    KIptvRssMaxThumbnailSize );
+
+#ifdef _DEBUG
+
+                    switch ( iState )
+                        {
+                        case ENormal:
+                            IPTVLOGSTRING_LOW_LEVEL(
+                                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL iState changed from ENormal -> EThumbnail" );
+                            break;
+
+                        case EThumbnail:
+                            IPTVLOGSTRING_LOW_LEVEL(
+                                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL iState changed from EThumbnail -> EThumbnail" );
+                            break;
+
+                        case EFinished:
+                            IPTVLOGSTRING_LOW_LEVEL(
+                                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL iState changed from EFinished -> EThumbnail" );
+                            break;
+
+                        default:
+                            IPTVLOGSTRING_LOW_LEVEL(
+                                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL iState changed from ? -> EThumbnail" );
+                            break;
+                        }
+
+#endif // _DEBUG
+
+                iState = EThumbnail;
+
+                if ( iTimer )
+                    {
+                    iTimer->Cancel();
+                    iTimer->After( KIptvTime_200_microsecond );
+                    return;
+                    }
+                }
+            // For all other files, those that will be actually downloaded,
+            // we check that we don't exceed critical disk space levels.
+            else
+                {
+                TBool checkResult = EFalse;
+                TRAPD( checkError, checkResult =
+                    SysUtil::DiskSpaceBelowCriticalLevelL(
+                        &iFs, static_cast<TInt64>(fullSize), EDriveC ) );
+                if ( checkError != KErrNone || checkResult )
+                    {
+                    IPTVLOGSTRING_LOW_LEVEL(
+                        "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL Disk space under critical level!!!" );
+
+                    ChangeState( ENoDiskSpace );
+
+                    if ( iTimer )
+                        {
+                        iTimer->Cancel();
+                        iTimer->After( KIptvTime_200_microsecond );
+                        return;
+                        }
+                    }
+
+#ifdef _DEBUG
+
+                else
+                    {
+                    IPTVLOGSTRING_LOW_LEVEL(
+                        "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL Disk space ok." );
+                    }
+
+#endif // _DEBUG
+
+                }
+            }
+        }
+
+    switch ( aEvent.iProgressState )
+        {
+        case EHttpContentTypeReceived:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpContentTypeReceived" );
+
+            // Fetch header info to find out whether item has bee updated.
+            TBuf<KMaxGeneralHeaderFieldLength> responseETag;
+            TBuf<KMaxGeneralHeaderFieldLength> responseModifiedSince;
+            aDownload.GetStringAttribute( EDlAttrResponseETag, responseETag );
+            aDownload.GetStringAttribute( EDlAttrEntityLastModified, responseModifiedSince );
+            iWaitingContentTypeCheck = EFalse;
+
+            // Compare header info.
+            TBool eTagMatch( EFalse );
+            if ( iETag )
+                {
+                if ( responseETag.Length() > 0 )
+                    {
+                    eTagMatch = ( responseETag.Compare( iETag->Des() ) == 0 );
+
+                    IPTVLOGSTRING2_LOW_LEVEL( "EDlAttrResponseETag :            %S",
+                        &responseETag );
+                    IPTVLOGSTRING2_LOW_LEVEL( "Local eTag valid :               %d",
+                        eTagMatch );
+                    }
+
+                delete iETag;
+                iETag = NULL;
+                iETag = HBufC::NewL( responseETag.Length() );
+                iETag->Des().Copy( responseETag );
+                }
+
+            TBool modifiedSinceMatch( EFalse );
+            if ( responseModifiedSince.Length() > 0 )
+                {
+                TTime lastUpdated( static_cast<TUint64>( 0 ) );
+
+                // Parse time string to TTime
+                HBufC* lastUpdatedStr = HBufC::NewLC( responseModifiedSince.Length() );
+                lastUpdatedStr->Des().Copy( responseModifiedSince );
+                CIptvXmlDateTime::ParseGmtL( lastUpdatedStr, lastUpdated );
+                CleanupStack::PopAndDestroy( lastUpdatedStr );
+
+                modifiedSinceMatch = lastUpdated <= iLastUpdated;
+
+#ifdef _DEBUG
+
+                // Debug print last updated info.
+                TBuf<KIptvEpgDbLastModifiedMaxLength> ecgDatePrint;
+                TBuf<KIptvEpgDbLastModifiedMaxLength> itemDatePrint;
+                _LIT( KIptvDatePrint, "%D%M%Y%/0%1%/1%2%/2%3%/3" );
+                iLastUpdated.FormatL( ecgDatePrint, KIptvDatePrint );
+                lastUpdated.FormatL( itemDatePrint, KIptvDatePrint );
+
+                TBuf<KIptvEpgDbLastModifiedMaxLength> ecgTimePrint;
+                TBuf<KIptvEpgDbLastModifiedMaxLength> itemTimePrint;
+                _LIT( KIptvTimePrint, "%-B%:0%J%:1%T%:2%S%.%*C4%:3%+B" );
+                iLastUpdated.FormatL( ecgTimePrint, KIptvTimePrint );
+                lastUpdated.FormatL( itemTimePrint, KIptvTimePrint );
+
+                IPTVLOGSTRING2_LOW_LEVEL( "EDlAttrEntityLastModified :      %S",
+                    &responseModifiedSince );
+                IPTVLOGSTRING3_LOW_LEVEL( "Local entity was last updated :  %S %S",
+                    &ecgDatePrint,
+                    &ecgTimePrint );
+                IPTVLOGSTRING3_LOW_LEVEL( "Server entity was last updated : %S %S",
+                    &itemDatePrint,
+                    &itemTimePrint );
+                IPTVLOGSTRING2_LOW_LEVEL( "Local entity valid :             %d",
+                    modifiedSinceMatch );
+
+#endif
+
+                iLastUpdated = lastUpdated;
+
+                }
+            else
+                {
+                iLastUpdated = TTime( static_cast<TUint64>( 0 ) );
+                }
+
+
+            if ( eTagMatch || modifiedSinceMatch )
+                {
+                // Download headers match, no download required.
+                IPTVLOGSTRING_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL: Headers match to previous." );
+                iDlStatus = EDownloadNoNeed;
+                iDlError  = EIptvDlNoError;
+
+                DeleteDownloadAsyncL();
+
+                // Retain old Thumbnail and remove it from list.
+                if ( iThumbnail && iFileName )
+                    {
+                    iPlugin.RemoveIconFromList( iFileName, EFalse );
+                    }
+                }
+            else
+                {
+                // Download headers do not match.
+                IPTVLOGSTRING_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL: Headers do not match." );
+                iDlStatus = EDownloadNeeded;
+                iDlError  = EIptvDlNoError;
+                ChangeState( ENormal );
+                iRestartDownload = ETrue;
+
+                // When service will not support header info, do not request it further.
+                if ( ( 0 ==  responseETag.Length() ) &&
+                     ( 0 == responseModifiedSince.Length() ) )
+                    {
+                    IPTVLOGSTRING_LOW_LEVEL(
+                        "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL: Further header check disabled." );
+                    iDisableLastModifiedCheck = ETrue; // Suppress further check
+                    }
+
+                DeleteDownloadAsyncL();
+
+                if ( iFileName )
+                    {
+                    // Delete old Thumbnail if exists and remove it from list.
+                    if ( iThumbnail )
+                        {
+                        iPlugin.RemoveIconFromList( iFileName, ETrue );
+                        }
+                    else
+                        {
+                        // Delete old file if exist.
+                        if ( BaflUtils::FileExists( iFs, iFileName->Des() ) )
+                            {
+                            iFs.Delete( iFileName->Des() );
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+
+        case EHttpProgNone:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgNone" );
+            }
+            break;
+
+        case EHttpStarted:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpStarted" );
+            }
+            break;
+
+        case EHttpProgCreatingConnection:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgCreatingConnection" );
+            }
+            break;
+
+        case EHttpProgConnectionNeeded:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgConnectionNeeded" );
+            }
+            break;
+
+        case EHttpProgConnected:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgConnected" );
+            }
+            break;
+
+        case EHttpProgConnectionSuspended:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgConnectionSuspended" );
+            }
+            break;
+
+        case EHttpProgDisconnected:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgDisconnected" );
+            }
+            break;
+
+        case EHttpProgDownloadStarted:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgDownloadStarted" );
+            }
+            break;
+
+        case EHttpContentTypeRequested:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpContentTypeRequested" );
+            }
+            break;
+
+        case EHttpProgSubmitIssued:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgSubmitIssued" );
+            }
+            break;
+
+        case EHttpProgResponseHeaderReceived:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgResponseHeaderReceived" );
+            }
+            break;
+
+        case EHttpProgResponseBodyReceived:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgResponseBodyReceived" );
+            }
+            break;
+
+        case EHttpProgRedirectedPermanently:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgRedirectedPermanently" );
+            }
+            break;
+
+        case EHttpProgRedirectedTemporarily:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgRedirectedTemporarily" );
+            }
+            break;
+
+        case EHttpProgDlNameChanged:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgDlNameChanged" );
+            }
+            break;
+
+        case EHttpProgContentTypeChanged:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgContentTypeChanged" );
+            }
+            break;
+
+        case EHttpProgCodDescriptorDownloaded:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgCodDescriptorDownloaded" );
+            }
+            break;
+
+        case EHttpProgCodDownloadStarted:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgCodDownloadStarted" );
+            }
+            break;
+
+        case EHttpProgCodDescriptorAccepted:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgCodDescriptorAccepted" );
+            }
+            break;
+
+        case EHttpProgCodLoadEnd:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgCodLoadEnd" );
+            }
+            break;
+
+        case EHttpProgSupportedMultiPart:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL HttpProgSupportedMultiPart" );
+            }
+            break;
+
+        case EHttpProgMovingContentFile:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgMovingContentFilep" );
+            }
+            break;
+
+        case EHttpProgContentFileMoved:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpProgContentFileMoved" );
+            }
+            break;
+
+        default:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL Unknown state" );
+            break;
+            }
+        }
+
+    switch ( aEvent.iDownloadState )
+        {
+        case EHttpDlCompleted:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlCompleted" );
+            iDlStatus = EDownloadSucceeded;
+            iDlError  = EIptvDlNoError;
+            DeleteDownloadAsyncL();
+            }
+            break;
+
+        case EHttpDlFailed:
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlFailed" );
+            // When header download failed, we can still retry actual download.
+            if ( iWaitingContentTypeCheck )
+                {
+                iDlStatus = EDownloadNeeded;
+                iDlError  = EIptvDlNoError;
+                ChangeState( ENormal );
+
+                // Delete old Thumbnail and remove it from list.
+                if ( iThumbnail && iFileName )
+                    {
+                    iPlugin.RemoveIconFromList( iFileName, ETrue );
+                    }
+
+                iRestartDownload = ETrue;
+                IPTVLOGSTRING_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL Further header check disabled." );
+                iDisableLastModifiedCheck = ETrue; // Suppress further check
+                iWaitingContentTypeCheck = EFalse;
+                DeleteDownloadAsyncL();
+                }
+            else
+                {
+                GetDownloadErrorCode( aDownload, iDlError );
+                // No state change, when only progress information.
+                if ( EIptvDlNoError != iDlError )
+                    {
+                    iDlStatus = EDownloadFailed;
+                    DeleteDownloadAsyncL();
+                    }
+                }
+            }
+            break;
+
+        case EHttpDlCreated:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlCreated" );
+            break;
+
+        case EHttpDlInprogress:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlInprogress" );
+            break;
+
+        case EHttpDlPaused:
+            {
+            // Ignore paused state when content type is received because download is finished earlier.
+            if ( aEvent.iProgressState != EHttpContentTypeReceived )
+                {
+                IPTVLOGSTRING_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlPaused" );
+
+                ChangeState( EPause );
+
+                if ( iTimer )
+                    {
+                    if ( !iTimer->IsActive() )
+                        {
+                        iTimer->After( KIptvTime_1_second );
+                        }
+                    }
+                }
+            }
+            break;
+
+        case EHttpDlMoved:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlMoved" );
+            break;
+
+        case EHttpDlMediaRemoved:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlMediaRemoved" );
+            break;
+
+        case EHttpDlMediaInserted:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlMediaInserted" );
+            break;
+
+        case EHttpDlPausable:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlPausable" );
+            break;
+
+        case EHttpDlNonPausable:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlNonPausable" );
+            break;
+
+        case EHttpDlDeleted:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlDeleted" );
+            break;
+
+        case EHttpDlAlreadyRunning:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlAlreadyRunning" );
+            break;
+
+        case EHttpDlDeleting:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlDeleting" );
+            break;
+
+        case EHttpDlCancelTransaction:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL EHttpDlCancelTransaction" );
+            break;
+
+        default:
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL Unknown state" );
+            break;
+        }
+
+    if ( iState == ENormal )
+        {
+        ChangeState( EWaiting );
+        if ( iTimer )
+            {
+            if ( !iTimer->IsActive() )
+                {
+                iTimer->After( KIptvTime_1_second );
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Set authentication information.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::SetAuthenticationInformationL(
+    RHttpDownload& aDownload ) const
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::SetAuthenticationInformation" );
+
+    User::LeaveIfError(
+        aDownload.SetStringAttribute( EDlAttrUsername, iUserName ) );
+    User::LeaveIfError(
+        aDownload.SetStringAttribute( EDlAttrPassword, iPassword ) );
+    }
+
+// --------------------------------------------------------------------------
+// Set service information.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::SetServiceInformation( CIptvEpgService* aService )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::SetServiceInformation" );
+
+    iService = aService;
+
+    if ( aService )
+        {
+        iUserName.Copy( aService->iUserName );
+        iPassword.Copy( aService->iPassword );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Initialize plugin.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::InitializeL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin  --- CIptvRssDownload::InitializeL" );
+
+    if ( !iConnected )
+        {
+        if ( iPlugin.IsSearchOperation() )
+            {
+            iDownloadManager.ConnectL( KIptvSearchUid, *this, ETrue );
+            }
+        else
+            {
+            iDownloadManager.ConnectL( iService->iUid, *this, ETrue );
+            }
+        iConnected = ETrue;
+        }
+
+    iDownloadManager.DeleteAll();
+    }
+
+// --------------------------------------------------------------------------
+// Disconnect download manager session.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::Disconnect()
+    {
+    IPTVLOGSTRING_LOW_LEVEL( "RSS Plugin  --- CIptvRssDownload::Disconnect" );
+
+    if ( iConnected )
+        {
+        iDownloadManager.DeleteAll();
+        iDownloadManager.RemoveObserver( *this );
+        iDownloadManager.Close();
+
+        iConnected = EFalse;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Get download error code.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::GetDownloadErrorCode(
+    RHttpDownload& aDownload, TIptvDlError& aError ) const
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin  --- CIptvRssDownload::GetDownloadErrorCode" );
+
+    TInt32 errorId;
+    TInt32 globalErrorId;
+    aDownload.GetIntAttribute( EDlAttrErrorId, errorId );
+    aDownload.GetIntAttribute( EDlAttrGlobalErrorId, globalErrorId );
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::GetDownloadErrorCode:: DL error ID: %d",
+        errorId );
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::GetDownloadErrorCode:: DL global error ID: %d",
+        globalErrorId );
+
+    switch ( errorId )
+        {
+        case EConnectionFailed:
+            {
+            aError = EIptvDlConnectionFailed;
+            }
+            break;
+
+        case EHttpAuthenticationFailed:
+            {
+            aError = EIptvDlAuthFailed;
+            }
+            break;
+
+        case EProxyAuthenticationFailed:
+            {
+            aError = EIptvDlProxyAuthFailed;
+            }
+            break;
+
+        case EDestFileInUse:
+            {
+            aError = EIptvDlDestFileInUse;
+            }
+            break;
+
+        case EBadUrl:
+            {
+            aError = EIptvDlBadUrl;
+            }
+            break;
+
+        case EMMCRemoved:
+            {
+            aError = EIptvDlMmcRemoved;
+            }
+            break;
+
+        case EDiskFull:
+            {
+            aError = EIptvDlDiskFull;
+            }
+            break;
+
+        case EObjectNotFound:
+        case ETransactionFailed:
+            {
+            aError = EIptvDlContentNotFound;
+            }
+            break;
+
+        default:
+            {
+            aError = EIptvDlGeneral;
+            }
+            break;
+        }
+
+    switch ( globalErrorId )
+        {
+        case EHttpResponsePaymentRequired:
+            {
+            aError = EIptvDlContentNotFound;
+            }
+            break;
+
+        case EHttpResponseContinue:
+        case EHttpResponseSwitchingProtocols:
+            {
+            aError = EIptvDlNoError;
+            }
+            break;
+
+        default:
+            // Default should not affect aError, due only special cases
+            // are handled here.
+            break;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Timer expired.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::TimerExpired( CIptvTimer* aTimer )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::TimerExpired" );
+
+    if ( aTimer == iDlDeleteTimer )
+        {
+        delete iDlDeleteTimer;
+        iDlDeleteTimer = NULL;
+        if ( iDownloadIdValid )
+            {
+            DeleteCurrentDownload();
+            }
+
+        if ( iRestartDownload )
+            {
+            // Create new download.
+            iRestartDownload = EFalse;
+            if ( iFileName )
+                {
+                TRAP_IGNORE( DownloadL() )
+                }
+        }
+        else if ( iState == EThumbnail )
+            {
+            TRAP_IGNORE( iPlugin.DownloadThumbnailsL() )
+            }
+        else
+            {
+            TRAP_IGNORE( iPlugin.DownloadFinishedL( iDlStatus, iDlError ) )
+            }
+
+        return;
+        }
+
+    //lint -e{961} Else block not needed, default is no operation.
+    if ( iState == EPause )
+        {
+        iPauseCounter++;
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::TimerExpired PAUSED %d SECONDS",
+            iPauseCounter );
+
+        if ( iPauseCounter > KIptvMaxPauseInSeconds )
+            {
+            IPTVLOGSTRING_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::TimerExpired PAUSED TOO LONG, PLUGIN FAILED, PROBABLY WLAN CONNECTION LOST" );
+            iDlStatus = EDownloadFailed;
+            iDlError  = EIptvDlConnectionFailed;
+            TRAP_IGNORE( DeleteDownloadAsyncL() )
+            }
+        else
+            {
+            if ( iTimer && !iTimer->IsActive() )
+                {
+                iTimer->After( KIptvTime_1_second );
+                }
+            }
+        }
+    else if ( iState == EWaiting )
+        {
+        iPauseCounter++;
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::TimerExpired WAITING EVENTS FROM DL-MANAGER %d SECONDS",
+            iPauseCounter );
+
+        if ( iPauseCounter > KIptvMaxTimeoutInSeconds )
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::TimerExpired TIMEOUT %d REACHED!",
+                KIptvMaxTimeoutInSeconds );
+            iDlStatus = EDownloadFailed;
+            iDlError  = EIptvDlNoError;
+            TRAP_IGNORE( DeleteDownloadAsyncL() )
+            }
+        else
+            {
+            if ( iTimer && !iTimer->IsActive() )
+                {
+                iTimer->After( KIptvTime_1_second );
+                }
+            }
+        }
+    else if ( iState == EThumbnail )
+        {
+        TRAP_IGNORE( DeleteDownloadAsyncL() )
+        }
+    else if ( iState == ENoDiskSpace )
+        {
+        IPTVLOGSTRING_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssDownload::TimerExpired No disk space, deleting download." );
+        iDlStatus = EDownloadFailed;
+        iDlError  = EIptvDlDiskFull;
+        TRAP_IGNORE( DeleteDownloadAsyncL() )
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Finish and delete current download.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::DeleteCurrentDownload()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::DeleteCurrentDownload" );
+
+    ChangeState( EFinished );
+
+    TInt count = iDownloadManager.CurrentDownloads().Count();
+    TInt32 downloadId;
+    for ( TInt i = 0; i < count; i++ )
+        {
+        iDownloadManager.CurrentDownloads()[i]->GetIntAttribute(
+            EDlAttrId, downloadId );
+        if ( downloadId == iDownloadId )
+            {
+            RHttpDownload* dl = iDownloadManager.CurrentDownloads()[i];
+            if ( dl )
+                {
+                dl->Delete();
+                iDownloadIdValid = EFalse;
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Change the state of the download.
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::ChangeState( TInt aState )
+    {
+    switch ( iState )
+        {
+        case ENormal:
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload:: iState changed -> ENormal, was: %d", iState );
+            break;
+            }
+
+        case EPause:
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload:: iState changed -> EPause, was: %d", iState );
+            break;
+            }
+
+        case EThumbnail:
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload:: iState changed -> EThumbnail, was: %d", iState );
+            break;
+            }
+
+        case EWaiting:
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload:: iState changed -> EWaiting, was: %d", iState );
+            break;
+            }
+
+        case EFinished:
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload:: iState changed -> EFinished, was: %d", iState );
+            break;
+            }
+
+        case ETimeout:
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload:: iState changed -> ETimeout, was: %d", iState );
+            break;
+            }
+
+        case ENoDiskSpace:
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssDownload::HandleDMgrEventL iState changed -> ENoDiskSpace, was: %d", iState );
+            break;
+            }
+
+        default:
+            {
+            break;
+            }
+        }
+
+    iState = aState;
+    }
+
+// --------------------------------------------------------------------------
+// CIptvRssDownload::SkipCurrentDownloadAsyncL
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::SkipCurrentDownloadAsyncL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssDownload::SkipCurrentDownloadAsyncL" );
+
+    iDlStatus = EDownloadAlreadyDownloaded;
+    iDlError  = EIptvDlNoError;
+
+    DeleteDownloadAsyncL();
+    }
+
+// --------------------------------------------------------------------------
+// CIptvRssDownload::DeleteDownloadAsyncL
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::DeleteDownloadAsyncL()
+    {
+    delete iDlDeleteTimer;
+    iDlDeleteTimer = NULL;
+    iDlDeleteTimer = CIptvTimer::NewL( 0, *this );
+    iDlDeleteTimer->After( 1 ); //just to make it async
+    }
+
+// --------------------------------------------------------------------------
+// Getter for ETag
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::GetETag( TDes& aETag ) const
+    {
+    if ( iETag )
+        {
+        aETag.Copy( iETag->Des() );
+        }
+    else
+        {
+        aETag.Copy( KIptvEmptyDes );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Getter for LastModifiedSince
+// --------------------------------------------------------------------------
+//
+void CIptvRssDownload::GetLastModifiedSince( TTime& aLastUpdated ) const
+    {
+    aLastUpdated = iLastUpdated;
+    }