codhandler/codeng/src/FileSaver.cpp
changeset 0 dd21522fd290
child 8 7c90e6132015
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/codhandler/codeng/src/FileSaver.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,743 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of 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: 
+*      Implementation of class CFileSaver.   
+*      
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "FileSaver.h"
+#include "CodBuffStorage.h"
+#include "CodLoadObserver.h"
+#include "RFeatMgr.h"
+#include "CodUtil.h"
+#include "CodLogger.h"
+#include "CodError.h"
+#include "CodPanic.h"
+#include "DrmHandler.h"
+#include "CodData.h"
+
+#include <f32file.h>
+#include <HttpDownloadMgrCommon.h>
+#include <DocumentHandler.h>
+#include <pathinfo.h>
+#include <MGXFileManagerFactory.h>
+#include <CMGXFileManager.h>
+#include <DcfEntry.h>
+#include <DcfRep.h>
+
+const TInt KDefaultStorageBufferSize = 128 * 1024;
+const TInt KDefaultStorageBufferSizePD = 16 * 1024;
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CFileSaver::NewL()
+// ---------------------------------------------------------
+//
+CFileSaver* CFileSaver::NewL
+        (
+        const TDesC8& aType,
+        RFs& aFs,
+        CDocumentHandler& aDocHandler,
+        const TFileName& aTempPath,
+        const TFileName& aRootPath,
+        const TFileName& aFname
+        )
+    {
+    CFileSaver* saver = new (ELeave) CFileSaver
+        ( aType, aFs, aDocHandler, aTempPath, aRootPath, aFname );
+    CleanupStack::PushL( saver );
+    saver->ConstructL();
+    CleanupStack::Pop( saver );
+    return saver;
+    }
+// ---------------------------------------------------------
+// CFileSaver::ConstructL()
+// ---------------------------------------------------------
+//
+void CFileSaver::ConstructL()
+    {
+    CCodSaver::ConstructL();
+    iBufferSize =  KDefaultStorageBufferSize ;
+    iProgressiveDownload = EFalse ;
+    
+    iStorage = CCodBuffStorage::NewL(this);
+    }
+
+// ---------------------------------------------------------
+// CFileSaver::CFileSaver()
+// ---------------------------------------------------------
+//
+CFileSaver::CFileSaver
+    (
+    const TDesC8& aType,
+    RFs& aFs,
+    CDocumentHandler& aDocHandler,
+    const TFileName& aTempPath,
+    const TFileName& aRootPath,
+    const TFileName& aFname
+    )
+: CCodSaver( aType ),
+  iDocHandler( aDocHandler ),
+  iFs( aFs ),
+  iTempPath( aTempPath ),
+  iRootPath( aRootPath ),
+  iFname( aFname)
+    {
+    CLOG(( ECodEng, 2, _L("*** CFileSaver::CFileSaver") ));
+    }
+  
+// ---------------------------------------------------------
+// CFileSaver::~CFileSaver()
+// ---------------------------------------------------------
+//
+CFileSaver::~CFileSaver()
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::~CFileSaver") ));
+    delete iDrmHandler;
+    delete iStorage;
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::~CFileSaver") ));
+    }
+
+// ---------------------------------------------------------
+// CFileSaver::OpenStoreL()
+// ---------------------------------------------------------
+//
+void CFileSaver::OpenStoreL()
+    {
+    CLOG(( ECodEng, 2, _L("CFileSaver::OpenStoreL") ));
+    __ASSERT_DEBUG( iState == EInit, CodPanic( ECodInternal ) );
+    
+    // Store (temp file) is not opened now.
+    // Opening is deferred until first data chunk arrives.
+
+    TInt err = iFile.Open(  iFs, 
+                            iFname, 
+                            EFileShareAny | 
+                            EFileStream | 
+#ifdef BRDO_RFILE_WRITE_DIRECT_IO_FF
+                            EFileWrite |
+                            EFileWriteDirectIO );
+#else                            
+                            EFileWrite );
+#endif                            
+                       
+	if(err == KErrNotFound)                               
+	    {
+        err = iFile.Replace( iFs, 
+                           iFname, 
+                           EFileShareAny | 
+                           EFileStream | 
+#ifdef BRDO_RFILE_WRITE_DIRECT_IO_FF
+                                       EFileWrite |
+                                       EFileWriteDirectIO );
+#else                           
+                           EFileWrite );
+#endif                           
+
+	    }
+
+    if( !err )
+        {
+        TInt pos( 0 );
+        iFile.Seek( ESeekEnd, pos );
+        }
+    iSize = 0;
+    iState = EStoreOpen;
+    }
+    
+// ---------------------------------------------------------
+// CFileSaver::AppendData()
+// ---------------------------------------------------------
+//
+TInt CFileSaver::AppendData( const TDesC8& aData )
+    {
+    CLOG(( ECodEng, 4, \
+        _L("-> CFileSaver::AppendData (%d) bytes"), aData.Length() ));
+//TODO:    __ASSERT_DEBUG( iState == EStoreOpen, CodPanic( ECodInternal ) );
+    TInt err = CheckMaxSize( aData.Size() );
+    if ( !err && !iFile.SubSessionHandle() )
+        {
+//TODO:        __ASSERT_DEBUG( !iFname.Length(), CodPanic( ECodInternal ) );
+        (void)iFs.MkDirAll( iTempPath );
+
+        /*if( !iPausable )
+            {
+            // nothing persisted yet. If there's a file with the same name,
+            // delete it.
+            err = iFile.Replace( iFs, 
+                                   iFname, 
+                                   EFileShareAny | 
+                                   EFileStream | 
+                                   EFileWrite );
+            }
+        else*/
+
+        }
+    if ( !err )
+        {
+        err = iStorage->WriteOutNextBodyDataL(aData );
+        }
+    
+    CLOG(( EHttpLoad, 2, _L("<- CFileSaver::AppendData returns (%d)"), err ));
+    return err;
+    }
+
+// ---------------------------------------------------------
+// CFileSaver::CloseStore()
+// ---------------------------------------------------------
+//
+void CFileSaver::CloseStore()
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::CloseStore") ));
+    FlushL();
+    iFile.Close();
+    iState = EStoreClosed;
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::CloseStore") ));
+    }
+
+// ---------------------------------------------------------
+// CFileSaver::CheckResponseAttributesL()
+// ---------------------------------------------------------
+//
+void CFileSaver::CheckResponseAttributesL( const CCodData& aData )
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::CheckResponseAttributesL") ));
+    __ASSERT_DEBUG( iState == EStoreClosed, CodPanic( ECodInternal ) );
+#ifdef __TEST_COD_LOG
+    TPtrC8 mime( iType.Des8() );
+    CLOG(( ECodEng, 4, _L8("  MIME==<%S>, size(%d)"), &mime, iSize ));
+#endif /* def __TEST_COD_LOG */
+
+    if ( !iSize )
+        {
+        CLOG(( ECodEng, 4, _L("  0 bytes data") ));
+        User::Leave( KErrCodAttributeMismatch );
+        }
+//TODO:    __ASSERT_DEBUG( iFname.Length(), CodPanic( ECodInternal ) );
+
+    // Compare content MIME type against descriptor.
+
+    // Size is not checked, no exact match is required. Quote form spec:
+    // "The storage size and the execution size are dependent on the
+    // environment and may be different from the value of the size attribute.
+    // The transport size may also be different, if compression or some
+    // packaging format is used."
+    //
+    // There is a safety upper bound on the transaction size, that is already
+    // applied. See SetMaxSize().
+    
+    TDataType drm( KOma1DrmMessageContentType );
+    TDataType dcf( KOma1DcfContentType );
+
+    if ( iType == drm )
+        {
+        // DRM message arrived.
+        // DRM filter should have already turned this into a DCF. Fail now.
+        CLOG(( ECodEng, 4, _L("  DRM unexpected") ));
+        User::Leave( KErrCodAttributeMismatch );
+        }
+    else if ( iType == dcf )
+        {
+        // DCF arrived. MIME type check may be limited:
+        // - Received file (inside DRM) must be DRM-supported (CDrmHandler
+        //   does this).
+        // - COD file must specify COD, DRM, or the received MIME type.
+        __ASSERT_DEBUG( !iDrmHandler, CodPanic( ECodInternal ) );
+        iDrmHandler = CDrmHandler::NewL( iFname );
+        TDataType typeInsideDcf( iDrmHandler->Type() );
+#ifdef __TEST_COD_LOG
+        mime.Set( typeInsideDcf.Des8() );
+        CLOG(( ECodEng, 4, _L8("  inside DCF: MIME==<%S>"), &mime ));
+#endif /* def __TEST_COD_LOG */
+        if ( ! ((*aData[aData.ActiveDownload()]).HasType( typeInsideDcf.Des8() ) ||
+                (*aData[aData.ActiveDownload()]).HasType( KOma1DrmMessageContentType ) ||
+                (*aData[aData.ActiveDownload()]).HasType( KOma1DcfContentType ) )
+           )
+            {
+            // MIME type mismatch, attribute mismatch.
+            CLOG(( ECodEng, 4,  _L("  type mismatch") ));
+            User::Leave( KErrCodAttributeMismatch );
+            }
+        }
+    else
+        {
+        // Other than DRM stuff arrived. Proper check for MIME type.
+        if( !(*aData[aData.ActiveDownload()]).HasType( iType.Des8() ) )
+            {
+            CLOG(( ECodEng, 4, _L("  mismatch") ));
+            User::Leave( KErrCodAttributeMismatch );
+            }
+        }
+
+    iState = ERespChecked;
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::CheckResponseAttributesL (match)") ));
+    }
+
+
+// ---------------------------------------------------------
+// CFileSaver::BulkInstallL()
+// ---------------------------------------------------------
+//
+void CFileSaver::BulkInstallL( TRequestStatus* aStatus, const CCodData &aData, const TBool aAttached )
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::BulkInstallL") ));
+    __ASSERT_DEBUG( iState == ERespChecked, CodPanic( ECodInternal ) );
+    __ASSERT_DEBUG( aStatus, CodPanic( ECodInternal ) );
+
+/* check if the PD app has been started (PD appl is responsible for file moving after play is done)
+   In this case leave and go to the next state.
+*/
+    if (!aAttached)
+	    {
+#if 0 
+        RFs fs;
+        TInt err( KErrNone );
+        HBufC* filename = HBufC::NewLC(KMaxFileName);
+        TPtr filenamePtr = filename->Des();
+        filenamePtr = iRootPath;
+        filenamePtr.Append(_L("download\\"));
+        User::LeaveIfError( fs.Connect() );
+        CleanupClosePushL(fs);
+        CFileMan* file=CFileMan::NewL(fs);
+        CleanupStack::PushL(file);
+        TInt error = fs.MkDirAll(filenamePtr);
+        if (error!=KErrNone && error!=KErrAlreadyExists)
+           {
+            User::Leave(error);   
+           }
+   
+        // Find a unique name to avoid any conflict.
+        // Here iFname has full path of current location of file
+        // and filename has destination path.
+        FindUniqueDestinationFileNameL( iFname, filename );
+        
+        filenamePtr = filename->Des();     
+               
+        err = file->Move(iFname, filenamePtr, CFileMan::EOverWrite);
+    
+        if(err != KErrNone)
+           {
+           User::Leave(err);
+           }
+       
+        iFname = filenamePtr;              
+        NotifyMediaGalleryL( filenamePtr );        
+        CleanupStack::PopAndDestroy(file);
+        CleanupStack::PopAndDestroy(&fs);
+        CleanupStack::PopAndDestroy(filename);
+#else
+        RFs fs;
+        User::LeaveIfError( fs.Connect() );
+        CleanupClosePushL(fs);
+        CFileMan* file=CFileMan::NewL(fs);
+        CleanupStack::PushL(file);
+        
+        
+        for( TInt i = 1; i <= aData.Count() ; ++i )
+            {
+            HBufC* filename = HBufC::NewLC(KMaxFileName);
+            TPtr filenamePtr = filename->Des();
+            filenamePtr = (*aData[i]).iRootPath;
+
+            filenamePtr.Append(_L("download\\"));
+            TInt error = fs.MkDirAll(filenamePtr);
+            if (error!=KErrNone && error!=KErrAlreadyExists)
+               {
+                User::Leave(error);   
+               }
+            iFname = (*aData[i]).iFullName->Des();
+            
+            // Find a unique name to avoid any conflict.
+            // Here iFname has full path of current location of file
+            // and filename has destination path.
+            FindUniqueDestinationFileNameL( iFname, filename );
+            
+            filenamePtr = filename->Des();
+            TInt err = file->Move(iFname, filenamePtr, CFileMan::EOverWrite);
+            if(err != KErrNone)
+            	{
+            	User::LeaveIfError(err);
+            	}
+            iFname = filenamePtr;              
+            NotifyMediaGalleryL( filenamePtr );
+
+            (*aData[i]).iFileName = iFname;
+            (*aData[i]).iFullName = NameL();
+            CleanupStack::PopAndDestroy(filename);
+            }
+        CleanupStack::PopAndDestroy(file);
+        CleanupStack::PopAndDestroy(&fs);
+
+#endif // RD_MULTIPLE_DRIVE
+    // TODO set iType to that of the packaged object (??)
+    CLOG(( ECodEng, 4, _L("CFileSaver::InstallL: saved==<%S> handler(0x%x)"), \
+        &iFname, iHandler ));
+
+	}
+
+    // Normal file saving is not async.
+    *aStatus = KRequestPending;
+    User::RequestComplete( aStatus, KErrNone );
+
+    iState = EInstalled;
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::BulkInstallL") ));
+    }
+
+
+// ---------------------------------------------------------
+// CFileSaver::InstallL()
+// ---------------------------------------------------------
+//
+void CFileSaver::InstallL( TRequestStatus* aStatus, const TDesC& /* aName */, const TBool aAttached )
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::InstallL") ));
+    __ASSERT_DEBUG( iState == ERespChecked, CodPanic( ECodInternal ) );
+//    __ASSERT_DEBUG( iFname.Length(), CodPanic( ECodInternal ) );
+    __ASSERT_DEBUG( aStatus, CodPanic( ECodInternal ) );
+
+/* check if the PD app has been started (PD appl is responsible for file moving after play is done)
+   In this case leave and go to the next state.
+*/
+    if (!aAttached)
+	    {
+#ifdef RD_MULTIPLE_DRIVE 
+        RFs fs;
+        TInt err( KErrNone );
+        HBufC* filename = HBufC::NewLC(KMaxFileName);
+        TPtr filenamePtr = filename->Des();
+        filenamePtr = iRootPath;
+        filenamePtr.Append(_L("download\\"));
+        User::LeaveIfError( fs.Connect() );
+        CleanupClosePushL(fs);
+        CFileMan* file=CFileMan::NewL(fs);
+        CleanupStack::PushL(file);
+        TInt error = fs.MkDirAll(filenamePtr);
+        if (error!=KErrNone && error!=KErrAlreadyExists)
+           {
+            User::Leave(error);   
+           }
+   
+        // Find a unique name to avoid any conflict.
+        // Here iFname has full path of current location of file
+        // and filename has destination path.
+        FindUniqueDestinationFileNameL( iFname, filename );
+        
+        filenamePtr = filename->Des();     
+               
+        err = file->Move(iFname, filenamePtr, CFileMan::EOverWrite);
+    
+        if(err != KErrNone)
+           {
+           User::Leave(err);
+           }
+       
+        iFname = filenamePtr;              
+        NotifyMediaGalleryL( filenamePtr );        
+        CleanupStack::PopAndDestroy(file);
+        CleanupStack::PopAndDestroy(&fs);
+        CleanupStack::PopAndDestroy(filename);
+#else
+            RFs fs;
+            HBufC* filename = HBufC::NewLC(KMaxFileName);
+            TPtr filenamePtr = filename->Des();
+            filenamePtr = iRootPath;
+
+            filenamePtr.Append(_L("download\\"));
+            User::LeaveIfError( fs.Connect() );
+            CleanupClosePushL(fs);
+            CFileMan* file=CFileMan::NewL(fs);
+            CleanupStack::PushL(file);
+            TInt error = fs.MkDirAll(filenamePtr);
+            if (error!=KErrNone && error!=KErrAlreadyExists)
+               {
+                User::Leave(error);   
+               }
+
+            // Find a unique name to avoid any conflict.
+            // Here iFname has full path of current location of file
+            // and filename has destination path.
+            FindUniqueDestinationFileNameL( iFname, filename );
+            
+            filenamePtr = filename->Des();
+            TInt err = file->Move(iFname, filenamePtr, CFileMan::EOverWrite);
+        
+            if(err != KErrNone)
+               {
+               User::Leave(err);
+                }
+            iFname = filenamePtr;              
+            NotifyMediaGalleryL( filenamePtr );
+            CleanupStack::PopAndDestroy(file);
+            CleanupStack::PopAndDestroy(&fs);
+            CleanupStack::PopAndDestroy(filename);
+#endif // RD_MULTIPLE_DRIVE
+    // TODO set iType to that of the packaged object (??)
+    CLOG(( ECodEng, 4, _L("CFileSaver::InstallL: saved==<%S> handler(0x%x)"), \
+        &iFname, iHandler ));
+
+	}
+
+    // Normal file saving is not async.
+    *aStatus = KRequestPending;
+    User::RequestComplete( aStatus, KErrNone );
+
+    iState = EInstalled;
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::InstallL") ));
+    }
+
+// ---------------------------------------------------------
+// CFileSaver::CancelInstall()
+// ---------------------------------------------------------
+//
+void CFileSaver::CancelInstall()
+    {
+    CLOG(( ECodEng, 2, _L("CFileSaver::CancelInstall") ));
+    // Do nothing, saving is completed already (not async).
+    }
+
+// ---------------------------------------------------------
+// CFileSaver::ReleaseContent()
+// ---------------------------------------------------------
+//
+void CFileSaver::ReleaseContent( TFileName& aFname, TUid& aHandler )
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::ReleaseContent") ));
+    //__ASSERT_DEBUG( iState == EInstalled, CodPanic( ECodInternal ) );
+    aFname = iFname;
+    aHandler = iHandler;
+    iFname = KNullDesC;
+    iHandler = KNullUid;
+    iSize = 0;
+    delete iDrmHandler;
+    iDrmHandler = NULL;
+    iState = EInit;  //for PD iState = StartFeatch
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::ReleaseContent") ));
+    }
+
+// ---------------------------------------------------------
+// CFileSaver::ReleaseFileName()
+// ---------------------------------------------------------
+//
+void CFileSaver::ReleaseFileName( TFileName& aFname)
+{
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::ReleaseFileName") ));
+    aFname = iFname;
+}
+
+// ---------------------------------------------------------
+// CFileSaver::Cleanup()
+// ---------------------------------------------------------
+//
+void CFileSaver::Cleanup( TBool aDeleteFile )
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::Cleanup") ));
+    // Clean up the temporary file, ignore errors.
+    // Expected error: KErrNotFound (if there is no temp file).
+    // Unexpected error: all the rest -> nothing we can do with them.
+    CloseStore();
+    
+	if( aDeleteFile )
+	    {
+#ifdef __TEST_COD_LOG
+        TInt err =  // ('Log-only' variable.)
+#endif /* def __TEST_COD_LOG */
+        iFs.Delete( iFname );
+        CLOG(( ECodEng, 4, \
+        _L("CFileSaver::Cleanup <%S> err(%d)"), &iFname, err ));
+	    }
+
+    iFname = KNullDesC; // Now we are done with the file.
+    iHandler = KNullUid;
+    iSize = 0;
+    if ( iDrmHandler )
+        {
+        iDrmHandler->Cleanup();
+        delete iDrmHandler;
+        iDrmHandler = NULL;
+        }
+    iState = EInit;
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::Cleanup") ));
+    }
+
+  
+// ---------------------------------------------------------
+// CFileSaver::UpdateDCFRepositoryL()
+// Update saved file to DCFRepository  
+// ---------------------------------------------------------
+// 
+void CFileSaver::UpdateDCFRepositoryL( const TDesC& aFileName )
+    {
+    CDcfEntry* dcfEntry = NULL;
+    dcfEntry = CDcfEntry::NewL();    
+    CleanupStack::PushL( dcfEntry );
+    
+    CDcfRep* dcfRep = NULL;
+    dcfRep = CDcfRep::NewL();
+    CleanupStack::PushL( dcfRep );
+
+    dcfEntry->SetLocationL( aFileName, 0 );    
+    dcfRep->UpdateL( dcfEntry );
+    CleanupStack::PopAndDestroy(2); // dcfEntry, dcfRep
+    }   
+    
+// ---------------------------------------------------------
+// CFileSaver::UpdateMediaGalleryIfNeededL()
+// Calls MediaGallery Update method so that media gallery
+// knows update its view.
+// ---------------------------------------------------------
+// 
+void CFileSaver::UpdateMediaGalleryIfNeededL( const TDesC& aFileName )
+    {       
+    CMGXFileManager* fm = MGXFileManagerFactory::NewFileManagerL( iFs );
+    CleanupStack::PushL(fm);
+    fm->UpdateL(aFileName);
+    CleanupStack::PopAndDestroy(); // fm
+    }
+// ---------------------------------------------------------
+// CFileSaver::NotifyMediaGalleryL()
+// Notify media gallery about the new file.
+// ---------------------------------------------------------
+// 
+void CFileSaver::NotifyMediaGalleryL( const TDesC& aFileName )
+    {
+    CMGXFileManager* mgFileManager = MGXFileManagerFactory::NewFileManagerL( iFs );
+    CleanupStack::PushL( mgFileManager );
+
+    TRAP_IGNORE( mgFileManager->UpdateL() );
+    CleanupStack::PopAndDestroy( mgFileManager );
+
+    // Notify Media Gallery
+    TRAP_IGNORE( UpdateMediaGalleryIfNeededL( aFileName ) );
+    
+    // Notify DCF repository
+    TRAP_IGNORE( UpdateDCFRepositoryL( aFileName ) );
+    }
+// ---------------------------------------------------------
+// CFileSaver::DownloadedFileSize()
+// ---------------------------------------------------------
+//
+TInt CFileSaver::DownloadedFileSize()
+    {
+    // check how many bytes are already persisted
+    TInt DownloadedSize(0);
+    TInt err = iFile.Size( (TInt&)DownloadedSize );
+    
+    CLOG(( ECodStorage, 2, _L("CFileSaver::DownloadedFileSize  Downloaded size = %d  error = %d"), \
+               DownloadedSize,err ));
+
+    if(err != KErrNone)
+        return err;
+    return DownloadedSize;
+    }
+    
+    
+/**
+* Discard the old contents
+*/        
+void CFileSaver::ResetL()
+    {
+    
+    
+    iFile.Close();
+    
+    User::LeaveIfError( iFile.Replace(  iFs, 
+                                        iFname, 
+                                        EFileShareAny | 
+                                        EFileStream | 
+                                        EFileWrite ) );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHttpStorage::SetProgressiveMode
+// -----------------------------------------------------------------------------
+//
+void CFileSaver::SetProgressiveMode( TBool aValue )
+    {
+    iProgressiveDownload = aValue;
+    if( iProgressiveDownload )
+        {
+        iBufferSize = KDefaultStorageBufferSizePD;
+        }
+    
+    
+    if( iBufferSize != iStorage->CurrentBufferSize())
+        {
+        FlushL();
+        }
+
+    if ( iFile.SubSessionHandle() )
+        {
+     	
+        if( iProgressiveDownload )
+            {
+            if( iLength != KDefaultContentLength )    
+                {
+                iFile.SetSize( iLength );
+                }
+            }
+        else
+            {
+            iFile.SetSize( iSize );
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHttpStorage::Flush
+// Flush internal buffer to disk
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CFileSaver::FlushL()
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::FlushL") ));
+    iStorage->FlushBuffersL();
+    iStorage->ResetBuffers();
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::FlushL") ));
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CFileSaver::OnCompleted
+// Called if download completed.
+// -----------------------------------------------------------------------------
+//
+void CFileSaver::OnComplete()
+    {
+    CLOG(( ECodEng, 2, _L("-> CFileSaver::OnComplete") ));    
+    FlushL();
+    iStorage->ClearErrors();
+    iFile.Close();
+    CLOG(( ECodEng, 2, _L("<- CFileSaver::OnComplete") ));     
+    }
+
+
+
+
+// ---------------------------------------------------------
+// CFileSaver::Name()
+// ---------------------------------------------------------
+HBufC* CFileSaver::NameL() const
+    {
+    return iFname.AllocL();
+    }