diff -r 000000000000 -r a2952bb97e68 mpx/commonframework/common/src/mpxpluginhandlerbase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpx/commonframework/common/src/mpxpluginhandlerbase.cpp Thu Dec 17 08:55:47 2009 +0200 @@ -0,0 +1,1109 @@ +/* +* Copyright (c) 2006 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: Base plugin handler +* +* CMPXPluginHandlerBase instantiates and owns a CMPXPluginMonitor to monitor +* plugins for the designated plugin interface. When a plugin for that plugin +* interface is added/removed, PluginsChangedL is called. This base plugin +* handler provides a default implementation for PluginsChangedL which requests +* child class to perform plugin resolution. +* +* CMPXPluginHandlerBase also provides plugin selection plugin APIs. These +* methods set up the selection criteria and then request child class to +* resolve these selection criteria to a plugin via ResolvePluginL. +* +* +*/ + + + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "mpxpluginhandlerobserver.h" +#include "mpxpluginhandlerbase.h" + +// CONSTANTS + +// ============================ LOCAL FUNCTIONS ============================== + +// --------------------------------------------------------------------------- +// Local function to cleanup an array +// --------------------------------------------------------------------------- +// +static void CleanupPluginInfoArray( + TAny* item) + { + ((RPointerArray*)item)->ResetAndDestroy(); + ((RPointerArray*)item)->Close(); + } + +// ============================ MEMBER FUNCTIONS ============================== + +// ---------------------------------------------------------------------------- +// Constructor. +// ---------------------------------------------------------------------------- +// +EXPORT_C CMPXPluginHandlerBase::CMPXPluginHandlerBase( + TUid aInterfaceUid, + TPluginSelection aSelection, + TInt aSelectionType, + MMPXPluginHandlerObserver& aObserver, + CMPXPluginMonitor* aPluginMonitor/*=NULL*/) +: iObserver(aObserver), + iInterfaceUid(aInterfaceUid), + iPluginMonitor(aPluginMonitor), + iSelection(aSelection), + iSelectedType(aSelectionType) + { + iOwnedPluginMonitor = iPluginMonitor ? EFalse : ETrue; + } + +// ---------------------------------------------------------------------------- +// 2nd phase constructor. +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::BaseConstructL() + { + CreatePluginListL(); + if (iOwnedPluginMonitor) + { + iPluginMonitor = CMPXPluginMonitor::NewL(iInterfaceUid); + } + iPluginMonitor->AddObserverL(*this); + } + +// ---------------------------------------------------------------------------- +// Destructor. +// ---------------------------------------------------------------------------- +// +EXPORT_C CMPXPluginHandlerBase::~CMPXPluginHandlerBase() + { + if ( iPluginMonitor ) + { + TRAP_IGNORE( iPluginMonitor->RemoveObserverL( *this ) ); + } + if (iOwnedPluginMonitor) + { + delete iPluginMonitor; + } + delete iDataType; + delete iScheme; + delete iExt; + + iPluginInfoArray.ResetAndDestroy(); + } +// ---------------------------------------------------------------------------- +// Select this specific plugin +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::SelectPluginL(const TUid& aPluginUid) + { + MPX_DEBUG2("CMPXPluginHandlerBase::SelectPluginL(Uid 0x%08x)", aPluginUid.iUid); + + ClearSelectionCriteria(); + + iSelection=ESelectionUid; + iSelectedUid=aPluginUid; + + ResolvePluginL(); + MPX_DEBUG1("<--CMPXPluginHandlerBase::SelectPluginL() exits"); + } + +// ---------------------------------------------------------------------------- +// select the plugin with the specified name +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::SelectPluginL(const TDesC& aPluginName) + { + MPX_DEBUG2("CMPXPluginHandlerBase::SelectPluginL(PluginName %S)", &aPluginName); + + SelectPluginL( PluginUid( aPluginName ) ); + MPX_DEBUG1("<--CMPXPluginHandlerBase::SelectPluginL() exits"); + } + +// ---------------------------------------------------------------------------- +// Set up selection criteria, e.g. data type, extension, and scheme and then +// resolve plugin +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::SelectPluginL( + const TDesC& aUri, + const TDesC8& aDataType) + { + MPX_FUNC("CMPXPluginHandlerBase::PluginL"); + + delete iScheme; + iScheme=NULL; + delete iExt; + iExt=NULL; + delete iDataType; + iDataType=NULL; + + TPtrC fullpath; + TUriParser up; + TParse fp; + // + // Is it a valid URI, or even full path (e.g. c:\\data\test.mp3") + // + if (up.Parse(aUri)==KErrNone) + { + const TDesC& uriScheme=up.Extract(EUriScheme); + // + // Could be just drive letter if path + // which isn't really a scheme + // + if (uriScheme.Length()>1) + { + iScheme=MPXUser::Alloc8L(uriScheme); + } + else if (fp.Set(aUri,NULL,NULL)==KErrNone) // Must be a full path + { + fullpath.Set(fp.FullName()); + } + else + { + User::Leave(KErrArgument); + } + // + // Get the extension + // + iExt=MPXUser::Alloc8L(fp.Ext()); + } + if (aDataType.Length()) + { + iDataType=aDataType.AllocL(); + } + else if (fullpath.Length()) + { + RApaLsSession aps; + TInt error = aps.Connect(); // always fail in console test + if (KErrNone == error) + { + CleanupClosePushL(aps); + TDataType dataType; + TUid ignore; + if(aps.AppForDocument(fullpath,ignore,dataType)==KErrNone) + { + iDataType=dataType.Des8().AllocL(); + } + CleanupStack::PopAndDestroy(&aps); + } // else APPARC is not working in Console environment, + // Always find plugin by scheme & etension + } + else + { + if ( !iScheme ) // last valid case + { + User::Leave(KErrArgument); + } + } + + ResolvePluginL(); + } + +// ---------------------------------------------------------------------------- +// Select a plugin with the specific type +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::SelectPluginL(TInt aPluginType) + { + MPX_DEBUG2("CMPXPluginHandlerBase::SelectPluginL(PluginType %x)", aPluginType); + + ClearSelectionCriteria(); + iSelectedType=aPluginType; + ResolvePluginL(); + MPX_DEBUG1("<--CMPXPluginHandlerBase::SelectPluginL() exits"); + } + +// ---------------------------------------------------------------------------- +// select plug-in appropriate for a file +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::SelectPluginL(const RFile& aFile) + { + MPX_FUNC("CMPXPluginHandlerBase::SelectPluginL(RFile)"); + + TFileName fn; + User::LeaveIfError(aFile.FullName(fn)); + SelectPluginL(fn, KNullDesC8); + } + +// ---------------------------------------------------------------------------- +// CMPXPluginHandlerBase::UsePlugin +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::UsePlugin( + const TUid& aPluginUid) + { + MPX_FUNC_EX("CMPXPluginHandlerBase::UsePlugin"); + + TInt index(IndexOf(aPluginUid)); + if (index != KErrNotFound) + { + iPluginInfoArray[index]->ReferenceCount()++; + } + } + +// ---------------------------------------------------------------------------- +// CMPXPluginHandlerBase::ReleasePlugin +// ---------------------------------------------------------------------------- +// +EXPORT_C TBool CMPXPluginHandlerBase::ReleasePlugin( + const TUid& aPluginUid) + { + MPX_FUNC_EX("CMPXPluginHandlerBase::ReleasePlugin"); + + TBool unload(EFalse); + TInt index(IndexOf(aPluginUid)); + if (index != KErrNotFound) + { + TInt& refCount = iPluginInfoArray[index]->ReferenceCount(); + refCount--; + + if (!refCount) + { + UnloadPlugin(aPluginUid); + unload = ETrue; + } + } + + return unload; + } + +// ---------------------------------------------------------------------------- +// Get current selection criteria +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::GetSelectionCriteria( + TPluginSelection& aPluginSelection, + TInt& aPluginType, + TUid& aPluginUid, + TPtrC8& aDataType, + TPtrC8& aScheme, + TPtrC8& aExtension) + { + aPluginSelection=iSelection; + aPluginType=iSelectedType; + aPluginUid=iSelectedUid; + + aDataType.Set(*iDataType); + aScheme.Set(*iScheme); + aExtension.Set(*iExt); + } + +// ---------------------------------------------------------------------------- +// Clear current selection criteria +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::ClearSelectionCriteria() + { + iSelection=ESelectionType; + iSelectedType=0; // unknown type. this info is unknown + iSelectedUid=KNullUid; + + delete iScheme; + iScheme=NULL; + delete iExt; + iExt=NULL; + delete iDataType; + iDataType=NULL; + } + +// ---------------------------------------------------------------------------- +// Resolve a plugin, based on properties (iDataType, iExt and iScheme) +// and selection criteria. If selection is by type, then there is always a +// plug-in resolved (if there are any of that type). +// TO-DO: Room for optimisation +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::DoResolvePluginL( + TUid& aPluginUid, + TInt& aIndex, + TPtrC& aDisplayName, + TInt& aPluginType) + { + MPX_DEBUG2("===>CMPXPluginHandlerBase::DoResolvePluginL 0x%08x", this); + TInt index=KErrNotFound; + if (iSelection==ESelectionUid) + { + index=IndexOf(iSelectedUid); + } + else // if (iSelection==ESelectionType) + { + TInt score=0; + TInt maxScore=0; + + TInt count(iPluginInfoArray.Count()); + for(TInt i = 0; i < count; ++i) + { + // Must scan from beginning of plugin info array, because plugins + // sorted by priority descendingly + score=0; + + // + // First, try scheme then data type, then extension + // and total up the points + // + HBufC* hbuf = NULL; + TInt pos(0); + const CDesCArray& schemas = iPluginInfoArray[i]->SupportedSchemas(); + if (schemas.MdcaCount() && iScheme) + { + if (iScheme->Length()) + { + hbuf = MPXUser::AllocL(*iScheme); + if (!schemas.FindIsq(*hbuf, pos)) + { // schema supported by the plugin + score+=4; + } + delete hbuf; + hbuf=NULL; + } + } // else schema not supported + + if (iDataType) + { + hbuf = MPXUser::AllocL(*iDataType); + if (!iPluginInfoArray[i]->SupportedMimeTypes().FindIsq(*hbuf, pos)) + { // mime type supported by the plugin + score+=3; + } + delete hbuf; + hbuf=NULL; + } + + if (iExt) + { + hbuf = MPXUser::AllocL(*iExt); + if (!iPluginInfoArray[i]->SupportedExtensions().FindIsq(*hbuf, pos)) + { // extension supported by the plugin + score+=2; + } + delete hbuf; + hbuf=NULL; + } + + if (iSelectedType == iPluginInfoArray[i]->PluginType().iUid) + { + score+=1; // Just for being the right "type" + } + + if (score > maxScore) + { + maxScore=score; + index=i; + } + } + } + + if (index==KErrNotFound) + { + User::Leave(KErrNotSupported); + } + + // + // set return values + // + aPluginUid = iPluginInfoArray[index]->ImplementationUid(); + aIndex = index; + aDisplayName.Set(iPluginInfoArray[index]->DisplayName()); + aPluginType = iPluginInfoArray[index]->PluginType().iUid; + +#ifdef _DEBUG + PrintPluginInfo(); +#endif + + MPX_DEBUG5("<===CMPXPluginHandlerBase::DoResolvePluginL 0x%08x (aPluginUid 0x%08x, aIndex %d, aDisplayName %S)", + this, aPluginUid.iUid, aIndex, &aDisplayName); + } + +// ---------------------------------------------------------------------------- +// Handles request completion event +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::PluginsChangedL() + { + MPX_DEBUG2("===> CMPXPluginHandlerBase::PluginsChangedL 0x%08x", this); + CreatePluginListL(); + ResolvePluginL(); + MPX_DEBUG2("<=== CMPXPluginHandlerBase::PluginsChangedL 0x%08x", this); + } + +// ---------------------------------------------------------------------------- +// Handles a plugin unload request +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::HandlePluginUnload( + const TUid& aPluginUid) + { + UnloadPlugin(aPluginUid); + } + +// ---------------------------------------------------------------------------- +// Resolve a plugin +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::ResolvePluginL() + { + // Do nothing in base class + } + +// ---------------------------------------------------------------------------- +// CMPXPluginHandlerBase::IsPluginLoaded +// This method had to be made virtual (and not pure virtual) because +// the playlist engine instantiates the base class. +// ---------------------------------------------------------------------------- +// +EXPORT_C TBool CMPXPluginHandlerBase::IsPluginLoaded( + const TUid& /* aPluginUid */) + { + return EFalse; + } + +// ---------------------------------------------------------------------------- +// CMPXPluginHandlerBase::LoadPluginL +// This method had to be made virtual (and not pure virtual) because +// the playlist engine instantiates the base class. +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::LoadPluginL( + const TUid& /* aPluginUid */) + { + // do nothing + } + +// ---------------------------------------------------------------------------- +// CMPXPluginHandlerBase::UnloadPlugin +// This method had to be made virtual (and not pure virtual) because +// the playlist engine instantiates the base class. +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::UnloadPlugin( + const TUid& /* aPluginUid */) + { + // do nothing + } + +// ---------------------------------------------------------------------------- +// Return a new instance of the plugin info class +// ---------------------------------------------------------------------------- +// +EXPORT_C CMPXPluginInfo* CMPXPluginHandlerBase::ConstructPluginInfoLC( + const CImplementationInformation& aData ) + { + return CMPXPluginInfo::NewLC( aData ); + } + + +// ---------------------------------------------------------------------------- +// Return plugin name which supports the specified type +// ---------------------------------------------------------------------------- +// +EXPORT_C const TDesC& CMPXPluginHandlerBase::PluginName( + TInt aPluginType) const + { + const TDesC* name=&KNullDesC; + for ( TInt i=iPluginInfoArray.Count(); --i >= 0 ; ) + { + if ( aPluginType == iPluginInfoArray[i]->PluginType().iUid ) + { + name = &(iPluginInfoArray[i]->DisplayName()); + break; + } + } + return *name; + } + +// ---------------------------------------------------------------------------- +// Return plugin name which supports the specified uid +// ---------------------------------------------------------------------------- +// +EXPORT_C const TDesC& CMPXPluginHandlerBase::PluginName(const TUid& aUid) const + { + const TDesC* name=&KNullDesC; + TInt index(IndexOf(aUid)); + MPX_ASSERT(KErrNotFound!=index && indexDisplayName(); + return *name; + } + +// ---------------------------------------------------------------------------- +// Return a list of plugin names +// ---------------------------------------------------------------------------- +// +EXPORT_C CDesCArray* CMPXPluginHandlerBase::PluginNamesL() + { + CDesCArray* desArray = new(ELeave)CDesCArrayFlat(KMPXArrayGranularity); + CleanupStack::PushL(desArray); + for(TInt i=iPluginInfoArray.Count(); --i>=0 ;) + { + HBufC* item = iPluginInfoArray[i]->DisplayName().AllocLC(); + + //ignore leave when insert the same item + TRAP_IGNORE(desArray->InsertIsqL(*item)); + CleanupStack::PopAndDestroy(item); + } + CleanupStack::Pop(desArray); + return desArray; + } + +// ---------------------------------------------------------------------------- +// returns a list of plugin types +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::GetPluginTypes(RArray& aTypes) const + { + aTypes.Reset(); + TInt count(iPluginInfoArray.Count()); + for(TInt i=0; iPluginType().iUid); + } + } + +// ---------------------------------------------------------------------------- +// Return the list of UIDs of all plugins +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::GetPluginUids(RArray& aUids) const + { + aUids.Reset(); + TInt count(iPluginInfoArray.Count()); + for(TInt i=0; iImplementationUid()); + } + } + +// ---------------------------------------------------------------------------- +// Get plugin list with the specific type +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::GetPluginUidsL( + RArray& aPlugins, + TInt aPluginType) const + { + aPlugins.Reset(); + for(TInt i=iPluginInfoArray.Count(); --i>=0 ;) + { + if (aPluginType == iPluginInfoArray[i]->PluginType().iUid) + { + aPlugins.Append(iPluginInfoArray[i]->ImplementationUid()); + } + } + } + +// ---------------------------------------------------------------------------- +// Get plugin UID with the specified display name +// ---------------------------------------------------------------------------- +// +EXPORT_C TUid CMPXPluginHandlerBase::PluginUid(const TDesC& aPluginName) const + { + TUid uid( KNullUid ); + + for(TInt i=iPluginInfoArray.Count();--i>=0;) + { + if ( aPluginName.Compare(iPluginInfoArray[i]->DisplayName()) == 0 ) + { + uid = iPluginInfoArray[i]->ImplementationUid(); + break; + } + } + + return uid; + } + +// ---------------------------------------------------------------------------- +// returns the index of the specified plugin +// ---------------------------------------------------------------------------- +// +EXPORT_C TInt CMPXPluginHandlerBase::IndexOf(const TUid& aPluginUid) const + { + TInt ret(KErrNotFound); + TInt count(iPluginInfoArray.Count()); + for(TInt i=0; iImplementationUid()==aPluginUid) + { + ret = i; + break; + } + } + return ret; + } + +// ---------------------------------------------------------------------------- +// Return a list of mime types supported by the plugins +// ---------------------------------------------------------------------------- +// +EXPORT_C CDesCArray* CMPXPluginHandlerBase::SupportedMimeTypesL() + { + CDesCArray* descArray = new(ELeave)CDesCArrayFlat(KMPXArrayGranularity); + for(TInt i=iPluginInfoArray.Count();--i>=0;) + { + if( iPluginInfoArray[i] ) + { + MPXUser::MergeArray(iPluginInfoArray[i]->SupportedMimeTypes(), + *descArray); + } + } + return descArray; + } + +// ---------------------------------------------------------------------------- +// Return a list of extensions supported by the plugins +// ---------------------------------------------------------------------------- +// +EXPORT_C CDesCArray* CMPXPluginHandlerBase::SupportedExtensionsL() + { + CDesCArray* descArray = new(ELeave)CDesCArrayFlat(KMPXArrayGranularity); + for(TInt i=iPluginInfoArray.Count();--i>=0;) + { + MPXUser::MergeArray(iPluginInfoArray[i]->SupportedExtensions(), + *descArray); + } + return descArray; + } + +// ---------------------------------------------------------------------------- +// Get plugin type for a given implementation UID +// ---------------------------------------------------------------------------- +// +EXPORT_C TUid CMPXPluginHandlerBase::PluginType( const TUid& aUid ) const + { + TUid ret( KNullUid ); + TInt count( iPluginInfoArray.Count() ); + for( TInt i = 0; i < count; ++i ) + { + if ( iPluginInfoArray[i]->ImplementationUid() == aUid ) + { + ret = iPluginInfoArray[i]->PluginType(); + break; + } + } + return ret; + } + +// ---------------------------------------------------------------------------- +// Get supported app uid for a given implementation UID +// ---------------------------------------------------------------------------- +// +EXPORT_C TUid CMPXPluginHandlerBase::SupportedAppUid( const TUid& aUid ) const + { + TUid ret( KNullUid ); + TInt count( iPluginInfoArray.Count() ); + for( TInt i = 0; i < count; ++i ) + { + if ( iPluginInfoArray[i]->ImplementationUid() == aUid ) + { + ret = iPluginInfoArray[i]->SupportedAppUid(); + MPX_DEBUG2("SupportedAppUid = %d", ret); + break; + } + } + return ret; + } + +// ---------------------------------------------------------------------------- +// Get plugin type for a given implementation UID +// ---------------------------------------------------------------------------- +// +EXPORT_C TUint CMPXPluginHandlerBase::PluginFlagsL( const TUid& aUid ) const + { + TUint ret( 0 ); + TInt count( iPluginInfoArray.Count() ); + TBool found( EFalse ); + for( TInt i = 0; !found && i < count; ++i ) + { + if ( iPluginInfoArray[i]->ImplementationUid() == aUid ) + { + ret = iPluginInfoArray[i]->Flags(); + found = ETrue; + } + } + if ( !found ) + { + User::Leave( KErrNotFound ); + } + return ret; + } + +// ---------------------------------------------------------------------------- +// Return a list of schemas supported by the plugins +// ---------------------------------------------------------------------------- +// +EXPORT_C CDesCArray* CMPXPluginHandlerBase::SupportedSchemasL() + { + CDesCArray* descArray = new(ELeave)CDesCArrayFlat(KMPXArrayGranularity); + for(TInt i=iPluginInfoArray.Count();--i>=0;) + { + MPXUser::MergeArray(iPluginInfoArray[i]->SupportedSchemas(), + *descArray); + } + return descArray; + } + +// ---------------------------------------------------------------------------- +// Return a list of mime types supported by the plugins +// ---------------------------------------------------------------------------- +// +EXPORT_C CDesCArray* CMPXPluginHandlerBase::SupportedMimeTypesL(const TUid& aUid) + { + CDesCArray* descArray = new(ELeave)CDesCArrayFlat(KMPXArrayGranularity); + CleanupStack::PushL(descArray); + for(TInt i=iPluginInfoArray.Count();--i>=0;) + { + if (aUid == iPluginInfoArray[i]->ImplementationUid()) + { + MPXUser::CopyArrayL(iPluginInfoArray[i]->SupportedMimeTypes(), + *descArray); + break; + } + } + CleanupStack::Pop(descArray); + return descArray; + } + +// ---------------------------------------------------------------------------- +// Return a list of extensions supported by the plugins +// ---------------------------------------------------------------------------- +// +EXPORT_C CDesCArray* CMPXPluginHandlerBase::SupportedExtensionsL(const TUid& aUid) + { + CDesCArray* descArray = new(ELeave)CDesCArrayFlat(KMPXArrayGranularity); + CleanupStack::PushL(descArray); + for(TInt i=iPluginInfoArray.Count();--i>=0;) + { + if (aUid == iPluginInfoArray[i]->ImplementationUid()) + { + MPXUser::CopyArrayL(iPluginInfoArray[i]->SupportedExtensions(), + *descArray); + break; + } + } + CleanupStack::Pop(descArray); + return descArray; + } + +// ---------------------------------------------------------------------------- +// Recreates the list of plugins. Handles the scenarios of plugin update, +// addition and removal by comparing the previous list with the current one. +// In case any change is detected to the plugin list the observer interface is +// used to notify the owner. +// +// NOTE: ECOM takes care of versioning for us. When two plugins that implement +// the same interface and have the same implementation UID are detected, it loads +// the one with the higher version. There is no way to have two implementations +// of the same interface that share the implementation UID returned by +// REComSession::ListImplementationsL. +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::CreatePluginListL() + { + MPX_DEBUG_THREAD("CMPXPluginHandlerBase::CreatePluginListL"); + // Get the current list of plugins that implement the interface + // The ECOM versioning mechanism is appied here. + // Auto destroy array, no need to call ResetAndDestroy and Close + RMPXPointerArray implInfoArray; + REComSession::ListImplementationsL(iInterfaceUid, implInfoArray); + + // Temporary array to store the new plugin infos. + RPointerArray tempInfoArray; + CleanupStack::PushL(TCleanupItem(CleanupPluginInfoArray, &tempInfoArray)); + + // Reused variables + CMPXPluginInfo* prevInfo(NULL); + TBool loaded(EFalse); + + // Iterate the new plugins + // It is expected that when the loop ends the temporary array will contain + // all current plugins and iPluginInfoArray will contain the plugins that + // have been removed + TInt count(implInfoArray.Count()); + MPX_DEBUG3("CMPXPluginHandlerBase::CreatePluginListL numbers of the plugin 0x%08x %d", + this, count); + TInt index(0); + CMPXPluginInfo* info(NULL); + for (; index < count; ++index) + { + // Convert to an internal plugin info instance + info = ConstructPluginInfoLC(*implInfoArray[index]); + const TUid& uid = info->ImplementationUid(); + + // Check if the plugin existed in the previous list + TInt prevIndex = IndexOf(uid); + if (prevIndex != KErrNotFound) + { + // The plugin existed before the update + prevInfo = iPluginInfoArray[prevIndex]; + MPX_DEBUG5("Process the existing plugin 0x%08x uid 0x%08x, old version %d new version %d", + this, uid.iUid, prevInfo->Version(), info->Version()); + // Copy the reference count + info->ReferenceCount() = prevInfo->ReferenceCount(); + + // Compare the versions + if (prevInfo->Version() < info->Version()) + { + // The plugin is being upgraded + loaded = IsPluginLoaded(uid); + + // Generate an update start notification + iObserver.HandlePluginHandlerEvent( + MMPXPluginHandlerObserver::EPluginUpdateStart, uid, loaded, + info->Version()); + + // Check if this plugin was loaded. The plugin is still loaded if this is the first + // handler that got notified or it is already unloaded for any otehr handlers. + if (info->ReferenceCount()) + { + if (loaded) + { + // Unload the old plugin version + MPX_DEBUG2("CMPXPluginHandlerBase::CreatePluginListL unload old plugin 0x%08x", this); + + // The plugin is loaded - ask the monitor to tell all + // handler instances (including this one) to unload it. + // After the call below all plugin instances owned by + // all monitors are unloaded. + // + // Only make this call if the plugin is still loaded, + // i.e. from the first handler that detects the update. + iPluginMonitor->NotifyUnload(uid); + + // Necessary to ensure version upgrade of ECom plugins + // is successful. This call will unload any garbage + // plugins. + REComSession::FinalClose(); + } + + MPX_DEBUG2("CMPXPluginHandlerBase::CreatePluginListL load new plugin 0x%08x", this); + // Load the new plugin version + LoadPluginL(uid); + MPX_DEBUG2("CMPXPluginHandlerBase::CreatePluginListL load new plugin finished 0x%08x", this); + } + + // Generate an update end notification + iObserver.HandlePluginHandlerEvent( + MMPXPluginHandlerObserver::EPluginUpdateEnd, uid, loaded, + info->Version()); + } + + // Delete the entry from the info array + iPluginInfoArray.Remove(prevIndex); + delete prevInfo; + prevInfo = NULL; + } + else + { + MPX_DEBUG2("CMPXPluginHandlerBase::CreatePluginListL found new plugin 0x%08x", this); + // A new plugin is being added + iObserver.HandlePluginHandlerEvent( + MMPXPluginHandlerObserver::EPluginAdd, uid, EFalse, info->Version()); + } + + // Insert into the temporary array - order by priority, high priority first + tempInfoArray.InsertInOrderAllowRepeatsL(info, + CMPXPluginInfo::ComparePluginInfoByPriority); + + CleanupStack::Pop(info); + } + + // What is left in iPluginInfoArray are removed plugins + while (iPluginInfoArray.Count()) + { + prevInfo = iPluginInfoArray[0]; + const TUid& uid = prevInfo->ImplementationUid(); + + loaded = IsPluginLoaded(uid); + MPX_DEBUG3("CMPXPluginHandlerBase::CreatePluginListL plugin removed 0x%08x uid 0x%08x", + this, uid.iUid); + // Generate an remove notification + iObserver.HandlePluginHandlerEvent( + MMPXPluginHandlerObserver::EPluginRemove, uid, loaded, + prevInfo->Version()); + + // Check if the plugin is currently loaded + if (loaded) + { + // Unload the plugin + UnloadPlugin(uid); + } + + iPluginInfoArray.Remove(0); + delete prevInfo; + prevInfo = NULL; + } + + // iPluginInfoArray should be empty and the temp array should contain all new plugins + // Copy the pointers to iPluginInfoArray - the ownership is transferred + for (index = 0; index < count; ++index) + { + info = tempInfoArray[0]; + iPluginInfoArray.AppendL(info); + tempInfoArray.Remove(0); + // check if this plugin should be pre-loaded and not loaded yet + if (info->Flags() & EMPXPluginFlagPreLoad && info->ReferenceCount() == 0) + { + // pre-load the plugin - have to go through SelectPluginL + // to apply the reference counting consistently + TRAP_IGNORE(SelectPluginL(info->ImplementationUid())); + } + } + + // Reset the temp array - this does not delete the plugin info instances pointed to + // from the array - these were copied to iPluginInfoArray + CleanupStack::Pop(); // TCleanupItem(CleanupPluginInfoArray, &tempInfoArray) + tempInfoArray.Close(); + } + +// ---------------------------------------------------------------------------- +// CMPXPluginHandlerBase::SupportUids +// ---------------------------------------------------------------------------- +// +EXPORT_C TBool CMPXPluginHandlerBase::SupportUids( + const TUid& aPluginId, + const TArray& aUids) const + { + TInt index(IndexOf(aPluginId)); + MPX_ASSERT(index!=KErrNotFound && index < iPluginInfoArray.Count()); + return iPluginInfoArray[index]->SupportUids(aUids); + } + +// ---------------------------------------------------------------------------- +// Search a plugin by matching implementation id, supported id and plugin type +// If two plugins get the same score, high priority plugin's implementation +// uid will be returned +// ---------------------------------------------------------------------------- +// +EXPORT_C TUid CMPXPluginHandlerBase::FindPlugin(const TArray& aUids) const + { + MPX_DEBUG1("#### MPX Plugins ####"); + TInt count(iPluginInfoArray.Count()); + for (TInt index = 0; index < count; ++index) + { + CMPXPluginInfo* info = iPluginInfoArray[index]; + const TDesC& name = info->DisplayName(); + MPX_DEBUG5("%S [0x%08X] Priority: %d Ref Count: %d", &name, info->ImplementationUid(), + info->Priority(), info->ReferenceCount()); + MPX_DEBUG2("Version %d", info->Version()); + } + + TInt lastScore( 0 ); + CMPXPluginInfo* mostPossiblePluginInfo( NULL ); + TUid uid = TUid::Null(); + + // Find the most suitable plugin + for ( TInt i = iPluginInfoArray.Count(); --i >= 0; ) + { + TInt score( 0 ); + CMPXPluginInfo* info = iPluginInfoArray[i]; + const TArray supportedUids = info->SupportedUids(); + + for ( TInt j = aUids.Count(); --j >= 0; ) + { + for (TInt k=supportedUids.Count(); --k >=0;) + { + if ( aUids[j] == supportedUids[k] ) + { + // Five scores if in the supported uids list. + score += 5; + + // We now allow a UID to be repeated multiple times + // for emphasized scoring. + //break; + } + } + if (info->ImplementationUid() == aUids[j]) + { + score += 100; + } + if ( info->PluginType() == aUids[j]) + { // One more if match plugin type + score++; + } + } + + if ( score ) + { + if ( lastScore < score ) + { + lastScore = score; + mostPossiblePluginInfo = info; + } + else if ( lastScore == score ) + { + // Use priority to determine if scores are the same + // If same priorities are detected, the first found plugin + // will be used. + if (mostPossiblePluginInfo->Priority() < info->Priority()) + { + mostPossiblePluginInfo = info; + } + } // else do nothing + } + } + if (mostPossiblePluginInfo) + { + uid = mostPossiblePluginInfo->ImplementationUid(); + } + return uid; + } + +#ifdef _DEBUG + +// ---------------------------------------------------------------------------- +// CMPXPluginHandlerBase::PrintPluginInfo +// ---------------------------------------------------------------------------- +// +void CMPXPluginHandlerBase::PrintPluginInfo() + { + MPX_DEBUG1("#### MPX Plugins ####"); + + TInt count(iPluginInfoArray.Count()); + for (TInt index = 0; index < count; ++index) + { + CMPXPluginInfo* info = iPluginInfoArray[index]; + const TDesC& name = info->DisplayName(); + MPX_DEBUG5("%S [0x%08X] Priority: %d Ref Count: %d", &name, info->ImplementationUid(), + info->Priority(), info->ReferenceCount()); + MPX_DEBUG2("Version %d", info->Version()); + } + } + +#endif + +#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API +// ---------------------------------------------------------------------------- +// select plug-in appropriate for a file +// ---------------------------------------------------------------------------- +// +EXPORT_C void CMPXPluginHandlerBase::SelectPlugin64L(const RFile64& aFile) + { + MPX_FUNC("CMPXPluginHandlerBase::SelectPlugin64L(RFile64)"); + + TFileName fn; + User::LeaveIfError(aFile.FullName(fn)); + SelectPluginL(fn, KNullDesC8); + } +#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API + +// End of file