diff -r a4d6f1ea0416 -r e7aa27f58ae1 emailservices/emailclientapi/src/emailinterfacefactoryimpl.cpp --- a/emailservices/emailclientapi/src/emailinterfacefactoryimpl.cpp Tue Jan 26 11:45:42 2010 +0200 +++ b/emailservices/emailclientapi/src/emailinterfacefactoryimpl.cpp Tue Feb 02 00:02:40 2010 +0200 @@ -15,6 +15,9 @@ * */ +#include // RProperty +#include // RDesRead/WriteStream + #include "emailinterfacefactoryimpl.h" #include "emailcontent.h" #include "CFSMailClient.h" @@ -22,8 +25,10 @@ #include "emailclientapiimpl.h" #include "emailaddress.h" #include "emailmessagesearch.h" +#include "emailshutdownconst.h" _LIT( KEmailImplPanic, "Email client API" ); +const TInt KEmailUidExtraBuffer = 2 * KEmailPlatformApiUidItemSize; // --------------------------------------------------------------------------- // Email client API panic wrapper @@ -43,6 +48,9 @@ CEmailInterfaceFactoryImpl* CEmailInterfaceFactoryImpl::NewL() { CEmailInterfaceFactoryImpl* self = new (ELeave) CEmailInterfaceFactoryImpl(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); return self; } @@ -52,6 +60,7 @@ // CEmailInterfaceFactoryImpl::~CEmailInterfaceFactoryImpl() { + TRAP_IGNORE( AppendOrRemoveUidL( EEmailUidModeRemove ) ); } // --------------------------------------------------------------------------- @@ -62,7 +71,20 @@ CEmailInterfaceFactory() { } - + +// --------------------------------------------------------------------------- +// CEmailInterfaceFactoryImpl::ConstructL +// --------------------------------------------------------------------------- +// +void CEmailInterfaceFactoryImpl::ConstructL() + { + // This leaves if related P&S keys are not defined by EmailServerMonitor, + // so EmailServerMonitor need to be started before using client API. + // TRAP_IGNORE should be removed after EmailServerMonitor is added to + // starter list. + TRAP_IGNORE( AppendOrRemoveUidL( EEmailUidModeAppend ) ); + } + // --------------------------------------------------------------------------- // CEmailInterfaceFactoryImpl::InterfaceL // --------------------------------------------------------------------------- @@ -90,4 +112,113 @@ return interface; } +// --------------------------------------------------------------------------- +// CEmailInterfaceFactoryImpl::AppendOrRemoveUidL +// --------------------------------------------------------------------------- +// +void CEmailInterfaceFactoryImpl::AppendOrRemoveUidL( + const TEmailUidAppendRemoveMode aMode ) + { + // Read buffer length + TInt bufLength( 0 ); + User::LeaveIfError( RProperty::Get( KEmailShutdownPsCategory, + EEmailPsKeyPlatformApiAppsToCloseLength, + bufLength ) ); + + // Allocate buffer for reading and then read the list of UIDs from P&S. + // Adding some extra buffer just in case the size key and actual list + // are out of sync. This shouldn't happen, but you never know. + HBufC8* readBuf = HBufC8::NewLC( bufLength + KEmailUidExtraBuffer ); + TPtr8 readPtr = readBuf->Des(); + + User::LeaveIfError( RProperty::Get( KEmailShutdownPsCategory, + EEmailPsKeyPlatformApiAppsToClose, + readPtr ) ); + + // For writing get the size of the original buffer + room for our own UID + // if needed + TInt writeBufSize = readPtr.Length(); + if( aMode == EEmailUidModeAppend ) + { + writeBufSize += KEmailPlatformApiUidItemSize; + } + + HBufC8* writeBuf = HBufC8::NewLC( writeBufSize ); + TPtr8 writePtr = writeBuf->Des(); + + // Read and write streams used to read/write the UIDs from/to descriptors + RDesReadStream readStream( readPtr ); + CleanupClosePushL( readStream ); + + RDesWriteStream writeStream( writePtr ); + CleanupClosePushL( writeStream ); + + // Get our own process UID + RProcess ownProcess; + TUid ownUid = ownProcess.SecureId(); + ownProcess.Close(); + + TInt itemsCount = readPtr.Length() / KEmailPlatformApiUidItemSize; + + TBool ownUidFound = EFalse; + TInt writeLength = 0; + for ( TInt ii = 0;ii < itemsCount; ++ii ) + { + // Read next UID from the stream + TUid item = TUid::Uid( readStream.ReadInt32L() ); + + // We can skip our own UID. If we are removing, then we don't want + // our UID to be written. If we are adding, we don't need to set + // the new values as our UID already exists in the list. + if( item == ownUid ) + { + ownUidFound = ETrue; + if( aMode == EEmailUidModeAppend ) + { + // Our own UID is already in the list, so no need to update + // the list. Hence we can quit here. + break; + } + } + else + { + writeStream.WriteInt32L( item.iUid ); + writeLength += KEmailPlatformApiUidItemSize; + } + } + + // If we are appending our UID and it wasn't found from the list, + // write it to the stream + if( aMode == EEmailUidModeAppend && !ownUidFound ) + { + writeStream.WriteInt32L( ownUid.iUid ); + writeLength += KEmailPlatformApiUidItemSize; + } + + // Set correct length for the write ptr buffer as it might not be + // updated correctly by the write stream + writePtr.SetLength( writeLength ); + + // Set new values to P&S only if something has changed, so either: + // 1) We are appending our UID and it didn't exist before + // 2) We are removing our UID and it did exist before + if( ( aMode == EEmailUidModeAppend && !ownUidFound ) || + ( aMode == EEmailUidModeRemove && ownUidFound ) ) + { + // Write first the UID list as it is more probable to fail, writing + // plain integer value shouldn't fail in any case. This way these + // values stay in sync also in case of error, as the list length + // gets updated only if the list itself is updated succesfully. + User::LeaveIfError( RProperty::Set( KEmailShutdownPsCategory, + EEmailPsKeyPlatformApiAppsToClose, + writePtr ) ); + + User::LeaveIfError( RProperty::Set( KEmailShutdownPsCategory, + EEmailPsKeyPlatformApiAppsToCloseLength, + writeLength ) ); + } + + CleanupStack::PopAndDestroy( 4, readBuf ); + } + // End of file.