--- 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 <e32property.h> // RProperty
+#include <s32mem.h> // 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.