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