mtpfws/mtpfw/dataproviders/proxydp/src/cmtpmoveobject.cpp
changeset 0 d0791faffa3f
child 11 4843bb5893b6
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <bautils.h>
       
    17 #include <f32file.h>
       
    18 #include <mtp/cmtptypearray.h>
       
    19 #include <mtp/cmtpobjectmetadata.h>
       
    20 
       
    21 #include "cmtpdataprovider.h"
       
    22 #include "cmtpmoveobject.h"
       
    23 #include "cmtpobjectmgr.h"
       
    24 #include "cmtpparserrouter.h"
       
    25 #include "cmtpstoragemgr.h"
       
    26 #include "mtpproxydppanic.h"
       
    27 #include "cmtpobjectbrowser.h"
       
    28 #include "mtpdppanic.h"
       
    29 
       
    30 __FLOG_STMT(_LIT8(KComponent,"PrxyMoveObj");)
       
    31 const TUint KInvalidDpId = 0xFF;
       
    32 /**
       
    33 Verification data for the MoveObject request
       
    34 */    
       
    35 const TMTPRequestElementInfo CMTPMoveObject::KMTPMoveObjectPolicy[] = 
       
    36     {
       
    37     	{TMTPTypeRequest::ERequestParameter1, EMTPElementTypeObjectHandle, EMTPElementAttrFileOrDir | EMTPElementAttrWrite, 0, 0, 0},   	
       
    38         {TMTPTypeRequest::ERequestParameter2, EMTPElementTypeStorageId, EMTPElementAttrWrite, 0, 0, 0},                
       
    39         {TMTPTypeRequest::ERequestParameter3, EMTPElementTypeObjectHandle, EMTPElementAttrDir | EMTPElementAttrWrite, 1, 0, 0}
       
    40     };
       
    41     
       
    42 /**
       
    43 Two-phase construction method
       
    44 @param aFramework    The data provider framework
       
    45 @param aConnection    The connection from which the request comes
       
    46 @return a pointer to the created request processor object
       
    47 */ 
       
    48 MMTPRequestProcessor* CMTPMoveObject::NewL(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection)
       
    49     {
       
    50     CMTPMoveObject* self = new (ELeave) CMTPMoveObject(aFramework, aConnection);
       
    51     CleanupStack::PushL(self);
       
    52     self->ConstructL();
       
    53     CleanupStack::Pop(self);
       
    54     return self;
       
    55     }
       
    56 
       
    57 /**
       
    58 Destructor
       
    59 */    
       
    60 CMTPMoveObject::~CMTPMoveObject()
       
    61     {
       
    62     iSingletons.Close();
       
    63     iNewParent.Close();
       
    64 	delete iPathToCreate;
       
    65 	
       
    66     delete iFileMan;
       
    67     iFolderToRemove.Close();
       
    68     delete iObjInfoCache;
       
    69     iNewHandleParentStack.Close();
       
    70     iHandleDepths.Close();
       
    71     iHandles.Close();
       
    72     delete iObjBrowser;
       
    73     iTargetDps.Close();
       
    74     __FLOG(_L8("+/-Dtor"));
       
    75     __FLOG_CLOSE;
       
    76     }
       
    77 
       
    78 /**
       
    79 Constructor
       
    80 */    
       
    81 CMTPMoveObject::CMTPMoveObject(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection) :
       
    82     CMTPRequestProcessor(aFramework, aConnection, sizeof(KMTPMoveObjectPolicy)/sizeof(TMTPRequestElementInfo), KMTPMoveObjectPolicy)
       
    83     {
       
    84     __FLOG_OPEN( KMTPSubsystem, KComponent );
       
    85     __FLOG( _L8("+/-Ctor") );
       
    86     }
       
    87     
       
    88 /**
       
    89 Second phase constructor.
       
    90 */
       
    91 void CMTPMoveObject::ConstructL()
       
    92     {
       
    93     __FLOG( _L8("+ConstructL") );
       
    94     iNewParent.CreateL(KMaxFileName);
       
    95     iSingletons.OpenL();
       
    96     iFolderToRemove.CreateL( KMaxFileName );
       
    97     iOwnerDp = KInvalidDpId;
       
    98     __FLOG( _L8("-ConstructL") );
       
    99     }
       
   100     
       
   101 /**
       
   102 MoveObject request handler
       
   103 */ 
       
   104 void CMTPMoveObject::ServiceL()
       
   105     {
       
   106     __FLOG( _L8("+ServiceL") );
       
   107     iTargetDps.Reset();
       
   108     CMTPParserRouter& router(iSingletons.Router());
       
   109     CMTPParserRouter::TRoutingParameters params(Request(), iConnection);
       
   110     router.ParseOperationRequestL(params);
       
   111     router.RouteOperationRequestL(params, iTargetDps);
       
   112     
       
   113     BrowseHandlesL();
       
   114     __FLOG( _L8("-ServiceL") );
       
   115     }
       
   116 
       
   117 void CMTPMoveObject::ProxyReceiveDataL(MMTPType& /*aData*/, const TMTPTypeRequest& /*aRequest*/, MMTPConnection& /*aConnection*/, TRequestStatus& /*aStatus*/)
       
   118     {
       
   119     Panic(EMTPWrongRequestPhase);    
       
   120     }
       
   121     
       
   122 void CMTPMoveObject::ProxySendDataL(const MMTPType& /*aData*/, const TMTPTypeRequest& /*aRequest*/, MMTPConnection& /*aConnection*/, TRequestStatus& /*aStatus*/)
       
   123     {
       
   124     Panic(EMTPWrongRequestPhase);
       
   125     }
       
   126     
       
   127 #ifdef _DEBUG    
       
   128 void CMTPMoveObject::ProxySendResponseL(const TMTPTypeResponse& aResponse, const TMTPTypeRequest& aRequest, MMTPConnection& aConnection, TRequestStatus& aStatus)
       
   129 #else
       
   130 void CMTPMoveObject::ProxySendResponseL(const TMTPTypeResponse& aResponse, const TMTPTypeRequest& /*aRequest*/, MMTPConnection& /*aConnection*/, TRequestStatus& aStatus)
       
   131 #endif
       
   132     {
       
   133     __FLOG( _L8("+ProxySendResponseL") );
       
   134     __ASSERT_DEBUG(((&iCurrentRequest == &aRequest) && (&iConnection == &aConnection)), Panic(EMTPNotSameRequestProxy));
       
   135     MMTPType::CopyL(aResponse, iResponse);
       
   136 	TRequestStatus* status = &aStatus;
       
   137 	User::RequestComplete(status, KErrNone);
       
   138     __FLOG( _L8("-ProxySendResponseL") );
       
   139     }
       
   140 
       
   141 #ifdef _DEBUG    
       
   142 void CMTPMoveObject::ProxyTransactionCompleteL(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
       
   143 #else
       
   144 void CMTPMoveObject::ProxyTransactionCompleteL(const TMTPTypeRequest& /*aRequest*/, MMTPConnection& /*aConnection*/)
       
   145 #endif
       
   146     {
       
   147     __FLOG( _L8("+ProxyTransactionCompleteL") );
       
   148     __ASSERT_DEBUG(((&iCurrentRequest == &aRequest) && (&iConnection == &aConnection)), Panic(EMTPNotSameRequestProxy));
       
   149     TInt err((iResponse.Uint16(TMTPTypeResponse::EResponseCode) == EMTPRespCodeOK) ? KErrNone : KErrGeneral);    
       
   150     if (err == KErrNone)
       
   151         {
       
   152         iCurrentHandle--;
       
   153         Schedule(err);
       
   154         }
       
   155     else
       
   156         {
       
   157         SendResponseL( iResponse.Uint16( TMTPTypeResponse::EResponseCode ) ); 
       
   158         }
       
   159 
       
   160     __FLOG( _L8("-ProxyTransactionCompleteL") );
       
   161     }
       
   162 
       
   163 /**
       
   164 Retrive the parameters of the request
       
   165 */	
       
   166 void CMTPMoveObject::GetParametersL()
       
   167     {
       
   168     __FLOG( _L8("+GetParametersL") );
       
   169     
       
   170     TUint32 objectHandle  = iCurrentRequest.Uint32( TMTPTypeRequest::ERequestParameter1 );
       
   171     TUint32 newParentHandle  = iCurrentRequest.Uint32( TMTPTypeRequest::ERequestParameter3 );
       
   172     
       
   173     if(newParentHandle == 0)
       
   174         {
       
   175         GetDefaultParentObjectL( iNewParent );
       
   176         }
       
   177     else	
       
   178         {
       
   179         iFramework.ObjectMgr().ObjectL( TMTPTypeUint32( newParentHandle ), *iObjInfoCache );
       
   180         iNewParent = iObjInfoCache->DesC(CMTPObjectMetaData::ESuid);
       
   181         }
       
   182     
       
   183     iFramework.ObjectMgr().ObjectL( TMTPTypeUint32( objectHandle ), *iObjInfoCache );
       
   184     __FLOG( _L8("-GetParametersL") );	
       
   185     }
       
   186 
       
   187 /**
       
   188 Get a default parent object, when the current request does not specify a parent object
       
   189 */
       
   190 void CMTPMoveObject::GetDefaultParentObjectL( TDes& aObjectName )
       
   191     {
       
   192     __FLOG( _L8("+GetDefaultParentObjectL") );
       
   193     const CMTPStorageMetaData& storageMetaData( iFramework.StorageMgr().StorageL(iStorageId) );
       
   194     aObjectName = storageMetaData.DesC(CMTPStorageMetaData::EStorageSuid);
       
   195     __FLOG( _L8("-GetDefaultParentObjectL") );
       
   196 
       
   197     }
       
   198 
       
   199 /**
       
   200 Check if we can move the file to the new location
       
   201 */
       
   202 TMTPResponseCode CMTPMoveObject::CanMoveObjectL(const TDesC& aOldName, const TDesC& aNewName) const
       
   203 	{
       
   204 	__FLOG(_L8("+CanMoveObjectL"));
       
   205 	TMTPResponseCode result = EMTPRespCodeOK;
       
   206 
       
   207 	TEntry fileEntry;
       
   208 	User::LeaveIfError(iFramework.Fs().Entry(aOldName, fileEntry));
       
   209 	TInt drive(iFramework.StorageMgr().DriveNumber(iStorageId));
       
   210 	User::LeaveIfError(drive);
       
   211 	TVolumeInfo volumeInfo;
       
   212 	User::LeaveIfError(iFramework.Fs().Volume(volumeInfo, drive));
       
   213 	
       
   214 	if (BaflUtils::FileExists(iFramework.Fs(), aNewName))			
       
   215 		{
       
   216 		result = EMTPRespCodeInvalidParentObject;
       
   217 		}
       
   218 	__FLOG_VA((_L8("-CanMoveObjectL (Exit with response code 0x%04X)"), result));
       
   219 	return result;	
       
   220 	}
       
   221 	
       
   222 void CMTPMoveObject::GetSuidFromHandleL(TUint aHandle, TDes& aSuid) const
       
   223 	{
       
   224 	CMTPObjectMetaData* meta(CMTPObjectMetaData::NewLC());	
       
   225 	iFramework.ObjectMgr().ObjectL(aHandle, *meta);
       
   226 	__ASSERT_DEBUG(meta, Panic(EMTPDpObjectNull));
       
   227 	aSuid = meta->DesC(CMTPObjectMetaData::ESuid);
       
   228 	CleanupStack::PopAndDestroy(meta);
       
   229 	}
       
   230 		
       
   231 void CMTPMoveObject::RunL()
       
   232     {
       
   233     __FLOG( _L8("+RunL") );
       
   234     if ( iStatus==KErrNone )
       
   235         {
       
   236         switch ( iState )
       
   237             {
       
   238             case ERemoveSourceFolderTree:
       
   239                 SendResponseL(iResponse.Uint16(TMTPTypeResponse::EResponseCode));
       
   240                 break;
       
   241             default:
       
   242                 NextObjectHandleL();
       
   243                 if ( iOwnerDp != KInvalidDpId )
       
   244                     {
       
   245                     CMTPDataProvider& dp = iSingletons.DpController().DataProviderL( iOwnerDp );
       
   246                     dp.ExecuteProxyRequestL( iCurrentRequest, Connection(), *this );
       
   247                     }
       
   248                 break;
       
   249             }
       
   250         }
       
   251     else
       
   252         {
       
   253         SendResponseL( iResponse.Uint16( TMTPTypeResponse::EResponseCode ) );
       
   254         }
       
   255 
       
   256     __FLOG( _L8("-RunL") );
       
   257     }
       
   258     	
       
   259 TInt CMTPMoveObject::RunError(TInt /*aError*/)
       
   260 	{
       
   261 	TRAP_IGNORE(SendResponseL(EMTPRespCodeGeneralError));
       
   262 	return KErrNone;
       
   263 	}
       
   264 		    
       
   265 /**
       
   266 Completes the current asynchronous request with the specified 
       
   267 completion code.
       
   268 @param aError The asynchronous request completion request.
       
   269 */
       
   270 void CMTPMoveObject::Schedule(TInt aError)
       
   271     {
       
   272     TRequestStatus* status = &iStatus;
       
   273     User::RequestComplete(status, aError);
       
   274     SetActive();
       
   275     }
       
   276         
       
   277 /**
       
   278 Sends a response to the initiator.
       
   279 @param aCode MTP response code
       
   280 */
       
   281 void CMTPMoveObject::SendResponseL(TUint16 aCode)
       
   282     {
       
   283     const TMTPTypeRequest& req(Request());
       
   284     iResponse.SetUint16(TMTPTypeResponse::EResponseCode, aCode);
       
   285     iResponse.SetUint32(TMTPTypeResponse::EResponseSessionID, req.Uint32(TMTPTypeRequest::ERequestSessionID));
       
   286     iResponse.SetUint32(TMTPTypeResponse::EResponseTransactionID, req.Uint32(TMTPTypeRequest::ERequestTransactionID));
       
   287     iFramework.SendResponseL(iResponse, req, Connection());
       
   288     }
       
   289 
       
   290 TMTPResponseCode CMTPMoveObject::CreateFolderL()
       
   291     {
       
   292     __FLOG( _L8("+CreateFolderL") );
       
   293     TMTPResponseCode ret = EMTPRespCodeOK;
       
   294     
       
   295     GetParametersL();
       
   296     __FLOG_1( _L("New folder parent: %S"), &iNewParent );
       
   297     const TDesC& oldPath = iObjInfoCache->DesC( CMTPObjectMetaData::ESuid );
       
   298     if ( iFolderToRemove.Length() == 0 )
       
   299         {
       
   300         iFolderToRemove = oldPath;
       
   301         }
       
   302     
       
   303     TFileName fileNamePart;
       
   304     User::LeaveIfError( BaflUtils::MostSignificantPartOfFullName( oldPath, fileNamePart ) );
       
   305     __FLOG_1( _L("Folder name: %S"), &fileNamePart );
       
   306     
       
   307     if ( ( iNewParent.Length() + fileNamePart.Length() + 1 ) <= iNewParent.MaxLength() )
       
   308         {
       
   309         iNewParent.Append( fileNamePart );
       
   310         iNewParent.Append( KPathDelimiter );
       
   311         }
       
   312     else
       
   313         {
       
   314         ret = EMTPRespCodeInvalidParentObject;
       
   315         }
       
   316     if ( EMTPRespCodeOK == ret )
       
   317         {
       
   318         __FLOG_VA( ( _L("Try to move %S to %S"), &oldPath, &iNewParent ) );
       
   319         ret = CanMoveObjectL( oldPath, iNewParent );
       
   320         
       
   321         if ( EMTPRespCodeOK == ret )
       
   322             {
       
   323             TInt err = iFramework.Fs().MkDir( iNewParent );
       
   324             User::LeaveIfError( err );
       
   325             iNewHandleParentStack.AppendL( iObjInfoCache->Uint( CMTPObjectMetaData::EHandle ) );
       
   326             }
       
   327         }
       
   328     
       
   329     __FLOG( _L8("-CreateFolderL") );
       
   330     return ret;
       
   331     }
       
   332 
       
   333 void CMTPMoveObject::RemoveSourceFolderTreeL()
       
   334     {
       
   335     __FLOG( _L8("+RemoveSourceFolderTreeL") );
       
   336     
       
   337     if ( iFolderToRemove.Length() > 0 )
       
   338         {
       
   339         __FLOG_1( _L("Removing %S"), &iFolderToRemove );
       
   340         delete iFileMan;
       
   341         iFileMan = NULL;
       
   342         iFileMan = CFileMan::NewL( iFramework.Fs() );
       
   343         
       
   344         iState = ERemoveSourceFolderTree;
       
   345         User::LeaveIfError( iFileMan->RmDir( iFolderToRemove, iStatus ) );
       
   346         SetActive();
       
   347         }
       
   348     else
       
   349         {
       
   350         SendResponseL( iResponse.Uint16( TMTPTypeResponse::EResponseCode ) );
       
   351         }
       
   352     
       
   353     __FLOG( _L8("-RemoveSourceFolderTreeL") );
       
   354     }
       
   355 
       
   356 void CMTPMoveObject::BrowseHandlesL()
       
   357     {
       
   358     __FLOG( _L8("+BrowseHandlesL") );
       
   359     
       
   360     iFolderToRemove.SetLength( 0 );
       
   361     iState = EInit;
       
   362     
       
   363     delete iObjBrowser;
       
   364     iObjBrowser = NULL;
       
   365     iObjBrowser = CMTPObjectBrowser::NewL( iFramework );
       
   366     
       
   367     iHandles.Reset();
       
   368     iHandleDepths.Reset();
       
   369     
       
   370     delete iObjInfoCache;
       
   371     iObjInfoCache = NULL;
       
   372     iObjInfoCache = CMTPObjectMetaData::NewL();
       
   373     
       
   374     iNewHandleParentStack.Reset();
       
   375     
       
   376     MMTPType::CopyL( Request(), iCurrentRequest );
       
   377     iStorageId = Request().Uint32( TMTPTypeRequest::ERequestParameter2 );
       
   378     
       
   379     CMTPObjectBrowser::TBrowseCallback callback = { CMTPMoveObject::OnBrowseObjectL, this };
       
   380     TUint32 handle = Request().Uint32( TMTPTypeRequest::ERequestParameter1 );
       
   381     TUint32 newHandleParent = Request().Uint32( TMTPTypeRequest::ERequestParameter3 );
       
   382     iNewHandleParentStack.AppendL( newHandleParent );
       
   383     iObjBrowser->GoL( KMTPFormatsAll, handle, KMaxTUint32, callback );
       
   384     __FLOG_1( _L8("iHandles.Count() = %d"), iHandles.Count() );
       
   385     
       
   386     if ( iHandles.Count() > 0 )
       
   387         {
       
   388         iCurrentHandle = iHandles.Count() - 1;
       
   389         Schedule( KErrNone );
       
   390         }
       
   391     else
       
   392         {
       
   393         SendResponseL( EMTPRespCodeInvalidObjectHandle );
       
   394         }
       
   395     
       
   396     __FLOG( _L8("-BrowseHandlesL") );
       
   397     }
       
   398 
       
   399 void CMTPMoveObject::NextObjectHandleL()
       
   400     {
       
   401     __FLOG( _L8("+NextObjectHandleL") );
       
   402     __ASSERT_DEBUG( ( iNewHandleParentStack.Count() > 0 ), User::Invariant() );
       
   403     iOwnerDp = KInvalidDpId;
       
   404     if ( iCurrentHandle >=0 )
       
   405         {
       
   406         __FLOG_1( _L8("iCurrentHandle = %d"), iCurrentHandle );
       
   407         TUint32 handle = iHandles[iCurrentHandle];
       
   408         TUint32 depth = iHandleDepths[iCurrentHandle];
       
   409         __FLOG_1( _L8("depth = %d"), depth );
       
   410         if ( iCurrentHandle !=  ( iHandles.Count() - 1 ) )
       
   411             {
       
   412             TUint32 previousDepth = iHandleDepths[iCurrentHandle + 1];
       
   413             __FLOG_1( _L8("previousDepth = %d"), previousDepth );
       
   414             if ( depth < previousDepth )
       
   415                 {
       
   416                 // Completed copying folder and all its sub-folder and files, pop all copied folders' handle which are not shallower than the current one.
       
   417                 
       
   418                 // Step 1: pop the previous handle itself if it is am empty folder
       
   419                 if ( iIsMovingFolder )
       
   420                     {
       
   421                     iNewHandleParentStack.Remove( iNewHandleParentStack.Count() - 1 );
       
   422                     }
       
   423                 // Step 2: pop the other folders' handle which are not shallower than the current one
       
   424                 TUint loopCount = previousDepth - depth;
       
   425                 for ( TUint i = 0; i < loopCount; i++ )
       
   426                     {
       
   427                     iNewHandleParentStack.Remove( iNewHandleParentStack.Count() - 1 );
       
   428                     }
       
   429                 }
       
   430             else if ( ( depth == previousDepth ) && iIsMovingFolder )
       
   431                 {
       
   432                 // Completed moving empty folder, pop its handle
       
   433                 iNewHandleParentStack.Remove( iNewHandleParentStack.Count() - 1 );
       
   434                 }
       
   435             }
       
   436         iIsMovingFolder = EFalse;
       
   437         iOwnerDp = iSingletons.ObjectMgr().ObjectOwnerId( handle );
       
   438         if ( iOwnerDp == KInvalidDpId )
       
   439             {
       
   440             SendResponseL( EMTPRespCodeInvalidObjectHandle );
       
   441             }
       
   442         else
       
   443             {
       
   444             iCurrentRequest.SetUint32( TMTPTypeRequest::ERequestParameter1, handle );
       
   445             iCurrentRequest.SetUint32( TMTPTypeRequest::ERequestParameter3, iNewHandleParentStack[iNewHandleParentStack.Count()-1] );
       
   446             }
       
   447         if ( iOwnerDp==iSingletons.DpController().DeviceDpId() )
       
   448             {
       
   449             iIsMovingFolder = ETrue;
       
   450             if ( EMTPRespCodeOK != CreateFolderL() )
       
   451 			    {
       
   452 				iOwnerDp = KInvalidDpId;
       
   453 				iIsMovingFolder = EFalse;
       
   454 				SendResponseL( EMTPRespCodeInvalidParentObject );
       
   455                 }
       
   456             }
       
   457         }
       
   458     else
       
   459         {
       
   460         RemoveSourceFolderTreeL();
       
   461         }
       
   462     
       
   463     __FLOG( _L8("-NextObjectHandleL") );
       
   464     }
       
   465 
       
   466 void CMTPMoveObject::OnBrowseObjectL( TAny* aSelf, TUint aHandle, TUint32 aCurDepth )
       
   467     {
       
   468     CMTPMoveObject* self = reinterpret_cast< CMTPMoveObject* >( aSelf );
       
   469     if ( self->iTargetDps.Find(self->iSingletons.ObjectMgr().ObjectOwnerId(aHandle)) != KErrNotFound )
       
   470         {
       
   471         self->iHandles.AppendL( aHandle );
       
   472         self->iHandleDepths.AppendL( aCurDepth );        
       
   473         }      
       
   474     }
       
   475