emailservices/psmruadapter/src/CPsMruAdapter.cpp
branchRCL_3
changeset 25 3533d4323edc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/psmruadapter/src/CPsMruAdapter.cpp	Wed Sep 01 12:28:57 2010 +0100
@@ -0,0 +1,742 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Data Store Adapter for MRU list
+ *
+*/
+
+
+
+
+#include <CPsData.h>
+#include <CPcsDefs.h>
+#include <coemain.h>
+#include <data_caging_path_literals.hrh>
+#include <VPbkEng.rsg>
+//<cmail>
+#include "cfsmailclient.h"
+#include "CPsMruAdapter.h"
+//</cmail>
+#include <mmf/common/mmfcontrollerpluginresolver.h> // CleanupResetAndDestroy
+
+
+#define PRINT(x)
+
+#include "emailtrace.h"
+
+// ============================== MEMBER FUNCTIONS ============================
+
+// Identifier for mailbox Uri
+_LIT(KDefaultMailBoxURI, "mailbox://");
+// Separator for plugin/mailbox identifiers inside the Uri string
+const TText8 KDefaultMailBoxURISeparator = '/';
+// Maximum length of uri
+const TInt KMaximumMailboxUriLength = 64;
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::NewL
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+CPsMruAdapter* CPsMruAdapter::NewL( TAny* aPsDataPluginParameters )
+    {
+    FUNC_LOG;
+    PRINT ( _L( "Enter CPsMruAdapter::NewL" ) );
+    
+    // Get the PsData plugin parametrs
+    TPsDataPluginParams* params =
+            reinterpret_cast<TPsDataPluginParams*>(aPsDataPluginParameters );
+    CPsMruAdapter* self = new ( ELeave ) CPsMruAdapter();
+    CleanupStack::PushL(self);
+    self->ConstructL( params->iDataStoreObserver, params->iStoreListObserver );
+    CleanupStack::Pop( self );
+    
+    PRINT ( _L( "End CPsMruAdapter::NewL" ) );
+    
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::CPsMruAdapter
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+CPsMruAdapter::CPsMruAdapter()
+    {
+    FUNC_LOG;
+    PRINT ( _L( "Enter CPsMruAdapter::CPsMruAdapter" ) );
+    iDelayMailboxCreationPtr = NULL;
+    PRINT ( _L( "End CPsMruAdapter::CPsMruAdapter" ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::ConstructL
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+void CPsMruAdapter::ConstructL( MDataStoreObserver* aObserverForDataStore,
+        MStoreListObserver* aStoreListObserver )
+    {
+    FUNC_LOG;   
+    PRINT ( _L( "Enter CPsMruAdapter::ConstructL" ) );
+
+    // Mail client for FS Email framework
+    iMailClient = CFSMailClient::NewL();
+
+    // Register as observer for mail client, we'll need this to observe MRU list changes
+    // When i.e mail is sent
+    iMailClient->AddObserverL( *this );
+
+    // This updates the list of all the supported datastores
+    UpdateSupportedDataStoresList();
+
+    // Store these for later use
+    iDataStoreObserver = aObserverForDataStore;
+    iStoreListObserver = aStoreListObserver;
+
+    PRINT ( _L( "End CPsMruAdapter::ConstructL" ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::~CPsMruAdapter
+// Destructor
+// ----------------------------------------------------------------------------
+CPsMruAdapter::~CPsMruAdapter()
+    {
+    FUNC_LOG;   
+    PRINT ( _L( "Enter CPsMruAdapter::~CPsMruAdapter" ) );
+
+    iSupportedUris.ResetAndDestroy();
+
+    // Remove observer, we don't need it anymore because we're shutting down
+    RemoveAllMailboxObservers();
+    iObservedMailboxes.Close();
+
+    if ( iMailClient )
+        {
+        iMailClient->RemoveObserver( *this );
+        iMailClient->Close();
+        }
+    if(iDelayMailboxCreationPtr)
+        {
+        delete iDelayMailboxCreationPtr;
+        iDelayMailboxCreationPtr = NULL;
+        }
+    
+    iDelayedCreatedMailboxes.Reset();
+    iDelayedCreatedMailboxes.Close();
+    
+    PRINT ( _L( "End CPsMruAdapter::~CPsMruAdapter" ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::RequestForDataL
+// 
+// ----------------------------------------------------------------------------
+void CPsMruAdapter::RequestForDataL( TDesC& aDataStoreURI )
+    {
+    FUNC_LOG;   
+    PRINT ( _L( "Enter CPsMruAdapter::RequestForDataL" ) );
+
+    // Add data to datastore, fill only requested one
+    FillDataStoreL( aDataStoreURI );
+
+    PRINT ( _L( "Enter CPsMruAdapter::RequestForDataL" ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::GetSupportedDataStoresL
+// 
+// ----------------------------------------------------------------------------
+
+void CPsMruAdapter::GetSupportedDataStoresL(
+        RPointerArray<TDesC> &aDataStoresURIs )
+    {
+    FUNC_LOG;   
+    for ( TInt i = 0; i < iSupportedUris.Count(); i++ )
+        {
+        aDataStoresURIs.Append( iSupportedUris[i] );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::RequestForDataExtensionL
+// 
+// ----------------------------------------------------------------------------
+TAny* CPsMruAdapter::RequestForDataExtensionL(TInt /*aItemId*/)
+    {
+    FUNC_LOG;   
+    // No extention required for this since we have and interger as itemId
+    // Simply return NULL
+    return NULL;
+    }
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::UpdateSupportedDataStoresList
+// 
+// ----------------------------------------------------------------------------
+void CPsMruAdapter::UpdateSupportedDataStoresList()
+    {
+    FUNC_LOG;   
+    // Mailboxes will be fetched to this array
+    RPointerArray<CFSMailBox> mailBoxes;
+
+    // List all mailboxes
+    TFSMailMsgId plugin;
+    iMailClient->ListMailBoxes( plugin, mailBoxes );
+
+    iSupportedUris.ResetAndDestroy();
+
+    // Add all mailboxes as data stores
+    for ( TInt i = 0; i < mailBoxes.Count(); i++ )
+        {
+        // Get id of mailbox
+        TFSMailMsgId id = mailBoxes[i]->GetId();
+
+        // Convert it to string, this will be the unique identifier for this mailbox
+        HBufC* identifier = HBufC::New( KMaximumMailboxUriLength );
+        if ( identifier && GetUriFromMailboxIdentifier( id, *identifier ) )
+            {
+            // Add to supported Uris list
+            if ( iSupportedUris.Append( identifier ) == KErrNone )
+                {
+                // Ownership of the string is successfully moved to the array
+                identifier = NULL;
+                }
+            }
+        delete identifier;
+        }
+
+    // Release allocated memory
+    mailBoxes.ResetAndDestroy();
+    }
+
+// ----------------------------------------------------------------------------
+// CPsMruAdapter::FillDataStoreL
+// ----------------------------------------------------------------------------
+TBool CPsMruAdapter::FillDataStoreL( TDesC& aDataStoreURI )
+    {
+    FUNC_LOG;   
+    TBool result = EFalse;
+
+    TFSMailMsgId dataStoreId;
+
+    if ( GetMailboxIdentifierFromUri( aDataStoreURI, dataStoreId ) )
+        {
+        result = FillDataStoreL( dataStoreId, aDataStoreURI );
+        }
+
+    return result;
+    }
+
+TBool CPsMruAdapter::FillDataStoreL( TFSMailMsgId& aId )
+    {
+    FUNC_LOG;   
+    TBool result = EFalse;
+
+    // Create Uri for this mailbox
+    HBufC* identifier = HBufC::NewLC( KMaximumMailboxUriLength );
+    if ( GetUriFromMailboxIdentifier( aId, *identifier ) )
+        {
+        result = FillDataStoreL( aId, *identifier );
+        }
+    CleanupStack::PopAndDestroy( identifier );
+    return result;
+    }
+
+void CPsMruAdapter::AddMruEmailsL( MDesCArray* aMruList, TDesC& aDataStoreURI )
+    {
+    FUNC_LOG;   
+    TInt entryIndex = 0;
+    // Add all data to data store, the format is:
+    // index0: displayname
+    // index1: email
+    // index2: next displayname
+    // index3: next email
+    // etc..
+    for ( int mruIndex = 0; mruIndex < aMruList->MdcaCount(); mruIndex += 2 )
+        {
+        TPtrC displayName = aMruList->MdcaPoint( mruIndex );
+        TPtrC emailAddress = aMruList->MdcaPoint( mruIndex + 1 );
+
+        CPsData* mruData = CPsData::NewL();
+        CleanupStack::PushL(mruData);
+        mruData->SetId( entryIndex++ );
+
+        // Set the data
+        mruData->SetDataL( 0, displayName );
+        mruData->SetDataL( 1, KNullDesC );
+        mruData->SetDataL( 2, emailAddress );
+
+        iDataStoreObserver->AddData( aDataStoreURI, mruData );
+        CleanupStack::Pop(mruData); // transferred ownership
+        }
+    }
+
+TBool CPsMruAdapter::FillDataStoreL( TFSMailMsgId& aId, TDesC& aDataStoreURI )
+    {
+    FUNC_LOG;   
+    TBool result = EFalse;
+// code was simplified not to trace all mailboxes
+// function has trap in  Event() -case> TFSEventNewMailbox and in DeleayedMailboxCreationEventL()
+// should not leave when new mailbox only when new mail address
+// TODO SK how to avoid extra calls?    
+    CFSMailBox *mailBox = iMailClient->GetMailBoxByUidLC(aId);
+    if( mailBox )
+        {
+        AddMailboxObserverL( aId );
+        
+        // Get MRU list for this mailbox
+        MDesCArray* mruList = mailBox->ListMrusL(); // TODO SK this value can be cached?
+        //TODO add to cleanup stack?
+        
+        // update the caching status as InProgress
+        iDataStoreObserver->UpdateCachingStatus( aDataStoreURI,
+                ECachingInProgress );
+
+        // Update datastore contents, first reset
+        iDataStoreObserver->RemoveAll( aDataStoreURI );
+
+        TInt trap_err=KErrNone; // for trap macro
+        if ( mruList )
+            {
+            // trap the error to enable returning status back
+            TRAP(trap_err, AddMruEmailsL( mruList, aDataStoreURI ) );  
+            delete mruList;
+            }
+        // update the caching status as Complete
+        iDataStoreObserver->UpdateCachingStatus( aDataStoreURI,
+                ECachingComplete );
+        if ( trap_err != KErrNone ) // check for error leave code 
+            {  
+            User::Leave(trap_err);       
+            }
+        result = ETrue;
+        }   // if (mailBox)
+    CleanupStack::PopAndDestroy( mailBox );
+    return result;
+    }
+
+// ----------------------------------------------------------------------------
+// CPsContactDataAdapter::IsDataStoresSupportedL
+// 
+// ----------------------------------------------------------------------------
+TBool CPsMruAdapter::IsDataStoresSupportedL( TDesC& aDataStoreURI )
+    {
+    FUNC_LOG;   
+    for ( TInt i = 0; i < iSupportedUris.Count(); i++ )
+        {
+        if ( iSupportedUris[i]->Compare( aDataStoreURI ) == 0 )
+            return ETrue;
+        }
+    return EFalse;
+    }
+
+// ----------------------------------------------------------------------------
+// CPsContactDataAdapter::GetSupportedDataFieldsL
+// 
+// ----------------------------------------------------------------------------
+void CPsMruAdapter::GetSupportedDataFieldsL( RArray<TInt>& aDataFields )
+    {
+    FUNC_LOG;   
+    aDataFields.Append( R_VPBK_FIELD_TYPE_FIRSTNAME );
+    aDataFields.Append( R_VPBK_FIELD_TYPE_LASTNAME );
+    aDataFields.Append( R_VPBK_FIELD_TYPE_EMAILGEN );
+    }
+
+TBool CPsMruAdapter::GetMailboxIdentifierFromUri( TDesC& aUri, TFSMailMsgId& aId )
+    {
+    FUNC_LOG;   
+    // Find first separator in reverse order
+    TInt lastSeparator = aUri.LocateReverseF( KDefaultMailBoxURISeparator );
+    if ( lastSeparator == KErrNotFound )
+        return EFalse;
+
+    // This is where plugin id string starts
+    TInt pluginIdStartPosition = KDefaultMailBoxURI().Length();
+    TInt mailboxIdStartPosition = lastSeparator + 1;
+
+    // It cannot be further than mailbox id
+    if ( pluginIdStartPosition >= mailboxIdStartPosition )
+        return EFalse;
+
+    // Use TLex to convert string to integer
+    TLex pluginIdConverter( aUri.Mid( pluginIdStartPosition,
+            mailboxIdStartPosition - pluginIdStartPosition - 1 ) );
+
+    // Use TLex to convert string to integer
+    TLex mailboxIdConverter( aUri.Mid( mailboxIdStartPosition, aUri.Length()
+            - mailboxIdStartPosition ) );
+
+    TInt pluginId;
+    TInt mailboxId;
+
+    // Get plugin ID
+    if ( pluginIdConverter.Val( pluginId ) != KErrNone)
+        return EFalse;
+
+    // Get mailbox ID
+    if ( mailboxIdConverter.Val( mailboxId ) != KErrNone)
+        return EFalse;
+
+    // Store and we're ready
+    aId.SetPluginId( TUid::Uid( pluginId ) );
+    aId.SetId( mailboxId );
+
+    return ETrue;
+    }
+
+TBool CPsMruAdapter::GetUriFromMailboxIdentifier( TFSMailMsgId& aId, HBufC& aUri )
+    {
+    FUNC_LOG;   
+    // Add the uri identifier
+    aUri.Des().Copy( KDefaultMailBoxURI );
+    // Add plugin ID
+    aUri.Des().AppendNum( aId.PluginId().iUid );
+    // Add separator
+    aUri.Des().Append( KDefaultMailBoxURISeparator );
+    // Add mailbox id
+    aUri.Des().AppendNum( aId.Id() );
+    
+    return true;
+    }
+
+void CPsMruAdapter::EventL( TFSMailEvent aEvent, TFSMailMsgId aMailbox,
+        TAny* /*aParam1*/, TAny* aParam2, TAny* /*aParam3*/ )
+    {
+    FUNC_LOG;   
+    switch ( aEvent )
+        {
+        case TFSEventMailMoved:
+        case TFSEventMailCopied:        
+        case TFSEventNewMail:
+            {
+            // Check the new parent folder id for this message
+            // For all these events, param2 indicates the new parent folder
+            TFSMailMsgId* parentFolderId =
+                    static_cast< TFSMailMsgId* >( aParam2 );
+            if ( parentFolderId )
+                {
+                TFSFolderType folderType( EFSInbox ); 
+                if ( (*parentFolderId) == iPreviousParentFolderId && aMailbox == iPreviousMailboxId )
+                    {
+                    // we assume that folder with some id does not change 
+                    // its type during mail synchronization
+                    folderType = iPreviousParentFolderType;
+                    }
+                else
+                    {
+                    // Get the parent folder object
+                    CFSMailFolder* parentFolder = iMailClient->GetFolderByUidL(
+                            aMailbox, *parentFolderId );
+                    if ( parentFolder )
+                        {
+                        iPreviousParentFolderId = (*parentFolderId);
+                        iPreviousMailboxId = aMailbox;
+                        folderType = parentFolder->GetFolderType();
+                        iPreviousParentFolderType = folderType;
+                        delete parentFolder;
+                        parentFolder = NULL;
+                        }
+                    }
+                // If it's sent/outbox folder,
+                // we'll consider that as a new message being sent
+                // and therefore we'll update the MRU list here
+                if ( ( folderType == EFSSentFolder ) || 
+                     ( folderType == EFSOutbox ) )
+                    {
+                    FillDataStoreL( aMailbox );
+                    }
+                }
+            }
+            break;
+            
+        case TFSEventNewMailbox:
+            {
+            CFSMailBox *mailboxPtr(NULL);
+            // if mailbox is not ready it may leave here
+            TRAPD(trap_err, mailboxPtr = iMailClient->GetMailBoxByUidL( aMailbox ));
+            if ( trap_err != KErrNone )
+                {
+                mailboxPtr = NULL;
+                }
+            if( mailboxPtr ) 
+                {
+                delete mailboxPtr;
+                mailboxPtr = NULL;
+                }
+            else
+                {
+                // mailbox still does not exist
+                DeleayMailboxCreationEventL( aMailbox ); // start timer to postpone creation    
+                break;
+                }
+            
+            HBufC* identifier = HBufC::NewLC( KMaximumMailboxUriLength ); // new string ident
+            if ( GetUriFromMailboxIdentifier( aMailbox, *identifier ) )
+                {
+                // Add to supported Uri list
+                iSupportedUris.AppendL( identifier );
+
+                // Add new data store to cache
+                iStoreListObserver->AddDataStore( *identifier );
+
+                // Add all data to data store
+                // FillDataStoreL( *identifier );
+                // FillDataStoreL removed - called by AddDataStore through RequestForDataL callback
+
+                // In case there is a problem with transferring strings to  - should be obsolete 
+                AddMailboxObserverL( aMailbox ); // will be added by FillDataStoreL
+
+                CleanupStack::Pop( identifier );
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy( identifier );
+                }
+            }
+            break;
+
+        case TFSEventMailboxDeleted:
+            {
+            HBufC* identifier = HBufC::NewL( KMaximumMailboxUriLength );
+            if ( GetUriFromMailboxIdentifier( aMailbox, *identifier ) )
+                {
+                RemoveMailboxObserver( aMailbox );
+
+                // Remove data store from cache
+                iStoreListObserver->RemoveDataStore( *identifier );
+
+                // Remove from supported Uri list
+                for ( TInt i = 0; i < iSupportedUris.Count(); i++ )
+                    {
+                    if ( iSupportedUris[i]->Compare( *identifier ) == 0 )
+                        {
+                        delete iSupportedUris[i];
+                        iSupportedUris.Remove( i );
+                        break;
+                        }
+                    }
+                }
+            delete identifier;
+            
+            iPreviousParentFolderId = TFSMailMsgId();
+            iPreviousMailboxId = TFSMailMsgId();  
+            break;
+            }
+        case TFSEventMailboxSettingsChanged: // TODO SK check
+            {
+            iPreviousParentFolderId = TFSMailMsgId();
+            iPreviousMailboxId = TFSMailMsgId();  
+            break;
+            }
+        }
+    }
+TBool CPsMruAdapter::AddMailboxObserverL( TFSMailMsgId& aId )
+    {
+    FUNC_LOG;   
+    for( TInt index = 0; index < iObservedMailboxes.Count(); index++ )
+        {
+        if( iObservedMailboxes[index] == aId )
+            {
+            // Already observing
+            return EFalse;
+            }
+        }
+    
+    iMailClient->SubscribeMailboxEventsL( aId, *this );
+    iObservedMailboxes.Append( aId );
+    return ETrue;
+    }
+
+TBool CPsMruAdapter::RemoveMailboxObserver( TFSMailMsgId& aId )
+    {
+    FUNC_LOG;   
+    for( TInt index = 0; index < iObservedMailboxes.Count(); index++ )
+        {
+        if( iObservedMailboxes[index] == aId )
+            {
+            iMailClient->UnsubscribeMailboxEvents( aId, *this );
+            iObservedMailboxes.Remove( index );
+            return ETrue;
+            }
+        }
+    
+    return EFalse;
+    }
+
+void CPsMruAdapter::RemoveAllMailboxObservers()
+    {
+    FUNC_LOG;   
+    for( TInt index = 0; index < iObservedMailboxes.Count(); index++ )
+        {
+        iMailClient->UnsubscribeMailboxEvents( iObservedMailboxes[index], *this );
+        }
+
+    iObservedMailboxes.Reset(); 
+    }
+
+/**
+ * If problem with NewMailbox this function will be called 
+ * by CDelayMailboxCreationHelper timer to try it after some delay
+ */
+TBool CPsMruAdapter::DeleayedMailboxCreationEventL()
+    {
+    FUNC_LOG;
+    for ( int i = iDelayedCreatedMailboxes.Count()-1; i>=0; i-- )
+        {
+        CFSMailBox *mailboxPtr(NULL);
+        // if mailbox is not ready it may leave there
+        TRAPD(trap_err, mailboxPtr = iMailClient->GetMailBoxByUidL( iDelayedCreatedMailboxes[i] ));
+        if ( trap_err != KErrNone )
+            {
+            mailboxPtr = NULL;
+            }
+        if ( mailboxPtr ) 
+            {
+            delete mailboxPtr;
+            mailboxPtr = NULL;
+            
+            HBufC* identifier = HBufC::NewLC( KMaximumMailboxUriLength ); // new string ident
+            if ( GetUriFromMailboxIdentifier( iDelayedCreatedMailboxes[i], *identifier ) )
+                {
+
+                // Add to supported Uri list
+                iSupportedUris.AppendL( identifier );
+
+                // Add new data store to cache
+                iStoreListObserver->AddDataStore( *identifier );
+
+                // Add all data to data store 
+                // removed because this is called by AddDataStore through RequestForDataL callback
+                // FillDataStoreL( *identifier );
+
+                // In case there is a problem with transferring strings to  - should be obsolete 
+                AddMailboxObserverL( iDelayedCreatedMailboxes[i] ); // will be added by FillDataStoreL
+
+                CleanupStack::Pop( identifier );
+                iDelayedCreatedMailboxes.Remove( i );       
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy( identifier );
+                }
+            } 
+        }
+    return ( 0 == iDelayedCreatedMailboxes.Count() );
+    }
+
+/**
+ * If problem with NewMailbox this function will use 
+ * CDelayMailboxCreationHelper to try it after some delay
+ */
+void CPsMruAdapter::DeleayMailboxCreationEventL( TFSMailMsgId &aMailbox )
+    {
+    FUNC_LOG;   
+    if ( NULL == iDelayMailboxCreationPtr )
+        {
+        iDelayMailboxCreationPtr = CDelayMailboxCreationHelper::NewL( this );
+        }
+    iDelayedCreatedMailboxes.Append( aMailbox );
+    iDelayMailboxCreationPtr->StartDelayedCall();
+    }
+
+// ---------------------------------------------------------------------------------------------------
+// class CDelayMailboxCreationHelper : public CTimer
+// ---------------------------------------------------------------------------------------------------
+
+// static construction leaving on the stack
+CDelayMailboxCreationHelper* CDelayMailboxCreationHelper::NewLC( CPsMruAdapter *aPsMruAdapterPtr )
+    {
+    FUNC_LOG;
+    CDelayMailboxCreationHelper* self = new ( ELeave ) CDelayMailboxCreationHelper( aPsMruAdapterPtr );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// static construction leaving
+CDelayMailboxCreationHelper* CDelayMailboxCreationHelper::NewL( CPsMruAdapter *aPsMruAdapterPtr )
+    {
+    FUNC_LOG;
+    CDelayMailboxCreationHelper* self = CDelayMailboxCreationHelper::NewLC( aPsMruAdapterPtr );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// used by MruAdapter when delayed datasource adding is needed
+void CDelayMailboxCreationHelper::StartDelayedCall()    
+    {
+    FUNC_LOG;
+    if( IsActive() )  // don't call again in case the timer rq is pending
+        {
+        Cancel();
+        }
+    iNumberOfDelayedTrials = KNumberOfDelayedTrials;
+    After( KDelayToRunAddMailbox );  // CTimer::After contains SetActive() 
+    }
+
+// Limited unsuccesful call repeating
+void CDelayMailboxCreationHelper::RunL()
+    {
+    FUNC_LOG;
+    iNumberOfDelayedTrials --; 
+    User::LeaveIfError( iStatus.Int() );
+    TBool Handled = iPsMruAdapterPtr->DeleayedMailboxCreationEventL();
+    if (( Handled ) || ( 0 >= iNumberOfDelayedTrials ))
+        { // no need to call again
+        Cancel();
+        }
+    else
+        { // wait once more
+//      SetActive is called by After
+        After( KDelayToRunAddMailbox ); 
+        }
+    }
+
+// when leave from RunL, if err handled return KErrNone
+TInt CDelayMailboxCreationHelper::RunError( TInt aError )
+    {
+    FUNC_LOG;
+    if ( KErrNone != aError )
+        {
+        Cancel(); // stop pending requiest
+        }
+    return KErrNone; //not desired to panic the thread in case of error returned
+    }
+
+// 2nd phase of construction
+void CDelayMailboxCreationHelper::ConstructL()
+    {
+    FUNC_LOG;
+    CTimer::ConstructL();
+    CActiveScheduler::Add( this );
+    }
+
+// c-tor   
+CDelayMailboxCreationHelper::CDelayMailboxCreationHelper(
+    CPsMruAdapter *aPsMruAdapterPtr )
+    : CTimer( EPriorityStandard )  //possible also EPriorityLow, EPriorityIdle
+    , iPsMruAdapterPtr ( aPsMruAdapterPtr )  // not ownink ptr
+    , iNumberOfDelayedTrials ( KNumberOfDelayedTrials ) //limited repeating num.
+    {
+    FUNC_LOG;
+    }
+
+// d-tor
+CDelayMailboxCreationHelper::~CDelayMailboxCreationHelper()
+    {
+    FUNC_LOG;
+    iPsMruAdapterPtr = NULL; // not owning interface ptr
+    Cancel();  // stop pending request
+    Deque();   // remove from CActiveScheduler
+    }
+
+// End of file