sl@0: /* sl@0: * Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include sl@0: #include sl@0: sl@0: #include "resolver.h" sl@0: #include sl@0: #include sl@0: #include "agentinfo.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: using namespace ContentAccess; sl@0: sl@0: // Constants for the F32 agent sl@0: _LIT(KF32Agent,"F32 CA Agent"); sl@0: sl@0: sl@0: _LIT(KParentDir, "..\\"); sl@0: _LIT(KPrivateDir, "\\private\\"); sl@0: const TInt KPrivateDirLength = 9; // "\\private\\" sl@0: const TInt KPrivateDirAndDriveLength = 11; // "x:\\private\\" sl@0: const TInt KPrivateDirOffset = 2; // "x:\\" sl@0: sl@0: sl@0: EXPORT_C CAgentResolver* CAgentResolver::NewLC(const TBool aDynamicAgentUpdate) sl@0: { sl@0: CAgentResolver* self = new (ELeave) CAgentResolver(aDynamicAgentUpdate); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CAgentResolver* CAgentResolver::NewL(const TBool aDynamicAgentUpdate) sl@0: { sl@0: CAgentResolver* self = CAgentResolver::NewLC(aDynamicAgentUpdate); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CAgentResolver::CAgentResolver(const TBool aDynamicAgentUpdate) : CActive(EPriorityStandard), iDynamicAgentUpdate(aDynamicAgentUpdate) sl@0: { sl@0: } sl@0: sl@0: CAgentResolver::~CAgentResolver() sl@0: { sl@0: // remove ourselves from the ActiveScheduler sl@0: if(IsAdded()) sl@0: { sl@0: Deque(); sl@0: } sl@0: sl@0: // Unload all the agents sl@0: DestroyListOfAgents(); sl@0: sl@0: // Close our ECOM session sl@0: if(iEcomSession) sl@0: { sl@0: if(iDynamicAgentUpdate) sl@0: { sl@0: iEcomSession->CancelNotifyOnChange(iStatus); sl@0: } sl@0: iEcomSession->Close(); sl@0: REComSession::FinalClose(); sl@0: } sl@0: sl@0: iSupplierMimeTypes.Close(); sl@0: iConsumerMimeTypes.Close(); sl@0: iAgentInfos.Close(); sl@0: } sl@0: sl@0: void CAgentResolver::ConstructL() sl@0: { sl@0: if(iDynamicAgentUpdate) sl@0: { sl@0: // Add ourselves to the current active scheduler so we can get dynamic sl@0: // updates when agents are removed or new agents are added sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: iEcomSession = &REComSession::OpenL(); sl@0: sl@0: // find all the agents sl@0: BuildListOfAgentsL(); sl@0: sl@0: if(iDynamicAgentUpdate) sl@0: { sl@0: // register for ECOM update notifications in case a new agent appears sl@0: SetActive(); sl@0: iEcomSession->NotifyOnChange(iStatus); sl@0: } sl@0: } sl@0: sl@0: void CAgentResolver::BuildListOfAgentsL() sl@0: { sl@0: TInt err = KErrNone; sl@0: sl@0: // Get all plugins which implement the agent interface sl@0: RImplInfoPtrArray implArray; sl@0: CleanupStack::PushL(TCleanupItem(CleanImplArray, &implArray)); sl@0: REComSession::ListImplementationsL(KCAAgentInterfaceUid, implArray); sl@0: sl@0: for (TInt i = 0; i < implArray.Count(); ++i) sl@0: { sl@0: #ifdef __EPOC32__ sl@0: // On hardware - to load agents from sources other than ROM the patch sl@0: // data KCafLoadPostProductionAgents must be set to True (non-zero). sl@0: // Default SymbianOS behavior is to only load agents from ROM sl@0: if ((KCafLoadPostProductionAgents == 0) && sl@0: !implArray[i]->RomBased()) sl@0: { sl@0: // If the agent is not in ROM, don't load it because it might sl@0: // be a security risk. sl@0: continue; sl@0: } sl@0: #endif sl@0: sl@0: // Construct all the agent infos from these implementations sl@0: TRAP(err, AddAgentL(*implArray[i])); sl@0: sl@0: // If we ran out of memory proagate the leave to the caller sl@0: // otherwise don't let a dodgy agent affect the construction of the other sl@0: // agents sl@0: if(err == KErrNoMemory) sl@0: { sl@0: User::Leave(KErrNoMemory); sl@0: } sl@0: } sl@0: CleanupStack::PopAndDestroy(&implArray); sl@0: sl@0: sl@0: if (!iDefaultAgent) sl@0: { sl@0: // If we didn't find a default agent, we have a big problem so panic sl@0: User::Panic(KCafPanicString, ECafPanicNoF32Agent); sl@0: } sl@0: } sl@0: sl@0: void CAgentResolver::AddAgentL(const CImplementationInformation& aImplInfo) sl@0: { sl@0: // Create a CAgentInfo instance sl@0: CAgentInfo* agentInfo = CAgentInfo::NewLC(aImplInfo); sl@0: sl@0: sl@0: if(IsF32Agent(*agentInfo)) sl@0: { sl@0: // It's the F32 Agent sl@0: if(iDefaultAgent) sl@0: { sl@0: // If we already have a default agent something is seriously wrong sl@0: User::Panic(KCafPanicString, ECafPanicDuplicateF32Agent); sl@0: } sl@0: sl@0: // Note that the default agent is NOT stored in the agents list, it is a special case sl@0: iDefaultAgent = agentInfo; sl@0: CleanupStack::Pop(agentInfo); sl@0: } sl@0: else sl@0: { sl@0: // All other agents go in the agent list sl@0: User::LeaveIfError(iAgentInfos.Append(agentInfo)); sl@0: CleanupStack::Pop(agentInfo); sl@0: sl@0: TInt mimeIndex=0; sl@0: sl@0: // Update our list of all supplier mime types supported by CAF sl@0: for(mimeIndex=0;mimeIndex < agentInfo->SupplierMimeTypes().Count(); mimeIndex++) sl@0: { sl@0: User::LeaveIfError(iSupplierMimeTypes.Append(*agentInfo->SupplierMimeTypes()[mimeIndex])); sl@0: } sl@0: sl@0: // Update our list of all consumer mime types supported by CAF sl@0: for(mimeIndex=0;mimeIndex < agentInfo->ConsumerMimeTypes().Count(); mimeIndex++) sl@0: { sl@0: User::LeaveIfError(iConsumerMimeTypes.Append(*agentInfo->ConsumerMimeTypes()[mimeIndex])); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CAgentResolver::DestroyListOfAgents() sl@0: { sl@0: iSupplierMimeTypes.Reset(); sl@0: iConsumerMimeTypes.Reset(); sl@0: sl@0: // cant forget to delete the default agent sl@0: delete iDefaultAgent; sl@0: iDefaultAgent = NULL; sl@0: sl@0: // Free memory assocated with the iAgentInfos array sl@0: iAgentInfos.ResetAndDestroy(); sl@0: } sl@0: sl@0: void CAgentResolver::DoCancel() sl@0: { sl@0: // Abort any update notification sl@0: iEcomSession->CancelNotifyOnChange(iStatus); sl@0: } sl@0: sl@0: void CAgentResolver::RunL() sl@0: { sl@0: // Called by the ECOM framework if a new agent appears sl@0: sl@0: // remove the existing list of agents and build a new one sl@0: DestroyListOfAgents(); sl@0: BuildListOfAgentsL(); sl@0: sl@0: // request notification of any further changes sl@0: iEcomSession->NotifyOnChange(iStatus); sl@0: SetActive(); sl@0: } sl@0: sl@0: TBool CAgentResolver::IsF32Agent(CAgentInfo& aAgentInfo) sl@0: { sl@0: // Check if the agent has no consumer or supplier mime types sl@0: // and that it has the correct name and Uid sl@0: if (aAgentInfo.Agent().ImplementationUid() == KF32AgentImplUid sl@0: && aAgentInfo.Agent().Name().Compare(KF32Agent()) == 0 sl@0: && aAgentInfo.ConsumerMimeTypes().Count() == 0 sl@0: && aAgentInfo.SupplierMimeTypes().Count() == 0) sl@0: { sl@0: return ETrue; sl@0: } sl@0: else sl@0: { sl@0: return EFalse; sl@0: } sl@0: } sl@0: sl@0: CAgentInfo& CAgentResolver::ResolveSupplierMimeL(const TDesC8& aMimeType) const sl@0: { sl@0: // Go through all the agents and return the one which supports the sl@0: // required supplier mime type sl@0: CAgentInfo* retVal=NULL; sl@0: sl@0: for (TInt i = 0; i < iAgentInfos.Count(); ++i) sl@0: { sl@0: if (iAgentInfos[i]->IsSupportedSupplier(aMimeType)) sl@0: { sl@0: retVal = iAgentInfos[i]; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if (!retVal) sl@0: { sl@0: User::Leave(KErrCANoAgent); sl@0: } sl@0: return *retVal; sl@0: } sl@0: sl@0: CAgentInfo& CAgentResolver::ResolveConsumerMime(const TDesC8& aMimeType) const sl@0: { sl@0: // By default, set the return value to be the default agent. If we find sl@0: // anything better, then we change it sl@0: CAgentInfo* retVal = iDefaultAgent; sl@0: sl@0: for (TInt i = 0; i < iAgentInfos.Count(); ++i) sl@0: { sl@0: if (iAgentInfos[i]->IsSupportedConsumer(aMimeType)) sl@0: { sl@0: retVal = iAgentInfos[i]; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: ASSERT(retVal); sl@0: return *retVal; sl@0: } sl@0: sl@0: CAgentInfo& CAgentResolver::ResolveFileL(const TDesC& aURI, TDes& aActualUri, TContentShareMode aShareMode) const sl@0: { sl@0: // Go through all the agents and return the one which supports the file at the given URI sl@0: TBool thePrivateDir = EFalse; sl@0: TUid agentUid = ResolveDirectory(aURI, aActualUri, thePrivateDir); sl@0: sl@0: if(agentUid != iDefaultAgent->Agent().ImplementationUid()) sl@0: { sl@0: // this file must be living in a private server directory sl@0: // return the agent who owns the directory sl@0: return AgentInfoL(agentUid); sl@0: } sl@0: else sl@0: { sl@0: TInt agentsCount(iAgentInfos.Count()); sl@0: CAgentManager* agentManager = NULL; sl@0: for (TInt i = 0; i < agentsCount; ++i) sl@0: { sl@0: TRAPD(result, agentManager = &iAgentInfos[i]->AgentManagerL()); sl@0: if(result != KErrNone) sl@0: { sl@0: if(KErrNoMemory == result) sl@0: { sl@0: User::Leave(result); sl@0: } sl@0: else sl@0: { sl@0: continue; sl@0: } sl@0: } sl@0: if (agentManager->IsRecognizedL(aURI, aShareMode)) sl@0: { sl@0: return *iAgentInfos[i]; sl@0: } sl@0: } sl@0: } sl@0: return *iDefaultAgent; sl@0: } sl@0: sl@0: CAgentInfo& CAgentResolver::ResolveFileL(RFile& aFile) const sl@0: { sl@0: // Go through all the agents and return the one which supports the file sl@0: sl@0: TInt agentsCount(iAgentInfos.Count()); sl@0: CAgentManager* agentManager = NULL; sl@0: for (TInt i = 0; i < agentsCount; ++i) sl@0: { sl@0: TRAPD(result, agentManager = &iAgentInfos[i]->AgentManagerL()); sl@0: if(result != KErrNone) sl@0: { sl@0: if(KErrNoMemory == result) sl@0: { sl@0: User::Leave(result); sl@0: } sl@0: else sl@0: { sl@0: continue; sl@0: } sl@0: } sl@0: if (agentManager->IsRecognizedL(aFile)) sl@0: { sl@0: return *iAgentInfos[i]; sl@0: } sl@0: } sl@0: return *iDefaultAgent; sl@0: } sl@0: sl@0: #ifdef SYMBIAN_ENABLE_SDP_WMDRM_SUPPORT sl@0: sl@0: CAgentInfo& CAgentResolver::ResolveFileL(const TDesC8& aHeaderData) sl@0: { sl@0: // Go through all the agents and return the one which supports the given WMDRM content. sl@0: sl@0: TInt agentsCount(iAgentInfos.Count()); sl@0: CAgentManager* agentManager = NULL; sl@0: sl@0: for (TInt i = 0; i < agentsCount; ++i) sl@0: { sl@0: TRAPD(result, agentManager = &iAgentInfos[i]->AgentManagerL()); sl@0: if(result != KErrNone) sl@0: { sl@0: if(KErrNoMemory == result) sl@0: { sl@0: User::Leave(result); sl@0: } sl@0: else sl@0: { sl@0: continue; sl@0: } sl@0: } sl@0: sl@0: if (agentManager->IsRecognizedL(aHeaderData)) sl@0: { sl@0: return *iAgentInfos[i]; sl@0: } sl@0: } sl@0: sl@0: // will never reach here sl@0: return *iDefaultAgent; sl@0: } sl@0: sl@0: sl@0: EXPORT_C TBool CAgentResolver::DoRecognizeL(const TDesC8& aHeader, TDes8& aFileMimeType, TDes8& aContentMimeType) sl@0: { sl@0: // Go through all the agents and return the one which supports the given WMDRM content. sl@0: TInt agentsCount(iAgentInfos.Count()); sl@0: CAgentManager* agentManager = NULL; sl@0: for (TInt i = 0; i < agentsCount; ++i) sl@0: { sl@0: TRAPD(result, agentManager = &iAgentInfos[i]->AgentManagerL()); sl@0: if(result != KErrNone) sl@0: { sl@0: if(KErrNoMemory == result) sl@0: { sl@0: User::Leave(result); sl@0: } sl@0: else sl@0: { sl@0: continue; sl@0: } sl@0: } sl@0: sl@0: if (agentManager->RecognizeContentL(aHeader, aFileMimeType, aContentMimeType)) sl@0: { sl@0: // force to lower case to ensure that chosen lower case scheme for mime types is maintained sl@0: aFileMimeType.LowerCase(); sl@0: aContentMimeType.LowerCase(); sl@0: return ETrue; sl@0: } sl@0: } sl@0: sl@0: return EFalse; sl@0: } sl@0: sl@0: #endif //#ifdef SYMBIAN_ENABLE_SDP_WMDRM_SUPPORT sl@0: sl@0: TUid CAgentResolver::ResolveDirectory(const TDesC& aPath, TDes& aActualPath, TBool& aThePrivateDir) const sl@0: { sl@0: TInt i = 0; sl@0: TInt pathLength = 0; sl@0: TBuf pathLowerCase; sl@0: sl@0: // Assume it's a publicly accessable path sl@0: aThePrivateDir = EFalse; sl@0: sl@0: // Find the length of the path and private directory sl@0: pathLength = aPath.Length(); sl@0: sl@0: // Check that the path is long enough to be within a private directory sl@0: // and does not include "..\\".The "..\\" sequence could be a security risk sl@0: if(aPath.Find(KParentDir()) == KErrNotFound && pathLength >= KPrivateDirAndDriveLength) sl@0: { sl@0: // Create a lower case copy of the left hand side of the path sl@0: TPtrC lowerCasePtr = aPath.Mid(KPrivateDirOffset, KPrivateDirLength); sl@0: pathLowerCase.Copy(lowerCasePtr); sl@0: pathLowerCase.LowerCase(); sl@0: sl@0: // Compare the first directory in the path to \\private\\ sl@0: if(KPrivateDir() == pathLowerCase) sl@0: { sl@0: // It is a private directory of some sort sl@0: if(pathLength > KPrivateDirAndDriveLength) sl@0: { sl@0: // It must be a server private directory data cage sl@0: TPtrC serverDirectoryPath = aPath.Right(pathLength - KPrivateDirAndDriveLength); sl@0: for(i = 0; i < AgentInfoCount(); i++) sl@0: { sl@0: // See if the part after \\private\\ matches the agent name sl@0: TPtrC privateDirectoryName = AgentInfo(i).PrivateDirectoryName(); sl@0: TPtrC agentName = AgentInfo(i).Agent().Name(); sl@0: if(privateDirectoryName.Length() && agentName.Length() && agentName == serverDirectoryPath.Left(agentName.Length())) sl@0: { sl@0: // It must be this agent's private directory sl@0: // Convert \\private\\agentName\\... to \\private\\SID\\... sl@0: aActualPath.Copy(aPath.Left(KPrivateDirAndDriveLength)); sl@0: aActualPath.Append(privateDirectoryName); sl@0: aActualPath.Append(aPath.Right(pathLength - KPrivateDirAndDriveLength - agentName.Length())); sl@0: return AgentInfo(i).Agent().ImplementationUid(); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // It's just the c:\\private\\ directory sl@0: // Use the default agent, any calls will just fail sl@0: aThePrivateDir = ETrue; sl@0: } sl@0: } sl@0: } sl@0: sl@0: // Not an agent private directory so just return the default agent sl@0: aActualPath.Copy(aPath); sl@0: return iDefaultAgent->Agent().ImplementationUid(); sl@0: } sl@0: sl@0: HBufC* CAgentResolver::ConvertAgentFileNameL(const TDesC& aFileName) const sl@0: { sl@0: TInt i = 0; sl@0: TInt fileNameLength = 0; sl@0: TBuf pathLowerCase; sl@0: sl@0: fileNameLength = aFileName.Length(); sl@0: sl@0: // If the path is shorter than the x:\\private\\ it must be a F32 file sl@0: if(fileNameLength > KPrivateDirAndDriveLength) sl@0: { sl@0: // Create a lower case copy of the left hand side of the path sl@0: TPtrC lowerCasePtr = aFileName.Mid(KPrivateDirOffset, KPrivateDirLength); sl@0: pathLowerCase.Copy(lowerCasePtr); sl@0: pathLowerCase.LowerCase(); sl@0: sl@0: // Compare the first directory in the path to \\private\\ sl@0: if(KPrivateDir() == pathLowerCase) sl@0: { sl@0: // It is a private directory of some sort sl@0: if(fileNameLength > KPrivateDirAndDriveLength) sl@0: { sl@0: // It must be a server private directory data cage sl@0: TPtrC serverDirectoryPath = aFileName.Right(fileNameLength - KPrivateDirAndDriveLength); sl@0: for(i = 0; i < AgentInfoCount(); i++) sl@0: { sl@0: // See if the part after \\private\\ matches the agent name sl@0: TPtrC privateDirectoryName = AgentInfo(i).PrivateDirectoryName(); sl@0: TPtrC agentName = AgentInfo(i).Agent().Name(); sl@0: if(privateDirectoryName.Length() && agentName.Length() && privateDirectoryName == serverDirectoryPath.Left(privateDirectoryName.Length())) sl@0: { sl@0: // It is this agent's private directory sl@0: // Convert \\private\\SID\\... \\private\\agentName\\... sl@0: HBufC* buffer = HBufC::NewL(fileNameLength - privateDirectoryName.Length() + agentName.Length()); sl@0: TPtr ptr = buffer->Des(); sl@0: ptr.Copy(aFileName.Left(KPrivateDirAndDriveLength)); sl@0: ptr.Append(agentName); sl@0: ptr.Append(aFileName.Right(fileNameLength - KPrivateDirAndDriveLength - privateDirectoryName.Length())); sl@0: return buffer; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: } sl@0: return aFileName.AllocL(); sl@0: } sl@0: sl@0: EXPORT_C TBool CAgentResolver::DoRecognizeL(const TDesC& aName, const TDesC8& aBuffer, TDes8& aFileMimeType, TDes8& aContentMimeType) sl@0: { sl@0: sl@0: // Given the filename and buffer from apparc, ask the agents in turn if they recognize the file sl@0: // Note this will not call the DefaultAgent (F32) because it won't be able to recognize anything sl@0: sl@0: TInt agentsCount(iAgentInfos.Count()); sl@0: CAgentManager* agentManager = NULL; sl@0: for (TInt i = 0; i < agentsCount; ++i) sl@0: { sl@0: TRAPD(result, agentManager = &iAgentInfos[i]->AgentManagerL()); sl@0: if(result != KErrNone) sl@0: { sl@0: if(KErrNoMemory == result) sl@0: { sl@0: User::Leave(result); sl@0: } sl@0: else sl@0: { sl@0: continue; sl@0: } sl@0: } sl@0: if (agentManager->RecognizeFileL(aName, aBuffer, aFileMimeType, aContentMimeType)) sl@0: { sl@0: // force to lower case to ensure that chosen lower case scheme for mime types is maintained sl@0: aFileMimeType.LowerCase(); sl@0: aContentMimeType.LowerCase(); sl@0: return ETrue; sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: sl@0: void CAgentResolver::CleanImplArray(TAny* aArray) sl@0: { sl@0: static_cast(aArray)->ResetAndDestroy(); sl@0: } sl@0: sl@0: EXPORT_C TInt CAgentResolver::PreferredBufferSize() sl@0: { sl@0: TInt size=0; sl@0: sl@0: if(iDefaultAgent != NULL) sl@0: { sl@0: size = iDefaultAgent->PreferredBufferSize(); sl@0: } sl@0: sl@0: // Find out the maximum buffer requested by any agent sl@0: for (TInt i = 0; i < iAgentInfos.Count(); ++i) sl@0: { sl@0: if(iAgentInfos[i]->PreferredBufferSize() > size) sl@0: { sl@0: size = iAgentInfos[i]->PreferredBufferSize(); sl@0: } sl@0: } sl@0: return size; sl@0: } sl@0: sl@0: sl@0: EXPORT_C const RArray& CAgentResolver::ConsumerMimeTypes() const sl@0: { sl@0: return iConsumerMimeTypes; sl@0: } sl@0: sl@0: sl@0: EXPORT_C const RArray& CAgentResolver::SupplierMimeTypes() const sl@0: { sl@0: return iSupplierMimeTypes; sl@0: } sl@0: sl@0: sl@0: CAgentInfo& CAgentResolver::AgentInfoL(const TDesC& aAgentName) const sl@0: { sl@0: TBool found = EFalse; sl@0: TInt i = 0; sl@0: for(i = 0; i < iAgentInfos.Count(); i++) sl@0: { sl@0: if(iAgentInfos[i]->Agent().Name() == aAgentName) sl@0: { sl@0: found = ETrue; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if(!found) sl@0: { sl@0: // Can't find the agent so leave sl@0: User::Leave(KErrNotFound); sl@0: } sl@0: sl@0: return *iAgentInfos[i]; sl@0: } sl@0: sl@0: CAgentInfo& CAgentResolver::AgentInfoL(const TUid& aUid) const sl@0: { sl@0: TInt i = 0; sl@0: TBool found = EFalse; sl@0: sl@0: // See if it's the F32 agent sl@0: if(aUid == DefaultAgentUid()) sl@0: { sl@0: return *iDefaultAgent; sl@0: } sl@0: sl@0: for(i = 0; i < iAgentInfos.Count(); i++) sl@0: { sl@0: if(iAgentInfos[i]->Agent().ImplementationUid() == aUid) sl@0: { sl@0: found = ETrue; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if(!found) sl@0: { sl@0: // couldn't find the agent so leave sl@0: User::Leave(KErrNotFound); sl@0: } sl@0: sl@0: return *iAgentInfos[i]; sl@0: } sl@0: sl@0: CAgentInfo& CAgentResolver::AgentInfo(TInt aIndex) const sl@0: { sl@0: return *iAgentInfos[aIndex]; sl@0: } sl@0: sl@0: TInt CAgentResolver::AgentInfoCount() const sl@0: { sl@0: return iAgentInfos.Count(); sl@0: } sl@0: sl@0: TUid CAgentResolver::DefaultAgentUid() const sl@0: { sl@0: return iDefaultAgent->Agent().ImplementationUid(); sl@0: }