phonebookui/Phonebook2/remotecontactlookup/contactactionservice/src/cfsccontactactionpluginengine.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/remotecontactlookup/contactactionservice/src/cfsccontactactionpluginengine.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,500 @@
+/*
+* 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:  Implementation of the class CFscContactActionPluginEngine.
+*
+*/
+
+
+// INCLUDES
+#include "emailtrace.h"
+#include <e32std.h>
+
+#include "fsccontactactionserviceuids.hrh"
+#include "cfsccontactactionpluginengine.h"
+#include "cfscactionutils.h"
+#include "mfsccontactaction.h"
+#include "cfsccontactactionplugin.h"
+#include "tfsccontactactionqueryresult.h"
+#include "mfsccontactactionpluginengineobserver.h"
+
+// ======== LOCAL FUNCTIONS ========
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CFscContactActionPluginEngine* CFscContactActionPluginEngine::NewL(
+    CVPbkContactManager& aContactManager )
+    {
+    FUNC_LOG;
+
+    CFscContactActionPluginEngine* self = 
+        new ( ELeave ) CFscContactActionPluginEngine( aContactManager );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+        
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CFscContactActionPluginEngine::~CFscContactActionPluginEngine()
+    {
+    FUNC_LOG;
+    ReleasePlugins();
+    iActionPlugins.Close();
+    delete iActionUtils;
+    }
+
+// ---------------------------------------------------------------------------
+// Detect and load plugins.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::LoadPluginsL()
+    {
+    FUNC_LOG;
+    
+    if ( iPluginsLoaded )
+        {
+        // Realease plugins before reloading
+        ReleasePlugins();
+        }
+        
+    RImplInfoPtrArray implArray;
+    TUid pluginIfUid = { KFscContactActionPluginIfUid };
+    REComSession::ListImplementationsL( pluginIfUid, implArray );
+        
+    //Create implementations
+    CFscContactActionPlugin* plugin = NULL;
+    TInt implArrayCount = implArray.Count();
+    for ( TInt i = 0; i < implArrayCount; i++ )
+        {
+        TRAPD( error,
+            {
+            plugin = CFscContactActionPlugin::NewL( 
+                implArray[i]->ImplementationUid(), iPluginParams );
+            CleanupStack::PushL( plugin );
+            iActionPlugins.AppendL( plugin );    
+            CleanupStack::Pop( plugin );
+            });
+        if ( error )
+            {
+                     
+            // Leave only if no memory. This way unstable plugins can not make 
+            // service totaly unusable
+            if ( error == KErrNoMemory )
+                {
+                implArray.ResetAndDestroy();            
+                User::Leave( error );
+                }
+            }
+        plugin = NULL;
+        }
+        
+    implArray.ResetAndDestroy();
+    iPluginsLoaded = ETrue;
+    
+    
+    }
+
+// ---------------------------------------------------------------------------
+// Release loaded plugins.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::ReleasePlugins()
+    {
+	FUNC_LOG;
+    iActionPlugins.ResetAndDestroy();
+    iPluginsLoaded = EFalse;
+    REComSession::FinalClose();
+    }
+    
+// ---------------------------------------------------------------------------
+// Query state of plugins.
+// ---------------------------------------------------------------------------
+//
+TBool CFscContactActionPluginEngine::PluginsLoaded()
+    {
+	FUNC_LOG;
+    return iPluginsLoaded;
+    }    
+
+// ---------------------------------------------------------------------------
+// CFscContactActionPluginEngine::AllActionsListL
+//
+// Get all actions of all contact action plugins matching provided action type flags
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::AllActionsListL(
+        CFscContactActionList& aActionList,
+        TUint64 aActionTypeFlags) 
+    {  
+    // Loop all loaded action plugins
+    TInt i = 0;       
+    while ( i < iActionPlugins.Count() )
+        {       
+        CFscContactActionPlugin* plugin = 
+                iActionPlugins[ i++ ];
+                  
+        const CArrayFix<TUid>* pluginActionList = plugin->ActionList();
+        TInt pluginActionCount = 
+                ( pluginActionList != NULL ) ? pluginActionList->Count() : 0;
+        
+        // Loop actions of single plugin and add only actions
+        // matching to the filter flags 
+        TInt j = 0; 
+        while ( j < pluginActionCount  )
+            {                                         
+            TUid uid = ( *pluginActionList )[ j++ ];
+            const MFscContactAction& action = plugin->GetActionL( uid );
+            if ( aActionTypeFlags & action.Type() )
+                {
+                TFscContactActionQueryResult contactActionQueryResult;
+                contactActionQueryResult.iAction = &action;
+                // add to full list    
+                aActionList.AppendL( contactActionQueryResult );     
+                }
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Method for quering actions for contacts and groups.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::QueryActionsL( 
+    CFscContactActionList& aActionList, MFscContactSet& aContactSet,
+    TBool aStopWhenOneActionFound, TUint64 aActionTypeFlags, 
+    TInt aMinPriority, MFscContactActionPluginEngineObserver* aObserver )
+    {
+	FUNC_LOG;
+    switch ( iLastEvent )
+        {
+        case ECasEventIdle:
+            {
+            iActionList = &aActionList;
+            iContactSet = &aContactSet;
+            iStopWhenOneActionFound = aStopWhenOneActionFound;
+            iActionTypeFlags = aActionTypeFlags; 
+            iMinPriority = aMinPriority;
+            iObserver = aObserver;
+            iCurrentActionPlugin = 0;
+            iCurrentAction = 0;
+            //iLastEvent = ECasEventBeforePriorityForContactSet;
+            // break; - no break here so we can go further when method 
+            // called for 1st time.
+            }
+        
+        case ECasEventBeforePriorityForContactSet:
+            {
+            TBool asyncStarted = EFalse;
+            // Loop plugins
+            while ( iCurrentActionPlugin < iActionPlugins.Count() 
+                    && !asyncStarted )
+                {
+                //Loop actions of single plugin
+                CFscContactActionPlugin* plugin = 
+                    iActionPlugins[ iCurrentActionPlugin ];
+                
+                const CArrayFix<TUid>* actionList = plugin->ActionList();
+                TInt actionCount = 
+                    ( actionList != NULL ) ? actionList->Count() : 0;
+                
+                while ( iCurrentAction < actionCount && !asyncStarted )
+                    {
+                    TUid uid = ( *actionList )[ iCurrentAction ];
+                    
+                    if ( aActionTypeFlags & plugin->GetActionL( uid ).Type() )
+                        {
+                        asyncStarted = ETrue;
+                        //Check action's priority for given contact set
+                        plugin->PriorityForContactSetL( uid, aContactSet,
+                            iContactActionQueryResult.iActionMenuVisibility,
+                            iContactActionQueryResult.iOptionsMenuVisibility, 
+                            this );
+                        }
+                    
+                    if ( !asyncStarted )
+                        {
+                        ++iCurrentAction;
+                        }
+                    }
+                
+                if ( !asyncStarted )
+                    {
+                    iCurrentAction = 0;
+                    ++iCurrentActionPlugin;
+                    }
+                }
+            
+            if ( !asyncStarted )
+                {
+                // inform observer that method finished
+                iObserver->QueryActionsComplete();
+                iLastEvent = ECasEventIdle;
+                }
+            
+            break;
+            }
+            
+        case ECasEventAfterPriorityForContactSet:
+            {
+            // here we have to do the same as in 
+            // ECasEventBeforePriorityForContactSet event
+            // because GetActionL returns const reference which we can't hold 
+            // in class' data.
+            CFscContactActionPlugin* plugin = 
+                iActionPlugins[ iCurrentActionPlugin ];
+            
+            const CArrayFix<TUid>* actionList = plugin->ActionList();
+            TInt actionCount = 
+                ( actionList != NULL ) ? actionList->Count() : 0;
+            
+            TUid uid = ( *actionList )[ iCurrentAction ];
+            const MFscContactAction& action = plugin->GetActionL( uid );
+            
+            // Add action if given minimum priority is exceeded
+            if ( iContactActionQueryResult.iPriority >= aMinPriority &&
+                 iContactActionQueryResult.iActionMenuVisibility.iVisibility != 
+                 TFscContactActionVisibility::EFscActionHidden )
+                {
+                iContactActionQueryResult.iAction = &action;
+                if( iActionList )
+                    {
+                    iActionList->AppendL( iContactActionQueryResult );
+                    }
+                }
+            
+            // if only one action is needed we stop method execution
+            if ( iStopWhenOneActionFound && iActionList && iActionList->Count() )
+                {
+                iLastEvent = ECasEventIdle;
+                iObserver->QueryActionsComplete();
+                }
+            else
+                {
+                // get next action
+                if ( iCurrentAction < actionCount )
+                    {
+                    iCurrentAction++;
+                    }
+                else
+                    {
+                    // no more actions for current plugin
+                    iCurrentAction = 0;
+                    iCurrentActionPlugin++;
+                    }
+                
+                // if needed run for next plugin
+                if ( iCurrentActionPlugin < iActionPlugins.Count() )
+                    {
+                    iLastEvent = ECasEventBeforePriorityForContactSet;
+                    QueryActionsL( *iActionList, *iContactSet, 
+                        iStopWhenOneActionFound, iActionTypeFlags, 
+                        iMinPriority, iObserver );
+                    }
+                else
+                    {
+                    // inform observer that method finished
+                    iLastEvent = ECasEventIdle;
+                    iObserver->QueryActionsComplete();
+                    }
+                }
+                        
+            break;
+            }
+            
+        case ECasEventCanceledPriorityForContactSet:
+            {
+            // PriorityforContactSet was cancelled
+            iLastEvent = ECasEventIdle;
+            iCurrentActionPlugin = 0;
+            iCurrentAction = 0;
+            if( iActionList )
+                {
+                iActionList->Reset();
+                }
+            break;
+            }
+            
+        default:
+            {
+            // we shouldn't be here
+            iObserver->QueryActionsFailed( KErrArgument );
+            iLastEvent = ECasEventIdle;
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Cancels async method QueryActionsL.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::CancelQueryActions()
+    {
+	FUNC_LOG;
+    TInt err = KErrNone;
+    if ( iActionPlugins.Count() > iCurrentActionPlugin )
+        {
+        iActionPlugins[ iCurrentActionPlugin ]->CancelPriorityForContactSet();
+        iLastEvent = ECasEventCanceledPriorityForContactSet;
+        TRAP( err, QueryActionsL( *iActionList, *iContactSet, 
+                    iStopWhenOneActionFound, iActionTypeFlags, iMinPriority, 
+                    iObserver ) );        
+        }
+    
+    if ( err!= KErrNone )
+        {
+        iObserver->QueryActionsFailed( err );
+        iLastEvent = ECasEventIdle;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Called when PriorityForContactSetL method is complete.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::PriorityForContactSetComplete( 
+    TInt aPriority )
+    {
+	FUNC_LOG;
+    iContactActionQueryResult.iPriority = aPriority;
+    iLastEvent = ECasEventAfterPriorityForContactSet;
+    TRAPD(err, QueryActionsL( *iActionList, *iContactSet, 
+            iStopWhenOneActionFound, iActionTypeFlags, iMinPriority, 
+            iObserver ) );
+    if ( err!= KErrNone )
+    	{
+    	iLastEvent = ECasEventIdle;
+    	iObserver->QueryActionsFailed( err );
+    	}
+    }
+
+// ---------------------------------------------------------------------------
+// Called when PriorityForContactSetL method failed.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::PriorityForContactSetFailed( 
+    TInt aError )
+    {
+	FUNC_LOG;
+    iLastEvent = ECasEventIdle;
+    iObserver->QueryActionsFailed( aError );
+    }
+
+// ---------------------------------------------------------------------------
+// Execute action. Aynchronous method.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::ExecuteL( 
+    TUid aActionUid, MFscContactSet& aContactSet,
+    MFscContactActionPluginEngineObserver* aObserver )
+    {
+	FUNC_LOG;
+    iObserver = aObserver;
+        
+    // Loop plugins
+    TBool found = EFalse;
+    for ( iCurrentActionPlugin = 0; 
+          iCurrentActionPlugin < iActionPlugins.Count() && !found; 
+          iCurrentActionPlugin++ )
+        {
+        // Loop actions
+        const CArrayFix<TUid>* actionList = 
+            iActionPlugins[ iCurrentActionPlugin ]->ActionList();
+        
+        TInt actionCount = 
+            ( actionList != NULL) ? actionList->Count() : 0;
+        for ( TInt j = 0; j < actionCount && !found; j++)
+            {
+            if ( ( *actionList )[j] == aActionUid )
+                {
+                found = ETrue;
+                
+                // Action found -> Execute
+                iActionPlugins[ iCurrentActionPlugin ]->ExecuteL( 
+                    aActionUid, aContactSet, this );
+                    
+                }
+            }// Loop actions
+        } // Loop plugins
+        
+    if ( !found )
+        {
+        ExecuteFailed( KErrNotFound );
+        }
+        
+    }
+
+// ---------------------------------------------------------------------------
+// Cancels async method ExecuteL.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::CancelExecute()
+    {
+	FUNC_LOG;
+    iActionPlugins[ iCurrentActionPlugin ]->CancelExecute();
+    }
+
+// ---------------------------------------------------------------------------
+// Called when ExecuteL method is complete.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::ExecuteComplete()
+    {
+	FUNC_LOG;
+    iObserver->ExecuteComplete();
+    }
+       
+// ---------------------------------------------------------------------------
+// Called when ExecuteL method failed.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::ExecuteFailed( TInt aError )
+    {
+	FUNC_LOG;
+    iObserver->ExecuteFailed( aError );
+    }
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CFscContactActionPluginEngine::CFscContactActionPluginEngine(
+    CVPbkContactManager& aContactManager )
+    : iContactManager( aContactManager ),
+    iPluginParams( NULL ),
+    iLastEvent( ECasEventIdle )
+    {
+	FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// Second phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CFscContactActionPluginEngine::ConstructL()
+    {
+	FUNC_LOG;
+    iActionUtils = CFscActionUtils::NewL( iContactManager );
+    iPluginParams = TFscContactActionPluginParams( iActionUtils );
+    }   
+