ncdengine/provider/server/src/ncddownloadoperationimpl.cpp
changeset 0 ba25891c3a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/server/src/ncddownloadoperationimpl.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,937 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+#include "ncddownloadoperationimpl.h"
+
+#include <s32mem.h>
+#include <f32file.h>
+
+#include "catalogsbasemessage.h"
+#include "ncdnodemanager.h"
+#include "ncdfilehandler.h"
+#include "ncdskindownloadhandler.h"
+#include "ncdicondownloadhandler.h"
+#include "ncdpreviewdownloadhandler.h"
+#include "ncdfiledownloadhandler.h"
+#include "ncdscreenshotdownloadhandler.h"
+#include "ncdfilestoragefilehandler.h"
+#include "ncdnodeimpl.h"
+#include "ncddatabasefilehandler.h"
+#include "ncdnodeidentifier.h"
+#include "ncdsessionhandler.h"
+#include "ncdhttpheaders.h"
+#include "catalogsutils.h"
+#include "ncdconfigurationmanager.h"
+#include "catalogscontext.h"
+#include "ncdproviderdefines.h"
+#include "ncdnodeclassids.h"
+#include "ncdnodelink.h"
+#include "catalogsaccesspointmanager.h"
+#include "ncdoperationremovehandler.h"
+#include "ncdproviderutils.h"
+#include "ncdnodemetadataimpl.h"
+#include "catalogshttpincludes.h"
+#include "ncdgeneralmanager.h"
+
+#include "catalogsdebug.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CNcdDownloadOperation* CNcdDownloadOperation::NewL( 
+    MNcdOperationRemoveHandler& aRemoveHandler, 
+    TNcdDownloadDataType aType, 
+    const CNcdNodeIdentifier& aNodeId,
+    CNcdGeneralManager& aGeneralManager,
+    MCatalogsHttpSession& aHttpSession,
+    MNcdSessionHandler* aSessionHandler,
+    MNcdStorageClient* aStorageClient,
+    const TUid& aClientUid,
+    TInt aDownloadIndex,
+    MCatalogsSession& aSession )
+    {
+    CNcdDownloadOperation* self = new( ELeave ) CNcdDownloadOperation( 
+        aRemoveHandler,
+        aGeneralManager, 
+        aHttpSession, 
+        aSessionHandler, 
+        aType, 
+        aClientUid, 
+        aSession );
+    CleanupClosePushL( *self );
+    self->ConstructL( aNodeId, aDownloadIndex, aStorageClient );
+
+    CleanupStack::Pop();
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CNcdDownloadOperation::~CNcdDownloadOperation()
+    {
+    DLTRACEIN( ( "" ) );
+    if ( iDownload ) 
+        {
+        iDownload->Release();
+        iDownload = NULL;
+        }
+        
+    delete iFileHandler;
+    delete iDownloadHandler;
+    
+    delete iSessionId;
+    DLTRACEOUT((""));
+    }
+
+
+// ---------------------------------------------------------------------------
+// Download config getter
+// ---------------------------------------------------------------------------
+//
+MCatalogsHttpConfig& CNcdDownloadOperation::Config()
+    {
+    DASSERT( iDownload );
+    return iDownload->Config();
+    }
+
+// ---------------------------------------------------------------------------
+// Node Id getter
+// ---------------------------------------------------------------------------
+//
+const CNcdNodeIdentifier& CNcdDownloadOperation::NodeIdentifier() const
+    {
+    return iDownloadHandler->NodeId();
+    }
+
+// ---------------------------------------------------------------------------
+// Cancel
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperation::Cancel() 
+    {    
+    DLTRACEIN(( "" ));
+    if ( iDownload ) 
+        {
+        // Cancel also releases the dl        
+        iDownload->Cancel();
+        iDownload = NULL;
+        }
+    DLTRACEOUT(( "" ));
+    }
+
+
+// ---------------------------------------------------------------------------
+// ReceiveMessage
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperation::ReceiveMessage( 
+    MCatalogsBaseMessage* aMessage,
+    TInt aFunctionNumber )
+    {
+    DLTRACEIN(( "Function: %d", aFunctionNumber ));
+    TNcdOperationMessageCompletionId completionId;
+    TInt err = KErrNone;
+        
+    // Response to pause and resume messages, other messages are handled
+    // by the base class
+    switch ( aFunctionNumber )
+        {
+        // GetData which in fact is pausable check
+        case ENCDOperationFunctionGetData: 
+            {
+            DLTRACE(( "ENCDOperationFunctionGetData "));
+            // Only error will come from CompleteMessageL
+            TRAP_IGNORE( GetPausableStateL( *aMessage ) );
+            return;
+            }
+            
+        // Pause download if it's pausable
+        case ENCDOperationFunctionPause:
+            {
+            DLTRACE( ( "ENCDOperationFunctionPause" ) );
+            err = iDownload->Pause();              
+            if ( err == KErrNone ) 
+                {
+                iDownloadState = ENcdDownloadPaused;
+                }
+            completionId = ENCDOperationMessageCompletionPause;
+            break;
+            }
+            
+        
+        // Resume download
+        case ENCDOperationFunctionResume:
+            {
+            DLTRACE( ( "ENCDOperationFunctionResume" ) );
+            
+            if ( iDownload->Progress().iState == ECatalogsHttpOpPaused ) 
+                {
+                err = iDownload->Start();                
+                if ( err == KErrNone ) 
+                    {
+                    iDownloadState = ENcdDownloadInProgress;
+                    }
+                }
+            completionId = ENCDOperationMessageCompletionResume;
+            break;
+            }
+            
+        default:
+            {
+            DLTRACE(("Calling baseclass"));
+            // Call implementation in the base class
+            CNcdBaseOperation::ReceiveMessage( aMessage, aFunctionNumber );
+            DLTRACEOUT(( "Called baseclass" ));
+            return;
+            }
+        }
+        
+        
+    TCatalogsTransportProgress progress( iDownload->Progress() );
+    
+    iProgress = TNcdSendableProgress( 
+        iCurrentFile,
+        iTotalFileCount, 
+        progress.iProgress,
+        progress.iMaxProgress );
+    
+    // this ensures that the proxy handles pausing correctly
+    iProgress.iState = iDownloadState;
+
+    if ( !iPendingMessage && 
+          iDownloadState != ENcdDownloadPaused )
+        {
+        DLTRACE(("No pending message, ask for one"));        
+        iProgress.iState = KNcdDownloadContinueMessageRequired;    
+        }
+    
+    // Complete pause/resume message
+    if ( CompleteMessage( aMessage, completionId, iProgress, err ) 
+        != KErrNone ) 
+        {
+        DLTRACE( ( "Complete message failed" ) );
+        }
+        
+    iProgress.iState = iCurrentFile;
+    iProgress.iOperationId = iTotalFileCount;
+    DLTRACEOUT(( "" ));
+    }
+
+
+// ---------------------------------------------------------------------------
+// Checks if the download matches the given criteria
+// ---------------------------------------------------------------------------
+//
+TBool CNcdDownloadOperation::MatchDownload( 
+    const CNcdNodeIdentifier& aId, 
+    TNcdDownloadDataType& aType, TInt aIndex ) const
+    {
+    DLTRACEIN((""));
+    if ( aType != iType || 
+         aIndex != ( iDownloadHandler->CurrentDownload() - 1 ) ) 
+        {
+        DLTRACEOUT(("Type or index didn't match"));
+        return EFalse;
+        }
+    
+    // Generic file download don't have node nor metadata
+    if ( aType != ENcdGenericFileDownload ) 
+        {
+        DLTRACE(("Not a generic file download"));
+        // Compare metadata id's because temp nodes have different node 
+        // id's but same metadata id's as normal nodes
+        const CNcdNode* node = NULL;    
+        TRAP_IGNORE( node = &iDownloadHandler->NodeL() );
+        
+        if ( node ) 
+            {        
+            const CNcdNodeMetaData* metadata = node->NodeMetaData();
+            if ( metadata && metadata->Identifier().Equals( aId ) )
+                {
+                return ETrue;
+                }
+            }
+        }
+    else // generic file downloads
+        {
+        DLTRACEOUT(("Generic file download"));
+        return aId.Equals( iDownloadHandler->NodeId() );
+        }
+    return EFalse;
+    }
+
+
+// ---------------------------------------------------------------------------
+// HandleHttpEvent
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperation::HandleHttpEventL( 
+    MCatalogsHttpOperation& aOperation, 
+    TCatalogsHttpEvent aEvent )
+    {
+    DLTRACEIN( ( "" ) );
+    (void) aOperation; // suppresses compiler warning
+    
+    DASSERT( &aOperation == iDownload );
+    DASSERT( aOperation.OperationType() == ECatalogsHttpDownload );
+
+        // minimizing stack usage
+        {        
+        TCatalogsTransportProgress progress( iDownload->Progress() );
+        
+        iProgress = TNcdSendableProgress( 
+            iCurrentFile,
+            iTotalFileCount, 
+            progress.iProgress,
+            progress.iMaxProgress );
+        }        
+    
+    switch( aEvent.iOperationState ) 
+        {
+        // Handle completed operation
+        case ECatalogsHttpOpCompleted:
+            {
+            iCurrentFile++;
+            DLTRACE(("ECatalogsHttpOpCompleted"));
+            if ( iPendingMessage ) 
+                {
+                DLTRACE( ( "Completing message" ) );
+                // Finish the download = move it to destination
+                TRAPD( err, iDownloadHandler->FinishDownloadL( 
+                    *iDownload, iFileHandler ) );
+                
+                // Release old download                
+                iDownload->Release();
+                iDownload = NULL;
+                
+                if ( iDownloadHandler->CurrentDownload() == 
+                     iDownloadHandler->DownloadCount() )
+                    {   
+                    DLTRACE(("Download(s) finished"));                 
+                    CompleteMessage( iPendingMessage,
+                        ENCDOperationMessageCompletionComplete,
+                        iProgress, err );
+                    iDownloadState = ENcdDownloadComplete;
+                    iOperationState = EStateComplete;
+                    }
+                else 
+                    {
+                    DLTRACE(("More downloads"));
+
+                    
+                    // Get the next download
+                    TRAP( err, iDownload = iDownloadHandler->DownloadL() );
+                    iError = err;
+                    if ( err != KErrNone ) 
+                        {
+                        /**
+                         * @ Is this correct?
+                         */
+                        return;
+                        }
+                    
+                    // Set observer
+                    iDownload->Config().SetObserver( this );
+                    UpdateHeadersL( iPendingMessage->Session().Context() );
+                    err = iDownload->Start( MCatalogsHttpOperation::EAutomaticResume );
+                    if ( err >= 0 ) 
+                        {
+                        iDownloadState = ENcdDownloadInProgress;
+                        err = KErrNone;
+                        iOperationState = EStateRunning;
+                        TCatalogsTransportProgress progress( 
+                            iDownload->Progress() );
+                        
+                        iProgress = TNcdSendableProgress( 
+                            iCurrentFile,
+                            iTotalFileCount, progress.iProgress,                            
+                            progress.iMaxProgress );
+                            
+                        CompleteMessage( iPendingMessage,
+                            ENCDOperationMessageCompletionProgress,
+                            iProgress, KErrNone );
+                        }
+                     else 
+                        {
+                        /** @ Handle error
+                        */
+                        iOperationState = EStateComplete;
+                        iDownloadState = ENcdDownloadComplete;
+
+                        }
+                    
+                    }                
+                iPendingMessage = NULL;
+                }
+            else 
+                {
+                iDownloadState = ENcdDownloadComplete;
+                }
+            break;
+            }
+        
+        // Handle operation in progress
+        case ECatalogsHttpOpInProgress:
+            {
+            iDownloadState = ENcdDownloadInProgress;
+            switch( aEvent.iProgressState ) 
+                {
+                case ECatalogsHttpResponseBodyReceived:
+                    {                    
+                    //Notify Proxy about progress                    
+                    /*
+                    if ( iPendingMessage ) 
+                        {            
+                                   
+                        CompleteMessage( iPendingMessage,
+                            ENCDOperationMessageCompletionProgress,
+                            iProgress, KErrNone );
+                        }
+                    */
+                    iOperationState = EStateRunning;
+                    iUnhandledEvent = ETrue;
+                    RunOperation();
+                    break;
+                    }
+                    
+                default:
+                    {
+                    }
+                }
+            break;
+            }
+        
+        default:
+            {
+            break;
+            }
+        }
+    DLTRACEOUT((""));
+    }
+    
+    
+// ---------------------------------------------------------------------------
+// HandleHttpError
+// ---------------------------------------------------------------------------
+//
+TBool CNcdDownloadOperation::HandleHttpError(
+    MCatalogsHttpOperation& aOperation,
+    TCatalogsHttpError aError )
+    {    
+    DLTRACEIN( ( "Error type: %i, id: %i", aError.iType, aError.iError ) );
+    DASSERT( &aOperation == iDownload );
+    
+    if ( aError.iError == KErrCancel ) 
+        {
+        aOperation.Cancel();
+        }
+    else 
+        {        
+        aOperation.Release();
+        }
+    iDownload = NULL;
+    iError = aError.iError;
+    iDownloadState = ENcdDownloadFailed;
+    if ( iPendingMessage ) 
+        {        
+        
+        CompleteMessage( iPendingMessage,
+            ENCDOperationMessageCompletionError, iProgress, aError.iError );
+        
+        iOperationState = EStateComplete;   
+        }
+    DLTRACEOUT((""));
+    return ETrue;
+    }
+
+
+// ---------------------------------------------------------------------------
+// RunOperation
+// ---------------------------------------------------------------------------
+//
+TInt CNcdDownloadOperation::RunOperation()
+    {
+    DLTRACEIN(( "Pending message: %X", iPendingMessage ));
+    DASSERT( iDownload );
+    
+    if ( !iPendingMessage ) 
+        {      
+        DLTRACE(("No pending message"));  
+        return KErrNotReady;
+        }
+     
+    TInt err = KErrNone;
+    DLTRACE(("DL state: %i", iDownloadState ));
+
+    switch( iDownloadState ) 
+        {
+        // Start the download
+        case ENcdDownloadStopped: 
+            {
+            DLTRACE(("ENcdDownloadStopped"));
+            
+            TRAP( err, UpdateHeadersL( iPendingMessage->Session().Context() ));
+            if ( err != KErrNone ) 
+                {
+                break;
+                }
+            
+            DLTRACE(("Starting the download"));
+            err = iDownload->Start();
+            if ( err >= 0 ) 
+                {
+                iDownloadState = ENcdDownloadInProgress;
+                err = KErrNone;
+                iOperationState = EStateRunning;
+                TCatalogsTransportProgress progress( iDownload->Progress() );
+                
+                // Send progress information
+                iProgress = TNcdSendableProgress( iCurrentFile,
+                    iTotalFileCount, 
+                    progress.iProgress,
+                    progress.iMaxProgress );
+                }
+            DLTRACE(("ENcdDownloadStopped done"));
+            break;
+            }
+        
+        case ENcdDownloadInProgress: 
+            {
+            DLTRACE(("ENcdDownloadInProgress"));
+            if ( iUnhandledEvent ) 
+                {
+                DLTRACE(("Completing progress message"));
+                CompleteMessage( iPendingMessage,
+                    ENCDOperationMessageCompletionProgress,
+                    iProgress, KErrNone );
+                iUnhandledEvent = EFalse;
+                }
+                
+            DLTRACE(("ENcdDownloadInProgress done"));
+            break;
+            }
+            
+        case ENcdDownloadComplete:
+            {
+            DLTRACE(("ENcdDownloadComplete"));
+            iUnhandledEvent = EFalse;
+            // Finish the download = move it to destination
+            TRAP( err, iDownloadHandler->FinishDownloadL( *iDownload,
+                iFileHandler ) );
+            
+            // Check if the download was the last
+            if ( iDownloadHandler->CurrentDownload() == 
+                 iDownloadHandler->DownloadCount() ) 
+                {
+                // Send completion message in case didn't have any pending
+                // messages when the download actually completed
+                
+                if ( CompleteMessage( iPendingMessage,
+                    ENCDOperationMessageCompletionComplete, 
+                    iProgress, err ) != KErrNone ) 
+                    {
+                    DLERROR(( "Message completion failed" ));
+                    }
+                    
+                iOperationState = EStateComplete;
+                }
+             else 
+                {
+                // Release old download
+                iDownload->Release();
+                iDownload = NULL;
+                
+                // Get the next download
+                TRAP( err, iDownload = iDownloadHandler->DownloadL() );
+                if ( err != KErrNone ) 
+                    {
+                    /**
+                     * @ Is this correct?
+                     */
+                    break;
+                    }
+                
+                // Set observer
+                iDownload->Config().SetObserver( this );
+                TRAP( err, UpdateHeadersL( iPendingMessage->Session().Context() ));
+                if ( err != KErrNone ) 
+                    {
+                    break;
+                    }
+                err = iDownload->Start( MCatalogsHttpOperation::EAutomaticResume );
+                if ( err >= 0 ) 
+                    {
+                    iDownloadState = ENcdDownloadInProgress;
+                    err = KErrNone;
+                    iOperationState = EStateRunning;
+                    TCatalogsTransportProgress progress( iDownload->Progress() );
+                    
+                    // Send progress information
+                    iProgress = TNcdSendableProgress( iCurrentFile,
+                        iTotalFileCount, 
+                        progress.iProgress,
+                        progress.iMaxProgress );
+                        
+                    CompleteMessage( iPendingMessage,
+                        ENCDOperationMessageCompletionProgress, iProgress, iError );
+                    }
+                
+                }
+            iPendingMessage = NULL;
+            DLTRACE(("ENcdDownloadComplete done"));
+            break;
+            }
+            
+        case ENcdDownloadFailed:
+            {
+            DLTRACE(("ENcdDownloadFailed"));
+            // Send error message in case didn't have any pending
+            // messages when the download actually failed
+            
+            CompleteMessage( iPendingMessage,
+                ENCDOperationMessageCompletionError, iProgress,
+                iError );
+            DLTRACE(("ENcdDownloadFailed done"));
+            break;            
+            }
+            
+        default: 
+            {
+            DLTRACE(("Default"));
+            DASSERT( 0 );
+            }
+        }
+        
+    if ( err != KErrNone )
+        {
+        DLTRACE(("error: %d", err));
+        Cancel();
+        iDownloadState = ENcdDownloadFailed;
+        iError = err;
+        if ( iPendingMessage )
+            {
+            CompleteMessage( iPendingMessage,
+                ENCDOperationMessageCompletionError, iError );
+            }
+        // call observers
+        CompleteCallback();
+        }
+    DLTRACEOUT(("err: %d", err));
+    return err;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Initializer
+// ---------------------------------------------------------------------------
+//
+TInt CNcdDownloadOperation::Initialize()
+    {
+    DLTRACEIN( ( "" ) );
+    DASSERT( iDownloadHandler );
+    TRAPD(err,
+        {
+    
+        switch( iType ) 
+            {
+            // read the target filename and path from the message
+            case ENcdSkinDownload: // Flowthrough
+                {
+                RCatalogsMessageReader reader;
+                reader.OpenLC( *iPendingMessage );
+                              
+                HBufC* filename = NULL;
+                DLTRACE(("Internalizing filename"));
+                InternalizeDesL( filename, reader() );
+                                
+                CleanupStack::PopAndDestroy( &reader );
+                
+                CleanupStack::PushL( filename );
+                
+                DLTRACE(( _L("Parsing filename: %S"), filename ));
+                // Parse the path and set directory and filename
+                TParsePtrC parse( *filename );
+                iDownload->Config().SetDirectoryL( parse.DriveAndPath() );
+                iDownload->Config().SetFilenameL( parse.NameAndExt() );
+                
+                CleanupStack::PopAndDestroy( filename );
+                
+                // Just check that we're not already below critical level
+                WouldDiskSpaceGoBelowCriticalLevelL( 
+                    iDownload->Config().Directory(),
+                    CNcdProviderUtils::FileSession(),
+                    0 );
+                
+                break;
+                }
+                
+            default:
+                // nothing to initialize for other types
+                break;
+                
+            } // switch
+    
+
+    
+        DLTRACE(("Writing initialize response"));
+        iCurrentFile = 1;
+        iTotalFileCount = iDownloadHandler->DownloadCount();
+        // Write the response
+        RCatalogsBufferWriter writer;
+        writer.OpenLC();
+        writer().WriteInt32L( ENCDOperationMessageCompletionInit );
+        writer().WriteInt32L( iDownloadHandler->DownloadCount() );
+        
+        // write pause-status
+        writer().WriteInt32L( iDownloadState == ENcdDownloadPaused );
+        
+        iPendingMessage->CompleteAndReleaseL( writer.PtrL(), KErrNone );
+        iPendingMessage = NULL;
+        CleanupStack::PopAndDestroy( &writer );
+        });
+        
+    if ( err != KErrNone ) 
+        {
+        DLINFO(("err: %d", err));
+        iPendingMessage->CompleteAndRelease( err );
+        iPendingMessage = NULL;
+        }
+    
+    DLTRACEOUT(( "err: %d", err ));
+    return err;    
+    }
+
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CNcdDownloadOperation::CNcdDownloadOperation( 
+    MNcdOperationRemoveHandler& aRemoveHandler,
+    CNcdGeneralManager& aGeneralManager,
+    MCatalogsHttpSession& aHttpSession, 
+    MNcdSessionHandler* aSessionHandler, 
+    TNcdDownloadDataType aType,
+    const TUid& aClientUid,
+    MCatalogsSession& aSession ) : 
+        CNcdBaseOperation( aGeneralManager, &aRemoveHandler, EDownloadOperation,
+            aSession ),
+        iHttpSession( aHttpSession ),
+        iSessionHandler( aSessionHandler ),
+        iConfigurationManager( aGeneralManager.ConfigurationManager() ),
+        iAccessPointManager( aGeneralManager.AccessPointManager() ),
+        iType( aType ),
+        iDownloadState( ENcdDownloadStopped ),
+        iClientUid( aClientUid )
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperation::ConstructL( const CNcdNodeIdentifier& aNodeId, 
+    TInt aDownloadIndex,
+    MNcdStorageClient* aStorageClient )
+    {
+    DLTRACEIN(( "DL index: %i", aDownloadIndex ));
+    // Call ConstructL for the base class
+    CNcdBaseOperation::ConstructL();    
+
+    if ( iSessionHandler && iType != ENcdGenericFileDownload ) 
+        {        
+        // Ignore error, it's possible that there's no session for URI
+        // anymore
+        TRAP_IGNORE( 
+            {
+            // Leaves if the node is not found        
+            CNcdNode& node = iNodeManager->NodeL( aNodeId );                    
+
+            // Get server URI from the node
+            const TDesC& serverUri = node.NodeLinkL().ServerUri();
+            if ( iSessionHandler->DoesSessionExist( serverUri, 
+                aNodeId.NodeNameSpace() ) ) 
+                {        
+                // Get session ID for the URI
+                iSessionId = iSessionHandler->Session( serverUri,
+                    aNodeId.NodeNameSpace() ).AllocL();
+                }
+            });
+        }
+    
+        
+    // Choose the correct handlers for the download
+    switch ( iType ) 
+        {
+        case ENcdSkinDownload : 
+            {
+            DLTRACE(("Skin download"));
+            iFileHandler = NULL;
+            iDownloadHandler = CNcdSkinDownloadHandler::NewL( aNodeId, 
+                *iNodeManager,
+                iHttpSession );
+            break;
+            
+            }
+        case ENcdGenericFileDownload :
+            {
+            DLTRACE(("Generic file download"));
+            // No file handler, Transport takes care of moving the file
+            iFileHandler = NULL;
+            iDownloadHandler = CNcdFileDownloadHandler::NewL( aNodeId,
+                *iNodeManager,
+                iHttpSession );
+            break;
+            }
+
+        case ENcdPreviewDownload :
+            {
+            DLTRACE(("Preview download"));
+            DASSERT( aStorageClient );
+            iFileHandler = CNcdFileStorageFileHandler::NewL( *aStorageClient );
+            iDownloadHandler = CNcdPreviewDownloadHandler::NewL( aNodeId,
+                *iNodeManager,
+                iHttpSession );
+            break;
+            }
+
+        case ENcdIconDownload :
+            {
+            DLTRACE(("Icon download"));
+            DASSERT( aStorageClient );
+            iFileHandler = CNcdDatabaseFileHandler::NewL( *aStorageClient,
+                NcdNodeClassIds::ENcdIconData );            
+            iDownloadHandler = CNcdIconDownloadHandler::NewL( aNodeId,
+                *iNodeManager,
+                iHttpSession );
+            break;
+            }
+
+        case ENcdScreenshotDownload :
+            {
+            DLTRACE(("Screenshot download"));
+            DASSERT( aStorageClient );
+            iFileHandler = CNcdDatabaseFileHandler::NewL( *aStorageClient,
+                NcdNodeClassIds::ENcdScreenshotData );
+            iDownloadHandler = CNcdScreenshotDownloadHandler::NewL( aNodeId,
+                *iNodeManager,
+                iHttpSession );
+            break;
+            }
+        
+        default:
+            {
+            DASSERT( 0 );
+            }
+        }
+    
+    // Start downloading from the correct index
+    iDownloadHandler->SetCurrentDownload( aDownloadIndex );
+    
+    // Create the download
+    iDownload = iDownloadHandler->DownloadL();
+    iDownload->Config().SetObserver( this );
+    
+    DLTRACE(("Check that we're not below critical level on disk space"));
+    
+    // Target path for skin download is set in Initialize so
+    // we can't check it yet
+    if ( iType != ENcdSkinDownload )
+        {        
+        // Just check that we're not already below critical level
+        WouldDiskSpaceGoBelowCriticalLevelL( 
+            iDownload->Config().Directory(),
+            CNcdProviderUtils::FileSession(),
+            0 );
+        }
+    
+    if ( iType == ENcdSkinDownload || iType == ENcdPreviewDownload || 
+         iType == ENcdIconDownload || iType == ENcdScreenshotDownload ) 
+        {
+        // verify the node exists, otherwise call to AccessPointIdL won't work correctly
+        DASSERT( iNodeManager->NodePtrL( aNodeId ) != NULL );        
+        TUint32 apId;
+        TInt error = iAccessPointManager.AccessPointIdL(
+            aNodeId, MCatalogsAccessPointManager::EBrowse, iClientUid, apId);
+        if ( error == KErrNone ) 
+            {
+            DLTRACE(( "Setting access point %d for browse", apId ))   
+            Config().SetConnectionMethod( 
+                TCatalogsConnectionMethod( 
+                    apId, ECatalogsConnectionMethodTypeAccessPoint ) );
+            }
+        }
+    
+    DLTRACEOUT(( "" ));
+    }
+    
+
+// ---------------------------------------------------------------------------
+// Updates the download headers
+// ---------------------------------------------------------------------------
+//    
+void CNcdDownloadOperation::UpdateHeadersL( const MCatalogsContext& aContext )
+    {    
+    DLTRACEIN((""));
+    
+    DLTRACE(( _L("Client id: %S"), &iConfigurationManager.ClientIdL( 
+        aContext) ));
+    DASSERT( iDownload );
+    
+    // Add ClientId, SSIS and sessionId to file downloads
+    MCatalogsHttpHeaders& headers = iDownload->Config().RequestHeaders();
+    headers.AddHeaderL( NcdHttpHeaders::KClientIdHeader, 
+        iConfigurationManager.ClientIdL( aContext) );
+    headers.AddHeaderL( NcdHttpHeaders::KSsidHeader, 
+        iConfigurationManager.SsidL( aContext) );
+        
+    if ( iSessionId )
+        {  
+        DLTRACE(( _L("Adding session id: %S"), iSessionId ));      
+        headers.AddHeaderL( NcdHttpHeaders::KSessionIdHeader, *iSessionId );
+        }
+    DLTRACEOUT(( "" ));
+    }
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//    
+void CNcdDownloadOperation::GetPausableStateL( MCatalogsBaseMessage& aMessage )
+    {
+    DLTRACEIN((""));
+    TInt pausableState = KNcdDownloadIsNotPausable;
+    if ( iDownload && iDownload->IsPausable() ) 
+        {
+        DLTRACE(("Download is pausable"));
+        pausableState = KNcdDownloadIsPausable;
+        }
+                
+    aMessage.CompleteAndReleaseL(
+        pausableState, 
+        KErrNone );
+    
+    }