diff -r 000000000000 -r 5752a19fdefe imaging/imagingfws/resolver/ImageConversionResolver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imaging/imagingfws/resolver/ImageConversionResolver.cpp Wed Aug 25 12:29:52 2010 +0300 @@ -0,0 +1,586 @@ +// Copyright (c) 1997-2009 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: +// + + +#include +#include +#include + +#include "ImageConversionResolver.h" +#include "ImageConvResolvrUtils.h" + +_LIT(KIclResolverPanicCategory, "ImageConversionResolver"); + +//Current version of plugin framework. +//Plugin will be ignored if the version from opaque data doesn't +//match the current framework version. +//const TInt KPluginFrameworkVersion = 0; + +GLDEF_C void Panic(TInt aReason) + { + User::Panic(KIclResolverPanicCategory, aReason); + } + +/** + * Constructs and initialises a new instance of CImageConversionResolver. + * + * @param "MPublicRegistry& aRegistry" + * A reference to the registry on which it will operate + * @return "CImageConversionResolver*" + * A pointer to the newly constructed resolver + */ +CImageConversionResolver* CImageConversionResolver::NewL(MPublicRegistry& aRegistry) + { + return new(ELeave) CImageConversionResolver(aRegistry); + } + +/** + * + * Default destructor + * + */ +CImageConversionResolver::~CImageConversionResolver() + { + } + +/** + * + * Default constructor + * + * @param "MPublicRegistry& aRegistry" + * A reference to the registry on which it will operate + */ +CImageConversionResolver::CImageConversionResolver(MPublicRegistry& aRegistry) + : CResolver(aRegistry) + { + } + +/** + * + * Request that the resolver identify the most appropriate interface + * implementation. + * + * @param "TUid aInterfaceUid" + * The Uid of the interface you want to match against + * @param "const TEComResolverParams& aAdditionalParameters" + * A passed in reference to the parameters on which to match + * @return "TUid" + * The implementation Uid of the single best match found + */ +TUid CImageConversionResolver::IdentifyImplementationL(TUid aInterfaceUid, const TEComResolverParams& aAdditionalParameters) const + { + RImplInfoArray& implementationsInfo = iRegistry.ListImplementationsL(aInterfaceUid); + TUid found = KNullUid; + if (implementationsInfo.Count()) + found = ResolveL(implementationsInfo, aAdditionalParameters); + + return found; + } + +/** + * + * Called by IdentifyImplementationL to select an implementation from the + * supplied implementation uid, ignoring any implementations that have their + * Disabled flag set or are not of the current framework version. + * The image type and sub type is verified to ensure the implementation is of + * expected type. + * + * @param "const RImplInfoArray& aImplementationsInfo" + * The list of plugins you want to match against + * @param "const TEComResolverParams& aAdditionalParameters" + * A passed in reference to the parameters on which to match + * @return "TUid" + * The implementation Uid of plugin + */ +TUid CImageConversionResolver::ResolveL(const RImplInfoArray& aImplementationsInfo, const TEComResolverParams& aAdditionalParameters) const + { + // Retrieve the match data from the descriptor + CCustomMatchData* customMatch = CCustomMatchData::NewLC(aAdditionalParameters.DataType()); + + TResolverMatchType matchType = customMatch->MatchType(); + TUint requiredExtensions = customMatch->ExtensionOptions(); + TUint requiredOptions = customMatch->Options(); + TUid baseType = customMatch->BaseType(); + TUid subType = customMatch->SubType(); + TUid implementationUid = customMatch->ImplementationType(); + + RUidDataArray requiredOptionsUids; + if (requiredOptions) + { + CleanupClosePushL(requiredOptionsUids); + customMatch->GetOptionsUidsL(requiredOptionsUids); + } + + // Select plugin on implementation uid + if((matchType != EMatchUids) || (implementationUid == KNullUid)) + User::Leave(KErrArgument); + + TUid bestMatch = KNullUid; + TInt version = 0; + TBool requiredOptionsFound = EFalse; + + // Loop through the implementations searching for the implementation uid + const TInt count = aImplementationsInfo.Count(); + for(TInt index = 0; index < count; index++) + { + const CImplementationInformation& impData = *aImplementationsInfo[index]; + COpaqueDataParse* parse = NULL; + TRAPD(error, parse = COpaqueDataParse::NewL(impData.OpaqueData())); + if (error!=KErrNone) + { + if (error==KErrNotSupported) + { + // means that the resource entry was not valid + continue; + } + else + User::Leave(error); + } + + CleanupStack::PushL(parse); + + // we can assume the version is valid as it is checked in + // COpaqueDataParse::ConstructL() which leaves if not valid + ASSERT(parse->Version() <= KIclPluginFrameworkVersionMax); + + if (!impData.Disabled()) + { + if (implementationUid == impData.ImplementationUid()) + { // Got a match + // Moved here to optimize iteration through implementations + // Check if extension options are required. + if (requiredExtensions) + { + if (!parse->SupportsExtensionsL(requiredExtensions)) + { + CleanupStack::PopAndDestroy(parse); + continue; + } + } + + if ((baseType == parse->ImageTypeUid()) && (subType == parse->ImageSubTypeUid())) + {// ImageType and SubType match + if (requiredOptions) + { + parse->EnsureBinaryPropertiesReadL(); + if(parse->CheckOptionsUids(requiredOptionsUids)) + { + if (!requiredOptionsFound) + { + bestMatch = impData.ImplementationUid(); + version = impData.Version(); + requiredOptionsFound = ETrue; + CleanupStack::PopAndDestroy(parse); + continue; + } + } + else + { + if (requiredOptionsFound) + { + CleanupStack::PopAndDestroy(parse); + continue; + } + } + } + + if (version < impData.Version()) + { // Higher version match + bestMatch = impData.ImplementationUid(); + version = impData.Version(); + } + } + } + } + CleanupStack::PopAndDestroy(parse); + } + + if (requiredOptions) + { + CleanupStack::PopAndDestroy();//requiredOptionsUids + } + CleanupStack::PopAndDestroy(customMatch); + + return bestMatch; + } + +/* + * + * List all the implementations which satisfy the specified interface, ignoring + * any implementations that have their Disabled flag set or are not of the + * current framework version. + * + * The list is sorted: + * 1) For EMatchString in desending order of number of bytes matched and version number. + * 2) For EMatchMIMEType in asending order of the MIME position that matched and + * desending version number. + * 3) All others - desending version numbers. + * + * @param "TUid aInterfaceUid" + * The Uid of the interface you want to match against + * @param "const TEComResolverParams& aAdditionalParameters" + * A passed in reference to the parameters on which to match + * @return "RImplInfoArray*" + * The list of matches found + */ + RImplInfoArray* CImageConversionResolver::ListAllL(TUid aInterfaceUid, const TEComResolverParams& aAdditionalParameters) const + { + // Retrieve the match data from the descriptor + CCustomMatchData* customMatch = CCustomMatchData::NewLC(aAdditionalParameters.DataType()); + + TResolverMatchType matchType = customMatch->MatchType(); + TUint requiredExtensions = customMatch->ExtensionOptions(); + TUint requiredOptions = customMatch->Options(); + TUid baseType = customMatch->BaseType(); + TUid subType = customMatch->SubType(); + TUid implementationUid = customMatch->ImplementationType(); + HBufC8* matchString = customMatch->MatchString().AllocLC(); + HBufC* fileSuffix = customMatch->FileSuffix().AllocLC(); + + RUidDataArray requiredUids; + CleanupClosePushL(requiredUids); + customMatch->GetMatchReqUidsL(requiredUids); + + RUidDataArray requiredOptionsUids; + CleanupClosePushL(requiredOptionsUids); + customMatch->GetOptionsUidsL(requiredOptionsUids); + + // Use the member var to create the array so that we get proper cleanup behaviour + RImplInfoArray& fullList = iRegistry.ListImplementationsL(aInterfaceUid); + + RArray sortList; + CleanupClosePushL(sortList); + + TInt matchLevel = 0; + TInt optionsMatchLevel = 0; + + // Loop through the implementations matching on appropriate info + const TInt count = fullList.Count(); + TInt index; + + for(index = 0; index < count; index++) + { + const CImplementationInformation& impData = *(fullList[index]); + COpaqueDataParse* parse = NULL; + TRAPD(error, parse = COpaqueDataParse::NewL(impData.OpaqueData())); + if (error!=KErrNone) + { + if (error==KErrNotSupported) + { + // means that the resource entry was not valid + continue; + } + else + User::Leave(error); + } + + CleanupStack::PushL(parse); + + // we can assume the version is valid as it is checked in + // COpaqueDataParse::ConstructL() which leaves if not valid + ASSERT(parse->Version() <= KIclPluginFrameworkVersionMax); + + if (!impData.Disabled()) + { + + TBool matchFound = EFalse; + switch(matchType) + { + case EListImageTypes: + { + if (baseType == KNullUid) + { // Looking for base image types + if (parse->ImageSubTypeUid() == KNullUid) + matchFound = ETrue; + } + else + { // Looking for sub-types of a particular base image type + if ((baseType == parse->ImageTypeUid()) && (parse->ImageSubTypeUid() != KNullUid)) + matchFound = ETrue; + } + break; + } + + case EListFileTypes: + { // Looking for entries with file extensions and/or MIME types + if(!parse->OnlyUidsAvail() && !parse->IsSubCodec()) + matchFound = ETrue; + break; + } + + case EMatchMIMEType: + { + if(!parse->OnlyUidsAvail() && !parse->IsSubCodec()) + { //If codec has no MIME types ignore it + parse->EnsureMIMETypesReadL(); + const TInt numMimeTypes = parse->MIMETypesCount(); + for (TInt index2 = 0; index2 < numMimeTypes; index2++) + { + const TDesC8& mimeType = parse->MIMEType(index2); + if (COpaqueDataParse::CompareMIMETypes(*matchString, mimeType)) + { + matchFound = ETrue; + matchLevel = index2; + break; + } + } + } + + break; + } + + case EMatchString: + { // Match the match strings + if (CImageConversionResolverUtils::Match(*matchString, impData.DataType(), matchLevel)) + matchFound = ETrue; + break; + } + + case EMatchUids: + { // match on UIDs + if (implementationUid != KNullUid) + {// We're matching on codec implementation uid + if (implementationUid == impData.ImplementationUid()) + { + matchFound = ETrue; + } + else + { + matchFound = (implementationUid == parse->PluginClassUid()); + } + } + else + { // We're matching on image type (and sub-type) + if (parse->CompareUids(baseType, subType)) + matchFound = ETrue; + } + break; + } + + case EMatchFileSuffix: + { + if(!parse->OnlyUidsAvail() && parse->IsOpenAgainstSuffix()) + { //If codec has file extensions and allow matching on them + parse->EnsureExtnsReadL(); + const TInt numExtns = parse->ExtnsCount(); + for (TInt index2 = 0; index2 < numExtns; index2++) + { + const TDesC8& extn = parse->Extn(index2); + if (COpaqueDataParse::CompareFileSuffixL(*fileSuffix, extn)) + { + matchFound = ETrue; + matchLevel = index2; + break; + } + } + } + + break; + } + + case EMatchReqUids: + { + if(!parse->OnlyUidsAvail()) + { + parse->EnsureBinaryPropertiesReadL(); + if(parse->CheckRequiredUids(requiredUids)) + { + matchFound = ETrue; + if(parse->IsDefaultCodec()) + { + matchLevel = 1; + } + else + { + matchLevel = 0; + } + } + } + break; + } + + default: + {//unknown match type + Panic(KErrArgument); + } + } + + if (matchFound) + { + // Moved here to reduce timing required to list all codecs plugins. + // Check if certain extensions are required. + if (requiredExtensions) + { + if (!parse->SupportsExtensionsL(requiredExtensions)) + { + CleanupStack::PopAndDestroy(parse); + continue; + } + } + + // Check if certain options are required + if(requiredOptions) + { + optionsMatchLevel = 0; + parse->EnsureBinaryPropertiesReadL(); + if(parse->CheckOptionsUids(requiredOptionsUids)) + { + optionsMatchLevel = 1;// one for having required options + if(parse->IsDefaultCodec()) + { + optionsMatchLevel = 2; // two for being default codec and having required options + } + } + } + + TSortImplInfo sortInfo(fullList[index],matchLevel,optionsMatchLevel); + User::LeaveIfError(sortList.Append(sortInfo)); + } + } + CleanupStack::PopAndDestroy(parse); + } + + TLinearOrder* sortFunction = NULL; + if(matchType==EMatchMIMEType) + sortFunction = new (ELeave) TLinearOrder(SortAsending); + else + sortFunction = new (ELeave) TLinearOrder(SortDesending); + + sortList.Sort(*sortFunction); + delete sortFunction; + + RImplInfoArray* retList = new (ELeave) RImplInfoArray; + CleanupStack::PushL(retList); + // coverity[double_push] + CleanupClosePushL(*retList); // note the double PushL - will Close and delete on PopAndDestroy(2) + + TInt noEntries = sortList.Count(); + for(index = 0; index < noEntries; index++) + User::LeaveIfError(retList->Append(sortList[index].iImplInfo)); + + if ((matchType == EMatchString) && (noEntries > 1)) + { + // check that there is no ambiguity due to a short match string + TBool matchStringIsTooShort = EFalse; + for (TInt i = 0; i < noEntries; i++) + { + const CImplementationInformation& implementationInfo = *((*retList)[i]); + TInt implementationStringLength = implementationInfo.DataType().Length(); + while ((implementationStringLength > 0) && (implementationInfo.DataType()[implementationStringLength - 1] == '?')) + { // Clip extraneous '?' wildcards off the end of the plugin match string + implementationStringLength--; + } + if (matchString->Length() < implementationStringLength) + { + matchStringIsTooShort = ETrue; + break; + } + } + + if (matchStringIsTooShort) + { + User::Leave(KErrUnderflow); + } + } + + + + CleanupStack::Pop(2, retList); // retList x2 + + CleanupStack::PopAndDestroy(6, customMatch); // sortList, requiredOptionsUids, requiredUids, fileSuffix, matchString, customMatch + + return retList; + } + +/** + * Function to sort an array of TSortImplInfo in asending order of the match level, options match level and + * then in desending order of version numbers. + * + * @param "const TSortImplInfo& aImpInfo1" + * First element. + * @param "const TSortImplInfo& aImpInfo2" + * Second element. + * @return "TInt" + * Indication of element swapping order. + */ +TInt CImageConversionResolver::SortAsending(const TSortImplInfo& aImpInfo1, const TSortImplInfo& aImpInfo2) + { + TInt result = aImpInfo1.iMatchLevel - aImpInfo2.iMatchLevel; + + if(result == 0) + result = aImpInfo1.iOptionsMatchLevel - aImpInfo2.iOptionsMatchLevel; + + if(result == 0) + result = aImpInfo2.iImplInfo->Version() - aImpInfo1.iImplInfo->Version(); + + return result; + } + +/** + * Function to sort an array of TSortImplInfo in desending order of the match level, options match level + * and version numbers. + * + * @param "const TSortImplInfo& aImpInfo1" + * First element. + * @param "const TSortImplInfo& aImpInfo2" + * Second element. + * @return "TInt" + * Indication of element swapping order. + */ +TInt CImageConversionResolver::SortDesending(const TSortImplInfo& aImpInfo1, const TSortImplInfo& aImpInfo2) + { + TInt result = aImpInfo2.iMatchLevel - aImpInfo1.iMatchLevel; + + if(result == 0) + result = aImpInfo2.iOptionsMatchLevel - aImpInfo1.iOptionsMatchLevel; + + if(result == 0) + result = aImpInfo2.iImplInfo->Version() - aImpInfo1.iImplInfo->Version(); + + return result; + } + +/** + * Construtor for the TSortImplInfo class + * + * @param "CImplementationInformation *const aImplInfo" + * A implementation information element to be sorted. + * @param "TInt aMatchLevel" + * The matching level of the entry + */ +TSortImplInfo::TSortImplInfo(CImplementationInformation *const aImplInfo, TInt aMatchLevel): + iImplInfo(aImplInfo), + iMatchLevel(aMatchLevel), + iOptionsMatchLevel(0) + { + } + +/** + * Construtor for the TSortImplInfo class + * + * @param "CImplementationInformation *const aImplInfo" + * A implementation information element to be sorted. + * @param "TInt aMatchLevel" + * The matching level of the entry + * @param "TInt aOptionsMatchLevel" + * The options matching level of the entry + */ +TSortImplInfo::TSortImplInfo(CImplementationInformation *const aImplInfo, TInt aMatchLevel, TInt aOptionsMatchLevel): + iImplInfo(aImplInfo), + iMatchLevel(aMatchLevel), + iOptionsMatchLevel(aOptionsMatchLevel) + { + } +