diff -r 000000000000 -r ba25891c3a9e ncdengine/provider/client/src/ncddownloadoperationproxy.cpp --- /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 +#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(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(); + }