videofeeds/mrssplugin/src/CIptvRssPlugin.cpp
changeset 0 96612d01cf9f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videofeeds/mrssplugin/src/CIptvRssPlugin.cpp	Mon Jan 18 20:21:12 2010 +0200
@@ -0,0 +1,1509 @@
+/*
+* 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:    RSS plugin.*
+*/
+
+
+
+
+#include <e32base.h>
+#include <sysutil.h>
+#include <centralrepository.h>
+#include <bautils.h>
+#include <xml/parser.h>
+
+#include "IptvDebug.h"
+#include "MIptvEpgVodCallback.h"
+#include "MIptvEpgLiveTvCallback.h"
+#include "CIptvTimer.h"
+#include <hash.h>
+
+#include "CIptvEpgService.h"
+#include "iptvlastwatcheddata.h"
+#include "iptvlastwatchedapi.h"
+
+#include "CIptvRssPlugin.h"
+#include "CIptvRssDownload.h"
+#include "CIptv3XmlContentHandler.h"
+
+_LIT8( KMimeType, "text/xml" );
+
+_LIT( KIptvRssFileName, "rss." );
+_LIT( KIptvThumbnailExtension, ".jpg" );
+_LIT( KIptvVCFGExtension, ".vcfg" );
+_LIT( KIptvRssSearchFileName, "rsssearch." );
+_LIT( KIptvAllFiles, "*.*" );
+_LIT8( KIptvHexByteFormatStr, "%02x" );
+
+const TInt64 KIptvRssUpdateSuccesInterval( 60 );
+const TInt64 KIptvRssUpdateFailedInterval( 0 );
+const TInt KIptvExtensionMaxSize( 5 );
+
+const TInt KIptvRssPluginFreeSpace( 512000 ); // 500 KB
+
+static const TInt KReadAtOnceLength( 1000 );
+
+const TInt KIptvTime_200_microsecond( 200 );
+
+const TInt KIptvHexCharInByte( 2 );
+/**
+* Enable this flag to update feed from local XML file. The path
+* to XML file is defined with KIptvLocalTestFeed variable below.
+*/
+//#define IPTV_RSS_LOCAL_TEST
+
+#ifdef IPTV_RSS_LOCAL_TEST
+_LIT( KIptvLocalTestFeed, "C:\\videofeed.xml" );
+#warning Local feed test flag IPTV_RSS_LOCAL_TEST has been defined!!!
+#endif
+
+// ======== MEMBER FUNCTIONS ========
+
+// --------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::ConstructL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL( "RSS Plugin --- CIptvRssPlugin::ConstructL" );
+
+    User::LeaveIfError( iFs.Connect() );
+    iDownload = CIptvRssDownload::NewL( *this, iFs, *iXmlContentHandler );
+    iThumbnailDlAllowed = ThumbnailDlAllowedL();
+
+    if ( iThumbnailDlAllowed )
+        {
+        IPTVLOGSTRING_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::ConstructL --- Thumbnail downloading is allowed!" );
+        }
+    else
+        {
+        IPTVLOGSTRING_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::ConstructL --- Thumbnail downloading is not allowed!" );
+        }
+
+    iParserIdle = CIdle::NewL( CActive::EPriorityIdle );
+    iXmlContentHandler = CIptvXmlContentHandler::NewL( *this );
+    iParser = CParser::NewL( KMimeType, *iXmlContentHandler );
+    }
+
+// --------------------------------------------------------------------------
+// Two-phased constructor.
+// Create instance of concrete ECOM interface implementation
+// --------------------------------------------------------------------------
+//
+CIptvRssPlugin* CIptvRssPlugin::NewL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL( "RSS Plugin --- CIptvRssPlugin::NewL" );
+
+    CIptvRssPlugin* self = new( ELeave ) CIptvRssPlugin();
+    CleanupStack::PushL( self );
+
+    self->ConstructL();
+
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// Destructor
+// --------------------------------------------------------------------------
+//
+CIptvRssPlugin::~CIptvRssPlugin()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::~CIptvRssPlugin" );
+
+    delete iItem;
+    delete iParser;
+    delete iDownload;
+    delete iParserIdle;
+    delete iXmlContentHandler;
+    delete iXmlFileContent;
+    delete iStartTimer;
+    delete iMD5Calculator;
+    iDlQueue.ResetAndDestroy();
+    iIconList.ResetAndDestroy();
+    iPreviouslyDownloadedAddresses.ResetAndDestroy();
+    iPreviouslyDownloadedPaths.ResetAndDestroy();
+
+    iFs.Close();
+    iVodCallback = NULL;
+    }
+
+// --------------------------------------------------------------------------
+// C++ default constructor
+// --------------------------------------------------------------------------
+//
+CIptvRssPlugin::CIptvRssPlugin() :
+    iXmlContentHandler( NULL ),
+    iParser( NULL ),
+    iParserIdle( NULL ),
+    iDownload( NULL ),
+    iVodCallback( NULL ),
+    iXmlFileContent( NULL ),
+    iStartTimer( NULL ),
+    iServiceId( 0 ),
+    iItem( NULL ),
+    iDlThumbnail( EFalse ),
+    iThumbnailDlAllowed( EFalse ),
+    iParsingFailed( EFalse )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::CIptvRssPlugin" );
+    }
+
+// --------------------------------------------------------------------------
+// From CIptvEpgPluginInterface
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::RunPlugin()
+    {
+    IPTVLOGSTRING_LOW_LEVEL( "RSS Plugin --- CIptvRssPlugin::RunPlugin" );
+
+    // Timer removes UI jamming in update sequence.
+    if ( !iStartTimer )
+        {
+        TRAP_IGNORE( iStartTimer =
+            CIptvTimer::NewL( CActive::EPriorityUserInput, *this ) );
+        }
+
+    if ( iStartTimer )
+        {
+        if ( !iStartTimer->IsActive() )
+            {
+            iStartTimer->After( KIptvTime_200_microsecond );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Delayed plugin start.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::TimerExpired( CIptvTimer* /* aTimer */ )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "CIptvRssPlugin --- CIptvRssPlugin::TimerExpired" );
+
+    TRAPD( error, DoTimerExpiredL() );
+    if ( error != KErrNone )
+        {
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::TimerExpired --- Leave while DoTimerExpiredL() = %d",
+            error );
+        TRAP( error, PluginFailedL( EIptvDlNoError ) );
+        if ( error != KErrNone )
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssPlugin::TimerExpired --- Leave while PluginFailedL() = %d",
+                error );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Delayed plugin start.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::DoTimerExpiredL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::DoTimerExpiredL" );
+
+    iDownload->InitializeL();
+    RunPluginL();
+    }
+
+// --------------------------------------------------------------------------
+//  Start plugin.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::RunPluginL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL( "RSS Plugin --- CIptvRssPlugin::RunPluginL" );
+
+    if ( ! iIsGroupOperation )
+        {
+        // If exist, delete old rss file
+        if ( BaflUtils::FileExists( iFs, iRssPath ) )
+            {
+            BaflUtils::DeleteFile( iFs, iRssPath );
+            }
+        }
+
+    // Clear obsolete thumbnail list.
+    iIconList.ResetAndDestroy();
+
+    // Clear already downloaded thumbnail list.
+    iPreviouslyDownloadedAddresses.ResetAndDestroy();
+    iPreviouslyDownloadedPaths.ResetAndDestroy();
+
+    // Before we even start the download, we check that there is sensible
+    // amount of free disk space for content guide and thumbnail files.
+    TBool checkResult( EFalse );
+    TRAPD(
+        checkError,
+        checkResult = SysUtil::DiskSpaceBelowCriticalLevelL(
+            &iFs, KIptvRssPluginFreeSpace, EDriveC ) );
+    if ( checkError != KErrNone || checkResult )
+        {
+        // Not enough space on disk, return immediately without any downloading.
+        if ( iIsSearchOperation )
+            {
+            iVodCallback->ErrorL( KIptvErrorRssSearchFailed, EIptvDlDiskFull );
+            }
+        else
+            {
+            iVodCallback->ErrorL( KIptvErrorEpgUpdateFailed, EIptvDlDiskFull );
+            }
+        return;
+        }
+
+    // Callback EPG manager that plugin is started
+    if ( iVodCallback )
+        {
+        iVodCallback->StartedL();
+        }
+    else
+        {
+        IPTVLOGSTRING_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::RunPluginL --- iVodCallback is NULL" );
+        }
+
+#ifndef IPTV_RSS_LOCAL_TEST
+
+    if ( ( EIptvRssAddServiceThumbnailToDlQueue == iAction ) ||
+         ( EIptvRssAddItemThumbnailToDlQueue == iAction ) )
+        {
+        // Download only previously listed thumbnails.
+        iParsingFailed = EFalse;
+        DownloadThumbnailsL();
+        }
+    else
+        {
+        // Download RSS-file.
+        iDownload->DownloadL(
+            iServiceAddress,
+            iRssPath,
+            EFalse,
+            KIptvEmptyDes,
+            iLastUpdated );
+        }
+
+#else
+
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::RunPluginL --- Parsing XML from local filesystem!" );
+    iRssPath.Copy( KIptvLocalTestFeed );
+    DownloadFinishedL( EDownloadSucceeded, EIptvDlNoError );
+
+#endif
+    }
+
+// --------------------------------------------------------------------------
+// Set callback pointer to MIptvEpgVodCallback. Plugin uses
+// MIptvEpgVodCallback interface to supply Epg data to system.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::SetVodCallback( MIptvEpgVodCallback* aVodCallback )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::SetVodCallback" );
+
+    iXmlContentHandler->SetVodCallback( aVodCallback );
+    iVodCallback = aVodCallback;
+    }
+
+// --------------------------------------------------------------------------
+// Set callback pointer to MIptvEpgLiveTvCallback.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::SetLiveTvCallback(
+    MIptvEpgLiveTvCallback* /*aLiveTvCallback*/ )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::SetLiveTvCallback" );
+    }
+
+// --------------------------------------------------------------------------
+// From CIptvEpgPluginInterface interface
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::SetServiceInformation(
+    CIptvEpgService* aService,
+    TBool aUseSearchAddress )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::SetServiceInformation" );
+
+    TIptvRSSAction action( EIptvRssService );
+    if ( aUseSearchAddress )
+        {
+        action = EIptvRssSearch;
+        }
+
+    TRAP_IGNORE( SetServiceInformationL( aService, action ) );
+    }
+
+// --------------------------------------------------------------------------
+// From CIptvEpgPluginInterface interface
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::SetServiceInformationL(
+    CIptvEpgService* aService,
+    TIptvRSSAction aAction )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::SetServiceInformationL" );
+
+    if ( !aService )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    iAction = aAction;
+    iIsGroupOperation  =
+        ( ( EIptvRssServiceGroup == iAction ) ||
+          ( EIptvRssAddServiceThumbnailToDlQueue == iAction ) ||
+          ( EIptvRssAddItemThumbnailToDlQueue == iAction ) );
+    iIsSearchOperation = ( EIptvRssSearch == iAction );
+
+    if ( ( EIptvRssAddServiceThumbnailToDlQueue == iAction ) ||
+         ( EIptvRssAddItemThumbnailToDlQueue == iAction ) )
+        {
+        CIptvDownloadItem* item = CIptvDownloadItem::NewL();
+        CleanupStack::PushL( item );
+        item->iThumbnailUrl.Copy( aService->iAddress );
+        item->iServiceThumbnail = ( EIptvRssAddServiceThumbnailToDlQueue == iAction );
+        item->iId = aService->iServiceId;
+        AddToDlQueueL( item );
+        CleanupStack::Pop( item );
+        }
+    else
+        {
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::SetServiceInformationL --- USERNAME %S",
+            &aService->iUserName );
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::SetServiceInformationL --- PASSWORD %S",
+            &aService->iPassword );
+
+        iServiceId = aService->iServiceId;
+        if ( iIsSearchOperation )
+            {
+            iServiceAddress.Copy( aService->SearchUrl() );
+            }
+        else
+            {
+            iServiceAddress.Copy( aService->iAddress );
+            }
+
+        iDownload->SetServiceInformation( aService );
+
+        if ( iIsGroupOperation )
+            {
+            HBufC* path = HBufC::NewLC( KIptvMaxPath );
+            TPtr16 pathPtr = path->Des();
+            TBuf<KIptvCAContentUrlLength> url;
+            url.Copy( iServiceAddress );
+
+            // Get pathname for vcfg file.
+            BuildUniqueuPathNameL(
+                url,
+                EIptvPathTmp,
+                KIptvVCFGExtension,
+                ETrue,
+                pathPtr );
+
+            iRssPath.Copy( *path );
+            CleanupStack::PopAndDestroy( path );
+            }
+        else
+            {
+            // Get RSS temp file path
+            TRAP_IGNORE( CIptvUtil::GetPathL( iFs, EIptvPathTmp, iRssPath ) );
+
+            if ( iIsSearchOperation )
+                {
+                iRssPath.Append( KIptvRssSearchFileName );
+                }
+            else
+                {
+                iRssPath.Append( KIptvRssFileName );
+                }
+
+            TBuf<KIptvMaxPath> service;
+            service.Num( TInt64( iServiceId ) );
+            iRssPath.Append( service );
+            }
+
+        iLastUpdated = aService->iLastUpdated;
+
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::SetServiceInformation --- RSS temp file : %S",
+            &iRssPath );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Handles download finished.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::DownloadFinishedL( TInt aState, TIptvDlError aError )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::DownloadFinishedL" );
+
+    TBuf<1> empty;
+
+    if ( !iDlThumbnail )
+        {
+        switch ( aState )
+            {
+            case EDownloadFailed:
+                {
+                IPTVLOGSTRING_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssPlugin::DownloadFinishedL --- EDownloadFailed" );
+                PluginFailedL( aError );
+                }
+                break;
+
+            case EDownloadSucceeded:
+                {
+                IPTVLOGSTRING_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssPlugin::DownloadFinishedL --- EDownloadSucceeded" );
+                if ( iIsGroupOperation )
+                    {
+                    // This is used for group VCFG file download indication.
+                    iVodCallback->UpdateServiceThumbnailL( iRssPath, ETrue );
+                    }
+                else
+                    {
+                    ParseL();
+                    }
+                }
+                break;
+
+            case EDownloadNoNeed:
+            case EDownloadAlreadyDownloaded:
+                {
+                IPTVLOGSTRING_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssPlugin::DownloadFinishedL --- EDownloadNoNeed" );
+                // When rss file has not been changed, also thumnails are
+                // assumed not having been changed.
+                if ( iIsGroupOperation )
+                    {
+                    iVodCallback->ErrorL(
+                        KIptvContentUpdateCompleted,
+                        EIptvDlNoErrorUpToDate );
+                    iVodCallback->UpdateServiceThumbnailL( iRssPath, ETrue );
+                    }
+                else
+                    {
+                    PluginSucceededL();
+                    }
+                }
+                break;
+
+            default:
+                break;
+            }
+        }
+    else
+        {
+        if ( iItem )
+            {
+            if ( iItem->iServiceThumbnail )
+                {
+                switch ( aState )
+                    {
+                    case EDownloadFailed:
+                        {
+                        IPTVLOGSTRING_LOW_LEVEL(
+                            "RSS Plugin --- CIptvRssPlugin::DownloadFinishedL --- Service thumbnail download finished --- EDownloadFailed" );
+                        iVodCallback->UpdateServiceThumbnailL( empty, EFalse );
+
+                        // Thumbnail file id is not used
+                        TUint32 iconFileId( 0 );
+                        iVodCallback->UpdateCategoryIconL(
+                            iItem->iId, iconFileId, empty, EFalse );
+                        }
+                        break;
+
+                    case EDownloadSucceeded:
+                    case EDownloadNoNeed:
+                        // Set as already downloaded only first time,
+                        // when really done it.
+                        SetAlreadyDownloadedPathL();
+                    //lint -fallthrough intended here
+                    case EDownloadAlreadyDownloaded:
+                        {
+                        IPTVLOGSTRING2_LOW_LEVEL(
+                            "RSS Plugin --- CIptvRssPlugin::DownloadFinishedL --- Service thumbnail %S",
+                            &iDownloadPath );
+                        iVodCallback->UpdateServiceThumbnailL(
+                            iDownloadPath, EFalse );
+
+                        // Thumbnail file id is not used
+                        TUint32 iconFileId( 0 );
+                        iVodCallback->UpdateCategoryIconL(
+                            iItem->iId,
+                            iconFileId,
+                            iDownloadPath,
+                            EFalse );
+                        iVodCallback->ErrorL(
+                            KIptvServiceThumbnailDownloaded,
+                            iServiceId );
+                        }
+                        break;
+
+                    default:
+                        break;
+                    }
+                }
+            else
+                {
+                switch ( aState )
+                    {
+                    case EDownloadFailed:
+                        {
+                        IPTVLOGSTRING_LOW_LEVEL(
+                            "RSS Plugin:: --- CIptvRssPlugin::DownloadFinishedL --- Content thumbnail download finished --- EDownloadFailed" );
+                        // Thumbnail file id is not used
+                        TUint32 iconFileId( 0 );
+                        iVodCallback->UpdateContentIconL(
+                            iItem->iId,
+                            iconFileId,
+                            empty,
+                            EFalse );
+                        }
+                        break;
+
+                    case EDownloadSucceeded:
+                    case EDownloadNoNeed:
+                        // Set as already downloaded only first time,
+                        // when really done it.
+                        SetAlreadyDownloadedPathL();
+                    //lint -fallthrough intended here
+                    case EDownloadAlreadyDownloaded:
+                        {
+                        IPTVLOGSTRING2_LOW_LEVEL(
+                            "RSS Plugin:: --- CIptvRssPlugin::DownloadFinishedL --- Content thumbnail %S",
+                            &iDownloadPath );
+                        // Thumbnail file id is not used
+                        TUint32 iconFileId( 0 );
+                        iVodCallback->UpdateContentIconL(
+                            iItem->iId,
+                            iconFileId,
+                            iDownloadPath,
+                            EFalse );
+                        if ( iIsSearchOperation )
+                            {
+                            iVodCallback->ErrorL(
+                                KIptvRssSearchContentThumbnailDownloaded,
+                                iItem->iId );
+                            }
+                        else
+                            {
+                            iVodCallback->ErrorL(
+                                KIptvContentThumbnailDownloaded,
+                                iItem->iId );
+                            }
+                        }
+                        break;
+
+                    default:
+                        break;
+                    }
+                }
+            }
+
+        iDlThumbnail = EFalse;
+        DownloadThumbnailsL();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Set plugin failed.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::PluginFailedL( TIptvDlError aError )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin:: --- CIptvRssPlugin::PluginFailedL" );
+
+    TTime valid( KIptvRssUpdateFailedInterval );
+
+    if ( iParsingFailed )
+        {
+        if ( iIsSearchOperation )
+            {
+            iVodCallback->ErrorL(
+                KIptvErrorRssSearchFailed, KIptvRssParserError );
+            }
+        else
+            {
+            iVodCallback->ErrorL(
+                KIptvErrorEpgUpdateFailed, KIptvRssParserError );
+            }
+        }
+    else
+        {
+        if ( iIsSearchOperation )
+            {
+            iVodCallback->ErrorL( KIptvErrorRssSearchFailed, aError );
+            }
+        else
+            {
+            iVodCallback->ErrorL( KIptvErrorEpgUpdateFailed, aError );
+            }
+        }
+
+    iVodCallback->FinishedL( valid );
+    }
+
+// --------------------------------------------------------------------------
+// Set plugin succeeded.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::PluginSucceededL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin:: --- CIptvRssPlugin::PluginSucceededL" );
+
+    TInt64 ms;
+    ms = KIptvMinuteAsMicrosecond * KIptvRssUpdateSuccesInterval;
+    TTime valid( ms );
+
+    if ( iIsSearchOperation )
+        {
+        iVodCallback->ErrorL( KIptvErrorRssSearchSucceed, 0 );
+        }
+    else
+        {
+        iVodCallback->ErrorL( KIptvErrorEpgUpdateSuccessed, 0 );
+        }
+
+    iVodCallback->FinishedL( valid );
+    }
+
+// --------------------------------------------------------------------------
+// Parse EPG data.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::ParseL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL( "RSS Plugin:: --- CIptvRssPlugin::ParseL" );
+
+    TRAPD( err, StartParsingXmlFileL( iRssPath ) );
+    if ( err != KErrNone )
+        {
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::ParseL --- Leave while Parse() = %d",
+            err );
+        PluginFailedL( EIptvDlNoError );
+        }
+
+#ifndef IPTV_RSS_LOCAL_TEST
+
+    // If exist, delete downloaded rss file.
+    if ( BaflUtils::FileExists( iFs, iRssPath ) )
+        {
+        BaflUtils::DeleteFile( iFs, iRssPath );
+        }
+
+#endif
+
+    }
+
+// --------------------------------------------------------------------------
+// Parse EPG data.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::StartParsingXmlFileL( const TDesC& aFileName )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::StartParsingXmlFileL" );
+
+    RFile phile;
+    User::LeaveIfError( phile.Open( iFs, aFileName, EFileRead ) );
+    CleanupClosePushL( phile );
+    TInt size( 0 );
+    User::LeaveIfError( phile.Size( size ) );
+    delete iXmlFileContent;
+    iXmlFileContent = NULL;
+    if ( 0 < size )
+        {
+        iXmlFileContent = HBufC8::NewL( size );
+        TPtr8 fileContentPtr = iXmlFileContent->Des();
+        User::LeaveIfError( phile.Read( fileContentPtr ) );
+        size = iXmlFileContent->Length();
+        }
+    CleanupStack::PopAndDestroy( &phile );
+
+    // There was at least some content in the file
+    if ( 0 < size )
+        {
+        iCurrentParsePosition = 0;
+        iParser->ParseBeginL();
+        if ( iParserIdle->IsActive() )
+            {
+            iParserIdle->Cancel();
+            }
+        TCallBack cb( ParseIdleCallback, this );
+        iParserIdle->Start( cb );
+        }
+    else
+        {
+        iParsingFailed = ETrue;
+        PluginFailedL( EIptvDlContentNotFound );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Static entry point for CIdle callback.
+// --------------------------------------------------------------------------
+//
+TInt CIptvRssPlugin::ParseIdleCallback( TAny* aPluginImpl )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::ParseIdleCallback" );
+
+    CIptvRssPlugin* self = static_cast<CIptvRssPlugin*> ( aPluginImpl );
+    if ( self )
+        {
+        return self->HandleParseIdleCallback();
+        }
+    else
+        {
+        return NULL;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Add thumbnail to download queue.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::AddToDlQueueL( const CIptvDownloadItem* aItem )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::AddToDlQueueL" );
+
+    iDlQueue.AppendL( aItem );
+    }
+
+// --------------------------------------------------------------------------
+// Download thumbnails from download queue.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::DownloadThumbnailsL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::DownloadThumbnailsL" );
+
+    if ( iParsingFailed )
+        {
+        PluginFailedL( EIptvDlNoError );
+        return;
+        }
+
+    iDlThumbnail = ETrue;
+    TBool download( EFalse );
+    TBool loop( ETrue );
+    while ( loop )
+        {
+        download = EFalse;
+        TInt count( iDlQueue.Count() );
+        if ( count > 0 )
+            {
+            delete iItem;
+            iItem = NULL;
+            iItem = iDlQueue[0];
+            iDlQueue.Remove( 0 );
+
+            if ( iItem )
+                {
+                iServiceAddress.Copy( iItem->iThumbnailUrl );
+
+                // Create variable for thumbnail path
+                HBufC* path = HBufC::NewLC( KIptvMaxPath );
+                TPtr16 pathPtr = path->Des();
+
+                // If downloading service thumbnail
+                if ( iItem->iServiceThumbnail )
+                    {
+                    TBool doDownload( EFalse );
+
+                    if ( ! iIsSearchOperation )
+                        {
+                        doDownload = ETrue;
+                        }
+                    else
+                        {
+                        // we do nothing here. We dont want to download service
+                        // thumbnails for search results
+                        }
+
+                    // Download service thumbnail only for "normal" vod.
+                    // When doing search service thumbnail is not downloaded.
+                    if ( doDownload )
+                        {
+                        // Get pathname for service thumbnail.
+                        BuildUniqueuPathNameL(
+                            iItem->iThumbnailUrl,
+                            EIptvPathService,
+                            KIptvThumbnailExtension,
+                            EFalse,
+                            pathPtr );
+
+                        // If exists, add it to thumbnail list.
+                        if ( BaflUtils::FileExists( iFs, *path ) )
+                            {
+                            HBufC* srvIcon = HBufC::NewLC( path->Length() );
+                            TPtr16 srvIconPtr = srvIcon->Des();
+                            srvIconPtr.Copy( *path );
+                            iIconList.AppendL( srvIcon );
+                            CleanupStack::Pop( srvIcon );
+                            }
+
+                        loop = EFalse;
+                        download = ETrue;
+                        iDownloadPath.Copy( *path );
+                        IPTVLOGSTRING2_LOW_LEVEL(
+                            "RSS Plugin --- CIptvRssPlugin::DownloadThumbnailsL --- Downloading service thumbnail -> %S",
+                            &iDownloadPath );
+                        }
+                    else
+                        {
+                        loop = ETrue;
+                        download = EFalse;
+                        }
+                    }
+                else
+                    {
+                    if ( iThumbnailDlAllowed )
+                        {
+                        if ( iIsSearchOperation )
+                            {
+                            // Get pathname for search thumbnail.
+                            BuildUniqueuPathNameL(
+                                iItem->iThumbnailUrl,
+                                EIptvPathRssSearchThumbnail,
+                                KIptvThumbnailExtension,
+                                ETrue,
+                                pathPtr );
+                            }
+                        else if ( iIsGroupOperation )
+                            {
+                            // Get pathname for item thumbnail.
+                            BuildUniqueuPathNameL(
+                                iItem->iThumbnailUrl,
+                                EIptvPathService,
+                                KIptvThumbnailExtension,
+                                ETrue,
+                                pathPtr );
+                            }
+                        else
+                            {
+                            // Get pathname for item thumbnail.
+                            BuildUniqueuPathNameL(
+                                iItem->iThumbnailUrl,
+                                EIptvPathRssThumbnail,
+                                KIptvThumbnailExtension,
+                                ETrue,
+                                pathPtr );
+                            }
+
+                        loop = EFalse;
+                        download = ETrue;
+                        iDownloadPath.Copy( *path );
+                        IPTVLOGSTRING2_LOW_LEVEL(
+                            "RSS Plugin --- CIptvRssPlugin::DownloadThumbnailsL ---  Downloading content thumbnail -> %S",
+                            &iDownloadPath );
+                        }
+                    }
+                CleanupStack::PopAndDestroy( path );
+                }
+            }
+        else
+            {
+            loop = EFalse;
+            PluginSucceededL();
+            if ( EIptvRssService == iAction )
+                {
+                RemoveObsoleteIconsL();
+                }
+
+            // Clear already downloaded thumbnail list.
+            iPreviouslyDownloadedAddresses.ResetAndDestroy();
+            iPreviouslyDownloadedPaths.ResetAndDestroy();
+            }
+        }
+
+    if ( download )
+        {
+        // Get address from possible previously downloaded.
+        HBufC* alreadyDownloaded = GetAlreadyDownloadedPath();
+        if ( NULL == alreadyDownloaded )
+            {
+            TRAPD(
+                dlError,
+                iDownload->DownloadL(
+                    iServiceAddress,
+                    iDownloadPath,
+                    ETrue,
+                    KIptvEmptyDes,
+                    iLastUpdated ) );
+
+            // Starting of thumbnail download can fail for example because of
+            // invalid URL.
+            if ( dlError != KErrNone )
+                {
+                DownloadFinishedL( EDownloadFailed, EIptvDlGeneral );
+                }
+            }
+        else
+            {
+            // When already downloaded, use it.
+            if ( 0 != iDownloadPath.CompareF( *alreadyDownloaded ) )
+                {
+                BaflUtils::CopyFile( iFs, *alreadyDownloaded, iDownloadPath );
+                }
+
+            // Retain old Thumbnail and remove it from list.
+            HBufC* fileName = HBufC::NewLC( iDownloadPath.Length() );
+            fileName->Des().Copy( iDownloadPath );
+            RemoveIconFromList( fileName, EFalse );
+            CleanupStack::PopAndDestroy( fileName );
+
+            // Signaling must be done async to avoid recursive looping.
+            iDownload->SkipCurrentDownloadAsyncL();
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Keep track of already downloaded thumbnails to avoid to redownload.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::SetAlreadyDownloadedPathL()
+    {
+
+#ifdef _DEBUG
+
+    // Debug print filename and url.
+    TBuf<KIptvMaxPath> debugFileName;
+    debugFileName.Copy( iDownloadPath );
+
+    TBuf<KIptvMaxPath> debugUrl;
+    debugUrl.Copy( iServiceAddress );
+
+    IPTVLOGSTRING3_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::SetAlreadyDownloadedPathL --- Set to already downloaded: %S From: %S",
+        &debugFileName,
+        &debugUrl );
+
+#endif
+
+    // Append new service address.
+    TInt len( iServiceAddress.Length() );
+    HBufC8* addr = HBufC8::NewLC( len );
+    TPtr8 addrPtr = addr->Des();
+    addrPtr.Copy( iServiceAddress );
+    iPreviouslyDownloadedAddresses.AppendL( addr );
+    CleanupStack::Pop( addr );
+
+    // Append corresponding path.
+    len = iDownloadPath.Length();
+    HBufC* path = HBufC::NewLC( len );
+    TPtr16 pathPtr = path->Des();
+    pathPtr.Copy( iDownloadPath );
+    iPreviouslyDownloadedPaths.AppendL( path );
+    CleanupStack::Pop( path );
+    }
+
+// --------------------------------------------------------------------------
+// Keep track of already downloaded thumbnails to avoid to redownload.
+// --------------------------------------------------------------------------
+//
+HBufC* CIptvRssPlugin::GetAlreadyDownloadedPath()
+    {
+    HBufC* alreadyDownloaded( NULL );
+
+    TInt icon( -1 );
+
+    // Find address from list.
+    for ( TInt i = 0;
+          ( i < iPreviouslyDownloadedAddresses.Count() ) && ( -1 == icon );
+          i++ )
+        {
+        if ( 0 == iServiceAddress.CompareF( *iPreviouslyDownloadedAddresses[i] ) )
+            {
+            icon = i;
+            }
+        }
+
+    // When found, return it, otherwise append new one to the list.
+    if ( icon >= 0 )
+        {
+        if ( iPreviouslyDownloadedPaths.Count() > icon )
+            {
+            alreadyDownloaded = iPreviouslyDownloadedPaths[icon];
+
+#ifdef _DEBUG
+
+            // Debug print filename and url.
+            TBuf<KIptvMaxPath> debugFileName;
+            debugFileName.Copy( *alreadyDownloaded );
+
+            TBuf<KIptvMaxPath> debugUrl;
+            debugUrl.Copy( iServiceAddress );
+
+            IPTVLOGSTRING3_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssPlugin::GetAlreadyDownloadedPathL --- Already downloaded: %S From: %S",
+                &debugFileName,
+                &debugUrl );
+
+#endif
+
+            }
+        }
+
+    return alreadyDownloaded;
+    }
+
+// --------------------------------------------------------------------------
+// Handle idle callback functionality.
+// --------------------------------------------------------------------------
+//
+TInt CIptvRssPlugin::HandleParseIdleCallback()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::HandleParseIdleCallback" );
+
+    // By default add KReadAtOnceLength to current parse position
+    TInt lengthToBeExtracted( KReadAtOnceLength );
+    TBool isLastPart( EFalse );
+
+    // Dealing with last part of the data in the buffer
+    if ( ( iCurrentParsePosition + lengthToBeExtracted ) >
+         iXmlFileContent->Length() )
+        {
+        lengthToBeExtracted =
+            iXmlFileContent->Length() - iCurrentParsePosition;
+        isLastPart = ETrue;
+        }
+
+    // Get next data part to be parsed
+    TPtr8 midPtr = iXmlFileContent->Des().MidTPtr(
+        iCurrentParsePosition, lengthToBeExtracted );
+    TInt err( KErrNone );
+
+    // Trap possible leave. If there was something, wrong, just stop parsing
+    TRAP( err, iParser->ParseL( midPtr ) );
+
+    TInt retVal( 0 );
+    // ParseL went just fine
+    if ( err == KErrNone )
+        {
+        // We are dealing with last part of the data -> let's not call this
+        // callback again
+        if ( isLastPart )
+            {
+            // If some leave occured, just ignore it
+            TRAP( err, iParser->ParseEndL() );
+            iCurrentParsePosition = 0;
+
+#ifndef IPTV_RSS_LOCAL_TEST
+
+            if ( iThumbnailDlAllowed && ( EIptvRssService == iAction ) )
+                {
+                // We will start thumbnail downloading. Lets list
+                // current icons for comparing them with new available.
+                TRAP_IGNORE( ListCurrentIconsL() )
+                }
+
+            TRAP( err, DownloadThumbnailsL() );
+
+#else
+
+            TRAP_IGNORE( PluginSucceededL() );
+
+#endif // IPTV_RSS_LOCAL_TEST
+
+            }
+        // There will still be more data to be parsed in the buffer
+        else
+            {
+            iCurrentParsePosition += KReadAtOnceLength;
+            retVal = 1;
+            }
+        }
+    // ParseL leaved. Tell manager, that we have finished our job
+    else
+        {
+        TRAP( err, PluginFailedL( EIptvDlNoError ) );
+        retVal = 0;
+        }
+
+    return retVal;
+    }
+
+// --------------------------------------------------------------------------
+// Check is thumbnail download allowed.
+// --------------------------------------------------------------------------
+//
+TBool CIptvRssPlugin::ThumbnailDlAllowedL() const
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::ThumbnailDlAllowedL" );
+
+    TBool allow( EFalse );
+    CRepository* cenRep = CRepository::NewL( KIptvCenRepUid );
+    if ( cenRep )
+        {
+        CleanupStack::PushL( cenRep );
+        TInt value;
+        TInt error = cenRep->Get( KIptvCenRepVoDThumbnailsKey, value );
+        if ( error == KErrNone && value == 1 )
+            {
+            allow = ETrue;
+            }
+        CleanupStack::PopAndDestroy( cenRep );
+        }
+
+    return allow;
+    }
+
+// --------------------------------------------------------------------------
+// XML parsing failed.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::SetParsingFailed()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::SetParsingFailed" );
+
+    iParsingFailed = ETrue;
+    }
+
+// --------------------------------------------------------------------------
+// Content update completed.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::ContentUpdateCompletedL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::ContentUpdateCompletedL" );
+
+    iVodCallback->ContentUpdateCompletedL();
+
+    if ( EIptvRssService == iAction )
+        {
+        iVodCallback->ErrorL( KIptvThumbnailCount, iDlQueue.Count() );
+        }
+    else if ( EIptvRssSearch == iAction )
+        {
+        iVodCallback->ErrorL( KIptvRssSearchThumbnailCount, iDlQueue.Count() );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// Set first update.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::SetFirstUpdate( TBool /*aFirstUpdate*/ )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::SetFirstUpdate" );
+    }
+
+// --------------------------------------------------------------------------
+// Build unique pathname for download object.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::BuildUniqueuPathNameL(
+    const TDesC& aUrl,
+    const TIptvPathSelection aPathSelection,
+    const TDesC& aDefaultExtension,
+    const TBool aGenerateName,
+    TPtr aPathName )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::BuildUniqueuPathNameL" );
+
+    // Lets get files type extension ex. .jpg, vcgf, ...
+    TInt urlLength( aUrl.Length() );
+    TInt index( aUrl.LocateReverse( '.' ) );
+    TInt extensionLength( 0 );
+
+    if ( ( urlLength - index ) < KIptvExtensionMaxSize )
+        {
+        extensionLength = urlLength - index;
+        }
+
+    // Get path for download object.
+    if ( ( EIptvPathService == aPathSelection ) ||
+         ( EIptvPathTmp == aPathSelection ) )
+        {
+        CIptvUtil::GetPathL( iFs, aPathSelection, aPathName );
+        }
+    // Item thumbnail must be hashed to keep track on it.
+    else
+        {
+        CIptvUtil::GetPathL( iFs, aPathSelection, iServiceId, aPathName );
+        }
+
+    if ( aGenerateName )
+        {
+        // Check whether md5 calculator is already constructed.
+        if ( !iMD5Calculator )
+            {
+            iMD5Calculator = CMD5::NewL();
+            }
+
+        // Calculate the 128 bit, 16 byte hash
+        iMD5Calculator->Reset();
+        TBuf8<KIptvMaxPath> buffer;
+        buffer.Copy( aUrl );
+
+        TPtrC8 hash = iMD5Calculator->Hash( buffer );
+
+        // Now print it as a 32 byte hex number
+        TBuf8<KIptvHexCharInByte> hexNumber;
+        for ( TInt i = 0; i < hash.Length(); i++ )
+            {
+            hexNumber.Zero();
+            hexNumber.Format( KIptvHexByteFormatStr, hash[i] );
+            aPathName.Append( hexNumber[0] );
+            aPathName.Append( hexNumber[1] );
+            }
+        }
+    else
+        {
+        // Service thumbnail can be with service identifier.
+        aPathName.AppendNum( static_cast<TUint64>( iServiceId ) );
+        }
+
+    // Add thumbnail file extension.
+    if ( extensionLength > 0 )
+        {
+        // If there was a extension for thumbnail use it
+        aPathName.Append( aUrl.Right( extensionLength ) );
+        }
+    else
+        {
+        // By default add .jpg extension
+        aPathName.Append( aDefaultExtension );
+        }
+
+#ifdef _DEBUG
+
+    // Debug print filename.
+    TBuf<KIptvMaxPath> debugFileName;
+    debugFileName.Copy( aPathName );
+
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::BuildUniqueuPathNameL Generated path name: %S",
+        &debugFileName );
+
+#endif
+
+    }
+
+// --------------------------------------------------------------------------
+// List current icons.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::ListCurrentIconsL()
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::ListCurrentIconsL" );
+
+    CDir* iconList( NULL );
+
+    // Create mask path for thumbnail search
+    HBufC* mask = HBufC::NewLC( KIptvMaxPath );
+    TPtr16 maskPtr = mask->Des();
+
+    // list item icons.
+    CIptvUtil::GetPathL( iFs, EIptvPathRssThumbnail, iServiceId, maskPtr );
+    TInt dirLen( mask->Length() );
+    maskPtr.Append( KIptvAllFiles );
+
+    if ( iFs.GetDir( maskPtr,
+                     KEntryAttNormal,
+                     ESortNone,
+                     iconList ) == KErrNone )
+        {
+        CleanupStack::PushL( iconList );
+
+        for ( TInt i = 0; i < iconList->Count(); i++ )
+            {
+            TInt len( ( *iconList )[i].iName.Length() );
+            HBufC* icon = HBufC::NewLC( dirLen + len );
+            TPtr16 iconPtr = icon->Des();
+            iconPtr.Copy( maskPtr.Mid( 0, dirLen ) );
+            iconPtr.Append( ( *iconList )[i].iName.Mid( 0, len ) );
+            iIconList.AppendL( icon );
+
+            CleanupStack::Pop( icon );
+            }
+
+        IPTVLOGSTRING2_LOW_LEVEL(
+            "RSS Plugin --- CIptvRssPlugin::ListCurrentIconsL found: %d",
+            iIconList.Count() );
+
+        CleanupStack::PopAndDestroy( iconList );
+        }
+
+    CleanupStack::PopAndDestroy( mask );
+    }
+
+// --------------------------------------------------------------------------
+// Remove icons stored to list. These icons are either from remove items or
+// all icons are decided to be removed.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::RemoveObsoleteIconsL()
+    {
+    IPTVLOGSTRING2_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::RemoveObsoleteIconsL Count       : %d",
+        iIconList.Count() );
+
+    HBufC* iconPath( NULL );
+
+    // Fetch thumbnail of last watched clip, when any.
+    CIptvLastWatchedApi* lastWatchedApi = CIptvLastWatchedApi::NewL();
+    CleanupStack::PushL( lastWatchedApi );
+
+    CIptvLastWatchedData* lwData = CIptvLastWatchedData::NewL();
+    if ( lwData )
+        {
+        CleanupStack::PushL( lwData );
+        TInt err( KErrNone );
+        TRAPD( leaveErr, err = lastWatchedApi->GetLastWatchedDataL( *lwData ) );
+
+        if ( KErrNone == leaveErr && KErrNone == err )
+            {
+            // Fetch thumbnail, no need to put it to cleanup stack.
+            iconPath = HBufC::NewL( lwData->IconPath().Length() );
+            iconPath->Des().Copy( lwData->IconPath() );
+            }
+        CleanupStack::PopAndDestroy( lwData );
+        }
+    CleanupStack::PopAndDestroy( lastWatchedApi );
+
+    for ( TInt icon = 0; icon < iIconList.Count(); icon++ )
+        {
+        TBool wasLastWatched( EFalse );
+
+        // Check whether thumbnail belongs to last watched clip.
+        if ( iconPath )
+            {
+            if ( 0 == iIconList[icon]->Des().CompareF( *iconPath ) )
+                {
+                wasLastWatched = ETrue;
+                }
+            }
+
+#ifdef _DEBUG
+
+        // Debug print filename.
+        TBuf<KIptvMaxPath> debugFileName;
+        debugFileName.Copy( iIconList[icon]->Des() );
+        if ( wasLastWatched )
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssPlugin::RemoveObsoleteIconsL Thumbnail of last watched clip saved: %S",
+                &debugFileName );
+            }
+        else
+            {
+            IPTVLOGSTRING2_LOW_LEVEL(
+                "RSS Plugin --- CIptvRssPlugin::RemoveObsoleteIconsL Thumbnail deleted: %S",
+                &debugFileName );
+            }
+
+#endif
+
+        if ( !wasLastWatched )
+            {
+            // Delete list thumbnail.
+            iFs.Delete( iIconList[icon]->Des() );
+            }
+        }
+
+    if ( iconPath )
+        {
+        delete iconPath;
+        iconPath = NULL;
+        }
+
+    // Remove all icons from list.
+    iIconList.ResetAndDestroy();
+    }
+
+// --------------------------------------------------------------------------
+// Find thumbnail from list and delete it when found.
+// --------------------------------------------------------------------------
+//
+void CIptvRssPlugin::RemoveIconFromList(
+    const HBufC* aIconName,
+    TBool aDelete )
+    {
+    IPTVLOGSTRING_LOW_LEVEL(
+        "RSS Plugin --- CIptvRssPlugin::RemoveIconFromList" );
+
+    if ( aIconName && ( EIptvRssService == iAction ) )
+        {
+        TInt icon( -1 );
+
+        // Find icon from list.
+        for ( TInt i = 0; ( i < iIconList.Count() ) && ( -1 == icon ); i++ )
+            {
+            if ( 0 == iIconList[i]->Des().CompareF( *aIconName ) )
+                {
+                icon = i;
+                }
+            }
+
+        // When found, remove it.
+        if ( icon >= 0 )
+            {
+            if ( aDelete )
+                {
+
+#ifdef _DEBUG
+
+                // Debug print filename.
+                TBuf<KIptvMaxPath> debugFileName;
+                debugFileName.Copy( iIconList[icon]->Des() );
+                IPTVLOGSTRING2_LOW_LEVEL(
+                    "RSS Plugin --- CIptvRssPlugin::RemoveIconFromList --- Thumbnail deleted: %S",
+                    &debugFileName );
+
+#endif
+
+                // Delete list thumbnail.
+                iFs.Delete( iIconList[icon]->Des() );
+                }
+
+            // Remove thumbnail from list.
+            delete iIconList[icon];
+            iIconList.Remove( icon );
+            }
+        }
+    }