--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/client/src/ncddownloadoperationproxy.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,549 @@
+/*
+* 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: Implements CNcdDownloadOperationProxy
+*
+*/
+
+
+#include <s32strm.h>
+#include "ncddownloadoperationproxy.h"
+#include "ncddownloadoperationobserver.h"
+#include "catalogsdebug.h"
+#include "ncddownloadoperationstates.h"
+#include "ncdoperationproxyremovehandler.h"
+#include "catalogsclientserver.h"
+#include "ncdnodeproxy.h"
+#include "ncdnodemanagerproxy.h"
+#include "catalogsutils.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CNcdDownloadOperationProxy* CNcdDownloadOperationProxy::NewL(
+ MCatalogsClientServer& aSession,
+ TNcdDownloadDataType aDownloadType,
+ TInt aHandle,
+ MNcdOperationProxyRemoveHandler* aRemoveHandler,
+ CNcdNodeProxy* aNode,
+ MNcdDownloadOperationObserver* aObserver,
+ CNcdNodeManagerProxy* aNodeManager,
+ TInt aDownloadIndex,
+ TBool aIsRunning )
+ {
+ CNcdDownloadOperationProxy* self = CNcdDownloadOperationProxy::NewLC(
+ aSession,
+ aDownloadType,
+ aHandle,
+ aRemoveHandler,
+ aNode,
+ aObserver,
+ aNodeManager,
+ aDownloadIndex,
+ aIsRunning );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CNcdDownloadOperationProxy* CNcdDownloadOperationProxy::NewLC(
+ MCatalogsClientServer& aSession,
+ TNcdDownloadDataType aDownloadType,
+ TInt aHandle,
+ MNcdOperationProxyRemoveHandler* aRemoveHandler,
+ CNcdNodeProxy* aNode,
+ MNcdDownloadOperationObserver* aObserver,
+ CNcdNodeManagerProxy* aNodeManager,
+ TInt aDownloadIndex,
+ TBool aIsRunning )
+ {
+ CNcdDownloadOperationProxy* self =
+ new( ELeave ) CNcdDownloadOperationProxy( aDownloadType,
+ aDownloadIndex );
+
+ self->AddRef();
+ CleanupReleasePushL( *self );
+ self->ConstructL( aSession, aHandle, aRemoveHandler, aNode,
+ aObserver, aNodeManager, aIsRunning );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// From MNcdDownloadOperation
+//
+// ---------------------------------------------------------------------------
+//
+TInt CNcdDownloadOperationProxy::FileCount()
+ {
+ return iFileCount;
+ }
+
+
+// ---------------------------------------------------------------------------
+// From MNcdDownloadOperation
+//
+// ---------------------------------------------------------------------------
+//
+TInt CNcdDownloadOperationProxy::CurrentFile()
+ {
+ return iCurrentFile;
+ }
+
+
+// ---------------------------------------------------------------------------
+// From MNcdDownloadOperation
+//
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperationProxy::PauseL()
+ {
+ DLTRACEIN( ( "" ) );
+ HBufC8* data = NULL;
+
+ TState state = OperationStateL();
+ // Check that the operation is in a resumable state
+ if ( state == EStateCancelled )
+ {
+ DLERROR(("Cannot resume! Operation has been cancelled. Leaving"));
+ User::Leave( KErrCancel );
+ }
+
+ // Operation must be running for pause to work
+ if ( state != EStateRunning || iIsPaused )
+ {
+ DLTRACEOUT(("Operation complete or other unresumable state"));
+ return;
+ }
+
+ ClientServerSession().SendSyncAlloc( ENCDOperationFunctionPause,
+ KNullDesC8(),
+ data,
+ Handle(),
+ 0 );
+
+ if ( data )
+ {
+ DLTRACE(("Received progress information"));
+
+ RDesReadStream stream( *data );
+ CleanupStack::PushL( data );
+ CleanupClosePushL( stream );
+
+ // Just read completionId from the stream
+ stream.ReadInt32L();
+
+ TNcdSendableProgress progress;
+ // Read progress info
+ progress.InternalizeL( stream );
+
+ // Update paused state
+ iIsPaused = ( progress.iState == ENcdDownloadPaused );
+
+ CleanupStack::PopAndDestroy( 2, data ); // stream, data
+ }
+
+ SetState( EStateRunning );
+ DLTRACEOUT( ( "IsPaused: %d", iIsPaused ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// From MNcdDownloadOperation
+//
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperationProxy::ResumeL()
+ {
+ DLTRACEIN(( "" ));
+ HBufC8* data = NULL;
+ TState state = OperationStateL();
+
+ // Check that the operation is in a resumable state
+ if ( state == EStateCancelled )
+ {
+ DLERROR(("Cannot resume! Operation has been cancelled. Leaving"));
+ User::Leave( KErrCancel );
+ }
+
+ if ( ( state != EStateStopped && state != EStateRunning ) || !iIsPaused )
+ {
+ DLTRACEOUT(("Operation complete or other unresumable state"));
+ return;
+ }
+
+ ClientServerSession().SendSyncAlloc( ENCDOperationFunctionResume,
+ KNullDesC8(),
+ data,
+ Handle(),
+ 0 );
+
+ if ( data )
+ {
+ DLTRACE(("Received progress information"));
+ RDesReadStream stream( *data );
+ CleanupStack::PushL( data );
+ CleanupClosePushL( stream );
+
+ // Just read the completionId from the stream
+ stream.ReadInt32L();
+
+ TNcdSendableProgress progress;
+ // Read progress info
+
+ progress.InternalizeL( stream );
+ // Update paused-state
+ iIsPaused = ( progress.iState == ENcdDownloadPaused );
+
+ DLTRACE(("Sending continue message"));
+ if ( progress.iState == KNcdDownloadContinueMessageRequired )
+ {
+ SendContinueMessageL();
+ }
+ else if ( progress.iState == KNcdDownloadStartMessageRequired )
+ {
+ DLTRACE(("Start the operation"));
+ SetState( EStateStopped );
+ DoStartOperationL();
+ }
+
+ CleanupStack::PopAndDestroy( 2, data ); // stream, data
+ }
+
+ SetState( EStateRunning );
+ DLTRACEOUT(( "" ));
+ }
+
+
+// ---------------------------------------------------------------------------
+// From MNcdDownloadOperation
+//
+// ---------------------------------------------------------------------------
+//
+TBool CNcdDownloadOperationProxy::IsPaused()
+ {
+ return iIsPaused;
+ }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool CNcdDownloadOperationProxy::IsPausableL()
+ {
+ DLTRACEIN((""));
+ TInt data = KErrNone;
+ User::LeaveIfError( ClientServerSession().SendSync(
+ ENCDOperationFunctionGetData,
+ KNullDesC8(),
+ data,
+ Handle() ) );
+
+ DLTRACEOUT(("pausable: %d", data == KNcdDownloadIsPausable ));
+ return data == KNcdDownloadIsPausable;
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// From MNcdDownloadOperation
+// Observer adder
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperationProxy::AddObserverL(
+ MNcdDownloadOperationObserver& aObserver )
+ {
+ DLTRACEIN( ( "this: %X, aObserver: %X", this, &aObserver ) );
+ TInt err = iObservers.InsertInAddressOrder( &aObserver );
+ if ( err != KErrNone && err != KErrAlreadyExists )
+ {
+ User::Leave( err );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// From MNcdDownloadOperation
+// Observer remover
+// ---------------------------------------------------------------------------
+//
+TBool CNcdDownloadOperationProxy::RemoveObserver(
+ MNcdDownloadOperationObserver& aObserver )
+ {
+ DLTRACEIN( ( "this: %X, aObserver: %X", this, &aObserver ) );
+ // observer must exist
+
+ TInt index = iObservers.FindInAddressOrder( &aObserver );
+ if ( index != KErrNotFound )
+ {
+ DLTRACE(("Removing observer"));
+ iObservers.Remove( index );
+ return ETrue;
+ }
+ DLTRACE(("Observer didn't exist"))
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// From MNcdOperation
+// Operation type getter
+// ---------------------------------------------------------------------------
+//
+TNcdInterfaceId CNcdDownloadOperationProxy::OperationType() const
+ {
+ return static_cast<TNcdInterfaceId>(MNcdDownloadOperation::KInterfaceUid);
+ }
+
+
+// ---------------------------------------------------------------------------
+// Download type getter
+// ---------------------------------------------------------------------------
+//
+TNcdDownloadDataType CNcdDownloadOperationProxy::DownloadDataType() const
+ {
+ return iDownloadType;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CNcdDownloadOperationProxy::CNcdDownloadOperationProxy(
+ TNcdDownloadDataType aDownloadType,
+ TInt aDownloadIndex )
+ : CNcdOperation< MNcdDownloadOperation >( NULL ), iDownloadType( aDownloadType ),
+ iFileCount( 1 ), iCurrentFile( aDownloadIndex + 1 ), iIsPaused( EFalse )
+ {
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CNcdDownloadOperationProxy::~CNcdDownloadOperationProxy()
+ {
+ DLTRACEIN(( "this: %X", this ));
+ iObservers.Close();
+ DASSERT( iRemoveHandler );
+ DLTRACE(("Removing proxy from remove handler"));
+ if ( iRemoveHandler )
+ iRemoveHandler->RemoveOperationProxy( *this );
+
+ DLTRACEOUT(( "" ));
+ }
+
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperationProxy::ConstructL( MCatalogsClientServer& aSession,
+ TInt aHandle,
+ MNcdOperationProxyRemoveHandler* aRemoveHandler,
+ CNcdNodeProxy* aNode,
+ MNcdDownloadOperationObserver* aObserver,
+ CNcdNodeManagerProxy* aNodeManager,
+ TBool aIsRunning )
+ {
+ DLTRACEIN( ( "this: %X", this ) );
+ CNcdBaseOperationProxy::ConstructL( aSession, aHandle, aRemoveHandler,
+ aNode, aNodeManager );
+
+ if ( aObserver )
+ {
+ AddObserverL( *aObserver );
+ }
+
+ TNcdSendableProgress& sendableProgress( SendableProgress() );
+ sendableProgress.iMaxProgress = 1;
+
+ // Initialize the operation
+ InitializeOperationL();
+ if ( aIsRunning )
+ {
+ DLTRACE(("Setting state as EStateRunning"));
+ SetState( EStateRunning );
+ iIsPaused = ETrue;
+ }
+
+ DLTRACEOUT( ( "" ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle progress callback
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperationProxy::ProgressCallback()
+ {
+ DLTRACEIN( ( "this: %X", this ) );
+ TNcdSendableProgress& sendableProgress( SendableProgress() );
+ TNcdProgress progress( sendableProgress.iProgress,
+ sendableProgress.iMaxProgress );
+
+ iCurrentFile = sendableProgress.iState;
+ iFileCount = sendableProgress.iOperationId;
+
+ DLTRACE(("Progress: %d/%d", sendableProgress.iProgress,
+ sendableProgress.iMaxProgress ));
+
+ AddRef();
+ // Iterate backwards in case observers want to remove themselves
+ // from observers during callback
+ for ( TInt i = iObservers.Count() - 1; i >= 0; --i )
+ {
+ DLTRACE(("Calling observer"));
+ iObservers[i]->DownloadProgress( *this, progress );
+ }
+ Release();
+ DLTRACEOUT( ( "" ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle query received callback
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperationProxy::QueryReceivedCallback( CNcdQuery* /*aQuery*/ )
+ {
+ DLTRACEIN( ( "" ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle operation complete
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperationProxy::CompleteCallback( TInt aError )
+ {
+ DLTRACEIN( ( "Error: %d, this: %X", aError, this ) );
+ AddRef();
+ iIsPaused = EFalse;
+
+ if ( aError == KErrNone )
+ {
+ iCurrentFile = iFileCount;
+ }
+
+ if ( DownloadDataType() == ENcdContentDownload )
+ {
+ // The download operation for the purchased content has completed.
+ // Update the error code and operation time into the purchase history.
+ DLINFO(("Update purchase history"));
+ TRAP_IGNORE( UpdateOperationInfoToPurchaseHistoryL( aError ) );
+
+ // If no errors occurred during operation, then internalize the node.
+ if ( aError == KErrNone )
+ {
+ DLTRACE(("Updating related nodes"));
+ TRAP_IGNORE( NodeManager()->InternalizeRelatedNodesL( *NodeProxy() ) );
+ DLTRACE(("Node updated"));
+ }
+ }
+
+ DLTRACE(("Calling observers, count: %d", iObservers.Count() ));
+ // Iterate backwards in case observers want to remove themselves
+ // from observers during callback
+ for ( TInt i = iObservers.Count() - 1; i >= 0; --i )
+ {
+ iObservers[i]->OperationComplete( *this, aError );
+ }
+ DLTRACE(("Observers handled, this: %X", this));
+ Release();
+ DLTRACEOUT( ( "" ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Create initialization data sent to the server-side
+// ---------------------------------------------------------------------------
+//
+HBufC8* CNcdDownloadOperationProxy::CreateInitializationBufferL()
+ {
+ DLTRACEIN((""));
+ return KNullDesC8().AllocL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handle initialization callback
+// ---------------------------------------------------------------------------
+//
+void CNcdDownloadOperationProxy::InitializationCallback(
+ RReadStream& aReadStream, TInt /*aDataLength*/ )
+ {
+ DLTRACEIN( ( "" ) );
+ TRAP_IGNORE(
+ {
+ iCurrentFile = 1;
+ // Read file count from the stream
+ iFileCount = aReadStream.ReadInt32L();
+ iIsPaused = aReadStream.ReadInt32L();
+ });
+ DLTRACEOUT(( "%d files, paused: %d", iFileCount, iIsPaused ));
+ }
+
+
+void CNcdDownloadOperationProxy::DoCancel()
+ {
+ DLTRACEIN( ( "" ) );
+ // Let's internalize the node in cases of content download.
+ // This is needed for example in the following case:
+ // Cancel occurs when download notification is being sent to
+ // server. The content info has already been saved to purchase
+ // history. To enable retry of get after this cancellation
+ // the node information has to be transported from the
+ // server side to proxy side. This is done with internalize.
+ // Redownload from the actual server is not possible as it
+ // may have already received the installation confirmation.
+ if ( DownloadDataType() == ENcdContentDownload )
+ {
+ DLINFO(("Internalizing node in content download cancellation."));
+ // NOTICE: It is chosen that if the internalization fails then
+ // no error message is shown to user. This is because the
+ // cancellation can still be successfull and then it would be a
+ // bit misleading to show that the cancellation has failed. One
+ // possibility could be that in case of error the cancellation
+ // could be aborted, but it is probably more important to
+ // try the cancel than abort and show correct message.
+ // If the error message should still be shown, then this
+ // internalization should probably be done elsewhere.
+ // If this fails, then the outcome can be that the user
+ // cannot use option Get before the node is reinternalized.
+ // (This seems to happen with current implementation for example
+ // by pressing Back and re-entering the same folder)
+
+ // The download operation for the purchased content has completed.
+ // Update the error code and operation time into the purchase history.
+ DLINFO(("Update purchase history with cancel"));
+ TRAP_IGNORE( UpdateOperationInfoToPurchaseHistoryL( KErrCancel ) );
+
+ DLINFO(("Updating related nodes"));
+ TRAP_IGNORE( NodeManager()->InternalizeRelatedNodesL( *NodeProxy() ) );
+
+ DLINFO(("Node updated"));
+ }
+
+ CNcdBaseOperationProxy::DoCancel();
+ }