contextframework/cfw/src/cfoperationpluginservices/cfoperationpluginmanager.cpp
author William Roberts <williamr@symbian.org>
Fri, 23 Apr 2010 14:37:17 +0100
branchRCL_3
changeset 22 c82a39b81a38
parent 0 2e3d3ce01487
permissions -rw-r--r--
Rework addition of Symbian splash screen to reduce the source impact (uses SVG from Bug 2414) Notes: by using the OPTION SOURCEDIR parameter in the mifconv extension instructions, I can arrange to use the same source file name in sfimage, without having to export over the original Nokia file. This means that the name inside splashscreen.mbg is the same, which removes the need for the conditional compilation in SplashScreen.cpp, and gets rid of sf_splashscreen.mmp.

/*
* Copyright (c) 2008-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:  CFContextSourceManager class implementation.
*
*/



#include <ecom/ecom.h>
#include <centralrepository.h>
#include <bautils.h>

#include "cfoperationpluginmanager.h"
#include "ContextFrameworkPrivateCRKeys.h"
#include "cfoperationplugin.h"
#include "cfoperationservices.h"
#include "cftrace.h"
#include "CFScriptEngineInterface.h"

// ============================= LOCAL FUNCTIONS ==============================

/**
* Clenup operation for RImplInfoPtrArray
*/
LOCAL_C void CleanUpImplInfoArray( TAny* aParams )
    {
    RImplInfoPtrArray* array = static_cast<RImplInfoPtrArray*>( aParams );
    array->ResetAndDestroy();
    }

/**
* Push operations
*/
LOCAL_C void CleanupResetAndDestroyPushL( RImplInfoPtrArray& aArray )
    {
    TCleanupItem item( CleanUpImplInfoArray, &aArray );
    CleanupStack::PushL( item );
    }

/**
* Operation plug-in information.
*/
NONSHARABLE_CLASS( TCFOperationPluginInfo )
    {
    public:

        TCFOperationPluginInfo( CImplementationInformation& aImplInfo,
            CCFOperationPlugIn* aPlugIn ):
            iImplUid( aImplInfo.ImplementationUid() ),
            iImplVersion( aImplInfo.Version() ),
            iMissing( EFalse ),
            iPlugIn( aPlugIn )
            {
            }

    public:

        TUid iImplUid;
        TInt iImplVersion;
        TBool iMissing;
        CCFOperationPlugIn* iPlugIn;
    };

