--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/server/src/ncdoperationmanager.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1912 @@
+/*
+* 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 CNcdOperationManager class
+*
+*/
+
+
+#include "ncdoperationmanager.h"
+
+#include <e32err.h>
+#include <s32mem.h>
+
+#include "ncdbaseoperation.h"
+#include "ncdstoragemanager.h"
+#include "ncdprotocol.h"
+#include "catalogshttpsession.h"
+#include "ncdnodemanager.h"
+#include "catalogsbasemessage.h"
+#include "ncdloadnodeoperationimpl.h"
+#include "ncdloadrootnodeoperationimpl.h"
+#include "ncdloadbundlenodeoperationimpl.h"
+#include "ncdnodefunctionids.h"
+#include "ncddownloadoperationimpl.h"
+#include "ncdnodeidentifier.h"
+#include "ncdproviderdefines.h"
+#include "ncdstoragemanager.h"
+#include "ncdpurchasehistorydbimpl.h"
+#include "ncdconfigurationmanager.h"
+#include "catalogssmssession.h"
+#include "ncdpurchaseoperationimpl.h"
+#include "ncdnodeimpl.h"
+#include "ncdnodelink.h"
+#include "catalogscontext.h"
+#include "catalogshttpconfig.h"
+#include "catalogsutils.h"
+#include "ncdproviderimpl.h"
+#include "ncdinstalloperationimpl.h"
+#include "ncdchildloadmode.h"
+#include "ncdrightsobjectoperationimpl.h"
+#include "ncdutils.h"
+#include "ncdsearchoperationimpl.h"
+#include "ncdnodefolder.h"
+#include "ncdsubscriptionoperationimpl.h"
+#include "ncdsubscriptionmanagerimpl.h"
+#include "ncdcontentdownloadoperation.h"
+#include "ncdstorageclient.h"
+#include "ncdstorage.h"
+#include "ncdstorageitem.h"
+#include "ncddatabasestorage.h"
+#include "ncdnodemetadataimpl.h"
+#include "ncdreportmanager.h"
+#include "ncdcreateaccesspointoperationimpl.h"
+#include "ncdsendhttprequestoperationimpl.h"
+#include "ncdconnectionmethod.h"
+#include "ncdserverreportoperationimpl.h"
+#include "ncdoperationtype.h"
+#include "ncdnodeidentifiereditor.h"
+#include "ncderrors.h"
+#include "ncdgeneralmanager.h"
+
+#include "catalogsdebug.h"
+
+
+// Because of security issues these capabilities are set for silent install
+static _LIT_SECURITY_POLICY_C1( KSilentInstallInfoPolicy,
+ ECapabilityTrustedUI );
+
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CNcdOperationManager* CNcdOperationManager::NewL(
+ CNcdProvider& aProvider,
+ CNcdGeneralManager& aGeneralManager,
+ CNcdSubscriptionManager& aSubscriptionManager )
+ {
+ DLTRACEIN( ( "" ) );
+ CNcdOperationManager* self = new( ELeave ) CNcdOperationManager(
+ aProvider,
+ aGeneralManager,
+ aSubscriptionManager );
+
+ CleanupClosePushL( *self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ DLTRACEOUT( ( "" ) );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CNcdOperationManager::~CNcdOperationManager()
+ {
+ DLTRACEIN((""));
+ // Should we destroy the operations here if operations
+ // exist? operations should delete themselves when the operation
+ // is finished? This class may implement some interface that
+ // will be used to inform the manager when operation is
+ // finished...
+ // Close the cache array.
+
+ DLTRACE(("Closing operations"));
+
+
+ for ( TInt i = 0; i < iOperationCache.Count(); ++i )
+ {
+ iOperationCache[i]->Close();
+ }
+
+
+ DLTRACE(("Operations closed"));
+ iOperationCache.Reset();
+
+ iOperationQueue.Close();
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// CreateOperationL
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateLoadNodeOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+
+ DLTRACEIN((""));
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ DLTRACE(("create buffer"));
+
+ RBuf8 buf;
+ buf.CreateL( aMessage.InputLength() );
+ DLINFO(("input length=%d",aMessage.InputLength()));
+ CleanupClosePushL( buf );
+ User::LeaveIfError( aMessage.ReadInput( buf ) );
+
+
+ RDesReadStream stream( buf );
+ CleanupReleasePushL( stream );
+
+ DLTRACE(("get buffer data"));
+
+ // Create node identifier from the stream
+ CNcdNodeIdentifier* identifier = CNcdNodeIdentifier::NewLC(
+ stream );
+
+ if( ParallelOperationExistsForMetadataL( *identifier, aMessage.Session().Context() ) )
+ {
+ // Multiple simultaneous operations per one node are not supported, leave.
+ User::Leave( KNcdErrorParallelOperationNotAllowed );
+ }
+
+ DLTRACE(("get load children flag"));
+ TBool loadChildren = stream.ReadInt32L();
+ DLTRACE(("get pageSize"));
+ TInt pageSize = stream.ReadInt32L();
+ DLTRACE(("get pageStart"));
+ TInt pageStart = stream.ReadInt32L();
+ DLTRACE(("get depth"));
+ TInt depth = stream.ReadInt32L();
+ DLTRACE(("get mode"));
+ TNcdChildLoadMode mode = static_cast<TNcdChildLoadMode>(stream.ReadInt32L());
+ DLTRACE(("get search flag"));
+ TBool search = stream.ReadInt32L();
+ CNcdSearchFilter* filter = NULL;
+ if ( search )
+ {
+ DLTRACE(("get search filter"));
+ filter = CNcdSearchFilter::NewLC();
+ filter->SetContentPurposes( stream.ReadUint32L() );
+ TInt keywordCount = stream.ReadInt32L();
+ for ( TInt i = 0 ; i < keywordCount ; i++ )
+ {
+ HBufC* keyword = NULL;
+ InternalizeDesL( keyword, stream );
+ CleanupStack::PushL( keyword );
+ filter->AddKeywordL( *keyword );
+ CleanupStack::PopAndDestroy( keyword );
+ }
+ MNcdSearchFilter::TSearchMode mode;
+ InternalizeEnumL( mode, stream );
+ filter->SetSearchMode( mode );
+ filter->SetRecursionDepthL( stream.ReadUint32L() );
+ }
+
+ DLTRACE(( _L("id, size, start, depth: %S, %d, %d, %d"),
+ &identifier->NodeId(), pageSize, pageStart, depth ));
+
+
+ CNcdNode& node = iNodeManager.NodeL( *identifier );
+
+ DLTRACE(( _L("node found: %X"), &node ));
+
+ TNcdResponseFilterParams filterParams;
+ filterParams.iPageSize = pageSize;
+ filterParams.iPageStart = pageStart;
+ filterParams.iStructureDepth = depth;
+ filterParams.iMetadataDepth = depth;
+ filterParams.iMetadataPerLevel = pageSize;
+
+ // create the operation
+
+ CNcdLoadNodeOperationImpl* operation = NULL;
+ if( search )
+ {
+ DLTRACE(("Create search op"));
+ const CNcdNodeIdentifier* parentId = NULL;
+ if ( node.ClassId() == NcdNodeClassIds::ENcdSearchItemNodeClassId ||
+ node.ClassId() == NcdNodeClassIds::ENcdSearchFolderNodeClassId ||
+ node.ClassId() == NcdNodeClassIds::ENcdSearchRootNodeClassId ||
+ node.ClassId() == NcdNodeClassIds::ENcdSearchBundleNodeClassId )
+ {
+ DLTRACE(("search folder, use node's own parent"));
+ parentId = &node.CreateAndSetLinkL().ParentIdentifier();
+ }
+ else
+ {
+ DLTRACE(("not a search folder, set search root as parent"));
+ parentId =
+ &iNodeManager.CreateSearchRootL(aMessage.Session().Context()).Identifier();
+ }
+ // create op
+ operation = CNcdSearchOperation::NewL(
+ *identifier,
+ *parentId,
+ *filter,
+ filterParams,
+ iGeneralManager,
+ HttpSessionL( aMessage.Session().Context() ),
+ this, this, aMessage.Session(), loadChildren, mode,
+ filter->RecursionDepth() );
+ }
+ else
+ {
+ DLTRACE(("Create load op"));
+ CNcdNodeFactory::TNcdNodePurpose parentPurpose = CNcdNodeFactory::ENcdNormalNode;
+ if ( !node.NodeLinkL().ParentIdentifier().ContainsEmptyFields() )
+ {
+ CNcdNode* parentNode = iNodeManager.NodePtrL( node.NodeLinkL().ParentIdentifier() );
+ if ( parentNode )
+ {
+ parentPurpose = CNcdNodeFactory::NodePurposeL( *parentNode );
+ }
+ }
+ operation = CNcdLoadNodeOperationImpl::NewL(
+ *identifier,
+ node.NodeLinkL().ParentIdentifier(),
+ parentPurpose,
+ filterParams,
+ iGeneralManager,
+ HttpSessionL( aMessage.Session().Context() ),
+ this, this, aMessage.Session(), loadChildren, mode, EFalse, EFalse );
+ }
+
+ DLTRACE(( _L("operation created: %X"), operation ));
+ if( filter )
+ {
+ CleanupStack::PopAndDestroy( filter );
+ }
+ CleanupStack::PopAndDestroy( identifier );
+ CleanupStack::PopAndDestroy( &stream );
+ CleanupStack::PopAndDestroy( &buf );
+
+
+ CleanupStack::PushL( operation );
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+ operation->SetHandle( operationHandle );
+
+ // AddObjectL adds reference count by 1
+ operation->Close();
+ DLTRACE(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ // Is this ok?
+ User::Leave( error );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CreateOperationL
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateLoadRootNodeOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+
+ DLTRACEIN((""));
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+
+ RBuf8 nodeIdentifierData;
+ nodeIdentifierData.CreateL( aMessage.InputLength() );
+ CleanupClosePushL( nodeIdentifierData );
+ User::LeaveIfError( aMessage.ReadInput( nodeIdentifierData ) );
+
+ // Create node identifier from the stream
+ CNcdNodeIdentifier* identifier = CNcdNodeIdentifier::NewLC(
+ nodeIdentifierData );
+
+ if( ParallelOperationExistsForMetadataL( *identifier, aMessage.Session().Context(),
+ ETrue ) )
+ {
+ // Multiple simultaneous operations per one node are not supported, leave.
+ User::Leave( KNcdErrorParallelOperationNotAllowed );
+ }
+
+ // create the operation
+ CNcdLoadRootNodeOperation* operation = CNcdLoadRootNodeOperation::NewL(
+ aMessage.Session().Context().FamilyId().iUid,
+ iGeneralManager,
+ HttpSessionL( aMessage.Session().Context() ),
+ this,
+ aMessage.Session() );
+ CleanupStack::PopAndDestroy( identifier );
+ CleanupStack::PopAndDestroy( &nodeIdentifierData );
+
+ CleanupStack::PushL( operation );
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+
+ operation->SetHandle( operationHandle );
+
+ operation->Close();
+ DLTRACE(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CreateLoadBundleNodeOperationRequestL
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateLoadBundleNodeOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+
+ DLTRACEIN((""));
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ RBuf8 nodeIdentifierData;
+ nodeIdentifierData.CreateL( aMessage.InputLength() );
+ CleanupClosePushL( nodeIdentifierData );
+ User::LeaveIfError( aMessage.ReadInput( nodeIdentifierData ) );
+
+ // Create node identifier from the stream
+ CNcdNodeIdentifier* identifier = CNcdNodeIdentifier::NewLC(
+ nodeIdentifierData );
+
+ if( ParallelOperationExistsForMetadataL( *identifier, aMessage.Session().Context() ) )
+ {
+ // Multiple simultaneous operations per one node are not supported, leave.
+ User::Leave( KNcdErrorParallelOperationNotAllowed );
+ }
+
+ // create the operation
+ CNcdLoadBundleNodeOperation* operation = CNcdLoadBundleNodeOperation::NewL(
+ *identifier,
+ iGeneralManager,
+ HttpSessionL( aMessage.Session().Context() ),
+ this,
+ *this,
+ aMessage.Session() );
+ CleanupStack::PopAndDestroy( identifier );
+ CleanupStack::PopAndDestroy( &nodeIdentifierData );
+
+ CleanupStack::PushL( operation );
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+
+ operation->SetHandle( operationHandle );
+
+ operation->Close();
+ DLTRACE(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CreateDownloadOperationL
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateDownloadOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+
+ DLTRACEIN((""));
+
+ RCatalogsMessageReader reader;
+ reader.OpenLC( aMessage );
+
+ // Read operation type
+ TNcdDownloadDataType type = static_cast<TNcdDownloadDataType>(
+ reader().ReadInt32L() );
+
+ DLINFO(( "Operation type: %d", type ));
+ // Create node identifier from the stream
+ CNcdNodeIdentifier* identifier = CNcdNodeIdentifier::NewLC(
+ reader() );
+
+ if( ParallelOperationExistsForMetadataL( *identifier, aMessage.Session().Context(),
+ type == ENcdGenericFileDownload ) )
+ {
+ // Multiple simultaneous operations per one node are not supported, leave.
+ User::Leave( KNcdErrorParallelOperationNotAllowed );
+ }
+
+ DLINFO(( _L("NodeId: %S::%S"), &identifier->NodeNameSpace(),
+ &identifier->NodeId() ));
+
+ // Read download index
+ TInt downloadIndex = reader().ReadInt32L();
+ DLINFO(( "Download index: %d", downloadIndex ));
+
+ // Check if the download already exists, completes the message
+ // if it does
+ if ( DownloadExistsL( aMessage, *identifier, type, downloadIndex ) )
+ {
+ DLTRACE(("Download already exists"));
+ CleanupStack::PopAndDestroy( 2, &reader ); // identifier, reader
+ return;
+ }
+
+ CleanupStack::Pop( identifier );
+ CleanupStack::PopAndDestroy( &reader ); // reader
+ CleanupStack::PushL( identifier );
+
+ // Get current context
+ MCatalogsContext& context( aMessage.Session().Context() );
+
+ HBufC* clientUid = context.FamilyId().Name().AllocLC();
+
+ MNcdStorageClient* storageClient = NULL;
+ // Generic file download doesn't use storage
+ if ( type != ENcdGenericFileDownload )
+ {
+
+ // Quick fix: ensures that StorageManager has the client
+ MNcdStorage* storage = StorageL( *clientUid,
+ identifier->NodeNameSpace() );
+
+ // Find the correct storage for the client
+ storageClient =
+ &iStorageManager.StorageClientL( *clientUid );
+ }
+
+
+ DLTRACE(("Creating the download operation"));
+
+ // Try to get session handler
+ MNcdSessionHandler* sessionHandler = NULL;
+ TRAP_IGNORE(
+ sessionHandler = &iProtocolHandler.SessionHandlerL( context ) );
+
+ CNcdBaseOperation* operation = NULL;
+ if ( type != ENcdContentDownload )
+ {
+ // Create operation according to it's type
+ operation = CNcdDownloadOperation::NewL(
+ *this,
+ type,
+ *identifier,
+ iGeneralManager,
+ HttpSessionL( context ),
+ sessionHandler,
+ storageClient,
+ context.FamilyId(),
+ downloadIndex,
+ aMessage.Session() );
+ }
+ else
+ {
+ MNcdStorage* dlStorage = StorageL( *clientUid,
+ NcdProviderDefines::KDownloadNamespace );
+
+ // Create operation according to it's type
+ operation = CNcdContentDownloadOperation::NewL(
+ *this,
+ *identifier,
+ iGeneralManager,
+ HttpSessionL( context ),
+ ReportManagerL( context ),
+ sessionHandler,
+ dlStorage->DatabaseStorageL(
+ NcdProviderDefines::KDefaultDatabaseUid ),
+ aMessage.Session(),
+ downloadIndex );
+ }
+ DLTRACE(("Download operation created"));
+ CleanupStack::PopAndDestroy( clientUid );
+ CleanupStack::PopAndDestroy( identifier );
+ CleanupStack::PushL( operation );
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+ operation->SetHandle( operationHandle );
+ operation->Close();
+ DLTRACE(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+ DLTRACEOUT((""));
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// CreatePurchaseOperationL
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreatePurchaseOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ // Should use 8 bit version when client-server session supports it
+ RBuf8 buf;
+ buf.CreateL( aMessage.InputLength() );
+ DLINFO(("input length=%d",aMessage.InputLength()));
+ CleanupClosePushL( buf );
+ User::LeaveIfError( aMessage.ReadInput( buf ) );
+
+ RDesReadStream stream( buf );
+
+ CleanupReleasePushL( stream );
+
+ // Create node identifier from the stream
+ CNcdNodeIdentifier* identifier = CNcdNodeIdentifier::NewLC(
+ stream );
+
+ if( ParallelOperationExistsForMetadataL( *identifier, aMessage.Session().Context() ) )
+ {
+ // Multiple simultaneous operations per one node are not supported, leave.
+ User::Leave( KNcdErrorParallelOperationNotAllowed );
+ }
+
+ HBufC* purchaseOptionId = NULL;
+ TInt length = InternalizeDesL( purchaseOptionId, stream );
+ CleanupStack::PushL( purchaseOptionId );
+
+ if( length < 1 )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ // create the operation
+ CNcdPurchaseOperationImpl* operation = CNcdPurchaseOperationImpl::NewL(
+ identifier->NodeNameSpace(),
+ identifier->NodeId(),
+ identifier->ClientUid(),
+ *purchaseOptionId,
+ iGeneralManager,
+ HttpSessionL( aMessage.Session().Context() ),
+ SmsSessionL( aMessage.Session().Context() ),
+ iSubscriptionManager,
+ this,
+ aMessage.Session() );
+
+
+ CleanupStack::PopAndDestroy( purchaseOptionId );
+ CleanupStack::PopAndDestroy( identifier );
+ CleanupStack::PopAndDestroy( &stream );
+ CleanupStack::PopAndDestroy( &buf );
+
+
+ CleanupStack::PushL( operation );
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+ operation->SetHandle( operationHandle );
+
+ // AddObjectL adds reference count by 1
+ operation->Close();
+
+ DLTRACE(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// Create install operation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateInstallOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+
+ RBuf8 nodeIdentifierData;
+ nodeIdentifierData.CreateL( aMessage.InputLength() );
+ CleanupClosePushL( nodeIdentifierData );
+ User::LeaveIfError( aMessage.ReadInput( nodeIdentifierData ) );
+
+ // Create node identifier from the stream
+ CNcdNodeIdentifier* identifier = CNcdNodeIdentifier::NewLC(
+ nodeIdentifierData );
+
+ if( ParallelOperationExistsForMetadataL( *identifier, aMessage.Session().Context() ) )
+ {
+ // Multiple simultaneous operations per one node are not supported, leave.
+ User::Leave( KNcdErrorParallelOperationNotAllowed );
+ }
+
+ // create the operation
+ MCatalogsContext& context( requestSession.Context() );
+ CNcdInstallOperation* operation = CNcdInstallOperation::NewL(
+ *this,
+ *identifier,
+ iGeneralManager,
+ HttpSessionL( context ),
+ ReportManagerL( context ),
+ aMessage.Session() );
+
+ CleanupStack::PopAndDestroy( identifier );
+ CleanupStack::PopAndDestroy( &nodeIdentifierData );
+
+
+ CleanupStack::PushL( operation );
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+ operation->SetHandle( operationHandle );
+
+ // AddObjectL adds reference count by 1
+ operation->Close();
+
+ DLTRACE(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Create silent install operation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateSilentInstallOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ if ( !aMessage.CheckSecurityPolicy( KSilentInstallInfoPolicy() ) )
+ {
+ DLTRACE(("Not enough capabilities for silent install"));
+ User::Leave( KErrPermissionDenied );
+ }
+
+ // If there are enough capabilities, then just create a normal
+ // install operation
+ CreateInstallOperationRequestL( aMessage );
+
+ DLTRACEOUT((""));
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// Create rights object download and install operation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateRightsObjectOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DCHECK_CSTACK;
+ DLTRACEIN((""));
+
+ // Read input data buffer
+ RBuf8 buf;
+ buf.CreateL( aMessage.InputLength() );
+ DLINFO(("input length=%d",aMessage.InputLength()));
+ CleanupClosePushL( buf );
+ User::LeaveIfError( aMessage.ReadInput( buf ) );
+
+ // Create a stream for reading out of the buffer
+ RDesReadStream stream( buf );
+ CleanupClosePushL( stream );
+
+ // Read uri
+ HBufC* downloadUri = NULL;
+ InternalizeDesL( downloadUri, stream );
+ CleanupStack::PushL( downloadUri );
+ DLINFO((_L("Uri %S"), downloadUri ));
+
+ // Read mime type
+ HBufC* mimeType = NULL;
+ InternalizeDesL( mimeType, stream );
+ CleanupStack::PushL( mimeType );
+ DLINFO((_L("Mime type %S"), mimeType ));
+
+ // Read access point id
+ TNcdConnectionMethod method;
+ method.InternalizeL( stream );
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ // create the operation
+ CNcdRightsObjectOperation* operation = CNcdRightsObjectOperation::NewL(
+ iGeneralManager,
+ *downloadUri,
+ *mimeType,
+ method,
+ *this,
+ HttpSessionL( aMessage.Session().Context() ),
+ aMessage.Session() );
+ CleanupStack::PushL( operation );
+
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+
+ operation->SetHandle( operationHandle );
+
+ // AddObjectL adds reference count by 1
+ operation->Close();
+
+ DLINFO(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+
+ CleanupStack::PopAndDestroy( 4 ); // mimeType, downloadUri, stream-close, buf-close
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Create subscription operation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateSubscriptionOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ DLTRACE(("create buffer"));
+
+ RBuf8 buf;
+ buf.CreateL( aMessage.InputLength() );
+ DLINFO(( "input length=%d", aMessage.InputLength() ));
+ CleanupClosePushL( buf );
+ User::LeaveIfError( aMessage.ReadInput( buf ) );
+
+ RDesReadStream stream( buf );
+ CleanupReleasePushL( stream );
+
+ DLTRACE(("get buffer data"));
+
+ MNcdSubscriptionOperation::TType subscriptionOperationType =
+ (MNcdSubscriptionOperation::TType)stream.ReadInt32L();
+
+ CNcdSubscriptionOperation* operation( NULL );
+
+ switch ( subscriptionOperationType )
+ {
+ case MNcdSubscriptionOperation::EUnsubscribe:
+ {
+
+ DLINFO(( "-> EUnsubscribe" ));
+
+ HBufC* subscriptionPurchaseOptionId( NULL );
+ HBufC* subscriptionEntityId( NULL );
+ HBufC* subscriptionNamespace( NULL );
+ HBufC* subscriptionServerUri( NULL );
+
+ InternalizeDesL( subscriptionPurchaseOptionId, stream );
+ CleanupStack::PushL( subscriptionPurchaseOptionId );
+
+ InternalizeDesL( subscriptionEntityId, stream );
+ CleanupStack::PushL( subscriptionEntityId );
+
+ InternalizeDesL( subscriptionNamespace, stream );
+ CleanupStack::PushL( subscriptionNamespace );
+
+ InternalizeDesL( subscriptionServerUri, stream );
+ CleanupStack::PushL( subscriptionServerUri );
+
+ operation =
+ CNcdSubscriptionOperation::NewL(
+ MNcdSubscriptionOperation::EUnsubscribe,
+ *subscriptionPurchaseOptionId,
+ *subscriptionEntityId,
+ *subscriptionNamespace,
+ *subscriptionServerUri,
+ iGeneralManager,
+ iSubscriptionManager,
+ HttpSessionL( aMessage.Session().Context() ),
+ *this,
+ requestSession );
+
+ CleanupStack::PopAndDestroy( subscriptionServerUri );
+ CleanupStack::PopAndDestroy( subscriptionNamespace );
+ CleanupStack::PopAndDestroy( subscriptionEntityId );
+ CleanupStack::PopAndDestroy( subscriptionPurchaseOptionId );
+
+ break;
+ }
+
+ case MNcdSubscriptionOperation::ERefreshSubscriptions:
+ {
+ DLINFO(( "-> ERefreshSubscriptions" ));
+
+ operation =
+ CNcdSubscriptionOperation::NewL(
+ MNcdSubscriptionOperation::ERefreshSubscriptions,
+ iGeneralManager,
+ iSubscriptionManager,
+ HttpSessionL( aMessage.Session().Context() ),
+ *this,
+ requestSession );
+
+ break;
+ }
+
+ default:
+ {
+ User::Leave( KErrNotSupported );
+
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &stream );
+ CleanupStack::PopAndDestroy( &buf );
+
+ CleanupClosePushL( *operation );
+
+ DLTRACE(( _L("operation created: %X"), operation ));
+
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+ operation->SetHandle( operationHandle );
+
+ // AddObjectL adds reference count by 1
+ operation->Close();
+ DLTRACE(( "operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error, aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ // Is this ok?
+ User::Leave( error );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// Create access point creation operation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateCreateAccessPointOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ RCatalogsMessageReader reader;
+ reader.OpenLC( aMessage );
+
+ HBufC* accessPointData = NULL;
+ InternalizeDesL( accessPointData, reader() );
+
+ CleanupStack::PopAndDestroy( &reader );
+ CleanupStack::PushL( accessPointData );
+
+ DLINFO((_L("Data: %S"), accessPointData ));
+
+ // create the operation
+ // Note that ownership of accessPointData is transferred
+ CNcdCreateAccessPointOperation* operation = CNcdCreateAccessPointOperation::NewL(
+ accessPointData,
+ *this,
+ iGeneralManager,
+ aMessage.Session() );
+ CleanupStack::Pop( accessPointData );
+ CleanupStack::PushL( operation );
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+
+ operation->SetHandle( operationHandle );
+
+ // AddObjectL adds reference count by 1
+ operation->Close();
+
+ DLINFO(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+
+ DLTRACEOUT((""));
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// Send HTTP request operation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateSendHttpRequestOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ RCatalogsMessageReader reader;
+ reader.OpenLC( aMessage );
+
+ TNcdConnectionMethod method;
+ method.InternalizeL( reader() );
+
+ HBufC8* uri = NULL;
+ InternalizeDesL( uri, reader() );
+ CleanupStack::PushL( uri );
+
+ HBufC8* request = NULL;
+ InternalizeDesL( request, reader() );
+
+ CleanupStack::PushL( request );
+
+ DLINFO((_L("Data: %S"), request ));
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ // create the operation
+ // Note that ownership of accessPointData is transferred
+ CNcdSendHttpRequestOperation* operation = CNcdSendHttpRequestOperation::NewL(
+ uri,
+ request,
+ method,
+ iGeneralManager,
+ *this,
+ HttpSessionL( requestSession.Context() ),
+ aMessage.Session() );
+ CleanupStack::Pop( 2, uri ); // request, uri
+ CleanupStack::PopAndDestroy( &reader );
+ CleanupStack::PushL( operation );
+
+
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+
+ operation->SetHandle( operationHandle );
+
+ // AddObjectL adds reference count by 1
+ operation->Close();
+
+ DLINFO(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+
+
+ }
+
+
+// ---------------------------------------------------------------------------
+// Restore serialized downloads
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::RestoreDownloadOperationsRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ // Get current context
+ MCatalogsContext& context( aMessage.Session().Context() );
+
+ HBufC* clientUid = context.FamilyId().Name().AllocLC();
+
+
+ // Get client's download storage
+ MNcdStorage* storage = StorageL( *clientUid,
+ NcdProviderDefines::KDownloadNamespace );
+
+
+ CleanupStack::PopAndDestroy( clientUid );
+ DLTRACE(("Creating the download operation"));
+
+ // Get download db
+ MNcdDatabaseStorage& db( storage->DatabaseStorageL(
+ NcdProviderDefines::KDefaultDatabaseUid ) );
+
+ // Write the handles of resumed operations and return
+ // them to the client-side
+ RCatalogsBufferWriter writer;
+ writer.OpenLC();
+
+
+ // Get all items from the db
+ RPointerArray<MNcdStorageItem> items;
+ db.StorageItemsL( items );
+ CleanupClosePushL( items );
+
+ DLTRACE(("Internalizing %d downloads", items.Count() ));
+
+ MCatalogsHttpSession& httpSession( HttpSessionL( context ) );
+
+ CNcdReportManager& reportManager( ReportManagerL( context ) );
+
+ for ( TInt i = 0; i < items.Count(); ++i )
+ {
+ // Create operation
+ CNcdContentDownloadOperation* operation =
+ CNcdContentDownloadOperation::NewLC(
+ *this,
+ iGeneralManager,
+ httpSession,
+ reportManager,
+ db,
+ aMessage.Session() );
+
+ // Internalize from db
+ items[i]->SetDataItem( operation );
+ items[i]->ReadDataL();
+
+ if ( operation->IsOk() &&
+ !ParallelOperationExistsForMetadataL( operation->NodeId(),
+ aMessage.Session().Context() ) )
+ {
+ TInt32 operationHandle( aMessage.Session().AddObjectL( operation ) );
+ DLTRACE(("operation handle: %d", operationHandle ));
+ operation->SetHandle( operationHandle );
+ operation->Close();
+
+ // Add to operation cache
+ iOperationCache.AppendL( operation );
+
+ CleanupStack::Pop( operation );
+
+ // add object data
+ ExternalizeEnumL(
+ NcdProviderDefines::ENcdStreamDataObject, writer() );
+
+ // Write handle
+ writer().WriteInt32L( operationHandle );
+
+ // Write type
+ writer().WriteInt32L( ENcdContentDownload );
+
+ // Write metadata id
+
+ operation->MetadataId().ExternalizeL( writer() );
+
+ writer().WriteInt32L( operation->CurrentDownload() );
+
+ reportManager.SetReportsAsUsedL( operation->MetadataId() );
+ DLTRACE(("Download operation created"));
+ }
+ else
+ {
+ DLTRACE(("Removing failed download"));
+ TRAP_IGNORE( items[i]->RemoveFromStorageL() );
+ DLTRACE(("Pop&Destroy"));
+ CleanupStack::PopAndDestroy( operation );
+ }
+ }
+
+ if ( items.Count() )
+ {
+ DLTRACE(("Commit"));
+ db.CommitL();
+ }
+
+ // mark stream end
+ ExternalizeEnumL( NcdProviderDefines::ENcdStreamDataEnd, writer() );
+ CleanupStack::PopAndDestroy( &items );
+
+ // Delete downloads that were not restored
+ httpSession.DeleteRestoredDownloads();
+
+ reportManager.RemoveUnusedReportsL();
+
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( writer.PtrL(), KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+
+ // writer, operationHandles
+ CleanupStack::PopAndDestroy( &writer );
+
+ DLTRACEOUT((""));
+
+ }
+
+// ---------------------------------------------------------------------------
+// Create server report operation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CreateServerReportOperationRequestL(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ // Get the session that will contain the handle of the node
+ MCatalogsSession& requestSession( aMessage.Session() );
+
+ // create the operation
+ // Get current context
+ MCatalogsContext& context( aMessage.Session().Context() );
+ CNcdServerReportOperation* operation = CNcdServerReportOperation::NewL(
+ iGeneralManager,
+ *this,
+ ReportManagerL( context ),
+ aMessage.Session() );
+
+ CleanupStack::PushL( operation );
+ // Add the operation to the session and get the handle.
+ // If the operation already existed in the session we will still
+ // get a new handle to the same object.
+ TInt32 operationHandle( requestSession.AddObjectL( operation ) );
+ operation->SetHandle( operationHandle );
+
+ // AddObjectL adds reference count by 1
+ operation->Close();
+
+ DLTRACE(("operation handle: %d", operationHandle ));
+
+ // Because we created a new operation, it should be added to the
+ // cache.
+ iOperationCache.AppendL( operation );
+ CleanupStack::Pop( operation );
+
+ // Send the information to the client side
+ TRAPD( error,
+ aMessage.CompleteAndReleaseL( operationHandle, KErrNone ) );
+ if( error != KErrNone )
+ {
+ iOperationCache.Remove( iOperationCache.Count() - 1 );
+ }
+ DLTRACEOUT((""));
+ }
+
+
+MCatalogsHttpSession& CNcdOperationManager::HttpSessionL( MCatalogsContext& aContext )
+ {
+ TNcdProviderContext providerContext;
+ iProvider.GetProviderContextL( aContext, providerContext );
+ return *providerContext.iHttpSession;
+ }
+
+MCatalogsSmsSession& CNcdOperationManager::SmsSessionL( MCatalogsContext& aContext )
+ {
+ TNcdProviderContext providerContext;
+ iProvider.GetProviderContextL( aContext, providerContext );
+ return *providerContext.iSmsSession;
+ }
+
+CNcdReportManager& CNcdOperationManager::ReportManagerL( MCatalogsContext& aContext )
+ {
+ TNcdProviderContext providerContext;
+ iProvider.GetProviderContextL( aContext, providerContext );
+ return *providerContext.iReportManager;
+ }
+
+
+// ---------------------------------------------------------------------------
+// ReceiveMessage
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::ReceiveMessage( MCatalogsBaseMessage* aMessage,
+ TInt aFunctionNumber )
+ {
+ DLTRACEIN((""));
+
+ // The message is always required.
+ if( aMessage == NULL )
+ {
+ // Do not do anything here because we can not give any
+ // feedback
+ return;
+ }
+
+ TInt trapError( KErrNone );
+
+ switch( aFunctionNumber )
+ {
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateLoadNodeOperation:
+ DLTRACE(("Creating load node operation"));
+
+ TRAP( trapError, CreateLoadNodeOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateDownloadOperation:
+ DLTRACE(("Creating download operation"));
+
+ TRAP( trapError, CreateDownloadOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateLoadRootNodeOperation:
+ DLTRACE(("Creating load root node operation"));
+
+ TRAP( trapError, CreateLoadRootNodeOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateLoadBundleNodeOperation:
+ DLTRACE(("Creating load bundle node operation"));
+
+ TRAP( trapError, CreateLoadBundleNodeOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreatePurchaseOperation:
+ DLTRACE(("Creating purchase operation"));
+
+ TRAP( trapError, CreatePurchaseOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateRightsObjectOperation:
+ DLTRACE(("Creating rights object download and install operation"));
+
+ TRAP( trapError, CreateRightsObjectOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateInstallOperation:
+ DLTRACE(("Creating install operation"));
+
+ TRAP( trapError, CreateInstallOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateSilentInstallOperation:
+ DLTRACE(("Creating install operation"));
+
+ TRAP( trapError, CreateSilentInstallOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateSubscriptionOperation:
+ DLTRACE(("Creating subscription operation"));
+
+ TRAP( trapError, CreateSubscriptionOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerRestoreContentDownloads:
+ DLTRACE(("Restoring downloads"));
+
+ TRAP( trapError, RestoreDownloadOperationsRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateCreateAccessPointOperation:
+ DLTRACE(("Creating create accesspoint operation"));
+
+ TRAP( trapError, CreateCreateAccessPointOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateSendHttpRequestOperation:
+ DLTRACE(("Creating HTTP request sending operation"));
+
+ TRAP( trapError, CreateSendHttpRequestOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdOperationManagerCreateServerReportOperation:
+ DLTRACE(("Creating server report operation"));
+
+ TRAP( trapError, CreateServerReportOperationRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdRelease:
+ ReleaseRequest( *aMessage );
+ break;
+
+ default:
+ DASSERT( 0 );
+ break;
+ }
+
+ if ( trapError != KErrNone )
+ {
+ // Because something went wrong the complete has not been
+ // yet called for the message.
+ // So, inform the client about the error.
+ DLTRACE(("ERROR, Complete and release %d", trapError));
+
+ aMessage->CompleteAndRelease( trapError );
+ }
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// CounterPartLost
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::CounterPartLost( const MCatalogsSession& /*aSession*/ )
+ {
+ DLTRACEIN((""));
+ DLTRACEOUT((""));
+
+ }
+
+
+// ---------------------------------------------------------------------------
+// RemoveOperation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::RemoveOperation( CNcdBaseOperation& aOperation )
+ {
+ DLTRACEIN((""));
+ TInt index = iOperationCache.Find( &aOperation );
+ if ( index != KErrNotFound )
+ {
+ DLTRACE(("Removing operation"));
+ iOperationCache.Remove( index );
+ }
+
+ index = iOperationQueue.Find( &aOperation );
+ if ( index != KErrNotFound )
+ {
+ // Should never come here.
+ DASSERT( EFalse );
+ iOperationQueue.Remove( index );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// QueueOperation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::QueueOperationL( CNcdBaseOperation& aOperation )
+ {
+ DLTRACEIN(("queue size: %d", iOperationQueue.Count()));
+ iOperationQueue.AppendL( &aOperation );
+
+ // Start the operation if it is the only one in queue, or there are no load bundle
+ // node operations which may lock the database. If the operation is a load bundle operation
+ // it should not be started if the queue is not empty since there are other operations
+ // running.
+ if ( aOperation.Type() == ELoadBundleNodeOperation )
+ {
+ if ( iOperationQueue.Count() == 1 )
+ {
+ aOperation.RunOperation();
+ }
+ }
+ else
+ {
+ if ( !QueuedLoadBundleOperationsExists() )
+ {
+ aOperation.RunOperation();
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// QueueOperation
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::QueuedOperationComplete( CNcdBaseOperation& aOperation )
+ {
+ DLTRACEIN(("operation-ptr: %x", &aOperation));
+
+ TInt index = iOperationQueue.Find( &aOperation );
+
+ if ( index != KErrNotFound )
+ {
+ iOperationQueue.Remove( index );
+
+ // Start new operations only if the completed one was the first in queue since
+ // the first one is otherwise running still.
+ if ( index == 0 && iOperationQueue.Count() )
+ {
+ if ( iOperationQueue[ 0 ]->Type() == ELoadBundleNodeOperation )
+ {
+ // If the next in queue is load bundle node, it can be started since
+ // it is not started yet.
+ iOperationQueue[ 0 ]->ContinueOperationL();
+ }
+
+ else if ( aOperation.Type() == ELoadBundleNodeOperation )
+ {
+ // Completed operation was a bundle load op, so the next in queue are not
+ // started yet. Start the next operations in queue before the first load
+ // bundle node operation.
+ for ( TInt i = 0; i < iOperationQueue.Count(); i++ )
+ {
+ if ( iOperationQueue[ i ]->Type() != ELoadBundleNodeOperation )
+ {
+ iOperationQueue[ i ]->ContinueOperationL();
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CNcdOperationManager::CNcdOperationManager(
+ CNcdProvider& aProvider,
+ CNcdGeneralManager& aGeneralManager,
+ CNcdSubscriptionManager& aSubscriptionManager )
+ :
+ CCatalogsCommunicable(),
+ iProvider( aProvider ),
+ iGeneralManager( aGeneralManager ),
+ iStorageManager( aGeneralManager.StorageManager() ),
+ iProtocolHandler( aGeneralManager.ProtocolManager() ),
+ iNodeManager( aGeneralManager.NodeManager() ),
+ iPurchaseHistory( aGeneralManager.PurchaseHistory() ),
+ iConfigurationManager( aGeneralManager.ConfigurationManager() ),
+ iAccessPointManager( aGeneralManager.AccessPointManager() ),
+ iSubscriptionManager( aSubscriptionManager )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::ConstructL()
+ {
+ DLTRACEIN( ( "this: %X", this ) );
+
+ DLTRACEOUT( ( "" ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// StorageL
+// ---------------------------------------------------------------------------
+//
+MNcdStorage* CNcdOperationManager::StorageL( const TDesC& aClientUid,
+ const TDesC& aNamespace ) const
+ {
+ DLTRACEIN((""));
+ MNcdStorage* storage = NULL;
+
+
+ DLTRACE(( _L("Namespace: %S"), &aNamespace ));
+ TRAPD( err, storage = &iStorageManager.StorageL( aClientUid, aNamespace ) );
+
+ if ( err == KErrNotFound )
+ {
+ DLTRACE(("Creating storage for the client"));
+ err = KErrNone;
+ TRAP( err, storage = &iStorageManager.CreateStorageL( aClientUid, aNamespace ) );
+
+ if ( err == KErrAlreadyExists )
+ {
+ err = KErrNone;
+ storage = &iStorageManager.StorageL( aClientUid, aNamespace );
+ }
+ }
+
+ if ( err != KErrNone )
+ {
+ DLTRACE(("Leaving: %i", err));
+ User::Leave( err );
+ }
+
+ DLTRACEOUT((""));
+ return storage;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Release request
+// ---------------------------------------------------------------------------
+//
+void CNcdOperationManager::ReleaseRequest( MCatalogsBaseMessage& aMessage ) const
+ {
+ DLTRACEIN((""));
+
+ // Decrease the reference count for this object.
+ // When the reference count reaches zero, this object will be destroyed
+ // and removed from the session.
+ MCatalogsSession& requestSession( aMessage.Session() );
+ TInt handle( aMessage.Handle() );
+ aMessage.CompleteAndRelease( KErrNone );
+ requestSession.RemoveObject( handle );
+
+ DLTRACEOUT((""));
+ }
+
+
+// ---------------------------------------------------------------------------
+// Checks if a download already exists
+// ---------------------------------------------------------------------------
+//
+TBool CNcdOperationManager::DownloadExistsL( MCatalogsBaseMessage& aMessage,
+ const CNcdNodeIdentifier& aIdentifier,
+ TNcdDownloadDataType aType,
+ TInt aIndex )
+ {
+ DLTRACEIN(("Op cache count: %d", iOperationCache.Count()));
+ TInt32 handle = 0;
+
+ const CNcdNodeIdentifier* metaId = &aIdentifier;
+
+ // Use metadata id's for comparison since temp nodes have different
+ // node id's but same metadata id's as normal nodes
+ //
+ // Generic file downloads don't have node nor metadata. The given node id
+ // contains the URL and target filename
+ if ( aType != ENcdGenericFileDownload )
+ {
+ DLTRACE(("Not skin nor generic DL, getting metadata id"));
+
+ metaId = &iNodeManager.NodeL( aIdentifier ).NodeMetaDataL().Identifier();
+ }
+
+ for ( TInt i = 0; i < iOperationCache.Count(); ++i )
+ {
+ // Check other downloads but content
+ if ( aType != ENcdContentDownload &&
+ iOperationCache[i]->Type() ==
+ EDownloadOperation )
+ {
+ CNcdDownloadOperation* op = static_cast<CNcdDownloadOperation*>(
+ iOperationCache[i] );
+ if ( op->MatchDownload( *metaId, aType, aIndex ) )
+ {
+ DLTRACE(("Found a matching download"));
+ handle = op->Handle();
+ break;
+ }
+ }
+ // check content downloads
+ else if ( aType == ENcdContentDownload &&
+ iOperationCache[i]->Type() ==
+ EContentDownloadOperation )
+ {
+ CNcdContentDownloadOperation* op = static_cast<
+ CNcdContentDownloadOperation*>(
+ iOperationCache[i] );
+ if ( op->MatchDownload( *metaId, aType, aIndex ) )
+ {
+ DLTRACE(("Found a matching content download"));
+ handle = op->Handle();
+ break;
+ }
+ }
+ }
+ if ( handle )
+ {
+ // Send the information to the client side
+ aMessage.CompleteAndReleaseL( handle, KErrNone );
+ return ETrue;
+ }
+ DLTRACEOUT(("No matching download"));
+ return EFalse;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Checks if there are load bundle node operations in operation queue.
+// ---------------------------------------------------------------------------
+//
+TBool CNcdOperationManager::QueuedLoadBundleOperationsExists() const
+ {
+ DLTRACEIN((""));
+ TInt queueSize = iOperationQueue.Count();
+ for ( TInt i = 0; i < queueSize; i++ )
+ {
+ if ( iOperationQueue[ i ]->Type() == ELoadBundleNodeOperation )
+ {
+ DLINFO(("queued load bundle op exists"));
+ return ETrue;
+ }
+ }
+
+ DLINFO(("no queued load bundle op"));
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// Checks if there are on-going operations for the metadata for another client
+// ---------------------------------------------------------------------------
+//
+TBool CNcdOperationManager::ParallelOperationExistsForMetadataL(
+ const CNcdNodeIdentifier& aNodeIdentifier,
+ const MCatalogsContext& aContext,
+ TBool aCompareIdsDirectly ) const
+ {
+ DLTRACEIN((""));
+ const CNcdNodeIdentifier* metaId = NULL;
+
+ // If parameter suggests that ids should not be compared directly,
+ // make a safety check.
+ if ( !aCompareIdsDirectly
+ && NcdNodeIdentifierEditor::IdentifiesSomeRoot( aNodeIdentifier ) )
+ {
+ // In the case of root nodes, the metadata does not
+ // exist. So, force direct comparing of node ids.
+ DLINFO(("Force direct comparing of node ids"));
+ aCompareIdsDirectly = ETrue;
+ }
+
+ if( !aCompareIdsDirectly )
+ {
+ // The node should always exist.
+ CNcdNode& node( iNodeManager.NodeL( aNodeIdentifier ) );
+
+ // Above, a root node check was made to force direct comparing
+ // of ids for root nodes because they do not have metadata. So,
+ // in root node cases we do not come here.
+ // In normal cases, the metadata should always exist.
+ // But, to be safe in all cases, check if metadata is NULL here.
+ // Notice, ownership is not transferred here.
+ CNcdNodeMetaData* metadata( node.NodeMetaData() );
+
+ if ( metadata )
+ {
+ DLINFO(("Metadata existed for paralled operations checking"));
+ // Ownership is not transferred. Metadata owns its own identifier.
+ metaId = &metadata->Identifier();
+ }
+ else
+ {
+ // Because metadata is NULL,
+ // no operation should exist for it either.
+ DLTRACEOUT(("No metadata to compare parallel operations"));
+ return EFalse;
+ }
+ }
+
+ // Check operation cache
+ for ( TInt i = 0; i < iOperationCache.Count(); i++ )
+ {
+ // Check is only done if the client is not the same
+ if( iOperationCache[i]->Session().Context().FamilyId() != aContext.FamilyId() ||
+ ( iOperationCache[i]->Session().Context().SecureId() == aContext.SecureId() &&
+ iOperationCache[i]->Session().Context().InstanceId() == aContext.InstanceId() ) )
+ {
+ continue;
+ }
+ // Try to get id from operation, not all operations are node specific.
+ const CNcdNodeIdentifier* id = GetNodeIdFromOperation( *iOperationCache[i] );
+ if( !id )
+ {
+ continue;
+ }
+ if( !aCompareIdsDirectly &&
+ NcdNodeIdentifierEditor::DoesMetaDataIdentifierMatchL( *metaId, *id ) )
+ {
+ return ETrue;
+ }
+ else if( aNodeIdentifier.Equals( *id ) )
+ {
+ return ETrue;
+ }
+ }
+
+ // Check operation queue
+ for ( TInt i = 0; i < iOperationQueue.Count(); i++ )
+ {
+ // Check is only done if the client is not the same
+ if( iOperationQueue[i]->Session().Context().FamilyId() != aContext.FamilyId() ||
+ ( iOperationQueue[i]->Session().Context().SecureId() == aContext.SecureId() &&
+ iOperationQueue[i]->Session().Context().InstanceId() == aContext.InstanceId() ) )
+ {
+ continue;
+ }
+ // Try to get id from operation, not all operations are node specific.
+ const CNcdNodeIdentifier* id = GetNodeIdFromOperation( *iOperationQueue[i] );
+ if( !id )
+ {
+ continue;
+ }
+ if( !aCompareIdsDirectly &&
+ NcdNodeIdentifierEditor::DoesMetaDataIdentifierMatchL( *metaId, *id ) )
+ {
+ return ETrue;
+ }
+ else if( aNodeIdentifier.Equals( *id ) )
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+const CNcdNodeIdentifier* CNcdOperationManager::GetNodeIdFromOperation(
+ const CNcdBaseOperation& aOperation ) const
+ {
+ DLTRACEIN((""));
+ switch( aOperation.Type() )
+ {
+ case ELoadNodeOperation:
+ case ESearchOperation:
+ {
+ const CNcdLoadNodeOperationImpl& op =
+ static_cast<const CNcdLoadNodeOperationImpl&>( aOperation );
+ return op.NodeIdentifier();
+ }
+ case ELoadRootNodeOperation:
+ {
+ const CNcdLoadRootNodeOperation& op =
+ static_cast<const CNcdLoadRootNodeOperation&>( aOperation );
+ return &op.NodeIdentifier();
+ }
+ case ELoadBundleNodeOperation:
+ {
+ const CNcdLoadBundleNodeOperation& op =
+ static_cast<const CNcdLoadBundleNodeOperation&>( aOperation );
+ return &op.NodeIdentifier();
+ }
+ case EDownloadOperation:
+ {
+ const CNcdDownloadOperation& op =
+ static_cast<const CNcdDownloadOperation&>( aOperation );
+ return &op.NodeIdentifier();
+ }
+ case EInstallOperation:
+ {
+ const CNcdInstallOperation& op =
+ static_cast<const CNcdInstallOperation&>( aOperation );
+ return &op.NodeIdentifier();
+ }
+ case EPurchaseOperation:
+ {
+ const CNcdPurchaseOperationImpl& op =
+ static_cast<const CNcdPurchaseOperationImpl&>( aOperation );
+ return &op.NodeIdentifier();
+ }
+ case EContentDownloadOperation:
+ {
+ const CNcdContentDownloadOperation& op =
+ static_cast<const CNcdContentDownloadOperation&>( aOperation );
+ return &op.NodeId();
+ }
+ default:
+ {
+ return NULL;
+ }
+ // These operations are not node-specific, hence no id information can be
+ // retrieved from them:
+ /*EDownloadSubOperation,
+ EDescriptorDownloadSubOperation,
+ ESendNotificationSubOperation,
+ ERightsObjectOperation,
+ ECreateAccessPointOperation,
+ ESendHttpRequestOperation,
+ EServerReportOperation,
+ ESubscriptionOperation*/
+ }
+ }