mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/cdeleteobject.cpp
changeset 0 a2952bb97e68
child 9 bee149131e4b
child 25 d881023c13eb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/cdeleteobject.cpp	Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,362 @@
+/*
+* Copyright (c) 2009 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:  Implement the operation: DeleteObject
+*
+*/
+
+
+#include <mtp/mmtpdataproviderframework.h>
+#include <mtp/mmtpobjectmgr.h>
+#include <mtp/cmtpobjectmetadata.h>
+
+#include "cdeleteobject.h"
+#include "mmmtpdplogger.h"
+#include "mmmtpdpconfig.h"
+#include "cmmmtpdpmetadataaccesswrapper.h"
+
+// static const TInt KMTPDriveGranularity = 5;
+
+// -----------------------------------------------------------------------------
+// Verification data for the DeleteObject request
+// -----------------------------------------------------------------------------
+//
+const TMTPRequestElementInfo KMTPDeleteObjectPolicy[] =
+    {
+        {
+        TMTPTypeRequest::ERequestParameter1,
+        EMTPElementTypeObjectHandle,
+        EMTPElementAttrWrite,
+        1,
+        KMTPHandleAll,
+        0
+        },
+    };
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::NewL
+// Two-phase construction method
+// CDeleteObject is an abstract class and shouldn't be instaniated.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C MMmRequestProcessor* CDeleteObject::NewL( MMTPDataProviderFramework& aFramework,
+    MMTPConnection& aConnection,
+    MMmMtpDpConfig& aDpConfig )
+    {
+    CDeleteObject* self = new (ELeave) CDeleteObject( aFramework, aConnection, aDpConfig );
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+void CDeleteObject::ConstructL()
+    {
+    CActiveScheduler::Add( this );
+    SetPSStatus();
+    }
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::~CDeleteObject
+// Destructor
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDeleteObject::~CDeleteObject()
+    {
+    Cancel();
+    iObjectsToDelete.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::CDeleteObject
+// Standard c++ constructor
+// -----------------------------------------------------------------------------
+//
+CDeleteObject::CDeleteObject( MMTPDataProviderFramework& aFramework,
+    MMTPConnection& aConnection,
+    MMmMtpDpConfig& aDpConfig ) :
+    CRequestProcessor( aFramework,
+        aConnection,
+        sizeof( KMTPDeleteObjectPolicy ) / sizeof( TMTPRequestElementInfo ),
+        KMTPDeleteObjectPolicy ),
+    iObjectMgr( aFramework.ObjectMgr() ),
+    iFs( aFramework.Fs() ),
+    iObjectsToDelete( KMmMtpRArrayGranularity ), 
+    iDeleteError( KErrNone ),
+    iDpConfig( aDpConfig )
+    {
+    PRINT( _L( "Operation: DeleteObject(0x100B)" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::ServiceL
+// DeleteObject request handler
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDeleteObject::ServiceL()
+    {
+    iObjectsToDelete.Reset();
+    iDeleteError = KErrNone;
+    TUint32 objectHandle = Request().Uint32( TMTPTypeRequest::ERequestParameter1 );
+
+    PRINT3( _L( "MM MTP <> CDeleteObject::ServiceL, objectHandle = 0x%x, numObject = %d, iDeleteError = %d" ),
+        objectHandle,
+        iObjectsToDelete.Count(),
+        iDeleteError );
+
+    // Check to see whether the request is to delete all files or a specific file/directory
+    if ( objectHandle == KMTPHandleAll )
+        {
+        iIsMultiDelete = ETrue;
+        // Get the complete list of all the media files that are to be deleted
+        GetObjectHandlesL( KMTPStorageAll, KMTPHandleNoParent );
+        StartL();
+        }
+    else
+        {
+        iIsMultiDelete = EFalse;
+        // Not Owned the object
+        // TODO: need to check if this is best way and if it is applicable to other processors
+        CMTPObjectMetaData* objectInfo = iRequestChecker->GetObjectInfo( objectHandle );
+
+        if ( objectInfo->Uint( CMTPObjectMetaData::EFormatCode ) == EMTPFormatCodeAssociation )
+            {
+            TUint parentHandle = objectInfo->Uint( CMTPObjectMetaData::EHandle );
+            GetObjectHandlesL( KMTPStorageAll, parentHandle );
+            if ( iObjectsToDelete.Count() > 0 )
+                iIsMultiDelete = ETrue;
+            StartL();
+            }
+        else
+            {
+            DeleteObjectL( *objectInfo );
+            ProcessFinalPhaseL();
+            }
+        }
+
+    PRINT( _L( "MM MTP <= CDeleteObject::ServiceL" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// MTPDeleteObject::StartL
+// Control the deletion
+// -----------------------------------------------------------------------------
+//
+void CDeleteObject::StartL()
+    {
+    TInt numObjectsToDelete = iObjectsToDelete.Count();
+    PRINT2( _L( "MM MTP <> CDeleteObject::StartL, numObjectsToDelete = %d, iDeleteError = %d" ),
+        numObjectsToDelete,
+        iDeleteError );
+
+    TBool isOk = iDeleteError == KErrNone || iDeleteError == KErrNotFound;
+    if ( numObjectsToDelete > 0  &&  isOk )
+        {
+        //Set the active object going to delete the file
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete( status, KErrNone );
+        SetActive();
+        }
+    else
+        {
+        ProcessFinalPhaseL();
+        }
+    PRINT( _L( "MM MTP <= CDeleteObject::StartL" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::RunL
+// AO Run method, deletes a selection of files on the system
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDeleteObject::RunL()
+    {
+    TInt numObjectsToDelete = iObjectsToDelete.Count();
+    PRINT1( _L( "MM MTP => CDeleteObject::RunL, numObjectsToDelete = %d" ),
+        numObjectsToDelete );
+
+    if ( numObjectsToDelete > 0 )
+        {
+        // Get the next object
+        CMTPObjectMetaData* objectInfo = CMTPObjectMetaData::NewLC(); // + objectInfo
+
+        TUint32 handle = iObjectsToDelete[0];
+        iObjectMgr.ObjectL( handle, *objectInfo );
+        TFileName fileName( objectInfo->DesC( CMTPObjectMetaData::ESuid ) );
+        PRINT2( _L( "MM MTP <> CDeleteObject::RunL delete object handle is 0x%x, fileName is %S" ), handle, &fileName );
+
+        if ( objectInfo->Uint( CMTPObjectMetaData::EFormatCode ) == EMTPFormatCodeAssociation )
+            {
+            TUint parentHandle = objectInfo->Uint( CMTPObjectMetaData::EHandle );
+            GetObjectHandlesL( KMTPStorageAll, parentHandle );
+            }
+        else
+            {
+            DeleteObjectL( *objectInfo );
+            }
+
+        CleanupStack::PopAndDestroy( objectInfo ); // - objectInfo
+
+        iObjectsToDelete.Remove( 0 );
+        }
+
+    // Start the process again to read the next row...
+    StartL();
+    PRINT( _L( "MM MTP <= CDeleteObject::RunL" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::DeleteObjectL()
+// Deletes the object from the file system and the object from the store
+// -----------------------------------------------------------------------------
+//
+void CDeleteObject::DeleteObjectL( const CMTPObjectMetaData& aObjectInfo )
+    {
+    TFileName fileName( aObjectInfo.DesC( CMTPObjectMetaData::ESuid ) );
+    PRINT1( _L( "MM MTP <> CDeleteObject::DeleteObjectL fileName = %S" ), &fileName );
+
+    TParsePtrC parse( fileName );
+    iDpConfig.GetWrapperL().SetStorageRootL( parse.Drive() );
+
+    // To capture special situation: After copy, move, rename playlist folder name,
+    // record in MPX is not inlined with framework db, playlist should not be deleted
+    // until next session.
+    // This is used to keep the same behavior in mass storage and device file manager.
+    if ( aObjectInfo.Uint(CMTPObjectMetaData::EFormatCode )
+        == EMTPFormatCodeAbstractAudioVideoPlaylist
+        && !iDpConfig.GetWrapperL().IsExistL( fileName ) )
+        {
+        iDeleteError = KErrGeneral;
+        PRINT( _L( "MM MTP <= CDeleteObject::DeleteObjectL playlist file not exist in the MPX DB" ) );
+        return;
+        }
+
+    // 1. Delete object from file system
+    TEntry fileInfo;
+    iFs.Entry( fileName, fileInfo );
+    if ( fileInfo.IsReadOnly() )
+        {
+        iDeleteError = KErrAccessDenied;
+        PRINT1( _L( "MM MTP <= CDeleteObject::DeleteObjectL, \"%S\" is a read-only file"), &fileName );
+        return;
+        }
+    iDeleteError = iFs.Delete( fileName );
+    if ( iDeleteError != KErrNone && iDeleteError != KErrNotFound )
+        {
+        PRINT1( _L( "MM MTP <= CDeleteObject::DeleteObjectL, Delete from file system failed, err = %d" ), iDeleteError );
+        return;
+        }
+
+    // 2. Delete object from metadata db
+    TRAP( iDeleteError, iDpConfig.GetWrapperL().DeleteObjectL( fileName, aObjectInfo.Uint( CMTPObjectMetaData::EFormatCode ) ));
+    PRINT1( _L( "MM MTP <> CDeleteObject::DeleteObjectL, Delete from Media DB, err = %d" ), iDeleteError );
+
+    // 3. Delete object from framework db
+    iObjectMgr.RemoveObjectL( aObjectInfo.Uint( CMTPObjectMetaData::EHandle ) );
+
+    PRINT( _L( "MM MTP <= CDeleteObject::DeleteObjectL" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::DoCancel
+// Used to cancel the deletion of the files
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDeleteObject::DoCancel()
+    {
+    TRAP_IGNORE( ProcessFinalPhaseL() );
+    }
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::ProcessFinalPhaseL
+// Delete all of the associations if file deletion was successful
+// Then signals that the deletion has been completed
+// -----------------------------------------------------------------------------
+//
+void CDeleteObject::ProcessFinalPhaseL()
+    {
+    PRINT( _L( "MM MTP => CDeleteObject::ProcessFinalPhaseL" ) );
+
+    TInt num = iObjectsToDelete.Count();
+    TBool isOk = iDeleteError == KErrNone || iDeleteError == KErrNotFound;
+
+    if ( num == 0 && isOk )
+        {
+        SendResponseL( EMTPRespCodeOK );
+        }
+    else if ( iIsMultiDelete && !isOk )
+        {
+        SendResponseL( EMTPRespCodePartialDeletion );
+        }
+    else if( !iIsMultiDelete && iDeleteError == KErrAccessDenied )
+        {
+        SendResponseL( EMTPRespCodeObjectWriteProtected );
+        }
+    else
+        {
+        SendResponseL( EMTPRespCodeAccessDenied );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CDeleteObject::GetObjectHandlesL
+// Gets all object handles (for GetObjectHandlesL)
+// -----------------------------------------------------------------------------
+//
+void CDeleteObject::GetObjectHandlesL( TUint32 aStorageId,
+    TUint32 aParentHandle )
+    {
+    PRINT2( _L( "MM MTP => CDeleteObject::GetObjectHandlesL, StorageId = 0x%x, ParentHandle = 0x%x" ),
+        aStorageId, aParentHandle );
+    RMTPObjectMgrQueryContext context;
+    RArray<TUint> handles;
+    CleanupClosePushL( context ); // + context
+    CleanupClosePushL( handles ); // + handles
+
+    TMTPObjectMgrQueryParams params( aStorageId, KMTPFormatsAll, aParentHandle );
+
+    do
+        {
+        iFramework.ObjectMgr().GetObjectHandlesL( params, context, handles );
+
+        for ( TInt i = 0; i < handles.Count(); i++ )
+            {
+            if ( iFramework.ObjectMgr().ObjectOwnerId( handles[i] )
+                == iFramework.DataProviderId() )
+                {
+                iObjectsToDelete.Append( handles[i] );
+                }
+            // TODO: should not know dp id of device dp,
+            // else if ( iFramework.ObjectMgr().ObjectOwnerId( handles[i] ) == 0 ) // We know that the device dp id is always 0, otherwise the whole MTP won't work.
+            //     iParentHandles.AppendL( handles[i] );
+            else
+                {
+                CMTPObjectMetaData* objectInfo = CMTPObjectMetaData::NewLC(); // + objectInfo
+                iObjectMgr.ObjectL( handles[i], *objectInfo );
+                if ( EMTPFormatCodeAssociation == objectInfo->Uint( CMTPObjectMetaData::EFormatCode ) )
+                    {
+                    GetObjectHandlesL( KMTPStorageAll, handles[i] );
+                    }
+                CleanupStack::PopAndDestroy( objectInfo ); // - objectInfo
+                }
+            }
+        }
+    while ( !context.QueryComplete() );
+
+    CleanupStack::PopAndDestroy( &handles ); // - handles
+    CleanupStack::PopAndDestroy( &context ); // - context
+
+    PRINT( _L( "MM MTP <= CDeleteObject::GetObjectHandlesL" ) );
+    }
+
+// end of file