diff -r 000000000000 -r ba25891c3a9e ncdengine/provider/server/src/ncdnodepreviewimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ncdengine/provider/server/src/ncdnodepreviewimpl.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,444 @@ +/* +* 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 CNcdNodePreview class +* +*/ + + +#include "ncdnodepreviewimpl.h" +#include "ncdnodemetadataimpl.h" +#include "ncdnodeidentifier.h" +#include "catalogssession.h" +#include "catalogsbasemessage.h" +#include "ncdnodefunctionids.h" +#include "ncdnodeclassids.h" +#include "catalogsconstants.h" +#include "ncd_pp_dataentity.h" +#include "ncd_cp_query.h" +#include "catalogsutils.h" +#include "catalogsdebug.h" +#include "ncd_pp_download.h" +#include "ncdnodemanager.h" +#include "ncdproviderdefines.h" +#include "ncdpreviewmanager.h" +#include "ncderrors.h" + + +CNcdNodePreview::CNcdNodePreview( const NcdNodeClassIds::TNcdNodeClassId aClassId, + CNcdNodeMetaData& aParentMetaData, + CNcdNodeManager& aNodeManager ) +: CNcdCommunicable(), + iClassId( aClassId ), + iParentMetaData( aParentMetaData ), + iNodeManager( aNodeManager ) + { + } + +void CNcdNodePreview::ConstructL() + { + } + + +CNcdNodePreview* CNcdNodePreview::NewL( CNcdNodeMetaData& aParentMetaData, + CNcdNodeManager& aNodeManager ) + { + CNcdNodePreview* self = + CNcdNodePreview::NewLC( aParentMetaData, aNodeManager ); + CleanupStack::Pop( self ); + return self; + } + +CNcdNodePreview* CNcdNodePreview::NewLC( CNcdNodeMetaData& aParentMetaData, + CNcdNodeManager& aNodeManager ) + { + CNcdNodePreview* self = + new( ELeave ) CNcdNodePreview( + NcdNodeClassIds::ENcdNodePreviewClassId, + aParentMetaData, + aNodeManager ); + CleanupClosePushL( *self ); + self->ConstructL(); + return self; + } + + +CNcdNodePreview::~CNcdNodePreview() + { + DLTRACEIN(("")); + + iPreviewMimeTypes.ResetAndDestroy(); + iUris.ResetAndDestroy(); + + DLTRACEOUT(("")); + } + +NcdNodeClassIds::TNcdNodeClassId CNcdNodePreview::ClassId() const + { + return iClassId; + } + + +// Internalization from the protocol + +void CNcdNodePreview::InternalizeL( MNcdPreminetProtocolDataEntity& aData ) + { + DLTRACEIN(("")); + + iFileCount = aData.PreviewCount(); + + HBufC* mimetype; + HBufC* uri; + iPreviewMimeTypes.ResetAndDestroy(); + iUris.ResetAndDestroy(); + + for( int i = 0; i < iFileCount; i++ ) + { + mimetype = aData.PreviewL( i ).Mime().AllocLC(); + iPreviewMimeTypes.AppendL( mimetype ); + CleanupStack::Pop( mimetype ); + mimetype = 0; + + uri = aData.PreviewL( i ).Uri().AllocLC(); + iUris.AppendL( uri ); + CleanupStack::Pop( uri ); + uri = 0; + } + + // Try to update mime types from already downloaded previews + // if the server didn't send any for this + UpdateMimesFromPreviewManagerL(); + DLTRACEOUT(("")); + } + + +// Internalization from and externalization to the database + +void CNcdNodePreview::ExternalizeL( RWriteStream& aStream ) + { + DLTRACEIN(("")); + + // Set all the membervariable values to the stream. So, + // that the stream may be used later to create a new + // object. + + // First insert data that the creator of this class object will use to + // create this class object. Class id informs what class object + // will be created. + + aStream.WriteInt32L( ClassId() ); + + aStream.WriteInt16L( iFileCount ); + + for( int i = 0; i < iFileCount; i++ ) + { + ExternalizeDesL( *iPreviewMimeTypes[i], aStream ); + } + + for( int i = 0; i < iFileCount; i++ ) + { + ExternalizeDesL( *iUris[i], aStream ); + } + + DLTRACEOUT(("")); + } + + +void CNcdNodePreview::InternalizeL( RReadStream& aStream ) + { + DLTRACEIN(("")); + + // Read the class id first because it is set to the stream in internalize + // function and it is not read from the stream anywhere else. + TInt classId( aStream.ReadInt32L() ); + if ( classId != ClassId() ) + { + DLERROR(("Wrong class id")); + DASSERT( EFalse ); + // Leave because the stream does not match this class object + User::Leave( KErrCorrupt ); + } + + iFileCount = aStream.ReadInt16L(); + + HBufC* previewMimeType = 0; + iPreviewMimeTypes.ResetAndDestroy(); + for( int i = 0; i < iFileCount; i++ ) + { + InternalizeDesL( previewMimeType, aStream ); + CleanupStack::PushL( previewMimeType ); + iPreviewMimeTypes.AppendL( previewMimeType ); + CleanupStack::Pop( previewMimeType ); + } + + HBufC* uri = 0; + iUris.ResetAndDestroy(); + for( int i = 0; i < iFileCount; i++ ) + { + InternalizeDesL( uri, aStream ); + CleanupStack::PushL( uri ); + iUris.AppendL( uri ); + CleanupStack::Pop( uri ); + } + + // Try to update MIME from downloaded previews + UpdateMimesFromPreviewManagerL(); + DLTRACEOUT(("")); + } + + +void CNcdNodePreview::ReceiveMessage( MCatalogsBaseMessage* aMessage, + TInt aFunctionNumber ) + { + DLTRACEIN(("")); + + DASSERT( aMessage ); + + // Now, we can be sure that rest of the time iMessage exists. + // This member variable is set for the CounterPartLost function. + iMessage = aMessage; + + TInt trapError( KErrNone ); + + // Check which function is called by the proxy side object. + // Function number are located in ncdnodefunctinoids.h file. + switch( aFunctionNumber ) + { + case NcdNodeFunctionIds::ENcdInternalize: + // Internalize the proxy side according to the data + // of this object. + TRAP( trapError, InternalizeRequestL( *aMessage ) ); + break; + + case NcdNodeFunctionIds::ENcdPreviewOpenFile: + TRAP( trapError, OpenPreviewFileL( *aMessage ) ); + break; + + case NcdNodeFunctionIds::ENcdRelease: + // The proxy does not want to use this object anymore. + // So, release the handle from the session. + ReleaseRequest( *aMessage ); + break; + + case NcdNodeFunctionIds::ENcdIsPreviewLoaded: + TRAP( trapError, IsPreviewLoadedL( *aMessage )); + break; + + default: + DLERROR(("Unidentified function request")); + DASSERT( EFalse ); + 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 if the + // message is still available. + aMessage->CompleteAndRelease( trapError ); + } + + // Because the message should not be used after this, set it NULL. + // So, CounterPartLost function will know that no messages are + // waiting the response at the moment. + iMessage = NULL; + + DLTRACEOUT(("")); + } + +void CNcdNodePreview::CounterPartLost( const MCatalogsSession& aSession ) + { + // This function may be called whenever -- when the message is waiting + // response or when the message does not exist. + // iMessage may be NULL here, because in the end of the + // ReceiveMessage it is set to NULL. The life time of the message + // ends shortly after CompleteAndRelease is called. + if ( iMessage != NULL ) + { + iMessage->CounterPartLost( aSession ); + } + } + + +void CNcdNodePreview::InternalizeRequestL( MCatalogsBaseMessage& aMessage ) + { + DLTRACEIN(("")); + + CBufBase* buf = CBufFlat::NewL( KBufExpandSize ); + CleanupStack::PushL( buf ); + + RBufWriteStream stream( *buf ); + CleanupClosePushL( stream ); + + + // Include all the necessary node data to the stream + ExternalizeDataForRequestL( stream ); + + + // Commits data to the stream when closing. + CleanupStack::PopAndDestroy( &stream ); + + + // If this leaves, ReceiveMessage will complete the message. + // NOTE: that here we expect that the buffer contains at least + // some data. So, make sure that ExternalizeDataForRequestL inserts + // something to the buffer. + aMessage.CompleteAndReleaseL( buf->Ptr( 0 ), KErrNone ); + + + DLINFO(("Deleting the buf")); + CleanupStack::PopAndDestroy( buf ); + + DLTRACEOUT(("")); + } + + +void CNcdNodePreview::ExternalizeDataForRequestL( RWriteStream& aStream ) + { + DLTRACEIN(("")); + + if ( IsObsolete() ) + { + DLINFO(("Set as obsolete. This means that server has removed the object.")); + User::Leave( KNcdErrorObsolete ); + } + + aStream.WriteInt32L( ClassId() ); + + aStream.WriteInt16L( iFileCount ); + + for( int i = 0; i < iFileCount; i++ ) + { + ExternalizeDesL( *iPreviewMimeTypes[i], aStream ); + } + + DLTRACEOUT(("")); + } + +void CNcdNodePreview::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() ); + + // Send complete information back to proxy. + aMessage.CompleteAndRelease( KErrNone ); + + // Remove this object from the session. + requestSession.RemoveObject( handle ); + + DLTRACEOUT(("")); + } + +void CNcdNodePreview::OpenPreviewFileL( MCatalogsBaseMessage& aMessage ) + { + DLTRACEIN(("")); + RBuf8 buf; + buf.CreateL( aMessage.InputLength() ); + CleanupClosePushL( buf ); + User::LeaveIfError( aMessage.ReadInput( buf ) ); + + // Read the requested file index + TInt fileIndex = Des8ToInt( buf ); + + // Open a new file server session because using the same session + // for shared and non-shared files is a security risk + RFs fs; + CleanupClosePushL( fs ); + User::LeaveIfError( fs.Connect() ); + + // Share the file server session + User::LeaveIfError( fs.ShareProtected() ); + + DLTRACE(("Open preview file")); + RFile openFile = iNodeManager.PreviewManager().PreviewL( + fs, + iParentMetaData.Identifier(), + *iUris[fileIndex] ); + + CleanupClosePushL( openFile ); + + DLINFO(("File open, transferring to client")); + aMessage.CompleteAndReleaseL( fs, + openFile ); + + // a shared file must be closed on the server side too + // also the shared file session must be closed + CleanupStack::PopAndDestroy( 2, &fs ); // openFile, fs + + CleanupStack::PopAndDestroy( &buf ); + + DLTRACEOUT(("")); + } + + +TInt CNcdNodePreview::UriCount() const + { + return iUris.Count(); + } + + +const TDesC& CNcdNodePreview::Uri( TInt aIndex ) const + { + return *(iUris[aIndex]); + } + + +void CNcdNodePreview::UpdateMimesFromPreviewManagerL() + { + DLTRACEIN(("")); + CNcdPreviewManager& previewManager( iNodeManager.PreviewManager() ); + const CNcdNodeIdentifier& metaId( iParentMetaData.Identifier() ); + + TInt count = iFileCount; // use iFileCount since it's the "real" count + while ( count-- ) + { + if ( !iPreviewMimeTypes[ count ]->Length() ) + { + const TDesC& mime( previewManager.PreviewMimeType( + metaId, + *iUris[ count ] ) ); + + // assign only if there's something to assign + if ( mime.Length() ) + { + AssignDesL( iPreviewMimeTypes[ count ], mime ); + } + } + } + } + + +void CNcdNodePreview::IsPreviewLoadedL( MCatalogsBaseMessage& aMessage ) + { + RBuf8 buf; + buf.CreateL( aMessage.InputLength() ); + CleanupClosePushL( buf ); + User::LeaveIfError( aMessage.ReadInput( buf ) ); + + TInt fileIndex = Des8ToInt( buf ); + + TInt isLoaded = iNodeManager.PreviewManager().PreviewExists( + iParentMetaData.Identifier(), + *iUris[fileIndex] ); + + CleanupStack::PopAndDestroy( &buf ); + + aMessage.CompleteAndReleaseL( isLoaded, KErrNone ); + + }