filemanager/Engine/src/CFileManagerActiveExecute.cpp
changeset 0 6a9f87576119
child 1 d1daf54a55b5
equal deleted inserted replaced
-1:000000000000 0:6a9f87576119
       
     1 /*
       
     2 * Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0""
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Handles the copy/move operation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <bautils.h>
       
    21 //#include <cmgxfilemanager.h>
       
    22 //#include <mgxfilemanagerfactory.h>
       
    23 #include "CFileManagerActiveExecute.h"
       
    24 #include "MFileManagerProcessObserver.h"
       
    25 #include "CFileManagerEngine.h"
       
    26 #include "CFileManagerFileSystemIterator.h"
       
    27 #include "Cfilemanagerindexiterator.h"
       
    28 #include "CFileManagerCommonDefinitions.h"
       
    29 #include "CFileManagerUtils.h"
       
    30 #include "FileManagerDebug.h"
       
    31 #include "CFileManagerThreadWrapper.h"
       
    32 
       
    33 // CONSTANTS
       
    34 const TInt KFileManagerNotificationArrayGranularity = 64;
       
    35 
       
    36 // ============================ MEMBER FUNCTIONS ===============================
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CFileManagerActiveExecute::NewL
       
    40 // 
       
    41 // -----------------------------------------------------------------------------
       
    42 // 
       
    43 EXPORT_C CFileManagerActiveExecute* CFileManagerActiveExecute::NewL( 
       
    44         CFileManagerEngine& aEngine,
       
    45         MFileManagerProcessObserver::TFileManagerProcess aOperation,
       
    46         MFileManagerProcessObserver& aObserver,
       
    47         CArrayFixFlat<TInt>& aIndexList,
       
    48         const TDesC& aToFolder )
       
    49     {
       
    50     CFileManagerActiveExecute* self = 
       
    51         new( ELeave ) CFileManagerActiveExecute(
       
    52             aEngine,
       
    53             aOperation,
       
    54             aObserver );
       
    55     CleanupStack::PushL( self );
       
    56     self->ConstructL( aIndexList, aToFolder );
       
    57     CleanupStack::Pop( self );
       
    58     return self;
       
    59     }
       
    60 
       
    61 // -----------------------------------------------------------------------------
       
    62 // CFileManagerActiveExecute::~CFileManagerActiveExecute
       
    63 // 
       
    64 // -----------------------------------------------------------------------------
       
    65 // 
       
    66 EXPORT_C CFileManagerActiveExecute::~CFileManagerActiveExecute()
       
    67     {
       
    68     Cancel();
       
    69     delete iThreadWrapper;
       
    70     delete iItemIterator;
       
    71     delete iFullPath;
       
    72     delete iDestination;
       
    73     delete iToFolder;
       
    74     delete iIndexList;
       
    75     delete iChangedSrcItems;
       
    76     delete iChangedDstItems;
       
    77     }
       
    78 
       
    79 // -----------------------------------------------------------------------------
       
    80 // CFileManagerActiveExecute::ExecuteL
       
    81 // 
       
    82 // -----------------------------------------------------------------------------
       
    83 // 
       
    84 EXPORT_C void CFileManagerActiveExecute::ExecuteL( TFileManagerSwitch aOverWrite )
       
    85     {
       
    86     TInt error( KErrNone );
       
    87     
       
    88     if ( iCancelled )
       
    89         {
       
    90         TFileName newName;
       
    91         TParsePtrC parse( *iFullPath );
       
    92         if ( parse.NameOrExtPresent() )
       
    93             {
       
    94             newName.Copy( parse.NameAndExt() );
       
    95             }
       
    96         else
       
    97             {
       
    98             TPtrC name( iEngine.LocalizedName( *iFullPath ) );
       
    99             if ( name.Length() > 0 )
       
   100                 {
       
   101                 newName.Copy( name );
       
   102                 }
       
   103             else
       
   104                 {
       
   105                 newName = BaflUtils::FolderNameFromFullName( *iFullPath );
       
   106                 }
       
   107             }
       
   108         iObserver.ProcessFinishedL( iError, newName );
       
   109         return;
       
   110         }
       
   111     
       
   112     if ( aOverWrite == ENoOverWrite )
       
   113         {
       
   114         iItemIterator->CurrentL( &iSrc, &iDst, iItemType );
       
   115         }
       
   116 
       
   117     if ( iDst && iDst->Length() > KMaxFileName )
       
   118         {
       
   119         error = KErrBadName;
       
   120         TRequestStatus* status = &iStatus;
       
   121         User::RequestComplete( status, error );              
       
   122         }
       
   123     else if ( iItemType == EFileManagerFile )
       
   124         {
       
   125 #ifdef __KEEP_DRM_CONTENT_ON_PHONE
       
   126     if ( iSrc && iDst &&
       
   127         CFileManagerUtils::IsFromInternalToRemovableDrive( iFs, *iSrc, *iDst ) )
       
   128         {
       
   129         TBool protectedFile( EFalse );
       
   130 
       
   131         // silently ignore this file if it is protected, or if there
       
   132         // was an error in checking.
       
   133         // Did consider leaving, but what about eg KErrNotFound - eg another
       
   134         // process moving/deleting the file...
       
   135         TInt ret( iEngine.IsDistributableFile( *iSrc, protectedFile ) );
       
   136         if( protectedFile || ret != KErrNone )
       
   137             {
       
   138             TRequestStatus* status = &iStatus;
       
   139             User::RequestComplete( status, KErrNone );
       
   140             SetActive();
       
   141             return;
       
   142             }
       
   143         }
       
   144 #endif
       
   145         DoOperation( aOverWrite );
       
   146         return;
       
   147         }
       
   148     else if ( iItemType == EFileManagerFolder )
       
   149         {
       
   150         if ( !iIsDstRemoteDrive && iEngine.IsNameFoundL( *iDst ) )
       
   151             {
       
   152             TRequestStatus* status = &iStatus;
       
   153             User::RequestComplete( status, KErrAlreadyExists );
       
   154             SetActive();
       
   155             return;
       
   156             }
       
   157         DoOperation( aOverWrite );
       
   158         return;
       
   159         }
       
   160     else
       
   161         {
       
   162         // We must complete this
       
   163         TRequestStatus* status = &iStatus;
       
   164         User::RequestComplete( status, error );              
       
   165         }
       
   166     SetActive();
       
   167     }
       
   168 
       
   169 // -----------------------------------------------------------------------------
       
   170 // CFileManagerActiveExecute::CancelExecution
       
   171 // 
       
   172 // -----------------------------------------------------------------------------
       
   173 // 
       
   174 EXPORT_C void CFileManagerActiveExecute::CancelExecution()
       
   175     {
       
   176     FUNC_LOG
       
   177 
       
   178     iCancelled = ETrue;
       
   179 
       
   180     if ( iSrc )
       
   181         {
       
   182         iEngine.CancelTransfer( *iSrc );
       
   183         }
       
   184     if ( iDst )
       
   185         {
       
   186         iEngine.CancelTransfer( *iDst );
       
   187         }
       
   188     delete iThreadWrapper; // Cancel thread
       
   189     iThreadWrapper = NULL;
       
   190     Cancel();
       
   191     TRAP_IGNORE( CompleteL( KErrCancel ) );
       
   192     }
       
   193 
       
   194 // -----------------------------------------------------------------------------
       
   195 // CFileManagerActiveExecute::DoCancel
       
   196 // 
       
   197 // -----------------------------------------------------------------------------
       
   198 // 
       
   199 void CFileManagerActiveExecute::DoCancel()
       
   200     {
       
   201     iCancelled = ETrue;
       
   202 
       
   203     if ( iSrc )
       
   204         {
       
   205         iEngine.CancelTransfer( *iSrc );
       
   206         }
       
   207     if ( iDst )
       
   208         {
       
   209         iEngine.CancelTransfer( *iDst );
       
   210         }
       
   211     delete iThreadWrapper; // Cancel thread
       
   212     iThreadWrapper = NULL;
       
   213     }
       
   214 
       
   215 // ------------------------------------------------------------------------------
       
   216 // CFileManagerActiveExecute::KErrNoneAction
       
   217 //
       
   218 // ------------------------------------------------------------------------------
       
   219 //
       
   220 void CFileManagerActiveExecute::KErrNoneActionL()
       
   221     {
       
   222     UpdateNotifications( EFalse, KErrNone );
       
   223     if ( iItemIterator->NextL() )
       
   224         {
       
   225         ExecuteL( ENoOverWrite );
       
   226         }
       
   227     else
       
   228         {
       
   229         if ( iOperation == MFileManagerProcessObserver::EMoveProcess && 
       
   230             iEngine.IsFolder( iIndexList->At( 0 ) ) )
       
   231             {
       
   232             if ( !iFinalizeMove )
       
   233                 {
       
   234                 // Finalize move in the thread, the finalizing way take time
       
   235                 iFinalizeMove = ETrue;
       
   236                 DoOperation( ENoOverWrite );
       
   237                 return;
       
   238                 }
       
   239             }
       
   240         UpdateNotifications( ETrue, KErrNone );
       
   241         iObserver.ProcessFinishedL( KErrNone );
       
   242         }
       
   243     
       
   244     }
       
   245 
       
   246 // ------------------------------------------------------------------------------
       
   247 // CFileManagerActiveExecute::KErrAlreadyExistsAction
       
   248 //
       
   249 // ------------------------------------------------------------------------------
       
   250 //
       
   251 void CFileManagerActiveExecute::KErrAlreadyExistsActionL()
       
   252     {
       
   253     TParsePtrC dstParse( *iDst );
       
   254     HBufC* name = HBufC::NewLC( KMaxFileName );
       
   255     TPtr ptrName( name->Des() );
       
   256     TBool doContinue( EFalse );
       
   257 
       
   258     // Depending on target file can it be delete, we ask overwrite or rename.
       
   259     // If source and target is same, then rename is only possible choice.
       
   260     if ( iItemType == EFileManagerFile && iEngine.CanDelete( *iDst ) && iSrc->FindF( *iDst ) )
       
   261         {
       
   262         if ( iObserver.ProcessQueryOverWriteL( *iDst, ptrName, iOperation ) )
       
   263             {
       
   264             ExecuteL( EOverWrite );
       
   265             }
       
   266         else
       
   267             {
       
   268             // user does not want to overwrite item and ptrName should now contain
       
   269             // user given new name
       
   270             if ( ptrName.Length() > 0 )
       
   271                 {
       
   272                 ptrName.Insert( 0, dstParse.DriveAndPath() );
       
   273                 if ( !iDst->CompareF( ptrName ) )
       
   274                     {
       
   275                     DoOperation( ENoOverWrite );
       
   276                     }
       
   277                 else
       
   278                     {
       
   279                     iDst->Des().Copy( ptrName );
       
   280                     // Overwrite, because user already queried by overwrite
       
   281                     DoOperation( EOverWrite );
       
   282                     }
       
   283                 }
       
   284             else
       
   285                 {
       
   286                 // User is not willing to rename item, continue current operation
       
   287                 doContinue = ETrue;
       
   288                 }
       
   289             }
       
   290         }
       
   291     else
       
   292         {
       
   293         // item can't be overwrite
       
   294         if ( iObserver.ProcessQueryRenameL( *iDst, ptrName, iOperation ) )
       
   295             {
       
   296             if ( ptrName.Length() > 0 )
       
   297                 {
       
   298                 if ( iItemType == EFileManagerFile )
       
   299                     {
       
   300                     ptrName.Insert( 0, dstParse.DriveAndPath() );
       
   301                     iDst->Des().Copy( ptrName );
       
   302                     }
       
   303                 else if ( iItemType == EFileManagerFolder )
       
   304                     {
       
   305                     TPtr ptr( iDst->Des() );
       
   306                     AddLastFolder( ptr, ptrName, *iToFolder );
       
   307                     iDestination->Des().Copy( ptr );
       
   308                     }
       
   309                 // Overwrite, because user already queried by rename
       
   310                 ExecuteL( EOverWrite );
       
   311                 }
       
   312             else if ( iItemType == EFileManagerFolder )
       
   313                 {
       
   314                 iCancelled = ETrue;
       
   315                 iError = KErrCancel;
       
   316                 ExecuteL( ENoOverWrite );
       
   317                 }
       
   318             else
       
   319                 {
       
   320                 // User is not willing to rename item, continue current operation
       
   321                 doContinue = ETrue;
       
   322                 }
       
   323             }
       
   324         else if ( iItemType == EFileManagerFolder )
       
   325             {
       
   326             iCancelled = ETrue;
       
   327             iError = KErrCancel;
       
   328             ExecuteL( ENoOverWrite );
       
   329             }
       
   330         else
       
   331             {
       
   332             // User is not willing to rename item, continue current operation
       
   333             doContinue = ETrue;
       
   334             }
       
   335         }
       
   336 
       
   337     CleanupStack::PopAndDestroy( name );
       
   338 
       
   339     if ( doContinue )
       
   340         {
       
   341         if ( iItemIterator->NextL() )
       
   342             {
       
   343             ExecuteL( ENoOverWrite );
       
   344             }
       
   345         else
       
   346             {
       
   347             UpdateNotifications( ETrue, KErrNone );
       
   348             iObserver.ProcessFinishedL( KErrNone );
       
   349             }
       
   350         }
       
   351     }
       
   352 
       
   353 // -----------------------------------------------------------------------------
       
   354 // CFileManagerActiveExecute::RunL
       
   355 // 
       
   356 // -----------------------------------------------------------------------------
       
   357 // 
       
   358 void CFileManagerActiveExecute::RunL()
       
   359     {
       
   360     CompleteL( iStatus.Int() );
       
   361     }
       
   362 
       
   363 // -----------------------------------------------------------------------------
       
   364 // CFileManagerActiveExecute::CompleteL
       
   365 // 
       
   366 // -----------------------------------------------------------------------------
       
   367 // 
       
   368 void CFileManagerActiveExecute::CompleteL( TInt aError )
       
   369     {
       
   370     if ( iCancelled || !iItemIterator )
       
   371         {
       
   372         UpdateNotifications( ETrue, iError );
       
   373         TParsePtrC parse( CFileManagerUtils::StripFinalBackslash(
       
   374             *iDestination ) );
       
   375         if ( parse.NameOrExtPresent() )
       
   376             {
       
   377             iObserver.ProcessFinishedL( iError, parse.NameAndExt() );
       
   378             }
       
   379         else if ( parse.DrivePresent() )
       
   380             {
       
   381             iObserver.ProcessFinishedL( iError, parse.Drive() );
       
   382             }
       
   383         else
       
   384             {
       
   385             iObserver.ProcessFinishedL( iError );
       
   386             }
       
   387         return;
       
   388         }
       
   389 
       
   390     // Symbian returns KErrNone if source and destination
       
   391     // in moving is same. Here we have to treat it as error.
       
   392     if( iSrc && iDst )
       
   393         {
       
   394         if ( !iSrc->CompareF( *iDst ) && aError == KErrNone )
       
   395             {
       
   396             aError = KErrInUse;
       
   397             }
       
   398         }    
       
   399 
       
   400     ERROR_LOG1( "CFileManagerActiveExecute::CompleteL()-aError=%d", aError )
       
   401 
       
   402     switch ( aError )
       
   403         {
       
   404         case KErrNone:
       
   405             {
       
   406             KErrNoneActionL();
       
   407             break;
       
   408             }
       
   409         case KErrAlreadyExists:
       
   410             {
       
   411             KErrAlreadyExistsActionL();
       
   412             break;
       
   413             }
       
   414         case KErrCancel: // Suppressed errors
       
   415             {
       
   416             UpdateNotifications( ETrue, KErrNone );
       
   417             iObserver.ProcessFinishedL( KErrNone );
       
   418             break;
       
   419             }
       
   420         default:
       
   421             {
       
   422             if ( iSrc )
       
   423                 {
       
   424                 // Try rename when moving and the target file exists and is in use
       
   425                 if ( iOperation == MFileManagerProcessObserver::EMoveProcess &&
       
   426                     aError == KErrInUse &&
       
   427                     iDst &&
       
   428                     iEngine.CanDelete( *iSrc ) &&
       
   429                     iEngine.IsNameFoundL( *iDst ) )
       
   430                     {
       
   431                     KErrAlreadyExistsActionL();
       
   432                     }
       
   433                 else
       
   434                     {
       
   435                     UpdateNotifications( ETrue, aError );
       
   436                     TParsePtrC parse( *iSrc );
       
   437                     iObserver.ProcessFinishedL( aError, parse.NameAndExt() );
       
   438                     }
       
   439                 }
       
   440             else
       
   441                 {
       
   442                 UpdateNotifications( ETrue, aError );
       
   443                 iObserver.ProcessFinishedL( aError );
       
   444                 }
       
   445             break;
       
   446             }
       
   447         }
       
   448     }
       
   449 
       
   450 // -----------------------------------------------------------------------------
       
   451 // CFileManagerActiveExecute::RunError
       
   452 // 
       
   453 // -----------------------------------------------------------------------------
       
   454 // 
       
   455 TInt CFileManagerActiveExecute::RunError(TInt aError)
       
   456     {
       
   457     return aError;
       
   458     }
       
   459 
       
   460 // -----------------------------------------------------------------------------
       
   461 // CFileManagerActiveExecute::CFileManagerActiveExecute
       
   462 // 
       
   463 // -----------------------------------------------------------------------------
       
   464 // 
       
   465 CFileManagerActiveExecute::CFileManagerActiveExecute( 
       
   466     CFileManagerEngine& aEngine,
       
   467     MFileManagerProcessObserver::TFileManagerProcess aOperation,
       
   468     MFileManagerProcessObserver& aObserver ) :
       
   469         CActive( CActive::EPriorityLow ), // Use low to avoid progress note mess up
       
   470         iEngine( aEngine ),
       
   471         iFs( aEngine.Fs() ),
       
   472         iOperation( aOperation ),
       
   473         iObserver( aObserver )
       
   474     {
       
   475     CActiveScheduler::Add( this );
       
   476     }
       
   477 
       
   478 // -----------------------------------------------------------------------------
       
   479 // CFileManagerActiveExecute::ConstructL
       
   480 // 
       
   481 // -----------------------------------------------------------------------------
       
   482 // 
       
   483 void CFileManagerActiveExecute::ConstructL( CArrayFixFlat<TInt>& aIndexList,
       
   484                                             const TDesC& aToFolder )
       
   485     {
       
   486     iChangedSrcItems = new( ELeave ) CDesCArrayFlat(
       
   487         KFileManagerNotificationArrayGranularity );
       
   488     iChangedDstItems = new( ELeave ) CDesCArrayFlat(
       
   489         KFileManagerNotificationArrayGranularity );
       
   490     
       
   491     iToFolder = aToFolder.AllocL();
       
   492     TInt count( aIndexList.Count() );
       
   493     iIndexList = new( ELeave ) CArrayFixFlat< TInt >( count );
       
   494     for( TInt i( 0 ); i < count; ++i )
       
   495         {
       
   496         // make own copy of index list because caller may
       
   497         // destroy the original one.
       
   498         iIndexList->AppendL( aIndexList.At( i ) );
       
   499         }
       
   500     
       
   501     TInt index( iIndexList->At( iCurrentIndex ) );
       
   502     
       
   503     iFullPath = iEngine.IndexToFullPathL( index );
       
   504 
       
   505     TBool isDirectory( iEngine.IsFolder( index ) );
       
   506 
       
   507     iDestination = HBufC::NewL( KFmgrDoubleMaxFileName );
       
   508 
       
   509     if ( isDirectory )
       
   510         {
       
   511         TPtr ptr( iDestination->Des() );
       
   512         AddLastFolder( ptr, *iFullPath, *iToFolder );
       
   513         }
       
   514     else
       
   515         {
       
   516         iDestination->Des().Copy( aToFolder );
       
   517         }
       
   518     
       
   519     // Check that we are not copying/moving folder to inside it ( recursive copy )
       
   520     if ( isDirectory && !iDestination->FindF( *iFullPath ) && 
       
   521          iDestination->Length() > iFullPath->Length() )
       
   522         {
       
   523         iCancelled = ETrue;
       
   524         iError = KErrAccessDenied;
       
   525         }
       
   526     // Is destination path too long for file system
       
   527     else if ( iDestination->Length() > KMaxFileName )
       
   528         {
       
   529         iCancelled = ETrue;
       
   530         iError = KErrBadName;
       
   531         }
       
   532     else if ( isDirectory )
       
   533         {
       
   534         iItemIterator = CFileManagerFileSystemIterator::NewL(
       
   535             iFs, *iFullPath, *iDestination, iEngine );
       
   536         }
       
   537     else
       
   538         {
       
   539         iItemIterator = CFileManagerIndexIterator::NewL(
       
   540             iEngine, aIndexList, *iDestination );
       
   541         }
       
   542 
       
   543     // MG2 notification object
       
   544     //iMgxFileManager = &iEngine.MGXFileManagerL();
       
   545 
       
   546     // Check are operation source and target on the same drive
       
   547     TParsePtrC srcParse( *iFullPath  );
       
   548     TParsePtrC dstParse( *iDestination );
       
   549     TPtrC srcDrv( srcParse.Drive() );
       
   550     TPtrC dstDrv( dstParse.Drive() );
       
   551     iOperationOnSameDrive = !( srcDrv.CompareF( dstDrv ) );
       
   552     iIsSrcRemoteDrive = CFileManagerUtils::IsRemoteDrive( iFs, srcDrv );
       
   553     iIsDstRemoteDrive = CFileManagerUtils::IsRemoteDrive( iFs, dstDrv );
       
   554     }
       
   555 
       
   556 // -----------------------------------------------------------------------------
       
   557 // CFileManagerActiveExecute::AddLastFolder
       
   558 // 
       
   559 // -----------------------------------------------------------------------------
       
   560 // 
       
   561 void CFileManagerActiveExecute::AddLastFolder( TDes& aResult,
       
   562                                                const TDesC& aSrc, 
       
   563                                                const TDesC& aDst )
       
   564     {
       
   565     TInt lastBackslash = aSrc.LocateReverse( KFmgrBackslash()[0] );
       
   566     if ( lastBackslash != KErrNotFound )
       
   567         {
       
   568         // source is full path
       
   569         aResult.Copy( aSrc.Left( lastBackslash - 1 ) );
       
   570         // Last backslash is now temporary removed check next last backslash
       
   571         TInt secondLastBackslash( aResult.LocateReverse( KFmgrBackslash()[0] ) );
       
   572         // Now we know the coordinates of the last path
       
   573         aResult.Copy( iEngine.LocalizedName( aSrc ) );
       
   574         if ( aResult.Length() > 0 )
       
   575             {
       
   576             aResult.Insert( 0, aDst );
       
   577             aResult.Append( KFmgrBackslash );
       
   578             }
       
   579         else
       
   580             {
       
   581             aResult.Append( aDst );
       
   582             // Skip '\\'
       
   583             TInt startingPoint( secondLastBackslash + 1 );
       
   584             aResult.Append( aSrc.Mid( startingPoint, 
       
   585                                       lastBackslash - secondLastBackslash ) );
       
   586             }
       
   587         }
       
   588     else
       
   589         {
       
   590         // source is only one folder name
       
   591         aResult.Copy( aDst );
       
   592         aResult.Append( aSrc );
       
   593         aResult.Append( KFmgrBackslash );
       
   594         }
       
   595     }
       
   596 
       
   597 // -----------------------------------------------------------------------------
       
   598 // CFileManagerActiveExecute::DoOperation
       
   599 // 
       
   600 // -----------------------------------------------------------------------------
       
   601 // 
       
   602 TInt CFileManagerActiveExecute::DoOperation( TInt aSwitch )
       
   603     {
       
   604     // Source and destination must be different
       
   605     if ( iSrc && iDst && !iDst->CompareF( *iSrc ) )
       
   606         {
       
   607         TRequestStatus* status = &iStatus;
       
   608         User::RequestComplete( status, KErrAlreadyExists );
       
   609         SetActive();
       
   610         return KErrAlreadyExists;
       
   611         }
       
   612     TInt err( KErrNone );
       
   613 
       
   614     iSwitch = aSwitch;
       
   615 
       
   616     if ( !iThreadWrapper )
       
   617         {
       
   618         TRAP( err, iThreadWrapper = CFileManagerThreadWrapper::NewL() );
       
   619         if ( err != KErrNone )
       
   620             {
       
   621             TRequestStatus* status = &iStatus;
       
   622             User::RequestComplete( status, err );
       
   623             SetActive();
       
   624             return err;
       
   625             }
       
   626         }
       
   627     if ( iThreadWrapper->IsThreadStarted() )
       
   628         {
       
   629         iThreadWrapper->ResumeThread();
       
   630         }
       
   631     else
       
   632         {
       
   633         err = iThreadWrapper->StartThread(
       
   634             *this, ENotifyStepFinished, EPriorityLess );
       
   635         if ( err != KErrNone )
       
   636             {
       
   637             TRequestStatus* status = &iStatus;
       
   638             User::RequestComplete( status, err );
       
   639             SetActive();
       
   640             return err;
       
   641             }
       
   642         }
       
   643     return err;
       
   644     }
       
   645 
       
   646 // -----------------------------------------------------------------------------
       
   647 // CFileManagerActiveExecute::IsEmptyDir
       
   648 // 
       
   649 // -----------------------------------------------------------------------------
       
   650 // 
       
   651 TBool CFileManagerActiveExecute::IsEmptyDir( const TDesC& aDir )
       
   652     {
       
   653     return !CFileManagerUtils::HasAny(
       
   654         iFs, aDir, KEntryAttMatchMask | KEntryAttNormal );
       
   655     }
       
   656 
       
   657 // -----------------------------------------------------------------------------
       
   658 // CFileManagerActiveExecute::ThreadCopyOrMoveStepL()
       
   659 //
       
   660 // -----------------------------------------------------------------------------
       
   661 //
       
   662 void CFileManagerActiveExecute::ThreadCopyOrMoveStepL()
       
   663     {
       
   664     FUNC_LOG
       
   665 
       
   666     INFO_LOG2( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-%S=>%S",
       
   667          iSrc, iDst )
       
   668 
       
   669     TInt err( KErrNone );
       
   670     
       
   671     if ( iItemType == EFileManagerFolder )
       
   672         {
       
   673         // Handle folders
       
   674         err = iFs.MkDir( *iDst ); // Try faster way first
       
   675         LOG_IF_ERROR1(
       
   676             err,
       
   677             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-MkDir,err=%d",
       
   678             err )
       
   679         if ( err != KErrNone && err != KErrCancel )
       
   680             {
       
   681             err = iFs.MkDirAll( *iDst );
       
   682             LOG_IF_ERROR1(
       
   683                 err,
       
   684                 "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-MkDirAll,err=%d",
       
   685                 err )
       
   686             }
       
   687         if ( err == KErrNone )
       
   688             {
       
   689             TEntry entry;
       
   690             err = iFs.Entry( *iSrc, entry );
       
   691             if ( err == KErrNone )
       
   692                 {
       
   693                 iFs.SetEntry( *iDst, entry.iModified, entry.iAtt, 0 ); // Ignore error
       
   694                 }
       
   695             }
       
   696         User::LeaveIfError( err );
       
   697         return;
       
   698         }
       
   699     
       
   700     // Handle files
       
   701     if ( iOperationOnSameDrive &&
       
   702         iOperation == MFileManagerProcessObserver::EMoveProcess )
       
   703         {
       
   704         INFO_LOG(
       
   705             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-MoveInsideDrive" )
       
   706 
       
   707         if ( iSwitch == EOverWrite )
       
   708             {
       
   709             INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Overwrite" )
       
   710 
       
   711             err = iFs.Replace( *iSrc, *iDst );
       
   712             }
       
   713         else
       
   714             {
       
   715             INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-NoOverwrite" )
       
   716 
       
   717             err = iFs.Rename( *iSrc, *iDst );
       
   718             }
       
   719 
       
   720         LOG_IF_ERROR1(
       
   721             err,
       
   722             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-OnSameDrive,err=%d",
       
   723             err )
       
   724 
       
   725         if ( err == KErrNone || err == KErrCancel )
       
   726             {
       
   727             // Optimized move was successful or cancelled
       
   728             User::LeaveIfError( err );
       
   729             // If move the files in the same drive, the application
       
   730             // just calculate the amount of the files, so it should 
       
   731             // notify the observer that how many files have been moved.
       
   732             iBytesTransferredTotal++;
       
   733             TRAP_IGNORE( iObserver.ProcessAdvanceL(
       
   734                 iBytesTransferredTotal ) ); 
       
   735             return;
       
   736             }
       
   737         }
       
   738 
       
   739     TInt64 fileSize( 0 );
       
   740     RFile64 srcFile;
       
   741 
       
   742     // Open source file
       
   743     if ( iOperation == MFileManagerProcessObserver::EMoveProcess )
       
   744         {
       
   745         INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Move" )
       
   746 
       
   747         User::LeaveIfError( srcFile.Open(
       
   748             iFs, *iSrc, EFileRead | EFileShareExclusive ) );
       
   749         }
       
   750     else
       
   751         {
       
   752         INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Copy" )
       
   753 
       
   754         User::LeaveIfError( srcFile.Open(
       
   755             iFs, *iSrc, EFileRead | EFileShareReadersOnly ) );
       
   756         }
       
   757     CleanupClosePushL( srcFile );
       
   758     User::LeaveIfError( srcFile.Size( fileSize ) );
       
   759 
       
   760     // Open destination file
       
   761     RFile64 dstFile;
       
   762     if ( iSwitch == EOverWrite )
       
   763         {
       
   764         INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Overwrite" )
       
   765 
       
   766         User::LeaveIfError( dstFile.Replace(
       
   767             iFs, *iDst, EFileWrite | EFileShareExclusive ) );
       
   768         }
       
   769     else
       
   770         {
       
   771         INFO_LOG( "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-NoOverwrite" )
       
   772 
       
   773         User::LeaveIfError( dstFile.Create(
       
   774             iFs, *iDst, EFileWrite | EFileShareExclusive ) );
       
   775         }
       
   776     CleanupClosePushL( dstFile );
       
   777 
       
   778     dstFile.SetSize( fileSize ); // Setting the size first speeds up operation
       
   779 
       
   780     INFO_LOG1(
       
   781         "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-FileSize=%d",
       
   782          fileSize )
       
   783 
       
   784     // Create buffer and copy file data using it. 
       
   785     // Note that buffer size should not be too big to make it is possible 
       
   786     // to cancel the operation in reasonable time from the main thread. 
       
   787 
       
   788     // Move these to CenRep to make configuration and fine tuning easier.
       
   789     const TInt64 KBigBufSize = 0x40000; // 256KB
       
   790     const TInt64 KMediumBufSize = 0x10000; // 64KB
       
   791     const TInt64 KSmallBufSize = 0x2000; // 8KB
       
   792 
       
   793     HBufC8* buf = HBufC8::New(
       
   794         Max( KSmallBufSize, Min( fileSize, KBigBufSize ) ) );
       
   795     if ( !buf )
       
   796         {
       
   797         buf = HBufC8::New( KMediumBufSize );
       
   798         }
       
   799     if ( !buf )
       
   800         {
       
   801         buf = HBufC8::New( KSmallBufSize );
       
   802         }
       
   803     if ( !buf )
       
   804         {
       
   805         User::Leave( KErrNoMemory );
       
   806         }
       
   807     CleanupStack::PushL( buf );
       
   808 
       
   809     TPtr8 block( buf->Des() );
       
   810     
       
   811     INFO_LOG1(
       
   812         "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-BlockSize=%d",
       
   813          block.MaxSize() )
       
   814 
       
   815     while ( err == KErrNone && fileSize > 0 )
       
   816         {
       
   817         if ( iThreadWrapper->IsThreadCanceled() )
       
   818             {
       
   819             err = KErrCancel;
       
   820             break;
       
   821             }
       
   822         TInt blockSize( Min( fileSize, static_cast<TInt64>(block.MaxSize() ) ) );
       
   823         err = srcFile.Read( block, blockSize );
       
   824         if ( err == KErrNone )
       
   825             {
       
   826             if ( block.Length() == blockSize )
       
   827                 {
       
   828                 err = dstFile.Write( block, blockSize );
       
   829                 if ( err == KErrNone )
       
   830                     {
       
   831                     fileSize -= blockSize;
       
   832 
       
   833                     // Do not update the latest file transfer progress here.
       
   834                     // Flushing file below may take a long time and
       
   835                     // progress indicator should not get full before it.
       
   836                     TRAP_IGNORE( iObserver.ProcessAdvanceL(
       
   837                         iBytesTransferredTotal ) );
       
   838                     iBytesTransferredTotal += blockSize;
       
   839                     }
       
   840                 }
       
   841             else
       
   842                 {
       
   843                 err = KErrCorrupt;
       
   844                 }
       
   845             }
       
   846         }
       
   847 
       
   848     INFO_LOG2(
       
   849         "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-BytesNotWritten=%d,err=%d",
       
   850          fileSize, err )
       
   851 
       
   852     CleanupStack::PopAndDestroy( buf );
       
   853 
       
   854     // Copy attributes
       
   855     TTime mod;
       
   856     if ( err == KErrNone )
       
   857         {
       
   858         err = srcFile.Modified( mod );
       
   859 
       
   860         INFO_LOG1(
       
   861             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-ModifiedRead,err=%d",
       
   862             err )
       
   863 
       
   864         }
       
   865     if ( err == KErrNone )
       
   866         {
       
   867         err = dstFile.SetModified( mod );
       
   868 
       
   869         INFO_LOG1(
       
   870             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-ModifiedWritten,err=%d",
       
   871             err )
       
   872         }
       
   873     TUint att( 0 );
       
   874     if ( err == KErrNone )
       
   875         {
       
   876         err = srcFile.Att( att );
       
   877 
       
   878         INFO_LOG2(
       
   879             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-AttributesRead,err=%d,att=%d",
       
   880             err, att )
       
   881         }
       
   882     if ( err == KErrNone )
       
   883         {
       
   884         // Ignore fail, because some drives like remote drives
       
   885         // do not support attributes at all
       
   886         dstFile.SetAtt( att, ( ~att ) & KEntryAttMaskSupported );
       
   887 
       
   888         INFO_LOG(
       
   889             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-AttributesWritten" )
       
   890         }
       
   891     // Flush file and finalize transfer progress of this file.
       
   892     // Don't flush if copying failed because it causes save dialog to appear 
       
   893     // when remote drives are involved.
       
   894     if ( err == KErrNone )
       
   895         {
       
   896         err = dstFile.Flush();
       
   897 
       
   898         INFO_LOG1(
       
   899             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-Flushed,err=%d",
       
   900             err )
       
   901         }
       
   902     TRAP_IGNORE( iObserver.ProcessAdvanceL( iBytesTransferredTotal ) );
       
   903 
       
   904     CleanupStack::PopAndDestroy( &dstFile );
       
   905     CleanupStack::PopAndDestroy( &srcFile );
       
   906 
       
   907     // Delete source if move was succesful so far
       
   908     if ( err == KErrNone &&
       
   909         iOperation == MFileManagerProcessObserver::EMoveProcess )
       
   910         {
       
   911         // Ensure that read-only is removed before delete
       
   912         if ( att & KEntryAttReadOnly )
       
   913             {
       
   914             CFileManagerUtils::RemoveReadOnlyAttribute( iFs, *iSrc );
       
   915             }
       
   916         err = iFs.Delete( *iSrc );
       
   917 
       
   918         INFO_LOG1(
       
   919             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-MoveSourceDeleted,err=%d",
       
   920             err )
       
   921         }
       
   922 
       
   923     // Delete incomplete destination if error
       
   924     if ( err != KErrNone )
       
   925         {
       
   926         // Ensure that read-only is removed before delete
       
   927         if ( att & KEntryAttReadOnly )
       
   928             {
       
   929             CFileManagerUtils::RemoveReadOnlyAttribute( iFs, *iDst );
       
   930             }
       
   931         iFs.Delete( *iDst );
       
   932 
       
   933         ERROR_LOG1(
       
   934             "CFileManagerActiveExecute::ThreadCopyOrMoveStepL-FailedDstDeleted,fail=%d",
       
   935             err )
       
   936         }
       
   937 
       
   938     User::LeaveIfError( err );
       
   939     }
       
   940 
       
   941 // -----------------------------------------------------------------------------
       
   942 // CFileManagerActiveExecute::IsThreadDone()
       
   943 //
       
   944 // -----------------------------------------------------------------------------
       
   945 //
       
   946 TBool CFileManagerActiveExecute::IsThreadDone()
       
   947     {
       
   948     return EFalse;
       
   949     }
       
   950 
       
   951 // -----------------------------------------------------------------------------
       
   952 // CFileManagerActiveExecute::NotifyThreadClientL()
       
   953 //
       
   954 // -----------------------------------------------------------------------------
       
   955 //
       
   956 void CFileManagerActiveExecute::NotifyThreadClientL(
       
   957         TNotifyType aType, TInt aValue )
       
   958     {
       
   959     switch ( aType )
       
   960         {
       
   961         case ENotifyStepFinished:
       
   962             {
       
   963             CompleteL( aValue );
       
   964             break;
       
   965             }
       
   966         default:
       
   967             {
       
   968             break;
       
   969             }
       
   970         }
       
   971     }
       
   972 
       
   973 // -----------------------------------------------------------------------------
       
   974 // CFileManagerActiveExecute::AppendArrayIfNotFound()
       
   975 //
       
   976 // -----------------------------------------------------------------------------
       
   977 //
       
   978 void CFileManagerActiveExecute::AppendArrayIfNotFound(
       
   979         CDesCArray& aArray, const TDesC& aFullPath )
       
   980     {
       
   981     // Append if not already appended to the last item
       
   982     TBool append( ETrue );
       
   983     TInt count( aArray.MdcaCount() );
       
   984     if ( count > 0 )
       
   985         {
       
   986         TPtrC ptr( aArray.MdcaPoint( count - 1 ) );
       
   987         if ( !ptr.Compare( aFullPath ) )
       
   988             {
       
   989             append = EFalse;
       
   990             }
       
   991         }
       
   992     if ( append )
       
   993         {
       
   994         TRAPD( err, aArray.AppendL( aFullPath ) );
       
   995         if ( err != KErrNone )
       
   996             {
       
   997             ERROR_LOG1(
       
   998                 "CFileManagerActiveExecute::AppendArrayIfNotFound-err=%d",
       
   999                 err )
       
  1000             }
       
  1001         }
       
  1002     }
       
  1003 
       
  1004 // -----------------------------------------------------------------------------
       
  1005 // CFileManagerActiveExecute::FlushArray()
       
  1006 //
       
  1007 // -----------------------------------------------------------------------------
       
  1008 //
       
  1009 void CFileManagerActiveExecute::FlushArray( CDesCArray& aArray )
       
  1010     {
       
  1011     if ( aArray.MdcaCount() > 0 )
       
  1012         {
       
  1013 //        TRAP_IGNORE( iMgxFileManager->UpdateL( aArray ) );
       
  1014         aArray.Reset();
       
  1015         }
       
  1016     }
       
  1017 
       
  1018 // -----------------------------------------------------------------------------
       
  1019 // CFileManagerActiveExecute::UpdateNotifications()
       
  1020 //
       
  1021 // -----------------------------------------------------------------------------
       
  1022 //
       
  1023 void CFileManagerActiveExecute::UpdateNotifications(
       
  1024         TBool aFlush, TInt aError )
       
  1025     {
       
  1026     // Append notification item if operation was successful and 
       
  1027     // item does not already exist
       
  1028     if ( aError == KErrNone && iSrc && iDst && iItemType == EFileManagerFile )
       
  1029         {
       
  1030         // Notifications are relevant only for local drives
       
  1031         if ( iOperation == MFileManagerProcessObserver::EMoveProcess &&
       
  1032              !iIsSrcRemoteDrive )
       
  1033             {
       
  1034             AppendArrayIfNotFound( *iChangedSrcItems, *iSrc );
       
  1035             }
       
  1036         if ( !iIsDstRemoteDrive )
       
  1037             {
       
  1038             AppendArrayIfNotFound( *iChangedDstItems, *iDst );
       
  1039             }
       
  1040         }
       
  1041     if ( aFlush )
       
  1042         {
       
  1043         FlushArray( *iChangedSrcItems );
       
  1044         FlushArray( *iChangedDstItems );
       
  1045         }
       
  1046     }
       
  1047 
       
  1048 // -----------------------------------------------------------------------------
       
  1049 // CFileManagerActiveExecute::ThreadFinalizeMoveStepL()
       
  1050 //
       
  1051 // -----------------------------------------------------------------------------
       
  1052 //
       
  1053 void CFileManagerActiveExecute::ThreadFinalizeMoveStepL()
       
  1054     {
       
  1055     FUNC_LOG
       
  1056 
       
  1057     HBufC* folderToDelete = HBufC::NewLC( KMaxFileName );
       
  1058     TPtr ptrFolderToDelete( folderToDelete->Des() );
       
  1059     CDirScan* dirScan = CDirScan::NewLC( iFs );
       
  1060     dirScan->SetScanDataL( 
       
  1061         *iFullPath, 
       
  1062         KEntryAttNormal|KEntryAttHidden|KEntryAttSystem|
       
  1063         KEntryAttDir|KEntryAttMatchExclusive, 
       
  1064         ESortNone, 
       
  1065         CDirScan::EScanUpTree );
       
  1066     CDir* dir = NULL;
       
  1067     dirScan->NextL( dir );
       
  1068     while( dir )
       
  1069         {
       
  1070         CFileManagerUtils::RemoveReadOnlyAttribute(
       
  1071             iFs, dirScan->FullPath() );
       
  1072         CleanupStack::PushL( dir );
       
  1073         TInt count( dir->Count() );
       
  1074         for( TInt i( 0 ); i < count; ++i )
       
  1075             {
       
  1076             if ( iThreadWrapper->IsThreadCanceled() )
       
  1077                 {
       
  1078                 User::Leave( KErrCancel );
       
  1079                 }
       
  1080             TPtrC abbrPath( dirScan->AbbreviatedPath() );
       
  1081             const TEntry& entry( ( *dir )[ i ] );
       
  1082             ptrFolderToDelete.Copy( *iFullPath );
       
  1083             ptrFolderToDelete.Append( 
       
  1084                 abbrPath.Right( abbrPath.Length() - 1 ) );
       
  1085             ptrFolderToDelete.Append( entry.iName );
       
  1086             ptrFolderToDelete.Append( KFmgrBackslash );
       
  1087 #ifdef __KEEP_DRM_CONTENT_ON_PHONE
       
  1088             if ( iSrc && iDst &&
       
  1089                 CFileManagerUtils::IsFromInternalToRemovableDrive( iFs, *iSrc, *iDst ) )
       
  1090                 {
       
  1091                 HBufC* targetFolderToDelete = HBufC::NewLC( KMaxFileName );
       
  1092                 TPtr ptrTargetFolderToDelete( targetFolderToDelete->Des() );
       
  1093                 ptrTargetFolderToDelete.Append( *iDestination );
       
  1094                 ptrTargetFolderToDelete.Append( 
       
  1095                     abbrPath.Right( abbrPath.Length() - 1 ) );
       
  1096                 ptrTargetFolderToDelete.Append( entry.iName );
       
  1097                 ptrTargetFolderToDelete.Append( KFmgrBackslash );
       
  1098                 
       
  1099                 if ( IsEmptyDir( ptrFolderToDelete ) )
       
  1100                     {
       
  1101                     User::LeaveIfError( iFs.RmDir( ptrFolderToDelete ) );
       
  1102                     }
       
  1103                 else if ( IsEmptyDir( ptrTargetFolderToDelete ))
       
  1104                     {
       
  1105                     User::LeaveIfError( iFs.RmDir( ptrTargetFolderToDelete ) );
       
  1106                     }
       
  1107                 CleanupStack::PopAndDestroy( targetFolderToDelete );    
       
  1108                 }
       
  1109             else
       
  1110                 {
       
  1111                 User::LeaveIfError( iFs.RmDir( ptrFolderToDelete ) );   
       
  1112                 }
       
  1113 #else
       
  1114             User::LeaveIfError( iFs.RmDir( ptrFolderToDelete ) );
       
  1115 #endif
       
  1116             }
       
  1117         if ( iThreadWrapper->IsThreadCanceled() )
       
  1118             {
       
  1119             User::Leave( KErrCancel );
       
  1120             }
       
  1121         CleanupStack::PopAndDestroy( dir );
       
  1122         dir = NULL;
       
  1123         dirScan->NextL( dir );
       
  1124         }
       
  1125     CleanupStack::PopAndDestroy( dirScan );
       
  1126     CleanupStack::PopAndDestroy( folderToDelete );
       
  1127 #ifdef __KEEP_DRM_CONTENT_ON_PHONE
       
  1128     if ( iSrc && iDst &&
       
  1129         CFileManagerUtils::IsFromInternalToRemovableDrive( iFs, *iSrc, *iDst ) )
       
  1130         {
       
  1131         if ( IsEmptyDir( *iFullPath ) )
       
  1132             {
       
  1133             User::LeaveIfError( iFs.RmDir( *iFullPath ) );
       
  1134             }   
       
  1135         }
       
  1136     else
       
  1137         {
       
  1138         User::LeaveIfError( iFs.RmDir( *iFullPath ) );  
       
  1139         }
       
  1140 #else
       
  1141     User::LeaveIfError( iFs.RmDir( *iFullPath ) );
       
  1142 #endif
       
  1143     }
       
  1144 
       
  1145 // -----------------------------------------------------------------------------
       
  1146 // CFileManagerActiveExecute::ThreadStepL()
       
  1147 //
       
  1148 // -----------------------------------------------------------------------------
       
  1149 //
       
  1150 void CFileManagerActiveExecute::ThreadStepL()
       
  1151     {
       
  1152     FUNC_LOG
       
  1153 
       
  1154     if ( !iFinalizeMove )
       
  1155         {
       
  1156         ThreadCopyOrMoveStepL();
       
  1157         }
       
  1158     else
       
  1159         {
       
  1160         ThreadFinalizeMoveStepL();
       
  1161         }
       
  1162     }
       
  1163 
       
  1164 // -----------------------------------------------------------------------------
       
  1165 // CFileManagerActiveExecute::ToFolder()
       
  1166 //
       
  1167 // -----------------------------------------------------------------------------
       
  1168 //
       
  1169 EXPORT_C TPtrC CFileManagerActiveExecute::ToFolder()
       
  1170     {
       
  1171     if ( iToFolder )
       
  1172         {
       
  1173         return iToFolder->Des();
       
  1174         }
       
  1175     return TPtrC( KNullDesC );
       
  1176     }
       
  1177 
       
  1178 // End of File