emailservices/emailclientapi/src/emailinterfacefactoryimpl.cpp
changeset 4 e7aa27f58ae1
parent 0 8466d47a6819
child 8 e1b6206813b4
--- 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.