// ============================= MEMBER FUNCTIONS =============================

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::NewL
// ---------------------------------------------------------------------------
//
EXPORT_C CCFOperationPluginManager* CCFOperationPluginManager::NewL(
    MCFScriptEngineInterface& aScriptEngine )
    {
    FUNC_LOG;

    CCFOperationPluginManager* self =
        CCFOperationPluginManager::NewLC( aScriptEngine );
    CleanupStack::Pop( self );

    return self;
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::NewLC
// ---------------------------------------------------------------------------
//
EXPORT_C CCFOperationPluginManager* CCFOperationPluginManager::NewLC(
    MCFScriptEngineInterface& aScriptEngine )
    {
    FUNC_LOG;

    CCFOperationPluginManager* self =
        new( ELeave ) CCFOperationPluginManager( aScriptEngine );
    CleanupStack::PushL( self );
    self->ConstructL();

    return self;
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::~CCFOperationPluginManager
// ---------------------------------------------------------------------------
//
EXPORT_C CCFOperationPluginManager::~CCFOperationPluginManager()
    {
    FUNC_LOG;

    // Delete plug-ins
    TInt count = iPlugIns.Count();
    for( TInt i = 0; i < count; i++ )
        {
        delete iPlugIns[i].iPlugIn;
        }
    iPlugIns.Close();
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::CCFOperationPluginManager
// ---------------------------------------------------------------------------
//
CCFOperationPluginManager::CCFOperationPluginManager(
    MCFScriptEngineInterface& aScriptEngine ):
    iScriptEngine( aScriptEngine )
    {
    FUNC_LOG;

    // Nothing to do
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::ConstructL
// ---------------------------------------------------------------------------
//
void CCFOperationPluginManager::ConstructL()
    {
    FUNC_LOG;

    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::InitializePhaseL
// ---------------------------------------------------------------------------
//
void CCFOperationPluginManager::InitializePhaseL(
    CCFPhaseBase::TCFPhaseId aPhase )
    {
    FUNC_LOG;

    switch( aPhase )
        {
        case CCFPhaseBase::ECFDeviceStarting:
            {
            InitDeviceStartingPhaseL();
            break;
            }
        case CCFPhaseBase::ECFLoadingPlugins:
            {
            InitLoadingPluginsPhaseL();
            break;
            }
        default:
            {
            break;
            }
        }
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::SetEventHandler
// ---------------------------------------------------------------------------
//
void CCFOperationPluginManager::SetEventHandler( MCFStarterEventHandler& /*aEventHandler*/ )
    {
    FUNC_LOG;	  
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::CreateAndInitializePlugInL
// ---------------------------------------------------------------------------
//
CCFOperationPlugIn* CCFOperationPluginManager::CreateAndInitializePlugInL(
    const TUid& aImplementationUid, TOperationPluginInitParams& aParams )
    {
    FUNC_LOG;

    // Create plug-in
    CCFOperationPlugIn* plugIn = CCFOperationPlugIn::NewL(
        aImplementationUid,
        &aParams );
    CleanupStack::PushL( plugIn );

    // Cleanup
    CleanupStack::Pop( plugIn );

    return plugIn;
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::InitDeviceStartingPhaseL
// ---------------------------------------------------------------------------
//
void CCFOperationPluginManager::InitDeviceStartingPhaseL()
    {
    FUNC_LOG;

    INFO( "Checking plug-ins in [Init Device Starting] phase." );
    UpdatePlugInsL();
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::InitLoadingPluginsPhaseL
// ---------------------------------------------------------------------------
//
void CCFOperationPluginManager::InitLoadingPluginsPhaseL()
    {
    FUNC_LOG;
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::LoadPluginL
// ---------------------------------------------------------------------------
//
void CCFOperationPluginManager::LoadPluginL(
	CImplementationInformation& aImplInfo )
    {
    FUNC_LOG;

    INFO_2( "Loading operation plug-in with UID [%x], version [%d]",
    		aImplInfo.ImplementationUid().iUid,	aImplInfo.Version() );

    HEAP_2( "Before loading operation plug-in with UID [%x], version [%d]",
            aImplInfo.ImplementationUid().iUid, aImplInfo.Version() );

    TOperationPluginInitParams initParams;
    CCFOperationPlugIn* plugIn = NULL;
    TRAPD( err, plugIn = CreateAndInitializePlugInL(
    		aImplInfo.ImplementationUid(),
    		initParams ) );
    if( err == KErrNone )
        {
        // Plug-in loaded succesfully, store it
        TCFOperationPluginInfo info( aImplInfo, plugIn );
        TInt err = iPlugIns.Append( info );
        if( err != KErrNone )
            {
            ERROR_1( err, "Operation plug-in: [%x] could not be appended in array",
            		aImplInfo.ImplementationUid().iUid );
            delete plugIn;
            plugIn = NULL;
            }
        else
            {
            INFO_1( "Operation plug-in: [%x] succesfully loaded",
            		aImplInfo.ImplementationUid().iUid );
            }
        }
    else
        {
        ERROR_2( err, "Operation plug-in [%x] load error: [%d]",
        		aImplInfo.ImplementationUid().iUid, err );

        err = AddToBlackList( aImplInfo.ImplementationUid() );
        ERROR( err, "Failed to add UID to blacklist" );
        }

    HEAP_2( "After loading operation plug-in with UID [%x], version [%d]",
            aImplInfo.ImplementationUid().iUid, aImplInfo.Version() );
    }


// ---------------------------------------------------------------------------
// CCFOperationPluginManager::UpdatePlugInsL
// ---------------------------------------------------------------------------
//
void CCFOperationPluginManager::UpdatePlugInsL()
	{
    FUNC_LOG;

    // List all plugins
    RImplInfoPtrArray implInfoArray;
    CleanupResetAndDestroyPushL( implInfoArray );
    REComSession::ListImplementationsL( KOperationPlugInInterface,
        implInfoArray );
    RemoveBlackListed( implInfoArray );

    // Check if the update is install or uninstall based
    TInt allCount = implInfoArray.Count();
    TInt loadedCount = iPlugIns.Count();
    INFO_1( "Found %d operation plug-in implementations from ecom", allCount );
    INFO_1( "%d operation plug-ins currently loaded", loadedCount );

    // Check if there were plugins installed
    if( allCount >= loadedCount )
        {
        for( TInt i = iPlugIns.Count() - 1; i >= 0; i-- )
            {
            TCFOperationPluginInfo& pluginInfo = iPlugIns[i];
            for( TInt ii = 0; ii < implInfoArray.Count(); ii++ )
                {
                CImplementationInformation* implInfo = implInfoArray[ii];
                if( implInfo->ImplementationUid() == pluginInfo.iImplUid )
                    {
                    TInt oldVer = pluginInfo.iImplVersion;
                    TInt newVer = implInfo->Version();

                    // Check if the version has increased
                    if( newVer > oldVer )
                        {
                        // Remove scripts which have a dependency to the provider
                        // which is being deleted
                        TInt err = iScriptEngine.RemoveScriptByProviderUid(
                            pluginInfo.iImplUid, ETrue );
                        INFO_2( "Remove script by provider [%x] completed with code [%d]",
                            pluginInfo.iImplUid.iUid, err );

                        // Delete old plugin
                        ReleasePlugIn( pluginInfo.iPlugIn );
                        iPlugIns.Remove( i );

                        // Clean up old implementation
                        REComSession::FinalClose();

                        // Load the new version
                        TRAP( err, LoadPluginL( *implInfo ) );
                        ERROR_3( err, "Upgrade of new version of operation plugin [%x], oldVer: [%d], newVer: [%d] failed",
                            implInfo->ImplementationUid().iUid, oldVer, newVer );
                        if( err == KErrNone )
                            {
                            INFO_3( "Upgraded new version of operation plugin [%x], oldVer: [%d], newVer: [%d]",
                                implInfo->ImplementationUid().iUid, oldVer, newVer );

                            // Rollback removed scripts
                            iScriptEngine.RollbackScripts();
                            }
                        }

                    delete implInfo;
                    implInfoArray.Remove( ii );
                    break;
                    }
                }
            }

        // Check if the installed plugin was not an updgrade but a new plugin
        for( TInt i = 0; i < implInfoArray.Count(); i++ )
            {
            CImplementationInformation* implInfo = implInfoArray[i];
            TRAPD( err, LoadPluginL( *implInfo ) );
            if( err == KErrNone )
                {
                INFO_2( "Loaded operation plugin [%x], ver: [%d]",
                    implInfo->ImplementationUid().iUid, implInfo->Version() );
                }
            else
                {
                ERROR_2( err, "Failed to load operation plugin [%x], ver: [%d]",
                    implInfo->ImplementationUid().iUid, implInfo->Version() );
                }
            }
        }

    // Check if there were plugins unistalled
    else
        {
        for( TInt i = 0; i < iPlugIns.Count(); i++ )
            {
            TCFOperationPluginInfo& pluginInfo = iPlugIns[i];
            pluginInfo.iMissing = ETrue;
            }

        // Check that which plugins are missing
        for( TInt i = 0; i < implInfoArray.Count(); i++ )
            {
            CImplementationInformation* implInfo = implInfoArray[i];
            for( TInt i = 0; i < iPlugIns.Count(); i++ )
                {
                TCFOperationPluginInfo& pluginInfo = iPlugIns[i];
                if( pluginInfo.iImplUid == implInfo->ImplementationUid() )
                    {
                    pluginInfo.iMissing = EFalse;
                    break;
                    }
                }
            }

        // Delete missing plugins
        for( TInt i = iPlugIns.Count() - 1; i >= 0; i-- )
            {
            TCFOperationPluginInfo& pluginInfo = iPlugIns[i];
            if( pluginInfo.iMissing )
                {
                // Remove scripts which have a dependency to the provider
                // which is being deleted
                TInt err = iScriptEngine.RemoveScriptByProviderUid(
                    pluginInfo.iImplUid, ETrue );
                INFO_2( "Remove script by provider [%x] completed with code [%d]",
                    pluginInfo.iImplUid.iUid, err );

                // Release plug-in
                ReleasePlugIn( pluginInfo.iPlugIn );
                INFO_2( "Removed uninstalled operation plugin [%x], ver: [%d]",
                    pluginInfo.iImplUid.iUid, pluginInfo.iImplVersion );
                iPlugIns.Remove( i );

                // Clean up old implementation
                REComSession::FinalClose();

                // Rollback removed scripts since we might have uninstalled
                // plug-in which original version is in rom
                iScriptEngine.RollbackScripts();
                }
            }
        }

    // Cleanup
    CleanupStack::PopAndDestroy( &implInfoArray );
	}

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::ParseScriptRootL
// ---------------------------------------------------------------------------
//
CCFScriptRoot* CCFOperationPluginManager::ParseScriptRootL(
    CCFOperationNode* aParent,
    CMDXMLNode& aNode,
    MCFOperationServices& aOperationServices,
    TUid& aUid )
    {
    CCFScriptRoot* root = DoParseScriptRootL(
        aParent, aNode, aOperationServices, aUid );
    if ( root )
        {
        return root;
        }

    // Operation not found, check new plugins.
    UpdatePlugInsL();

    root = DoParseScriptRootL(
        aParent, aNode, aOperationServices, aUid );
    if ( root )
        {
        return root;
        }

    // Generate error info to log.

    return NULL;
    }

// ---------------------------------------------------------------------------
// CCFOperationPluginManager::ParseL
// ---------------------------------------------------------------------------
//
CCFOperationNode* CCFOperationPluginManager::ParseL( CCFOperationNode* aParent,
    CMDXMLNode& aDOMNode,
    MCFOperationServices& aOperationServices,
    TUid& aUid )
    {
    CCFOperationNode* node = DoParseL(
        aParent, aDOMNode, aOperationServices, aUid );
	if ( node )
		{
		return node;
		}

    // Operation not found, check new plugins.
    UpdatePlugInsL();

    node = DoParseL(
        aParent, aDOMNode, aOperationServices, aUid );
    if ( node )
        {
        return node;
        }

    // Generate error info to log.

    return NULL;
    }

//------------------------------------------------------------------------------
// CCFOperationPluginManager::ReleasePlugIn
//------------------------------------------------------------------------------
//
void CCFOperationPluginManager::ReleasePlugIn( CCFOperationPlugIn*& aPlugIn )
    {
    FUNC_LOG;

    delete aPlugIn;
    aPlugIn = NULL;
    }

//------------------------------------------------------------------------------
// CCFOperationPluginManager::DoParseL
//------------------------------------------------------------------------------
//
CCFOperationNode* CCFOperationPluginManager::DoParseL( CCFOperationNode* aParent,
    CMDXMLNode& aDOMNode,
    MCFOperationServices& aOperationServices,
    TUid& aUid )
    {
    FUNC_LOG;

    CCFOperationNode* node = NULL;
    for ( TInt i = 0; i < iPlugIns.Count(); i++ )
        {
        CCFOperationPlugIn* plugin = iPlugIns[ i ].iPlugIn;
        node = plugin->ParseL(
            aParent, aDOMNode, aOperationServices );
        if( node )
            {
            // Node found - break
            aUid = iPlugIns[i].iImplUid;
            break;
            }
        }

    return node;
    }

//------------------------------------------------------------------------------
// CCFOperationPluginManager::DoParseScriptRootL
//------------------------------------------------------------------------------
//
CCFScriptRoot* CCFOperationPluginManager::DoParseScriptRootL(
    CCFOperationNode* aParent,
    CMDXMLNode& aDOMNode,
    MCFOperationServices& aOperationServices,
    TUid& aUid )
    {
    FUNC_LOG;

    CCFScriptRoot* root = NULL;
    for ( TInt i = 0; i < iPlugIns.Count(); i++ )
        {
        CCFOperationPlugIn* plugin = iPlugIns[ i ].iPlugIn;
        root = plugin->ParseScriptRootL(
            aParent, aDOMNode, aOperationServices );
        if( root )
            {
            // Root found - break
            aUid = iPlugIns[i].iImplUid;
            break;
            }
        }

    return root;
    }

// End of file